forked from Mirrorlandia_minetest/minetest
Temporary commit; lots of test code and stuff
This commit is contained in:
parent
f5ff378dd0
commit
c57637b4c3
BIN
data/grass.png
BIN
data/grass.png
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 966 B |
BIN
data/stone.png
BIN
data/stone.png
Binary file not shown.
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 846 B |
@ -50,6 +50,7 @@ configure_file(
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(common_SRCS
|
set(common_SRCS
|
||||||
|
serverobject.cpp
|
||||||
noise.cpp
|
noise.cpp
|
||||||
mineral.cpp
|
mineral.cpp
|
||||||
porting.cpp
|
porting.cpp
|
||||||
@ -75,8 +76,10 @@ set(common_SRCS
|
|||||||
test.cpp
|
test.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Client sources
|
||||||
set(minetest_SRCS
|
set(minetest_SRCS
|
||||||
${common_SRCS}
|
${common_SRCS}
|
||||||
|
clientobject.cpp
|
||||||
guiMainMenu.cpp
|
guiMainMenu.cpp
|
||||||
guiMessageMenu.cpp
|
guiMessageMenu.cpp
|
||||||
guiTextInputMenu.cpp
|
guiTextInputMenu.cpp
|
||||||
@ -88,6 +91,7 @@ set(minetest_SRCS
|
|||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Server sources
|
||||||
set(minetestserver_SRCS
|
set(minetestserver_SRCS
|
||||||
${common_SRCS}
|
${common_SRCS}
|
||||||
servermain.cpp
|
servermain.cpp
|
||||||
|
71
src/activeobject.h
Normal file
71
src/activeobject.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ACTIVEOBJECT_HEADER
|
||||||
|
#define ACTIVEOBJECT_HEADER
|
||||||
|
|
||||||
|
#include "common_irrlicht.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
struct ActiveObjectMessage
|
||||||
|
{
|
||||||
|
ActiveObjectMessage(u16 id_, bool reliable_=true, std::string data_=""):
|
||||||
|
id(id_),
|
||||||
|
reliable(reliable_),
|
||||||
|
datastring(data_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
u16 id;
|
||||||
|
bool reliable;
|
||||||
|
std::string datastring;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ACTIVEOBJECT_TYPE_INVALID 0
|
||||||
|
#define ACTIVEOBJECT_TYPE_TEST 1
|
||||||
|
#define ACTIVEOBJECT_TYPE_LUA 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
Parent class for ServerActiveObject and ClientActiveObject
|
||||||
|
*/
|
||||||
|
class ActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ActiveObject(u16 id):
|
||||||
|
m_id(id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 getId()
|
||||||
|
{
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setId(u16 id)
|
||||||
|
{
|
||||||
|
m_id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual u8 getType() const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
u16 m_id; // 0 is invalid, "no id"
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
156
src/client.cpp
156
src/client.cpp
@ -56,10 +56,12 @@ Client::Client(
|
|||||||
const char *playername,
|
const char *playername,
|
||||||
MapDrawControl &control):
|
MapDrawControl &control):
|
||||||
m_thread(this),
|
m_thread(this),
|
||||||
m_env(new ClientMap(this, control,
|
m_env(
|
||||||
|
new ClientMap(this, control,
|
||||||
device->getSceneManager()->getRootSceneNode(),
|
device->getSceneManager()->getRootSceneNode(),
|
||||||
device->getSceneManager(), 666),
|
device->getSceneManager(), 666),
|
||||||
dout_client),
|
device->getSceneManager()
|
||||||
|
),
|
||||||
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
|
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
|
||||||
m_device(device),
|
m_device(device),
|
||||||
camera_position(0,0,0),
|
camera_position(0,0,0),
|
||||||
@ -83,19 +85,24 @@ Client::Client(
|
|||||||
|
|
||||||
m_thread.Start();
|
m_thread.Start();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add local player
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
JMutexAutoLock envlock(m_env_mutex);
|
||||||
//m_env.getMap().StartUpdater();
|
|
||||||
|
|
||||||
Player *player = new LocalPlayer();
|
Player *player = new LocalPlayer();
|
||||||
|
|
||||||
player->updateName(playername);
|
player->updateName(playername);
|
||||||
|
|
||||||
/*f32 y = BS*2 + BS*20;
|
|
||||||
player->setPosition(v3f(0, y, 0));*/
|
|
||||||
//player->setPosition(v3f(0, y, 30900*BS)); // DEBUG
|
|
||||||
m_env.addPlayer(player);
|
m_env.addPlayer(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add some active objects for testing
|
||||||
|
/*{
|
||||||
|
ClientActiveObject *obj = new TestCAO(0, v3f(0, 10*BS, 0));
|
||||||
|
m_env.addActiveObject(obj);
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::~Client()
|
Client::~Client()
|
||||||
@ -493,7 +500,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||||||
v3s16 playerpos_s16(0, BS*2+BS*20, 0);
|
v3s16 playerpos_s16(0, BS*2+BS*20, 0);
|
||||||
if(datasize >= 2+1+6)
|
if(datasize >= 2+1+6)
|
||||||
playerpos_s16 = readV3S16(&data[2+1]);
|
playerpos_s16 = readV3S16(&data[2+1]);
|
||||||
v3f playerpos_f = intToFloat(playerpos_s16) - v3f(0, BS/2, 0);
|
v3f playerpos_f = intToFloat(playerpos_s16, BS) - v3f(0, BS/2, 0);
|
||||||
|
|
||||||
{ //envlock
|
{ //envlock
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
JMutexAutoLock envlock(m_env_mutex);
|
||||||
@ -1037,6 +1044,99 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||||||
|
|
||||||
m_chat_queue.push_back(message);
|
m_chat_queue.push_back(message);
|
||||||
}
|
}
|
||||||
|
else if(command == TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
u16 command
|
||||||
|
u16 count of removed objects
|
||||||
|
for all removed objects {
|
||||||
|
u16 id
|
||||||
|
}
|
||||||
|
u16 count of added objects
|
||||||
|
for all added objects {
|
||||||
|
u16 id
|
||||||
|
u8 type
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
char buf[6];
|
||||||
|
// Get all data except the command number
|
||||||
|
std::string datastring((char*)&data[2], datasize-2);
|
||||||
|
// Throw them in an istringstream
|
||||||
|
std::istringstream is(datastring, std::ios_base::binary);
|
||||||
|
|
||||||
|
// Read stuff
|
||||||
|
|
||||||
|
// Read removed objects
|
||||||
|
is.read(buf, 2);
|
||||||
|
u16 removed_count = readU16((u8*)buf);
|
||||||
|
for(u16 i=0; i<removed_count; i++)
|
||||||
|
{
|
||||||
|
is.read(buf, 2);
|
||||||
|
u16 id = readU16((u8*)buf);
|
||||||
|
// Remove it
|
||||||
|
{
|
||||||
|
JMutexAutoLock envlock(m_env_mutex);
|
||||||
|
m_env.removeActiveObject(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read added objects
|
||||||
|
is.read(buf, 2);
|
||||||
|
u16 added_count = readU16((u8*)buf);
|
||||||
|
for(u16 i=0; i<added_count; i++)
|
||||||
|
{
|
||||||
|
is.read(buf, 2);
|
||||||
|
u16 id = readU16((u8*)buf);
|
||||||
|
is.read(buf, 1);
|
||||||
|
u8 type = readU8((u8*)buf);
|
||||||
|
// Add it
|
||||||
|
{
|
||||||
|
JMutexAutoLock envlock(m_env_mutex);
|
||||||
|
m_env.addActiveObject(id, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(command == TOCLIENT_ACTIVE_OBJECT_MESSAGES)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
u16 command
|
||||||
|
for all objects
|
||||||
|
{
|
||||||
|
u16 id
|
||||||
|
u16 message length
|
||||||
|
string message
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
char buf[6];
|
||||||
|
// Get all data except the command number
|
||||||
|
std::string datastring((char*)&data[2], datasize-2);
|
||||||
|
// Throw them in an istringstream
|
||||||
|
std::istringstream is(datastring, std::ios_base::binary);
|
||||||
|
|
||||||
|
while(is.eof() == false)
|
||||||
|
{
|
||||||
|
// Read stuff
|
||||||
|
is.read(buf, 2);
|
||||||
|
u16 id = readU16((u8*)buf);
|
||||||
|
if(is.eof())
|
||||||
|
break;
|
||||||
|
is.read(buf, 2);
|
||||||
|
u16 message_size = readU16((u8*)buf);
|
||||||
|
std::string message;
|
||||||
|
message.reserve(message_size);
|
||||||
|
for(u16 i=0; i<message_size; i++)
|
||||||
|
{
|
||||||
|
is.read(buf, 1);
|
||||||
|
message.append(buf, 1);
|
||||||
|
}
|
||||||
|
// Pass on to the environment
|
||||||
|
{
|
||||||
|
JMutexAutoLock envlock(m_env_mutex);
|
||||||
|
m_env.processActiveObjectMessage(id, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Default to queueing it (for slow commands)
|
// Default to queueing it (for slow commands)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1197,7 +1297,7 @@ bool Client::AsyncProcessPacket()
|
|||||||
main thread, from which is will want to retrieve textures.
|
main thread, from which is will want to retrieve textures.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
m_env.getMap().updateMeshes(block->getPos(), getDayNightRatio());
|
m_env.getClientMap().updateMeshes(block->getPos(), getDayNightRatio());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1464,7 +1564,7 @@ void Client::removeNode(v3s16 p)
|
|||||||
i.atEnd() == false; i++)
|
i.atEnd() == false; i++)
|
||||||
{
|
{
|
||||||
v3s16 p = i.getNode()->getKey();
|
v3s16 p = i.getNode()->getKey();
|
||||||
m_env.getMap().updateMeshes(p, m_env.getDayNightRatio());
|
m_env.getClientMap().updateMeshes(p, m_env.getDayNightRatio());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1486,7 +1586,7 @@ void Client::addNode(v3s16 p, MapNode n)
|
|||||||
i.atEnd() == false; i++)
|
i.atEnd() == false; i++)
|
||||||
{
|
{
|
||||||
v3s16 p = i.getNode()->getKey();
|
v3s16 p = i.getNode()->getKey();
|
||||||
m_env.getMap().updateMeshes(p, m_env.getDayNightRatio());
|
m_env.getClientMap().updateMeshes(p, m_env.getDayNightRatio());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1503,36 +1603,6 @@ MapNode Client::getNode(v3s16 p)
|
|||||||
return m_env.getMap().getNode(p);
|
return m_env.getMap().getNode(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void Client::getNode(v3s16 p, MapNode n)
|
|
||||||
{
|
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
|
||||||
m_env.getMap().setNode(p, n);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*f32 Client::getGroundHeight(v2s16 p)
|
|
||||||
{
|
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
|
||||||
return m_env.getMap().getGroundHeight(p);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*bool Client::isNodeUnderground(v3s16 p)
|
|
||||||
{
|
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
|
||||||
return m_env.getMap().isNodeUnderground(p);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*Player * Client::getLocalPlayer()
|
|
||||||
{
|
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
|
||||||
return m_env.getLocalPlayer();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*core::list<Player*> Client::getPlayers()
|
|
||||||
{
|
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
|
||||||
return m_env.getPlayers();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
v3f Client::getPlayerPosition()
|
v3f Client::getPlayerPosition()
|
||||||
{
|
{
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
JMutexAutoLock envlock(m_env_mutex);
|
||||||
@ -1597,7 +1667,7 @@ MapBlockObject * Client::getSelectedObject(
|
|||||||
|
|
||||||
// Calculate from_pos relative to block
|
// Calculate from_pos relative to block
|
||||||
v3s16 block_pos_i_on_map = block->getPosRelative();
|
v3s16 block_pos_i_on_map = block->getPosRelative();
|
||||||
v3f block_pos_f_on_map = intToFloat(block_pos_i_on_map);
|
v3f block_pos_f_on_map = intToFloat(block_pos_i_on_map, BS);
|
||||||
v3f from_pos_f_on_block = from_pos_f_on_map - block_pos_f_on_map;
|
v3f from_pos_f_on_block = from_pos_f_on_map - block_pos_f_on_map;
|
||||||
|
|
||||||
block->getObjects(from_pos_f_on_block, max_d, objects);
|
block->getObjects(from_pos_f_on_block, max_d, objects);
|
||||||
@ -1617,7 +1687,7 @@ MapBlockObject * Client::getSelectedObject(
|
|||||||
|
|
||||||
// Calculate shootline relative to block
|
// Calculate shootline relative to block
|
||||||
v3s16 block_pos_i_on_map = block->getPosRelative();
|
v3s16 block_pos_i_on_map = block->getPosRelative();
|
||||||
v3f block_pos_f_on_map = intToFloat(block_pos_i_on_map);
|
v3f block_pos_f_on_map = intToFloat(block_pos_i_on_map, BS);
|
||||||
core::line3d<f32> shootline_on_block(
|
core::line3d<f32> shootline_on_block(
|
||||||
shootline_on_map.start - block_pos_f_on_map,
|
shootline_on_map.start - block_pos_f_on_map,
|
||||||
shootline_on_map.end - block_pos_f_on_map
|
shootline_on_map.end - block_pos_f_on_map
|
||||||
@ -1672,7 +1742,7 @@ u32 Client::getDayNightRatio()
|
|||||||
v3f playerpos = player->getPosition();
|
v3f playerpos = player->getPosition();
|
||||||
v3f playerspeed = player->getSpeed();
|
v3f playerspeed = player->getSpeed();
|
||||||
|
|
||||||
v3s16 center_nodepos = floatToInt(playerpos);
|
v3s16 center_nodepos = floatToInt(playerpos, BS);
|
||||||
v3s16 center = getNodeBlockPos(center_nodepos);
|
v3s16 center = getNodeBlockPos(center_nodepos);
|
||||||
|
|
||||||
u32 counter = 0;
|
u32 counter = 0;
|
||||||
|
33
src/client.h
33
src/client.h
@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
#include "jmutex.h"
|
#include "jmutex.h"
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include "clientobject.h"
|
||||||
|
|
||||||
class ClientNotReadyException : public BaseException
|
class ClientNotReadyException : public BaseException
|
||||||
{
|
{
|
||||||
@ -165,11 +166,6 @@ public:
|
|||||||
|
|
||||||
// Returns InvalidPositionException if not found
|
// Returns InvalidPositionException if not found
|
||||||
MapNode getNode(v3s16 p);
|
MapNode getNode(v3s16 p);
|
||||||
// Returns InvalidPositionException if not found
|
|
||||||
//void setNode(v3s16 p, MapNode n);
|
|
||||||
|
|
||||||
// Returns InvalidPositionException if not found
|
|
||||||
//f32 getGroundHeight(v2s16 p);
|
|
||||||
|
|
||||||
v3f getPlayerPosition();
|
v3f getPlayerPosition();
|
||||||
|
|
||||||
@ -192,7 +188,6 @@ public:
|
|||||||
// Prints a line or two of info
|
// Prints a line or two of info
|
||||||
void printDebugInfo(std::ostream &os);
|
void printDebugInfo(std::ostream &os);
|
||||||
|
|
||||||
//s32 getDayNightIndex();
|
|
||||||
u32 getDayNightRatio();
|
u32 getDayNightRatio();
|
||||||
|
|
||||||
//void updateSomeExpiredMeshes();
|
//void updateSomeExpiredMeshes();
|
||||||
@ -230,27 +225,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void setTempMod(v3s16 p, NodeMod mod)
|
|
||||||
{
|
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
|
||||||
assert(m_env.getMap().mapType() == MAPTYPE_CLIENT);
|
|
||||||
bool changed = false;
|
|
||||||
v3s16 blockpos = ((ClientMap&)m_env.getMap()).setTempMod(p, mod, &changed);
|
|
||||||
if(changed)
|
|
||||||
m_env.getMap().updateMeshes(blockpos, m_env.getDayNightRatio());
|
|
||||||
}
|
|
||||||
void clearTempMod(v3s16 p)
|
|
||||||
{
|
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
|
||||||
assert(m_env.getMap().mapType() == MAPTYPE_CLIENT);
|
|
||||||
bool changed = false;
|
|
||||||
v3s16 blockpos = ((ClientMap&)m_env.getMap()).clearTempMod(p, &changed);
|
|
||||||
if(changed)
|
|
||||||
m_env.getMap().updateMeshes(blockpos, m_env.getDayNightRatio());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
float getAvgRtt()
|
float getAvgRtt()
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_con_mutex);
|
JMutexAutoLock lock(m_con_mutex);
|
||||||
@ -302,15 +276,12 @@ private:
|
|||||||
// NOTE: If connection and environment are both to be locked,
|
// NOTE: If connection and environment are both to be locked,
|
||||||
// environment shall be locked first.
|
// environment shall be locked first.
|
||||||
|
|
||||||
Environment m_env;
|
ClientEnvironment m_env;
|
||||||
JMutex m_env_mutex;
|
JMutex m_env_mutex;
|
||||||
|
|
||||||
con::Connection m_con;
|
con::Connection m_con;
|
||||||
JMutex m_con_mutex;
|
JMutex m_con_mutex;
|
||||||
|
|
||||||
/*core::map<v3s16, float> m_fetchblock_history;
|
|
||||||
JMutex m_fetchblock_mutex;*/
|
|
||||||
|
|
||||||
core::list<IncomingPacket> m_incoming_queue;
|
core::list<IncomingPacket> m_incoming_queue;
|
||||||
JMutex m_incoming_queue_mutex;
|
JMutex m_incoming_queue_mutex;
|
||||||
|
|
||||||
|
169
src/clientobject.cpp
Normal file
169
src/clientobject.cpp
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "clientobject.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "porting.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "utility.h"
|
||||||
|
|
||||||
|
ClientActiveObject::ClientActiveObject(u16 id):
|
||||||
|
ActiveObject(id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientActiveObject::~ClientActiveObject()
|
||||||
|
{
|
||||||
|
removeFromScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientActiveObject* ClientActiveObject::create(u8 type)
|
||||||
|
{
|
||||||
|
if(type == ACTIVEOBJECT_TYPE_INVALID)
|
||||||
|
{
|
||||||
|
dstream<<"ClientActiveObject::create(): passed "
|
||||||
|
<<"ACTIVEOBJECT_TYPE_INVALID"<<std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if(type == ACTIVEOBJECT_TYPE_TEST)
|
||||||
|
{
|
||||||
|
dstream<<"ClientActiveObject::create(): passed "
|
||||||
|
<<"ACTIVEOBJECT_TYPE_TEST"<<std::endl;
|
||||||
|
return new TestCAO(0);
|
||||||
|
}
|
||||||
|
else if(type == ACTIVEOBJECT_TYPE_LUA)
|
||||||
|
{
|
||||||
|
dstream<<"ClientActiveObject::create(): passed "
|
||||||
|
<<"ACTIVEOBJECT_TYPE_LUA"<<std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstream<<"ClientActiveObject::create(): passed "
|
||||||
|
<<"unknown type="<<type<<std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TestCAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
TestCAO::TestCAO(u16 id):
|
||||||
|
ClientActiveObject(id),
|
||||||
|
m_node(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TestCAO::~TestCAO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCAO::addToScene(scene::ISceneManager *smgr)
|
||||||
|
{
|
||||||
|
if(m_node != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
video::IVideoDriver* driver = smgr->getVideoDriver();
|
||||||
|
|
||||||
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
|
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
|
video::SColor c(255,255,255,255);
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
|
||||||
|
};
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
buf->append(vertices, 4, indices, 6);
|
||||||
|
// Set material
|
||||||
|
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
buf->getMaterial().setTexture
|
||||||
|
(0, driver->getTexture(porting::getDataPath("rat.png").c_str()));
|
||||||
|
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
// Add to mesh
|
||||||
|
mesh->addMeshBuffer(buf);
|
||||||
|
buf->drop();
|
||||||
|
m_node = smgr->addMeshSceneNode(mesh, NULL);
|
||||||
|
mesh->drop();
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCAO::removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->remove();
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCAO::updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 TestCAO::getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position, BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCAO::updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->setPosition(m_position);
|
||||||
|
//m_node->setRotation(v3f(0, 45, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCAO::step(float dtime)
|
||||||
|
{
|
||||||
|
if(m_node)
|
||||||
|
{
|
||||||
|
v3f rot = m_node->getRotation();
|
||||||
|
//dstream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
|
||||||
|
rot.Y += dtime * 180;
|
||||||
|
m_node->setRotation(rot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCAO::processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
//dstream<<"TestCAO: Got data: "<<data<<std::endl;
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
u16 cmd;
|
||||||
|
is>>cmd;
|
||||||
|
if(cmd == 0)
|
||||||
|
{
|
||||||
|
v3f newpos;
|
||||||
|
is>>newpos.X;
|
||||||
|
is>>newpos.Y;
|
||||||
|
is>>newpos.Z;
|
||||||
|
m_position = newpos;
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
88
src/clientobject.h
Normal file
88
src/clientobject.h
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CLIENTOBJECT_HEADER
|
||||||
|
#define CLIENTOBJECT_HEADER
|
||||||
|
|
||||||
|
#include "common_irrlicht.h"
|
||||||
|
#include "activeobject.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Some planning
|
||||||
|
-------------
|
||||||
|
|
||||||
|
* Client receives a network packet with information of added objects
|
||||||
|
in it
|
||||||
|
* Client supplies the information to its ClientEnvironment
|
||||||
|
* The environment adds the specified objects to itself
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ClientActiveObject : public ActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClientActiveObject(u16 id);
|
||||||
|
virtual ~ClientActiveObject();
|
||||||
|
|
||||||
|
virtual void addToScene(scene::ISceneManager *smgr){}
|
||||||
|
virtual void removeFromScene(){}
|
||||||
|
// 0 <= light_at_pos <= LIGHT_SUN
|
||||||
|
virtual void updateLight(u8 light_at_pos){}
|
||||||
|
virtual v3s16 getLightPosition(){return v3s16(0,0,0);}
|
||||||
|
|
||||||
|
// Step object in time
|
||||||
|
virtual void step(float dtime){}
|
||||||
|
|
||||||
|
// Process a message sent by the server side object
|
||||||
|
virtual void processMessage(const std::string &data){}
|
||||||
|
|
||||||
|
static ClientActiveObject* create(u8 type);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
};
|
||||||
|
|
||||||
|
class TestCAO : public ClientActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TestCAO(u16 id);
|
||||||
|
virtual ~TestCAO();
|
||||||
|
|
||||||
|
u8 getType() const
|
||||||
|
{
|
||||||
|
return ACTIVEOBJECT_TYPE_TEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr);
|
||||||
|
void removeFromScene();
|
||||||
|
void updateLight(u8 light_at_pos);
|
||||||
|
v3s16 getLightPosition();
|
||||||
|
void updateNodePos();
|
||||||
|
|
||||||
|
void step(float dtime);
|
||||||
|
|
||||||
|
void processMessage(const std::string &data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
scene::IMeshSceneNode *m_node;
|
||||||
|
v3f m_position;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -106,6 +106,31 @@ enum ToClientCommand
|
|||||||
wstring message
|
wstring message
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD = 0x31,
|
||||||
|
/*
|
||||||
|
u16 command
|
||||||
|
u16 count of removed objects
|
||||||
|
for all removed objects {
|
||||||
|
u16 id
|
||||||
|
}
|
||||||
|
u16 count of added objects
|
||||||
|
for all added objects {
|
||||||
|
u16 id
|
||||||
|
u8 type
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
TOCLIENT_ACTIVE_OBJECT_MESSAGES = 0x32,
|
||||||
|
/*
|
||||||
|
u16 command
|
||||||
|
for all objects
|
||||||
|
{
|
||||||
|
u16 id
|
||||||
|
u16 message length
|
||||||
|
string message
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ToServerCommand
|
enum ToServerCommand
|
||||||
|
@ -20,11 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
|
|
||||||
Environment::Environment(Map *map, std::ostream &dout):
|
Environment::Environment()
|
||||||
m_dout(dout)
|
|
||||||
{
|
{
|
||||||
m_map = map;
|
m_daynight_ratio = 0.5;
|
||||||
m_daynight_ratio = 0.2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Environment::~Environment()
|
Environment::~Environment()
|
||||||
@ -35,183 +33,16 @@ Environment::~Environment()
|
|||||||
{
|
{
|
||||||
delete (*i);
|
delete (*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The map is removed by the SceneManager
|
|
||||||
m_map->drop();
|
|
||||||
//delete m_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Environment::step(float dtime)
|
|
||||||
{
|
|
||||||
DSTACK(__FUNCTION_NAME);
|
|
||||||
/*
|
|
||||||
Run Map's timers
|
|
||||||
*/
|
|
||||||
//TimeTaker maptimerupdatetimer("m_map->timerUpdate()", g_device);
|
|
||||||
// 0ms
|
|
||||||
m_map->timerUpdate(dtime);
|
|
||||||
//maptimerupdatetimer.stop();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Get the highest speed some player is going
|
|
||||||
*/
|
|
||||||
//TimeTaker playerspeed("playerspeed", g_device);
|
|
||||||
// 0ms
|
|
||||||
f32 maximum_player_speed = 0.001; // just some small value
|
|
||||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
|
||||||
i != m_players.end(); i++)
|
|
||||||
{
|
|
||||||
f32 speed = (*i)->getSpeed().getLength();
|
|
||||||
if(speed > maximum_player_speed)
|
|
||||||
maximum_player_speed = speed;
|
|
||||||
}
|
|
||||||
//playerspeed.stop();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Maximum position increment
|
|
||||||
*/
|
|
||||||
//f32 position_max_increment = 0.05*BS;
|
|
||||||
f32 position_max_increment = 0.1*BS;
|
|
||||||
|
|
||||||
// Maximum time increment (for collision detection etc)
|
|
||||||
// time = distance / speed
|
|
||||||
f32 dtime_max_increment = position_max_increment / maximum_player_speed;
|
|
||||||
// Maximum time increment is 10ms or lower
|
|
||||||
if(dtime_max_increment > 0.01)
|
|
||||||
dtime_max_increment = 0.01;
|
|
||||||
|
|
||||||
//TimeTaker playerupdate("playerupdate", g_device);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Stuff that has a maximum time increment
|
|
||||||
*/
|
|
||||||
// Don't allow overly huge dtime
|
|
||||||
if(dtime > 0.5)
|
|
||||||
dtime = 0.5;
|
|
||||||
|
|
||||||
u32 loopcount = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
loopcount++;
|
|
||||||
|
|
||||||
f32 dtime_part;
|
|
||||||
if(dtime > dtime_max_increment)
|
|
||||||
dtime_part = dtime_max_increment;
|
|
||||||
else
|
|
||||||
dtime_part = dtime;
|
|
||||||
dtime -= dtime_part;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Handle players
|
|
||||||
*/
|
|
||||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
|
||||||
i != m_players.end(); i++)
|
|
||||||
{
|
|
||||||
Player *player = *i;
|
|
||||||
|
|
||||||
v3f playerpos = player->getPosition();
|
|
||||||
|
|
||||||
// Apply physics to local player
|
|
||||||
bool free_move = g_settings.getBool("free_move");
|
|
||||||
if(player->isLocal() && free_move == false)
|
|
||||||
{
|
|
||||||
// Apply gravity to local player
|
|
||||||
v3f speed = player->getSpeed();
|
|
||||||
if(player->swimming_up == false)
|
|
||||||
speed.Y -= 9.81 * BS * dtime_part * 2;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Apply water resistance
|
|
||||||
*/
|
|
||||||
if(player->in_water_stable || player->in_water)
|
|
||||||
{
|
|
||||||
f32 max_down = 2.0*BS;
|
|
||||||
if(speed.Y < -max_down) speed.Y = -max_down;
|
|
||||||
|
|
||||||
f32 max = 2.5*BS;
|
|
||||||
if(speed.getLength() > max)
|
|
||||||
{
|
|
||||||
speed = speed / speed.getLength() * max;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
player->setSpeed(speed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Move the player.
|
|
||||||
For local player, this also calculates collision detection.
|
|
||||||
*/
|
|
||||||
player->move(dtime_part, *m_map, position_max_increment);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Update lighting on remote players on client
|
|
||||||
*/
|
|
||||||
u8 light = LIGHT_MAX;
|
|
||||||
try{
|
|
||||||
// Get node at feet
|
|
||||||
v3s16 p = floatToInt(playerpos + v3f(0,BS/4,0));
|
|
||||||
MapNode n = m_map->getNode(p);
|
|
||||||
light = n.getLightBlend(m_daynight_ratio);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e) {}
|
|
||||||
player->updateLight(light);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Add footsteps to grass
|
|
||||||
*/
|
|
||||||
if(g_settings.getBool("footprints"))
|
|
||||||
{
|
|
||||||
// Get node that is at BS/4 under player
|
|
||||||
v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0));
|
|
||||||
try{
|
|
||||||
MapNode n = m_map->getNode(bottompos);
|
|
||||||
if(n.d == CONTENT_GRASS)
|
|
||||||
{
|
|
||||||
n.d = CONTENT_GRASS_FOOTSTEPS;
|
|
||||||
m_map->setNode(bottompos, n);
|
|
||||||
#ifndef SERVER
|
|
||||||
// Update mesh on client
|
|
||||||
if(m_map->mapType() == MAPTYPE_CLIENT)
|
|
||||||
{
|
|
||||||
v3s16 p_blocks = getNodeBlockPos(bottompos);
|
|
||||||
MapBlock *b = m_map->getBlockNoCreate(p_blocks);
|
|
||||||
b->updateMesh(m_daynight_ratio);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while(dtime > 0.001);
|
|
||||||
|
|
||||||
//std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map & Environment::getMap()
|
|
||||||
{
|
|
||||||
return *m_map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Environment::addPlayer(Player *player)
|
void Environment::addPlayer(Player *player)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
/*
|
/*
|
||||||
Check that only one local player exists and peer_ids are unique.
|
Check that peer_ids are unique.
|
||||||
Also check that names are unique.
|
Also check that names are unique.
|
||||||
Exception: there can be multiple players with peer_id=0
|
Exception: there can be multiple players with peer_id=0
|
||||||
*/
|
*/
|
||||||
#ifndef SERVER
|
|
||||||
/*
|
|
||||||
It is a failure if player is local and there already is a local
|
|
||||||
player
|
|
||||||
*/
|
|
||||||
assert(!(player->isLocal() == true && getLocalPlayer() != NULL));
|
|
||||||
#endif
|
|
||||||
// If peer id is non-zero, it has to be unique.
|
// If peer id is non-zero, it has to be unique.
|
||||||
if(player->peer_id != 0)
|
if(player->peer_id != 0)
|
||||||
assert(getPlayer(player->peer_id) == NULL);
|
assert(getPlayer(player->peer_id) == NULL);
|
||||||
@ -240,20 +71,6 @@ re_search:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SERVER
|
|
||||||
LocalPlayer * Environment::getLocalPlayer()
|
|
||||||
{
|
|
||||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
|
||||||
i != m_players.end(); i++)
|
|
||||||
{
|
|
||||||
Player *player = *i;
|
|
||||||
if(player->isLocal())
|
|
||||||
return (LocalPlayer*)player;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Player * Environment::getPlayer(u16 peer_id)
|
Player * Environment::getPlayer(u16 peer_id)
|
||||||
{
|
{
|
||||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||||
@ -315,7 +132,38 @@ void Environment::printPlayers(std::ostream &o)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Environment::serializePlayers(const std::string &savedir)
|
void Environment::setDayNightRatio(u32 r)
|
||||||
|
{
|
||||||
|
m_daynight_ratio = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 Environment::getDayNightRatio()
|
||||||
|
{
|
||||||
|
return m_daynight_ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ServerEnvironment
|
||||||
|
*/
|
||||||
|
|
||||||
|
ServerEnvironment::ServerEnvironment(ServerMap *map):
|
||||||
|
m_map(map),
|
||||||
|
m_random_spawn_timer(0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
TEST CODE
|
||||||
|
*/
|
||||||
|
TestSAO *obj = new TestSAO(0, v3f(0, BS*5, 0));
|
||||||
|
addActiveObject(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerEnvironment::~ServerEnvironment()
|
||||||
|
{
|
||||||
|
// Drop/delete map
|
||||||
|
m_map->drop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerEnvironment::serializePlayers(const std::string &savedir)
|
||||||
{
|
{
|
||||||
std::string players_path = savedir + "/players";
|
std::string players_path = savedir + "/players";
|
||||||
fs::CreateDir(players_path);
|
fs::CreateDir(players_path);
|
||||||
@ -430,7 +278,7 @@ void Environment::serializePlayers(const std::string &savedir)
|
|||||||
//dstream<<"Saved "<<saved_players.size()<<" players."<<std::endl;
|
//dstream<<"Saved "<<saved_players.size()<<" players."<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Environment::deSerializePlayers(const std::string &savedir)
|
void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
||||||
{
|
{
|
||||||
std::string players_path = savedir + "/players";
|
std::string players_path = savedir + "/players";
|
||||||
|
|
||||||
@ -492,25 +340,630 @@ void Environment::deSerializePlayers(const std::string &savedir)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerEnvironment::step(float dtime)
|
||||||
|
{
|
||||||
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
|
// Get some settings
|
||||||
|
//bool free_move = g_settings.getBool("free_move");
|
||||||
|
bool footprints = g_settings.getBool("footprints");
|
||||||
|
|
||||||
|
{
|
||||||
|
//TimeTaker timer("Server m_map->timerUpdate()", g_device);
|
||||||
|
m_map->timerUpdate(dtime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Handle players
|
||||||
|
*/
|
||||||
|
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||||
|
i != m_players.end(); i++)
|
||||||
|
{
|
||||||
|
Player *player = *i;
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
|
||||||
|
// Move
|
||||||
|
player->move(dtime, *m_map, 100*BS);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add footsteps to grass
|
||||||
|
*/
|
||||||
|
if(footprints)
|
||||||
|
{
|
||||||
|
// Get node that is at BS/4 under player
|
||||||
|
v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS);
|
||||||
|
try{
|
||||||
|
MapNode n = m_map->getNode(bottompos);
|
||||||
|
if(n.d == CONTENT_GRASS)
|
||||||
|
{
|
||||||
|
n.d = CONTENT_GRASS_FOOTSTEPS;
|
||||||
|
m_map->setNode(bottompos, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(InvalidPositionException &e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Step active objects
|
||||||
|
*/
|
||||||
|
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||||
|
i = m_active_objects.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
|
{
|
||||||
|
ServerActiveObject* obj = i.getNode()->getValue();
|
||||||
|
// Step object, putting messages directly to the queue
|
||||||
|
obj->step(dtime, m_active_object_messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove (m_removed && m_known_by_count==0) objects
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
core::list<u16> objects_to_remove;
|
||||||
|
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||||
|
i = m_active_objects.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
|
{
|
||||||
|
u16 id = i.getNode()->getKey();
|
||||||
|
ServerActiveObject* obj = i.getNode()->getValue();
|
||||||
|
// This shouldn't happen but check it
|
||||||
|
if(obj == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: NULL object found in ServerEnvironment"
|
||||||
|
<<" while finding removed objects. id="<<id<<std::endl;
|
||||||
|
// Id to be removed from m_active_objects
|
||||||
|
objects_to_remove.push_back(id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If not m_removed, don't remove.
|
||||||
|
if(obj->m_removed == false)
|
||||||
|
continue;
|
||||||
|
// Delete
|
||||||
|
delete obj;
|
||||||
|
// Id to be removed from m_active_objects
|
||||||
|
objects_to_remove.push_back(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove references from m_active_objects
|
||||||
|
for(core::list<u16>::Iterator i = objects_to_remove.begin();
|
||||||
|
i != objects_to_remove.end(); i++)
|
||||||
|
{
|
||||||
|
m_active_objects.remove(*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TEST CODE
|
||||||
|
*/
|
||||||
|
m_random_spawn_timer -= dtime;
|
||||||
|
if(m_random_spawn_timer < 0)
|
||||||
|
{
|
||||||
|
m_random_spawn_timer += 0.1;
|
||||||
|
TestSAO *obj = new TestSAO(0,
|
||||||
|
v3f(myrand_range(-2*BS,2*BS), BS*5, myrand_range(-2*BS,2*BS)));
|
||||||
|
addActiveObject(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* ServerEnvironment::getActiveObject(u16 id)
|
||||||
|
{
|
||||||
|
core::map<u16, ServerActiveObject*>::Node *n;
|
||||||
|
n = m_active_objects.find(id);
|
||||||
|
if(n == NULL)
|
||||||
|
return NULL;
|
||||||
|
return n->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isFreeServerActiveObjectId(u16 id,
|
||||||
|
core::map<u16, ServerActiveObject*> &objects)
|
||||||
|
{
|
||||||
|
if(id == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||||
|
i = objects.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
|
{
|
||||||
|
if(i.getNode()->getKey() == id)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 getFreeServerActiveObjectId(
|
||||||
|
core::map<u16, ServerActiveObject*> &objects)
|
||||||
|
{
|
||||||
|
u16 new_id = 1;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if(isFreeServerActiveObjectId(new_id, objects))
|
||||||
|
return new_id;
|
||||||
|
|
||||||
|
if(new_id == 65535)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
new_id++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
|
||||||
|
{
|
||||||
|
assert(object);
|
||||||
|
if(object->getId() == 0)
|
||||||
|
{
|
||||||
|
u16 new_id = getFreeServerActiveObjectId(m_active_objects);
|
||||||
|
if(new_id == 0)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: ServerEnvironment::addActiveObject(): "
|
||||||
|
<<"no free ids available"<<std::endl;
|
||||||
|
delete object;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
object->setId(new_id);
|
||||||
|
}
|
||||||
|
if(isFreeServerActiveObjectId(object->getId(), m_active_objects) == false)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: ServerEnvironment::addActiveObject(): "
|
||||||
|
<<"id is not free ("<<object->getId()<<")"<<std::endl;
|
||||||
|
delete object;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
dstream<<"INGO: ServerEnvironment::addActiveObject(): "
|
||||||
|
<<"added (id="<<object->getId()<<")"<<std::endl;
|
||||||
|
m_active_objects.insert(object->getId(), object);
|
||||||
|
return object->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Finds out what new objects have been added to
|
||||||
|
inside a radius around a position
|
||||||
|
*/
|
||||||
|
void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius,
|
||||||
|
core::map<u16, bool> ¤t_objects,
|
||||||
|
core::map<u16, bool> &added_objects)
|
||||||
|
{
|
||||||
|
v3f pos_f = intToFloat(pos, BS);
|
||||||
|
f32 radius_f = radius * BS;
|
||||||
|
/*
|
||||||
|
Go through the object list,
|
||||||
|
- discard m_removed objects,
|
||||||
|
- discard objects that are too far away,
|
||||||
|
- discard objects that are found in current_objects.
|
||||||
|
- add remaining objects to added_objects
|
||||||
|
*/
|
||||||
|
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||||
|
i = m_active_objects.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
|
{
|
||||||
|
u16 id = i.getNode()->getKey();
|
||||||
|
// Get object
|
||||||
|
ServerActiveObject *object = i.getNode()->getValue();
|
||||||
|
if(object == NULL)
|
||||||
|
continue;
|
||||||
|
// Discard if removed
|
||||||
|
if(object->m_removed)
|
||||||
|
continue;
|
||||||
|
// Discard if too far
|
||||||
|
f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
|
||||||
|
if(distance_f > radius_f)
|
||||||
|
continue;
|
||||||
|
// Discard if already on current_objects
|
||||||
|
core::map<u16, bool>::Node *n;
|
||||||
|
n = current_objects.find(id);
|
||||||
|
if(n != NULL)
|
||||||
|
continue;
|
||||||
|
// Add to added_objects
|
||||||
|
added_objects.insert(id, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Finds out what objects have been removed from
|
||||||
|
inside a radius around a position
|
||||||
|
*/
|
||||||
|
void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius,
|
||||||
|
core::map<u16, bool> ¤t_objects,
|
||||||
|
core::map<u16, bool> &removed_objects)
|
||||||
|
{
|
||||||
|
v3f pos_f = intToFloat(pos, BS);
|
||||||
|
f32 radius_f = radius * BS;
|
||||||
|
/*
|
||||||
|
Go through current_objects; object is removed if:
|
||||||
|
- object is not found in m_active_objects (this is actually an
|
||||||
|
error condition; objects should be set m_removed=true and removed
|
||||||
|
only after all clients have been informed about removal), or
|
||||||
|
- object has m_removed=true, or
|
||||||
|
- object is too far away
|
||||||
|
*/
|
||||||
|
for(core::map<u16, bool>::Iterator
|
||||||
|
i = current_objects.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
|
{
|
||||||
|
u16 id = i.getNode()->getKey();
|
||||||
|
ServerActiveObject *object = getActiveObject(id);
|
||||||
|
if(object == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: ServerEnvironment::getRemovedActiveObjects():"
|
||||||
|
<<" object in current_objects is NULL"<<std::endl;
|
||||||
|
}
|
||||||
|
else if(object->m_removed == false)
|
||||||
|
{
|
||||||
|
f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
|
||||||
|
/*dstream<<"removed == false"
|
||||||
|
<<"distance_f = "<<distance_f
|
||||||
|
<<", radius_f = "<<radius_f<<std::endl;*/
|
||||||
|
if(distance_f < radius_f)
|
||||||
|
{
|
||||||
|
// Not removed
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removed_objects.insert(id, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveObjectMessage ServerEnvironment::getActiveObjectMessage()
|
||||||
|
{
|
||||||
|
if(m_active_object_messages.size() == 0)
|
||||||
|
return ActiveObjectMessage(0);
|
||||||
|
|
||||||
|
return m_active_object_messages.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
void Environment::updateMeshes(v3s16 blockpos)
|
|
||||||
|
/*
|
||||||
|
ClientEnvironment
|
||||||
|
*/
|
||||||
|
|
||||||
|
ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr):
|
||||||
|
m_map(map),
|
||||||
|
m_smgr(smgr)
|
||||||
|
{
|
||||||
|
assert(m_map);
|
||||||
|
assert(m_smgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientEnvironment::~ClientEnvironment()
|
||||||
|
{
|
||||||
|
// delete active objects
|
||||||
|
for(core::map<u16, ClientActiveObject*>::Iterator
|
||||||
|
i = m_active_objects.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
|
{
|
||||||
|
delete i.getNode()->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop/delete map
|
||||||
|
m_map->drop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientEnvironment::addPlayer(Player *player)
|
||||||
|
{
|
||||||
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
/*
|
||||||
|
It is a failure if player is local and there already is a local
|
||||||
|
player
|
||||||
|
*/
|
||||||
|
assert(!(player->isLocal() == true && getLocalPlayer() != NULL));
|
||||||
|
|
||||||
|
Environment::addPlayer(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalPlayer * ClientEnvironment::getLocalPlayer()
|
||||||
|
{
|
||||||
|
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||||
|
i != m_players.end(); i++)
|
||||||
|
{
|
||||||
|
Player *player = *i;
|
||||||
|
if(player->isLocal())
|
||||||
|
return (LocalPlayer*)player;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientEnvironment::step(float dtime)
|
||||||
|
{
|
||||||
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
|
// Get some settings
|
||||||
|
bool free_move = g_settings.getBool("free_move");
|
||||||
|
bool footprints = g_settings.getBool("footprints");
|
||||||
|
|
||||||
|
{
|
||||||
|
//TimeTaker timer("Client m_map->timerUpdate()", g_device);
|
||||||
|
m_map->timerUpdate(dtime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get the speed the player is going
|
||||||
|
*/
|
||||||
|
f32 player_speed = 0.001; // just some small value
|
||||||
|
LocalPlayer *lplayer = getLocalPlayer();
|
||||||
|
if(lplayer)
|
||||||
|
player_speed = lplayer->getSpeed().getLength();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Maximum position increment
|
||||||
|
*/
|
||||||
|
//f32 position_max_increment = 0.05*BS;
|
||||||
|
f32 position_max_increment = 0.1*BS;
|
||||||
|
|
||||||
|
// Maximum time increment (for collision detection etc)
|
||||||
|
// time = distance / speed
|
||||||
|
f32 dtime_max_increment = position_max_increment / player_speed;
|
||||||
|
|
||||||
|
// Maximum time increment is 10ms or lower
|
||||||
|
if(dtime_max_increment > 0.01)
|
||||||
|
dtime_max_increment = 0.01;
|
||||||
|
|
||||||
|
// Don't allow overly huge dtime
|
||||||
|
if(dtime > 0.5)
|
||||||
|
dtime = 0.5;
|
||||||
|
|
||||||
|
f32 dtime_downcount = dtime;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Stuff that has a maximum time increment
|
||||||
|
*/
|
||||||
|
|
||||||
|
u32 loopcount = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
loopcount++;
|
||||||
|
|
||||||
|
f32 dtime_part;
|
||||||
|
if(dtime_downcount > dtime_max_increment)
|
||||||
|
dtime_part = dtime_max_increment;
|
||||||
|
else
|
||||||
|
dtime_part = dtime;
|
||||||
|
dtime_downcount -= dtime_part;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Handle local player
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
Player *player = getLocalPlayer();
|
||||||
|
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
|
||||||
|
// Apply physics
|
||||||
|
if(free_move == false)
|
||||||
|
{
|
||||||
|
// Gravity
|
||||||
|
v3f speed = player->getSpeed();
|
||||||
|
if(player->swimming_up == false)
|
||||||
|
speed.Y -= 9.81 * BS * dtime_part * 2;
|
||||||
|
|
||||||
|
// Water resistance
|
||||||
|
if(player->in_water_stable || player->in_water)
|
||||||
|
{
|
||||||
|
f32 max_down = 2.0*BS;
|
||||||
|
if(speed.Y < -max_down) speed.Y = -max_down;
|
||||||
|
|
||||||
|
f32 max = 2.5*BS;
|
||||||
|
if(speed.getLength() > max)
|
||||||
|
{
|
||||||
|
speed = speed / speed.getLength() * max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
player->setSpeed(speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move the player.
|
||||||
|
This also does collision detection.
|
||||||
|
*/
|
||||||
|
player->move(dtime_part, *m_map, position_max_increment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(dtime_downcount > 0.001);
|
||||||
|
|
||||||
|
//std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Stuff that can be done in an arbitarily large dtime
|
||||||
|
*/
|
||||||
|
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||||
|
i != m_players.end(); i++)
|
||||||
|
{
|
||||||
|
Player *player = *i;
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Handle non-local players
|
||||||
|
*/
|
||||||
|
if(player->isLocal() == false)
|
||||||
|
{
|
||||||
|
// Move
|
||||||
|
player->move(dtime, *m_map, 100*BS);
|
||||||
|
|
||||||
|
// Update lighting on remote players on client
|
||||||
|
u8 light = LIGHT_MAX;
|
||||||
|
try{
|
||||||
|
// Get node at head
|
||||||
|
v3s16 p = floatToInt(playerpos + v3f(0,BS+BS/2,0), BS);
|
||||||
|
MapNode n = m_map->getNode(p);
|
||||||
|
light = n.getLightBlend(m_daynight_ratio);
|
||||||
|
}
|
||||||
|
catch(InvalidPositionException &e) {}
|
||||||
|
player->updateLight(light);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add footsteps to grass
|
||||||
|
*/
|
||||||
|
if(footprints)
|
||||||
|
{
|
||||||
|
// Get node that is at BS/4 under player
|
||||||
|
v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS);
|
||||||
|
try{
|
||||||
|
MapNode n = m_map->getNode(bottompos);
|
||||||
|
if(n.d == CONTENT_GRASS)
|
||||||
|
{
|
||||||
|
n.d = CONTENT_GRASS_FOOTSTEPS;
|
||||||
|
m_map->setNode(bottompos, n);
|
||||||
|
// Update mesh on client
|
||||||
|
if(m_map->mapType() == MAPTYPE_CLIENT)
|
||||||
|
{
|
||||||
|
v3s16 p_blocks = getNodeBlockPos(bottompos);
|
||||||
|
MapBlock *b = m_map->getBlockNoCreate(p_blocks);
|
||||||
|
b->updateMesh(m_daynight_ratio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(InvalidPositionException &e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Step active objects
|
||||||
|
*/
|
||||||
|
for(core::map<u16, ClientActiveObject*>::Iterator
|
||||||
|
i = m_active_objects.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
|
{
|
||||||
|
ClientActiveObject* obj = i.getNode()->getValue();
|
||||||
|
// Step object
|
||||||
|
obj->step(dtime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientEnvironment::updateMeshes(v3s16 blockpos)
|
||||||
{
|
{
|
||||||
m_map->updateMeshes(blockpos, m_daynight_ratio);
|
m_map->updateMeshes(blockpos, m_daynight_ratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Environment::expireMeshes(bool only_daynight_diffed)
|
void ClientEnvironment::expireMeshes(bool only_daynight_diffed)
|
||||||
{
|
{
|
||||||
m_map->expireMeshes(only_daynight_diffed);
|
m_map->expireMeshes(only_daynight_diffed);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void Environment::setDayNightRatio(u32 r)
|
ClientActiveObject* ClientEnvironment::getActiveObject(u16 id)
|
||||||
{
|
{
|
||||||
m_daynight_ratio = r;
|
core::map<u16, ClientActiveObject*>::Node *n;
|
||||||
|
n = m_active_objects.find(id);
|
||||||
|
if(n == NULL)
|
||||||
|
return NULL;
|
||||||
|
return n->getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Environment::getDayNightRatio()
|
bool isFreeClientActiveObjectId(u16 id,
|
||||||
|
core::map<u16, ClientActiveObject*> &objects)
|
||||||
{
|
{
|
||||||
return m_daynight_ratio;
|
if(id == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for(core::map<u16, ClientActiveObject*>::Iterator
|
||||||
|
i = objects.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
|
{
|
||||||
|
if(i.getNode()->getKey() == id)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u16 getFreeClientActiveObjectId(
|
||||||
|
core::map<u16, ClientActiveObject*> &objects)
|
||||||
|
{
|
||||||
|
u16 new_id = 1;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if(isFreeClientActiveObjectId(new_id, objects))
|
||||||
|
return new_id;
|
||||||
|
|
||||||
|
if(new_id == 65535)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
new_id++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
|
||||||
|
{
|
||||||
|
assert(object);
|
||||||
|
if(object->getId() == 0)
|
||||||
|
{
|
||||||
|
u16 new_id = getFreeClientActiveObjectId(m_active_objects);
|
||||||
|
if(new_id == 0)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: ClientEnvironment::addActiveObject(): "
|
||||||
|
<<"no free ids available"<<std::endl;
|
||||||
|
delete object;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
object->setId(new_id);
|
||||||
|
}
|
||||||
|
if(isFreeClientActiveObjectId(object->getId(), m_active_objects) == false)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: ClientEnvironment::addActiveObject(): "
|
||||||
|
<<"id is not free ("<<object->getId()<<")"<<std::endl;
|
||||||
|
delete object;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
dstream<<"INGO: ClientEnvironment::addActiveObject(): "
|
||||||
|
<<"added (id="<<object->getId()<<")"<<std::endl;
|
||||||
|
m_active_objects.insert(object->getId(), object);
|
||||||
|
object->addToScene(m_smgr);
|
||||||
|
return object->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientEnvironment::addActiveObject(u16 id, u8 type)
|
||||||
|
{
|
||||||
|
ClientActiveObject* obj = ClientActiveObject::create(type);
|
||||||
|
if(obj == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: ClientEnvironment::addActiveObject(): "
|
||||||
|
<<"id="<<id<<" type="<<type<<": Couldn't create object"
|
||||||
|
<<std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->setId(id);
|
||||||
|
|
||||||
|
addActiveObject(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientEnvironment::removeActiveObject(u16 id)
|
||||||
|
{
|
||||||
|
dstream<<"ClientEnvironment::removeActiveObject(): "
|
||||||
|
<<"id="<<id<<std::endl;
|
||||||
|
ClientActiveObject* obj = getActiveObject(id);
|
||||||
|
if(obj == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: ClientEnvironment::removeActiveObject(): "
|
||||||
|
<<"id="<<id<<" not found"<<std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
obj->removeFromScene();
|
||||||
|
delete obj;
|
||||||
|
m_active_objects.remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientEnvironment::processActiveObjectMessage(u16 id,
|
||||||
|
const std::string &data)
|
||||||
|
{
|
||||||
|
ClientActiveObject* obj = getActiveObject(id);
|
||||||
|
if(obj == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: ClientEnvironment::processActiveObjectMessage():"
|
||||||
|
<<" got message for id="<<id<<", which doesn't exist."
|
||||||
|
<<std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
obj->processMessage(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // #ifndef SERVER
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,7 +26,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
- The map
|
- The map
|
||||||
- Players
|
- Players
|
||||||
- Other objects
|
- Other objects
|
||||||
- The current time in the game, etc.
|
- The current time in the game (actually it only contains the brightness)
|
||||||
|
- etc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
@ -39,51 +40,175 @@ class Environment
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Environment will delete the map passed to the constructor
|
// Environment will delete the map passed to the constructor
|
||||||
Environment(Map *map, std::ostream &dout);
|
Environment();
|
||||||
~Environment();
|
virtual ~Environment();
|
||||||
/*
|
|
||||||
This can do anything to the environment, such as removing
|
|
||||||
timed-out players.
|
|
||||||
Also updates Map's timers.
|
|
||||||
*/
|
|
||||||
void step(f32 dtime);
|
|
||||||
|
|
||||||
Map & getMap();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Environment deallocates players after use.
|
Step everything in environment.
|
||||||
|
- Move players
|
||||||
|
- Step mobs
|
||||||
|
- Run timers of map
|
||||||
*/
|
*/
|
||||||
void addPlayer(Player *player);
|
virtual void step(f32 dtime) = 0;
|
||||||
|
|
||||||
|
virtual Map & getMap() = 0;
|
||||||
|
|
||||||
|
virtual void addPlayer(Player *player);
|
||||||
void removePlayer(u16 peer_id);
|
void removePlayer(u16 peer_id);
|
||||||
#ifndef SERVER
|
|
||||||
LocalPlayer * getLocalPlayer();
|
|
||||||
#endif
|
|
||||||
Player * getPlayer(u16 peer_id);
|
Player * getPlayer(u16 peer_id);
|
||||||
Player * getPlayer(const char *name);
|
Player * getPlayer(const char *name);
|
||||||
core::list<Player*> getPlayers();
|
core::list<Player*> getPlayers();
|
||||||
core::list<Player*> getPlayers(bool ignore_disconnected);
|
core::list<Player*> getPlayers(bool ignore_disconnected);
|
||||||
void printPlayers(std::ostream &o);
|
void printPlayers(std::ostream &o);
|
||||||
|
|
||||||
void serializePlayers(const std::string &savedir);
|
|
||||||
// This loads players as ServerRemotePlayers
|
|
||||||
void deSerializePlayers(const std::string &savedir);
|
|
||||||
|
|
||||||
#ifndef SERVER
|
|
||||||
void updateMeshes(v3s16 blockpos);
|
|
||||||
void expireMeshes(bool only_daynight_diffed);
|
|
||||||
#endif
|
|
||||||
void setDayNightRatio(u32 r);
|
void setDayNightRatio(u32 r);
|
||||||
u32 getDayNightRatio();
|
u32 getDayNightRatio();
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
Map *m_map;
|
// peer_ids in here should be unique, except that there may be many 0s
|
||||||
// peer_ids in here should be unique, except that there may be
|
|
||||||
// many 0s
|
|
||||||
core::list<Player*> m_players;
|
core::list<Player*> m_players;
|
||||||
// Debug output goes here
|
// Brightness
|
||||||
std::ostream &m_dout;
|
|
||||||
u32 m_daynight_ratio;
|
u32 m_daynight_ratio;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
The server-side environment.
|
||||||
|
|
||||||
|
This is not thread-safe. Server uses an environment mutex.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "serverobject.h"
|
||||||
|
|
||||||
|
class ServerEnvironment : public Environment
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ServerEnvironment(ServerMap *map);
|
||||||
|
~ServerEnvironment();
|
||||||
|
|
||||||
|
Map & getMap()
|
||||||
|
{
|
||||||
|
return *m_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerMap & getServerMap()
|
||||||
|
{
|
||||||
|
return *m_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(f32 dtime);
|
||||||
|
|
||||||
|
void serializePlayers(const std::string &savedir);
|
||||||
|
void deSerializePlayers(const std::string &savedir);
|
||||||
|
|
||||||
|
/*
|
||||||
|
ActiveObjects
|
||||||
|
*/
|
||||||
|
|
||||||
|
ServerActiveObject* getActiveObject(u16 id);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Adds an active object to the environment.
|
||||||
|
Environment handles deletion of object.
|
||||||
|
Object may be deleted by environment immediately.
|
||||||
|
If id of object is 0, assigns a free id to it.
|
||||||
|
Returns the id of the object.
|
||||||
|
Returns 0 if not added and thus deleted.
|
||||||
|
*/
|
||||||
|
u16 addActiveObject(ServerActiveObject *object);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Finds out what new objects have been added to
|
||||||
|
inside a radius around a position
|
||||||
|
*/
|
||||||
|
void getAddedActiveObjects(v3s16 pos, s16 radius,
|
||||||
|
core::map<u16, bool> ¤t_objects,
|
||||||
|
core::map<u16, bool> &added_objects);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Finds out what new objects have been removed from
|
||||||
|
inside a radius around a position
|
||||||
|
*/
|
||||||
|
void getRemovedActiveObjects(v3s16 pos, s16 radius,
|
||||||
|
core::map<u16, bool> ¤t_objects,
|
||||||
|
core::map<u16, bool> &removed_objects);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Gets the next message emitted by some active object.
|
||||||
|
Returns a message with id=0 if no messages are available.
|
||||||
|
*/
|
||||||
|
ActiveObjectMessage getActiveObjectMessage();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ServerMap *m_map;
|
||||||
|
core::map<u16, ServerActiveObject*> m_active_objects;
|
||||||
|
Queue<ActiveObjectMessage> m_active_object_messages;
|
||||||
|
float m_random_spawn_timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef SERVER
|
||||||
|
|
||||||
|
#include "clientobject.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
The client-side environment.
|
||||||
|
|
||||||
|
This is not thread-safe.
|
||||||
|
Must be called from main (irrlicht) thread (uses the SceneManager)
|
||||||
|
Client uses an environment mutex.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ClientEnvironment : public Environment
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr);
|
||||||
|
~ClientEnvironment();
|
||||||
|
|
||||||
|
Map & getMap()
|
||||||
|
{
|
||||||
|
return *m_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientMap & getClientMap()
|
||||||
|
{
|
||||||
|
return *m_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(f32 dtime);
|
||||||
|
|
||||||
|
virtual void addPlayer(Player *player);
|
||||||
|
LocalPlayer * getLocalPlayer();
|
||||||
|
|
||||||
|
void updateMeshes(v3s16 blockpos);
|
||||||
|
void expireMeshes(bool only_daynight_diffed);
|
||||||
|
|
||||||
|
/*
|
||||||
|
ActiveObjects
|
||||||
|
*/
|
||||||
|
|
||||||
|
ClientActiveObject* getActiveObject(u16 id);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Adds an active object to the environment.
|
||||||
|
Environment handles deletion of object.
|
||||||
|
Object may be deleted by environment immediately.
|
||||||
|
If id of object is 0, assigns a free id to it.
|
||||||
|
Returns the id of the object.
|
||||||
|
Returns 0 if not added and thus deleted.
|
||||||
|
*/
|
||||||
|
u16 addActiveObject(ClientActiveObject *object);
|
||||||
|
|
||||||
|
void addActiveObject(u16 id, u8 type);
|
||||||
|
void removeActiveObject(u16 id);
|
||||||
|
|
||||||
|
void processActiveObjectMessage(u16 id, const std::string &data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ClientMap *m_map;
|
||||||
|
scene::ISceneManager *m_smgr;
|
||||||
|
core::map<u16, ClientActiveObject*> m_active_objects;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
#endif // _WIN32_WCE
|
#endif // _WIN32_WCE
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
// CriticalSection is way faster than the alternative
|
||||||
#define JMUTEX_CRITICALSECTION
|
#define JMUTEX_CRITICALSECTION
|
||||||
#else // using pthread
|
#else // using pthread
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
91
src/main.cpp
91
src/main.cpp
@ -160,32 +160,23 @@ TODO: Make fetching sector's blocks more efficient when rendering
|
|||||||
|
|
||||||
TODO: Flowing water animation
|
TODO: Flowing water animation
|
||||||
|
|
||||||
NOTE(FIXED): A lock condition is possible:
|
|
||||||
1) MapBlock::updateMesh() is called from client asynchronously:
|
|
||||||
- AsyncProcessData() -> Map::updateMeshes()
|
|
||||||
2) Asynchronous locks m_temp_mods_mutex
|
|
||||||
3) MapBlock::updateMesh() is called from client synchronously:
|
|
||||||
- Client::step() -> Environment::step()
|
|
||||||
4) Synchronous starts waiting for m_temp_mods_mutex
|
|
||||||
5) Asynchronous calls getTexture, which starts waiting for main thread
|
|
||||||
|
|
||||||
Configuration:
|
Configuration:
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
TODO: Make the video backend selectable
|
|
||||||
|
|
||||||
Client:
|
Client:
|
||||||
-------
|
-------
|
||||||
|
|
||||||
TODO: Untie client network operations from framerate
|
TODO: Untie client network operations from framerate
|
||||||
- Needs some input queues or something
|
- Needs some input queues or something
|
||||||
|
|
||||||
TODO: Make morning and evening transition more smooth and maybe shorter
|
SUGG: Make morning and evening transition more smooth and maybe shorter
|
||||||
|
|
||||||
TODO: Don't update all meshes always on single node changes, but
|
SUGG: Don't update all meshes always on single node changes, but
|
||||||
check which ones should be updated
|
check which ones should be updated
|
||||||
- implement Map::updateNodeMeshes()
|
- implement Map::updateNodeMeshes()
|
||||||
|
|
||||||
|
TODO: Remove IrrlichtWrapper
|
||||||
|
|
||||||
Server:
|
Server:
|
||||||
-------
|
-------
|
||||||
|
|
||||||
@ -194,16 +185,13 @@ TODO: When player dies, throw items on map
|
|||||||
TODO: Make an option to the server to disable building and digging near
|
TODO: Make an option to the server to disable building and digging near
|
||||||
the starting position
|
the starting position
|
||||||
|
|
||||||
TODO: Save players with inventories to disk
|
|
||||||
TODO: Players to be saved as text in map/players/<name>
|
|
||||||
|
|
||||||
TODO: Copy the text of the last picked sign to inventory in creative
|
TODO: Copy the text of the last picked sign to inventory in creative
|
||||||
mode
|
mode
|
||||||
|
|
||||||
TODO: Check what goes wrong with caching map to disk (Kray)
|
TODO: Check what goes wrong with caching map to disk (Kray)
|
||||||
- Nothing?
|
- Nothing?
|
||||||
|
|
||||||
TODO: When server sees that client is removing an inexistent block to
|
TODO: When server sees that client is removing an inexistent block in
|
||||||
an existent position, resend the MapBlock.
|
an existent position, resend the MapBlock.
|
||||||
|
|
||||||
FIXME: Server went into some infinite PeerNotFoundException loop
|
FIXME: Server went into some infinite PeerNotFoundException loop
|
||||||
@ -237,6 +225,11 @@ Block object server side:
|
|||||||
- TODO: For incoming blocks, time difference is calculated and
|
- TODO: For incoming blocks, time difference is calculated and
|
||||||
objects are stepped according to it.
|
objects are stepped according to it.
|
||||||
|
|
||||||
|
- When an active object goes far from a player, either delete
|
||||||
|
it or store it statically.
|
||||||
|
- When a statically stored active object comes near a player,
|
||||||
|
recreate the active object
|
||||||
|
|
||||||
Map:
|
Map:
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -345,18 +338,18 @@ Doing now (most important at the top):
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <jmutexautolock.h>
|
#include <jmutexautolock.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include "main.h"
|
||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "main.h"
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
#include "environment.h"
|
//#include "environment.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "serialization.h"
|
//#include "serialization.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "strfnd.h"
|
//#include "strfnd.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "irrlichtwrapper.h"
|
#include "irrlichtwrapper.h"
|
||||||
#include "gettime.h"
|
#include "gettime.h"
|
||||||
@ -905,8 +898,12 @@ class RandomInputHandler : public InputHandler
|
|||||||
public:
|
public:
|
||||||
RandomInputHandler()
|
RandomInputHandler()
|
||||||
{
|
{
|
||||||
|
leftdown = false;
|
||||||
|
rightdown = false;
|
||||||
leftclicked = false;
|
leftclicked = false;
|
||||||
rightclicked = false;
|
rightclicked = false;
|
||||||
|
leftreleased = false;
|
||||||
|
rightreleased = false;
|
||||||
for(u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
|
for(u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
|
||||||
keydown[i] = false;
|
keydown[i] = false;
|
||||||
}
|
}
|
||||||
@ -925,11 +922,11 @@ public:
|
|||||||
|
|
||||||
virtual bool getLeftState()
|
virtual bool getLeftState()
|
||||||
{
|
{
|
||||||
return false;
|
return leftdown;
|
||||||
}
|
}
|
||||||
virtual bool getRightState()
|
virtual bool getRightState()
|
||||||
{
|
{
|
||||||
return false;
|
return rightdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool getLeftClicked()
|
virtual bool getLeftClicked()
|
||||||
@ -951,37 +948,23 @@ public:
|
|||||||
|
|
||||||
virtual bool getLeftReleased()
|
virtual bool getLeftReleased()
|
||||||
{
|
{
|
||||||
return false;
|
return leftreleased;
|
||||||
}
|
}
|
||||||
virtual bool getRightReleased()
|
virtual bool getRightReleased()
|
||||||
{
|
{
|
||||||
return false;
|
return rightreleased;
|
||||||
}
|
}
|
||||||
virtual void resetLeftReleased()
|
virtual void resetLeftReleased()
|
||||||
{
|
{
|
||||||
|
leftreleased = false;
|
||||||
}
|
}
|
||||||
virtual void resetRightReleased()
|
virtual void resetRightReleased()
|
||||||
{
|
{
|
||||||
|
rightreleased = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void step(float dtime)
|
virtual void step(float dtime)
|
||||||
{
|
{
|
||||||
{
|
|
||||||
static float counter1 = 0;
|
|
||||||
counter1 -= dtime;
|
|
||||||
if(counter1 < 0.0)
|
|
||||||
{
|
|
||||||
counter1 = 0.1*Rand(1,10);
|
|
||||||
/*if(g_selected_material < USEFUL_CONTENT_COUNT-1)
|
|
||||||
g_selected_material++;
|
|
||||||
else
|
|
||||||
g_selected_material = 0;*/
|
|
||||||
if(g_selected_item < PLAYER_INVENTORY_SIZE-1)
|
|
||||||
g_selected_item++;
|
|
||||||
else
|
|
||||||
g_selected_item = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
static float counter1 = 0;
|
static float counter1 = 0;
|
||||||
counter1 -= dtime;
|
counter1 -= dtime;
|
||||||
@ -1033,7 +1016,11 @@ public:
|
|||||||
if(counter1 < 0.0)
|
if(counter1 < 0.0)
|
||||||
{
|
{
|
||||||
counter1 = 0.1*Rand(1, 30);
|
counter1 = 0.1*Rand(1, 30);
|
||||||
leftclicked = true;
|
leftdown = !leftdown;
|
||||||
|
if(leftdown)
|
||||||
|
leftclicked = true;
|
||||||
|
if(!leftdown)
|
||||||
|
leftreleased = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -1041,8 +1028,12 @@ public:
|
|||||||
counter1 -= dtime;
|
counter1 -= dtime;
|
||||||
if(counter1 < 0.0)
|
if(counter1 < 0.0)
|
||||||
{
|
{
|
||||||
counter1 = 0.1*Rand(1, 20);
|
counter1 = 0.1*Rand(1, 15);
|
||||||
rightclicked = true;
|
rightdown = !rightdown;
|
||||||
|
if(rightdown)
|
||||||
|
rightclicked = true;
|
||||||
|
if(!rightdown)
|
||||||
|
rightreleased = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mousepos += mousespeed;
|
mousepos += mousespeed;
|
||||||
@ -1056,8 +1047,12 @@ private:
|
|||||||
bool keydown[KEY_KEY_CODES_COUNT];
|
bool keydown[KEY_KEY_CODES_COUNT];
|
||||||
v2s32 mousepos;
|
v2s32 mousepos;
|
||||||
v2s32 mousespeed;
|
v2s32 mousespeed;
|
||||||
|
bool leftdown;
|
||||||
|
bool rightdown;
|
||||||
bool leftclicked;
|
bool leftclicked;
|
||||||
bool rightclicked;
|
bool rightclicked;
|
||||||
|
bool leftreleased;
|
||||||
|
bool rightreleased;
|
||||||
};
|
};
|
||||||
|
|
||||||
void updateViewingRange(f32 frametime_in, Client *client)
|
void updateViewingRange(f32 frametime_in, Client *client)
|
||||||
@ -2486,11 +2481,9 @@ int main(int argc, char *argv[])
|
|||||||
camera->setTarget(camera_position + camera_direction * 100.0);
|
camera->setTarget(camera_position + camera_direction * 100.0);
|
||||||
|
|
||||||
if(FIELD_OF_VIEW_TEST){
|
if(FIELD_OF_VIEW_TEST){
|
||||||
//client.m_env.getMap().updateCamera(v3f(0,0,0), v3f(0,0,1));
|
|
||||||
client.updateCamera(v3f(0,0,0), v3f(0,0,1));
|
client.updateCamera(v3f(0,0,0), v3f(0,0,1));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
//client.m_env.getMap().updateCamera(camera_position, camera_direction);
|
|
||||||
//TimeTaker timer("client.updateCamera");
|
//TimeTaker timer("client.updateCamera");
|
||||||
client.updateCamera(camera_position, camera_direction);
|
client.updateCamera(camera_position, camera_direction);
|
||||||
}
|
}
|
||||||
@ -2585,7 +2578,7 @@ int main(int argc, char *argv[])
|
|||||||
core::aabbox3d<f32> nodehilightbox;
|
core::aabbox3d<f32> nodehilightbox;
|
||||||
f32 mindistance = BS * 1001;
|
f32 mindistance = BS * 1001;
|
||||||
|
|
||||||
v3s16 pos_i = floatToInt(player_position);
|
v3s16 pos_i = floatToInt(player_position, BS);
|
||||||
|
|
||||||
/*std::cout<<"pos_i=("<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z<<")"
|
/*std::cout<<"pos_i=("<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z<<")"
|
||||||
<<std::endl;*/
|
<<std::endl;*/
|
||||||
@ -2615,7 +2608,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
v3s16 np(x,y,z);
|
v3s16 np(x,y,z);
|
||||||
v3f npf = intToFloat(np);
|
v3f npf = intToFloat(np, BS);
|
||||||
|
|
||||||
f32 d = 0.01;
|
f32 d = 0.01;
|
||||||
|
|
||||||
@ -2723,7 +2716,7 @@ int main(int argc, char *argv[])
|
|||||||
const float d = 0.502;
|
const float d = 0.502;
|
||||||
core::aabbox3d<f32> nodebox
|
core::aabbox3d<f32> nodebox
|
||||||
(-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d);
|
(-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d);
|
||||||
v3f nodepos_f = intToFloat(nodepos);
|
v3f nodepos_f = intToFloat(nodepos, BS);
|
||||||
nodebox.MinEdge += nodepos_f;
|
nodebox.MinEdge += nodepos_f;
|
||||||
nodebox.MaxEdge += nodepos_f;
|
nodebox.MaxEdge += nodepos_f;
|
||||||
nodehilightbox = nodebox;
|
nodehilightbox = nodebox;
|
||||||
|
177
src/map.cpp
177
src/map.cpp
@ -1221,95 +1221,6 @@ void Map::removeNodeAndUpdate(v3s16 p,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SERVER
|
|
||||||
void Map::expireMeshes(bool only_daynight_diffed)
|
|
||||||
{
|
|
||||||
TimeTaker timer("expireMeshes()");
|
|
||||||
|
|
||||||
core::map<v2s16, MapSector*>::Iterator si;
|
|
||||||
si = m_sectors.getIterator();
|
|
||||||
for(; si.atEnd() == false; si++)
|
|
||||||
{
|
|
||||||
MapSector *sector = si.getNode()->getValue();
|
|
||||||
|
|
||||||
core::list< MapBlock * > sectorblocks;
|
|
||||||
sector->getBlocks(sectorblocks);
|
|
||||||
|
|
||||||
core::list< MapBlock * >::Iterator i;
|
|
||||||
for(i=sectorblocks.begin(); i!=sectorblocks.end(); i++)
|
|
||||||
{
|
|
||||||
MapBlock *block = *i;
|
|
||||||
|
|
||||||
if(only_daynight_diffed && dayNightDiffed(block->getPos()) == false)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
JMutexAutoLock lock(block->mesh_mutex);
|
|
||||||
if(block->mesh != NULL)
|
|
||||||
{
|
|
||||||
/*block->mesh->drop();
|
|
||||||
block->mesh = NULL;*/
|
|
||||||
block->setMeshExpired(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Map::updateMeshes(v3s16 blockpos, u32 daynight_ratio)
|
|
||||||
{
|
|
||||||
assert(mapType() == MAPTYPE_CLIENT);
|
|
||||||
|
|
||||||
try{
|
|
||||||
v3s16 p = blockpos + v3s16(0,0,0);
|
|
||||||
MapBlock *b = getBlockNoCreate(p);
|
|
||||||
b->updateMesh(daynight_ratio);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e){}
|
|
||||||
// Leading edge
|
|
||||||
try{
|
|
||||||
v3s16 p = blockpos + v3s16(-1,0,0);
|
|
||||||
MapBlock *b = getBlockNoCreate(p);
|
|
||||||
b->updateMesh(daynight_ratio);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e){}
|
|
||||||
try{
|
|
||||||
v3s16 p = blockpos + v3s16(0,-1,0);
|
|
||||||
MapBlock *b = getBlockNoCreate(p);
|
|
||||||
b->updateMesh(daynight_ratio);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e){}
|
|
||||||
try{
|
|
||||||
v3s16 p = blockpos + v3s16(0,0,-1);
|
|
||||||
MapBlock *b = getBlockNoCreate(p);
|
|
||||||
b->updateMesh(daynight_ratio);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e){}
|
|
||||||
/*// Trailing edge
|
|
||||||
try{
|
|
||||||
v3s16 p = blockpos + v3s16(1,0,0);
|
|
||||||
MapBlock *b = getBlockNoCreate(p);
|
|
||||||
b->updateMesh(daynight_ratio);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e){}
|
|
||||||
try{
|
|
||||||
v3s16 p = blockpos + v3s16(0,1,0);
|
|
||||||
MapBlock *b = getBlockNoCreate(p);
|
|
||||||
b->updateMesh(daynight_ratio);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e){}
|
|
||||||
try{
|
|
||||||
v3s16 p = blockpos + v3s16(0,0,1);
|
|
||||||
MapBlock *b = getBlockNoCreate(p);
|
|
||||||
b->updateMesh(daynight_ratio);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e){}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool Map::dayNightDiffed(v3s16 blockpos)
|
bool Map::dayNightDiffed(v3s16 blockpos)
|
||||||
{
|
{
|
||||||
try{
|
try{
|
||||||
@ -4371,7 +4282,7 @@ continue_generating:
|
|||||||
//if(!is_ground_content(block->getNode(cp).d))
|
//if(!is_ground_content(block->getNode(cp).d))
|
||||||
if(1)
|
if(1)
|
||||||
{
|
{
|
||||||
RatObject *obj = new RatObject(NULL, -1, intToFloat(cp));
|
RatObject *obj = new RatObject(NULL, -1, intToFloat(cp, BS));
|
||||||
block->addObject(obj);
|
block->addObject(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5667,6 +5578,92 @@ bool ClientMap::clearTempMod(v3s16 p,
|
|||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientMap::expireMeshes(bool only_daynight_diffed)
|
||||||
|
{
|
||||||
|
TimeTaker timer("expireMeshes()");
|
||||||
|
|
||||||
|
core::map<v2s16, MapSector*>::Iterator si;
|
||||||
|
si = m_sectors.getIterator();
|
||||||
|
for(; si.atEnd() == false; si++)
|
||||||
|
{
|
||||||
|
MapSector *sector = si.getNode()->getValue();
|
||||||
|
|
||||||
|
core::list< MapBlock * > sectorblocks;
|
||||||
|
sector->getBlocks(sectorblocks);
|
||||||
|
|
||||||
|
core::list< MapBlock * >::Iterator i;
|
||||||
|
for(i=sectorblocks.begin(); i!=sectorblocks.end(); i++)
|
||||||
|
{
|
||||||
|
MapBlock *block = *i;
|
||||||
|
|
||||||
|
if(only_daynight_diffed && dayNightDiffed(block->getPos()) == false)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(block->mesh_mutex);
|
||||||
|
if(block->mesh != NULL)
|
||||||
|
{
|
||||||
|
/*block->mesh->drop();
|
||||||
|
block->mesh = NULL;*/
|
||||||
|
block->setMeshExpired(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientMap::updateMeshes(v3s16 blockpos, u32 daynight_ratio)
|
||||||
|
{
|
||||||
|
assert(mapType() == MAPTYPE_CLIENT);
|
||||||
|
|
||||||
|
try{
|
||||||
|
v3s16 p = blockpos + v3s16(0,0,0);
|
||||||
|
MapBlock *b = getBlockNoCreate(p);
|
||||||
|
b->updateMesh(daynight_ratio);
|
||||||
|
}
|
||||||
|
catch(InvalidPositionException &e){}
|
||||||
|
// Leading edge
|
||||||
|
try{
|
||||||
|
v3s16 p = blockpos + v3s16(-1,0,0);
|
||||||
|
MapBlock *b = getBlockNoCreate(p);
|
||||||
|
b->updateMesh(daynight_ratio);
|
||||||
|
}
|
||||||
|
catch(InvalidPositionException &e){}
|
||||||
|
try{
|
||||||
|
v3s16 p = blockpos + v3s16(0,-1,0);
|
||||||
|
MapBlock *b = getBlockNoCreate(p);
|
||||||
|
b->updateMesh(daynight_ratio);
|
||||||
|
}
|
||||||
|
catch(InvalidPositionException &e){}
|
||||||
|
try{
|
||||||
|
v3s16 p = blockpos + v3s16(0,0,-1);
|
||||||
|
MapBlock *b = getBlockNoCreate(p);
|
||||||
|
b->updateMesh(daynight_ratio);
|
||||||
|
}
|
||||||
|
catch(InvalidPositionException &e){}
|
||||||
|
/*// Trailing edge
|
||||||
|
try{
|
||||||
|
v3s16 p = blockpos + v3s16(1,0,0);
|
||||||
|
MapBlock *b = getBlockNoCreate(p);
|
||||||
|
b->updateMesh(daynight_ratio);
|
||||||
|
}
|
||||||
|
catch(InvalidPositionException &e){}
|
||||||
|
try{
|
||||||
|
v3s16 p = blockpos + v3s16(0,1,0);
|
||||||
|
MapBlock *b = getBlockNoCreate(p);
|
||||||
|
b->updateMesh(daynight_ratio);
|
||||||
|
}
|
||||||
|
catch(InvalidPositionException &e){}
|
||||||
|
try{
|
||||||
|
v3s16 p = blockpos + v3s16(0,0,1);
|
||||||
|
MapBlock *b = getBlockNoCreate(p);
|
||||||
|
b->updateMesh(daynight_ratio);
|
||||||
|
}
|
||||||
|
catch(InvalidPositionException &e){}*/
|
||||||
|
}
|
||||||
|
|
||||||
void ClientMap::PrintInfo(std::ostream &out)
|
void ClientMap::PrintInfo(std::ostream &out)
|
||||||
{
|
{
|
||||||
out<<"ClientMap: ";
|
out<<"ClientMap: ";
|
||||||
|
28
src/map.h
28
src/map.h
@ -33,7 +33,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
//#include "heightmap.h"
|
|
||||||
#include "mapnode.h"
|
#include "mapnode.h"
|
||||||
#include "mapblock.h"
|
#include "mapblock.h"
|
||||||
#include "mapsector.h"
|
#include "mapsector.h"
|
||||||
@ -62,6 +61,9 @@ public:
|
|||||||
return MAPTYPE_BASE;
|
return MAPTYPE_BASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Drop (client) or delete (server) the map.
|
||||||
|
*/
|
||||||
virtual void drop()
|
virtual void drop()
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
@ -211,19 +213,6 @@ public:
|
|||||||
void removeNodeAndUpdate(v3s16 p,
|
void removeNodeAndUpdate(v3s16 p,
|
||||||
core::map<v3s16, MapBlock*> &modified_blocks);
|
core::map<v3s16, MapBlock*> &modified_blocks);
|
||||||
|
|
||||||
#ifndef SERVER
|
|
||||||
void expireMeshes(bool only_daynight_diffed);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Update the faces of the given block and blocks on the
|
|
||||||
leading edge.
|
|
||||||
*/
|
|
||||||
void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
|
|
||||||
|
|
||||||
// Update meshes that touch the node
|
|
||||||
//void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Takes the blocks at the edges into account
|
Takes the blocks at the edges into account
|
||||||
*/
|
*/
|
||||||
@ -628,6 +617,17 @@ public:
|
|||||||
// Efficient implementation needs a cache of TempMods
|
// Efficient implementation needs a cache of TempMods
|
||||||
//void clearTempMods();
|
//void clearTempMods();
|
||||||
|
|
||||||
|
void expireMeshes(bool only_daynight_diffed);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Update the faces of the given block and blocks on the
|
||||||
|
leading edge.
|
||||||
|
*/
|
||||||
|
void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
|
||||||
|
|
||||||
|
// Update meshes that touch the node
|
||||||
|
//void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
|
||||||
|
|
||||||
// For debug printing
|
// For debug printing
|
||||||
virtual void PrintInfo(std::ostream &out);
|
virtual void PrintInfo(std::ostream &out);
|
||||||
|
|
||||||
|
@ -822,7 +822,7 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
if(dir == v3s16(0,1,0))
|
if(dir == v3s16(0,1,0))
|
||||||
vertices[i].Pos.rotateXZBy(-45);
|
vertices[i].Pos.rotateXZBy(-45);
|
||||||
|
|
||||||
vertices[i].Pos += intToFloat(p + getPosRelative());
|
vertices[i].Pos += intToFloat(p + getPosRelative(), BS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set material
|
// Set material
|
||||||
@ -1066,7 +1066,7 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
if(dir == v3s16(1,0,-0))
|
if(dir == v3s16(1,0,-0))
|
||||||
vertices[j].Pos.rotateXZBy(-90);
|
vertices[j].Pos.rotateXZBy(-90);
|
||||||
|
|
||||||
vertices[j].Pos += intToFloat(p + getPosRelative());
|
vertices[j].Pos += intToFloat(p + getPosRelative(), BS);
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
@ -1105,7 +1105,7 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
//vertices[i].Pos.Y += neighbor_levels[v3s16(0,0,0)];
|
//vertices[i].Pos.Y += neighbor_levels[v3s16(0,0,0)];
|
||||||
s32 j = corner_resolve[i];
|
s32 j = corner_resolve[i];
|
||||||
vertices[i].Pos.Y += corner_levels[j];
|
vertices[i].Pos.Y += corner_levels[j];
|
||||||
vertices[i].Pos += intToFloat(p + getPosRelative());
|
vertices[i].Pos += intToFloat(p + getPosRelative(), BS);
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
@ -1155,7 +1155,7 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
for(s32 i=0; i<4; i++)
|
for(s32 i=0; i<4; i++)
|
||||||
{
|
{
|
||||||
vertices[i].Pos.Y += (-0.5+node_water_level)*BS;
|
vertices[i].Pos.Y += (-0.5+node_water_level)*BS;
|
||||||
vertices[i].Pos += intToFloat(p + getPosRelative());
|
vertices[i].Pos += intToFloat(p + getPosRelative(), BS);
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
@ -1222,7 +1222,7 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
|
|
||||||
for(u16 i=0; i<4; i++)
|
for(u16 i=0; i<4; i++)
|
||||||
{
|
{
|
||||||
vertices[i].Pos += intToFloat(p + getPosRelative());
|
vertices[i].Pos += intToFloat(p + getPosRelative(), BS);
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
@ -1596,7 +1596,7 @@ void MapBlock::stepObjects(float dtime, bool server, u32 daynight_ratio)
|
|||||||
if(getNode(p).d == CONTENT_AIR
|
if(getNode(p).d == CONTENT_AIR
|
||||||
&& getNode(p).getLightBlend(daynight_ratio) <= 11)
|
&& getNode(p).getLightBlend(daynight_ratio) <= 11)
|
||||||
{
|
{
|
||||||
RatObject *obj = new RatObject(NULL, -1, intToFloat(p));
|
RatObject *obj = new RatObject(NULL, -1, intToFloat(p, BS));
|
||||||
addObject(obj);
|
addObject(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ v3f MapBlockObject::getAbsolutePos()
|
|||||||
return m_pos;
|
return m_pos;
|
||||||
|
|
||||||
// getPosRelative gets nodepos relative to map origin
|
// getPosRelative gets nodepos relative to map origin
|
||||||
v3f blockpos = intToFloat(m_block->getPosRelative());
|
v3f blockpos = intToFloat(m_block->getPosRelative(), BS);
|
||||||
return blockpos + m_pos;
|
return blockpos + m_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ v3f MovingObject::getAbsoluteShowPos()
|
|||||||
return m_pos;
|
return m_pos;
|
||||||
|
|
||||||
// getPosRelative gets nodepos relative to map origin
|
// getPosRelative gets nodepos relative to map origin
|
||||||
v3f blockpos = intToFloat(m_block->getPosRelative());
|
v3f blockpos = intToFloat(m_block->getPosRelative(), BS);
|
||||||
return blockpos + m_showpos;
|
return blockpos + m_showpos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ void MovingObject::move(float dtime, v3f acceleration)
|
|||||||
acceleration.X, acceleration.Y, acceleration.Z
|
acceleration.X, acceleration.Y, acceleration.Z
|
||||||
);
|
);
|
||||||
|
|
||||||
v3s16 oldpos_i = floatToInt(m_pos);
|
v3s16 oldpos_i = floatToInt(m_pos, BS);
|
||||||
|
|
||||||
if(m_block->isValidPosition(oldpos_i) == false)
|
if(m_block->isValidPosition(oldpos_i) == false)
|
||||||
{
|
{
|
||||||
@ -137,7 +137,7 @@ void MovingObject::move(float dtime, v3f acceleration)
|
|||||||
Collision detection
|
Collision detection
|
||||||
*/
|
*/
|
||||||
|
|
||||||
v3s16 pos_i = floatToInt(position);
|
v3s16 pos_i = floatToInt(position, BS);
|
||||||
|
|
||||||
// The loop length is limited to the object moving a distance
|
// The loop length is limited to the object moving a distance
|
||||||
f32 d = (float)BS * 0.15;
|
f32 d = (float)BS * 0.15;
|
||||||
@ -614,7 +614,7 @@ void MapBlockObjectList::update(std::istream &is, u8 version,
|
|||||||
{
|
{
|
||||||
u8 light = LIGHT_MAX;
|
u8 light = LIGHT_MAX;
|
||||||
try{
|
try{
|
||||||
v3s16 relpos_i = floatToInt(obj->m_pos);
|
v3s16 relpos_i = floatToInt(obj->m_pos, BS);
|
||||||
MapNode n = m_block->getNodeParent(relpos_i);
|
MapNode n = m_block->getNodeParent(relpos_i);
|
||||||
light = n.getLightBlend(daynight_ratio);
|
light = n.getLightBlend(daynight_ratio);
|
||||||
}
|
}
|
||||||
@ -772,7 +772,7 @@ void MapBlockObjectList::step(float dtime, bool server, u32 daynight_ratio)
|
|||||||
// Update light
|
// Update light
|
||||||
u8 light = LIGHT_MAX;
|
u8 light = LIGHT_MAX;
|
||||||
try{
|
try{
|
||||||
v3s16 relpos_i = floatToInt(obj->m_pos);
|
v3s16 relpos_i = floatToInt(obj->m_pos, BS);
|
||||||
MapNode n = m_block->getNodeParent(relpos_i);
|
MapNode n = m_block->getNodeParent(relpos_i);
|
||||||
light = n.getLightBlend(daynight_ratio);
|
light = n.getLightBlend(daynight_ratio);
|
||||||
}
|
}
|
||||||
@ -824,7 +824,7 @@ void MapBlockObjectList::step(float dtime, bool server, u32 daynight_ratio)
|
|||||||
{
|
{
|
||||||
MapBlockObject *obj = i.getNode()->getValue();
|
MapBlockObject *obj = i.getNode()->getValue();
|
||||||
|
|
||||||
v3s16 pos_i = floatToInt(obj->m_pos);
|
v3s16 pos_i = floatToInt(obj->m_pos, BS);
|
||||||
|
|
||||||
if(m_block->isValidPosition(pos_i))
|
if(m_block->isValidPosition(pos_i))
|
||||||
{
|
{
|
||||||
@ -871,7 +871,7 @@ bool MapBlockObjectList::wrapObject(MapBlockObject *object)
|
|||||||
// Calculate blockpos on map
|
// Calculate blockpos on map
|
||||||
v3s16 oldblock_pos_i_on_map = m_block->getPosRelative();
|
v3s16 oldblock_pos_i_on_map = m_block->getPosRelative();
|
||||||
v3f pos_f_on_oldblock = object->m_pos;
|
v3f pos_f_on_oldblock = object->m_pos;
|
||||||
v3s16 pos_i_on_oldblock = floatToInt(pos_f_on_oldblock);
|
v3s16 pos_i_on_oldblock = floatToInt(pos_f_on_oldblock, BS);
|
||||||
v3s16 pos_i_on_map = pos_i_on_oldblock + oldblock_pos_i_on_map;
|
v3s16 pos_i_on_map = pos_i_on_oldblock + oldblock_pos_i_on_map;
|
||||||
v3s16 pos_blocks_on_map = getNodeBlockPos(pos_i_on_map);
|
v3s16 pos_blocks_on_map = getNodeBlockPos(pos_i_on_map);
|
||||||
|
|
||||||
@ -905,9 +905,9 @@ bool MapBlockObjectList::wrapObject(MapBlockObject *object)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate position on new block
|
// Calculate position on new block
|
||||||
v3f oldblock_pos_f_on_map = intToFloat(oldblock_pos_i_on_map);
|
v3f oldblock_pos_f_on_map = intToFloat(oldblock_pos_i_on_map, BS);
|
||||||
v3s16 newblock_pos_i_on_map = newblock->getPosRelative();
|
v3s16 newblock_pos_i_on_map = newblock->getPosRelative();
|
||||||
v3f newblock_pos_f_on_map = intToFloat(newblock_pos_i_on_map);
|
v3f newblock_pos_f_on_map = intToFloat(newblock_pos_i_on_map, BS);
|
||||||
v3f pos_f_on_newblock = pos_f_on_oldblock
|
v3f pos_f_on_newblock = pos_f_on_oldblock
|
||||||
- newblock_pos_f_on_map + oldblock_pos_f_on_map;
|
- newblock_pos_f_on_map + oldblock_pos_f_on_map;
|
||||||
|
|
||||||
|
@ -683,32 +683,6 @@ struct MapNode
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Returns integer position of the node in given
|
|
||||||
floating point position.
|
|
||||||
*/
|
|
||||||
inline v3s16 floatToInt(v3f p)
|
|
||||||
{
|
|
||||||
v3s16 p2(
|
|
||||||
(p.X + (p.X>0 ? BS/2 : -BS/2))/BS,
|
|
||||||
(p.Y + (p.Y>0 ? BS/2 : -BS/2))/BS,
|
|
||||||
(p.Z + (p.Z>0 ? BS/2 : -BS/2))/BS);
|
|
||||||
return p2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
The same thing backwards
|
|
||||||
*/
|
|
||||||
inline v3f intToFloat(v3s16 p)
|
|
||||||
{
|
|
||||||
v3f p2(
|
|
||||||
p.X * BS,
|
|
||||||
p.Y * BS,
|
|
||||||
p.Z * BS
|
|
||||||
);
|
|
||||||
return p2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -273,7 +273,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
|||||||
{
|
{
|
||||||
v3f position = getPosition();
|
v3f position = getPosition();
|
||||||
v3f oldpos = position;
|
v3f oldpos = position;
|
||||||
v3s16 oldpos_i = floatToInt(oldpos);
|
v3s16 oldpos_i = floatToInt(oldpos, BS);
|
||||||
|
|
||||||
/*std::cout<<"oldpos_i=("<<oldpos_i.X<<","<<oldpos_i.Y<<","
|
/*std::cout<<"oldpos_i=("<<oldpos_i.X<<","<<oldpos_i.Y<<","
|
||||||
<<oldpos_i.Z<<")"<<std::endl;*/
|
<<oldpos_i.Z<<")"<<std::endl;*/
|
||||||
@ -296,7 +296,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Player position in nodes
|
// Player position in nodes
|
||||||
v3s16 pos_i = floatToInt(position);
|
v3s16 pos_i = floatToInt(position, BS);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check if player is in water (the oscillating value)
|
Check if player is in water (the oscillating value)
|
||||||
@ -305,13 +305,13 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
|||||||
// If in water, the threshold of coming out is at higher y
|
// If in water, the threshold of coming out is at higher y
|
||||||
if(in_water)
|
if(in_water)
|
||||||
{
|
{
|
||||||
v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0));
|
v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0), BS);
|
||||||
in_water = content_liquid(map.getNode(pp).d);
|
in_water = content_liquid(map.getNode(pp).d);
|
||||||
}
|
}
|
||||||
// If not in water, the threshold of going in is at lower y
|
// If not in water, the threshold of going in is at lower y
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0));
|
v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0), BS);
|
||||||
in_water = content_liquid(map.getNode(pp).d);
|
in_water = content_liquid(map.getNode(pp).d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -324,7 +324,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
|||||||
Check if player is in water (the stable value)
|
Check if player is in water (the stable value)
|
||||||
*/
|
*/
|
||||||
try{
|
try{
|
||||||
v3s16 pp = floatToInt(position + v3f(0,0,0));
|
v3s16 pp = floatToInt(position + v3f(0,0,0), BS);
|
||||||
in_water_stable = content_liquid(map.getNode(pp).d);
|
in_water_stable = content_liquid(map.getNode(pp).d);
|
||||||
}
|
}
|
||||||
catch(InvalidPositionException &e)
|
catch(InvalidPositionException &e)
|
||||||
@ -363,7 +363,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
|||||||
if(control.sneak && m_sneak_node_exists)
|
if(control.sneak && m_sneak_node_exists)
|
||||||
{
|
{
|
||||||
f32 maxd = 0.5*BS + sneak_max;
|
f32 maxd = 0.5*BS + sneak_max;
|
||||||
v3f lwn_f = intToFloat(m_sneak_node);
|
v3f lwn_f = intToFloat(m_sneak_node, BS);
|
||||||
position.X = rangelim(position.X, lwn_f.X-maxd, lwn_f.X+maxd);
|
position.X = rangelim(position.X, lwn_f.X-maxd, lwn_f.X+maxd);
|
||||||
position.Z = rangelim(position.Z, lwn_f.Z-maxd, lwn_f.Z+maxd);
|
position.Z = rangelim(position.Z, lwn_f.Z-maxd, lwn_f.Z+maxd);
|
||||||
|
|
||||||
@ -537,13 +537,13 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
|||||||
player is sneaking from, if any.
|
player is sneaking from, if any.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
v3s16 pos_i_bottom = floatToInt(position - v3f(0,BS/2,0));
|
v3s16 pos_i_bottom = floatToInt(position - v3f(0,BS/2,0), BS);
|
||||||
v2f player_p2df(position.X, position.Z);
|
v2f player_p2df(position.X, position.Z);
|
||||||
f32 min_distance_f = 100000.0*BS;
|
f32 min_distance_f = 100000.0*BS;
|
||||||
// If already seeking from some node, compare to it.
|
// If already seeking from some node, compare to it.
|
||||||
/*if(m_sneak_node_exists)
|
/*if(m_sneak_node_exists)
|
||||||
{
|
{
|
||||||
v3f sneaknode_pf = intToFloat(m_sneak_node);
|
v3f sneaknode_pf = intToFloat(m_sneak_node, BS);
|
||||||
v2f sneaknode_p2df(sneaknode_pf.X, sneaknode_pf.Z);
|
v2f sneaknode_p2df(sneaknode_pf.X, sneaknode_pf.Z);
|
||||||
f32 d_horiz_f = player_p2df.getDistanceFrom(sneaknode_p2df);
|
f32 d_horiz_f = player_p2df.getDistanceFrom(sneaknode_p2df);
|
||||||
f32 d_vert_f = fabs(sneaknode_pf.Y + BS*0.5 - position.Y);
|
f32 d_vert_f = fabs(sneaknode_pf.Y + BS*0.5 - position.Y);
|
||||||
@ -556,7 +556,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
|||||||
for(s16 z=-1; z<=1; z++)
|
for(s16 z=-1; z<=1; z++)
|
||||||
{
|
{
|
||||||
v3s16 p = pos_i_bottom + v3s16(x,0,z);
|
v3s16 p = pos_i_bottom + v3s16(x,0,z);
|
||||||
v3f pf = intToFloat(p);
|
v3f pf = intToFloat(p, BS);
|
||||||
v2f node_p2df(pf.X, pf.Z);
|
v2f node_p2df(pf.X, pf.Z);
|
||||||
f32 distance_f = player_p2df.getDistanceFrom(node_p2df);
|
f32 distance_f = player_p2df.getDistanceFrom(node_p2df);
|
||||||
f32 max_axis_distance_f = MYMAX(
|
f32 max_axis_distance_f = MYMAX(
|
||||||
|
@ -132,6 +132,10 @@ protected:
|
|||||||
v3f m_position;
|
v3f m_position;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Player on the server
|
||||||
|
*/
|
||||||
|
|
||||||
class ServerRemotePlayer : public Player
|
class ServerRemotePlayer : public Player
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -156,6 +160,10 @@ private:
|
|||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
|
|
||||||
|
/*
|
||||||
|
All the other players on the client are these
|
||||||
|
*/
|
||||||
|
|
||||||
class RemotePlayer : public Player, public scene::ISceneNode
|
class RemotePlayer : public Player, public scene::ISceneNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
466
src/server.cpp
466
src/server.cpp
@ -283,21 +283,14 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
// Increment timers
|
// Increment timers
|
||||||
{
|
m_nearest_unsent_reset_timer += dtime;
|
||||||
JMutexAutoLock lock(m_blocks_sent_mutex);
|
|
||||||
m_nearest_unsent_reset_timer += dtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Won't send anything if already sending
|
// Won't send anything if already sending
|
||||||
|
if(m_blocks_sending.size() >= g_settings.getU16
|
||||||
|
("max_simultaneous_block_sends_per_client"))
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_blocks_sending_mutex);
|
//dstream<<"Not sending any blocks, Queue full."<<std::endl;
|
||||||
|
return;
|
||||||
if(m_blocks_sending.size() >= g_settings.getU16
|
|
||||||
("max_simultaneous_block_sends_per_client"))
|
|
||||||
{
|
|
||||||
//dstream<<"Not sending any blocks, Queue full."<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Player *player = server->m_env.getPlayer(peer_id);
|
Player *player = server->m_env.getPlayer(peer_id);
|
||||||
@ -307,7 +300,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
v3f playerpos = player->getPosition();
|
v3f playerpos = player->getPosition();
|
||||||
v3f playerspeed = player->getSpeed();
|
v3f playerspeed = player->getSpeed();
|
||||||
|
|
||||||
v3s16 center_nodepos = floatToInt(playerpos);
|
v3s16 center_nodepos = floatToInt(playerpos, BS);
|
||||||
|
|
||||||
v3s16 center = getNodeBlockPos(center_nodepos);
|
v3s16 center = getNodeBlockPos(center_nodepos);
|
||||||
|
|
||||||
@ -323,29 +316,26 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
*/
|
*/
|
||||||
s16 last_nearest_unsent_d;
|
s16 last_nearest_unsent_d;
|
||||||
s16 d_start;
|
s16 d_start;
|
||||||
|
|
||||||
|
if(m_last_center != center)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_blocks_sent_mutex);
|
m_nearest_unsent_d = 0;
|
||||||
|
m_last_center = center;
|
||||||
if(m_last_center != center)
|
|
||||||
{
|
|
||||||
m_nearest_unsent_d = 0;
|
|
||||||
m_last_center = center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*dstream<<"m_nearest_unsent_reset_timer="
|
|
||||||
<<m_nearest_unsent_reset_timer<<std::endl;*/
|
|
||||||
if(m_nearest_unsent_reset_timer > 5.0)
|
|
||||||
{
|
|
||||||
m_nearest_unsent_reset_timer = 0;
|
|
||||||
m_nearest_unsent_d = 0;
|
|
||||||
//dstream<<"Resetting m_nearest_unsent_d"<<std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
last_nearest_unsent_d = m_nearest_unsent_d;
|
|
||||||
|
|
||||||
d_start = m_nearest_unsent_d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*dstream<<"m_nearest_unsent_reset_timer="
|
||||||
|
<<m_nearest_unsent_reset_timer<<std::endl;*/
|
||||||
|
if(m_nearest_unsent_reset_timer > 5.0)
|
||||||
|
{
|
||||||
|
m_nearest_unsent_reset_timer = 0;
|
||||||
|
m_nearest_unsent_d = 0;
|
||||||
|
//dstream<<"Resetting m_nearest_unsent_d"<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_nearest_unsent_d = m_nearest_unsent_d;
|
||||||
|
|
||||||
|
d_start = m_nearest_unsent_d;
|
||||||
|
|
||||||
u16 maximum_simultaneous_block_sends_setting = g_settings.getU16
|
u16 maximum_simultaneous_block_sends_setting = g_settings.getU16
|
||||||
("max_simultaneous_block_sends_per_client");
|
("max_simultaneous_block_sends_per_client");
|
||||||
u16 maximum_simultaneous_block_sends =
|
u16 maximum_simultaneous_block_sends =
|
||||||
@ -356,24 +346,15 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
|
|
||||||
Decrease send rate if player is building stuff.
|
Decrease send rate if player is building stuff.
|
||||||
*/
|
*/
|
||||||
|
m_time_from_building += dtime;
|
||||||
|
if(m_time_from_building < g_settings.getFloat(
|
||||||
|
"full_block_send_enable_min_time_from_building"))
|
||||||
{
|
{
|
||||||
SharedPtr<JMutexAutoLock> lock(m_time_from_building.getLock());
|
maximum_simultaneous_block_sends
|
||||||
m_time_from_building.m_value += dtime;
|
= LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
|
||||||
/*if(m_time_from_building.m_value
|
|
||||||
< FULL_BLOCK_SEND_ENABLE_MIN_TIME_FROM_BUILDING)*/
|
|
||||||
if(m_time_from_building.m_value < g_settings.getFloat(
|
|
||||||
"full_block_send_enable_min_time_from_building"))
|
|
||||||
{
|
|
||||||
maximum_simultaneous_block_sends
|
|
||||||
= LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 num_blocks_selected;
|
u32 num_blocks_selected = m_blocks_sending.size();
|
||||||
{
|
|
||||||
JMutexAutoLock lock(m_blocks_sending_mutex);
|
|
||||||
num_blocks_selected = m_blocks_sending.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
next time d will be continued from the d from which the nearest
|
next time d will be continued from the d from which the nearest
|
||||||
@ -384,11 +365,6 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
*/
|
*/
|
||||||
s32 new_nearest_unsent_d = -1;
|
s32 new_nearest_unsent_d = -1;
|
||||||
|
|
||||||
// Serialization version used
|
|
||||||
//u8 ser_version = serialization_version;
|
|
||||||
|
|
||||||
//bool has_incomplete_blocks = false;
|
|
||||||
|
|
||||||
s16 d_max = g_settings.getS16("max_block_send_distance");
|
s16 d_max = g_settings.getS16("max_block_send_distance");
|
||||||
s16 d_max_gen = g_settings.getS16("max_block_generate_distance");
|
s16 d_max_gen = g_settings.getS16("max_block_generate_distance");
|
||||||
|
|
||||||
@ -398,20 +374,16 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
{
|
{
|
||||||
//dstream<<"RemoteClient::SendBlocks(): d="<<d<<std::endl;
|
//dstream<<"RemoteClient::SendBlocks(): d="<<d<<std::endl;
|
||||||
|
|
||||||
//if(has_incomplete_blocks == false)
|
/*
|
||||||
|
If m_nearest_unsent_d was changed by the EmergeThread
|
||||||
|
(it can change it to 0 through SetBlockNotSent),
|
||||||
|
update our d to it.
|
||||||
|
Else update m_nearest_unsent_d
|
||||||
|
*/
|
||||||
|
if(m_nearest_unsent_d != last_nearest_unsent_d)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_blocks_sent_mutex);
|
d = m_nearest_unsent_d;
|
||||||
/*
|
last_nearest_unsent_d = m_nearest_unsent_d;
|
||||||
If m_nearest_unsent_d was changed by the EmergeThread
|
|
||||||
(it can change it to 0 through SetBlockNotSent),
|
|
||||||
update our d to it.
|
|
||||||
Else update m_nearest_unsent_d
|
|
||||||
*/
|
|
||||||
if(m_nearest_unsent_d != last_nearest_unsent_d)
|
|
||||||
{
|
|
||||||
d = m_nearest_unsent_d;
|
|
||||||
last_nearest_unsent_d = m_nearest_unsent_d;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -443,23 +415,19 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
maximum_simultaneous_block_sends_setting;
|
maximum_simultaneous_block_sends_setting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Limit is dynamically lowered when building
|
||||||
|
if(num_blocks_selected
|
||||||
|
>= maximum_simultaneous_block_sends_now)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_blocks_sending_mutex);
|
/*dstream<<"Not sending more blocks. Queue full. "
|
||||||
|
<<m_blocks_sending.size()
|
||||||
// Limit is dynamically lowered when building
|
<<std::endl;*/
|
||||||
if(num_blocks_selected
|
goto queue_full;
|
||||||
>= maximum_simultaneous_block_sends_now)
|
|
||||||
{
|
|
||||||
/*dstream<<"Not sending more blocks. Queue full. "
|
|
||||||
<<m_blocks_sending.size()
|
|
||||||
<<std::endl;*/
|
|
||||||
goto queue_full;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_blocks_sending.find(p) != NULL)
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(m_blocks_sending.find(p) != NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Do not go over-limit
|
Do not go over-limit
|
||||||
*/
|
*/
|
||||||
@ -519,7 +487,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Don't draw if not in sight
|
Don't generate or send if not in sight
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(isBlockInSight(p, camera_pos, camera_dir, 10000*BS) == false)
|
if(isBlockInSight(p, camera_pos, camera_dir, 10000*BS) == false)
|
||||||
@ -531,8 +499,6 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
Don't send already sent blocks
|
Don't send already sent blocks
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_blocks_sent_mutex);
|
|
||||||
|
|
||||||
if(m_blocks_sent.find(p) != NULL)
|
if(m_blocks_sent.find(p) != NULL)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -546,12 +512,6 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
bool block_is_invalid = false;
|
bool block_is_invalid = false;
|
||||||
if(block != NULL)
|
if(block != NULL)
|
||||||
{
|
{
|
||||||
/*if(block->isIncomplete())
|
|
||||||
{
|
|
||||||
has_incomplete_blocks = true;
|
|
||||||
continue;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if(block->isDummy())
|
if(block->isDummy())
|
||||||
{
|
{
|
||||||
surely_not_found_on_disk = true;
|
surely_not_found_on_disk = true;
|
||||||
@ -567,11 +527,6 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
v2s16 chunkpos = map->sector_to_chunk(p2d);
|
v2s16 chunkpos = map->sector_to_chunk(p2d);
|
||||||
if(map->chunkNonVolatile(chunkpos) == false)
|
if(map->chunkNonVolatile(chunkpos) == false)
|
||||||
block_is_invalid = true;
|
block_is_invalid = true;
|
||||||
/*MapChunk *chunk = map->getChunk(chunkpos);
|
|
||||||
if(chunk == NULL)
|
|
||||||
block_is_invalid = true;
|
|
||||||
else if(chunk->getIsVolatile() == true)
|
|
||||||
block_is_invalid = true;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -598,11 +553,6 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
*/
|
*/
|
||||||
if(block == NULL || surely_not_found_on_disk || block_is_invalid)
|
if(block == NULL || surely_not_found_on_disk || block_is_invalid)
|
||||||
{
|
{
|
||||||
//dstream<<"asd"<<std::endl;
|
|
||||||
|
|
||||||
/*SharedPtr<JMutexAutoLock> lock
|
|
||||||
(m_num_blocks_in_emerge_queue.getLock());*/
|
|
||||||
|
|
||||||
//TODO: Get value from somewhere
|
//TODO: Get value from somewhere
|
||||||
// Allow only one block in emerge queue
|
// Allow only one block in emerge queue
|
||||||
if(server->m_emerge_queue.peerItemCount(peer_id) < 1)
|
if(server->m_emerge_queue.peerItemCount(peer_id) < 1)
|
||||||
@ -624,7 +574,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Add block to queue
|
Add block to send queue
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PrioritySortedBlockTransfer q((float)d, p, peer_id);
|
PrioritySortedBlockTransfer q((float)d, p, peer_id);
|
||||||
@ -638,7 +588,6 @@ queue_full:
|
|||||||
|
|
||||||
if(new_nearest_unsent_d != -1)
|
if(new_nearest_unsent_d != -1)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_blocks_sent_mutex);
|
|
||||||
m_nearest_unsent_d = new_nearest_unsent_d;
|
m_nearest_unsent_d = new_nearest_unsent_d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -743,7 +692,7 @@ void RemoteClient::SendObjectData(
|
|||||||
v3f playerpos = player->getPosition();
|
v3f playerpos = player->getPosition();
|
||||||
v3f playerspeed = player->getSpeed();
|
v3f playerspeed = player->getSpeed();
|
||||||
|
|
||||||
v3s16 center_nodepos = floatToInt(playerpos);
|
v3s16 center_nodepos = floatToInt(playerpos, BS);
|
||||||
v3s16 center = getNodeBlockPos(center_nodepos);
|
v3s16 center = getNodeBlockPos(center_nodepos);
|
||||||
|
|
||||||
s16 d_max = g_settings.getS16("active_object_range");
|
s16 d_max = g_settings.getS16("active_object_range");
|
||||||
@ -767,7 +716,6 @@ void RemoteClient::SendObjectData(
|
|||||||
Ignore blocks that haven't been sent to the client
|
Ignore blocks that haven't been sent to the client
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
JMutexAutoLock sentlock(m_blocks_sent_mutex);
|
|
||||||
if(m_blocks_sent.find(p) == NULL)
|
if(m_blocks_sent.find(p) == NULL)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -861,8 +809,6 @@ skip_subsequent:
|
|||||||
|
|
||||||
void RemoteClient::GotBlock(v3s16 p)
|
void RemoteClient::GotBlock(v3s16 p)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_blocks_sending_mutex);
|
|
||||||
JMutexAutoLock lock2(m_blocks_sent_mutex);
|
|
||||||
if(m_blocks_sending.find(p) != NULL)
|
if(m_blocks_sending.find(p) != NULL)
|
||||||
m_blocks_sending.remove(p);
|
m_blocks_sending.remove(p);
|
||||||
else
|
else
|
||||||
@ -876,13 +822,6 @@ void RemoteClient::GotBlock(v3s16 p)
|
|||||||
|
|
||||||
void RemoteClient::SentBlock(v3s16 p)
|
void RemoteClient::SentBlock(v3s16 p)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_blocks_sending_mutex);
|
|
||||||
/*if(m_blocks_sending.size() > 15)
|
|
||||||
{
|
|
||||||
dstream<<"RemoteClient::SentBlock(): "
|
|
||||||
<<"m_blocks_sending.size()="
|
|
||||||
<<m_blocks_sending.size()<<std::endl;
|
|
||||||
}*/
|
|
||||||
if(m_blocks_sending.find(p) == NULL)
|
if(m_blocks_sending.find(p) == NULL)
|
||||||
m_blocks_sending.insert(p, 0.0);
|
m_blocks_sending.insert(p, 0.0);
|
||||||
else
|
else
|
||||||
@ -892,9 +831,6 @@ void RemoteClient::SentBlock(v3s16 p)
|
|||||||
|
|
||||||
void RemoteClient::SetBlockNotSent(v3s16 p)
|
void RemoteClient::SetBlockNotSent(v3s16 p)
|
||||||
{
|
{
|
||||||
JMutexAutoLock sendinglock(m_blocks_sending_mutex);
|
|
||||||
JMutexAutoLock sentlock(m_blocks_sent_mutex);
|
|
||||||
|
|
||||||
m_nearest_unsent_d = 0;
|
m_nearest_unsent_d = 0;
|
||||||
|
|
||||||
if(m_blocks_sending.find(p) != NULL)
|
if(m_blocks_sending.find(p) != NULL)
|
||||||
@ -905,9 +841,6 @@ void RemoteClient::SetBlockNotSent(v3s16 p)
|
|||||||
|
|
||||||
void RemoteClient::SetBlocksNotSent(core::map<v3s16, MapBlock*> &blocks)
|
void RemoteClient::SetBlocksNotSent(core::map<v3s16, MapBlock*> &blocks)
|
||||||
{
|
{
|
||||||
JMutexAutoLock sendinglock(m_blocks_sending_mutex);
|
|
||||||
JMutexAutoLock sentlock(m_blocks_sent_mutex);
|
|
||||||
|
|
||||||
m_nearest_unsent_d = 0;
|
m_nearest_unsent_d = 0;
|
||||||
|
|
||||||
for(core::map<v3s16, MapBlock*>::Iterator
|
for(core::map<v3s16, MapBlock*>::Iterator
|
||||||
@ -964,7 +897,7 @@ u32 PIChecksum(core::list<PlayerInfo> &l)
|
|||||||
Server::Server(
|
Server::Server(
|
||||||
std::string mapsavedir
|
std::string mapsavedir
|
||||||
):
|
):
|
||||||
m_env(new ServerMap(mapsavedir), dout_server),
|
m_env(new ServerMap(mapsavedir)),
|
||||||
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
|
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
|
||||||
m_thread(this),
|
m_thread(this),
|
||||||
m_emergethread(this),
|
m_emergethread(this),
|
||||||
@ -1257,11 +1190,8 @@ void Server::AsyncRunStep()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Update digging
|
Check added and deleted active objects
|
||||||
|
|
||||||
NOTE: Some of this could be moved to RemoteClient
|
|
||||||
*/
|
*/
|
||||||
#if 0
|
|
||||||
{
|
{
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
JMutexAutoLock envlock(m_env_mutex);
|
||||||
JMutexAutoLock conlock(m_con_mutex);
|
JMutexAutoLock conlock(m_con_mutex);
|
||||||
@ -1272,100 +1202,209 @@ void Server::AsyncRunStep()
|
|||||||
{
|
{
|
||||||
RemoteClient *client = i.getNode()->getValue();
|
RemoteClient *client = i.getNode()->getValue();
|
||||||
Player *player = m_env.getPlayer(client->peer_id);
|
Player *player = m_env.getPlayer(client->peer_id);
|
||||||
|
v3s16 pos = floatToInt(player->getPosition(), BS);
|
||||||
|
s16 radius = 32;
|
||||||
|
|
||||||
JMutexAutoLock digmutex(client->m_dig_mutex);
|
core::map<u16, bool> removed_objects;
|
||||||
|
core::map<u16, bool> added_objects;
|
||||||
|
m_env.getRemovedActiveObjects(pos, radius,
|
||||||
|
client->m_known_objects, removed_objects);
|
||||||
|
m_env.getAddedActiveObjects(pos, radius,
|
||||||
|
client->m_known_objects, added_objects);
|
||||||
|
|
||||||
if(client->m_dig_tool_item == -1)
|
// Ignore if nothing happened
|
||||||
|
if(removed_objects.size() == 0 && added_objects.size() == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
client->m_dig_time_remaining -= dtime;
|
std::string data_buffer;
|
||||||
|
|
||||||
if(client->m_dig_time_remaining > 0)
|
char buf[4];
|
||||||
|
|
||||||
|
// Handle removed objects
|
||||||
|
writeU16((u8*)buf, removed_objects.size());
|
||||||
|
data_buffer.append(buf, 2);
|
||||||
|
for(core::map<u16, bool>::Iterator
|
||||||
|
i = removed_objects.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
{
|
{
|
||||||
client->m_time_from_building.set(0.0);
|
// Get object
|
||||||
continue;
|
u16 id = i.getNode()->getKey();
|
||||||
|
ServerActiveObject* obj = m_env.getActiveObject(id);
|
||||||
|
|
||||||
|
// Add to data buffer for sending
|
||||||
|
writeU16((u8*)buf, i.getNode()->getKey());
|
||||||
|
data_buffer.append(buf, 2);
|
||||||
|
|
||||||
|
// Remove from known objects
|
||||||
|
client->m_known_objects.remove(i.getNode()->getKey());
|
||||||
|
|
||||||
|
if(obj && obj->m_known_by_count > 0)
|
||||||
|
obj->m_known_by_count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
v3s16 p_under = client->m_dig_position;
|
// Handle added objects
|
||||||
|
writeU16((u8*)buf, added_objects.size());
|
||||||
// Mandatory parameter; actually used for nothing
|
data_buffer.append(buf, 2);
|
||||||
core::map<v3s16, MapBlock*> modified_blocks;
|
for(core::map<u16, bool>::Iterator
|
||||||
|
i = added_objects.getIterator();
|
||||||
u8 material;
|
i.atEnd()==false; i++)
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
// Get material at position
|
// Get object
|
||||||
material = m_env.getMap().getNode(p_under).d;
|
u16 id = i.getNode()->getKey();
|
||||||
// If it's not diggable, do nothing
|
ServerActiveObject* obj = m_env.getActiveObject(id);
|
||||||
if(content_diggable(material) == false)
|
|
||||||
{
|
// Get object type
|
||||||
derr_server<<"Server: Not finishing digging: Node not diggable"
|
u8 type = ACTIVEOBJECT_TYPE_INVALID;
|
||||||
<<std::endl;
|
if(obj == NULL)
|
||||||
client->m_dig_tool_item = -1;
|
dstream<<"WARNING: "<<__FUNCTION_NAME
|
||||||
break;
|
<<": NULL object"<<std::endl;
|
||||||
}
|
else
|
||||||
}
|
type = obj->getType();
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
// Add to data buffer for sending
|
||||||
derr_server<<"Server: Not finishing digging: Node not found"
|
writeU16((u8*)buf, id);
|
||||||
<<std::endl;
|
data_buffer.append(buf, 2);
|
||||||
client->m_dig_tool_item = -1;
|
writeU8((u8*)buf, type);
|
||||||
break;
|
data_buffer.append(buf, 1);
|
||||||
|
|
||||||
|
// Add to known objects
|
||||||
|
client->m_known_objects.insert(i.getNode()->getKey(), false);
|
||||||
|
|
||||||
|
if(obj)
|
||||||
|
obj->m_known_by_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create packet
|
// Send packet
|
||||||
u32 replysize = 8;
|
SharedBuffer<u8> reply(2 + data_buffer.size());
|
||||||
SharedBuffer<u8> reply(replysize);
|
writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD);
|
||||||
writeU16(&reply[0], TOCLIENT_REMOVENODE);
|
memcpy((char*)&reply[2], data_buffer.c_str(),
|
||||||
writeS16(&reply[2], p_under.X);
|
data_buffer.size());
|
||||||
writeS16(&reply[4], p_under.Y);
|
|
||||||
writeS16(&reply[6], p_under.Z);
|
|
||||||
// Send as reliable
|
// Send as reliable
|
||||||
m_con.SendToAll(0, reply, true);
|
m_con.Send(client->peer_id, 0, reply, true);
|
||||||
|
|
||||||
if(g_settings.getBool("creative_mode") == false)
|
dstream<<"INFO: Server: Sent object remove/add: "
|
||||||
{
|
<<removed_objects.size()<<" removed, "
|
||||||
// Add to inventory and send inventory
|
<<added_objects.size()<<" added, "
|
||||||
InventoryItem *item = new MaterialItem(material, 1);
|
<<"packet size is "<<reply.getSize()<<std::endl;
|
||||||
player->inventory.addItem("main", item);
|
|
||||||
SendInventory(player->peer_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Remove the node
|
|
||||||
(this takes some time so it is done after the quick stuff)
|
|
||||||
*/
|
|
||||||
m_env.getMap().removeNodeAndUpdate(p_under, modified_blocks);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Update water
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Update water pressure around modification
|
|
||||||
// This also adds it to m_flow_active_nodes if appropriate
|
|
||||||
|
|
||||||
MapVoxelManipulator v(&m_env.getMap());
|
|
||||||
v.m_disable_water_climb =
|
|
||||||
g_settings.getBool("disable_water_climb");
|
|
||||||
|
|
||||||
VoxelArea area(p_under-v3s16(1,1,1), p_under+v3s16(1,1,1));
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
v.updateAreaWaterPressure(area, m_flow_active_nodes);
|
|
||||||
}
|
|
||||||
catch(ProcessingLimitException &e)
|
|
||||||
{
|
|
||||||
dstream<<"Processing limit reached (1)"<<std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
v.blitBack(modified_blocks);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Send object positions
|
/*
|
||||||
|
Send object messages
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
JMutexAutoLock envlock(m_env_mutex);
|
||||||
|
JMutexAutoLock conlock(m_con_mutex);
|
||||||
|
|
||||||
|
// Key = object id
|
||||||
|
// Value = data sent by object
|
||||||
|
core::map<u16, core::list<ActiveObjectMessage>* > buffered_messages;
|
||||||
|
|
||||||
|
// Get active object messages from environment
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
ActiveObjectMessage aom = m_env.getActiveObjectMessage();
|
||||||
|
if(aom.id == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
core::list<ActiveObjectMessage>* message_list = NULL;
|
||||||
|
core::map<u16, core::list<ActiveObjectMessage>* >::Node *n;
|
||||||
|
n = buffered_messages.find(aom.id);
|
||||||
|
if(n == NULL)
|
||||||
|
{
|
||||||
|
message_list = new core::list<ActiveObjectMessage>;
|
||||||
|
buffered_messages.insert(aom.id, message_list);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
message_list = n->getValue();
|
||||||
|
}
|
||||||
|
message_list->push_back(aom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Route data to every client
|
||||||
|
for(core::map<u16, RemoteClient*>::Iterator
|
||||||
|
i = m_clients.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
|
{
|
||||||
|
RemoteClient *client = i.getNode()->getValue();
|
||||||
|
std::string reliable_data;
|
||||||
|
std::string unreliable_data;
|
||||||
|
// Go through all objects in message buffer
|
||||||
|
for(core::map<u16, core::list<ActiveObjectMessage>* >::Iterator
|
||||||
|
j = buffered_messages.getIterator();
|
||||||
|
j.atEnd()==false; j++)
|
||||||
|
{
|
||||||
|
// If object is not known by client, skip it
|
||||||
|
u16 id = j.getNode()->getKey();
|
||||||
|
if(client->m_known_objects.find(id) == NULL)
|
||||||
|
continue;
|
||||||
|
// Get message list of object
|
||||||
|
core::list<ActiveObjectMessage>* list = j.getNode()->getValue();
|
||||||
|
// Go through every message
|
||||||
|
for(core::list<ActiveObjectMessage>::Iterator
|
||||||
|
k = list->begin(); k != list->end(); k++)
|
||||||
|
{
|
||||||
|
// Compose the full new data with header
|
||||||
|
ActiveObjectMessage aom = *k;
|
||||||
|
std::string new_data;
|
||||||
|
// Add header (object id + length)
|
||||||
|
char header[4];
|
||||||
|
writeU16((u8*)&header[0], aom.id);
|
||||||
|
writeU16((u8*)&header[2], aom.datastring.size());
|
||||||
|
new_data.append(header, 4);
|
||||||
|
// Add data
|
||||||
|
new_data += aom.datastring;
|
||||||
|
// Add data to buffer
|
||||||
|
if(aom.reliable)
|
||||||
|
reliable_data += new_data;
|
||||||
|
else
|
||||||
|
unreliable_data += new_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
reliable_data and unreliable_data are now ready.
|
||||||
|
Send them.
|
||||||
|
*/
|
||||||
|
if(reliable_data.size() > 0)
|
||||||
|
{
|
||||||
|
SharedBuffer<u8> reply(2 + reliable_data.size());
|
||||||
|
writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_MESSAGES);
|
||||||
|
memcpy((char*)&reply[2], reliable_data.c_str(),
|
||||||
|
reliable_data.size());
|
||||||
|
// Send as reliable
|
||||||
|
m_con.Send(client->peer_id, 0, reply, true);
|
||||||
|
}
|
||||||
|
if(unreliable_data.size() > 0)
|
||||||
|
{
|
||||||
|
SharedBuffer<u8> reply(2 + unreliable_data.size());
|
||||||
|
writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_MESSAGES);
|
||||||
|
memcpy((char*)&reply[2], unreliable_data.c_str(),
|
||||||
|
unreliable_data.size());
|
||||||
|
// Send as unreliable
|
||||||
|
m_con.Send(client->peer_id, 0, reply, false);
|
||||||
|
}
|
||||||
|
if(reliable_data.size() > 0 || unreliable_data.size() > 0)
|
||||||
|
{
|
||||||
|
dstream<<"INFO: Server: Size of object message data: "
|
||||||
|
<<"reliable: "<<reliable_data.size()
|
||||||
|
<<", unreliable: "<<unreliable_data.size()
|
||||||
|
<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear buffered_messages
|
||||||
|
for(core::map<u16, core::list<ActiveObjectMessage>* >::Iterator
|
||||||
|
i = buffered_messages.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
|
{
|
||||||
|
delete i.getNode()->getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Send object positions
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
float &counter = m_objectdata_timer;
|
float &counter = m_objectdata_timer;
|
||||||
counter += dtime;
|
counter += dtime;
|
||||||
@ -1485,7 +1524,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//u8 peer_ser_ver = peer->serialization_version;
|
|
||||||
u8 peer_ser_ver = getClient(peer->id)->serialization_version;
|
u8 peer_ser_ver = getClient(peer->id)->serialization_version;
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -1595,7 +1633,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||||||
SharedBuffer<u8> reply(2+1+6);
|
SharedBuffer<u8> reply(2+1+6);
|
||||||
writeU16(&reply[0], TOCLIENT_INIT);
|
writeU16(&reply[0], TOCLIENT_INIT);
|
||||||
writeU8(&reply[2], deployed);
|
writeU8(&reply[2], deployed);
|
||||||
writeV3S16(&reply[3], floatToInt(player->getPosition()+v3f(0,BS/2,0)));
|
writeV3S16(&reply[3], floatToInt(player->getPosition()+v3f(0,BS/2,0), BS));
|
||||||
// Send as reliable
|
// Send as reliable
|
||||||
m_con.Send(peer_id, 0, reply, true);
|
m_con.Send(peer_id, 0, reply, true);
|
||||||
|
|
||||||
@ -1892,6 +1930,17 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||||||
{
|
{
|
||||||
derr_server<<"Server: Not finishing digging: Node not diggable"
|
derr_server<<"Server: Not finishing digging: Node not diggable"
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
|
|
||||||
|
// Client probably has wrong data.
|
||||||
|
// Set block not sent, so that client will get
|
||||||
|
// a valid one.
|
||||||
|
dstream<<"Client "<<peer_id<<" tried to dig "
|
||||||
|
<<"node from invalid position; setting"
|
||||||
|
<<" MapBlock not sent."<<std::endl;
|
||||||
|
RemoteClient *client = getClient(peer_id);
|
||||||
|
v3s16 blockpos = getNodeBlockPos(p_under);
|
||||||
|
client->SetBlockNotSent(blockpos);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Get mineral
|
// Get mineral
|
||||||
@ -2088,7 +2137,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reset build time counter
|
// Reset build time counter
|
||||||
getClient(peer->id)->m_time_from_building.set(0.0);
|
getClient(peer->id)->m_time_from_building = 0.0;
|
||||||
|
|
||||||
// Create node data
|
// Create node data
|
||||||
MaterialItem *mitem = (MaterialItem*)item;
|
MaterialItem *mitem = (MaterialItem*)item;
|
||||||
@ -2166,9 +2215,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
v3s16 block_pos_i_on_map = block->getPosRelative();
|
v3s16 block_pos_i_on_map = block->getPosRelative();
|
||||||
v3f block_pos_f_on_map = intToFloat(block_pos_i_on_map);
|
v3f block_pos_f_on_map = intToFloat(block_pos_i_on_map, BS);
|
||||||
|
|
||||||
v3f pos = intToFloat(p_over);
|
v3f pos = intToFloat(p_over, BS);
|
||||||
pos -= block_pos_f_on_map;
|
pos -= block_pos_f_on_map;
|
||||||
|
|
||||||
/*dout_server<<"pos="
|
/*dout_server<<"pos="
|
||||||
@ -3060,6 +3109,7 @@ void Server::SendBlocks(float dtime)
|
|||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
JMutexAutoLock envlock(m_env_mutex);
|
||||||
|
JMutexAutoLock conlock(m_con_mutex);
|
||||||
|
|
||||||
//TimeTaker timer("Server::SendBlocks");
|
//TimeTaker timer("Server::SendBlocks");
|
||||||
|
|
||||||
@ -3087,8 +3137,6 @@ void Server::SendBlocks(float dtime)
|
|||||||
// Lowest is most important.
|
// Lowest is most important.
|
||||||
queue.sort();
|
queue.sort();
|
||||||
|
|
||||||
JMutexAutoLock conlock(m_con_mutex);
|
|
||||||
|
|
||||||
for(u32 i=0; i<queue.size(); i++)
|
for(u32 i=0; i<queue.size(); i++)
|
||||||
{
|
{
|
||||||
//TODO: Calculate limit dynamically
|
//TODO: Calculate limit dynamically
|
||||||
@ -3268,7 +3316,7 @@ Player *Server::emergePlayer(const char *name, const char *password,
|
|||||||
0,
|
0,
|
||||||
45, //64,
|
45, //64,
|
||||||
0
|
0
|
||||||
)));
|
), BS));
|
||||||
#endif
|
#endif
|
||||||
#if 0
|
#if 0
|
||||||
f32 groundheight = 0;
|
f32 groundheight = 0;
|
||||||
|
43
src/server.h
43
src/server.h
@ -239,13 +239,6 @@ public:
|
|||||||
pending_serialization_version = SER_FMT_VER_INVALID;
|
pending_serialization_version = SER_FMT_VER_INVALID;
|
||||||
m_nearest_unsent_d = 0;
|
m_nearest_unsent_d = 0;
|
||||||
m_nearest_unsent_reset_timer = 0.0;
|
m_nearest_unsent_reset_timer = 0.0;
|
||||||
|
|
||||||
m_blocks_sent_mutex.Init();
|
|
||||||
m_blocks_sending_mutex.Init();
|
|
||||||
|
|
||||||
/*m_dig_mutex.Init();
|
|
||||||
m_dig_time_remaining = 0;
|
|
||||||
m_dig_tool_item = -1;*/
|
|
||||||
}
|
}
|
||||||
~RemoteClient()
|
~RemoteClient()
|
||||||
{
|
{
|
||||||
@ -279,7 +272,6 @@ public:
|
|||||||
|
|
||||||
s32 SendingCount()
|
s32 SendingCount()
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_blocks_sending_mutex);
|
|
||||||
return m_blocks_sending.size();
|
return m_blocks_sending.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,8 +282,6 @@ public:
|
|||||||
|
|
||||||
void PrintInfo(std::ostream &o)
|
void PrintInfo(std::ostream &o)
|
||||||
{
|
{
|
||||||
JMutexAutoLock l2(m_blocks_sent_mutex);
|
|
||||||
JMutexAutoLock l3(m_blocks_sending_mutex);
|
|
||||||
o<<"RemoteClient "<<peer_id<<": "
|
o<<"RemoteClient "<<peer_id<<": "
|
||||||
<<", m_blocks_sent.size()="<<m_blocks_sent.size()
|
<<", m_blocks_sent.size()="<<m_blocks_sent.size()
|
||||||
<<", m_blocks_sending.size()="<<m_blocks_sending.size()
|
<<", m_blocks_sending.size()="<<m_blocks_sending.size()
|
||||||
@ -302,7 +292,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Time from last placing or removing blocks
|
// Time from last placing or removing blocks
|
||||||
MutexedVariable<float> m_time_from_building;
|
float m_time_from_building;
|
||||||
|
|
||||||
/*JMutex m_dig_mutex;
|
/*JMutex m_dig_mutex;
|
||||||
float m_dig_time_remaining;
|
float m_dig_time_remaining;
|
||||||
@ -310,22 +300,13 @@ public:
|
|||||||
s16 m_dig_tool_item;
|
s16 m_dig_tool_item;
|
||||||
v3s16 m_dig_position;*/
|
v3s16 m_dig_position;*/
|
||||||
|
|
||||||
private:
|
|
||||||
/*
|
/*
|
||||||
All members that are accessed by many threads should
|
List of active objects that the client knows of.
|
||||||
obviously be behind a mutex. The threads include:
|
Value is dummy.
|
||||||
- main thread (calls step())
|
|
||||||
- server thread (calls AsyncRunStep() and Receive())
|
|
||||||
- emerge thread
|
|
||||||
*/
|
*/
|
||||||
|
core::map<u16, bool> m_known_objects;
|
||||||
|
|
||||||
//TODO: core::map<v3s16, MapBlock*> m_active_blocks
|
private:
|
||||||
//NOTE: Not here, it should be server-wide!
|
|
||||||
|
|
||||||
// Number of blocks in the emerge queue that have this client as
|
|
||||||
// a receiver. Used for throttling network usage.
|
|
||||||
//MutexedVariable<s16> m_num_blocks_in_emerge_queue;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Blocks that have been sent to client.
|
Blocks that have been sent to client.
|
||||||
- These don't have to be sent again.
|
- These don't have to be sent again.
|
||||||
@ -339,7 +320,7 @@ private:
|
|||||||
s16 m_nearest_unsent_d;
|
s16 m_nearest_unsent_d;
|
||||||
v3s16 m_last_center;
|
v3s16 m_last_center;
|
||||||
float m_nearest_unsent_reset_timer;
|
float m_nearest_unsent_reset_timer;
|
||||||
JMutex m_blocks_sent_mutex;
|
|
||||||
/*
|
/*
|
||||||
Blocks that are currently on the line.
|
Blocks that are currently on the line.
|
||||||
This is used for throttling the sending of blocks.
|
This is used for throttling the sending of blocks.
|
||||||
@ -349,7 +330,6 @@ private:
|
|||||||
Value is time from sending. (not used at the moment)
|
Value is time from sending. (not used at the moment)
|
||||||
*/
|
*/
|
||||||
core::map<v3s16, float> m_blocks_sending;
|
core::map<v3s16, float> m_blocks_sending;
|
||||||
JMutex m_blocks_sending_mutex;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Count of excess GotBlocks().
|
Count of excess GotBlocks().
|
||||||
@ -361,15 +341,6 @@ private:
|
|||||||
u32 m_excess_gotblocks;
|
u32 m_excess_gotblocks;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*struct ServerSettings
|
|
||||||
{
|
|
||||||
ServerSettings()
|
|
||||||
{
|
|
||||||
creative_mode = false;
|
|
||||||
}
|
|
||||||
bool creative_mode;
|
|
||||||
};*/
|
|
||||||
|
|
||||||
class Server : public con::PeerHandler
|
class Server : public con::PeerHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -470,7 +441,7 @@ private:
|
|||||||
// NOTE: If connection and environment are both to be locked,
|
// NOTE: If connection and environment are both to be locked,
|
||||||
// environment shall be locked first.
|
// environment shall be locked first.
|
||||||
JMutex m_env_mutex;
|
JMutex m_env_mutex;
|
||||||
Environment m_env;
|
ServerEnvironment m_env;
|
||||||
|
|
||||||
JMutex m_con_mutex;
|
JMutex m_con_mutex;
|
||||||
con::Connection m_con;
|
con::Connection m_con;
|
||||||
|
75
src/serverobject.cpp
Normal file
75
src/serverobject.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "serverobject.h"
|
||||||
|
|
||||||
|
ServerActiveObject::ServerActiveObject(u16 id, v3f pos):
|
||||||
|
ActiveObject(id),
|
||||||
|
m_known_by_count(0),
|
||||||
|
m_removed(false),
|
||||||
|
m_base_position(pos)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject::~ServerActiveObject()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TestSAO::TestSAO(u16 id, v3f pos):
|
||||||
|
ServerActiveObject(id, pos),
|
||||||
|
m_timer1(0),
|
||||||
|
m_age(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSAO::step(float dtime, Queue<ActiveObjectMessage> &messages)
|
||||||
|
{
|
||||||
|
m_age += dtime;
|
||||||
|
if(m_age > 10)
|
||||||
|
{
|
||||||
|
m_removed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_base_position.Y += dtime * BS * 2;
|
||||||
|
if(m_base_position.Y > 8*BS)
|
||||||
|
m_base_position.Y = 2*BS;
|
||||||
|
|
||||||
|
m_timer1 -= dtime;
|
||||||
|
if(m_timer1 < 0.0)
|
||||||
|
{
|
||||||
|
m_timer1 += 0.125;
|
||||||
|
//dstream<<"TestSAO: id="<<getId()<<" sending data"<<std::endl;
|
||||||
|
|
||||||
|
std::string data;
|
||||||
|
|
||||||
|
data += itos(0); // 0 = position
|
||||||
|
data += " ";
|
||||||
|
data += itos(m_base_position.X);
|
||||||
|
data += " ";
|
||||||
|
data += itos(m_base_position.Y);
|
||||||
|
data += " ";
|
||||||
|
data += itos(m_base_position.Z);
|
||||||
|
|
||||||
|
//ActiveObjectMessage aom(getId(), true, data);
|
||||||
|
ActiveObjectMessage aom(getId(), false, data);
|
||||||
|
messages.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
87
src/serverobject.h
Normal file
87
src/serverobject.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SERVEROBJECT_HEADER
|
||||||
|
#define SERVEROBJECT_HEADER
|
||||||
|
|
||||||
|
#include "common_irrlicht.h"
|
||||||
|
#include "activeobject.h"
|
||||||
|
#include "utility.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Some planning
|
||||||
|
-------------
|
||||||
|
|
||||||
|
* Server environment adds an active object, which gets the id 1
|
||||||
|
* The active object list is scanned for each client once in a while,
|
||||||
|
and it finds out what objects have been added that are not known
|
||||||
|
by the client yet. This scan is initiated by the server and the
|
||||||
|
result ends up directly to the server.
|
||||||
|
* A network packet is created with the info and sent to the client.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ServerActiveObject : public ActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ServerActiveObject(u16 id, v3f pos=v3f(0,0,0));
|
||||||
|
virtual ~ServerActiveObject();
|
||||||
|
|
||||||
|
v3f getBasePosition()
|
||||||
|
{
|
||||||
|
return m_base_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Step object in time.
|
||||||
|
Messages added to messages are sent to client over network.
|
||||||
|
*/
|
||||||
|
virtual void step(float dtime, Queue<ActiveObjectMessage> &messages){}
|
||||||
|
|
||||||
|
// Number of players which know about this one
|
||||||
|
u16 m_known_by_count;
|
||||||
|
/*
|
||||||
|
Whether this object is to be removed when nobody knows about
|
||||||
|
it anymore.
|
||||||
|
Removal is delayed to preserve the id for the time during which
|
||||||
|
it could be confused to some other object by some client.
|
||||||
|
*/
|
||||||
|
bool m_removed;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
v3f m_base_position;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TestSAO : public ServerActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TestSAO(u16 id, v3f pos);
|
||||||
|
u8 getType() const
|
||||||
|
{
|
||||||
|
return ACTIVEOBJECT_TYPE_TEST;
|
||||||
|
}
|
||||||
|
void step(float dtime, Queue<ActiveObjectMessage> &messages);
|
||||||
|
private:
|
||||||
|
float m_timer1;
|
||||||
|
float m_age;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1738,5 +1738,30 @@ inline std::string wrap_rows(const std::string &from, u32 rowlen)
|
|||||||
#define MYMIN(a,b) ((a)<(b)?(a):(b))
|
#define MYMIN(a,b) ((a)<(b)?(a):(b))
|
||||||
#define MYMAX(a,b) ((a)>(b)?(a):(b))
|
#define MYMAX(a,b) ((a)>(b)?(a):(b))
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns integer position of node in given floating point position
|
||||||
|
*/
|
||||||
|
inline v3s16 floatToInt(v3f p, f32 d)
|
||||||
|
{
|
||||||
|
v3s16 p2(
|
||||||
|
(p.X + (p.X>0 ? BS/2 : -BS/2))/d,
|
||||||
|
(p.Y + (p.Y>0 ? BS/2 : -BS/2))/d,
|
||||||
|
(p.Z + (p.Z>0 ? BS/2 : -BS/2))/d);
|
||||||
|
return p2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns floating point position of node in given integer position
|
||||||
|
*/
|
||||||
|
inline v3f intToFloat(v3s16 p, f32 d)
|
||||||
|
{
|
||||||
|
v3f p2(
|
||||||
|
(f32)p.X * d,
|
||||||
|
(f32)p.Y * d,
|
||||||
|
(f32)p.Z * d
|
||||||
|
);
|
||||||
|
return p2;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user