From cb130d9158dc4e9c456d088d5e214b7d829ccc3a Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sun, 26 Jun 2011 00:03:58 +0300 Subject: cleaned map stuff --- src/map.cpp | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) (limited to 'src/map.cpp') diff --git a/src/map.cpp b/src/map.cpp index 0de9cf18e..4a8aeed59 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -18,8 +18,9 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "map.h" +#include "mapsector.h" +#include "mapblock.h" #include "main.h" -#include "jmutexautolock.h" #include "client.h" #include "filesys.h" #include "utility.h" @@ -122,31 +123,23 @@ MapSector * Map::getSectorNoGenerate(v2s16 p) return sector; } -MapBlock * Map::getBlockNoCreate(v3s16 p3d) -{ +MapBlock * Map::getBlockNoCreateNoEx(v3s16 p3d) +{ v2s16 p2d(p3d.X, p3d.Z); MapSector * sector = getSectorNoGenerate(p2d); - - MapBlock *block = sector->getBlockNoCreate(p3d.Y); - + MapBlock *block = sector->getBlockNoCreateNoEx(p3d.Y); return block; } -MapBlock * Map::getBlockNoCreateNoEx(v3s16 p3d) -{ - try - { - v2s16 p2d(p3d.X, p3d.Z); - MapSector * sector = getSectorNoGenerate(p2d); - MapBlock *block = sector->getBlockNoCreate(p3d.Y); - return block; - } - catch(InvalidPositionException &e) - { - return NULL; - } +MapBlock * Map::getBlockNoCreate(v3s16 p3d) +{ + MapBlock *block = getBlockNoCreateNoEx(p3d); + if(block == NULL) + throw InvalidPositionException(); + return block; } + /*MapBlock * Map::getBlockCreate(v3s16 p3d) { v2s16 p2d(p3d.X, p3d.Z); @@ -1422,9 +1415,8 @@ u32 Map::unloadUnusedData(float timeout, bool only_blocks, // Save if modified if(block->getModified() != MOD_STATE_CLEAN) saveBlock(block); - // Unload - sector->removeBlock(block); - delete block; + // Delete from memory + sector->deleteBlock(block); } else { @@ -3062,10 +3054,8 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto MapBlock *block = NULL; bool created_new = false; - try{ - block = sector->getBlockNoCreate(p3d.Y); - } - catch(InvalidPositionException &e) + block = sector->getBlockNoCreateNoEx(p3d.Y); + if(block == NULL) { block = sector->createBlankBlockNoInsert(p3d.Y); created_new = true; @@ -3235,6 +3225,7 @@ MapSector * ClientMap::emergeSector(v2s16 p2d) return sector; } +#if 0 void ClientMap::deSerializeSector(v2s16 p2d, std::istream &is) { DSTACK(__FUNCTION_NAME); @@ -3260,6 +3251,7 @@ void ClientMap::deSerializeSector(v2s16 p2d, std::istream &is) sector->deSerialize(is); } +#endif void ClientMap::OnRegisterSceneNode() { -- cgit v1.2.3 From 2915bd5518150955ed1581110527f4bb4adadfe8 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sun, 26 Jun 2011 01:31:43 +0300 Subject: more reorganizing of map code --- src/CMakeLists.txt | 3 +-- src/map.cpp | 4 +++- src/map.h | 6 +++--- src/mapblock.cpp | 2 +- src/mapblock.h | 15 +++++++++------ src/mapblock_mesh.cpp | 6 +----- src/mapblockobject.cpp | 11 +---------- src/mapsector.cpp | 8 ++++---- src/mapsector.h | 12 ++++++------ src/test.cpp | 11 +++++++++-- 10 files changed, 38 insertions(+), 40 deletions(-) (limited to 'src/map.cpp') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ac58d1d0f..73a960ecc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -206,8 +206,7 @@ else() endif() set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${RELEASE_WARNING_FLAGS} ${WARNING_FLAGS} -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops") - #set(CMAKE_CXX_FLAGS_DEBUG "-g -O1 -Wall ${WARNING_FLAGS}") - set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall ${WARNING_FLAGS}") + set(CMAKE_CXX_FLAGS_DEBUG "-g -O1 -Wall ${WARNING_FLAGS}") if(USE_GPROF) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg") diff --git a/src/map.cpp b/src/map.cpp index 4a8aeed59..d8cc34ca7 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -126,7 +126,9 @@ MapSector * Map::getSectorNoGenerate(v2s16 p) MapBlock * Map::getBlockNoCreateNoEx(v3s16 p3d) { v2s16 p2d(p3d.X, p3d.Z); - MapSector * sector = getSectorNoGenerate(p2d); + MapSector * sector = getSectorNoGenerateNoEx(p2d); + if(sector == NULL) + return NULL; MapBlock *block = sector->getBlockNoCreateNoEx(p3d.Y); return block; } diff --git a/src/map.h b/src/map.h index 99593a589..406b1bc84 100644 --- a/src/map.h +++ b/src/map.h @@ -110,17 +110,17 @@ public: virtual void onMapEditEvent(MapEditEvent *event) = 0; }; -class Map : public NodeContainer +class Map /*: public NodeContainer*/ { public: Map(std::ostream &dout); virtual ~Map(); - virtual u16 nodeContainerId() const + /*virtual u16 nodeContainerId() const { return NODECONTAINER_ID_MAP; - } + }*/ virtual s32 mapType() const { diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 2f6a4b850..7036cd035 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., MapBlock */ -MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy): +MapBlock::MapBlock(Map *parent, v3s16 pos, bool dummy): m_parent(parent), m_pos(pos), m_modified(MOD_STATE_WRITE_NEEDED), diff --git a/src/mapblock.h b/src/mapblock.h index 693bc5190..8f3b8464a 100644 --- a/src/mapblock.h +++ b/src/mapblock.h @@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapblock_mesh.h" #endif +class Map; #define BLOCK_TIMESTAMP_UNDEFINED 0xffffffff @@ -81,6 +82,7 @@ enum ModifiedState BLOCKGEN_FULLY_GENERATED=6 };*/ +#if 0 enum { NODECONTAINER_ID_MAPBLOCK, @@ -108,23 +110,24 @@ public: } } }; +#endif /* MapBlock itself */ -class MapBlock : public NodeContainer +class MapBlock /*: public NodeContainer*/ { public: - MapBlock(NodeContainer *parent, v3s16 pos, bool dummy=false); + MapBlock(Map *parent, v3s16 pos, bool dummy=false); ~MapBlock(); - virtual u16 nodeContainerId() const + /*virtual u16 nodeContainerId() const { return NODECONTAINER_ID_MAPBLOCK; - } + }*/ - NodeContainer * getParent() + Map * getParent() { return m_parent; } @@ -640,7 +643,7 @@ private: */ // NOTE: Lots of things rely on this being the Map - NodeContainer *m_parent; + Map *m_parent; // Position in blocks on parent v3s16 m_pos; diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp index d4921c2c5..447716d00 100644 --- a/src/mapblock_mesh.cpp +++ b/src/mapblock_mesh.cpp @@ -64,11 +64,7 @@ void MeshMakeData::fill(u32 daynight_ratio, MapBlock *block) */ // Get map - NodeContainer *parentcontainer = block->getParent(); - // This will only work if the parent is the map - assert(parentcontainer->nodeContainerId() == NODECONTAINER_ID_MAP); - // OK, we have the map! - Map *map = (Map*)parentcontainer; + Map *map = block->getParent(); for(u16 i=0; i<6; i++) { diff --git a/src/mapblockobject.cpp b/src/mapblockobject.cpp index 009163a18..51ac4c66b 100644 --- a/src/mapblockobject.cpp +++ b/src/mapblockobject.cpp @@ -856,16 +856,7 @@ bool MapBlockObjectList::wrapObject(MapBlockObject *object) assert(m_objects.find(object->m_id) != NULL); assert(m_objects[object->m_id] == object); - NodeContainer *parentcontainer = m_block->getParent(); - // This will only work if the parent is the map - if(parentcontainer->nodeContainerId() != NODECONTAINER_ID_MAP) - { - dstream<<"WARNING: Wrapping object not possible: " - "MapBlock's parent is not map"<getParent(); // Calculate blockpos on map v3s16 oldblock_pos_i_on_map = m_block->getPosRelative(); diff --git a/src/mapsector.cpp b/src/mapsector.cpp index 389714f40..4a526c412 100644 --- a/src/mapsector.cpp +++ b/src/mapsector.cpp @@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "exceptions.h" #include "mapblock.h" -MapSector::MapSector(NodeContainer *parent, v2s16 pos): +MapSector::MapSector(Map *parent, v2s16 pos): differs_from_disk(false), m_parent(parent), m_pos(pos), @@ -151,7 +151,7 @@ void MapSector::getBlocks(core::list &dest) ServerMapSector */ -ServerMapSector::ServerMapSector(NodeContainer *parent, v2s16 pos): +ServerMapSector::ServerMapSector(Map *parent, v2s16 pos): MapSector(parent, pos) { } @@ -184,7 +184,7 @@ void ServerMapSector::serialize(std::ostream &os, u8 version) ServerMapSector* ServerMapSector::deSerialize( std::istream &is, - NodeContainer *parent, + Map *parent, v2s16 p2d, core::map & sectors ) @@ -247,7 +247,7 @@ ServerMapSector* ServerMapSector::deSerialize( ClientMapSector */ -ClientMapSector::ClientMapSector(NodeContainer *parent, v2s16 pos): +ClientMapSector::ClientMapSector(Map *parent, v2s16 pos): MapSector(parent, pos) { } diff --git a/src/mapsector.h b/src/mapsector.h index c5a41ca19..44f45d8f0 100644 --- a/src/mapsector.h +++ b/src/mapsector.h @@ -30,7 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include class MapBlock; -class NodeContainer; +class Map; /* This is an Y-wise stack of MapBlocks. @@ -43,7 +43,7 @@ class MapSector { public: - MapSector(NodeContainer *parent, v2s16 pos); + MapSector(Map *parent, v2s16 pos); virtual ~MapSector(); virtual u32 getId() const = 0; @@ -73,7 +73,7 @@ protected: // The pile of MapBlocks core::map m_blocks; - NodeContainer *m_parent; + Map *m_parent; // Position on parent (in MapBlock widths) v2s16 m_pos; @@ -92,7 +92,7 @@ protected: class ServerMapSector : public MapSector { public: - ServerMapSector(NodeContainer *parent, v2s16 pos); + ServerMapSector(Map *parent, v2s16 pos); ~ServerMapSector(); u32 getId() const @@ -109,7 +109,7 @@ public: static ServerMapSector* deSerialize( std::istream &is, - NodeContainer *parent, + Map *parent, v2s16 p2d, core::map & sectors ); @@ -121,7 +121,7 @@ private: class ClientMapSector : public MapSector { public: - ClientMapSector(NodeContainer *parent, v2s16 pos); + ClientMapSector(Map *parent, v2s16 pos); ~ClientMapSector(); u32 getId() const diff --git a/src/test.cpp b/src/test.cpp index 9ea402b6f..7d71552a8 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -340,6 +340,12 @@ struct TestVoxelManipulator } }; +/* + NOTE: These tests became non-working then NodeContainer was removed. + These should be redone, utilizing some kind of a virtual + interface for Map (IMap would be fine). +*/ +#if 0 struct TestMapBlock { class TC : public NodeContainer @@ -663,6 +669,7 @@ struct TestMapSector } }; +#endif struct TestSocket { @@ -1029,8 +1036,8 @@ void run_tests() TEST(TestCompress); TEST(TestMapNode); TEST(TestVoxelManipulator); - TEST(TestMapBlock); - TEST(TestMapSector); + //TEST(TestMapBlock); + //TEST(TestMapSector); if(INTERNET_SIMULATOR == false){ TEST(TestSocket); dout_con<<"=== BEGIN RUNNING UNIT TESTS FOR CONNECTION ==="< Date: Sun, 26 Jun 2011 02:34:36 +0300 Subject: even more code refactoring --- src/client.cpp | 142 ++++++++++++++++++++++++++++++++++++++++++++++--- src/client.h | 118 ++++------------------------------------ src/environment.cpp | 2 +- src/game.cpp | 6 ++- src/main.cpp | 2 - src/map.cpp | 84 +++++++++++++++++++---------- src/map.h | 68 +++-------------------- src/mapblockobject.cpp | 1 + src/mapchunk.h | 6 +++ src/server.cpp | 1 + 10 files changed, 221 insertions(+), 209 deletions(-) (limited to 'src/map.cpp') diff --git a/src/client.cpp b/src/client.cpp index f97acfd43..6d0e6860c 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -5,7 +5,7 @@ Copyright (C) 2010 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. +MeshUpdateQueue::(at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -26,6 +26,104 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "porting.h" #include "mapsector.h" +#include "mapblock_mesh.h" +#include "mapblock.h" + +/* + QueuedMeshUpdate +*/ + +QueuedMeshUpdate::QueuedMeshUpdate(): + p(-1337,-1337,-1337), + data(NULL), + ack_block_to_server(false) +{ +} + +QueuedMeshUpdate::~QueuedMeshUpdate() +{ + if(data) + delete data; +} + +/* + MeshUpdateQueue +*/ + +MeshUpdateQueue::MeshUpdateQueue() +{ + m_mutex.Init(); +} + +MeshUpdateQueue::~MeshUpdateQueue() +{ + JMutexAutoLock lock(m_mutex); + + core::list::Iterator i; + for(i=m_queue.begin(); i!=m_queue.end(); i++) + { + QueuedMeshUpdate *q = *i; + delete q; + } +} + +/* + peer_id=0 adds with nobody to send to +*/ +void MeshUpdateQueue::addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_server) +{ + DSTACK(__FUNCTION_NAME); + + assert(data); + + JMutexAutoLock lock(m_mutex); + + /* + Find if block is already in queue. + If it is, update the data and quit. + */ + core::list::Iterator i; + for(i=m_queue.begin(); i!=m_queue.end(); i++) + { + QueuedMeshUpdate *q = *i; + if(q->p == p) + { + if(q->data) + delete q->data; + q->data = data; + if(ack_block_to_server) + q->ack_block_to_server = true; + return; + } + } + + /* + Add the block + */ + QueuedMeshUpdate *q = new QueuedMeshUpdate; + q->p = p; + q->data = data; + q->ack_block_to_server = ack_block_to_server; + m_queue.push_back(q); +} + +// Returned pointer must be deleted +// Returns NULL if queue is empty +QueuedMeshUpdate * MeshUpdateQueue::pop() +{ + JMutexAutoLock lock(m_mutex); + + core::list::Iterator i = m_queue.begin(); + if(i == m_queue.end()) + return NULL; + QueuedMeshUpdate *q = *i; + m_queue.erase(i); + return q; +} + +/* + MeshUpdateThread +*/ void * MeshUpdateThread::Thread() { @@ -1736,7 +1834,7 @@ void Client::addNode(v3s16 p, MapNode n) try { - TimeTaker timer3("Client::addNode(): addNodeAndUpdate"); + //TimeTaker timer3("Client::addNode(): addNodeAndUpdate"); m_env.getMap().addNodeAndUpdate(p, n, modified_blocks); } catch(InvalidPositionException &e) @@ -1964,12 +2062,6 @@ void Client::printDebugInfo(std::ostream &os) <= 0 && m_daynight_i < DAYNIGHT_CACHE_COUNT); - return m_daynight_i; -}*/ - u32 Client::getDayNightRatio() { //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out @@ -1983,6 +2075,40 @@ u16 Client::getHP() return player->hp; } +void Client::setTempMod(v3s16 p, NodeMod mod) +{ + //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out + assert(m_env.getMap().mapType() == MAPTYPE_CLIENT); + + core::map affected_blocks; + ((ClientMap&)m_env.getMap()).setTempMod(p, mod, + &affected_blocks); + + for(core::map::Iterator + i = affected_blocks.getIterator(); + i.atEnd() == false; i++) + { + i.getNode()->getValue()->updateMesh(m_env.getDayNightRatio()); + } +} + +void Client::clearTempMod(v3s16 p) +{ + //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out + assert(m_env.getMap().mapType() == MAPTYPE_CLIENT); + + core::map affected_blocks; + ((ClientMap&)m_env.getMap()).clearTempMod(p, + &affected_blocks); + + for(core::map::Iterator + i = affected_blocks.getIterator(); + i.atEnd() == false; i++) + { + i.getNode()->getValue()->updateMesh(m_env.getDayNightRatio()); + } +} + void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server) { /*dstream<<"Client::addUpdateMeshTask(): " diff --git a/src/client.h b/src/client.h index a1b1c66b4..442eaef5d 100644 --- a/src/client.h +++ b/src/client.h @@ -29,6 +29,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "clientobject.h" +struct MeshMakeData; + class ClientNotReadyException : public BaseException { public: @@ -43,18 +45,8 @@ struct QueuedMeshUpdate MeshMakeData *data; bool ack_block_to_server; - QueuedMeshUpdate(): - p(-1337,-1337,-1337), - data(NULL), - ack_block_to_server(false) - { - } - - ~QueuedMeshUpdate() - { - if(data) - delete data; - } + QueuedMeshUpdate(); + ~QueuedMeshUpdate(); }; /* @@ -63,76 +55,18 @@ struct QueuedMeshUpdate class MeshUpdateQueue { public: - MeshUpdateQueue() - { - m_mutex.Init(); - } - - ~MeshUpdateQueue() - { - JMutexAutoLock lock(m_mutex); + MeshUpdateQueue(); - core::list::Iterator i; - for(i=m_queue.begin(); i!=m_queue.end(); i++) - { - QueuedMeshUpdate *q = *i; - delete q; - } - } + ~MeshUpdateQueue(); /* peer_id=0 adds with nobody to send to */ - void addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_server) - { - DSTACK(__FUNCTION_NAME); - - assert(data); - - JMutexAutoLock lock(m_mutex); - - /* - Find if block is already in queue. - If it is, update the data and quit. - */ - core::list::Iterator i; - for(i=m_queue.begin(); i!=m_queue.end(); i++) - { - QueuedMeshUpdate *q = *i; - if(q->p == p) - { - if(q->data) - delete q->data; - q->data = data; - if(ack_block_to_server) - q->ack_block_to_server = true; - return; - } - } - - /* - Add the block - */ - QueuedMeshUpdate *q = new QueuedMeshUpdate; - q->p = p; - q->data = data; - q->ack_block_to_server = ack_block_to_server; - m_queue.push_back(q); - } + void addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_server); // Returned pointer must be deleted // Returns NULL if queue is empty - QueuedMeshUpdate * pop() - { - JMutexAutoLock lock(m_mutex); - - core::list::Iterator i = m_queue.begin(); - if(i == m_queue.end()) - return NULL; - QueuedMeshUpdate *q = *i; - m_queue.erase(i); - return q; - } + QueuedMeshUpdate * pop(); u32 size() { @@ -309,40 +243,8 @@ public: u16 getHP(); - //void updateSomeExpiredMeshes(); - - void setTempMod(v3s16 p, NodeMod mod) - { - //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out - assert(m_env.getMap().mapType() == MAPTYPE_CLIENT); - - core::map affected_blocks; - ((ClientMap&)m_env.getMap()).setTempMod(p, mod, - &affected_blocks); - - for(core::map::Iterator - i = affected_blocks.getIterator(); - i.atEnd() == false; i++) - { - i.getNode()->getValue()->updateMesh(m_env.getDayNightRatio()); - } - } - void clearTempMod(v3s16 p) - { - //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out - assert(m_env.getMap().mapType() == MAPTYPE_CLIENT); - - core::map affected_blocks; - ((ClientMap&)m_env.getMap()).clearTempMod(p, - &affected_blocks); - - for(core::map::Iterator - i = affected_blocks.getIterator(); - i.atEnd() == false; i++) - { - i.getNode()->getValue()->updateMesh(m_env.getDayNightRatio()); - } - } + void setTempMod(v3s16 p, NodeMod mod); + void clearTempMod(v3s16 p); float getAvgRtt() { diff --git a/src/environment.cpp b/src/environment.cpp index cd255341f..6a7c8478e 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "porting.h" #include "collision.h" #include "content_mapnode.h" - +#include "mapblock.h" Environment::Environment(): m_time_of_day(9000) diff --git a/src/game.cpp b/src/game.cpp index f3fac0c84..337879cb8 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -30,8 +30,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "clouds.h" #include "keycode.h" #include "farmesh.h" +#include "mapblock.h" -// TODO: Move content-aware stuff to separate file +/* + TODO: Move content-aware stuff to separate file by adding properties + and virtual interfaces +*/ #include "content_mapnode.h" #include "content_nodemeta.h" diff --git a/src/main.cpp b/src/main.cpp index 41da310f4..9c7cf2e28 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -238,8 +238,6 @@ FIXME: The new optimized map sending doesn't sometimes send enough blocks from big caves and such FIXME: Block send distance configuration does not take effect for some reason -TODO: Map saving should be done by EmergeThread - SUGG: Map unloading based on sector reference is not very good, it keeps unnecessary stuff in memory. I guess. Investigate this. diff --git a/src/map.cpp b/src/map.cpp index d8cc34ca7..3164028b7 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serverobject.h" #include "content_mapnode.h" #include "mapgen.h" +#include "nodemetadata.h" extern "C" { #include "sqlite3.h" @@ -141,19 +142,6 @@ MapBlock * Map::getBlockNoCreate(v3s16 p3d) return block; } - -/*MapBlock * Map::getBlockCreate(v3s16 p3d) -{ - v2s16 p2d(p3d.X, p3d.Z); - MapSector * sector = getSectorCreate(p2d); - assert(sector); - MapBlock *block = sector->getBlockNoCreate(p3d.Y); - if(block) - return block; - block = sector->createBlankBlock(p3d.Y); - return block; -}*/ - bool Map::isNodeUnderground(v3s16 p) { v3s16 blockpos = getNodeBlockPos(p); @@ -167,6 +155,45 @@ bool Map::isNodeUnderground(v3s16 p) } } +bool Map::isValidPosition(v3s16 p) +{ + v3s16 blockpos = getNodeBlockPos(p); + MapBlock *block = getBlockNoCreate(blockpos); + return (block != NULL); +} + +// Returns a CONTENT_IGNORE node if not found +MapNode Map::getNodeNoEx(v3s16 p) +{ + v3s16 blockpos = getNodeBlockPos(p); + MapBlock *block = getBlockNoCreateNoEx(blockpos); + if(block == NULL) + return MapNode(CONTENT_IGNORE); + v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; + return block->getNodeNoCheck(relpos); +} + +// throws InvalidPositionException if not found +MapNode Map::getNode(v3s16 p) +{ + v3s16 blockpos = getNodeBlockPos(p); + MapBlock *block = getBlockNoCreateNoEx(blockpos); + if(block == NULL) + throw InvalidPositionException(); + v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; + return block->getNodeNoCheck(relpos); +} + +// throws InvalidPositionException if not found +void Map::setNode(v3s16 p, MapNode & n) +{ + v3s16 blockpos = getNodeBlockPos(p); + MapBlock *block = getBlockNoCreate(blockpos); + v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; + block->setNodeNoCheck(relpos, n); +} + + /* Goes recursively through the neighbours of the node. @@ -2096,22 +2123,25 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data, /* Update lighting */ - - core::map lighting_update_blocks; - // Center block - lighting_update_blocks.insert(block->getPos(), block); -#if 0 - // All modified blocks - for(core::map::Iterator - i = changed_blocks.getIterator(); - i.atEnd() == false; i++) { - lighting_update_blocks.insert(i.getNode()->getKey(), - i.getNode()->getValue()); + TimeTaker t("finishBlockMake lighting update"); + + core::map lighting_update_blocks; + // Center block + lighting_update_blocks.insert(block->getPos(), block); + #if 0 + // All modified blocks + for(core::map::Iterator + i = changed_blocks.getIterator(); + i.atEnd() == false; i++) + { + lighting_update_blocks.insert(i.getNode()->getKey(), + i.getNode()->getValue()); + } + #endif + updateLighting(lighting_update_blocks, changed_blocks); } -#endif - updateLighting(lighting_update_blocks, changed_blocks); - + /* Add random objects to block */ diff --git a/src/map.h b/src/map.h index 406b1bc84..c64f8cbdb 100644 --- a/src/map.h +++ b/src/map.h @@ -25,27 +25,17 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include -#ifdef _WIN32 - #include - #define sleep_s(x) Sleep((x*1000)) -#else - #include - #define sleep_s(x) sleep(x) -#endif - #include "common_irrlicht.h" #include "mapnode.h" -#include "mapblock.h" +#include "mapblock_nodemod.h" #include "constants.h" #include "voxel.h" -#include "mapchunk.h" -#include "nodemetadata.h" class MapSector; class ServerMapSector; class ClientMapSector; - class MapBlock; +class NodeMetadata; namespace mapgen{ struct BlockMakeData; @@ -161,66 +151,20 @@ public: MapBlock * getBlockNoCreate(v3s16 p); // Returns NULL if not found MapBlock * getBlockNoCreateNoEx(v3s16 p); - // Gets an existing block or creates an empty one - //MapBlock * getBlockCreate(v3s16 p); // Returns InvalidPositionException if not found bool isNodeUnderground(v3s16 p); - // virtual from NodeContainer - bool isValidPosition(v3s16 p) - { - v3s16 blockpos = getNodeBlockPos(p); - MapBlock *blockref; - try{ - blockref = getBlockNoCreate(blockpos); - } - catch(InvalidPositionException &e) - { - return false; - } - return true; - /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; - bool is_valid = blockref->isValidPosition(relpos); - return is_valid;*/ - } + bool isValidPosition(v3s16 p); - // virtual from NodeContainer // throws InvalidPositionException if not found - MapNode getNode(v3s16 p) - { - v3s16 blockpos = getNodeBlockPos(p); - MapBlock * blockref = getBlockNoCreate(blockpos); - v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; + MapNode getNode(v3s16 p); - return blockref->getNodeNoCheck(relpos); - } - - // virtual from NodeContainer // throws InvalidPositionException if not found - void setNode(v3s16 p, MapNode & n) - { - v3s16 blockpos = getNodeBlockPos(p); - MapBlock * blockref = getBlockNoCreate(blockpos); - v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; - blockref->setNodeNoCheck(relpos, n); - } + void setNode(v3s16 p, MapNode & n); // Returns a CONTENT_IGNORE node if not found - MapNode getNodeNoEx(v3s16 p) - { - try{ - v3s16 blockpos = getNodeBlockPos(p); - MapBlock * blockref = getBlockNoCreate(blockpos); - v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; - - return blockref->getNodeNoCheck(relpos); - } - catch(InvalidPositionException &e) - { - return MapNode(CONTENT_IGNORE); - } - } + MapNode getNodeNoEx(v3s16 p); void unspreadLight(enum LightBank bank, core::map & from_nodes, diff --git a/src/mapblockobject.cpp b/src/mapblockobject.cpp index 51ac4c66b..ab1c20267 100644 --- a/src/mapblockobject.cpp +++ b/src/mapblockobject.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "map.h" #include "inventory.h" #include "utility.h" +#include "mapblock.h" /* MapBlockObject diff --git a/src/mapchunk.h b/src/mapchunk.h index 9860abad0..98df7ce66 100644 --- a/src/mapchunk.h +++ b/src/mapchunk.h @@ -20,6 +20,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef MAPCHUNK_HEADER #define MAPCHUNK_HEADER +/* + TODO: Remove +*/ + +#if 0 /* MapChunk contains map-generation-time metadata for an area of some MapSectors. (something like 16x16) @@ -66,6 +71,7 @@ private: u8 m_generation_level; bool m_modified; }; +#endif #endif diff --git a/src/server.cpp b/src/server.cpp index cf8b57773..671c3bd4e 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_mapnode.h" #include "content_craft.h" #include "content_nodemeta.h" +#include "mapblock.h" #define BLOCK_EMERGE_FLAG_FROMDISK (1<<0) -- cgit v1.2.3 From 91cfbe2891a3fbec2aac019ccfba74b667d94fc4 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sun, 26 Jun 2011 15:48:56 +0300 Subject: reorganized a lot of stuff and modified mapgen and objects slightly while doing it --- .hgignore | 5 + data/oerkki1.png | Bin 212 -> 250 bytes data/oerkki1_damaged.png | Bin 0 -> 341 bytes src/CMakeLists.txt | 2 + src/activeobject.h | 9 +- src/clientobject.cpp | 673 ----------------------------------------- src/clientobject.h | 217 ------------- src/collision.cpp | 54 ++++ src/collision.h | 7 +- src/content_cao.cpp | 753 ++++++++++++++++++++++++++++++++++++++++++++++ src/content_cao.h | 248 +++++++++++++++ src/content_inventory.cpp | 3 +- src/content_object.h | 29 ++ src/content_sao.cpp | 694 ++++++++++++++++++++++++++++++++++++++++++ src/content_sao.h | 118 ++++++++ src/environment.cpp | 36 ++- src/environment.h | 11 +- src/game.cpp | 12 +- src/inventory.cpp | 1 + src/map.cpp | 10 +- src/mapgen.cpp | 96 +++++- src/server.cpp | 7 +- src/serverobject.cpp | 598 ------------------------------------ src/serverobject.h | 102 +------ 24 files changed, 2059 insertions(+), 1626 deletions(-) create mode 100644 data/oerkki1_damaged.png create mode 100644 src/content_cao.cpp create mode 100644 src/content_cao.h create mode 100644 src/content_object.h create mode 100644 src/content_sao.cpp create mode 100644 src/content_sao.h (limited to 'src/map.cpp') diff --git a/.hgignore b/.hgignore index 0870e3c67..964b22bd9 100644 --- a/.hgignore +++ b/.hgignore @@ -9,7 +9,12 @@ src/jthread/CMakeFiles/* src/jthread/Makefile src/jthread/cmake_config.h src/jthread/cmake_install.cmake +src/.*.swp +src/sqlite/libsqlite3.a +src/session.vim +util/uloste.png minetest.conf +debug.txt bin/ CMakeCache.txt CPackConfig.cmake diff --git a/data/oerkki1.png b/data/oerkki1.png index c32fb99db..33cbac9e7 100644 Binary files a/data/oerkki1.png and b/data/oerkki1.png differ diff --git a/data/oerkki1_damaged.png b/data/oerkki1_damaged.png new file mode 100644 index 000000000..9b777387c Binary files /dev/null and b/data/oerkki1_damaged.png differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 73a960ecc..847269456 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -61,6 +61,7 @@ configure_file( ) set(common_SRCS + content_sao.cpp mapgen.cpp content_inventory.cpp content_nodemeta.cpp @@ -102,6 +103,7 @@ set(common_SRCS # Client sources set(minetest_SRCS ${common_SRCS} + content_cao.cpp mapblock_mesh.cpp farmesh.cpp keycode.cpp diff --git a/src/activeobject.h b/src/activeobject.h index 382f7f798..09ee23a14 100644 --- a/src/activeobject.h +++ b/src/activeobject.h @@ -23,6 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common_irrlicht.h" #include +#define ACTIVEOBJECT_TYPE_INVALID 0 +// Other types are defined in content_object.h + struct ActiveObjectMessage { ActiveObjectMessage(u16 id_, bool reliable_=true, std::string data_=""): @@ -36,12 +39,6 @@ struct ActiveObjectMessage std::string datastring; }; -#define ACTIVEOBJECT_TYPE_INVALID 0 -#define ACTIVEOBJECT_TYPE_TEST 1 -#define ACTIVEOBJECT_TYPE_ITEM 2 -#define ACTIVEOBJECT_TYPE_RAT 3 -#define ACTIVEOBJECT_TYPE_OERKKI1 4 - /* Parent class for ServerActiveObject and ClientActiveObject */ diff --git a/src/clientobject.cpp b/src/clientobject.cpp index 402535ffc..787efef29 100644 --- a/src/clientobject.cpp +++ b/src/clientobject.cpp @@ -21,9 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "debug.h" #include "porting.h" #include "constants.h" -#include "utility.h" -#include "environment.h" -#include "tile.h" /* ClientActiveObject @@ -68,674 +65,4 @@ void ClientActiveObject::registerType(u16 type, Factory f) m_types.insert(type, f); } -/* - TestCAO -*/ - -// Prototype -TestCAO proto_TestCAO; - -TestCAO::TestCAO(): - ClientActiveObject(0), - m_node(NULL), - m_position(v3f(0,10*BS,0)) -{ - ClientActiveObject::registerType(getType(), create); -} - -TestCAO::~TestCAO() -{ -} - -ClientActiveObject* TestCAO::create() -{ - return new TestCAO(); -} - -void TestCAO::addToScene(scene::ISceneManager *smgr) -{ - if(m_node != NULL) - return; - - video::IVideoDriver* driver = smgr->getVideoDriver(); - - scene::SMesh *mesh = new scene::SMesh(); - scene::IMeshBuffer *buf = new scene::SMeshBuffer(); - video::SColor c(255,255,255,255); - video::S3DVertex vertices[4] = - { - video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1), - video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1), - video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0), - video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0), - }; - u16 indices[] = {0,1,2,2,3,0}; - buf->append(vertices, 4, indices, 6); - // Set material - buf->getMaterial().setFlag(video::EMF_LIGHTING, false); - buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false); - buf->getMaterial().setTexture - (0, driver->getTexture(getTexturePath("rat.png").c_str())); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - // Add to mesh - mesh->addMeshBuffer(buf); - buf->drop(); - m_node = smgr->addMeshSceneNode(mesh, NULL); - mesh->drop(); - updateNodePos(); -} - -void TestCAO::removeFromScene() -{ - if(m_node == NULL) - return; - - m_node->remove(); - m_node = NULL; -} - -void TestCAO::updateLight(u8 light_at_pos) -{ -} - -v3s16 TestCAO::getLightPosition() -{ - return floatToInt(m_position, BS); -} - -void TestCAO::updateNodePos() -{ - if(m_node == NULL) - return; - - m_node->setPosition(m_position); - //m_node->setRotation(v3f(0, 45, 0)); -} - -void TestCAO::step(float dtime, ClientEnvironment *env) -{ - if(m_node) - { - v3f rot = m_node->getRotation(); - //dstream<<"dtime="<>cmd; - if(cmd == 0) - { - v3f newpos; - is>>newpos.X; - is>>newpos.Y; - is>>newpos.Z; - m_position = newpos; - updateNodePos(); - } -} - -/* - ItemCAO -*/ - -#include "inventory.h" - -// Prototype -ItemCAO proto_ItemCAO; - -ItemCAO::ItemCAO(): - ClientActiveObject(0), - m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.), - m_node(NULL), - m_position(v3f(0,10*BS,0)) -{ - ClientActiveObject::registerType(getType(), create); -} - -ItemCAO::~ItemCAO() -{ -} - -ClientActiveObject* ItemCAO::create() -{ - return new ItemCAO(); -} - -void ItemCAO::addToScene(scene::ISceneManager *smgr) -{ - if(m_node != NULL) - return; - - video::IVideoDriver* driver = smgr->getVideoDriver(); - - scene::SMesh *mesh = new scene::SMesh(); - scene::IMeshBuffer *buf = new scene::SMeshBuffer(); - video::SColor c(255,255,255,255); - video::S3DVertex vertices[4] = - { - /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1), - video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1), - video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0), - video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/ - video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1), - video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1), - video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0), - video::S3DVertex(BS/3.,0+BS*2./3.,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); - // Initialize with the stick texture - buf->getMaterial().setTexture - (0, driver->getTexture(getTexturePath("stick.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 ItemCAO::removeFromScene() -{ - if(m_node == NULL) - return; - - m_node->remove(); - m_node = NULL; -} - -void ItemCAO::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; jgetMeshBuffer(j); - video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); - u16 vc = buf->getVertexCount(); - for(u16 i=0; isetPosition(m_position); -} - -void ItemCAO::step(float dtime, ClientEnvironment *env) -{ - if(m_node) - { - /*v3f rot = m_node->getRotation(); - rot.Y += dtime * 120; - m_node->setRotation(rot);*/ - LocalPlayer *player = env->getLocalPlayer(); - assert(player); - v3f rot = m_node->getRotation(); - rot.Y = 180.0 - (player->getYaw()); - m_node->setRotation(rot); - } -} - -void ItemCAO::processMessage(const std::string &data) -{ - dstream<<"ItemCAO: Got message"<getMesh(); - - if(mesh == NULL) - return; - - scene::IMeshBuffer *buf = mesh->getMeshBuffer(0); - - if(buf == NULL) - return; - - // Create an inventory item to see what is its image - std::istringstream is(m_inventorystring, std::ios_base::binary); - video::ITexture *texture = NULL; - try{ - InventoryItem *item = NULL; - item = InventoryItem::deSerialize(is); - dstream<<__FUNCTION_NAME<<": m_inventorystring=\"" - < item="<getImage(); - delete item; - } - } - catch(SerializationError &e) - { - dstream<<"WARNING: "<<__FUNCTION_NAME - <<": error deSerializing inventorystring \"" - <getMaterial().setTexture(0, texture); - -} - -/* - RatCAO -*/ - -#include "inventory.h" - -// Prototype -RatCAO proto_RatCAO; - -RatCAO::RatCAO(): - 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); -} - -RatCAO::~RatCAO() -{ -} - -ClientActiveObject* RatCAO::create() -{ - return new RatCAO(); -} - -void RatCAO::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(getTexturePath("rat.png").c_str())); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - // Add to mesh - mesh->addMeshBuffer(buf); - buf->drop(); - m_node = smgr->addMeshSceneNode(mesh, NULL); - mesh->drop(); - // 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 RatCAO::removeFromScene() -{ - if(m_node == NULL) - return; - - m_node->remove(); - m_node = NULL; -} - -void RatCAO::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; jgetMeshBuffer(j); - video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); - u16 vc = buf->getVertexCount(); - for(u16 i=0; isetPosition(m_position); - m_node->setPosition(pos_translator.vect_show); - - v3f rot = m_node->getRotation(); - rot.Y = 180.0 - m_yaw; - m_node->setRotation(rot); -} - -void RatCAO::step(float dtime, ClientEnvironment *env) -{ - pos_translator.translate(dtime); - updateNodePos(); -} - -void RatCAO::processMessage(const std::string &data) -{ - //dstream<<"RatCAO: Got message"<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(getTexturePath("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; - - if(light_at_pos <= 2) - { - m_node->setVisible(false); - return; - } - - m_node->setVisible(true); - - 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; jgetMeshBuffer(j); - video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); - u16 vc = buf->getVertexCount(); - for(u16 i=0; isetPosition(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(m_position.Y - playerpos.Y) < 3.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"< 1.0) - anim_time = anim_time_counter; - else - anim_time = anim_time * 0.9 + anim_time_counter * 0.1; - anim_time_counter = 0; - anim_counter = 0; - } - - void translate(f32 dtime) - { - anim_time_counter = anim_time_counter + dtime; - anim_counter = anim_counter + dtime; - v3f vect_move = vect_aim - vect_old; - f32 moveratio = 1.0; - if(anim_time > 0.001) - moveratio = anim_time_counter / anim_time; - // Move a bit less than should, to avoid oscillation - moveratio = moveratio * 0.8; - if(moveratio > 1.5) - moveratio = 1.5; - vect_show = vect_old + vect_move * moveratio; - } -}; - class ClientEnvironment; class ClientActiveObject : public ActiveObject @@ -153,164 +95,5 @@ struct DistanceSortedActiveObject } }; -/* - TestCAO -*/ - -class TestCAO : public ClientActiveObject -{ -public: - TestCAO(); - virtual ~TestCAO(); - - u8 getType() const - { - return ACTIVEOBJECT_TYPE_TEST; - } - - 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); - -private: - scene::IMeshSceneNode *m_node; - v3f m_position; -}; - -/* - ItemCAO -*/ - -class ItemCAO : public ClientActiveObject -{ -public: - ItemCAO(); - virtual ~ItemCAO(); - - u8 getType() const - { - return ACTIVEOBJECT_TYPE_ITEM; - } - - 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* getSelectionBox() - {return &m_selection_box;} - v3f getPosition() - {return m_position;} - -private: - core::aabbox3d m_selection_box; - scene::IMeshSceneNode *m_node; - v3f m_position; - std::string m_inventorystring; -}; - -/* - RatCAO -*/ - -class RatCAO : public ClientActiveObject -{ -public: - RatCAO(); - virtual ~RatCAO(); - - u8 getType() const - { - return ACTIVEOBJECT_TYPE_RAT; - } - - 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* getSelectionBox() - {return &m_selection_box;} - v3f getPosition() - {return m_position;} - -private: - core::aabbox3d m_selection_box; - scene::IMeshSceneNode *m_node; - v3f m_position; - float m_yaw; - 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* getSelectionBox() - {return &m_selection_box;} - v3f getPosition() - {return pos_translator.vect_show;} - //{return m_position;} - -private: - IntervalLimiter m_attack_interval; - core::aabbox3d m_selection_box; - scene::IMeshSceneNode *m_node; - v3f m_position; - float m_yaw; - SmoothTranslator pos_translator; -}; - #endif diff --git a/src/collision.cpp b/src/collision.cpp index 63186a84a..01d546284 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -182,4 +182,58 @@ collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d, return result; } +collisionMoveResult collisionMovePrecise(Map *map, f32 pos_max_d, + const core::aabbox3d &box_0, + f32 dtime, v3f &pos_f, v3f &speed_f) +{ + collisionMoveResult final_result; + + // Maximum time increment (for collision detection etc) + // time = distance / speed + f32 dtime_max_increment = pos_max_d / speed_f.getLength(); + + // Maximum time increment is 10ms or lower + if(dtime_max_increment > 0.01) + dtime_max_increment = 0.01; + + // Don't allow overly huge dtime + if(dtime > 2.0) + dtime = 2.0; + + f32 dtime_downcount = dtime; + + u32 loopcount = 0; + do + { + loopcount++; + + f32 dtime_part; + if(dtime_downcount > dtime_max_increment) + { + dtime_part = dtime_max_increment; + dtime_downcount -= dtime_part; + } + else + { + dtime_part = dtime_downcount; + /* + Setting this to 0 (no -=dtime_part) disables an infinite loop + when dtime_part is so small that dtime_downcount -= dtime_part + does nothing + */ + dtime_downcount = 0; + } + + collisionMoveResult result = collisionMoveSimple(map, pos_max_d, + box_0, dtime_part, pos_f, speed_f); + + if(result.touching_ground) + final_result.touching_ground = true; + } + while(dtime_downcount > 0.001); + + + return final_result; +} + diff --git a/src/collision.h b/src/collision.h index 9c913c6a9..6d167bb7b 100644 --- a/src/collision.h +++ b/src/collision.h @@ -33,10 +33,15 @@ struct collisionMoveResult {} }; +// Moves using a single iteration; speed should not exceed pos_max_d/dtime collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d, const core::aabbox3d &box_0, f32 dtime, v3f &pos_f, v3f &speed_f); -//{return collisionMoveResult();} + +// Moves using as many iterations as needed +collisionMoveResult collisionMovePrecise(Map *map, f32 pos_max_d, + const core::aabbox3d &box_0, + f32 dtime, v3f &pos_f, v3f &speed_f); enum CollisionType { diff --git a/src/content_cao.cpp b/src/content_cao.cpp new file mode 100644 index 000000000..ab20f1a95 --- /dev/null +++ b/src/content_cao.cpp @@ -0,0 +1,753 @@ +/* +Minetest-c55 +Copyright (C) 2010-2011 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "content_cao.h" +#include "tile.h" +#include "environment.h" + +/* + TestCAO +*/ + +// Prototype +TestCAO proto_TestCAO; + +TestCAO::TestCAO(): + ClientActiveObject(0), + m_node(NULL), + m_position(v3f(0,10*BS,0)) +{ + ClientActiveObject::registerType(getType(), create); +} + +TestCAO::~TestCAO() +{ +} + +ClientActiveObject* TestCAO::create() +{ + return new TestCAO(); +} + +void TestCAO::addToScene(scene::ISceneManager *smgr) +{ + if(m_node != NULL) + return; + + video::IVideoDriver* driver = smgr->getVideoDriver(); + + scene::SMesh *mesh = new scene::SMesh(); + scene::IMeshBuffer *buf = new scene::SMeshBuffer(); + video::SColor c(255,255,255,255); + video::S3DVertex vertices[4] = + { + video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1), + video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1), + video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0), + video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0), + }; + u16 indices[] = {0,1,2,2,3,0}; + buf->append(vertices, 4, indices, 6); + // Set material + buf->getMaterial().setFlag(video::EMF_LIGHTING, false); + buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false); + buf->getMaterial().setTexture + (0, driver->getTexture(getTexturePath("rat.png").c_str())); + buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); + buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); + buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + // Add to mesh + mesh->addMeshBuffer(buf); + buf->drop(); + m_node = smgr->addMeshSceneNode(mesh, NULL); + mesh->drop(); + updateNodePos(); +} + +void TestCAO::removeFromScene() +{ + if(m_node == NULL) + return; + + m_node->remove(); + m_node = NULL; +} + +void TestCAO::updateLight(u8 light_at_pos) +{ +} + +v3s16 TestCAO::getLightPosition() +{ + return floatToInt(m_position, BS); +} + +void TestCAO::updateNodePos() +{ + if(m_node == NULL) + return; + + m_node->setPosition(m_position); + //m_node->setRotation(v3f(0, 45, 0)); +} + +void TestCAO::step(float dtime, ClientEnvironment *env) +{ + if(m_node) + { + v3f rot = m_node->getRotation(); + //dstream<<"dtime="<>cmd; + if(cmd == 0) + { + v3f newpos; + is>>newpos.X; + is>>newpos.Y; + is>>newpos.Z; + m_position = newpos; + updateNodePos(); + } +} + +/* + ItemCAO +*/ + +#include "inventory.h" + +// Prototype +ItemCAO proto_ItemCAO; + +ItemCAO::ItemCAO(): + ClientActiveObject(0), + m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.), + m_node(NULL), + m_position(v3f(0,10*BS,0)) +{ + ClientActiveObject::registerType(getType(), create); +} + +ItemCAO::~ItemCAO() +{ +} + +ClientActiveObject* ItemCAO::create() +{ + return new ItemCAO(); +} + +void ItemCAO::addToScene(scene::ISceneManager *smgr) +{ + if(m_node != NULL) + return; + + video::IVideoDriver* driver = smgr->getVideoDriver(); + + scene::SMesh *mesh = new scene::SMesh(); + scene::IMeshBuffer *buf = new scene::SMeshBuffer(); + video::SColor c(255,255,255,255); + video::S3DVertex vertices[4] = + { + /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1), + video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1), + video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0), + video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/ + video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1), + video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1), + video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0), + video::S3DVertex(BS/3.,0+BS*2./3.,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); + // Initialize with the stick texture + buf->getMaterial().setTexture + (0, driver->getTexture(getTexturePath("stick.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 ItemCAO::removeFromScene() +{ + if(m_node == NULL) + return; + + m_node->remove(); + m_node = NULL; +} + +void ItemCAO::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; jgetMeshBuffer(j); + video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); + u16 vc = buf->getVertexCount(); + for(u16 i=0; isetPosition(m_position); +} + +void ItemCAO::step(float dtime, ClientEnvironment *env) +{ + if(m_node) + { + /*v3f rot = m_node->getRotation(); + rot.Y += dtime * 120; + m_node->setRotation(rot);*/ + LocalPlayer *player = env->getLocalPlayer(); + assert(player); + v3f rot = m_node->getRotation(); + rot.Y = 180.0 - (player->getYaw()); + m_node->setRotation(rot); + } +} + +void ItemCAO::processMessage(const std::string &data) +{ + dstream<<"ItemCAO: Got message"<getMesh(); + + if(mesh == NULL) + return; + + scene::IMeshBuffer *buf = mesh->getMeshBuffer(0); + + if(buf == NULL) + return; + + // Create an inventory item to see what is its image + std::istringstream is(m_inventorystring, std::ios_base::binary); + video::ITexture *texture = NULL; + try{ + InventoryItem *item = NULL; + item = InventoryItem::deSerialize(is); + dstream<<__FUNCTION_NAME<<": m_inventorystring=\"" + < item="<getImage(); + delete item; + } + } + catch(SerializationError &e) + { + dstream<<"WARNING: "<<__FUNCTION_NAME + <<": error deSerializing inventorystring \"" + <getMaterial().setTexture(0, texture); + +} + +/* + RatCAO +*/ + +#include "inventory.h" + +// Prototype +RatCAO proto_RatCAO; + +RatCAO::RatCAO(): + 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); +} + +RatCAO::~RatCAO() +{ +} + +ClientActiveObject* RatCAO::create() +{ + return new RatCAO(); +} + +void RatCAO::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(getTexturePath("rat.png").c_str())); + buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); + buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); + buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + // Add to mesh + mesh->addMeshBuffer(buf); + buf->drop(); + m_node = smgr->addMeshSceneNode(mesh, NULL); + mesh->drop(); + // 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 RatCAO::removeFromScene() +{ + if(m_node == NULL) + return; + + m_node->remove(); + m_node = NULL; +} + +void RatCAO::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; jgetMeshBuffer(j); + video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); + u16 vc = buf->getVertexCount(); + for(u16 i=0; isetPosition(m_position); + m_node->setPosition(pos_translator.vect_show); + + v3f rot = m_node->getRotation(); + rot.Y = 180.0 - m_yaw; + m_node->setRotation(rot); +} + +void RatCAO::step(float dtime, ClientEnvironment *env) +{ + pos_translator.translate(dtime); + updateNodePos(); +} + +void RatCAO::processMessage(const std::string &data) +{ + //dstream<<"RatCAO: Got message"<getVideoDriver(); + + scene::SMesh *mesh = new scene::SMesh(); + scene::IMeshBuffer *buf = new scene::SMeshBuffer(); + video::SColor c(255,255,255,255); + video::S3DVertex vertices[4] = + { + video::S3DVertex(-BS/2-BS,0,0, 0,0,0, c, 0,1), + video::S3DVertex(BS/2+BS,0,0, 0,0,0, c, 1,1), + video::S3DVertex(BS/2+BS,BS*2,0, 0,0,0, c, 1,0), + video::S3DVertex(-BS/2-BS,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(getTexturePath("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; + + if(light_at_pos <= 2) + { + m_node->setVisible(false); + return; + } + + m_node->setVisible(true); + + 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; jgetMeshBuffer(j); + video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); + u16 vc = buf->getVertexCount(); + for(u16 i=0; isetPosition(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(m_position.Y - playerpos.Y) < 3.0*BS && + objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS) + { + if(m_attack_interval.step(dtime, 0.5)) + { + env->damageLocalPlayer(2); + } + } + + if(m_damage_visual_timer > 0) + { + if(!m_damage_texture_enabled) + { + // Enable damage texture + if(m_node) + { + video::IVideoDriver* driver = + m_node->getSceneManager()->getVideoDriver(); + + scene::IMesh *mesh = m_node->getMesh(); + if(mesh == NULL) + return; + + u16 mc = mesh->getMeshBufferCount(); + for(u16 j=0; jgetMeshBuffer(j); + buf->getMaterial().setTexture(0, driver->getTexture( + getTexturePath("oerkki1_damaged.png").c_str())); + } + } + m_damage_texture_enabled = true; + } + m_damage_visual_timer -= dtime; + } + else + { + if(m_damage_texture_enabled) + { + // Disable damage texture + if(m_node) + { + video::IVideoDriver* driver = + m_node->getSceneManager()->getVideoDriver(); + + scene::IMesh *mesh = m_node->getMesh(); + if(mesh == NULL) + return; + + u16 mc = mesh->getMeshBufferCount(); + for(u16 j=0; jgetMeshBuffer(j); + buf->getMaterial().setTexture(0, driver->getTexture( + getTexturePath("oerkki1.png").c_str())); + } + } + m_damage_texture_enabled = false; + } + } +} + +void Oerkki1CAO::processMessage(const std::string &data) +{ + //dstream<<"Oerkki1CAO: Got message"< + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef CONTENT_CAO_HEADER +#define CONTENT_CAO_HEADER + +#include "clientobject.h" +#include "content_object.h" +#include "utility.h" // For IntervalLimiter + +/* + SmoothTranslator +*/ + +struct SmoothTranslator +{ + v3f vect_old; + f32 anim_counter; + f32 anim_time; + f32 anim_time_counter; + v3f vect_show; + v3f vect_aim; + + SmoothTranslator(): + vect_old(0,0,0), + anim_counter(0), + anim_time(0), + anim_time_counter(0), + vect_show(0,0,0), + vect_aim(0,0,0) + {} + + void init(v3f vect) + { + vect_old = vect; + vect_show = vect; + vect_aim = vect; + } + + void update(v3f vect_new) + { + vect_old = vect_show; + vect_aim = vect_new; + if(anim_time < 0.001 || anim_time > 1.0) + anim_time = anim_time_counter; + else + anim_time = anim_time * 0.9 + anim_time_counter * 0.1; + anim_time_counter = 0; + anim_counter = 0; + } + + void translate(f32 dtime) + { + anim_time_counter = anim_time_counter + dtime; + anim_counter = anim_counter + dtime; + v3f vect_move = vect_aim - vect_old; + f32 moveratio = 1.0; + if(anim_time > 0.001) + moveratio = anim_time_counter / anim_time; + // Move a bit less than should, to avoid oscillation + moveratio = moveratio * 0.8; + if(moveratio > 1.5) + moveratio = 1.5; + vect_show = vect_old + vect_move * moveratio; + } +}; + + +/* + TestCAO +*/ + +class TestCAO : public ClientActiveObject +{ +public: + TestCAO(); + virtual ~TestCAO(); + + u8 getType() const + { + return ACTIVEOBJECT_TYPE_TEST; + } + + 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); + +private: + scene::IMeshSceneNode *m_node; + v3f m_position; +}; + +/* + ItemCAO +*/ + +class ItemCAO : public ClientActiveObject +{ +public: + ItemCAO(); + virtual ~ItemCAO(); + + u8 getType() const + { + return ACTIVEOBJECT_TYPE_ITEM; + } + + 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* getSelectionBox() + {return &m_selection_box;} + v3f getPosition() + {return m_position;} + +private: + core::aabbox3d m_selection_box; + scene::IMeshSceneNode *m_node; + v3f m_position; + std::string m_inventorystring; +}; + +/* + RatCAO +*/ + +class RatCAO : public ClientActiveObject +{ +public: + RatCAO(); + virtual ~RatCAO(); + + u8 getType() const + { + return ACTIVEOBJECT_TYPE_RAT; + } + + 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* getSelectionBox() + {return &m_selection_box;} + v3f getPosition() + {return m_position;} + +private: + core::aabbox3d m_selection_box; + scene::IMeshSceneNode *m_node; + v3f m_position; + float m_yaw; + 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* getSelectionBox() + {return &m_selection_box;} + v3f getPosition() + {return pos_translator.vect_show;} + //{return m_position;} + +private: + IntervalLimiter m_attack_interval; + core::aabbox3d m_selection_box; + scene::IMeshSceneNode *m_node; + v3f m_position; + float m_yaw; + SmoothTranslator pos_translator; + float m_damage_visual_timer; + bool m_damage_texture_enabled; +}; + + +#endif + diff --git a/src/content_inventory.cpp b/src/content_inventory.cpp index 3b72b31f1..ac48a6195 100644 --- a/src/content_inventory.cpp +++ b/src/content_inventory.cpp @@ -19,8 +19,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_inventory.h" #include "inventory.h" -#include "serverobject.h" #include "content_mapnode.h" +//#include "serverobject.h" +#include "content_sao.h" bool item_material_is_cookable(u8 content) { diff --git a/src/content_object.h b/src/content_object.h new file mode 100644 index 000000000..ecabd8a38 --- /dev/null +++ b/src/content_object.h @@ -0,0 +1,29 @@ +/* +Minetest-c55 +Copyright (C) 2010-2011 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef CONTENT_OBJECT_HEADER +#define CONTENT_OBJECT_HEADER + +#define ACTIVEOBJECT_TYPE_TEST 1 +#define ACTIVEOBJECT_TYPE_ITEM 2 +#define ACTIVEOBJECT_TYPE_RAT 3 +#define ACTIVEOBJECT_TYPE_OERKKI1 4 + +#endif + diff --git a/src/content_sao.cpp b/src/content_sao.cpp new file mode 100644 index 000000000..fc6f208a0 --- /dev/null +++ b/src/content_sao.cpp @@ -0,0 +1,694 @@ +/* +Minetest-c55 +Copyright (C) 2010-2011 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "content_sao.h" +#include "collision.h" +#include "environment.h" + +/* + TestSAO +*/ + +// Prototype +TestSAO proto_TestSAO(NULL, 0, v3f(0,0,0)); + +TestSAO::TestSAO(ServerEnvironment *env, u16 id, v3f pos): + ServerActiveObject(env, id, pos), + m_timer1(0), + m_age(0) +{ + ServerActiveObject::registerType(getType(), create); +} + +ServerActiveObject* TestSAO::create(ServerEnvironment *env, u16 id, v3f pos, + const std::string &data) +{ + return new TestSAO(env, id, pos); +} + +void TestSAO::step(float dtime, bool send_recommended) +{ + m_age += dtime; + if(m_age > 10) + { + m_removed = true; + return; + } + + m_base_position.Y += dtime * BS * 2; + if(m_base_position.Y > 8*BS) + m_base_position.Y = 2*BS; + + if(send_recommended == false) + return; + + m_timer1 -= dtime; + if(m_timer1 < 0.0) + { + m_timer1 += 0.125; + //dstream<<"TestSAO: id="< box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.); + collisionMoveResult moveresult; + // Apply gravity + m_speed_f += v3f(0, -dtime*9.81*BS, 0); + // 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); + + if(send_recommended == false) + return; + + if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS) + { + setBasePosition(pos_f); + m_last_sent_position = pos_f; + + std::ostringstream os(std::ios::binary); + char buf[6]; + // command (0 = update position) + buf[0] = 0; + os.write(buf, 1); + // pos + writeS32((u8*)buf, m_base_position.X*1000); + os.write(buf, 4); + writeS32((u8*)buf, m_base_position.Y*1000); + os.write(buf, 4); + writeS32((u8*)buf, m_base_position.Z*1000); + os.write(buf, 4); + // create message and add to list + ActiveObjectMessage aom(getId(), false, os.str()); + m_messages_out.push_back(aom); + } +} + +std::string ItemSAO::getClientInitializationData() +{ + std::ostringstream os(std::ios::binary); + char buf[6]; + // version + buf[0] = 0; + os.write(buf, 1); + // pos + writeS32((u8*)buf, m_base_position.X*1000); + os.write(buf, 4); + writeS32((u8*)buf, m_base_position.Y*1000); + os.write(buf, 4); + writeS32((u8*)buf, m_base_position.Z*1000); + os.write(buf, 4); + // inventorystring + os< item="< 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; + // Check connected players + core::list players = m_env->getPlayers(true); + core::list::Iterator i; + for(i = players.begin(); + i != players.end(); i++) + { + Player *player = *i; + v3f playerpos = player->getPosition(); + if(m_base_position.getDistanceFrom(playerpos) < BS*10.0) + { + player_is_close = true; + 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 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; + 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 = wrapDegrees(m_yaw); + } + } + } + + m_oldpos = m_base_position; + + /* + Move it, with collision detection + */ + + core::aabbox3d box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./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()); + m_messages_out.push_back(aom); + } +} + +std::string RatSAO::getClientInitializationData() +{ + std::ostringstream os(std::ios::binary); + // version + writeU8(os, 0); + // pos + writeV3F1000(os, m_base_position); + return os.str(); +} + +std::string RatSAO::getStaticData() +{ + //dstream<<__FUNCTION_NAME< max_increase) + dl = max_increase; + + v3f d = d_wanted.normalize() * dl; + + speed.X += d.X; + speed.Z += d.Z; + speed.Y = target_speed.Y; +} + +// 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; + m_after_jump_timer = 0; +} + +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, 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 > 120) + { + // Die + m_removed = true; + return; + } + + m_after_jump_timer -= dtime; + + v3f old_speed = m_speed_f; + + // Apply gravity + m_speed_f.Y -= dtime*9.81*BS; + + /* + Move around if some player is close + */ + bool player_is_close = false; + bool player_is_too_close = false; + v3f near_player_pos; + // Check connected players + core::list players = m_env->getPlayers(true); + core::list::Iterator i; + for(i = players.begin(); + i != players.end(); i++) + { + Player *player = *i; + v3f playerpos = player->getPosition(); + f32 dist = m_base_position.getDistanceFrom(playerpos); + if(dist < BS*1.45) + { + player_is_too_close = true; + near_player_pos = playerpos; + break; + } + else if(dist < BS*15.0) + { + player_is_close = true; + near_player_pos = playerpos; + } + } + + m_is_active = player_is_close; + + v3f target_speed = m_speed_f; + + if(!player_is_close) + { + target_speed = v3f(0,0,0); + } + else + { + // Move around + + v3f ndir = near_player_pos - m_base_position; + ndir.Y = 0; + ndir.normalize(); + + 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); + + f32 speed = 2*BS; + + if((m_touching_ground || m_after_jump_timer > 0.0) + && !player_is_too_close) + { + v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI)); + target_speed.X = speed * dir.X; + target_speed.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 += 0.2; + // Jump + target_speed.Y = 5.0*BS; + m_after_jump_timer = 1.0; + } + } + + { + 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); + } + } + } + + if((m_speed_f - target_speed).getLength() > BS*4 || player_is_too_close) + accelerate_xz(m_speed_f, target_speed, dtime*BS*8); + else + accelerate_xz(m_speed_f, target_speed, dtime*BS*4); + + m_oldpos = m_base_position; + + /* + Move it, with collision detection + */ + + core::aabbox3d 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 = collisionMovePrecise(&m_env->getMap(), pos_max_d, + box, dtime, pos_f, m_speed_f); + m_touching_ground = moveresult.touching_ground; + + // Do collision damage + float tolerance = BS*12; + float factor = BS*0.5; + v3f speed_diff = old_speed - m_speed_f; + // Increase effect in X and Z + speed_diff.X *= 2; + speed_diff.Z *= 2; + float vel = speed_diff.getLength(); + if(vel > tolerance) + { + f32 damage_f = (vel - tolerance)/BS*factor; + u16 damage = (u16)(damage_f+0.5); + doDamage(damage); + } + + setBasePosition(pos_f); + + if(send_recommended == false && m_speed_f.getLength() < 3.0*BS) + 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()); + m_messages_out.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< + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef CONTENT_SAO_HEADER +#define CONTENT_SAO_HEADER + +#include "serverobject.h" +#include "content_object.h" + +class TestSAO : public ServerActiveObject +{ +public: + TestSAO(ServerEnvironment *env, u16 id, v3f pos); + u8 getType() const + {return ACTIVEOBJECT_TYPE_TEST;} + static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos, + const std::string &data); + void step(float dtime, bool send_recommended); +private: + float m_timer1; + float m_age; +}; + +class ItemSAO : public ServerActiveObject +{ +public: + ItemSAO(ServerEnvironment *env, u16 id, v3f pos, + const std::string inventorystring); + u8 getType() const + {return ACTIVEOBJECT_TYPE_ITEM;} + static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos, + const std::string &data); + void step(float dtime, bool send_recommended); + std::string getClientInitializationData(); + std::string getStaticData(); + InventoryItem* createInventoryItem(); + InventoryItem* createPickedUpItem(){return createInventoryItem();} +private: + std::string m_inventorystring; + v3f m_speed_f; + v3f m_last_sent_position; + IntervalLimiter m_move_interval; +}; + +class RatSAO : public ServerActiveObject +{ +public: + RatSAO(ServerEnvironment *env, u16 id, v3f pos); + u8 getType() const + {return ACTIVEOBJECT_TYPE_RAT;} + static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos, + const std::string &data); + void step(float dtime, bool send_recommended); + std::string getClientInitializationData(); + std::string getStaticData(); + InventoryItem* createPickedUpItem(); +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; +}; + +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, bool send_recommended); + std::string getClientInitializationData(); + std::string getStaticData(); + InventoryItem* createPickedUpItem(){return NULL;} + u16 punch(const std::string &toolname, v3f dir); +private: + void doDamage(u16 d); + + 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; + float m_after_jump_timer; +}; + + +#endif + diff --git a/src/environment.cpp b/src/environment.cpp index 6a7c8478e..d9c62978f 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "collision.h" #include "content_mapnode.h" #include "mapblock.h" +#include "serverobject.h" +#include "content_sao.h" Environment::Environment(): m_time_of_day(9000) @@ -918,8 +920,14 @@ void ServerEnvironment::step(float dtime) // Don't step if is to be removed or stored statically if(obj->m_removed || obj->m_pending_deactivation) continue; - // Step object, putting messages directly to the queue - obj->step(dtime, m_active_object_messages, send_recommended); + // Step object + obj->step(dtime, send_recommended); + // Read messages from object + while(obj->m_messages_out.size() > 0) + { + m_active_object_messages.push_back( + obj->m_messages_out.pop_front()); + } } } @@ -1660,17 +1668,21 @@ void ClientEnvironment::step(float dtime) ClientActiveObject* obj = i.getNode()->getValue(); // Step object obj->step(dtime, this); - // Update lighting - //u8 light = LIGHT_MAX; - u8 light = 0; - try{ - // Get node at head - v3s16 p = obj->getLightPosition(); - MapNode n = m_map->getNode(p); - light = n.getLightBlend(getDayNightRatio()); + + if(m_active_object_light_update_interval.step(dtime, 0.5)) + { + // Update lighting + //u8 light = LIGHT_MAX; + u8 light = 0; + try{ + // Get node at head + v3s16 p = obj->getLightPosition(); + MapNode n = m_map->getNode(p); + light = n.getLightBlend(getDayNightRatio()); + } + catch(InvalidPositionException &e) {} + obj->updateLight(light); } - catch(InvalidPositionException &e) {} - obj->updateLight(light); } } diff --git a/src/environment.h b/src/environment.h index eac69d222..ce6b5ae1e 100644 --- a/src/environment.h +++ b/src/environment.h @@ -36,6 +36,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "map.h" #include #include "utility.h" +#include "activeobject.h" + +class Server; +class ActiveBlockModifier; +class ServerActiveObject; class Environment { @@ -118,11 +123,6 @@ private: This is not thread-safe. Server uses an environment mutex. */ -#include "serverobject.h" - -class Server; -class ActiveBlockModifier; - class ServerEnvironment : public Environment { public: @@ -412,6 +412,7 @@ private: scene::ISceneManager *m_smgr; core::map m_active_objects; Queue m_client_event_queue; + IntervalLimiter m_active_object_light_update_interval; }; #endif diff --git a/src/game.cpp b/src/game.cpp index aa1cf4a70..59f14d37d 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -661,7 +661,9 @@ void the_game( screensize = driver->getScreenSize(); const s32 hotbar_itemcount = 8; - const s32 hotbar_imagesize = 36; + //const s32 hotbar_imagesize = 36; + //const s32 hotbar_imagesize = 64; + s32 hotbar_imagesize = 48; // The color of the sky @@ -967,6 +969,14 @@ void the_game( screensize = driver->getScreenSize(); v2s32 displaycenter(screensize.X/2,screensize.Y/2); //bool screensize_changed = screensize != last_screensize; + + // Resize hotbar + if(screensize.Y <= 600) + hotbar_imagesize = 32; + else if(screensize.Y <= 1024) + hotbar_imagesize = 48; + else + hotbar_imagesize = 64; // Hilight boxes collected during the loop and displayed core::list< core::aabbox3d > hilightboxes; diff --git a/src/inventory.cpp b/src/inventory.cpp index 0c76ed845..fec51a759 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serverobject.h" #include "content_mapnode.h" #include "content_inventory.h" +#include "content_sao.h" /* InventoryItem diff --git a/src/map.cpp b/src/map.cpp index 3164028b7..a20cd9910 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -26,10 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "utility.h" #include "voxel.h" #include "porting.h" -#include "mineral.h" -#include "noise.h" -#include "serverobject.h" -#include "content_mapnode.h" #include "mapgen.h" #include "nodemetadata.h" @@ -901,7 +897,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, { } -#if 1 +#if 0 /* If the new node is solid and there is grass below, change it to mud */ @@ -2869,10 +2865,10 @@ MapSector* ServerMap::loadSectorMeta(std::string sectordir, bool save_after_load // format. Just go ahead and create the sector. if(fs::PathExists(sectordir)) { - dstream<<"ServerMap::loadSectorMeta(): Sector metafile " + /*dstream<<"ServerMap::loadSectorMeta(): Sector metafile " <= 3) @@ -672,14 +673,63 @@ public: continue; v3s16 roomplace; // X east, Z north, Y up +#if 0 + if(doordir == v3s16(1,0,0)) // X+ + roomplace = doorplace + v3s16(0,-1,-roomsize.Z/2+ + m_random.range(-roomsize.Z/2+1,roomsize.Z/2-1)); + if(doordir == v3s16(-1,0,0)) // X- + roomplace = doorplace + v3s16(-roomsize.X+1,-1,-roomsize.Z/2 + +m_random.range(-roomsize.Z/2+1,roomsize.Z/2-1)); + if(doordir == v3s16(0,0,1)) // Z+ + roomplace = doorplace + v3s16(-roomsize.X/2 + +m_random.range(-roomsize.X/2+1,roomsize.X/2-1),-1,0); + if(doordir == v3s16(0,0,-1)) // Z- + roomplace = doorplace + v3s16(-roomsize.X/2 + +m_random.range(-roomsize.X/2+1,roomsize.X/2-1),-1, + -roomsize.Z+1); +#endif +#if 0 + if(doordir == v3s16(1,0,0)) // X+ + roomplace = doorplace + v3s16(0,-1,-roomsize.Z/2+ + m_random.range(-roomsize.Z/2+(roomsize.Z%2==0?2:1), + roomsize.Z/2-1)); + if(doordir == v3s16(-1,0,0)) // X- + roomplace = doorplace + v3s16(-roomsize.X+1,-1,-roomsize.Z/2 + +m_random.range(-roomsize.Z/2+(roomsize.Z%2==0?2:1), + roomsize.Z/2-1)); + if(doordir == v3s16(0,0,1)) // Z+ + roomplace = doorplace + v3s16(-roomsize.X/2 + +m_random.range(-roomsize.X/2+(roomsize.X%2==0?2:1), + roomsize.X/2-1),-1,0); + if(doordir == v3s16(0,0,-1)) // Z- + roomplace = doorplace + v3s16(-roomsize.X/2 + +m_random.range(-roomsize.X/2+(roomsize.X%2==0?2:1), + roomsize.X/2-1),-1, -roomsize.Z+1); +#endif +#if 1 + if(doordir == v3s16(1,0,0)) // X+ + roomplace = doorplace + + v3s16(0,-1,m_random.range(-roomsize.Z+1,-2)); + if(doordir == v3s16(-1,0,0)) // X- + roomplace = doorplace + + v3s16(-roomsize.X+1,-1,m_random.range(-roomsize.Z+1,-2)); + if(doordir == v3s16(0,0,1)) // Z+ + roomplace = doorplace + + v3s16(m_random.range(-roomsize.X+1,-2),-1,0); + if(doordir == v3s16(0,0,-1)) // Z- + roomplace = doorplace + + v3s16(m_random.range(-roomsize.X+1,-2),-1,-roomsize.Z+1); +#endif +#if 0 if(doordir == v3s16(1,0,0)) // X+ - roomplace = doorplace + v3s16(0,-1,-roomsize.Z/2+m_random.range(-roomsize.Z/2+1,roomsize.Z/2-1)); + roomplace = doorplace + v3s16(0,-1,-roomsize.Z/2); if(doordir == v3s16(-1,0,0)) // X- - roomplace = doorplace + v3s16(-roomsize.X+1,-1,-roomsize.Z/2+m_random.range(-roomsize.Z/2+1,roomsize.Z/2-1)); + roomplace = doorplace + v3s16(-roomsize.X+1,-1,-roomsize.Z/2); if(doordir == v3s16(0,0,1)) // Z+ - roomplace = doorplace + v3s16(-roomsize.X/2+m_random.range(-roomsize.X/2+1,roomsize.X/2-1),-1,0); + roomplace = doorplace + v3s16(-roomsize.X/2,-1,0); if(doordir == v3s16(0,0,-1)) // Z- - roomplace = doorplace + v3s16(-roomsize.X/2+m_random.range(-roomsize.X/2+1,roomsize.X/2-1),-1,-roomsize.Z+1); + roomplace = doorplace + v3s16(-roomsize.X/2,-1,-roomsize.Z+1); +#endif // Check fit bool fits = true; @@ -790,7 +840,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random) // Determine walker start position - bool start_in_last_room = (random.range(0,1)==0); + bool start_in_last_room = (random.range(0,2)!=0); //bool start_in_last_room = true; v3s16 walker_start_place; @@ -858,7 +908,9 @@ NoiseParams get_cave_noise1_params(u64 seed) { /*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 5, 0.7, 200, CAVE_NOISE_SCALE);*/ - return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 4, 0.7, + /*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 4, 0.7, + 100, CAVE_NOISE_SCALE);*/ + return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 5, 0.6, 100, CAVE_NOISE_SCALE); } @@ -866,7 +918,9 @@ NoiseParams get_cave_noise2_params(u64 seed) { /*return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 5, 0.7, 200, CAVE_NOISE_SCALE);*/ - return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 4, 0.7, + /*return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 4, 0.7, + 100, CAVE_NOISE_SCALE);*/ + return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 5, 0.6, 100, CAVE_NOISE_SCALE); } @@ -1054,6 +1108,7 @@ double get_sector_maximum_ground_level(u64 seed, v2s16 sectorpos, double p) v2s16 node_min = sectorpos*MAP_BLOCKSIZE; v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1); double a = -31000; + // Corners a = MYMAX(a, find_ground_level_from_noise(seed, v2s16(node_min.X, node_min.Y), p)); a = MYMAX(a, find_ground_level_from_noise(seed, @@ -1062,8 +1117,18 @@ double get_sector_maximum_ground_level(u64 seed, v2s16 sectorpos, double p) v2s16(node_max.X, node_max.Y), p)); a = MYMAX(a, find_ground_level_from_noise(seed, v2s16(node_min.X, node_min.Y), p)); + // Center a = MYMAX(a, find_ground_level_from_noise(seed, v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y+MAP_BLOCKSIZE/2), p)); + // Side middle points + a = MYMAX(a, find_ground_level_from_noise(seed, + v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y), p)); + a = MYMAX(a, find_ground_level_from_noise(seed, + v2s16(node_min.X+MAP_BLOCKSIZE/2, node_max.Y), p)); + a = MYMAX(a, find_ground_level_from_noise(seed, + v2s16(node_min.X, node_min.Y+MAP_BLOCKSIZE/2), p)); + a = MYMAX(a, find_ground_level_from_noise(seed, + v2s16(node_max.X, node_min.Y+MAP_BLOCKSIZE/2), p)); return a; } @@ -1074,6 +1139,7 @@ double get_sector_minimum_ground_level(u64 seed, v2s16 sectorpos, double p) v2s16 node_min = sectorpos*MAP_BLOCKSIZE; v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1); double a = 31000; + // Corners a = MYMIN(a, find_ground_level_from_noise(seed, v2s16(node_min.X, node_min.Y), p)); a = MYMIN(a, find_ground_level_from_noise(seed, @@ -1082,8 +1148,18 @@ double get_sector_minimum_ground_level(u64 seed, v2s16 sectorpos, double p) v2s16(node_max.X, node_max.Y), p)); a = MYMIN(a, find_ground_level_from_noise(seed, v2s16(node_min.X, node_min.Y), p)); + // Center a = MYMIN(a, find_ground_level_from_noise(seed, v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y+MAP_BLOCKSIZE/2), p)); + // Side middle points + a = MYMIN(a, find_ground_level_from_noise(seed, + v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y), p)); + a = MYMIN(a, find_ground_level_from_noise(seed, + v2s16(node_min.X+MAP_BLOCKSIZE/2, node_max.Y), p)); + a = MYMIN(a, find_ground_level_from_noise(seed, + v2s16(node_min.X, node_min.Y+MAP_BLOCKSIZE/2), p)); + a = MYMIN(a, find_ground_level_from_noise(seed, + v2s16(node_max.X, node_min.Y+MAP_BLOCKSIZE/2), p)); return a; } @@ -1328,7 +1404,7 @@ void make_block(BlockMakeData *data) If block is deep underground, this is set to true and ground density noise is not generated, for speed optimization. */ - bool all_is_ground_except_caves = (minimum_ground_depth > 16); + bool all_is_ground_except_caves = (minimum_ground_depth > 40); /* Create a block-specific seed diff --git a/src/server.cpp b/src/server.cpp index 16346b870..18357e19d 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_craft.h" #include "content_nodemeta.h" #include "mapblock.h" +#include "serverobject.h" #define BLOCK_EMERGE_FLAG_FROMDISK (1<<0) @@ -2411,8 +2412,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) toolname = titem->getToolName(); } } + + v3f playerpos = player->getPosition(); + v3f objpos = obj->getBasePosition(); + v3f dir = (objpos - playerpos).normalize(); - u16 wear = obj->punch(toolname); + u16 wear = obj->punch(toolname, dir); if(titem) { diff --git a/src/serverobject.cpp b/src/serverobject.cpp index d31e9a31c..8acb35f6d 100644 --- a/src/serverobject.cpp +++ b/src/serverobject.cpp @@ -19,9 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serverobject.h" #include -#include "environment.h" #include "inventory.h" -#include "collision.h" core::map ServerActiveObject::m_types; @@ -71,600 +69,4 @@ void ServerActiveObject::registerType(u16 type, Factory f) } -/* - TestSAO -*/ - -// Prototype -TestSAO proto_TestSAO(NULL, 0, v3f(0,0,0)); - -TestSAO::TestSAO(ServerEnvironment *env, u16 id, v3f pos): - ServerActiveObject(env, id, pos), - m_timer1(0), - m_age(0) -{ - ServerActiveObject::registerType(getType(), create); -} - -ServerActiveObject* TestSAO::create(ServerEnvironment *env, u16 id, v3f pos, - const std::string &data) -{ - return new TestSAO(env, id, pos); -} - -void TestSAO::step(float dtime, Queue &messages, - bool send_recommended) -{ - m_age += dtime; - if(m_age > 10) - { - m_removed = true; - return; - } - - m_base_position.Y += dtime * BS * 2; - if(m_base_position.Y > 8*BS) - m_base_position.Y = 2*BS; - - if(send_recommended == false) - return; - - m_timer1 -= dtime; - if(m_timer1 < 0.0) - { - m_timer1 += 0.125; - //dstream<<"TestSAO: id="< &messages, - bool send_recommended) -{ - assert(m_env); - - const float interval = 0.2; - if(m_move_interval.step(dtime, interval)==false) - return; - dtime = interval; - - core::aabbox3d box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.); - collisionMoveResult moveresult; - // Apply gravity - m_speed_f += v3f(0, -dtime*9.81*BS, 0); - // 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); - - if(send_recommended == false) - return; - - if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS) - { - setBasePosition(pos_f); - m_last_sent_position = pos_f; - - std::ostringstream os(std::ios::binary); - char buf[6]; - // command (0 = update position) - buf[0] = 0; - os.write(buf, 1); - // pos - writeS32((u8*)buf, m_base_position.X*1000); - os.write(buf, 4); - writeS32((u8*)buf, m_base_position.Y*1000); - os.write(buf, 4); - writeS32((u8*)buf, m_base_position.Z*1000); - os.write(buf, 4); - // create message and add to list - ActiveObjectMessage aom(getId(), false, os.str()); - messages.push_back(aom); - } -} - -std::string ItemSAO::getClientInitializationData() -{ - std::ostringstream os(std::ios::binary); - char buf[6]; - // version - buf[0] = 0; - os.write(buf, 1); - // pos - writeS32((u8*)buf, m_base_position.X*1000); - os.write(buf, 4); - writeS32((u8*)buf, m_base_position.Y*1000); - os.write(buf, 4); - writeS32((u8*)buf, m_base_position.Z*1000); - os.write(buf, 4); - // inventorystring - os< item="< &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; - // Check connected players - core::list players = m_env->getPlayers(true); - core::list::Iterator i; - for(i = players.begin(); - i != players.end(); i++) - { - Player *player = *i; - v3f playerpos = player->getPosition(); - if(m_base_position.getDistanceFrom(playerpos) < BS*10.0) - { - player_is_close = true; - 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 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; - 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 = wrapDegrees(m_yaw); - } - } - } - - m_oldpos = m_base_position; - - /* - Move it, with collision detection - */ - - core::aabbox3d box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./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 RatSAO::getClientInitializationData() -{ - std::ostringstream os(std::ios::binary); - // version - writeU8(os, 0); - // pos - writeV3F1000(os, m_base_position); - return os.str(); -} - -std::string RatSAO::getStaticData() -{ - //dstream<<__FUNCTION_NAME<m_hp = hp; - return o; -} - -void Oerkki1SAO::step(float dtime, Queue &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 > 120) - { - // 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 players = m_env->getPlayers(true); - core::list::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 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< &messages, - bool send_recommended){} + virtual void step(float dtime, bool send_recommended){} /* The return value of this is passed to the client-side object @@ -104,7 +103,8 @@ public: 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;} + virtual u16 punch(const std::string &toolname, v3f dir) + {return 0;} /* Number of players which know about this object. Object won't be @@ -144,6 +144,11 @@ public: */ v3s16 m_static_block; + /* + Queue of messages to be sent to the client + */ + Queue m_messages_out; + protected: // Used for creating objects based on type typedef ServerActiveObject* (*Factory) @@ -159,96 +164,5 @@ private: static core::map m_types; }; -class TestSAO : public ServerActiveObject -{ -public: - TestSAO(ServerEnvironment *env, u16 id, v3f pos); - u8 getType() const - {return ACTIVEOBJECT_TYPE_TEST;} - static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos, - const std::string &data); - void step(float dtime, Queue &messages, - bool send_recommended); -private: - float m_timer1; - float m_age; -}; - -class ItemSAO : public ServerActiveObject -{ -public: - ItemSAO(ServerEnvironment *env, u16 id, v3f pos, - const std::string inventorystring); - u8 getType() const - {return ACTIVEOBJECT_TYPE_ITEM;} - static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos, - const std::string &data); - void step(float dtime, Queue &messages, - bool send_recommended); - std::string getClientInitializationData(); - std::string getStaticData(); - InventoryItem* createInventoryItem(); - InventoryItem* createPickedUpItem(){return createInventoryItem();} -private: - std::string m_inventorystring; - v3f m_speed_f; - v3f m_last_sent_position; - IntervalLimiter m_move_interval; -}; - -class RatSAO : public ServerActiveObject -{ -public: - RatSAO(ServerEnvironment *env, u16 id, v3f pos); - u8 getType() const - {return ACTIVEOBJECT_TYPE_RAT;} - static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos, - const std::string &data); - void step(float dtime, Queue &messages, - bool send_recommended); - std::string getClientInitializationData(); - std::string getStaticData(); - InventoryItem* createPickedUpItem(); -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; -}; - -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 &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 -- cgit v1.2.3 From d3d369a63b25be74f14b58ebda0d40b39d8da6ab Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sun, 26 Jun 2011 18:51:57 +0300 Subject: reorganized stuff --- src/main.cpp | 1 + src/main.h | 2 +- src/map.cpp | 19 +++++++++++++++++++ src/mineral.h | 1 - 4 files changed, 21 insertions(+), 2 deletions(-) (limited to 'src/map.cpp') diff --git a/src/main.cpp b/src/main.cpp index 9c7cf2e28..9fb17e211 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -427,6 +427,7 @@ TODO: Use MapBlock::resetUsageTimer() in appropriate places #include "materials.h" #include "game.h" #include "keycode.h" +#include "tile.h" // This makes textures ITextureSource *g_texturesource = NULL; diff --git a/src/main.h b/src/main.h index 450525c26..b2dee1494 100644 --- a/src/main.h +++ b/src/main.h @@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., extern Settings g_settings; // This makes and maps textures -#include "tile.h" +class ITextureSource; extern ITextureSource *g_texturesource; // Global profiler diff --git a/src/map.cpp b/src/map.cpp index a20cd9910..5bf278667 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -755,6 +755,25 @@ void Map::updateLighting(enum LightBank bank, } } + + /* + Enable this to disable proper lighting for speeding up map + generation for testing or whatever + */ +#if 0 + //if(g_settings.get("")) + { + core::map::Iterator i; + i = blocks_to_update.getIterator(); + for(; i.atEnd() == false; i++) + { + MapBlock *block = i.getNode()->getValue(); + v3s16 p = block->getPos(); + block->setLightingExpired(false); + } + return; + } +#endif #if 0 { diff --git a/src/mineral.h b/src/mineral.h index 970ff1f78..61776e669 100644 --- a/src/mineral.h +++ b/src/mineral.h @@ -21,7 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MINERAL_HEADER #include "inventory.h" -#include "tile.h" /* Minerals -- cgit v1.2.3 From 3fccc67eb7c530c280e9b496e22288ffa772152d Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sun, 26 Jun 2011 21:53:11 +0300 Subject: fixed block unloading from memory (a better fix coming next) --- src/client.cpp | 10 +++--- src/defaultsettings.cpp | 1 + src/environment.cpp | 3 ++ src/map.cpp | 95 ++++++++++++++++++++----------------------------- src/map.h | 15 +++++--- src/mapblock.cpp | 2 +- src/mapgen.cpp | 2 +- src/server.cpp | 16 +++++---- 8 files changed, 70 insertions(+), 74 deletions(-) (limited to 'src/map.cpp') diff --git a/src/client.cpp b/src/client.cpp index 248cd8a4c..449b0c2f2 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -333,16 +333,16 @@ void Client::step(float dtime) true, &deleted_blocks);*/ // Delete whole sectors - u32 num = m_env.getMap().unloadUnusedData + m_env.getMap().unloadUnusedData (delete_unused_sectors_timeout, - false, &deleted_blocks); + &deleted_blocks); - if(num > 0) + if(deleted_blocks.size() > 0) { /*dstream<getBlockNoCreateNoEx(p); if(block==NULL) continue; + + // Reset block usage timer + block->resetUsageTimer(); // Set current time as timestamp block->setTimestampNoChangedFlag(m_game_time); diff --git a/src/map.cpp b/src/map.cpp index 5bf278667..2cf7bb2e5 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1388,8 +1388,6 @@ bool Map::dayNightDiffed(v3s16 blockpos) */ void Map::timerUpdate(float dtime) { - //JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out - core::map::Iterator si; si = m_sectors.getIterator(); @@ -1407,38 +1405,27 @@ void Map::timerUpdate(float dtime) } } -void Map::deleteSectors(core::list &list, bool only_blocks) +void Map::deleteSectors(core::list &list) { core::list::Iterator j; for(j=list.begin(); j!=list.end(); j++) { MapSector *sector = m_sectors[*j]; - if(only_blocks) - { - sector->deleteBlocks(); - } - else - { - /* - If sector is in sector cache, remove it from there - */ - if(m_sector_cache == sector) - { - m_sector_cache = NULL; - } - /* - Remove from map and delete - */ - m_sectors.remove(*j); - delete sector; - } + // If sector is in sector cache, remove it from there + if(m_sector_cache == sector) + m_sector_cache = NULL; + // Remove from map and delete + m_sectors.remove(*j); + delete sector; } } -u32 Map::unloadUnusedData(float timeout, bool only_blocks, +void Map::unloadUnusedData(float timeout, core::list *deleted_blocks) { core::list sector_deletion_queue; + u32 deleted_blocks_count = 0; + u32 saved_blocks_count = 0; core::map::Iterator si = m_sectors.getIterator(); for(; si.atEnd() == false; si++) @@ -1453,14 +1440,18 @@ u32 Map::unloadUnusedData(float timeout, bool only_blocks, i != blocks.end(); i++) { MapBlock *block = (*i); - + if(block->getUsageTimer() > timeout) { // Save if modified if(block->getModified() != MOD_STATE_CLEAN) + { saveBlock(block); + saved_blocks_count++; + } // Delete from memory sector->deleteBlock(block); + deleted_blocks_count++; } else { @@ -1474,36 +1465,14 @@ u32 Map::unloadUnusedData(float timeout, bool only_blocks, } } -#if 0 - core::map::Iterator i = m_sectors.getIterator(); - for(; i.atEnd() == false; i++) - { - MapSector *sector = i.getNode()->getValue(); - /* - Delete sector from memory if it hasn't been used in a long time - */ - if(sector->usage_timer > timeout) - { - sector_deletion_queue.push_back(i.getNode()->getKey()); + deleteSectors(sector_deletion_queue); - if(deleted_blocks != NULL) - { - // Collect positions of blocks of sector - MapSector *sector = i.getNode()->getValue(); - core::list blocks; - sector->getBlocks(blocks); - for(core::list::Iterator i = blocks.begin(); - i != blocks.end(); i++) - { - deleted_blocks->push_back((*i)->getPos()); - } - } - } - } -#endif + dstream<<"Map: Unloaded "<vmanip.print(dstream);*/ @@ -2095,10 +2066,11 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data, //TimeTaker timer("finishBlockMake() blitBackAll"); data->vmanip->blitBackAll(&changed_blocks); } -#if 1 - dstream<<"finishBlockMake: changed_blocks.size()=" - < &list, bool only_blocks); + // If deleted sector is in sector cache, clears cache + void deleteSectors(core::list &list); - // Returns count of deleted sectors - u32 unloadUnusedData(float timeout, bool only_blocks=false, + /* + Unload unused data + = flush changed to disk and delete from memory, if usage timer of + block is more than timeout + */ + void unloadUnusedData(float timeout, core::list *deleted_blocks=NULL); // For debug printing diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 7036cd035..c125e67c8 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -38,7 +38,7 @@ MapBlock::MapBlock(Map *parent, v3s16 pos, bool dummy): m_generated(false), m_objects(this), m_timestamp(BLOCK_TIMESTAMP_UNDEFINED), - m_usage_timer(BLOCK_TIMESTAMP_UNDEFINED) + m_usage_timer(0) { data = NULL; if(dummy == false) diff --git a/src/mapgen.cpp b/src/mapgen.cpp index e481ee30c..4a2a39aec 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -1389,7 +1389,7 @@ void make_block(BlockMakeData *data) /* Create a block-specific seed */ - u32 blockseed = (data->seed%0x100000000) + full_node_min.Z*38134234 + u32 blockseed = (u32)(data->seed%0x100000000) + full_node_min.Z*38134234 + full_node_min.Y*42123 + full_node_min.X*23; /* diff --git a/src/server.cpp b/src/server.cpp index 2ee94f345..b65f0bdb5 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1831,17 +1831,21 @@ void Server::AsyncRunStep() JMutexAutoLock lock(m_env_mutex); if(((ServerMap*)(&m_env.getMap()))->isSavingEnabled() == true) { + // Unload unused data (delete from memory) + m_env.getMap().unloadUnusedData( + g_settings.getFloat("server_unload_unused_sectors_timeout")); + /*u32 deleted_count = m_env.getMap().unloadUnusedData( + g_settings.getFloat("server_unload_unused_sectors_timeout")); + */ + // Save only changed parts m_env.getMap().save(true); - // Delete unused sectors - u32 deleted_count = m_env.getMap().unloadUnusedData( - g_settings.getFloat("server_unload_unused_sectors_timeout")); - if(deleted_count > 0) + /*if(deleted_count > 0) { dout_server<<"Server: Unloaded "< Date: Mon, 27 Jun 2011 00:27:17 +0300 Subject: map unloading is now a whole lot better --- minetest.conf.example | 8 +++- src/client.cpp | 96 ++++++++++++++++++++++++++++++------- src/client.h | 3 +- src/clientserver.h | 2 +- src/defaultsettings.cpp | 4 +- src/environment.cpp | 15 +----- src/main.cpp | 124 +++++++++++++++++------------------------------- src/map.cpp | 99 +++++++++++++++++++++++++++----------- src/map.h | 15 ++++-- src/server.cpp | 115 ++++++++++++++++++++++---------------------- src/server.h | 1 + 11 files changed, 272 insertions(+), 210 deletions(-) (limited to 'src/map.cpp') diff --git a/minetest.conf.example b/minetest.conf.example index 6e8a82bac..f94c8dee5 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -9,6 +9,10 @@ # # Further documentation: # http://celeron.55.lt/~celeron55/minetest/wiki/doku.php +# +# NOTE: This file might not be up-to-date, refer to the +# defaultsettings.cpp file for an up-to-date list: +# https://bitbucket.org/celeron55/minetest/src/tip/src/defaultsettings.cpp # # Client side stuff @@ -92,7 +96,7 @@ #random_input = false # Timeout for client to remove unused map data from memory -#client_delete_unused_sectors_timeout = 1200 +#client_unload_unused_data_timeout = 1200 # # Server side stuff @@ -140,6 +144,6 @@ #time_speed = 1440 #time_send_interval = 5 -#server_unload_unused_sectors_timeout = 60 +#server_unload_unused_data_timeout = 60 #server_map_save_interval = 60 diff --git a/src/client.cpp b/src/client.cpp index 449b0c2f2..585fce11c 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -199,7 +199,7 @@ Client::Client( m_access_denied(false) { m_packetcounter_timer = 0.0; - m_delete_unused_sectors_timer = 0.0; + //m_delete_unused_sectors_timer = 0.0; m_connection_reinit_timer = 0.0; m_avg_rtt_timer = 0.0; m_playerpos_send_timer = 0.0; @@ -303,7 +303,11 @@ void Client::step(float dtime) m_packetcounter.clear(); } } + + // Get connection status + bool connected = connectedAndInitialized(); +#if 0 { /* Delete unused sectors @@ -324,8 +328,7 @@ void Client::step(float dtime) core::list deleted_blocks; - float delete_unused_sectors_timeout = - g_settings.getFloat("client_delete_unused_sectors_timeout"); + g_settings.getFloat("client_unload_unused_data_timeout"); // Delete sector blocks /*u32 num = m_env.getMap().unloadUnusedData @@ -392,8 +395,7 @@ void Client::step(float dtime) } } } - - bool connected = connectedAndInitialized(); +#endif if(connected == false) { @@ -438,6 +440,67 @@ void Client::step(float dtime) Do stuff if connected */ + /* + Run Map's timers and unload unused data + */ + const float map_timer_and_unload_dtime = 5.25; + if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime)) + { + ScopeProfiler sp(&g_profiler, "Client: map timer and unload"); + core::list deleted_blocks; + m_env.getMap().timerUpdate(map_timer_and_unload_dtime, + g_settings.getFloat("client_unload_unused_data_timeout"), + &deleted_blocks); + + /*if(deleted_blocks.size() > 0) + dstream<<"Client: Unloaded "<::Iterator i = deleted_blocks.begin(); + core::list sendlist; + for(;;) + { + if(sendlist.size() == 255 || i == deleted_blocks.end()) + { + if(sendlist.size() == 0) + break; + /* + [0] u16 command + [2] u8 count + [3] v3s16 pos_0 + [3+6] v3s16 pos_1 + ... + */ + u32 replysize = 2+1+6*sendlist.size(); + SharedBuffer reply(replysize); + writeU16(&reply[0], TOSERVER_DELETEDBLOCKS); + reply[2] = sendlist.size(); + u32 k = 0; + for(core::list::Iterator + j = sendlist.begin(); + j != sendlist.end(); j++) + { + writeV3S16(&reply[2+1+6*k], *j); + k++; + } + m_con.Send(PEER_ID_SERVER, 1, reply, true); + + if(i == deleted_blocks.end()) + break; + + sendlist.clear(); + } + + sendlist.push_back(*i); + i++; + } + } + /* Handle environment */ @@ -453,23 +516,23 @@ void Client::step(float dtime) //TimeTaker envtimer("env step", m_device); // Step environment m_env.step(dtime); - - // Step active blocks + + /* + Handle active blocks + NOTE: These old objects are DEPRECATED. TODO: Remove + */ for(core::map::Iterator i = m_active_blocks.getIterator(); i.atEnd() == false; i++) { v3s16 p = i.getNode()->getKey(); - MapBlock *block = NULL; - try - { - block = m_env.getMap().getBlockNoCreate(p); - block->stepObjects(dtime, false, m_env.getDayNightRatio()); - } - catch(InvalidPositionException &e) - { - } + MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(p); + if(block == NULL) + continue; + + // Step MapBlockObjects + block->stepObjects(dtime, false, m_env.getDayNightRatio()); } /* @@ -1183,6 +1246,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) /* Read block objects + NOTE: Deprecated stuff here, TODO: Remove */ // Read active block count diff --git a/src/client.h b/src/client.h index 442eaef5d..bd838fee0 100644 --- a/src/client.h +++ b/src/client.h @@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "jmutex.h" #include #include "clientobject.h" +#include "utility.h" // For IntervalLimiter struct MeshMakeData; @@ -306,11 +307,11 @@ private: void sendPlayerInfo(); float m_packetcounter_timer; - float m_delete_unused_sectors_timer; float m_connection_reinit_timer; float m_avg_rtt_timer; float m_playerpos_send_timer; float m_ignore_damage_timer; // Used after server moves player + IntervalLimiter m_map_timer_and_unload_interval; MeshUpdateThread m_mesh_update_thread; diff --git a/src/clientserver.h b/src/clientserver.h index 7972762c0..35484fe76 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -37,7 +37,7 @@ enum ToClientCommand [0] u16 TOSERVER_INIT [2] u8 deployed version [3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd - ([4] u64 map seed (new as of 2011-02-27)) + [12] u64 map seed (new as of 2011-02-27) NOTE: The position in here is deprecated; position is explicitly sent afterwards diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 99bead6b0..0213ede1f 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -56,7 +56,7 @@ void set_default_settings() g_settings.setDefault("screenH", "600"); g_settings.setDefault("address", ""); g_settings.setDefault("random_input", "false"); - g_settings.setDefault("client_delete_unused_sectors_timeout", "1200"); + g_settings.setDefault("client_unload_unused_data_timeout", "1200"); g_settings.setDefault("enable_fog", "true"); g_settings.setDefault("new_style_water", "false"); g_settings.setDefault("new_style_leaves", "true"); @@ -94,7 +94,7 @@ void set_default_settings() g_settings.setDefault("max_block_generate_distance", "8"); g_settings.setDefault("time_send_interval", "20"); g_settings.setDefault("time_speed", "96"); - g_settings.setDefault("server_unload_unused_sectors_timeout", "60"); + g_settings.setDefault("server_unload_unused_data_timeout", "60"); g_settings.setDefault("server_map_save_interval", "60"); g_settings.setDefault("full_block_send_enable_min_time_from_building", "2.0"); //g_settings.setDefault("dungeon_rarity", "0.025"); diff --git a/src/environment.cpp b/src/environment.cpp index b52a46dde..ac69c8ae2 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -660,14 +660,6 @@ void ServerEnvironment::step(float dtime) m_game_time_fraction_counter -= (float)inc_i; } - /* - Let map update it's timers - */ - { - //TimeTaker timer("Server m_map->timerUpdate()"); - m_map->timerUpdate(dtime); - } - /* Handle players */ @@ -1469,11 +1461,6 @@ void ClientEnvironment::step(float dtime) bool free_move = g_settings.getBool("free_move"); bool footprints = g_settings.getBool("footprints"); - { - //TimeTaker timer("Client m_map->timerUpdate()"); - m_map->timerUpdate(dtime); - } - // Get local player LocalPlayer *lplayer = getLocalPlayer(); assert(lplayer); @@ -1672,7 +1659,7 @@ void ClientEnvironment::step(float dtime) // Step object obj->step(dtime, this); - if(m_active_object_light_update_interval.step(dtime, 0.5)) + if(m_active_object_light_update_interval.step(dtime, 0.21)) { // Update lighting //u8 light = LIGHT_MAX; diff --git a/src/main.cpp b/src/main.cpp index 9fb17e211..65d6006e3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,6 +27,33 @@ NOTE: Global locale is now set at initialization NOTE: If VBO (EHM_STATIC) is used, remember to explicitly free the hardware buffer (it is not freed automatically) +NOTE: A random to-do list saved here as documentation: +A list of "active blocks" in which stuff happens. (+=done) + + Add a never-resetted game timer to the server + + Add a timestamp value to blocks + + The simple rule: All blocks near some player are "active" + - Do stuff in real time in active blocks + + Handle objects + - Grow grass, delete leaves without a tree + - Spawn some mobs based on some rules + - Transform cobble to mossy cobble near water + - Run a custom script + - ...And all kinds of other dynamic stuff + + Keep track of when a block becomes active and becomes inactive + + When a block goes inactive: + + Store objects statically to block + + Store timer value as the timestamp + + When a block goes active: + + Create active objects out of static objects + - Simulate the results of what would have happened if it would have + been active for all the time + - Grow a lot of grass and so on + + Initially it is fine to send information about every active object + to every player. Eventually it should be modified to only send info + about the nearest ones. + + This was left to be done by the old system and it sends only the + nearest ones. + Old, wild and random suggestions that probably won't be done: ------------------------------------------------------------- @@ -73,9 +100,6 @@ SUGG: Make the amount of blocks sending to client and the total SUGG: Meshes of blocks could be split into 6 meshes facing into different directions and then only those drawn that need to be -SUGG: Calculate lighting per vertex to get a lighting effect like in - bartwe's game - SUGG: Background music based on cellular automata? http://www.earslap.com/projectslab/otomata @@ -90,6 +114,8 @@ SUGG: Make a system for pregenerating quick information for mapblocks, so or even generated. SUGG: Erosion simulation at map generation time + - This might be plausible if larger areas of map were pregenerated + without lighting (which is slow) - Simulate water flows, which would carve out dirt fast and then turn stone into gravel and sand and relocate it. - How about relocating minerals, too? Coal and gold in @@ -231,6 +257,7 @@ FIXME: Server sometimes goes into some infinite PeerNotFoundException loop * Fix the problem with the server constantly saving one or a few blocks? List the first saved block, maybe it explains. - It is probably caused by oscillating water + - TODO: Investigate if this still happens (this is a very old one) * Make a small history check to transformLiquids to detect and log continuous oscillations, in such detail that they can be fixed. @@ -238,42 +265,12 @@ FIXME: The new optimized map sending doesn't sometimes send enough blocks from big caves and such FIXME: Block send distance configuration does not take effect for some reason -SUGG: Map unloading based on sector reference is not very good, it keeps - unnecessary stuff in memory. I guess. Investigate this. - -TODO: When block is placed and it has param_type==CPT_FACEDIR_SIMPLE, set - the direction accordingly. - Environment: ------------ -TODO: A list of "active blocks" in which stuff happens. (+=done) - + Add a never-resetted game timer to the server - + Add a timestamp value to blocks - + The simple rule: All blocks near some player are "active" - - Do stuff in real time in active blocks - + Handle objects - TODO: Make proper hooks in here - - Grow grass, delete leaves without a tree - - Spawn some mobs based on some rules - - Transform cobble to mossy cobble near water - - Run a custom script - - ...And all kinds of other dynamic stuff - + Keep track of when a block becomes active and becomes inactive - + When a block goes inactive: - + Store objects statically to block - + Store timer value as the timestamp - + When a block goes active: - + Create active objects out of static objects - TODO: Make proper hooks in here - - Simulate the results of what would have happened if it would have - been active for all the time - - Grow a lot of grass and so on - + Initially it is fine to send information about every active object - to every player. Eventually it should be modified to only send info - about the nearest ones. - + This was left to be done by the old system and it sends only the - nearest ones. +TODO: Add proper hooks to when adding and removing active blocks + +TODO: Finish the ActiveBlockModifier stuff and use it for something Objects: -------- @@ -285,6 +282,7 @@ TODO: Get rid of MapBlockObjects and use only ActiveObjects SUGG: MovingObject::move and Player::move are basically the same. combine them. + - NOTE: This is a bit tricky because player has the sneaking ability - NOTE: Player::move is more up-to-date. - NOTE: There is a simple move implementation now in collision.{h,cpp} - NOTE: MovingObject will be deleted (MapBlockObject) @@ -303,42 +301,17 @@ TODO: Mineral and ground material properties TODO: Flowing water to actually contain flow direction information - There is a space for this - it just has to be implemented. -SUGG: Try out the notch way of generating maps, that is, make bunches - of low-res 3d noise and interpolate linearly. - -Mapgen v2 (the current one): -* Possibly add some kind of erosion and other stuff -* Better water generation (spread it to underwater caverns but don't - fill dungeons that don't touch big water masses) -* When generating a chunk and the neighboring chunk doesn't have mud - and stuff yet and the ground is fairly flat, the mud will flow to - the other chunk making nasty straight walls when the other chunk - is generated. Fix it. Maybe just a special case if the ground is - flat? -* Consider not updating this one and make a good mainly block-based - generator - -SUGG: Make two "modified states", one that forces the block to be saved at - the next save event, and one that makes the block to be saved at exit - time. - -TODO: Add a not_fully_generated flag to MapBlock, which would be set for - blocks that contain eg. trees from neighboring generations but haven't - been generated itself. This is required for the future generator. - Misc. stuff: ------------ -- Make sure server handles removing grass when a block is placed (etc) - - The client should not do it by itself -- Block cube placement around player's head -- Protocol version field -- Consider getting some textures from cisoun's texture pack - - Ask from Cisoun -- Make sure the fence implementation and data format is good - - Think about using same bits for material for fences and doors, for - example -- Finish the ActiveBlockModifier stuff and use it for something -- Move mineral to param2, increment map serialization version, add conversion +TODO: Make sure server handles removing grass when a block is placed (etc) + - The client should not do it by itself + - NOTE: I think nobody does it currently... +TODO: Block cube placement around player's head +TODO: Protocol version field +TODO: Think about using same bits for material for fences and doors, for + example +TODO: Move mineral to param2, increment map serialization version, add + conversion TODO: Add a per-sector database to store surface stuff as simple flags/values - Light? @@ -354,8 +327,6 @@ TODO: Restart irrlicht completely when coming back to main menu from game. TODO: Merge bahamada's audio stuff (clean patch available) -TODO: Merge spongie's chest/furnace direction (by hand) - TODO: Merge key configuration menu (no clean patch available) Making it more portable: @@ -373,9 +344,6 @@ Stuff to do after release: Doing currently: ---------------- -TODO: Use MapBlock::resetUsageTimer() in appropriate places - (on client and server) - ====================================================================== */ @@ -404,16 +372,12 @@ TODO: Use MapBlock::resetUsageTimer() in appropriate places #include #include -//#include #include #include "main.h" #include "common_irrlicht.h" #include "debug.h" -//#include "map.h" -//#include "player.h" #include "test.h" #include "server.h" -//#include "client.h" #include "constants.h" #include "porting.h" #include "gettime.h" @@ -422,8 +386,6 @@ TODO: Use MapBlock::resetUsageTimer() in appropriate places #include "config.h" #include "guiMainMenu.h" #include "mineral.h" -//#include "noise.h" -//#include "tile.h" #include "materials.h" #include "game.h" #include "keycode.h" diff --git a/src/map.cpp b/src/map.cpp index 2cf7bb2e5..0f3741691 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1386,8 +1386,15 @@ bool Map::dayNightDiffed(v3s16 blockpos) /* Updates usage timers */ -void Map::timerUpdate(float dtime) +void Map::timerUpdate(float dtime, float unload_timeout, + core::list *unloaded_blocks) { + bool save_before_unloading = (mapType() == MAPTYPE_SERVER); + + core::list sector_deletion_queue; + u32 deleted_blocks_count = 0; + u32 saved_blocks_count = 0; + core::map::Iterator si; si = m_sectors.getIterator(); @@ -1395,13 +1402,60 @@ void Map::timerUpdate(float dtime) { MapSector *sector = si.getNode()->getValue(); + bool all_blocks_deleted = true; + core::list blocks; sector->getBlocks(blocks); for(core::list::Iterator i = blocks.begin(); i != blocks.end(); i++) { - (*i)->incrementUsageTimer(dtime); + MapBlock *block = (*i); + + block->incrementUsageTimer(dtime); + + if(block->getUsageTimer() > unload_timeout) + { + v3s16 p = block->getPos(); + + // Save if modified + if(block->getModified() != MOD_STATE_CLEAN + && save_before_unloading) + { + saveBlock(block); + saved_blocks_count++; + } + + // Delete from memory + sector->deleteBlock(block); + + if(unloaded_blocks) + unloaded_blocks->push_back(p); + + deleted_blocks_count++; + } + else + { + all_blocks_deleted = false; + } } + + if(all_blocks_deleted) + { + sector_deletion_queue.push_back(si.getNode()->getKey()); + } + } + + // Finally delete the empty sectors + deleteSectors(sector_deletion_queue); + + if(deleted_blocks_count != 0) + { + PrintInfo(dstream); // ServerMap/ClientMap: + dstream<<"Unloaded "< &list) } } +#if 0 void Map::unloadUnusedData(float timeout, core::list *deleted_blocks) { @@ -1474,6 +1529,7 @@ void Map::unloadUnusedData(float timeout, //return sector_deletion_queue.getSize(); //return deleted_blocks_count; } +#endif void Map::PrintInfo(std::ostream &out) { @@ -1500,7 +1556,7 @@ void Map::transformLiquids(core::map & modified_blocks) */ v3s16 p0 = m_transforming_liquid.pop_front(); - MapNode n0 = getNode(p0); + MapNode n0 = getNodeNoEx(p0); // Don't deal with non-liquids if(content_liquid(n0.d) == false) @@ -1532,13 +1588,10 @@ void Map::transformLiquids(core::map & modified_blocks) }; for(u16 i=0; i<5; i++) { - try - { - bool from_top = (i==0); v3s16 p2 = p0 + dirs_from[i]; - MapNode n2 = getNode(p2); + MapNode n2 = getNodeNoEx(p2); if(content_liquid(n2.d)) { @@ -1572,10 +1625,6 @@ void Map::transformLiquids(core::map & modified_blocks) if(new_liquid_level > new_liquid_level_max) new_liquid_level_max = new_liquid_level; } - - }catch(InvalidPositionException &e) - { - } } //for /* @@ -1618,20 +1667,13 @@ void Map::transformLiquids(core::map & modified_blocks) }; for(u16 i=0; i<6; i++) { - try - { - v3s16 p2 = p0 + dirs[i]; - MapNode n2 = getNode(p2); + MapNode n2 = getNodeNoEx(p2); if(content_flowing_liquid(n2.d)) { m_transforming_liquid.push_back(p2); } - - }catch(InvalidPositionException &e) - { - } } } } @@ -1652,9 +1694,6 @@ void Map::transformLiquids(core::map & modified_blocks) }; for(u16 i=0; i<5; i++) { - try - { - bool to_bottom = (i == 0); // If liquid is at lowest possible height, it's not going @@ -1680,7 +1719,7 @@ void Map::transformLiquids(core::map & modified_blocks) v3s16 p2 = p0 + dirs_to[i]; - MapNode n2 = getNode(p2); + MapNode n2 = getNodeNoEx(p2); //dstream<<"[1] n2.param="<<(int)n2.param< & modified_blocks) // If n2_changed to bottom, don't flow anywhere else if(to_bottom && flowed && !is_source) break; - - }catch(InvalidPositionException &e) - { - } } loopcount++; @@ -1945,7 +1980,6 @@ ServerMap::~ServerMap() { if(m_map_saving_enabled) { - //save(false); // Save only changed parts save(true); dstream<resetUsageTimer(); // This is ugly (spherical distance limit?) /*if(m_control.range_all == false && diff --git a/src/map.h b/src/map.h index 2fe749007..71101b8e4 100644 --- a/src/map.h +++ b/src/map.h @@ -223,19 +223,23 @@ public: virtual void save(bool only_changed){assert(0);}; - // Server implements this + // Server implements this. + // Client leaves it as no-op. virtual void saveBlock(MapBlock *block){}; /* - Updates usage timers + Updates usage timers and unloads unused blocks and sectors. + Saves modified blocks before unloading on MAPTYPE_SERVER. */ - void timerUpdate(float dtime); + void timerUpdate(float dtime, float unload_timeout, + core::list *unloaded_blocks=NULL); // Deletes sectors and their blocks from memory // Takes cache into account // If deleted sector is in sector cache, clears cache void deleteSectors(core::list &list); - + +#if 0 /* Unload unused data = flush changed to disk and delete from memory, if usage timer of @@ -243,8 +247,9 @@ public: */ void unloadUnusedData(float timeout, core::list *deleted_blocks=NULL); +#endif - // For debug printing + // For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: " virtual void PrintInfo(std::ostream &out); void transformLiquids(core::map & modified_blocks); diff --git a/src/server.cpp b/src/server.cpp index b65f0bdb5..798f36ac1 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -602,6 +602,9 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, bool block_is_invalid = false; if(block != NULL) { + // Reset usage timer, this block will be of use in the future. + block->resetUsageTimer(); + // Block is dummy if data doesn't exist. // It means it has been not found from disk and not generated if(block->isDummy()) @@ -1297,12 +1300,21 @@ void Server::AsyncRunStep() } { - // Step environment - // This also runs Map's timers JMutexAutoLock lock(m_env_mutex); + // Step environment ScopeProfiler sp(&g_profiler, "Server: environment step"); m_env.step(dtime); } + + const float map_timer_and_unload_dtime = 5.15; + if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime)) + { + JMutexAutoLock lock(m_env_mutex); + // Run Map's timers and unload unused data + ScopeProfiler sp(&g_profiler, "Server: map timer and unload"); + m_env.getMap().timerUpdate(map_timer_and_unload_dtime, + g_settings.getFloat("server_unload_unused_data_timeout")); + } /* Do background stuff @@ -1665,8 +1677,15 @@ void Server::AsyncRunStep() if(m_unsent_map_edit_queue.size() >= 4) disable_single_change_sending = true; + bool got_any_events = false; + + // We'll log the amount of each + Profiler prof; + while(m_unsent_map_edit_queue.size() != 0) { + got_any_events = true; + MapEditEvent* event = m_unsent_map_edit_queue.pop_front(); // Players far away from the change are stored here. @@ -1676,7 +1695,8 @@ void Server::AsyncRunStep() if(event->type == MEET_ADDNODE) { - dstream<<"Server: MEET_ADDNODE"<p, event->n, event->already_known_by_peer, &far_players, 5); @@ -1686,7 +1706,8 @@ void Server::AsyncRunStep() } else if(event->type == MEET_REMOVENODE) { - dstream<<"Server: MEET_REMOVENODE"<p, event->already_known_by_peer, &far_players, 5); @@ -1697,15 +1718,18 @@ void Server::AsyncRunStep() else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED) { dstream<<"Server: MEET_BLOCK_NODE_METADATA_CHANGED"<p); } else if(event->type == MEET_OTHER) { + prof.add("MEET_OTHER", 1); dstream<<"WARNING: Server: MEET_OTHER not implemented" <type)<= 1 && m_unsent_map_edit_queue.size() < 100) break;*/ } + + if(got_any_events) + { + dstream<<"Server: MapEditEvents:"< changed_blocks; - m_env.getMap().nodeMetadataStep(dtime, changed_blocks); - - // Use setBlockNotSent - - for(core::map::Iterator - i = changed_blocks.getIterator(); - i.atEnd() == false; i++) - { - MapBlock *block = i.getNode()->getValue(); - - for(core::map::Iterator - i = m_clients.getIterator(); - i.atEnd()==false; i++) - { - RemoteClient *client = i.getNode()->getValue(); - client->SetBlockNotSent(block->getPos()); - } - } - }*/ - /* Trigger emergethread (it somehow gets to a non-triggered but bysy state sometimes) @@ -1829,30 +1827,29 @@ void Server::AsyncRunStep() // Map JMutexAutoLock lock(m_env_mutex); - if(((ServerMap*)(&m_env.getMap()))->isSavingEnabled() == true) - { - // Unload unused data (delete from memory) - m_env.getMap().unloadUnusedData( - g_settings.getFloat("server_unload_unused_sectors_timeout")); - /*u32 deleted_count = m_env.getMap().unloadUnusedData( - g_settings.getFloat("server_unload_unused_sectors_timeout")); - */ - // Save only changed parts - m_env.getMap().save(true); + /*// Unload unused data (delete from memory) + m_env.getMap().unloadUnusedData( + g_settings.getFloat("server_unload_unused_sectors_timeout")); + */ + /*u32 deleted_count = m_env.getMap().unloadUnusedData( + g_settings.getFloat("server_unload_unused_sectors_timeout")); + */ - /*if(deleted_count > 0) - { - dout_server<<"Server: Unloaded "< 0) + { + dout_server<<"Server: Unloaded "<clone(); diff --git a/src/server.h b/src/server.h index b88369ddf..1da004da5 100644 --- a/src/server.h +++ b/src/server.h @@ -534,6 +534,7 @@ private: float m_objectdata_timer; float m_emergethread_trigger_timer; float m_savemap_timer; + IntervalLimiter m_map_timer_and_unload_interval; // NOTE: If connection and environment are both to be locked, // environment shall be locked first. -- cgit v1.2.3 From 282912caa0f8a19d5b5fb94a3cb6a41432a3a2df Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Mon, 27 Jun 2011 09:50:34 +0300 Subject: tried to fix block selection in map rendering a bit --- src/map.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/map.cpp') diff --git a/src/map.cpp b/src/map.cpp index 0f3741691..79f2a40af 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -3378,13 +3378,13 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) // Take a fair amount as we will be dropping more out later v3s16 p_blocks_min( - p_nodes_min.X / MAP_BLOCKSIZE - 1, - p_nodes_min.Y / MAP_BLOCKSIZE - 1, - p_nodes_min.Z / MAP_BLOCKSIZE - 1); + p_nodes_min.X / MAP_BLOCKSIZE - 2, + p_nodes_min.Y / MAP_BLOCKSIZE - 2, + p_nodes_min.Z / MAP_BLOCKSIZE - 2); v3s16 p_blocks_max( - p_nodes_max.X / MAP_BLOCKSIZE, - p_nodes_max.Y / MAP_BLOCKSIZE, - p_nodes_max.Z / MAP_BLOCKSIZE); + p_nodes_max.X / MAP_BLOCKSIZE + 1, + p_nodes_max.Y / MAP_BLOCKSIZE + 1, + p_nodes_max.Z / MAP_BLOCKSIZE + 1); u32 vertex_count = 0; -- cgit v1.2.3 From 71f5d4b3443c6ea770463838a2c84b85d9fa3b21 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Fri, 1 Jul 2011 21:04:40 +0300 Subject: Fixed objects being sometimes not able to be stored statically in a block when block has been unloaded --- src/environment.cpp | 29 +++++++++++++++++------------ src/main.cpp | 24 +++++++++++++----------- src/map.cpp | 52 ++++++++++++++++++++++++++++++++++++++++------------ src/map.h | 21 +++++---------------- src/server.cpp | 2 ++ 5 files changed, 77 insertions(+), 51 deletions(-) (limited to 'src/map.cpp') diff --git a/src/environment.cpp b/src/environment.cpp index ac69c8ae2..ac78107a3 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -1177,7 +1177,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, block->setChangedFlag(); } else{ - dstream<<"WARNING: Server: Could not find a block for " + dstream<<"WARNING: ServerEnv: Could not find a block for " <<"storing newly added static active object"<getType(), objectpos, staticdata); // Add to the block where the object is located in v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS)); - MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos); + // Get or generate the block + MapBlock *block = m_map->emergeBlock(blockpos); + + /*MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos); + if(block == NULL) + { + // Block not found. Is the old block still ok? + if(oldblock) + block = oldblock; + // Load from disk or generate + else + block = m_map->emergeBlock(blockpos); + }*/ + if(block) { block->m_static_objects.insert(0, s_obj); @@ -1357,17 +1370,9 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) obj->m_static_exists = true; obj->m_static_block = block->getPos(); } - // If not possible, add back to previous block - else if(oldblock) - { - oldblock->m_static_objects.insert(0, s_obj); - oldblock->setChangedFlag(); - obj->m_static_exists = true; - obj->m_static_block = oldblock->getPos(); - } else{ - dstream<<"WARNING: Server: Could not find a block for " - <<"storing static object"<m_static_exists = false; continue; } diff --git a/src/main.cpp b/src/main.cpp index cd5df666d..698c5fc71 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -126,6 +126,16 @@ SUGG: Erosion simulation at map generation time - Simulate rock falling from cliffs when water has removed enough solid rock from the bottom +SUGG: For non-mapgen FarMesh: Add a per-sector database to store surface + stuff as simple flags/values + - Light? + - A building? + And at some point make the server send this data to the client too, + instead of referring to the noise functions + - Ground height + - Surface ground type + - Trees? + Gaming ideas: ------------- @@ -199,12 +209,13 @@ SUGG: Make fetching sector's blocks more efficient when rendering sectors that have very large amounts of blocks (on client) - Is this necessary at all? -TODO: Flowing water animation - SUGG: Draw cubes in inventory directly with 3D drawing commands, so that animating them is easier. SUGG: Option for enabling proper alpha channel for textures + +TODO: Flowing water animation + TODO: A setting for enabling bilinear filtering for textures TODO: Better control of draw_control.wanted_max_blocks @@ -321,15 +332,6 @@ TODO: Think about using same bits for material for fences and doors, for TODO: Move mineral to param2, increment map serialization version, add conversion -TODO: Add a per-sector database to store surface stuff as simple flags/values - - Light? - - A building? - And at some point make the server send this data to the client too, - instead of referring to the noise functions - - Ground height - - Surface ground type - - Trees? - TODO: Restart irrlicht completely when coming back to main menu from game. - This gets rid of everything that is stored in irrlicht's caches. diff --git a/src/map.cpp b/src/map.cpp index 79f2a40af..dc66b4d55 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -2442,23 +2442,51 @@ MapBlock * ServerMap::createBlock(v3s16 p) return block; } -#if 0 -MapBlock * ServerMap::emergeBlock( - v3s16 p, - bool only_from_disk, - core::map &changed_blocks, - core::map &lighting_invalidated_blocks -) +MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate) { - DSTACKF("%s: p=(%d,%d,%d), only_from_disk=%d", + DSTACKF("%s: p=(%d,%d,%d), allow_generate=%d", __FUNCTION_NAME, - p.X, p.Y, p.Z, only_from_disk); + p.X, p.Y, p.Z, allow_generate); - // This has to be redone or removed - assert(0); + { + MapBlock *block = getBlockNoCreateNoEx(p); + if(block) + return block; + } + + { + MapBlock *block = loadBlock(p); + if(block) + return block; + } + + if(allow_generate) + { + core::map modified_blocks; + MapBlock *block = generateBlock(p, modified_blocks); + if(block) + { + MapEditEvent event; + event.type = MEET_OTHER; + event.p = p; + + // Copy modified_blocks to event + for(core::map::Iterator + i = modified_blocks.getIterator(); + i.atEnd()==false; i++) + { + event.modified_blocks.insert(i.getNode()->getKey(), false); + } + + // Queue event + dispatchEvent(&event); + + return block; + } + } + return NULL; } -#endif #if 0 /* diff --git a/src/map.h b/src/map.h index 71101b8e4..a8aa8e679 100644 --- a/src/map.h +++ b/src/map.h @@ -57,7 +57,7 @@ enum MapEditEventType{ // Node metadata of block changed (not knowing which node exactly) // p stores block coordinate MEET_BLOCK_NODE_METADATA_CHANGED, - // Anything else + // Anything else (modified_blocks are set unsent) MEET_OTHER }; @@ -338,24 +338,13 @@ public: */ MapBlock * createBlock(v3s16 p); -#if 0 /* - NOTE: This comment might be outdated - Forcefully get a block from somewhere. - - InvalidPositionException possible if only_from_disk==true - - Parameters: - changed_blocks: Blocks that have been modified + - Memory + - Load from disk + - Generate */ - MapBlock * emergeBlock( - v3s16 p, - bool only_from_disk, - core::map &changed_blocks, - core::map &lighting_invalidated_blocks - ); -#endif + MapBlock * emergeBlock(v3s16 p, bool allow_generate=true); // Helper for placing objects on ground level s16 findGroundLevel(v2s16 p2d); diff --git a/src/server.cpp b/src/server.cpp index 798f36ac1..c2433e1af 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1739,6 +1739,7 @@ void Server::AsyncRunStep() */ if(far_players.size() > 0) { + // Convert list format to that wanted by SetBlocksNotSent core::map modified_blocks2; for(core::map::Iterator i = event->modified_blocks.getIterator(); @@ -1748,6 +1749,7 @@ void Server::AsyncRunStep() modified_blocks2.insert(p, m_env.getMap().getBlockNoCreateNoEx(p)); } + // Set blocks not sent for(core::list::Iterator i = far_players.begin(); i != far_players.end(); i++) -- cgit v1.2.3