aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/ServerLevel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Minecraft.Client/ServerLevel.cpp')
-rw-r--r--Minecraft.Client/ServerLevel.cpp574
1 files changed, 367 insertions, 207 deletions
diff --git a/Minecraft.Client/ServerLevel.cpp b/Minecraft.Client/ServerLevel.cpp
index de8c66cd..8501cbf9 100644
--- a/Minecraft.Client/ServerLevel.cpp
+++ b/Minecraft.Client/ServerLevel.cpp
@@ -6,26 +6,29 @@
#include "ServerPlayer.h"
#include "PlayerConnection.h"
#include "EntityTracker.h"
+#include "ServerScoreboard.h"
+#include "..\Minecraft.World\ScoreboardSaveData.h"
#include "..\Minecraft.World\net.minecraft.world.h"
+#include "..\Minecraft.World\net.minecraft.world.item.h"
+#include "..\Minecraft.World\net.minecraft.world.entity.h"
+#include "..\Minecraft.World\net.minecraft.world.entity.ai.village.h"
+#include "..\Minecraft.World\net.minecraft.world.entity.global.h"
+#include "..\Minecraft.World\net.minecraft.world.entity.npc.h"
+#include "..\Minecraft.World\net.minecraft.world.entity.player.h"
#include "..\Minecraft.World\net.minecraft.world.level.h"
+#include "..\Minecraft.World\net.minecraft.world.level.biome.h"
+#include "..\Minecraft.World\net.minecraft.world.level.chunk.h"
#include "..\Minecraft.World\net.minecraft.world.level.dimension.h"
+#include "..\Minecraft.World\net.minecraft.world.level.levelgen.feature.h"
#include "..\Minecraft.World\net.minecraft.world.level.storage.h"
-#include "..\Minecraft.World\net.minecraft.world.level.chunk.h"
#include "..\Minecraft.World\net.minecraft.world.level.tile.entity.h"
-#include "..\Minecraft.World\net.minecraft.world.level.biome.h"
-#include "..\Minecraft.World\net.minecraft.world.entity.h"
-#include "..\Minecraft.World\net.minecraft.world.entity.ai.village.h"
-#include "..\Minecraft.World\net.minecraft.world.entity.player.h"
-#include "..\Minecraft.World\net.minecraft.world.entity.npc.h"
-#include "..\Minecraft.World\net.minecraft.world.entity.global.h"
+#include "..\Minecraft.World\net.minecraft.world.scores.h"
#include "..\Minecraft.World\ItemEntity.h"
#include "..\Minecraft.World\Arrow.h"
#include "..\Minecraft.World\PrimedTnt.h"
#include "..\Minecraft.World\FallingTile.h"
#include "..\Minecraft.World\net.minecraft.network.packet.h"
#include "..\Minecraft.World\Mth.h"
-#include "..\Minecraft.World\net.minecraft.world.level.levelgen.feature.h"
-#include "..\Minecraft.World\net.minecraft.world.item.h"
#include "..\Minecraft.World\StructurePiece.h"
#include "..\Minecraft.Client\ServerLevelListener.h"
#include "..\Minecraft.World\WeighedTreasure.h"
@@ -65,17 +68,17 @@ void ServerLevel::staticCtor()
#endif
m_updateThread->Run();
- RANDOM_BONUS_ITEMS = WeighedTreasureArray(20);
+ RANDOM_BONUS_ITEMS = WeighedTreasureArray(20);
RANDOM_BONUS_ITEMS[0] = new WeighedTreasure(Item::stick_Id, 0, 1, 3, 10);
- RANDOM_BONUS_ITEMS[1] = new WeighedTreasure(Tile::wood_Id, 0, 1, 3, 10);
- RANDOM_BONUS_ITEMS[2] = new WeighedTreasure(Tile::treeTrunk_Id, 0, 1, 3, 10);
- RANDOM_BONUS_ITEMS[3] = new WeighedTreasure(Item::hatchet_stone_Id, 0, 1, 1, 3);
- RANDOM_BONUS_ITEMS[4] = new WeighedTreasure(Item::hatchet_wood_Id, 0, 1, 1, 5);
- RANDOM_BONUS_ITEMS[5] = new WeighedTreasure(Item::pickAxe_stone_Id, 0, 1, 1, 3);
- RANDOM_BONUS_ITEMS[6] = new WeighedTreasure(Item::pickAxe_wood_Id, 0, 1, 1, 5);
- RANDOM_BONUS_ITEMS[7] = new WeighedTreasure(Item::apple_Id, 0, 2, 3, 5);
- RANDOM_BONUS_ITEMS[8] = new WeighedTreasure(Item::bread_Id, 0, 2, 3, 3);
+ RANDOM_BONUS_ITEMS[1] = new WeighedTreasure(Tile::wood_Id, 0, 1, 3, 10);
+ RANDOM_BONUS_ITEMS[2] = new WeighedTreasure(Tile::treeTrunk_Id, 0, 1, 3, 10);
+ RANDOM_BONUS_ITEMS[3] = new WeighedTreasure(Item::hatchet_stone_Id, 0, 1, 1, 3);
+ RANDOM_BONUS_ITEMS[4] = new WeighedTreasure(Item::hatchet_wood_Id, 0, 1, 1, 5);
+ RANDOM_BONUS_ITEMS[5] = new WeighedTreasure(Item::pickAxe_stone_Id, 0, 1, 1, 3);
+ RANDOM_BONUS_ITEMS[6] = new WeighedTreasure(Item::pickAxe_wood_Id, 0, 1, 1, 5);
+ RANDOM_BONUS_ITEMS[7] = new WeighedTreasure(Item::apple_Id, 0, 2, 3, 5);
+ RANDOM_BONUS_ITEMS[8] = new WeighedTreasure(Item::bread_Id, 0, 2, 3, 3);
// 4J-PB - new items
RANDOM_BONUS_ITEMS[9] = new WeighedTreasure(Tile::sapling_Id, 0, 4, 4, 2);
RANDOM_BONUS_ITEMS[10] = new WeighedTreasure(Tile::sapling_Id, 1, 4, 4, 2);
@@ -87,7 +90,7 @@ void ServerLevel::staticCtor()
RANDOM_BONUS_ITEMS[16] = new WeighedTreasure(Item::dye_powder_Id, DyePowderItem::BROWN, 1, 2, 2);
RANDOM_BONUS_ITEMS[17] = new WeighedTreasure(Item::potato_Id, 0, 1, 2, 3);
RANDOM_BONUS_ITEMS[18] = new WeighedTreasure(Item::carrots_Id, 0, 1, 2, 3);
- RANDOM_BONUS_ITEMS[19] = new WeighedTreasure(Tile::mushroom1_Id, 0, 1, 2, 2);
+ RANDOM_BONUS_ITEMS[19] = new WeighedTreasure(Tile::mushroom_brown_Id, 0, 1, 2, 2);
};
@@ -110,8 +113,21 @@ ServerLevel::ServerLevel(MinecraftServer *server, shared_ptr<LevelStorage>levelS
server->setLevel(dimension, this); // The listener needs the server to have the level set up... this will be set up anyway on return of this ctor but setting up early here
addListener(new ServerLevelListener(server, this));
- this->tracker = new EntityTracker(this);
- this->chunkMap = new PlayerChunkMap(this, dimension, server->getPlayers()->getViewDistance());
+ tracker = new EntityTracker(this);
+ chunkMap = new PlayerChunkMap(this, dimension, server->getPlayers()->getViewDistance());
+
+ mobSpawner = new MobSpawner();
+ portalForcer = new PortalForcer(this);
+ scoreboard = new ServerScoreboard(server);
+
+ //shared_ptr<ScoreboardSaveData> scoreboardSaveData = dynamic_pointer_cast<ScoreboardSaveData>( savedDataStorage->get(typeid(ScoreboardSaveData), ScoreboardSaveData::FILE_ID) );
+ //if (scoreboardSaveData == NULL)
+ //{
+ // scoreboardSaveData = shared_ptr<ScoreboardSaveData>( new ScoreboardSaveData() );
+ // savedDataStorage->set(ScoreboardSaveData::FILE_ID, scoreboardSaveData);
+ //}
+ //scoreboardSaveData->setScoreboard(scoreboard);
+ //((ServerScoreboard *) scoreboard)->setSaveData(scoreboardSaveData);
// This also used to be called in parent ctor, but can't be called until chunkSource is created. Call now if required.
if (!levelData->isInitialized())
@@ -145,6 +161,9 @@ ServerLevel::ServerLevel(MinecraftServer *server, shared_ptr<LevelStorage>levelS
ServerLevel::~ServerLevel()
{
+ delete portalForcer;
+ delete mobSpawner;
+
EnterCriticalSection(&m_csQueueSendTileUpdates);
for(AUTO_VAR(it, m_queuedSendTileUpdates.begin()); it != m_queuedSendTileUpdates.end(); ++it)
{
@@ -175,41 +194,45 @@ ServerLevel::~ServerLevel()
void ServerLevel::tick()
{
Level::tick();
- if (getLevelData()->isHardcore() && difficulty < 3)
+ if (getLevelData()->isHardcore() && difficulty < 3)
{
- difficulty = 3;
- }
+ difficulty = 3;
+ }
dimension->biomeSource->update();
if (allPlayersAreSleeping())
{
- bool somebodyWokeUp = false;
- if (spawnEnemies && difficulty >= Difficulty::EASY)
- {
- }
-
- if (!somebodyWokeUp)
+ if (getGameRules()->getBoolean(GameRules::RULE_DAYLIGHT))
{
// skip time until new day
- __int64 newTime = levelData->getTime() + TICKS_PER_DAY;
+ __int64 newTime = levelData->getDayTime() + TICKS_PER_DAY;
// 4J : WESTY : Changed so that time update goes through stats tracking update code.
//levelData->setTime(newTime - (newTime % TICKS_PER_DAY));
- setTime(newTime - (newTime % TICKS_PER_DAY));
-
- awakenAllPlayers();
+ setDayTime(newTime - (newTime % TICKS_PER_DAY));
}
+ awakenAllPlayers();
}
PIXBeginNamedEvent(0,"Mob spawner tick");
// for Minecraft 1.8, spawn friendlies really rarely - 4J - altered from once every 400 ticks to 40 ticks as we depend on this a more than the original since we don't have chunk post-process spawning
- MobSpawner::tick(this, spawnEnemies, spawnFriendlies && (levelData->getTime() % 40) == 0);
+ if (getGameRules()->getBoolean(GameRules::RULE_DOMOBSPAWNING))
+ {
+ // Note - these flags are used logically in an inverted way. Mob spawning is not performed if:
+ // (1) finalSpawnEnemies isn't set, and mob category isn't friendly
+ // (2) finalSpawnFriendlies isn't set, and mob category is friendly
+ // (3) finalSpawnPersistent isn't set, and mob category is persistent
+ bool finalSpawnEnemies = spawnEnemies && ((levelData->getGameTime() % 2) == 0); // Spawn enemies every other tick
+ bool finalSpawnFriendlies = spawnFriendlies && ((levelData->getGameTime() % 40) == 0); // Spawn friendlies once per 40 ticks
+ bool finalSpawnPersistent = finalSpawnFriendlies && ((levelData->getGameTime() % 80) == 0); // All persistents are also friendly - do them once every other friendly spawning, ie once per 80 ticks
+ mobSpawner->tick(this, finalSpawnEnemies, finalSpawnFriendlies, finalSpawnPersistent);
+ }
PIXEndNamedEvent();
PIXBeginNamedEvent(0,"Chunk source tick");
chunkSource->tick();
PIXEndNamedEvent();
- int newDark = this->getOldSkyDarken(1);
+ int newDark = getOldSkyDarken(1);
if (newDark != skyDarken)
{
skyDarken = newDark;
@@ -222,16 +245,11 @@ void ServerLevel::tick()
}
}
}
-
- PIXBeginNamedEvent(0,"runTileEvents");
- // run after entity updates
- runTileEvents();
- PIXEndNamedEvent();
//4J - temporarily disabling saves as they are causing gameplay to generally stutter quite a lot
- __int64 time = levelData->getTime() + 1;
-// 4J Stu - Putting this back in, but I have reduced the number of chunks that save when not forced
+ __int64 time = levelData->getGameTime() + 1;
+ // 4J Stu - Putting this back in, but I have reduced the number of chunks that save when not forced
#ifdef _LARGE_WORLDS
if (time % (saveInterval) == (dimension->id + 1))
#else
@@ -246,7 +264,18 @@ void ServerLevel::tick()
// 4J : WESTY : Changed so that time update goes through stats tracking update code.
//levelData->setTime(time);
- setTime(time);
+ setGameTime(levelData->getGameTime() + 1);
+ if (getGameRules()->getBoolean(GameRules::RULE_DAYLIGHT))
+ {
+ // 4J: Debug setting added to keep it at day time
+#ifndef _FINAL_BUILD
+ bool freezeTime = app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_FreezeTime);
+ if (!freezeTime)
+#endif
+ {
+ setDayTime(levelData->getDayTime() + 1);
+ }
+ }
PIXBeginNamedEvent(0,"Tick pending ticks");
// if (tickCount % 5 == 0) {
@@ -268,8 +297,14 @@ void ServerLevel::tick()
//MemSect(0);
PIXEndNamedEvent();
+ PIXBeginNamedEvent(0,"Tick portal forcer");
+ portalForcer->tick(getGameTime());
+ PIXEndNamedEvent();
+
// repeat after tile ticks
+ PIXBeginNamedEvent(0,"runTileEvents");
runTileEvents();
+ PIXEndNamedEvent();
// 4J Added
runQueuedSendTileUpdates();
@@ -277,10 +312,10 @@ void ServerLevel::tick()
Biome::MobSpawnerData *ServerLevel::getRandomMobSpawnAt(MobCategory *mobCategory, int x, int y, int z)
{
- vector<Biome::MobSpawnerData *> *mobList = getChunkSource()->getMobsAt(mobCategory, x, y, z);
+ vector<Biome::MobSpawnerData *> *mobList = getChunkSource()->getMobsAt(mobCategory, x, y, z);
if (mobList == NULL || mobList->empty()) return NULL;
- return (Biome::MobSpawnerData *) WeighedRandom::getRandomItem(random, (vector<WeighedRandomItem *> *)mobList);
+ return (Biome::MobSpawnerData *) WeighedRandom::getRandomItem(random, (vector<WeighedRandomItem *> *)mobList);
}
void ServerLevel::updateSleepingPlayerList()
@@ -289,7 +324,7 @@ void ServerLevel::updateSleepingPlayerList()
m_bAtLeastOnePlayerSleeping = false;
AUTO_VAR(itEnd, players.end());
- for (vector<shared_ptr<Player> >::iterator it = players.begin(); it != itEnd; it++)
+ for (AUTO_VAR(it, players.begin()); it != itEnd; it++)
{
if (!(*it)->isSleeping())
{
@@ -454,7 +489,7 @@ void ServerLevel::tickTiles()
m_updateChunkX[iLev][m_updateChunkCount[iLev]] = cp.x;
m_updateChunkZ[iLev][m_updateChunkCount[iLev]++] = cp.z;
- LevelChunk *lc = this->getChunk(cp.x, cp.z);
+ LevelChunk *lc = getChunk(cp.x, cp.z);
tickClientSideTiles(xo, zo, lc);
if (random->nextInt(prob) == 0 && isRaining() && isThundering())
@@ -468,25 +503,24 @@ void ServerLevel::tickTiles()
if (isRainingAt(x, y, z))
{
addGlobalEntity( shared_ptr<LightningBolt>( new LightningBolt(this, x, y, z) ) );
- lightningTime = 2;
}
}
// 4J - changes here brought forrward from 1.2.3
if (random->nextInt(16) == 0)
{
- randValue = randValue * 3 + addend;
- int val = (randValue >> 2);
- int x = (val & 15);
- int z = ((val >> 8) & 15);
- int yy = this->getTopRainBlock(x + xo, z + zo);
- if (shouldFreeze(x + xo, yy - 1, z + zo))
+ randValue = randValue * 3 + addend;
+ int val = (randValue >> 2);
+ int x = (val & 15);
+ int z = ((val >> 8) & 15);
+ int yy = getTopRainBlock(x + xo, z + zo);
+ if (shouldFreeze(x + xo, yy - 1, z + zo))
{
- setTile(x + xo, yy - 1, z + zo, Tile::ice_Id);
- }
- if (isRaining() && shouldSnow(x + xo, yy, z + zo))
+ setTileAndUpdate(x + xo, yy - 1, z + zo, Tile::ice_Id);
+ }
+ if (isRaining() && shouldSnow(x + xo, yy, z + zo))
{
- setTile(x + xo, yy, z + zo, Tile::topSnow_Id);
+ setTileAndUpdate(x + xo, yy, z + zo, Tile::topSnow_Id);
}
if (isRaining())
{
@@ -512,30 +546,50 @@ void ServerLevel::tickTiles()
m_updateTrigger->Set(iLev);
}
+bool ServerLevel::isTileToBeTickedAt(int x, int y, int z, int tileId)
+{
+ TickNextTickData td = TickNextTickData(x, y, z, tileId);
+ return std::find(toBeTicked.begin(), toBeTicked.end(), td) != toBeTicked.end();
+}
+
void ServerLevel::addToTickNextTick(int x, int y, int z, int tileId, int tickDelay)
{
+ addToTickNextTick(x, y, z, tileId, tickDelay, 0);
+}
+
+void ServerLevel::addToTickNextTick(int x, int y, int z, int tileId, int tickDelay, int priorityTilt)
+{
MemSect(27);
TickNextTickData td = TickNextTickData(x, y, z, tileId);
- int r = 8;
- if (getInstaTick())
+ int r = 0;
+ if (getInstaTick() && tileId > 0)
{
- if (hasChunksAt(td.x - r, td.y - r, td.z - r, td.x + r, td.y + r, td.z + r))
+ if(Tile::tiles[tileId]->canInstantlyTick())
{
- int id = getTile(td.x, td.y, td.z);
- if (id == td.tileId && id > 0)
+ r = 8;
+ if (hasChunksAt(td.x - r, td.y - r, td.z - r, td.x + r, td.y + r, td.z + r))
{
- Tile::tiles[id]->tick(this, td.x, td.y, td.z, random);
+ int id = getTile(td.x, td.y, td.z);
+ if (id == td.tileId && id > 0)
+ {
+ Tile::tiles[id]->tick(this, td.x, td.y, td.z, random);
+ }
}
+ MemSect(0);
+ return;
+ }
+ else
+ {
+ tickDelay = 1;
}
- MemSect(0);
- return;
}
if (hasChunksAt(x - r, y - r, z - r, x + r, y + r, z + r))
{
if (tileId > 0)
{
- td.delay(tickDelay + levelData->getTime());
+ td.delay(tickDelay + levelData->getGameTime());
+ td.setPriorityTilt(priorityTilt);
}
EnterCriticalSection(&m_tickNextTickCS);
if ( tickNextTickSet.find(td) == tickNextTickSet.end() )
@@ -548,20 +602,21 @@ void ServerLevel::addToTickNextTick(int x, int y, int z, int tileId, int tickDel
MemSect(0);
}
-void ServerLevel::forceAddTileTick(int x, int y, int z, int tileId, int tickDelay)
+void ServerLevel::forceAddTileTick(int x, int y, int z, int tileId, int tickDelay, int prioTilt)
{
- TickNextTickData td = TickNextTickData(x, y, z, tileId);
+ TickNextTickData td = TickNextTickData(x, y, z, tileId);
+ td.setPriorityTilt(prioTilt);
- if (tileId > 0)
+ if (tileId > 0)
{
- td.delay(tickDelay + levelData->getTime());
- }
+ td.delay(tickDelay + levelData->getGameTime());
+ }
EnterCriticalSection(&m_tickNextTickCS);
if ( tickNextTickSet.find(td) == tickNextTickSet.end() )
{
- tickNextTickSet.insert(td);
- tickNextTickList.insert(td);
- }
+ tickNextTickSet.insert(td);
+ tickNextTickList.insert(td);
+ }
LeaveCriticalSection(&m_tickNextTickCS);
}
@@ -576,12 +631,17 @@ void ServerLevel::tickEntities()
}
else
{
- emptyTime = 0;
+ resetEmptyTime();
}
Level::tickEntities();
}
+void ServerLevel::resetEmptyTime()
+{
+ emptyTime = 0;
+}
+
bool ServerLevel::tickPendingTicks(bool force)
{
EnterCriticalSection(&m_tickNextTickCS);
@@ -593,29 +653,43 @@ bool ServerLevel::tickPendingTicks(bool force)
//throw new IllegalStateException("TickNextTick list out of synch");
}
if (count > MAX_TICK_TILES_PER_TICK) count = MAX_TICK_TILES_PER_TICK;
-
+
AUTO_VAR(itTickList, tickNextTickList.begin());
for (int i = 0; i < count; i++)
{
TickNextTickData td = *(itTickList);
- if (!force && td.m_delay > levelData->getTime())
+ if (!force && td.m_delay > levelData->getGameTime())
{
break;
}
itTickList = tickNextTickList.erase(itTickList);
tickNextTickSet.erase(td);
- int r = 8;
+ toBeTicked.push_back(td);
+ }
+
+ for(AUTO_VAR(it,toBeTicked.begin()); it != toBeTicked.end();)
+ {
+ TickNextTickData td = *it;
+ it = toBeTicked.erase(it);
+
+ int r = 0;
if (hasChunksAt(td.x - r, td.y - r, td.z - r, td.x + r, td.y + r, td.z + r))
{
int id = getTile(td.x, td.y, td.z);
- if (id == td.tileId && id > 0)
+ if (id > 0 && Tile::isMatching(id, td.tileId))
{
Tile::tiles[id]->tick(this, td.x, td.y, td.z, random);
}
}
+ else
+ {
+ addToTickNextTick(td.x, td.y, td.z, td.tileId, 0);
+ }
}
+ toBeTicked.clear();
+
int count3 = (int)tickNextTickList.size();
int count4 = (int)tickNextTickSet.size();
@@ -628,36 +702,72 @@ bool ServerLevel::tickPendingTicks(bool force)
vector<TickNextTickData> *ServerLevel::fetchTicksInChunk(LevelChunk *chunk, bool remove)
{
EnterCriticalSection(&m_tickNextTickCS);
- vector<TickNextTickData> *results = new vector<TickNextTickData>;
+ vector<TickNextTickData> *results = new vector<TickNextTickData>;
- ChunkPos *pos = chunk->getPos();
- int west = pos->x << 4;
- int east = west + 16;
- int north = pos->z << 4;
- int south = north + 16;
+ ChunkPos *pos = chunk->getPos();
+ int xMin = (pos->x << 4) - 2;
+ int xMax = (xMin + 16) + 2;
+ int zMin = (pos->z << 4) - 2;
+ int zMax = (zMin + 16) + 2;
delete pos;
- for( AUTO_VAR(it, tickNextTickSet.begin()); it != tickNextTickSet.end(); )
+ for (int i = 0; i < 2; i++)
{
- TickNextTickData td = *it;
-
- if (td.x >= west && td.x < east && td.z >= north && td.z < south)
+ if (i == 0)
{
- if (remove)
- {
- tickNextTickList.erase(td);
- it = tickNextTickSet.erase(it);
- }
- else
+ for( AUTO_VAR(it, tickNextTickList.begin()); it != tickNextTickList.end(); )
{
- it++;
- }
+ TickNextTickData td = *it;
+
+ if (td.x >= xMin && td.x < xMax && td.z >= zMin && td.z < zMax)
+ {
+ if (remove)
+ {
+ tickNextTickSet.erase(td);
+ it = tickNextTickList.erase(it);
+ }
+ else
+ {
+ it++;
+ }
- results->push_back(td);
- }
+ results->push_back(td);
+ }
+ else
+ {
+ it++;
+ }
+ }
+ }
else
{
- it++;
+ if (!toBeTicked.empty())
+ {
+ app.DebugPrintf("To be ticked size: %d\n",toBeTicked.size());
+ }
+ for( AUTO_VAR(it, toBeTicked.begin()); it != toBeTicked.end();)
+ {
+ TickNextTickData td = *it;
+
+ if (td.x >= xMin && td.x < xMax && td.z >= zMin && td.z < zMax)
+ {
+ if (remove)
+ {
+ tickNextTickList.erase(td);
+ it = toBeTicked.erase(it);
+ }
+ else
+ {
+ it++;
+ }
+
+ results->push_back(td);
+ }
+ else
+ {
+ it++;
+ }
+ }
}
}
@@ -667,18 +777,15 @@ vector<TickNextTickData> *ServerLevel::fetchTicksInChunk(LevelChunk *chunk, bool
void ServerLevel::tick(shared_ptr<Entity> e, bool actual)
{
- if (!server->isAnimals() && ((e->GetType() & eTYPE_ANIMAL) || (e->GetType() & eTYPE_WATERANIMAL)))
+ if ( !server->isAnimals() && (e->instanceof(eTYPE_ANIMAL) || e->instanceof(eTYPE_WATERANIMAL)) )
{
- e->remove();
- }
+ e->remove();
+ }
if (!server->isNpcsEnabled() && (dynamic_pointer_cast<Npc>(e) != NULL))
{
e->remove();
}
- if (e->rider.lock() == NULL || (dynamic_pointer_cast<Player>(e->rider.lock())==NULL) ) // 4J - was !(e->rider instanceof Player)
- {
- Level::tick(e, actual);
- }
+ Level::tick(e, actual);
}
void ServerLevel::forceTick(shared_ptr<Entity> e, bool actual)
@@ -688,23 +795,23 @@ void ServerLevel::forceTick(shared_ptr<Entity> e, bool actual)
ChunkSource *ServerLevel::createChunkSource()
{
- ChunkStorage *storage = levelStorage->createChunkStorage(dimension);
+ ChunkStorage *storage = levelStorage->createChunkStorage(dimension);
cache = new ServerChunkCache(this, storage, dimension->createRandomLevelSource());
- return cache;
+ return cache;
}
vector<shared_ptr<TileEntity> > *ServerLevel::getTileEntitiesInRegion(int x0, int y0, int z0, int x1, int y1, int z1)
{
- vector<shared_ptr<TileEntity> > *result = new vector<shared_ptr<TileEntity> >;
- for (unsigned int i = 0; i < tileEntityList.size(); i++)
+ vector<shared_ptr<TileEntity> > *result = new vector<shared_ptr<TileEntity> >;
+ for (unsigned int i = 0; i < tileEntityList.size(); i++)
{
- shared_ptr<TileEntity> te = tileEntityList[i];
- if (te->x >= x0 && te->y >= y0 && te->z >= z0 && te->x < x1 && te->y < y1 && te->z < z1)
+ shared_ptr<TileEntity> te = tileEntityList[i];
+ if (te->x >= x0 && te->y >= y0 && te->z >= z0 && te->x < x1 && te->y < y1 && te->z < z1)
{
- result->push_back(te);
- }
- }
- return result;
+ result->push_back(te);
+ }
+ }
+ return result;
}
bool ServerLevel::mayInteract(shared_ptr<Player> player, int xt, int yt, int zt, int content)
@@ -720,10 +827,7 @@ bool ServerLevel::mayInteract(shared_ptr<Player> player, int xt, int yt, int zt,
}
else if(dimension->id == 0) // 4J Stu - Only limit this in the overworld
{
- int xd = (int) Mth::abs((float)(xt - levelData->getXSpawn()));
- int zd = (int) Mth::abs((float)(zt - levelData->getZSpawn()));
- if (xd > zd) zd = xd;
- return (zd > 16 || server->getPlayers()->isOp(player->name));
+ return !server->isUnderSpawnProtection(this, xt, yt, zt, player);
}
return true;
}
@@ -783,7 +887,7 @@ void ServerLevel::setInitialSpawn(LevelSettings *levelSettings)
zSpawn += random.nextInt(64) - random.nextInt(64);
if(zSpawn>maxXZ) zSpawn=0;
if(zSpawn<minXZ) zSpawn=0;
-
+
if (++tries == 1000) break;
}
@@ -798,8 +902,8 @@ void ServerLevel::setInitialSpawn(LevelSettings *levelSettings)
// 4J - brought forward from 1.3.2
void ServerLevel::generateBonusItemsNearSpawn()
{
- // once we've found the initial spawn, try to find a location for the
-// starting bonus chest
+ // once we've found the initial spawn, try to find a location for the
+ // starting bonus chest
// 4J - added - scan the spawn area first to see if there's already a chest near here
static const int r = 20;
@@ -811,7 +915,7 @@ void ServerLevel::generateBonusItemsNearSpawn()
int x = xx + xs;
int z = zz + zs;
int y = getTopSolidBlock( x, z ) - 1;
-
+
if( getTile( x, y, z ) == Tile::chest_Id )
{
shared_ptr<ChestTileEntity> chest = dynamic_pointer_cast<ChestTileEntity>(getTileEntity(x, y, z));
@@ -825,19 +929,19 @@ void ServerLevel::generateBonusItemsNearSpawn()
}
}
- BonusChestFeature *feature = new BonusChestFeature(RANDOM_BONUS_ITEMS, 16);
- for (int attempt = 0; attempt < 16; attempt++)
- {
- int x = levelData->getXSpawn() + random->nextInt(6) - random->nextInt(6);
- int z = levelData->getZSpawn() + random->nextInt(6) - random->nextInt(6);
- int y = getTopSolidBlock(x, z) + 1;
-
- if (feature->place(this, random, x, y, z, (attempt == 15) ))
+ BonusChestFeature *feature = new BonusChestFeature(RANDOM_BONUS_ITEMS, 16);
+ for (int attempt = 0; attempt < 16; attempt++)
{
- break;
- }
- }
- delete feature;
+ int x = levelData->getXSpawn() + random->nextInt(6) - random->nextInt(6);
+ int z = levelData->getZSpawn() + random->nextInt(6) - random->nextInt(6);
+ int y = getTopSolidBlock(x, z) + 1;
+
+ if (feature->place(this, random, x, y, z, (attempt == 15) ))
+ {
+ break;
+ }
+ }
+ delete feature;
}
Pos *ServerLevel::getDimensionSpecificSpawn()
@@ -871,7 +975,7 @@ void ServerLevel::save(bool force, ProgressListener *progressListener, bool bAut
{
progressListener->progressStartNoAbort(IDS_PROGRESS_SAVING_LEVEL);
}
-
+
}
PIXBeginNamedEvent(0,"Saving level data");
saveLevelData();
@@ -950,8 +1054,8 @@ void ServerLevel::saveLevelData()
void ServerLevel::entityAdded(shared_ptr<Entity> e)
{
- Level::entityAdded(e);
- entitiesById[e->entityId] = e;
+ Level::entityAdded(e);
+ entitiesById[e->entityId] = e;
vector<shared_ptr<Entity> > *es = e->getSubEntities();
if (es != NULL)
{
@@ -966,7 +1070,7 @@ void ServerLevel::entityAdded(shared_ptr<Entity> e)
void ServerLevel::entityRemoved(shared_ptr<Entity> e)
{
- Level::entityRemoved(e);
+ Level::entityRemoved(e);
entitiesById.erase(e->entityId);
vector<shared_ptr<Entity> > *es = e->getSubEntities();
if (es != NULL)
@@ -987,29 +1091,29 @@ shared_ptr<Entity> ServerLevel::getEntity(int id)
bool ServerLevel::addGlobalEntity(shared_ptr<Entity> e)
{
- if (Level::addGlobalEntity(e))
+ if (Level::addGlobalEntity(e))
{
- server->getPlayers()->broadcast(e->x, e->y, e->z, 512, dimension->id, shared_ptr<AddGlobalEntityPacket>( new AddGlobalEntityPacket(e) ) );
- return true;
- }
- return false;
+ server->getPlayers()->broadcast(e->x, e->y, e->z, 512, dimension->id, shared_ptr<AddGlobalEntityPacket>( new AddGlobalEntityPacket(e) ) );
+ return true;
+ }
+ return false;
}
void ServerLevel::broadcastEntityEvent(shared_ptr<Entity> e, byte event)
{
- shared_ptr<Packet> p = shared_ptr<EntityEventPacket>( new EntityEventPacket(e->entityId, event) );
- server->getLevel(dimension->id)->getTracker()->broadcastAndSend(e, p);
+ shared_ptr<Packet> p = shared_ptr<EntityEventPacket>( new EntityEventPacket(e->entityId, event) );
+ server->getLevel(dimension->id)->getTracker()->broadcastAndSend(e, p);
}
shared_ptr<Explosion> ServerLevel::explode(shared_ptr<Entity> source, double x, double y, double z, float r, bool fire, bool destroyBlocks)
{
- // instead of calling super, we run the same explosion code here except
- // we don't generate any particles
- shared_ptr<Explosion> explosion = shared_ptr<Explosion>( new Explosion(this, source, x, y, z, r) );
- explosion->fire = fire;
+ // instead of calling super, we run the same explosion code here except
+ // we don't generate any particles
+ shared_ptr<Explosion> explosion = shared_ptr<Explosion>( new Explosion(this, source, x, y, z, r) );
+ explosion->fire = fire;
explosion->destroyBlocks = destroyBlocks;
- explosion->explode();
- explosion->finalizeExplosion(false);
+ explosion->explode();
+ explosion->finalizeExplosion(false);
if (!destroyBlocks)
{
@@ -1044,17 +1148,17 @@ shared_ptr<Explosion> ServerLevel::explode(shared_ptr<Entity> source, double x,
}
}
- if (player->distanceToSqr(x, y, z) < 64 * 64)
+ if (player->distanceToSqr(x, y, z) < 64 * 64)
{
Vec3 *knockbackVec = explosion->getHitPlayerKnockback(player);
//app.DebugPrintf("Sending %s with knockback (%f,%f,%f)\n", knockbackOnly?"knockbackOnly":"allExplosion",knockbackVec->x,knockbackVec->y,knockbackVec->z);
// If the player is not the primary on the system, then we only want to send info for the knockback
player->connection->send( shared_ptr<ExplodePacket>( new ExplodePacket(x, y, z, r, &explosion->toBlow, knockbackVec, knockbackOnly)));
sentTo.push_back( player );
- }
- }
+ }
+ }
- return explosion;
+ return explosion;
}
void ServerLevel::tileEvent(int x, int y, int z, int tile, int b0, int b1)
@@ -1099,8 +1203,7 @@ bool ServerLevel::doTileEvent(TileEventData *te)
{
int t = getTile(te->getX(), te->getY(), te->getZ());
if (t == te->getTile()) {
- Tile::tiles[t]->triggerEvent(this, te->getX(), te->getY(), te->getZ(), te->getParamA(), te->getParamB());
- return true;
+ return Tile::tiles[t]->triggerEvent(this, te->getX(), te->getY(), te->getZ(), te->getParamA(), te->getParamB());
}
return false;
}
@@ -1112,20 +1215,20 @@ void ServerLevel::closeLevelStorage()
void ServerLevel::tickWeather()
{
- bool wasRaining = isRaining();
- Level::tickWeather();
+ bool wasRaining = isRaining();
+ Level::tickWeather();
- if (wasRaining != isRaining())
+ if (wasRaining != isRaining())
{
- if (wasRaining)
+ if (wasRaining)
{
- server->getPlayers()->broadcastAll( shared_ptr<GameEventPacket>( new GameEventPacket(GameEventPacket::STOP_RAINING, 0) ) );
- }
+ server->getPlayers()->broadcastAll( shared_ptr<GameEventPacket>( new GameEventPacket(GameEventPacket::STOP_RAINING, 0) ) );
+ }
else
{
- server->getPlayers()->broadcastAll( shared_ptr<GameEventPacket>( new GameEventPacket(GameEventPacket::START_RAINING, 0) ) );
- }
- }
+ server->getPlayers()->broadcastAll( shared_ptr<GameEventPacket>( new GameEventPacket(GameEventPacket::START_RAINING, 0) ) );
+ }
+ }
}
@@ -1141,7 +1244,7 @@ EntityTracker *ServerLevel::getTracker()
void ServerLevel::setTimeAndAdjustTileTicks(__int64 newTime)
{
- __int64 delta = newTime - levelData->getTime();
+ __int64 delta = newTime - levelData->getGameTime();
// 4J - can't directly adjust m_delay in a set as it has a const interator, since changing values in here might change the ordering of the elements in the set.
// Instead move to a vector, do the adjustment, put back in the set.
vector<TickNextTickData> temp;
@@ -1155,7 +1258,7 @@ void ServerLevel::setTimeAndAdjustTileTicks(__int64 newTime)
{
tickNextTickList.insert(temp[i]);
}
- setTime(newTime);
+ setGameTime(newTime);
}
PlayerChunkMap *ServerLevel::getChunkMap()
@@ -1163,6 +1266,28 @@ PlayerChunkMap *ServerLevel::getChunkMap()
return chunkMap;
}
+PortalForcer *ServerLevel::getPortalForcer()
+{
+ return portalForcer;
+}
+
+void ServerLevel::sendParticles(const wstring &name, double x, double y, double z, int count)
+{
+ sendParticles(name, x + 0.5f, y + 0.5f, z + 0.5f, count, 0.5f, 0.5f, 0.5f, 0.02f);
+}
+
+void ServerLevel::sendParticles(const wstring &name, double x, double y, double z, int count, double xDist, double yDist, double zDist, double speed)
+{
+ shared_ptr<Packet> packet = shared_ptr<LevelParticlesPacket>( new LevelParticlesPacket(name, (float) x, (float) y, (float) z, (float) xDist, (float) yDist, (float) zDist, (float) speed, count) );
+
+
+ for(AUTO_VAR(it, players.begin()); it != players.end(); ++it)
+ {
+ shared_ptr<ServerPlayer> player = dynamic_pointer_cast<ServerPlayer>(*it);
+ player->connection->send(packet);
+ }
+}
+
// 4J Stu - Sometimes we want to update tiles on the server from the main thread (eg SignTileEntity when string verify returns)
void ServerLevel::queueSendTileUpdate(int x, int y, int z)
{
@@ -1188,19 +1313,19 @@ void ServerLevel::runQueuedSendTileUpdates()
bool ServerLevel::addEntity(shared_ptr<Entity> e)
{
// If its an item entity, and we've got to our capacity, delete the oldest
- if( dynamic_pointer_cast<ItemEntity>(e) != NULL )
+ if( e->instanceof(eTYPE_ITEMENTITY) )
{
-// printf("Adding item entity count %d\n",m_itemEntities.size());
+ // printf("Adding item entity count %d\n",m_itemEntities.size());
EnterCriticalSection(&m_limiterCS);
if( m_itemEntities.size() >= MAX_ITEM_ENTITIES )
{
-// printf("Adding - doing remove\n");
+ // printf("Adding - doing remove\n");
removeEntityImmediately(m_itemEntities.front());
}
LeaveCriticalSection(&m_limiterCS);
}
// If its an hanging entity, and we've got to our capacity, delete the oldest
- else if( dynamic_pointer_cast<HangingEntity>(e) != NULL )
+ else if( e->instanceof(eTYPE_HANGING_ENTITY) )
{
// printf("Adding item entity count %d\n",m_itemEntities.size());
EnterCriticalSection(&m_limiterCS);
@@ -1217,25 +1342,25 @@ bool ServerLevel::addEntity(shared_ptr<Entity> e)
LeaveCriticalSection(&m_limiterCS);
}
// If its an arrow entity, and we've got to our capacity, delete the oldest
- else if( dynamic_pointer_cast<Arrow>(e) != NULL )
+ else if( e->instanceof(eTYPE_ARROW) )
{
-// printf("Adding arrow entity count %d\n",m_arrowEntities.size());
+ // printf("Adding arrow entity count %d\n",m_arrowEntities.size());
EnterCriticalSection(&m_limiterCS);
if( m_arrowEntities.size() >= MAX_ARROW_ENTITIES )
{
-// printf("Adding - doing remove\n");
+ // printf("Adding - doing remove\n");
removeEntityImmediately(m_arrowEntities.front());
}
LeaveCriticalSection(&m_limiterCS);
}
// If its an experience orb entity, and we've got to our capacity, delete the oldest
- else if( dynamic_pointer_cast<ExperienceOrb>(e) != NULL )
+ else if( e->instanceof(eTYPE_EXPERIENCEORB) )
{
-// printf("Adding arrow entity count %d\n",m_arrowEntities.size());
+ // printf("Adding arrow entity count %d\n",m_arrowEntities.size());
EnterCriticalSection(&m_limiterCS);
if( m_experienceOrbEntities.size() >= MAX_EXPERIENCEORB_ENTITIES )
{
-// printf("Adding - doing remove\n");
+ // printf("Adding - doing remove\n");
removeEntityImmediately(m_experienceOrbEntities.front());
}
LeaveCriticalSection(&m_limiterCS);
@@ -1243,44 +1368,79 @@ bool ServerLevel::addEntity(shared_ptr<Entity> e)
return Level::addEntity(e);
}
+// 4J: Returns true if the level is at its limit for this type of entity (only checks arrows, hanging, item and experience orbs)
+bool ServerLevel::atEntityLimit(shared_ptr<Entity> e)
+{
+ // TODO: This duplicates code from addEntity above, fix
+
+ bool atLimit = false;
+
+ if( e->instanceof(eTYPE_ITEMENTITY) )
+ {
+ EnterCriticalSection(&m_limiterCS);
+ atLimit = m_itemEntities.size() >= MAX_ITEM_ENTITIES;
+ LeaveCriticalSection(&m_limiterCS);
+ }
+ else if( e->instanceof(eTYPE_HANGING_ENTITY) )
+ {
+ EnterCriticalSection(&m_limiterCS);
+ atLimit = m_hangingEntities.size() >= MAX_HANGING_ENTITIES;
+ LeaveCriticalSection(&m_limiterCS);
+ }
+ else if( e->instanceof(eTYPE_ARROW) )
+ {
+ EnterCriticalSection(&m_limiterCS);
+ atLimit = m_arrowEntities.size() >= MAX_ARROW_ENTITIES;
+ LeaveCriticalSection(&m_limiterCS);
+ }
+ else if( e->instanceof(eTYPE_EXPERIENCEORB) )
+ {
+ EnterCriticalSection(&m_limiterCS);
+ atLimit = m_experienceOrbEntities.size() >= MAX_EXPERIENCEORB_ENTITIES;
+ LeaveCriticalSection(&m_limiterCS);
+ }
+
+ return atLimit;
+}
+
// Maintain a cound of primed tnt & falling tiles in this level
void ServerLevel::entityAddedExtra(shared_ptr<Entity> e)
{
- if( dynamic_pointer_cast<ItemEntity>(e) != NULL )
+ if( e->instanceof(eTYPE_ITEMENTITY) )
{
EnterCriticalSection(&m_limiterCS);
m_itemEntities.push_back(e);
-// printf("entity added: item entity count now %d\n",m_itemEntities.size());
+ // printf("entity added: item entity count now %d\n",m_itemEntities.size());
LeaveCriticalSection(&m_limiterCS);
}
- else if( dynamic_pointer_cast<HangingEntity>(e) != NULL )
+ else if( e->instanceof(eTYPE_HANGING_ENTITY) )
{
EnterCriticalSection(&m_limiterCS);
m_hangingEntities.push_back(e);
// printf("entity added: item entity count now %d\n",m_itemEntities.size());
LeaveCriticalSection(&m_limiterCS);
}
- else if( dynamic_pointer_cast<Arrow>(e) != NULL )
+ else if( e->instanceof(eTYPE_ARROW) )
{
EnterCriticalSection(&m_limiterCS);
m_arrowEntities.push_back(e);
-// printf("entity added: arrow entity count now %d\n",m_arrowEntities.size());
+ // printf("entity added: arrow entity count now %d\n",m_arrowEntities.size());
LeaveCriticalSection(&m_limiterCS);
}
- else if( dynamic_pointer_cast<ExperienceOrb>(e) != NULL )
+ else if( e->instanceof(eTYPE_EXPERIENCEORB) )
{
EnterCriticalSection(&m_limiterCS);
m_experienceOrbEntities.push_back(e);
-// printf("entity added: experience orb entity count now %d\n",m_arrowEntities.size());
+ // printf("entity added: experience orb entity count now %d\n",m_arrowEntities.size());
LeaveCriticalSection(&m_limiterCS);
}
- else if( dynamic_pointer_cast<PrimedTnt>(e) != NULL )
+ else if( e->instanceof(eTYPE_PRIMEDTNT) )
{
EnterCriticalSection(&m_limiterCS);
m_primedTntCount++;
LeaveCriticalSection(&m_limiterCS);
}
- else if( dynamic_pointer_cast<FallingTile>(e) != NULL )
+ else if( e->instanceof(eTYPE_FALLINGTILE) )
{
EnterCriticalSection(&m_limiterCS);
m_fallingTileCount++;
@@ -1291,20 +1451,20 @@ void ServerLevel::entityAddedExtra(shared_ptr<Entity> e)
// Maintain a cound of primed tnt & falling tiles in this level, and remove any item entities from our list
void ServerLevel::entityRemovedExtra(shared_ptr<Entity> e)
{
- if( dynamic_pointer_cast<ItemEntity>(e) != NULL )
+ if( e->instanceof(eTYPE_ITEMENTITY) )
{
EnterCriticalSection(&m_limiterCS);
-// printf("entity removed: item entity count %d\n",m_itemEntities.size());
+ // printf("entity removed: item entity count %d\n",m_itemEntities.size());
AUTO_VAR(it, find(m_itemEntities.begin(),m_itemEntities.end(),e));
if( it != m_itemEntities.end() )
{
-// printf("Item to remove found\n");
+ // printf("Item to remove found\n");
m_itemEntities.erase(it);
}
-// printf("entity removed: item entity count now %d\n",m_itemEntities.size());
+ // printf("entity removed: item entity count now %d\n",m_itemEntities.size());
LeaveCriticalSection(&m_limiterCS);
}
- else if( dynamic_pointer_cast<HangingEntity>(e) != NULL )
+ else if( e->instanceof(eTYPE_HANGING_ENTITY) )
{
EnterCriticalSection(&m_limiterCS);
// printf("entity removed: item entity count %d\n",m_itemEntities.size());
@@ -1317,39 +1477,39 @@ void ServerLevel::entityRemovedExtra(shared_ptr<Entity> e)
// printf("entity removed: item entity count now %d\n",m_itemEntities.size());
LeaveCriticalSection(&m_limiterCS);
}
- else if( dynamic_pointer_cast<Arrow>(e) != NULL )
+ else if( e->instanceof(eTYPE_ARROW) )
{
EnterCriticalSection(&m_limiterCS);
-// printf("entity removed: arrow entity count %d\n",m_arrowEntities.size());
+ // printf("entity removed: arrow entity count %d\n",m_arrowEntities.size());
AUTO_VAR(it, find(m_arrowEntities.begin(),m_arrowEntities.end(),e));
if( it != m_arrowEntities.end() )
{
-// printf("Item to remove found\n");
+ // printf("Item to remove found\n");
m_arrowEntities.erase(it);
}
-// printf("entity removed: arrow entity count now %d\n",m_arrowEntities.size());
+ // printf("entity removed: arrow entity count now %d\n",m_arrowEntities.size());
LeaveCriticalSection(&m_limiterCS);
}
- else if( dynamic_pointer_cast<ExperienceOrb>(e) != NULL )
+ else if( e->instanceof(eTYPE_EXPERIENCEORB) )
{
EnterCriticalSection(&m_limiterCS);
-// printf("entity removed: experience orb entity count %d\n",m_arrowEntities.size());
+ // printf("entity removed: experience orb entity count %d\n",m_arrowEntities.size());
AUTO_VAR(it, find(m_experienceOrbEntities.begin(),m_experienceOrbEntities.end(),e));
if( it != m_experienceOrbEntities.end() )
{
-// printf("Item to remove found\n");
+ // printf("Item to remove found\n");
m_experienceOrbEntities.erase(it);
}
-// printf("entity removed: experience orb entity count now %d\n",m_arrowEntities.size());
+ // printf("entity removed: experience orb entity count now %d\n",m_arrowEntities.size());
LeaveCriticalSection(&m_limiterCS);
}
- else if( dynamic_pointer_cast<PrimedTnt>(e) != NULL )
+ else if( e->instanceof(eTYPE_PRIMEDTNT) )
{
EnterCriticalSection(&m_limiterCS);
m_primedTntCount--;
LeaveCriticalSection(&m_limiterCS);
}
- else if( dynamic_pointer_cast<FallingTile>(e) != NULL )
+ else if( e->instanceof(eTYPE_FALLINGTILE) )
{
EnterCriticalSection(&m_limiterCS);
m_fallingTileCount--;