Some work-in-progress in hp and mobs and a frightening amount of random fixes.
After Width: | Height: | Size: 220 B |
After Width: | Height: | Size: 212 B |
BIN
data/stick.png
Before Width: | Height: | Size: 947 B After Width: | Height: | Size: 182 B |
Before Width: | Height: | Size: 990 B After Width: | Height: | Size: 252 B |
Before Width: | Height: | Size: 207 B After Width: | Height: | Size: 209 B |
Before Width: | Height: | Size: 272 B After Width: | Height: | Size: 271 B |
Before Width: | Height: | Size: 235 B After Width: | Height: | Size: 216 B |
Before Width: | Height: | Size: 196 B After Width: | Height: | Size: 193 B |
Before Width: | Height: | Size: 990 B After Width: | Height: | Size: 262 B |
Before Width: | Height: | Size: 206 B After Width: | Height: | Size: 203 B |
Before Width: | Height: | Size: 196 B After Width: | Height: | Size: 190 B |
Before Width: | Height: | Size: 989 B After Width: | Height: | Size: 245 B |
Before Width: | Height: | Size: 200 B After Width: | Height: | Size: 203 B |
|
@ -52,6 +52,8 @@
|
||||||
# Set to true to enable creative mode (unlimited inventory)
|
# Set to true to enable creative mode (unlimited inventory)
|
||||||
#creative_mode = false
|
#creative_mode = false
|
||||||
|
|
||||||
|
#enable_damage = false
|
||||||
|
|
||||||
# Player and object positions are sent at intervals specified by this
|
# Player and object positions are sent at intervals specified by this
|
||||||
#objectdata_inverval = 0.2
|
#objectdata_inverval = 0.2
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ struct ActiveObjectMessage
|
||||||
#define ACTIVEOBJECT_TYPE_TEST 1
|
#define ACTIVEOBJECT_TYPE_TEST 1
|
||||||
#define ACTIVEOBJECT_TYPE_ITEM 2
|
#define ACTIVEOBJECT_TYPE_ITEM 2
|
||||||
#define ACTIVEOBJECT_TYPE_RAT 3
|
#define ACTIVEOBJECT_TYPE_RAT 3
|
||||||
|
#define ACTIVEOBJECT_TYPE_OERKKI1 4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Parent class for ServerActiveObject and ClientActiveObject
|
Parent class for ServerActiveObject and ClientActiveObject
|
||||||
|
|
336
src/client.cpp
|
@ -90,6 +90,7 @@ Client::Client(
|
||||||
m_connection_reinit_timer = 0.0;
|
m_connection_reinit_timer = 0.0;
|
||||||
m_avg_rtt_timer = 0.0;
|
m_avg_rtt_timer = 0.0;
|
||||||
m_playerpos_send_timer = 0.0;
|
m_playerpos_send_timer = 0.0;
|
||||||
|
m_ignore_damage_timer = 0.0;
|
||||||
|
|
||||||
//m_env_mutex.Init();
|
//m_env_mutex.Init();
|
||||||
//m_con_mutex.Init();
|
//m_con_mutex.Init();
|
||||||
|
@ -154,6 +155,10 @@ void Client::step(float dtime)
|
||||||
if(dtime > 2.0)
|
if(dtime > 2.0)
|
||||||
dtime = 2.0;
|
dtime = 2.0;
|
||||||
|
|
||||||
|
if(m_ignore_damage_timer > dtime)
|
||||||
|
m_ignore_damage_timer -= dtime;
|
||||||
|
else
|
||||||
|
m_ignore_damage_timer = 0.0;
|
||||||
|
|
||||||
//dstream<<"Client steps "<<dtime<<std::endl;
|
//dstream<<"Client steps "<<dtime<<std::endl;
|
||||||
|
|
||||||
|
@ -311,6 +316,9 @@ void Client::step(float dtime)
|
||||||
Do stuff if connected
|
Do stuff if connected
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Handle environment
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
// 0ms
|
// 0ms
|
||||||
//JMutexAutoLock lock(m_env_mutex); //bulk comment-out
|
//JMutexAutoLock lock(m_env_mutex); //bulk comment-out
|
||||||
|
@ -341,8 +349,37 @@ void Client::step(float dtime)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get events
|
||||||
|
*/
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
ClientEnvEvent event = m_env.getClientEvent();
|
||||||
|
if(event.type == CEE_NONE)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(event.type == CEE_PLAYER_DAMAGE)
|
||||||
|
{
|
||||||
|
if(m_ignore_damage_timer <= 0)
|
||||||
|
{
|
||||||
|
u8 damage = event.player_damage.amount;
|
||||||
|
sendDamage(damage);
|
||||||
|
|
||||||
|
// Add to ClientEvent queue
|
||||||
|
ClientEvent event;
|
||||||
|
event.type = CE_PLAYER_DAMAGE;
|
||||||
|
event.player_damage.amount = damage;
|
||||||
|
m_client_event_queue.push_back(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Print some info
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
float &counter = m_avg_rtt_timer;
|
float &counter = m_avg_rtt_timer;
|
||||||
counter += dtime;
|
counter += dtime;
|
||||||
|
@ -355,6 +392,10 @@ void Client::step(float dtime)
|
||||||
dstream<<DTIME<<"Client: avg_rtt="<<peer->avg_rtt<<std::endl;
|
dstream<<DTIME<<"Client: avg_rtt="<<peer->avg_rtt<<std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Send player position to server
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
float &counter = m_playerpos_send_timer;
|
float &counter = m_playerpos_send_timer;
|
||||||
counter += dtime;
|
counter += dtime;
|
||||||
|
@ -388,6 +429,8 @@ void Client::step(float dtime)
|
||||||
}
|
}
|
||||||
if(r.ack_block_to_server)
|
if(r.ack_block_to_server)
|
||||||
{
|
{
|
||||||
|
/*dstream<<"Client: ACK block ("<<r.p.X<<","<<r.p.Y
|
||||||
|
<<","<<r.p.Z<<")"<<std::endl;*/
|
||||||
/*
|
/*
|
||||||
Acknowledge block
|
Acknowledge block
|
||||||
*/
|
*/
|
||||||
|
@ -447,7 +490,7 @@ void Client::ReceiveAll()
|
||||||
void Client::Receive()
|
void Client::Receive()
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
u32 data_maxsize = 10000;
|
u32 data_maxsize = 200000;
|
||||||
Buffer<u8> data(data_maxsize);
|
Buffer<u8> data(data_maxsize);
|
||||||
u16 sender_peer_id;
|
u16 sender_peer_id;
|
||||||
u32 datasize;
|
u32 datasize;
|
||||||
|
@ -1294,248 +1337,63 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if(command == TOCLIENT_HP)
|
||||||
{
|
{
|
||||||
dout_client<<DTIME<<"WARNING: Client: Ignoring unknown command "
|
std::string datastring((char*)&data[2], datasize-2);
|
||||||
<<command<<std::endl;
|
std::istringstream is(datastring, std::ios_base::binary);
|
||||||
|
Player *player = m_env.getLocalPlayer();
|
||||||
|
assert(player != NULL);
|
||||||
|
u8 hp = readU8(is);
|
||||||
|
player->hp = hp;
|
||||||
}
|
}
|
||||||
#if 0
|
else if(command == TOCLIENT_MOVE_PLAYER)
|
||||||
// Default to queueing it (for slow commands)
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_incoming_queue_mutex);
|
std::string datastring((char*)&data[2], datasize-2);
|
||||||
|
std::istringstream is(datastring, std::ios_base::binary);
|
||||||
IncomingPacket packet(data, datasize);
|
Player *player = m_env.getLocalPlayer();
|
||||||
m_incoming_queue.push_back(packet);
|
assert(player != NULL);
|
||||||
}
|
v3f pos = readV3F1000(is);
|
||||||
#endif
|
f32 pitch = readF1000(is);
|
||||||
}
|
f32 yaw = readF1000(is);
|
||||||
|
player->setPosition(pos);
|
||||||
|
/*player->setPitch(pitch);
|
||||||
|
player->setYaw(yaw);*/
|
||||||
|
|
||||||
#if 0
|
dstream<<"Client got TOCLIENT_MOVE_PLAYER"
|
||||||
/*
|
<<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
|
||||||
Returns true if there was something in queue
|
<<" pitch="<<pitch
|
||||||
*/
|
<<" yaw="<<yaw
|
||||||
bool Client::AsyncProcessPacket()
|
<<std::endl;
|
||||||
{
|
|
||||||
DSTACK(__FUNCTION_NAME);
|
|
||||||
|
|
||||||
try //for catching con::PeerNotFoundException
|
|
||||||
{
|
|
||||||
|
|
||||||
con::Peer *peer;
|
|
||||||
{
|
|
||||||
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
|
|
||||||
// All data is coming from the server
|
|
||||||
peer = m_con.GetPeer(PEER_ID_SERVER);
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 ser_version = m_server_ser_ver;
|
|
||||||
|
|
||||||
IncomingPacket packet = getPacket();
|
|
||||||
u8 *data = packet.m_data;
|
|
||||||
u32 datasize = packet.m_datalen;
|
|
||||||
|
|
||||||
// An empty packet means queue is empty
|
|
||||||
if(data == NULL){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(datasize < 2)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
ToClientCommand command = (ToClientCommand)readU16(&data[0]);
|
|
||||||
|
|
||||||
if(command == TOCLIENT_BLOCKDATA)
|
|
||||||
{
|
|
||||||
// Ignore too small packet
|
|
||||||
if(datasize < 8)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
v3s16 p;
|
|
||||||
p.X = readS16(&data[2]);
|
|
||||||
p.Y = readS16(&data[4]);
|
|
||||||
p.Z = readS16(&data[6]);
|
|
||||||
|
|
||||||
/*dout_client<<DTIME<<"Client: Thread: BLOCKDATA for ("
|
|
||||||
<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
|
|
||||||
/*dstream<<DTIME<<"Client: Thread: BLOCKDATA for ("
|
|
||||||
<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
|
|
||||||
|
|
||||||
std::string datastring((char*)&data[8], datasize-8);
|
|
||||||
std::istringstream istr(datastring, std::ios_base::binary);
|
|
||||||
|
|
||||||
MapSector *sector;
|
|
||||||
MapBlock *block;
|
|
||||||
|
|
||||||
{ //envlock
|
|
||||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
|
||||||
|
|
||||||
v2s16 p2d(p.X, p.Z);
|
|
||||||
sector = m_env.getMap().emergeSector(p2d);
|
|
||||||
|
|
||||||
v2s16 sp = sector->getPos();
|
|
||||||
if(sp != p2d)
|
|
||||||
{
|
|
||||||
dstream<<"ERROR: Got sector with getPos()="
|
|
||||||
<<"("<<sp.X<<","<<sp.Y<<"), tried to get"
|
|
||||||
<<"("<<p2d.X<<","<<p2d.Y<<")"<<std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(sp == p2d);
|
|
||||||
//assert(sector->getPos() == p2d);
|
|
||||||
|
|
||||||
//TimeTaker timer("MapBlock deSerialize");
|
|
||||||
// 0ms
|
|
||||||
|
|
||||||
try{
|
|
||||||
block = sector->getBlockNoCreate(p.Y);
|
|
||||||
/*
|
|
||||||
Update an existing block
|
|
||||||
*/
|
|
||||||
//dstream<<"Updating"<<std::endl;
|
|
||||||
block->deSerialize(istr, ser_version);
|
|
||||||
//block->setChangedFlag();
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Create a new block
|
|
||||||
*/
|
|
||||||
//dstream<<"Creating new"<<std::endl;
|
|
||||||
block = new MapBlock(&m_env.getMap(), p);
|
|
||||||
block->deSerialize(istr, ser_version);
|
|
||||||
sector->insertBlock(block);
|
|
||||||
//block->setChangedFlag();
|
|
||||||
|
|
||||||
//DEBUG
|
|
||||||
/*NodeMod mod;
|
|
||||||
mod.type = NODEMOD_CHANGECONTENT;
|
|
||||||
mod.param = CONTENT_MESE;
|
|
||||||
block->setTempMod(v3s16(8,10,8), mod);
|
|
||||||
block->setTempMod(v3s16(8,9,8), mod);
|
|
||||||
block->setTempMod(v3s16(8,8,8), mod);
|
|
||||||
block->setTempMod(v3s16(8,7,8), mod);
|
|
||||||
block->setTempMod(v3s16(8,6,8), mod);*/
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
Add some coulds
|
|
||||||
Well, this is a dumb way to do it, they should just
|
|
||||||
be drawn as separate objects. But the looks of them
|
|
||||||
can be tested this way.
|
|
||||||
*/
|
|
||||||
if(p.Y == 3)
|
|
||||||
{
|
|
||||||
NodeMod mod;
|
|
||||||
mod.type = NODEMOD_CHANGECONTENT;
|
|
||||||
mod.param = CONTENT_CLOUD;
|
|
||||||
v3s16 p2;
|
|
||||||
p2.Y = 8;
|
|
||||||
for(p2.X=3; p2.X<=13; p2.X++)
|
|
||||||
for(p2.Z=3; p2.Z<=13; p2.Z++)
|
|
||||||
{
|
|
||||||
block->setTempMod(p2, mod);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
} //envlock
|
|
||||||
|
|
||||||
/*
|
|
||||||
Acknowledge block.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
[0] u16 command
|
|
||||||
[2] u8 count
|
|
||||||
[3] v3s16 pos_0
|
|
||||||
[3+6] v3s16 pos_1
|
|
||||||
...
|
|
||||||
*/
|
|
||||||
u32 replysize = 2+1+6;
|
|
||||||
SharedBuffer<u8> reply(replysize);
|
|
||||||
writeU16(&reply[0], TOSERVER_GOTBLOCKS);
|
|
||||||
reply[2] = 1;
|
|
||||||
writeV3S16(&reply[3], p);
|
|
||||||
// Send as reliable
|
|
||||||
m_con.Send(PEER_ID_SERVER, 1, reply, true);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Update Mesh of this block and blocks at x-, y- and z-.
|
Add to ClientEvent queue.
|
||||||
Environment should not be locked as it interlocks with the
|
This has to be sent to the main program because otherwise
|
||||||
main thread, from which is will want to retrieve textures.
|
it would just force the pitch and yaw values to whatever
|
||||||
|
the camera points to.
|
||||||
*/
|
*/
|
||||||
|
ClientEvent event;
|
||||||
|
event.type = CE_PLAYER_FORCE_MOVE;
|
||||||
|
event.player_force_move.pitch = pitch;
|
||||||
|
event.player_force_move.yaw = yaw;
|
||||||
|
m_client_event_queue.push_back(event);
|
||||||
|
|
||||||
//m_env.getClientMap().updateMeshes(block->getPos(), getDayNightRatio());
|
// Ignore damage for a few seconds, so that the player doesn't
|
||||||
|
// get damage from falling on ground
|
||||||
MeshMakeData data;
|
m_ignore_damage_timer = 3.0;
|
||||||
{
|
|
||||||
//TimeTaker timer("data fill");
|
|
||||||
// 0ms
|
|
||||||
data.fill(getDayNightRatio(), block);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
TimeTaker timer("make mesh");
|
|
||||||
scene::SMesh *mesh_new = NULL;
|
|
||||||
mesh_new = makeMapBlockMesh(&data);
|
|
||||||
block->replaceMesh(mesh_new);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dout_client<<DTIME<<"WARNING: Client: Ignoring unknown command "
|
dout_client<<DTIME<<"WARNING: Client: Ignoring unknown command "
|
||||||
<<command<<std::endl;
|
<<command<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} //try
|
|
||||||
catch(con::PeerNotFoundException &e)
|
|
||||||
{
|
|
||||||
/*dout_client<<DTIME<<"Client::AsyncProcessData(): Cancelling: The server"
|
|
||||||
" connection doesn't exist (a timeout or not yet connected?)"<<std::endl;*/
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::AsyncProcessData()
|
|
||||||
{
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
bool r = AsyncProcessPacket();
|
|
||||||
if(r == false)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void Client::Send(u16 channelnum, SharedBuffer<u8> data, bool reliable)
|
void Client::Send(u16 channelnum, SharedBuffer<u8> data, bool reliable)
|
||||||
{
|
{
|
||||||
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
|
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out
|
||||||
m_con.Send(PEER_ID_SERVER, channelnum, data, reliable);
|
m_con.Send(PEER_ID_SERVER, channelnum, data, reliable);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
IncomingPacket Client::getPacket()
|
|
||||||
{
|
|
||||||
JMutexAutoLock lock(m_incoming_queue_mutex);
|
|
||||||
|
|
||||||
core::list<IncomingPacket>::Iterator i;
|
|
||||||
// Refer to first one
|
|
||||||
i = m_incoming_queue.begin();
|
|
||||||
|
|
||||||
// If queue is empty, return empty packet
|
|
||||||
if(i == m_incoming_queue.end()){
|
|
||||||
IncomingPacket packet;
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pop out first packet and return it
|
|
||||||
IncomingPacket packet = *i;
|
|
||||||
m_incoming_queue.erase(i);
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void Client::groundAction(u8 action, v3s16 nodepos_undersurface,
|
void Client::groundAction(u8 action, v3s16 nodepos_undersurface,
|
||||||
v3s16 nodepos_oversurface, u16 item)
|
v3s16 nodepos_oversurface, u16 item)
|
||||||
{
|
{
|
||||||
|
@ -1739,6 +1597,21 @@ void Client::sendChatMessage(const std::wstring &message)
|
||||||
Send(0, data, true);
|
Send(0, data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::sendDamage(u8 damage)
|
||||||
|
{
|
||||||
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
std::ostringstream os(std::ios_base::binary);
|
||||||
|
|
||||||
|
writeU16(os, TOSERVER_DAMAGE);
|
||||||
|
writeU8(os, damage);
|
||||||
|
|
||||||
|
// Make data buffer
|
||||||
|
std::string s = os.str();
|
||||||
|
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||||
|
// Send as reliable
|
||||||
|
Send(0, data, true);
|
||||||
|
}
|
||||||
|
|
||||||
void Client::sendPlayerPos()
|
void Client::sendPlayerPos()
|
||||||
{
|
{
|
||||||
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
|
||||||
|
@ -2061,6 +1934,13 @@ u32 Client::getDayNightRatio()
|
||||||
return m_env.getDayNightRatio();
|
return m_env.getDayNightRatio();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u16 Client::getHP()
|
||||||
|
{
|
||||||
|
Player *player = m_env.getLocalPlayer();
|
||||||
|
assert(player != NULL);
|
||||||
|
return player->hp;
|
||||||
|
}
|
||||||
|
|
||||||
void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server)
|
void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server)
|
||||||
{
|
{
|
||||||
/*dstream<<"Client::addUpdateMeshTask(): "
|
/*dstream<<"Client::addUpdateMeshTask(): "
|
||||||
|
@ -2141,3 +2021,15 @@ void Client::addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server)
|
||||||
catch(InvalidPositionException &e){}
|
catch(InvalidPositionException &e){}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClientEvent Client::getClientEvent()
|
||||||
|
{
|
||||||
|
if(m_client_event_queue.size() == 0)
|
||||||
|
{
|
||||||
|
ClientEvent event;
|
||||||
|
event.type = CE_NONE;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
return m_client_event_queue.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
79
src/client.h
|
@ -174,55 +174,28 @@ public:
|
||||||
MutexedQueue<MeshUpdateResult> m_queue_out;
|
MutexedQueue<MeshUpdateResult> m_queue_out;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0
|
enum ClientEventType
|
||||||
struct IncomingPacket
|
|
||||||
{
|
{
|
||||||
IncomingPacket()
|
CE_NONE,
|
||||||
{
|
CE_PLAYER_DAMAGE,
|
||||||
m_data = NULL;
|
CE_PLAYER_FORCE_MOVE
|
||||||
m_datalen = 0;
|
};
|
||||||
m_refcount = NULL;
|
|
||||||
}
|
struct ClientEvent
|
||||||
IncomingPacket(const IncomingPacket &a)
|
{
|
||||||
{
|
ClientEventType type;
|
||||||
m_data = a.m_data;
|
union{
|
||||||
m_datalen = a.m_datalen;
|
struct{
|
||||||
m_refcount = a.m_refcount;
|
} none;
|
||||||
if(m_refcount != NULL)
|
struct{
|
||||||
(*m_refcount)++;
|
u8 amount;
|
||||||
}
|
} player_damage;
|
||||||
IncomingPacket(u8 *data, u32 datalen)
|
struct{
|
||||||
{
|
f32 pitch;
|
||||||
m_data = new u8[datalen];
|
f32 yaw;
|
||||||
memcpy(m_data, data, datalen);
|
} player_force_move;
|
||||||
m_datalen = datalen;
|
};
|
||||||
m_refcount = new s32(1);
|
|
||||||
}
|
|
||||||
~IncomingPacket()
|
|
||||||
{
|
|
||||||
if(m_refcount != NULL){
|
|
||||||
assert(*m_refcount > 0);
|
|
||||||
(*m_refcount)--;
|
|
||||||
if(*m_refcount == 0){
|
|
||||||
if(m_data != NULL)
|
|
||||||
delete[] m_data;
|
|
||||||
delete m_refcount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*IncomingPacket & operator=(IncomingPacket a)
|
|
||||||
{
|
|
||||||
m_data = a.m_data;
|
|
||||||
m_datalen = a.m_datalen;
|
|
||||||
m_refcount = a.m_refcount;
|
|
||||||
(*m_refcount)++;
|
|
||||||
return *this;
|
|
||||||
}*/
|
|
||||||
u8 *m_data;
|
|
||||||
u32 m_datalen;
|
|
||||||
s32 *m_refcount;
|
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
class Client : public con::PeerHandler, public InventoryManager
|
class Client : public con::PeerHandler, public InventoryManager
|
||||||
{
|
{
|
||||||
|
@ -281,6 +254,7 @@ public:
|
||||||
void sendSignNodeText(v3s16 p, std::string text);
|
void sendSignNodeText(v3s16 p, std::string text);
|
||||||
void sendInventoryAction(InventoryAction *a);
|
void sendInventoryAction(InventoryAction *a);
|
||||||
void sendChatMessage(const std::wstring &message);
|
void sendChatMessage(const std::wstring &message);
|
||||||
|
void sendDamage(u8 damage);
|
||||||
|
|
||||||
// locks envlock
|
// locks envlock
|
||||||
void removeNode(v3s16 p);
|
void removeNode(v3s16 p);
|
||||||
|
@ -330,6 +304,8 @@ public:
|
||||||
|
|
||||||
u32 getDayNightRatio();
|
u32 getDayNightRatio();
|
||||||
|
|
||||||
|
u16 getHP();
|
||||||
|
|
||||||
//void updateSomeExpiredMeshes();
|
//void updateSomeExpiredMeshes();
|
||||||
|
|
||||||
void setTempMod(v3s16 p, NodeMod mod)
|
void setTempMod(v3s16 p, NodeMod mod)
|
||||||
|
@ -394,13 +370,13 @@ public:
|
||||||
|
|
||||||
u64 getMapSeed(){ return m_map_seed; }
|
u64 getMapSeed(){ return m_map_seed; }
|
||||||
|
|
||||||
/*
|
|
||||||
These are not thread-safe
|
|
||||||
*/
|
|
||||||
void addUpdateMeshTask(v3s16 blockpos, bool ack_to_server=false);
|
void addUpdateMeshTask(v3s16 blockpos, bool ack_to_server=false);
|
||||||
// Including blocks at appropriate edges
|
// Including blocks at appropriate edges
|
||||||
void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false);
|
void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false);
|
||||||
|
|
||||||
|
// Get event from queue. CE_NONE is returned if queue is empty.
|
||||||
|
ClientEvent getClientEvent();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Virtual methods from con::PeerHandler
|
// Virtual methods from con::PeerHandler
|
||||||
|
@ -419,6 +395,7 @@ private:
|
||||||
float m_connection_reinit_timer;
|
float m_connection_reinit_timer;
|
||||||
float m_avg_rtt_timer;
|
float m_avg_rtt_timer;
|
||||||
float m_playerpos_send_timer;
|
float m_playerpos_send_timer;
|
||||||
|
float m_ignore_damage_timer; // Used after server moves player
|
||||||
|
|
||||||
MeshUpdateThread m_mesh_update_thread;
|
MeshUpdateThread m_mesh_update_thread;
|
||||||
|
|
||||||
|
@ -454,6 +431,8 @@ private:
|
||||||
u64 m_map_seed;
|
u64 m_map_seed;
|
||||||
|
|
||||||
InventoryContext m_inventory_context;
|
InventoryContext m_inventory_context;
|
||||||
|
|
||||||
|
Queue<ClientEvent> m_client_event_queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !SERVER
|
#endif // !SERVER
|
||||||
|
|
|
@ -494,7 +494,7 @@ void RatCAO::updateLight(u8 light_at_pos)
|
||||||
|
|
||||||
v3s16 RatCAO::getLightPosition()
|
v3s16 RatCAO::getLightPosition()
|
||||||
{
|
{
|
||||||
return floatToInt(m_position, BS);
|
return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RatCAO::updateNodePos()
|
void RatCAO::updateNodePos()
|
||||||
|
@ -552,4 +552,181 @@ void RatCAO::initialize(const std::string &data)
|
||||||
updateNodePos();
|
updateNodePos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Oerkki1CAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "inventory.h"
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
Oerkki1CAO proto_Oerkki1CAO;
|
||||||
|
|
||||||
|
Oerkki1CAO::Oerkki1CAO():
|
||||||
|
ClientActiveObject(0),
|
||||||
|
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
|
||||||
|
m_node(NULL),
|
||||||
|
m_position(v3f(0,10*BS,0)),
|
||||||
|
m_yaw(0)
|
||||||
|
{
|
||||||
|
ClientActiveObject::registerType(getType(), create);
|
||||||
|
}
|
||||||
|
|
||||||
|
Oerkki1CAO::~Oerkki1CAO()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientActiveObject* Oerkki1CAO::create()
|
||||||
|
{
|
||||||
|
return new Oerkki1CAO();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1CAO::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,0,0, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(-BS/2,BS*2,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, NULL);
|
||||||
|
buf->getMaterial().setTexture
|
||||||
|
(0, driver->getTexture(porting::getDataPath("oerkki1.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();
|
||||||
|
// Set it to use the materials of the meshbuffers directly.
|
||||||
|
// This is needed for changing the texture in the future
|
||||||
|
m_node->setReadOnlyMaterials(true);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1CAO::removeFromScene()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node->remove();
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1CAO::updateLight(u8 light_at_pos)
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u8 li = decode_light(light_at_pos);
|
||||||
|
video::SColor color(255,li,li,li);
|
||||||
|
|
||||||
|
scene::IMesh *mesh = m_node->getMesh();
|
||||||
|
if(mesh == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u16 mc = mesh->getMeshBufferCount();
|
||||||
|
for(u16 j=0; j<mc; j++)
|
||||||
|
{
|
||||||
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||||
|
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
|
||||||
|
u16 vc = buf->getVertexCount();
|
||||||
|
for(u16 i=0; i<vc; i++)
|
||||||
|
{
|
||||||
|
vertices[i].Color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 Oerkki1CAO::getLightPosition()
|
||||||
|
{
|
||||||
|
return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1CAO::updateNodePos()
|
||||||
|
{
|
||||||
|
if(m_node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//m_node->setPosition(m_position);
|
||||||
|
m_node->setPosition(pos_translator.vect_show);
|
||||||
|
|
||||||
|
v3f rot = m_node->getRotation();
|
||||||
|
rot.Y = 180.0 - m_yaw + 90.0;
|
||||||
|
m_node->setRotation(rot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
|
||||||
|
{
|
||||||
|
pos_translator.translate(dtime);
|
||||||
|
updateNodePos();
|
||||||
|
|
||||||
|
LocalPlayer *player = env->getLocalPlayer();
|
||||||
|
assert(player);
|
||||||
|
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
v2f playerpos_2d(playerpos.X,playerpos.Z);
|
||||||
|
v2f objectpos_2d(m_position.X,m_position.Z);
|
||||||
|
|
||||||
|
if(fabs(objectpos_2d.Y - playerpos_2d.Y) < 2.0*BS &&
|
||||||
|
objectpos_2d.getDistanceFrom(playerpos_2d) < 1.0*BS)
|
||||||
|
{
|
||||||
|
if(m_attack_interval.step(dtime, 0.5))
|
||||||
|
{
|
||||||
|
env->damageLocalPlayer(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1CAO::processMessage(const std::string &data)
|
||||||
|
{
|
||||||
|
//dstream<<"Oerkki1CAO: Got message"<<std::endl;
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// command
|
||||||
|
u8 cmd = readU8(is);
|
||||||
|
if(cmd == 0)
|
||||||
|
{
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.update(m_position);
|
||||||
|
// yaw
|
||||||
|
m_yaw = readF1000(is);
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1CAO::initialize(const std::string &data)
|
||||||
|
{
|
||||||
|
//dstream<<"Oerkki1CAO: Got init data"<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// check version
|
||||||
|
if(version != 0)
|
||||||
|
return;
|
||||||
|
// pos
|
||||||
|
m_position = readV3F1000(is);
|
||||||
|
pos_translator.init(m_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNodePos();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
#include "activeobject.h"
|
#include "activeobject.h"
|
||||||
|
#include "utility.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
@ -267,5 +268,49 @@ private:
|
||||||
SmoothTranslator pos_translator;
|
SmoothTranslator pos_translator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Oerkki1CAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Oerkki1CAO : public ClientActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Oerkki1CAO();
|
||||||
|
virtual ~Oerkki1CAO();
|
||||||
|
|
||||||
|
u8 getType() const
|
||||||
|
{
|
||||||
|
return ACTIVEOBJECT_TYPE_OERKKI1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClientActiveObject* create();
|
||||||
|
|
||||||
|
void addToScene(scene::ISceneManager *smgr);
|
||||||
|
void removeFromScene();
|
||||||
|
void updateLight(u8 light_at_pos);
|
||||||
|
v3s16 getLightPosition();
|
||||||
|
void updateNodePos();
|
||||||
|
|
||||||
|
void step(float dtime, ClientEnvironment *env);
|
||||||
|
|
||||||
|
void processMessage(const std::string &data);
|
||||||
|
|
||||||
|
void initialize(const std::string &data);
|
||||||
|
|
||||||
|
core::aabbox3d<f32>* getSelectionBox()
|
||||||
|
{return &m_selection_box;}
|
||||||
|
v3f getPosition()
|
||||||
|
{return pos_translator.vect_show;}
|
||||||
|
//{return m_position;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
IntervalLimiter m_attack_interval;
|
||||||
|
core::aabbox3d<f32> m_selection_box;
|
||||||
|
scene::IMeshSceneNode *m_node;
|
||||||
|
v3f m_position;
|
||||||
|
float m_yaw;
|
||||||
|
SmoothTranslator pos_translator;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -33,15 +33,18 @@ enum ToClientCommand
|
||||||
|
|
||||||
[0] u16 TOSERVER_INIT
|
[0] u16 TOSERVER_INIT
|
||||||
[2] u8 deployed version
|
[2] u8 deployed version
|
||||||
[3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd
|
[3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd
|
||||||
[4] u64 map seed (new as of 2011-02-27)
|
([4] u64 map seed (new as of 2011-02-27))
|
||||||
|
|
||||||
|
NOTE: The position in here is deprecated; position is
|
||||||
|
explicitly sent afterwards
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TOCLIENT_BLOCKDATA = 0x20, //TODO: Multiple blocks
|
TOCLIENT_BLOCKDATA = 0x20, //TODO: Multiple blocks
|
||||||
TOCLIENT_ADDNODE = 0x21,
|
TOCLIENT_ADDNODE = 0x21,
|
||||||
TOCLIENT_REMOVENODE = 0x22,
|
TOCLIENT_REMOVENODE = 0x22,
|
||||||
|
|
||||||
TOCLIENT_PLAYERPOS = 0x23,
|
TOCLIENT_PLAYERPOS = 0x23, // Obsolete
|
||||||
/*
|
/*
|
||||||
[0] u16 command
|
[0] u16 command
|
||||||
// Followed by an arbitary number of these:
|
// Followed by an arbitary number of these:
|
||||||
|
@ -62,9 +65,9 @@ enum ToClientCommand
|
||||||
[N] char[20] name
|
[N] char[20] name
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TOCLIENT_OPT_BLOCK_NOT_FOUND = 0x25, // Not used
|
TOCLIENT_OPT_BLOCK_NOT_FOUND = 0x25, // Obsolete
|
||||||
|
|
||||||
TOCLIENT_SECTORMETA = 0x26, // Not used
|
TOCLIENT_SECTORMETA = 0x26, // Obsolete
|
||||||
/*
|
/*
|
||||||
[0] u16 command
|
[0] u16 command
|
||||||
[2] u8 sector count
|
[2] u8 sector count
|
||||||
|
@ -134,6 +137,19 @@ enum ToClientCommand
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
TOCLIENT_HP = 0x33,
|
||||||
|
/*
|
||||||
|
u16 command
|
||||||
|
u8 hp
|
||||||
|
*/
|
||||||
|
|
||||||
|
TOCLIENT_MOVE_PLAYER = 0x34,
|
||||||
|
/*
|
||||||
|
u16 command
|
||||||
|
v3f1000 player position
|
||||||
|
f1000 player pitch
|
||||||
|
f1000 player yaw
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ToServerCommand
|
enum ToServerCommand
|
||||||
|
@ -155,9 +171,9 @@ enum ToServerCommand
|
||||||
[0] u16 TOSERVER_INIT2
|
[0] u16 TOSERVER_INIT2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TOSERVER_GETBLOCK=0x20, // Not used
|
TOSERVER_GETBLOCK=0x20, // Obsolete
|
||||||
TOSERVER_ADDNODE = 0x21, // Not used
|
TOSERVER_ADDNODE = 0x21, // Obsolete
|
||||||
TOSERVER_REMOVENODE = 0x22, // deprecated
|
TOSERVER_REMOVENODE = 0x22, // Obsolete
|
||||||
|
|
||||||
TOSERVER_PLAYERPOS = 0x23,
|
TOSERVER_PLAYERPOS = 0x23,
|
||||||
/*
|
/*
|
||||||
|
@ -186,7 +202,7 @@ enum ToServerCommand
|
||||||
...
|
...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TOSERVER_ADDNODE_FROM_INVENTORY = 0x26, // deprecated
|
TOSERVER_ADDNODE_FROM_INVENTORY = 0x26, // Obsolete
|
||||||
/*
|
/*
|
||||||
[0] u16 command
|
[0] u16 command
|
||||||
[2] v3s16 pos
|
[2] v3s16 pos
|
||||||
|
@ -218,9 +234,9 @@ enum ToServerCommand
|
||||||
3: digging completed
|
3: digging completed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TOSERVER_RELEASE = 0x29, // Not used
|
TOSERVER_RELEASE = 0x29, // Obsolete
|
||||||
|
|
||||||
TOSERVER_SIGNTEXT = 0x30,
|
TOSERVER_SIGNTEXT = 0x30, // Old signs
|
||||||
/*
|
/*
|
||||||
u16 command
|
u16 command
|
||||||
v3s16 blockpos
|
v3s16 blockpos
|
||||||
|
@ -257,7 +273,12 @@ enum ToServerCommand
|
||||||
[3] u16 id
|
[3] u16 id
|
||||||
[5] u16 item
|
[5] u16 item
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
TOSERVER_DAMAGE = 0x35,
|
||||||
|
/*
|
||||||
|
u16 command
|
||||||
|
u8 amount
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
inline SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time)
|
inline SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time)
|
||||||
|
|
|
@ -70,6 +70,7 @@ collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Go through every node around the object
|
Go through every node around the object
|
||||||
|
TODO: Calculate the range of nodes that need to be checked
|
||||||
*/
|
*/
|
||||||
for(s16 y = oldpos_i.Y - 1; y <= oldpos_i.Y + 2; y++)
|
for(s16 y = oldpos_i.Y - 1; y <= oldpos_i.Y + 2; y++)
|
||||||
for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
|
for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
|
||||||
|
|
|
@ -38,6 +38,16 @@ collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
|
||||||
f32 dtime, v3f &pos_f, v3f &speed_f);
|
f32 dtime, v3f &pos_f, v3f &speed_f);
|
||||||
//{return collisionMoveResult();}
|
//{return collisionMoveResult();}
|
||||||
|
|
||||||
|
enum CollisionType
|
||||||
|
{
|
||||||
|
COLLISION_FALL
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CollisionInfo
|
||||||
|
{
|
||||||
|
CollisionType t;
|
||||||
|
f32 speed;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ void set_default_settings()
|
||||||
|
|
||||||
g_settings.setDefault("enable_experimental", "false");
|
g_settings.setDefault("enable_experimental", "false");
|
||||||
g_settings.setDefault("creative_mode", "false");
|
g_settings.setDefault("creative_mode", "false");
|
||||||
|
g_settings.setDefault("enable_damage", "false"); //TODO: Set to true
|
||||||
|
|
||||||
g_settings.setDefault("objectdata_interval", "0.2");
|
g_settings.setDefault("objectdata_interval", "0.2");
|
||||||
g_settings.setDefault("active_object_range", "2");
|
g_settings.setDefault("active_object_range", "2");
|
||||||
|
|
|
@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
|
#include "collision.h"
|
||||||
|
|
||||||
Environment::Environment()
|
Environment::Environment()
|
||||||
{
|
{
|
||||||
|
@ -377,6 +378,55 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void spawnRandomObjects(MapBlock *block)
|
||||||
|
{
|
||||||
|
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
|
||||||
|
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
|
||||||
|
{
|
||||||
|
bool last_node_walkable = false;
|
||||||
|
for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
|
||||||
|
{
|
||||||
|
v3s16 p(x0,y0,z0);
|
||||||
|
MapNode n = block->getNodeNoEx(p);
|
||||||
|
if(n.d == CONTENT_IGNORE)
|
||||||
|
continue;
|
||||||
|
if(content_features(n.d).liquid_type != LIQUID_NONE)
|
||||||
|
continue;
|
||||||
|
if(content_features(n.d).walkable)
|
||||||
|
{
|
||||||
|
last_node_walkable = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(last_node_walkable)
|
||||||
|
{
|
||||||
|
// If block contains light information
|
||||||
|
if(content_features(n.d).param_type == CPT_LIGHT)
|
||||||
|
{
|
||||||
|
if(n.getLight(LIGHTBANK_DAY) <= 5)
|
||||||
|
{
|
||||||
|
if(myrand() % 1000 == 0)
|
||||||
|
{
|
||||||
|
v3f pos_f = intToFloat(p+block->getPosRelative(), BS);
|
||||||
|
pos_f.Y -= BS*0.4;
|
||||||
|
ServerActiveObject *obj = new Oerkki1SAO(NULL,0,pos_f);
|
||||||
|
std::string data = obj->getStaticData();
|
||||||
|
StaticObject s_obj(obj->getType(),
|
||||||
|
obj->getBasePosition(), data);
|
||||||
|
// Add one
|
||||||
|
block->m_static_objects.insert(0, s_obj);
|
||||||
|
delete obj;
|
||||||
|
block->setChangedFlag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last_node_walkable = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void ServerEnvironment::step(float dtime)
|
void ServerEnvironment::step(float dtime)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
@ -429,26 +479,29 @@ void ServerEnvironment::step(float dtime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Step active objects
|
Step active objects
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool send_recommended = false;
|
|
||||||
m_send_recommended_timer += dtime;
|
|
||||||
if(m_send_recommended_timer > 0.15)
|
|
||||||
{
|
{
|
||||||
m_send_recommended_timer = 0;
|
//TimeTaker timer("Step active objects");
|
||||||
send_recommended = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(core::map<u16, ServerActiveObject*>::Iterator
|
bool send_recommended = false;
|
||||||
i = m_active_objects.getIterator();
|
m_send_recommended_timer += dtime;
|
||||||
i.atEnd()==false; i++)
|
if(m_send_recommended_timer > 0.15)
|
||||||
{
|
{
|
||||||
ServerActiveObject* obj = i.getNode()->getValue();
|
m_send_recommended_timer = 0;
|
||||||
// Step object, putting messages directly to the queue
|
send_recommended = true;
|
||||||
obj->step(dtime, m_active_object_messages, send_recommended);
|
}
|
||||||
|
|
||||||
|
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, send_recommended);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_object_management_interval.step(dtime, 0.5))
|
if(m_object_management_interval.step(dtime, 0.5))
|
||||||
|
@ -506,7 +559,7 @@ void ServerEnvironment::step(float dtime)
|
||||||
|
|
||||||
|
|
||||||
const s16 to_active_max_blocks = 3;
|
const s16 to_active_max_blocks = 3;
|
||||||
const f32 to_static_max_f = (to_active_max_blocks+1)*MAP_BLOCKSIZE*BS;
|
const f32 to_static_max_f = (to_active_max_blocks+2)*MAP_BLOCKSIZE*BS;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Convert stored objects from blocks near the players to active.
|
Convert stored objects from blocks near the players to active.
|
||||||
|
@ -719,7 +772,8 @@ void ServerEnvironment::step(float dtime)
|
||||||
|
|
||||||
//TestSAO *obj = new TestSAO(this, 0, pos);
|
//TestSAO *obj = new TestSAO(this, 0, pos);
|
||||||
//ServerActiveObject *obj = new ItemSAO(this, 0, pos, "CraftItem Stick 1");
|
//ServerActiveObject *obj = new ItemSAO(this, 0, pos, "CraftItem Stick 1");
|
||||||
ServerActiveObject *obj = new RatSAO(this, 0, pos);
|
//ServerActiveObject *obj = new RatSAO(this, 0, pos);
|
||||||
|
ServerActiveObject *obj = new Oerkki1SAO(this, 0, pos);
|
||||||
addActiveObject(obj);
|
addActiveObject(obj);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -976,14 +1030,18 @@ void ClientEnvironment::step(float dtime)
|
||||||
//TimeTaker timer("Client m_map->timerUpdate()", g_device);
|
//TimeTaker timer("Client m_map->timerUpdate()", g_device);
|
||||||
m_map->timerUpdate(dtime);
|
m_map->timerUpdate(dtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get local player
|
||||||
|
LocalPlayer *lplayer = getLocalPlayer();
|
||||||
|
assert(lplayer);
|
||||||
|
// collision info queue
|
||||||
|
core::list<CollisionInfo> player_collisions;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get the speed the player is going
|
Get the speed the player is going
|
||||||
*/
|
*/
|
||||||
f32 player_speed = 0.001; // just some small value
|
f32 player_speed = 0.001; // just some small value
|
||||||
LocalPlayer *lplayer = getLocalPlayer();
|
player_speed = lplayer->getSpeed().getLength();
|
||||||
if(lplayer)
|
|
||||||
player_speed = lplayer->getSpeed().getLength();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Maximum position increment
|
Maximum position increment
|
||||||
|
@ -1036,20 +1094,18 @@ void ClientEnvironment::step(float dtime)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
{
|
{
|
||||||
Player *player = getLocalPlayer();
|
v3f lplayerpos = lplayer->getPosition();
|
||||||
|
|
||||||
v3f playerpos = player->getPosition();
|
|
||||||
|
|
||||||
// Apply physics
|
// Apply physics
|
||||||
if(free_move == false)
|
if(free_move == false)
|
||||||
{
|
{
|
||||||
// Gravity
|
// Gravity
|
||||||
v3f speed = player->getSpeed();
|
v3f speed = lplayer->getSpeed();
|
||||||
if(player->swimming_up == false)
|
if(lplayer->swimming_up == false)
|
||||||
speed.Y -= 9.81 * BS * dtime_part * 2;
|
speed.Y -= 9.81 * BS * dtime_part * 2;
|
||||||
|
|
||||||
// Water resistance
|
// Water resistance
|
||||||
if(player->in_water_stable || player->in_water)
|
if(lplayer->in_water_stable || lplayer->in_water)
|
||||||
{
|
{
|
||||||
f32 max_down = 2.0*BS;
|
f32 max_down = 2.0*BS;
|
||||||
if(speed.Y < -max_down) speed.Y = -max_down;
|
if(speed.Y < -max_down) speed.Y = -max_down;
|
||||||
|
@ -1061,19 +1117,47 @@ void ClientEnvironment::step(float dtime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
player->setSpeed(speed);
|
lplayer->setSpeed(speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Move the player.
|
Move the lplayer.
|
||||||
This also does collision detection.
|
This also does collision detection.
|
||||||
*/
|
*/
|
||||||
player->move(dtime_part, *m_map, position_max_increment);
|
lplayer->move(dtime_part, *m_map, position_max_increment,
|
||||||
|
&player_collisions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(dtime_downcount > 0.001);
|
while(dtime_downcount > 0.001);
|
||||||
|
|
||||||
//std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
|
//std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
|
||||||
|
|
||||||
|
for(core::list<CollisionInfo>::Iterator
|
||||||
|
i = player_collisions.begin();
|
||||||
|
i != player_collisions.end(); i++)
|
||||||
|
{
|
||||||
|
CollisionInfo &info = *i;
|
||||||
|
if(info.t == COLLISION_FALL)
|
||||||
|
{
|
||||||
|
//f32 tolerance = BS*10; // 2 without damage
|
||||||
|
f32 tolerance = BS*12; // 3 without damage
|
||||||
|
f32 factor = 1;
|
||||||
|
if(info.speed > tolerance)
|
||||||
|
{
|
||||||
|
f32 damage_f = (info.speed - tolerance)/BS*factor;
|
||||||
|
u16 damage = (u16)(damage_f+0.5);
|
||||||
|
if(lplayer->hp > damage)
|
||||||
|
lplayer->hp -= damage;
|
||||||
|
else
|
||||||
|
lplayer->hp = 0;
|
||||||
|
|
||||||
|
ClientEnvEvent event;
|
||||||
|
event.type = CEE_PLAYER_DAMAGE;
|
||||||
|
event.player_damage.amount = damage;
|
||||||
|
m_client_event_queue.push_back(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Stuff that can be done in an arbitarily large dtime
|
Stuff that can be done in an arbitarily large dtime
|
||||||
|
@ -1287,6 +1371,30 @@ void ClientEnvironment::processActiveObjectMessage(u16 id,
|
||||||
obj->processMessage(data);
|
obj->processMessage(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Callbacks for activeobjects
|
||||||
|
*/
|
||||||
|
|
||||||
|
void ClientEnvironment::damageLocalPlayer(u8 damage)
|
||||||
|
{
|
||||||
|
LocalPlayer *lplayer = getLocalPlayer();
|
||||||
|
assert(lplayer);
|
||||||
|
|
||||||
|
if(lplayer->hp > damage)
|
||||||
|
lplayer->hp -= damage;
|
||||||
|
else
|
||||||
|
lplayer->hp = 0;
|
||||||
|
|
||||||
|
ClientEnvEvent event;
|
||||||
|
event.type = CEE_PLAYER_DAMAGE;
|
||||||
|
event.player_damage.amount = damage;
|
||||||
|
m_client_event_queue.push_back(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Client likes to call these
|
||||||
|
*/
|
||||||
|
|
||||||
void ClientEnvironment::getActiveObjects(v3f origin, f32 max_d,
|
void ClientEnvironment::getActiveObjects(v3f origin, f32 max_d,
|
||||||
core::array<DistanceSortedActiveObject> &dest)
|
core::array<DistanceSortedActiveObject> &dest)
|
||||||
{
|
{
|
||||||
|
@ -1307,6 +1415,16 @@ void ClientEnvironment::getActiveObjects(v3f origin, f32 max_d,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClientEnvEvent ClientEnvironment::getClientEvent()
|
||||||
|
{
|
||||||
|
if(m_client_event_queue.size() == 0)
|
||||||
|
{
|
||||||
|
ClientEnvEvent event;
|
||||||
|
event.type = CEE_NONE;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
return m_client_event_queue.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
#endif // #ifndef SERVER
|
#endif // #ifndef SERVER
|
||||||
|
|
||||||
|
|
|
@ -170,6 +170,24 @@ private:
|
||||||
Client uses an environment mutex.
|
Client uses an environment mutex.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
enum ClientEnvEventType
|
||||||
|
{
|
||||||
|
CEE_NONE,
|
||||||
|
CEE_PLAYER_DAMAGE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ClientEnvEvent
|
||||||
|
{
|
||||||
|
ClientEnvEventType type;
|
||||||
|
union {
|
||||||
|
struct{
|
||||||
|
} none;
|
||||||
|
struct{
|
||||||
|
u8 amount;
|
||||||
|
} player_damage;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
class ClientEnvironment : public Environment
|
class ClientEnvironment : public Environment
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -214,15 +232,29 @@ public:
|
||||||
void removeActiveObject(u16 id);
|
void removeActiveObject(u16 id);
|
||||||
|
|
||||||
void processActiveObjectMessage(u16 id, const std::string &data);
|
void processActiveObjectMessage(u16 id, const std::string &data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Callbacks for activeobjects
|
||||||
|
*/
|
||||||
|
|
||||||
|
void damageLocalPlayer(u8 damage);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Client likes to call these
|
||||||
|
*/
|
||||||
|
|
||||||
// Get all nearby objects
|
// Get all nearby objects
|
||||||
void getActiveObjects(v3f origin, f32 max_d,
|
void getActiveObjects(v3f origin, f32 max_d,
|
||||||
core::array<DistanceSortedActiveObject> &dest);
|
core::array<DistanceSortedActiveObject> &dest);
|
||||||
|
|
||||||
|
// Get event from queue. CEE_NONE is returned if queue is empty.
|
||||||
|
ClientEnvEvent getClientEvent();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ClientMap *m_map;
|
ClientMap *m_map;
|
||||||
scene::ISceneManager *m_smgr;
|
scene::ISceneManager *m_smgr;
|
||||||
core::map<u16, ClientActiveObject*> m_active_objects;
|
core::map<u16, ClientActiveObject*> m_active_objects;
|
||||||
|
Queue<ClientEnvEvent> m_client_event_queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -369,6 +369,12 @@ public:
|
||||||
basename = "tool_stoneaxe.png";
|
basename = "tool_stoneaxe.png";
|
||||||
else if(m_toolname == "SteelAxe")
|
else if(m_toolname == "SteelAxe")
|
||||||
basename = "tool_steelaxe.png";
|
basename = "tool_steelaxe.png";
|
||||||
|
else if(m_toolname == "WSword")
|
||||||
|
basename = "tool_woodsword.png";
|
||||||
|
else if(m_toolname == "STSword")
|
||||||
|
basename = "tool_stonesword.png";
|
||||||
|
else if(m_toolname == "SteelSword")
|
||||||
|
basename = "tool_steelsword.png";
|
||||||
else
|
else
|
||||||
basename = "cloud.png";
|
basename = "cloud.png";
|
||||||
|
|
||||||
|
|
551
src/main.cpp
|
@ -93,6 +93,10 @@ SUGG: Meshes of blocks could be split into 6 meshes facing into
|
||||||
SUGG: Calculate lighting per vertex to get a lighting effect like in
|
SUGG: Calculate lighting per vertex to get a lighting effect like in
|
||||||
bartwe's game
|
bartwe's game
|
||||||
|
|
||||||
|
SUGG: Background music based on cellular automata?
|
||||||
|
http://www.earslap.com/projectslab/otomata
|
||||||
|
|
||||||
|
|
||||||
Gaming ideas:
|
Gaming ideas:
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
@ -126,6 +130,12 @@ Game content:
|
||||||
- You can drop on top of it, and have some time to attack there
|
- You can drop on top of it, and have some time to attack there
|
||||||
before he shakes you off
|
before he shakes you off
|
||||||
|
|
||||||
|
- Maybe the difficulty could come from monsters getting tougher in
|
||||||
|
far-away places, and the player starting to need something from
|
||||||
|
there when time goes by.
|
||||||
|
- The player would have some of that stuff at the beginning, and
|
||||||
|
would need new supplies of it when it runs out
|
||||||
|
|
||||||
Documentation:
|
Documentation:
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
@ -1210,7 +1220,7 @@ void updateViewingRange(f32 frametime_in, Client *client)
|
||||||
|
|
||||||
void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
|
void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
|
||||||
v2s32 centerlowerpos, s32 imgsize, s32 itemcount,
|
v2s32 centerlowerpos, s32 imgsize, s32 itemcount,
|
||||||
Inventory *inventory)
|
Inventory *inventory, s32 halfheartcount)
|
||||||
{
|
{
|
||||||
InventoryList *mainlist = inventory->getList("main");
|
InventoryList *mainlist = inventory->getList("main");
|
||||||
if(mainlist == NULL)
|
if(mainlist == NULL)
|
||||||
|
@ -1259,6 +1269,40 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
|
||||||
drawInventoryItem(driver, font, item, rect, NULL);
|
drawInventoryItem(driver, font, item, rect, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Draw hearts
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
video::ITexture *heart_texture =
|
||||||
|
driver->getTexture(porting::getDataPath("heart.png").c_str());
|
||||||
|
v2s32 p = pos + v2s32(0, -20);
|
||||||
|
for(s32 i=0; i<halfheartcount/2; i++)
|
||||||
|
{
|
||||||
|
const video::SColor color(255,255,255,255);
|
||||||
|
const video::SColor colors[] = {color,color,color,color};
|
||||||
|
core::rect<s32> rect(0,0,16,16);
|
||||||
|
rect += p;
|
||||||
|
driver->draw2DImage(heart_texture, rect,
|
||||||
|
core::rect<s32>(core::position2d<s32>(0,0),
|
||||||
|
core::dimension2di(heart_texture->getOriginalSize())),
|
||||||
|
NULL, colors, true);
|
||||||
|
p += v2s32(20,0);
|
||||||
|
}
|
||||||
|
if(halfheartcount % 2 == 1)
|
||||||
|
{
|
||||||
|
const video::SColor color(255,255,255,255);
|
||||||
|
const video::SColor colors[] = {color,color,color,color};
|
||||||
|
core::rect<s32> rect(0,0,16/2,16);
|
||||||
|
rect += p;
|
||||||
|
core::dimension2di srcd(heart_texture->getOriginalSize());
|
||||||
|
srcd.Width /= 2;
|
||||||
|
driver->draw2DImage(heart_texture, rect,
|
||||||
|
core::rect<s32>(core::position2d<s32>(0,0), srcd),
|
||||||
|
NULL, colors, true);
|
||||||
|
p += v2s32(20,0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -1519,6 +1563,215 @@ void SpeedTests()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void getPointedNode(v3f player_position,
|
||||||
|
v3f camera_direction, v3f camera_position,
|
||||||
|
bool &nodefound, core::line3d<f32> shootline,
|
||||||
|
v3s16 &nodepos, v3s16 &neighbourpos,
|
||||||
|
core::aabbox3d<f32> &nodehilightbox,
|
||||||
|
f32 d)
|
||||||
|
{
|
||||||
|
assert(g_client);
|
||||||
|
|
||||||
|
f32 mindistance = BS * 1001;
|
||||||
|
|
||||||
|
v3s16 pos_i = floatToInt(player_position, BS);
|
||||||
|
|
||||||
|
/*std::cout<<"pos_i=("<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z<<")"
|
||||||
|
<<std::endl;*/
|
||||||
|
|
||||||
|
s16 a = d;
|
||||||
|
s16 ystart = pos_i.Y + 0 - (camera_direction.Y<0 ? a : 1);
|
||||||
|
s16 zstart = pos_i.Z - (camera_direction.Z<0 ? a : 1);
|
||||||
|
s16 xstart = pos_i.X - (camera_direction.X<0 ? a : 1);
|
||||||
|
s16 yend = pos_i.Y + 1 + (camera_direction.Y>0 ? a : 1);
|
||||||
|
s16 zend = pos_i.Z + (camera_direction.Z>0 ? a : 1);
|
||||||
|
s16 xend = pos_i.X + (camera_direction.X>0 ? a : 1);
|
||||||
|
|
||||||
|
for(s16 y = ystart; y <= yend; y++)
|
||||||
|
for(s16 z = zstart; z <= zend; z++)
|
||||||
|
for(s16 x = xstart; x <= xend; x++)
|
||||||
|
{
|
||||||
|
MapNode n;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
n = g_client->getNode(v3s16(x,y,z));
|
||||||
|
if(content_pointable(n.d) == false)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
catch(InvalidPositionException &e)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 np(x,y,z);
|
||||||
|
v3f npf = intToFloat(np, BS);
|
||||||
|
|
||||||
|
f32 d = 0.01;
|
||||||
|
|
||||||
|
v3s16 dirs[6] = {
|
||||||
|
v3s16(0,0,1), // back
|
||||||
|
v3s16(0,1,0), // top
|
||||||
|
v3s16(1,0,0), // right
|
||||||
|
v3s16(0,0,-1), // front
|
||||||
|
v3s16(0,-1,0), // bottom
|
||||||
|
v3s16(-1,0,0), // left
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Meta-objects
|
||||||
|
*/
|
||||||
|
if(n.d == CONTENT_TORCH)
|
||||||
|
{
|
||||||
|
v3s16 dir = unpackDir(n.dir);
|
||||||
|
v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
|
||||||
|
dir_f *= BS/2 - BS/6 - BS/20;
|
||||||
|
v3f cpf = npf + dir_f;
|
||||||
|
f32 distance = (cpf - camera_position).getLength();
|
||||||
|
|
||||||
|
core::aabbox3d<f32> box;
|
||||||
|
|
||||||
|
// bottom
|
||||||
|
if(dir == v3s16(0,-1,0))
|
||||||
|
{
|
||||||
|
box = core::aabbox3d<f32>(
|
||||||
|
npf - v3f(BS/6, BS/2, BS/6),
|
||||||
|
npf + v3f(BS/6, -BS/2+BS/3*2, BS/6)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// top
|
||||||
|
else if(dir == v3s16(0,1,0))
|
||||||
|
{
|
||||||
|
box = core::aabbox3d<f32>(
|
||||||
|
npf - v3f(BS/6, -BS/2+BS/3*2, BS/6),
|
||||||
|
npf + v3f(BS/6, BS/2, BS/6)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// side
|
||||||
|
else
|
||||||
|
{
|
||||||
|
box = core::aabbox3d<f32>(
|
||||||
|
cpf - v3f(BS/6, BS/3, BS/6),
|
||||||
|
cpf + v3f(BS/6, BS/3, BS/6)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(distance < mindistance)
|
||||||
|
{
|
||||||
|
if(box.intersectsWithLine(shootline))
|
||||||
|
{
|
||||||
|
nodefound = true;
|
||||||
|
nodepos = np;
|
||||||
|
neighbourpos = np;
|
||||||
|
mindistance = distance;
|
||||||
|
nodehilightbox = box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(n.d == CONTENT_SIGN_WALL)
|
||||||
|
{
|
||||||
|
v3s16 dir = unpackDir(n.dir);
|
||||||
|
v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
|
||||||
|
dir_f *= BS/2 - BS/6 - BS/20;
|
||||||
|
v3f cpf = npf + dir_f;
|
||||||
|
f32 distance = (cpf - camera_position).getLength();
|
||||||
|
|
||||||
|
v3f vertices[4] =
|
||||||
|
{
|
||||||
|
v3f(BS*0.42,-BS*0.35,-BS*0.4),
|
||||||
|
v3f(BS*0.49, BS*0.35, BS*0.4),
|
||||||
|
};
|
||||||
|
|
||||||
|
for(s32 i=0; i<2; i++)
|
||||||
|
{
|
||||||
|
if(dir == v3s16(1,0,0))
|
||||||
|
vertices[i].rotateXZBy(0);
|
||||||
|
if(dir == v3s16(-1,0,0))
|
||||||
|
vertices[i].rotateXZBy(180);
|
||||||
|
if(dir == v3s16(0,0,1))
|
||||||
|
vertices[i].rotateXZBy(90);
|
||||||
|
if(dir == v3s16(0,0,-1))
|
||||||
|
vertices[i].rotateXZBy(-90);
|
||||||
|
if(dir == v3s16(0,-1,0))
|
||||||
|
vertices[i].rotateXYBy(-90);
|
||||||
|
if(dir == v3s16(0,1,0))
|
||||||
|
vertices[i].rotateXYBy(90);
|
||||||
|
|
||||||
|
vertices[i] += npf;
|
||||||
|
}
|
||||||
|
|
||||||
|
core::aabbox3d<f32> box;
|
||||||
|
|
||||||
|
box = core::aabbox3d<f32>(vertices[0]);
|
||||||
|
box.addInternalPoint(vertices[1]);
|
||||||
|
|
||||||
|
if(distance < mindistance)
|
||||||
|
{
|
||||||
|
if(box.intersectsWithLine(shootline))
|
||||||
|
{
|
||||||
|
nodefound = true;
|
||||||
|
nodepos = np;
|
||||||
|
neighbourpos = np;
|
||||||
|
mindistance = distance;
|
||||||
|
nodehilightbox = box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Regular blocks
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(u16 i=0; i<6; i++)
|
||||||
|
{
|
||||||
|
v3f dir_f = v3f(dirs[i].X,
|
||||||
|
dirs[i].Y, dirs[i].Z);
|
||||||
|
v3f centerpoint = npf + dir_f * BS/2;
|
||||||
|
f32 distance =
|
||||||
|
(centerpoint - camera_position).getLength();
|
||||||
|
|
||||||
|
if(distance < mindistance)
|
||||||
|
{
|
||||||
|
core::CMatrix4<f32> m;
|
||||||
|
m.buildRotateFromTo(v3f(0,0,1), dir_f);
|
||||||
|
|
||||||
|
// This is the back face
|
||||||
|
v3f corners[2] = {
|
||||||
|
v3f(BS/2, BS/2, BS/2),
|
||||||
|
v3f(-BS/2, -BS/2, BS/2+d)
|
||||||
|
};
|
||||||
|
|
||||||
|
for(u16 j=0; j<2; j++)
|
||||||
|
{
|
||||||
|
m.rotateVect(corners[j]);
|
||||||
|
corners[j] += npf;
|
||||||
|
}
|
||||||
|
|
||||||
|
core::aabbox3d<f32> facebox(corners[0]);
|
||||||
|
facebox.addInternalPoint(corners[1]);
|
||||||
|
|
||||||
|
if(facebox.intersectsWithLine(shootline))
|
||||||
|
{
|
||||||
|
nodefound = true;
|
||||||
|
nodepos = np;
|
||||||
|
neighbourpos = np + dirs[i];
|
||||||
|
mindistance = distance;
|
||||||
|
|
||||||
|
//nodehilightbox = facebox;
|
||||||
|
|
||||||
|
const float d = 0.502;
|
||||||
|
core::aabbox3d<f32> nodebox
|
||||||
|
(-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d);
|
||||||
|
v3f nodepos_f = intToFloat(nodepos, BS);
|
||||||
|
nodebox.MinEdge += nodepos_f;
|
||||||
|
nodebox.MaxEdge += nodepos_f;
|
||||||
|
nodehilightbox = nodebox;
|
||||||
|
}
|
||||||
|
} // if distance < mindistance
|
||||||
|
} // for dirs
|
||||||
|
} // regular block
|
||||||
|
} // for coords
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -2148,30 +2401,14 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
//video::SColor skycolor = video::SColor(255,90,140,200);
|
//video::SColor skycolor = video::SColor(255,90,140,200);
|
||||||
//video::SColor skycolor = video::SColor(255,166,202,244);
|
//video::SColor skycolor = video::SColor(255,166,202,244);
|
||||||
video::SColor skycolor = video::SColor(255,120,185,244);
|
//video::SColor skycolor = video::SColor(255,120,185,244);
|
||||||
|
video::SColor skycolor = video::SColor(255,140,186,250);
|
||||||
|
|
||||||
camera->setFOV(FOV_ANGLE);
|
camera->setFOV(FOV_ANGLE);
|
||||||
|
|
||||||
// Just so big a value that everything rendered is visible
|
// Just so big a value that everything rendered is visible
|
||||||
camera->setFarValue(100000*BS);
|
camera->setFarValue(100000*BS);
|
||||||
|
|
||||||
/*
|
|
||||||
Lighting test code. Doesn't quite work this way.
|
|
||||||
The CPU-computed lighting is good.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
smgr->addLightSceneNode(NULL,
|
|
||||||
v3f(0, BS*1000000, 0),
|
|
||||||
video::SColorf(0.3,0.3,0.3),
|
|
||||||
BS*10000000);
|
|
||||||
|
|
||||||
smgr->setAmbientLight(video::SColorf(0.0, 0.0, 0.0));
|
|
||||||
|
|
||||||
scene::ILightSceneNode *light = smgr->addLightSceneNode(camera,
|
|
||||||
v3f(0, 0, 0), video::SColorf(0.5,0.5,0.5), BS*4);
|
|
||||||
*/
|
|
||||||
|
|
||||||
f32 camera_yaw = 0; // "right/left"
|
f32 camera_yaw = 0; // "right/left"
|
||||||
f32 camera_pitch = 0; // "up/down"
|
f32 camera_pitch = 0; // "up/down"
|
||||||
|
|
||||||
|
@ -2226,6 +2463,8 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
core::list<float> frametime_log;
|
core::list<float> frametime_log;
|
||||||
|
|
||||||
|
float damage_flash_timer = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Main loop
|
Main loop
|
||||||
*/
|
*/
|
||||||
|
@ -2453,6 +2692,16 @@ int main(int argc, char *argv[])
|
||||||
);
|
);
|
||||||
client.setPlayerControl(control);
|
client.setPlayerControl(control);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Run server
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(server != NULL)
|
||||||
|
{
|
||||||
|
//TimeTaker timer("server->step(dtime)");
|
||||||
|
server->step(dtime);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Process environment
|
Process environment
|
||||||
|
@ -2464,12 +2713,28 @@ int main(int argc, char *argv[])
|
||||||
//client.step(dtime_avg1);
|
//client.step(dtime_avg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(server != NULL)
|
// Read client events
|
||||||
|
for(;;)
|
||||||
{
|
{
|
||||||
//TimeTaker timer("server->step(dtime)");
|
ClientEvent event = client.getClientEvent();
|
||||||
server->step(dtime);
|
if(event.type == CE_NONE)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(event.type == CE_PLAYER_DAMAGE)
|
||||||
|
{
|
||||||
|
//u16 damage = event.player_damage.amount;
|
||||||
|
//dstream<<"Player damage: "<<damage<<std::endl;
|
||||||
|
damage_flash_timer = 0.05;
|
||||||
|
}
|
||||||
|
else if(event.type == CE_PLAYER_FORCE_MOVE)
|
||||||
|
{
|
||||||
|
camera_yaw = event.player_force_move.yaw;
|
||||||
|
camera_pitch = event.player_force_move.pitch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get player position
|
||||||
v3f player_position = client.getPlayerPosition();
|
v3f player_position = client.getPlayerPosition();
|
||||||
|
|
||||||
//TimeTaker //timer2("//timer2");
|
//TimeTaker //timer2("//timer2");
|
||||||
|
@ -2637,22 +2902,6 @@ int main(int argc, char *argv[])
|
||||||
else if(g_input->getRightClicked())
|
else if(g_input->getRightClicked())
|
||||||
{
|
{
|
||||||
std::cout<<DTIME<<"Right-clicked object"<<std::endl;
|
std::cout<<DTIME<<"Right-clicked object"<<std::endl;
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
Check if we want to modify the object ourselves
|
|
||||||
*/
|
|
||||||
if(selected_object->getTypeId() == MAPBLOCKOBJECT_TYPE_SIGN)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
Otherwise pass the event to the server as-is
|
|
||||||
*/
|
|
||||||
else
|
|
||||||
{
|
|
||||||
client.clickObject(1, selected_object->getBlock()->getPos(),
|
|
||||||
selected_object->getId(), g_selected_item);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // selected_object == NULL
|
else // selected_object == NULL
|
||||||
|
@ -2666,205 +2915,13 @@ int main(int argc, char *argv[])
|
||||||
v3s16 nodepos;
|
v3s16 nodepos;
|
||||||
v3s16 neighbourpos;
|
v3s16 neighbourpos;
|
||||||
core::aabbox3d<f32> nodehilightbox;
|
core::aabbox3d<f32> nodehilightbox;
|
||||||
f32 mindistance = BS * 1001;
|
|
||||||
|
|
||||||
v3s16 pos_i = floatToInt(player_position, BS);
|
|
||||||
|
|
||||||
/*std::cout<<"pos_i=("<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z<<")"
|
|
||||||
<<std::endl;*/
|
|
||||||
|
|
||||||
s16 a = d;
|
|
||||||
s16 ystart = pos_i.Y + 0 - (camera_direction.Y<0 ? a : 1);
|
|
||||||
s16 zstart = pos_i.Z - (camera_direction.Z<0 ? a : 1);
|
|
||||||
s16 xstart = pos_i.X - (camera_direction.X<0 ? a : 1);
|
|
||||||
s16 yend = pos_i.Y + 1 + (camera_direction.Y>0 ? a : 1);
|
|
||||||
s16 zend = pos_i.Z + (camera_direction.Z>0 ? a : 1);
|
|
||||||
s16 xend = pos_i.X + (camera_direction.X>0 ? a : 1);
|
|
||||||
|
|
||||||
for(s16 y = ystart; y <= yend; y++)
|
|
||||||
for(s16 z = zstart; z <= zend; z++)
|
|
||||||
for(s16 x = xstart; x <= xend; x++)
|
|
||||||
{
|
|
||||||
MapNode n;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
n = client.getNode(v3s16(x,y,z));
|
|
||||||
if(content_pointable(n.d) == false)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
v3s16 np(x,y,z);
|
|
||||||
v3f npf = intToFloat(np, BS);
|
|
||||||
|
|
||||||
f32 d = 0.01;
|
|
||||||
|
|
||||||
v3s16 dirs[6] = {
|
|
||||||
v3s16(0,0,1), // back
|
|
||||||
v3s16(0,1,0), // top
|
|
||||||
v3s16(1,0,0), // right
|
|
||||||
v3s16(0,0,-1), // front
|
|
||||||
v3s16(0,-1,0), // bottom
|
|
||||||
v3s16(-1,0,0), // left
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Meta-objects
|
|
||||||
*/
|
|
||||||
if(n.d == CONTENT_TORCH)
|
|
||||||
{
|
|
||||||
v3s16 dir = unpackDir(n.dir);
|
|
||||||
v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
|
|
||||||
dir_f *= BS/2 - BS/6 - BS/20;
|
|
||||||
v3f cpf = npf + dir_f;
|
|
||||||
f32 distance = (cpf - camera_position).getLength();
|
|
||||||
|
|
||||||
core::aabbox3d<f32> box;
|
|
||||||
|
|
||||||
// bottom
|
|
||||||
if(dir == v3s16(0,-1,0))
|
|
||||||
{
|
|
||||||
box = core::aabbox3d<f32>(
|
|
||||||
npf - v3f(BS/6, BS/2, BS/6),
|
|
||||||
npf + v3f(BS/6, -BS/2+BS/3*2, BS/6)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// top
|
|
||||||
else if(dir == v3s16(0,1,0))
|
|
||||||
{
|
|
||||||
box = core::aabbox3d<f32>(
|
|
||||||
npf - v3f(BS/6, -BS/2+BS/3*2, BS/6),
|
|
||||||
npf + v3f(BS/6, BS/2, BS/6)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// side
|
|
||||||
else
|
|
||||||
{
|
|
||||||
box = core::aabbox3d<f32>(
|
|
||||||
cpf - v3f(BS/6, BS/3, BS/6),
|
|
||||||
cpf + v3f(BS/6, BS/3, BS/6)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(distance < mindistance)
|
|
||||||
{
|
|
||||||
if(box.intersectsWithLine(shootline))
|
|
||||||
{
|
|
||||||
nodefound = true;
|
|
||||||
nodepos = np;
|
|
||||||
neighbourpos = np;
|
|
||||||
mindistance = distance;
|
|
||||||
nodehilightbox = box;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(n.d == CONTENT_SIGN_WALL)
|
|
||||||
{
|
|
||||||
v3s16 dir = unpackDir(n.dir);
|
|
||||||
v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
|
|
||||||
dir_f *= BS/2 - BS/6 - BS/20;
|
|
||||||
v3f cpf = npf + dir_f;
|
|
||||||
f32 distance = (cpf - camera_position).getLength();
|
|
||||||
|
|
||||||
v3f vertices[4] =
|
|
||||||
{
|
|
||||||
v3f(BS*0.42,-BS*0.35,-BS*0.4),
|
|
||||||
v3f(BS*0.49, BS*0.35, BS*0.4),
|
|
||||||
};
|
|
||||||
|
|
||||||
for(s32 i=0; i<2; i++)
|
|
||||||
{
|
|
||||||
if(dir == v3s16(1,0,0))
|
|
||||||
vertices[i].rotateXZBy(0);
|
|
||||||
if(dir == v3s16(-1,0,0))
|
|
||||||
vertices[i].rotateXZBy(180);
|
|
||||||
if(dir == v3s16(0,0,1))
|
|
||||||
vertices[i].rotateXZBy(90);
|
|
||||||
if(dir == v3s16(0,0,-1))
|
|
||||||
vertices[i].rotateXZBy(-90);
|
|
||||||
if(dir == v3s16(0,-1,0))
|
|
||||||
vertices[i].rotateXYBy(-90);
|
|
||||||
if(dir == v3s16(0,1,0))
|
|
||||||
vertices[i].rotateXYBy(90);
|
|
||||||
|
|
||||||
vertices[i] += npf;
|
|
||||||
}
|
|
||||||
|
|
||||||
core::aabbox3d<f32> box;
|
|
||||||
|
|
||||||
box = core::aabbox3d<f32>(vertices[0]);
|
|
||||||
box.addInternalPoint(vertices[1]);
|
|
||||||
|
|
||||||
if(distance < mindistance)
|
|
||||||
{
|
|
||||||
if(box.intersectsWithLine(shootline))
|
|
||||||
{
|
|
||||||
nodefound = true;
|
|
||||||
nodepos = np;
|
|
||||||
neighbourpos = np;
|
|
||||||
mindistance = distance;
|
|
||||||
nodehilightbox = box;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
Regular blocks
|
|
||||||
*/
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(u16 i=0; i<6; i++)
|
|
||||||
{
|
|
||||||
v3f dir_f = v3f(dirs[i].X,
|
|
||||||
dirs[i].Y, dirs[i].Z);
|
|
||||||
v3f centerpoint = npf + dir_f * BS/2;
|
|
||||||
f32 distance =
|
|
||||||
(centerpoint - camera_position).getLength();
|
|
||||||
|
|
||||||
if(distance < mindistance)
|
|
||||||
{
|
|
||||||
core::CMatrix4<f32> m;
|
|
||||||
m.buildRotateFromTo(v3f(0,0,1), dir_f);
|
|
||||||
|
|
||||||
// This is the back face
|
|
||||||
v3f corners[2] = {
|
|
||||||
v3f(BS/2, BS/2, BS/2),
|
|
||||||
v3f(-BS/2, -BS/2, BS/2+d)
|
|
||||||
};
|
|
||||||
|
|
||||||
for(u16 j=0; j<2; j++)
|
|
||||||
{
|
|
||||||
m.rotateVect(corners[j]);
|
|
||||||
corners[j] += npf;
|
|
||||||
}
|
|
||||||
|
|
||||||
core::aabbox3d<f32> facebox(corners[0]);
|
|
||||||
facebox.addInternalPoint(corners[1]);
|
|
||||||
|
|
||||||
if(facebox.intersectsWithLine(shootline))
|
|
||||||
{
|
|
||||||
nodefound = true;
|
|
||||||
nodepos = np;
|
|
||||||
neighbourpos = np + dirs[i];
|
|
||||||
mindistance = distance;
|
|
||||||
|
|
||||||
//nodehilightbox = facebox;
|
|
||||||
|
|
||||||
const float d = 0.502;
|
|
||||||
core::aabbox3d<f32> nodebox
|
|
||||||
(-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d);
|
|
||||||
v3f nodepos_f = intToFloat(nodepos, BS);
|
|
||||||
nodebox.MinEdge += nodepos_f;
|
|
||||||
nodebox.MaxEdge += nodepos_f;
|
|
||||||
nodehilightbox = nodebox;
|
|
||||||
}
|
|
||||||
} // if distance < mindistance
|
|
||||||
} // for dirs
|
|
||||||
} // regular block
|
|
||||||
} // for coords
|
|
||||||
|
|
||||||
|
getPointedNode(player_position,
|
||||||
|
camera_direction, camera_position,
|
||||||
|
nodefound, shootline,
|
||||||
|
nodepos, neighbourpos,
|
||||||
|
nodehilightbox, d);
|
||||||
|
|
||||||
static float nodig_delay_counter = 0.0;
|
static float nodig_delay_counter = 0.0;
|
||||||
|
|
||||||
if(nodefound)
|
if(nodefound)
|
||||||
|
@ -3430,10 +3487,26 @@ int main(int argc, char *argv[])
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
draw_hotbar(driver, font, v2s32(displaycenter.X, screensize.Y),
|
draw_hotbar(driver, font, v2s32(displaycenter.X, screensize.Y),
|
||||||
hotbar_imagesize, hotbar_itemcount, &local_inventory);
|
hotbar_imagesize, hotbar_itemcount, &local_inventory,
|
||||||
|
client.getHP());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Damage flash
|
||||||
|
*/
|
||||||
|
if(damage_flash_timer > 0.0)
|
||||||
|
{
|
||||||
|
damage_flash_timer -= dtime;
|
||||||
|
|
||||||
|
video::SColor color(128,255,0,0);
|
||||||
|
driver->draw2DRectangle(color,
|
||||||
|
core::rect<s32>(0,0,screensize.X,screensize.Y),
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// End drawing
|
/*
|
||||||
|
End scene
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
TimeTaker timer("endScene");
|
TimeTaker timer("endScene");
|
||||||
driver->endScene();
|
driver->endScene();
|
||||||
|
|
36
src/map.cpp
|
@ -37,8 +37,8 @@ Map::Map(std::ostream &dout):
|
||||||
m_dout(dout),
|
m_dout(dout),
|
||||||
m_sector_cache(NULL)
|
m_sector_cache(NULL)
|
||||||
{
|
{
|
||||||
m_sector_mutex.Init();
|
/*m_sector_mutex.Init();
|
||||||
assert(m_sector_mutex.IsInitialized());
|
assert(m_sector_mutex.IsInitialized());*/
|
||||||
}
|
}
|
||||||
|
|
||||||
Map::~Map()
|
Map::~Map()
|
||||||
|
@ -104,7 +104,7 @@ MapSector * Map::getSectorNoGenerateNoExNoLock(v2s16 p)
|
||||||
|
|
||||||
MapSector * Map::getSectorNoGenerateNoEx(v2s16 p)
|
MapSector * Map::getSectorNoGenerateNoEx(v2s16 p)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_sector_mutex);
|
//JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out
|
||||||
|
|
||||||
return getSectorNoGenerateNoExNoLock(p);
|
return getSectorNoGenerateNoExNoLock(p);
|
||||||
}
|
}
|
||||||
|
@ -1347,7 +1347,7 @@ bool Map::dayNightDiffed(v3s16 blockpos)
|
||||||
*/
|
*/
|
||||||
void Map::timerUpdate(float dtime)
|
void Map::timerUpdate(float dtime)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_sector_mutex);
|
//JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out
|
||||||
|
|
||||||
core::map<v2s16, MapSector*>::Iterator si;
|
core::map<v2s16, MapSector*>::Iterator si;
|
||||||
|
|
||||||
|
@ -1397,7 +1397,7 @@ void Map::deleteSectors(core::list<v2s16> &list, bool only_blocks)
|
||||||
u32 Map::deleteUnusedSectors(float timeout, bool only_blocks,
|
u32 Map::deleteUnusedSectors(float timeout, bool only_blocks,
|
||||||
core::list<v3s16> *deleted_blocks)
|
core::list<v3s16> *deleted_blocks)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_sector_mutex);
|
//JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out
|
||||||
|
|
||||||
core::list<v2s16> sector_deletion_queue;
|
core::list<v2s16> sector_deletion_queue;
|
||||||
core::map<v2s16, MapSector*>::Iterator i = m_sectors.getIterator();
|
core::map<v2s16, MapSector*>::Iterator i = m_sectors.getIterator();
|
||||||
|
@ -2163,6 +2163,18 @@ void addRandomObjects(MapBlock *block)
|
||||||
block->m_static_objects.insert(0, s_obj);
|
block->m_static_objects.insert(0, s_obj);
|
||||||
delete obj;
|
delete obj;
|
||||||
}
|
}
|
||||||
|
if(myrand() % 300 == 0)
|
||||||
|
{
|
||||||
|
v3f pos_f = intToFloat(p+block->getPosRelative(), BS);
|
||||||
|
pos_f.Y -= BS*0.4;
|
||||||
|
ServerActiveObject *obj = new Oerkki1SAO(NULL,0,pos_f);
|
||||||
|
std::string data = obj->getStaticData();
|
||||||
|
StaticObject s_obj(obj->getType(),
|
||||||
|
obj->getBasePosition(), data);
|
||||||
|
// Add one
|
||||||
|
block->m_static_objects.insert(0, s_obj);
|
||||||
|
delete obj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4714,7 +4726,7 @@ plan_b:
|
||||||
// This won't work if proper generation is disabled
|
// This won't work if proper generation is disabled
|
||||||
if(m_chunksize == 0)
|
if(m_chunksize == 0)
|
||||||
return WATER_LEVEL+2;
|
return WATER_LEVEL+2;
|
||||||
double level = base_rock_level_2d(m_seed, p2d);
|
double level = base_rock_level_2d(m_seed, p2d) + AVERAGE_MUD_AMOUNT;
|
||||||
return (s16)level;
|
return (s16)level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4794,7 +4806,7 @@ void ServerMap::save(bool only_changed)
|
||||||
u32 block_count = 0;
|
u32 block_count = 0;
|
||||||
|
|
||||||
{ //sectorlock
|
{ //sectorlock
|
||||||
JMutexAutoLock lock(m_sector_mutex);
|
//JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out
|
||||||
|
|
||||||
core::map<v2s16, MapSector*>::Iterator i = m_sectors.getIterator();
|
core::map<v2s16, MapSector*>::Iterator i = m_sectors.getIterator();
|
||||||
for(; i.atEnd() == false; i++)
|
for(; i.atEnd() == false; i++)
|
||||||
|
@ -4856,7 +4868,7 @@ void ServerMap::loadAll()
|
||||||
|
|
||||||
dstream<<DTIME<<"There are "<<list.size()<<" sectors."<<std::endl;
|
dstream<<DTIME<<"There are "<<list.size()<<" sectors."<<std::endl;
|
||||||
|
|
||||||
JMutexAutoLock lock(m_sector_mutex);
|
//JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out
|
||||||
|
|
||||||
s32 counter = 0;
|
s32 counter = 0;
|
||||||
s32 printed_counter = -100000;
|
s32 printed_counter = -100000;
|
||||||
|
@ -5163,7 +5175,7 @@ bool ServerMap::loadSectorFull(v2s16 p2d)
|
||||||
|
|
||||||
MapSector *sector = NULL;
|
MapSector *sector = NULL;
|
||||||
|
|
||||||
JMutexAutoLock lock(m_sector_mutex);
|
//JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out
|
||||||
|
|
||||||
try{
|
try{
|
||||||
sector = loadSectorMeta(sectorsubdir);
|
sector = loadSectorMeta(sectorsubdir);
|
||||||
|
@ -5410,7 +5422,7 @@ MapSector * ClientMap::emergeSector(v2s16 p2d)
|
||||||
ClientMapSector *sector = new ClientMapSector(this, p2d);
|
ClientMapSector *sector = new ClientMapSector(this, p2d);
|
||||||
|
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_sector_mutex);
|
//JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out
|
||||||
m_sectors.insert(p2d, sector);
|
m_sectors.insert(p2d, sector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5422,7 +5434,7 @@ void ClientMap::deSerializeSector(v2s16 p2d, std::istream &is)
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
ClientMapSector *sector = NULL;
|
ClientMapSector *sector = NULL;
|
||||||
|
|
||||||
JMutexAutoLock lock(m_sector_mutex);
|
//JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out
|
||||||
|
|
||||||
core::map<v2s16, MapSector*>::Node *n = m_sectors.find(p2d);
|
core::map<v2s16, MapSector*>::Node *n = m_sectors.find(p2d);
|
||||||
|
|
||||||
|
@ -5435,7 +5447,7 @@ void ClientMap::deSerializeSector(v2s16 p2d, std::istream &is)
|
||||||
{
|
{
|
||||||
sector = new ClientMapSector(this, p2d);
|
sector = new ClientMapSector(this, p2d);
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_sector_mutex);
|
//JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out
|
||||||
m_sectors.insert(p2d, sector);
|
m_sectors.insert(p2d, sector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
src/map.h
|
@ -287,6 +287,11 @@ public:
|
||||||
void removeNodeMetadata(v3s16 p);
|
void removeNodeMetadata(v3s16 p);
|
||||||
void nodeMetadataStep(float dtime,
|
void nodeMetadataStep(float dtime,
|
||||||
core::map<v3s16, MapBlock*> &changed_blocks);
|
core::map<v3s16, MapBlock*> &changed_blocks);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Misc.
|
||||||
|
*/
|
||||||
|
core::map<v2s16, MapSector*> *getSectorsPtr(){return &m_sectors;}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Variables
|
Variables
|
||||||
|
@ -298,16 +303,13 @@ protected:
|
||||||
|
|
||||||
core::map<MapEventReceiver*, bool> m_event_receivers;
|
core::map<MapEventReceiver*, bool> m_event_receivers;
|
||||||
|
|
||||||
// Mutex is important because on client map is accessed asynchronously
|
|
||||||
core::map<v2s16, MapSector*> m_sectors;
|
core::map<v2s16, MapSector*> m_sectors;
|
||||||
JMutex m_sector_mutex;
|
//JMutex m_sector_mutex;
|
||||||
|
|
||||||
// Be sure to set this to NULL when the cached sector is deleted
|
// Be sure to set this to NULL when the cached sector is deleted
|
||||||
MapSector *m_sector_cache;
|
MapSector *m_sector_cache;
|
||||||
v2s16 m_sector_cache_p;
|
v2s16 m_sector_cache_p;
|
||||||
|
|
||||||
//WrapperHeightmap m_hwrapper;
|
|
||||||
|
|
||||||
// Queued transforming water nodes
|
// Queued transforming water nodes
|
||||||
UniqueQueue<v3s16> m_transforming_liquid;
|
UniqueQueue<v3s16> m_transforming_liquid;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1924,9 +1924,19 @@ void MapBlock::serialize(std::ostream &os, u8 version)
|
||||||
*/
|
*/
|
||||||
if(version >= 14)
|
if(version >= 14)
|
||||||
{
|
{
|
||||||
std::ostringstream oss(std::ios_base::binary);
|
if(version <= 15)
|
||||||
m_node_metadata.serialize(oss);
|
{
|
||||||
os<<serializeString(oss.str());
|
std::ostringstream oss(std::ios_base::binary);
|
||||||
|
m_node_metadata.serialize(oss);
|
||||||
|
os<<serializeString(oss.str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::ostringstream oss(std::ios_base::binary);
|
||||||
|
m_node_metadata.serialize(oss);
|
||||||
|
compressZlib(oss.str(), os);
|
||||||
|
//os<<serializeLongString(oss.str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2055,9 +2065,20 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
|
||||||
{
|
{
|
||||||
// Ignore errors
|
// Ignore errors
|
||||||
try{
|
try{
|
||||||
std::string data = deSerializeString(is);
|
if(version <= 15)
|
||||||
std::istringstream iss(data, std::ios_base::binary);
|
{
|
||||||
m_node_metadata.deSerialize(iss);
|
std::string data = deSerializeString(is);
|
||||||
|
std::istringstream iss(data, std::ios_base::binary);
|
||||||
|
m_node_metadata.deSerialize(iss);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//std::string data = deSerializeLongString(is);
|
||||||
|
std::ostringstream oss(std::ios_base::binary);
|
||||||
|
decompressZlib(is, oss);
|
||||||
|
std::istringstream iss(oss.str(), std::ios_base::binary);
|
||||||
|
m_node_metadata.deSerialize(iss);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(SerializationError &e)
|
catch(SerializationError &e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,6 +33,7 @@ Player::Player():
|
||||||
in_water_stable(false),
|
in_water_stable(false),
|
||||||
swimming_up(false),
|
swimming_up(false),
|
||||||
craftresult_is_preview(true),
|
craftresult_is_preview(true),
|
||||||
|
hp(20),
|
||||||
peer_id(PEER_ID_INEXISTENT),
|
peer_id(PEER_ID_INEXISTENT),
|
||||||
m_pitch(0),
|
m_pitch(0),
|
||||||
m_yaw(0),
|
m_yaw(0),
|
||||||
|
@ -102,6 +103,7 @@ void Player::serialize(std::ostream &os)
|
||||||
args.setFloat("yaw", m_yaw);
|
args.setFloat("yaw", m_yaw);
|
||||||
args.setV3F("position", m_position);
|
args.setV3F("position", m_position);
|
||||||
args.setBool("craftresult_is_preview", craftresult_is_preview);
|
args.setBool("craftresult_is_preview", craftresult_is_preview);
|
||||||
|
args.setS32("hp", hp);
|
||||||
|
|
||||||
args.writeLines(os);
|
args.writeLines(os);
|
||||||
|
|
||||||
|
@ -138,6 +140,11 @@ void Player::deSerialize(std::istream &is)
|
||||||
}catch(SettingNotFoundException &e){
|
}catch(SettingNotFoundException &e){
|
||||||
craftresult_is_preview = true;
|
craftresult_is_preview = true;
|
||||||
}
|
}
|
||||||
|
try{
|
||||||
|
hp = args.getS32("hp");
|
||||||
|
}catch(SettingNotFoundException &e){
|
||||||
|
hp = 20;
|
||||||
|
}
|
||||||
|
|
||||||
inventory.deSerialize(is);
|
inventory.deSerialize(is);
|
||||||
}
|
}
|
||||||
|
@ -276,7 +283,8 @@ LocalPlayer::~LocalPlayer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
||||||
|
core::list<CollisionInfo> *collision_info)
|
||||||
{
|
{
|
||||||
v3f position = getPosition();
|
v3f position = getPosition();
|
||||||
v3f oldpos = position;
|
v3f oldpos = position;
|
||||||
|
@ -530,9 +538,23 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
||||||
*/
|
*/
|
||||||
if(other_axes_overlap && main_axis_collides)
|
if(other_axes_overlap && main_axis_collides)
|
||||||
{
|
{
|
||||||
|
v3f old_speed = m_speed;
|
||||||
|
|
||||||
m_speed -= m_speed.dotProduct(dirs[i]) * dirs[i];
|
m_speed -= m_speed.dotProduct(dirs[i]) * dirs[i];
|
||||||
position -= position.dotProduct(dirs[i]) * dirs[i];
|
position -= position.dotProduct(dirs[i]) * dirs[i];
|
||||||
position += oldpos.dotProduct(dirs[i]) * dirs[i];
|
position += oldpos.dotProduct(dirs[i]) * dirs[i];
|
||||||
|
|
||||||
|
if(collision_info)
|
||||||
|
{
|
||||||
|
// Report fall collision
|
||||||
|
if(old_speed.Y < m_speed.Y - 0.1)
|
||||||
|
{
|
||||||
|
CollisionInfo info;
|
||||||
|
info.t = COLLISION_FALL;
|
||||||
|
info.speed = m_speed.Y - old_speed.Y;
|
||||||
|
collision_info->push_back(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -617,6 +639,11 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
||||||
setPosition(position);
|
setPosition(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
|
||||||
|
{
|
||||||
|
move(dtime, map, pos_max_d, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void LocalPlayer::applyControl(float dtime)
|
void LocalPlayer::applyControl(float dtime)
|
||||||
{
|
{
|
||||||
// Clear stuff
|
// Clear stuff
|
||||||
|
|
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
|
#include "collision.h"
|
||||||
|
|
||||||
#define PLAYERNAME_SIZE 20
|
#define PLAYERNAME_SIZE 20
|
||||||
|
|
||||||
|
@ -124,6 +125,8 @@ public:
|
||||||
|
|
||||||
bool craftresult_is_preview;
|
bool craftresult_is_preview;
|
||||||
|
|
||||||
|
u16 hp;
|
||||||
|
|
||||||
u16 peer_id;
|
u16 peer_id;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -325,6 +328,8 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void move(f32 dtime, Map &map, f32 pos_max_d,
|
||||||
|
core::list<CollisionInfo> *collision_info);
|
||||||
void move(f32 dtime, Map &map, f32 pos_max_d);
|
void move(f32 dtime, Map &map, f32 pos_max_d);
|
||||||
|
|
||||||
void applyControl(float dtime);
|
void applyControl(float dtime);
|
||||||
|
|
|
@ -105,6 +105,12 @@ void compressZlib(SharedBuffer<u8> data, std::ostream &os)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void compressZlib(const std::string &data, std::ostream &os)
|
||||||
|
{
|
||||||
|
SharedBuffer<u8> databuf((u8*)data.c_str(), data.size());
|
||||||
|
compressZlib(databuf, os);
|
||||||
|
}
|
||||||
|
|
||||||
void decompressZlib(std::istream &is, std::ostream &os)
|
void decompressZlib(std::istream &is, std::ostream &os)
|
||||||
{
|
{
|
||||||
z_stream z;
|
z_stream z;
|
||||||
|
|
|
@ -48,17 +48,23 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
13: (dev) Mapgen v2
|
13: (dev) Mapgen v2
|
||||||
14: (dev) NodeMetadata
|
14: (dev) NodeMetadata
|
||||||
15: (dev) StaticObjects
|
15: (dev) StaticObjects
|
||||||
|
16: (dev) larger maximum size of node metadata, and compression
|
||||||
*/
|
*/
|
||||||
// This represents an uninitialized or invalid format
|
// This represents an uninitialized or invalid format
|
||||||
#define SER_FMT_VER_INVALID 255
|
#define SER_FMT_VER_INVALID 255
|
||||||
// Highest supported serialization version
|
// Highest supported serialization version
|
||||||
#define SER_FMT_VER_HIGHEST 15
|
#define SER_FMT_VER_HIGHEST 16
|
||||||
// Lowest supported serialization version
|
// Lowest supported serialization version
|
||||||
#define SER_FMT_VER_LOWEST 0
|
#define SER_FMT_VER_LOWEST 0
|
||||||
|
|
||||||
#define ser_ver_supported(v) (v >= SER_FMT_VER_LOWEST && v <= SER_FMT_VER_HIGHEST)
|
#define ser_ver_supported(v) (v >= SER_FMT_VER_LOWEST && v <= SER_FMT_VER_HIGHEST)
|
||||||
|
|
||||||
|
void compressZlib(SharedBuffer<u8> data, std::ostream &os);
|
||||||
|
void compressZlib(const std::string &data, std::ostream &os);
|
||||||
|
void decompressZlib(std::istream &is, std::ostream &os);
|
||||||
|
|
||||||
void compress(SharedBuffer<u8> data, std::ostream &os, u8 version);
|
void compress(SharedBuffer<u8> data, std::ostream &os, u8 version);
|
||||||
|
//void compress(const std::string &data, std::ostream &os, u8 version);
|
||||||
void decompress(std::istream &is, std::ostream &os, u8 version);
|
void decompress(std::istream &is, std::ostream &os, u8 version);
|
||||||
|
|
||||||
/*class Serializable
|
/*class Serializable
|
||||||
|
|
864
src/server.cpp
27
src/server.h
|
@ -33,6 +33,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Some random functions
|
||||||
|
*/
|
||||||
|
v3f findSpawnPos(ServerMap &map);
|
||||||
|
|
||||||
|
/*
|
||||||
|
A structure containing the data needed for queueing the fetching
|
||||||
|
of blocks.
|
||||||
|
*/
|
||||||
struct QueuedBlockEmerge
|
struct QueuedBlockEmerge
|
||||||
{
|
{
|
||||||
v3s16 pos;
|
v3s16 pos;
|
||||||
|
@ -397,12 +406,24 @@ private:
|
||||||
void peerAdded(con::Peer *peer);
|
void peerAdded(con::Peer *peer);
|
||||||
void deletingPeer(con::Peer *peer, bool timeout);
|
void deletingPeer(con::Peer *peer, bool timeout);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Static send methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Non-static send methods
|
||||||
|
*/
|
||||||
|
|
||||||
// Envlock and conlock should be locked when calling these
|
// Envlock and conlock should be locked when calling these
|
||||||
void SendObjectData(float dtime);
|
void SendObjectData(float dtime);
|
||||||
void SendPlayerInfos();
|
void SendPlayerInfos();
|
||||||
void SendInventory(u16 peer_id);
|
void SendInventory(u16 peer_id);
|
||||||
void SendChatMessage(u16 peer_id, const std::wstring &message);
|
void SendChatMessage(u16 peer_id, const std::wstring &message);
|
||||||
void BroadcastChatMessage(const std::wstring &message);
|
void BroadcastChatMessage(const std::wstring &message);
|
||||||
|
void SendPlayerHP(Player *player);
|
||||||
|
void SendMovePlayer(Player *player);
|
||||||
/*
|
/*
|
||||||
Send a node removal/addition event to all clients except ignore_id.
|
Send a node removal/addition event to all clients except ignore_id.
|
||||||
Additionally, if far_players!=NULL, players further away than
|
Additionally, if far_players!=NULL, players further away than
|
||||||
|
@ -418,6 +439,12 @@ private:
|
||||||
|
|
||||||
// Sends blocks to clients
|
// Sends blocks to clients
|
||||||
void SendBlocks(float dtime);
|
void SendBlocks(float dtime);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Something random
|
||||||
|
*/
|
||||||
|
|
||||||
|
void UpdateCrafting(u16 peer_id);
|
||||||
|
|
||||||
// When called, connection mutex should be locked
|
// When called, connection mutex should be locked
|
||||||
RemoteClient* getClient(u16 peer_id);
|
RemoteClient* getClient(u16 peer_id);
|
||||||
|
|
|
@ -451,4 +451,219 @@ InventoryItem* RatSAO::createPickedUpItem()
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Oerkki1SAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Prototype
|
||||||
|
Oerkki1SAO proto_Oerkki1SAO(NULL, 0, v3f(0,0,0));
|
||||||
|
|
||||||
|
Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos):
|
||||||
|
ServerActiveObject(env, id, pos),
|
||||||
|
m_is_active(false),
|
||||||
|
m_speed_f(0,0,0)
|
||||||
|
{
|
||||||
|
ServerActiveObject::registerType(getType(), create);
|
||||||
|
|
||||||
|
m_oldpos = v3f(0,0,0);
|
||||||
|
m_last_sent_position = v3f(0,0,0);
|
||||||
|
m_yaw = 0;
|
||||||
|
m_counter1 = 0;
|
||||||
|
m_counter2 = 0;
|
||||||
|
m_age = 0;
|
||||||
|
m_touching_ground = false;
|
||||||
|
m_hp = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string &data)
|
||||||
|
{
|
||||||
|
std::istringstream is(data, std::ios::binary);
|
||||||
|
// read version
|
||||||
|
u8 version = readU8(is);
|
||||||
|
// read hp
|
||||||
|
u8 hp = readU8(is);
|
||||||
|
// check if version is supported
|
||||||
|
if(version != 0)
|
||||||
|
return NULL;
|
||||||
|
Oerkki1SAO *o = new Oerkki1SAO(env, id, pos);
|
||||||
|
o->m_hp = hp;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oerkki1SAO::step(float dtime, Queue<ActiveObjectMessage> &messages,
|
||||||
|
bool send_recommended)
|
||||||
|
{
|
||||||
|
assert(m_env);
|
||||||
|
|
||||||
|
if(m_is_active == false)
|
||||||
|
{
|
||||||
|
if(m_inactive_interval.step(dtime, 0.5)==false)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The AI
|
||||||
|
*/
|
||||||
|
|
||||||
|
m_age += dtime;
|
||||||
|
if(m_age > 60)
|
||||||
|
{
|
||||||
|
// Die
|
||||||
|
m_removed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply gravity
|
||||||
|
m_speed_f.Y -= dtime*9.81*BS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move around if some player is close
|
||||||
|
*/
|
||||||
|
bool player_is_close = false;
|
||||||
|
v3f near_player_pos;
|
||||||
|
// Check connected players
|
||||||
|
core::list<Player*> players = m_env->getPlayers(true);
|
||||||
|
core::list<Player*>::Iterator i;
|
||||||
|
for(i = players.begin();
|
||||||
|
i != players.end(); i++)
|
||||||
|
{
|
||||||
|
Player *player = *i;
|
||||||
|
v3f playerpos = player->getPosition();
|
||||||
|
if(m_base_position.getDistanceFrom(playerpos) < BS*15.0)
|
||||||
|
{
|
||||||
|
player_is_close = true;
|
||||||
|
near_player_pos = playerpos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_is_active = player_is_close;
|
||||||
|
|
||||||
|
if(player_is_close == false)
|
||||||
|
{
|
||||||
|
m_speed_f.X = 0;
|
||||||
|
m_speed_f.Z = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Move around
|
||||||
|
|
||||||
|
v3f ndir = near_player_pos - m_base_position;
|
||||||
|
ndir.Y = 0;
|
||||||
|
ndir /= ndir.getLength();
|
||||||
|
f32 nyaw = 180./PI*atan2(ndir.Z,ndir.X);
|
||||||
|
if(nyaw < m_yaw - 180)
|
||||||
|
nyaw += 360;
|
||||||
|
else if(nyaw > m_yaw + 180)
|
||||||
|
nyaw -= 360;
|
||||||
|
m_yaw = 0.95*m_yaw + 0.05*nyaw;
|
||||||
|
m_yaw = wrapDegrees(m_yaw);
|
||||||
|
|
||||||
|
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
|
||||||
|
f32 speed = 2*BS;
|
||||||
|
m_speed_f.X = speed * dir.X;
|
||||||
|
m_speed_f.Z = speed * dir.Z;
|
||||||
|
|
||||||
|
if(m_touching_ground && (m_oldpos - m_base_position).getLength()
|
||||||
|
< dtime*speed/2)
|
||||||
|
{
|
||||||
|
m_counter1 -= dtime;
|
||||||
|
if(m_counter1 < 0.0)
|
||||||
|
{
|
||||||
|
m_counter1 += 1.0;
|
||||||
|
// Jump
|
||||||
|
m_speed_f.Y = 5.0*BS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
m_counter2 -= dtime;
|
||||||
|
if(m_counter2 < 0.0)
|
||||||
|
{
|
||||||
|
m_counter2 += (float)(myrand()%100)/100*3.0;
|
||||||
|
//m_yaw += ((float)(myrand()%200)-100)/100*180;
|
||||||
|
m_yaw += ((float)(myrand()%200)-100)/100*90;
|
||||||
|
m_yaw = wrapDegrees(m_yaw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_oldpos = m_base_position;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Move it, with collision detection
|
||||||
|
*/
|
||||||
|
|
||||||
|
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*5./3.,BS/3.);
|
||||||
|
collisionMoveResult moveresult;
|
||||||
|
// Maximum movement without glitches
|
||||||
|
f32 pos_max_d = BS*0.25;
|
||||||
|
// Limit speed
|
||||||
|
if(m_speed_f.getLength()*dtime > pos_max_d)
|
||||||
|
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
|
||||||
|
v3f pos_f = getBasePosition();
|
||||||
|
v3f pos_f_old = pos_f;
|
||||||
|
moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
|
||||||
|
box, dtime, pos_f, m_speed_f);
|
||||||
|
m_touching_ground = moveresult.touching_ground;
|
||||||
|
|
||||||
|
setBasePosition(pos_f);
|
||||||
|
|
||||||
|
if(send_recommended == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
|
||||||
|
{
|
||||||
|
m_last_sent_position = pos_f;
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (0 = update position)
|
||||||
|
writeU8(os, 0);
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_base_position);
|
||||||
|
// yaw
|
||||||
|
writeF1000(os, m_yaw);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
messages.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Oerkki1SAO::getClientInitializationData()
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_base_position);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Oerkki1SAO::getStaticData()
|
||||||
|
{
|
||||||
|
//dstream<<__FUNCTION_NAME<<std::endl;
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
// hp
|
||||||
|
writeU8(os, m_hp);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 Oerkki1SAO::punch(const std::string &toolname)
|
||||||
|
{
|
||||||
|
u16 amount = 5;
|
||||||
|
if(amount < m_hp)
|
||||||
|
{
|
||||||
|
m_hp -= amount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Die
|
||||||
|
m_removed = true;
|
||||||
|
}
|
||||||
|
return 65536/100;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,12 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual InventoryItem* createPickedUpItem(){return NULL;}
|
virtual InventoryItem* createPickedUpItem(){return NULL;}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If the object doesn't return an item, this will be called.
|
||||||
|
Return value is tool wear.
|
||||||
|
*/
|
||||||
|
virtual u16 punch(const std::string &toolname){return 0;}
|
||||||
|
|
||||||
// Number of players which know about this object
|
// Number of players which know about this object
|
||||||
u16 m_known_by_count;
|
u16 m_known_by_count;
|
||||||
/*
|
/*
|
||||||
|
@ -201,5 +207,33 @@ private:
|
||||||
bool m_touching_ground;
|
bool m_touching_ground;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Oerkki1SAO : public ServerActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos);
|
||||||
|
u8 getType() const
|
||||||
|
{return ACTIVEOBJECT_TYPE_OERKKI1;}
|
||||||
|
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
|
||||||
|
const std::string &data);
|
||||||
|
void step(float dtime, Queue<ActiveObjectMessage> &messages,
|
||||||
|
bool send_recommended);
|
||||||
|
std::string getClientInitializationData();
|
||||||
|
std::string getStaticData();
|
||||||
|
InventoryItem* createPickedUpItem(){return NULL;}
|
||||||
|
u16 punch(const std::string &toolname);
|
||||||
|
private:
|
||||||
|
bool m_is_active;
|
||||||
|
IntervalLimiter m_inactive_interval;
|
||||||
|
v3f m_speed_f;
|
||||||
|
v3f m_oldpos;
|
||||||
|
v3f m_last_sent_position;
|
||||||
|
float m_yaw;
|
||||||
|
float m_counter1;
|
||||||
|
float m_counter2;
|
||||||
|
float m_age;
|
||||||
|
bool m_touching_ground;
|
||||||
|
u8 m_hp;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
16
src/test.cpp
|
@ -951,18 +951,18 @@ struct TestConnection
|
||||||
assert(got_exception);
|
assert(got_exception);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
//u8 data1[1100];
|
const int datasize = 30000;
|
||||||
SharedBuffer<u8> data1(1100);
|
SharedBuffer<u8> data1(datasize);
|
||||||
for(u16 i=0; i<1100; i++){
|
for(u16 i=0; i<datasize; i++){
|
||||||
data1[i] = i/4;
|
data1[i] = i/4;
|
||||||
}
|
}
|
||||||
|
|
||||||
dstream<<"Sending data (size="<<1100<<"):";
|
dstream<<"Sending data (size="<<datasize<<"):";
|
||||||
for(int i=0; i<1100 && i<20; i++){
|
for(int i=0; i<datasize && i<20; i++){
|
||||||
if(i%2==0) DEBUGPRINT(" ");
|
if(i%2==0) DEBUGPRINT(" ");
|
||||||
DEBUGPRINT("%.2X", ((int)((const char*)*data1)[i])&0xff);
|
DEBUGPRINT("%.2X", ((int)((const char*)*data1)[i])&0xff);
|
||||||
}
|
}
|
||||||
if(1100>20)
|
if(datasize>20)
|
||||||
dstream<<"...";
|
dstream<<"...";
|
||||||
dstream<<std::endl;
|
dstream<<std::endl;
|
||||||
|
|
||||||
|
@ -970,10 +970,10 @@ struct TestConnection
|
||||||
|
|
||||||
sleep_ms(50);
|
sleep_ms(50);
|
||||||
|
|
||||||
u8 recvdata[2000];
|
u8 recvdata[datasize + 1000];
|
||||||
dstream<<"** running client.Receive()"<<std::endl;
|
dstream<<"** running client.Receive()"<<std::endl;
|
||||||
u16 peer_id = 132;
|
u16 peer_id = 132;
|
||||||
u16 size = client.Receive(peer_id, recvdata, 2000);
|
u16 size = client.Receive(peer_id, recvdata, datasize + 1000);
|
||||||
dstream<<"** Client received: peer_id="<<peer_id
|
dstream<<"** Client received: peer_id="<<peer_id
|
||||||
<<", size="<<size
|
<<", size="<<size
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
|
|
|
@ -215,8 +215,8 @@ inline void writeU16(std::ostream &os, u16 p)
|
||||||
}
|
}
|
||||||
inline u16 readU16(std::istream &is)
|
inline u16 readU16(std::istream &is)
|
||||||
{
|
{
|
||||||
char buf[12];
|
char buf[2];
|
||||||
is.read(buf, 12);
|
is.read(buf, 2);
|
||||||
return readU16((u8*)buf);
|
return readU16((u8*)buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,8 +228,8 @@ inline void writeF1000(std::ostream &os, f32 p)
|
||||||
}
|
}
|
||||||
inline f32 readF1000(std::istream &is)
|
inline f32 readF1000(std::istream &is)
|
||||||
{
|
{
|
||||||
char buf[12];
|
char buf[2];
|
||||||
is.read(buf, 12);
|
is.read(buf, 2);
|
||||||
return readF1000((u8*)buf);
|
return readF1000((u8*)buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|