TU19: merge Minecraft.Client/Level

This commit is contained in:
Tropical 2026-03-21 20:29:13 -05:00
parent 1c12bedc86
commit b319cb3cea
6 changed files with 417 additions and 175 deletions

View file

@ -9,9 +9,11 @@
#include "../MinecraftServer.h"
#include "ServerLevel.h"
#include "../Minecraft.h"
#include "../Rendering/Particles/FireworksParticles.h"
#include "../../Minecraft.World/Entities/Mobs/PrimedTnt.h"
#include "../../Minecraft.World/Blocks/Tile.h"
#include "../../Minecraft.World/Blocks/TileEntities/TileEntity.h"
#include "../../Minecraft.World/Util/JavaMath.h"
MultiPlayerLevel::ResetInfo::ResetInfo(int x, int y, int z, int tile,
int data) {
@ -53,10 +55,10 @@ MultiPlayerLevel::MultiPlayerLevel(ClientConnection* connection,
// multiplayer, this should only be set by receiving a packet from the
// server (which happens when a player logs in)
// setSpawnPos(new Pos(8, 64, 8));
// The base ctor already has made some storage, so need to delete that
// The base ctor already has made some storage, so need to delete that
if (this->savedDataStorage) delete savedDataStorage;
if (connection != NULL) {
this->savedDataStorage = connection->savedDataStorage;
savedDataStorage = connection->savedDataStorage;
}
unshareCheckX = 0;
unshareCheckZ = 0;
@ -88,17 +90,30 @@ void MultiPlayerLevel::shareChunkAt(int x, int z) {
void MultiPlayerLevel::tick() {
PIXBeginNamedEvent(0, "Sky color changing");
setTime(getTime() + 1);
setGameTime(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(getDayTime() + 1);
}
}
/* 4J - change brought forward from 1.8.2
int newDark = this->getSkyDarken(1);
if (newDark != skyDarken)
int newDark = this->getSkyDarken(1);
if (newDark != skyDarken)
{
skyDarken = newDark;
for (unsigned int i = 0; i < listeners.size(); i++)
{
listeners[i]->skyColorChanged();
{
listeners[i]->skyColorChanged();
}
}*/
}*/
PIXEndNamedEvent();
PIXBeginNamedEvent(0, "Entity re-entry");
@ -128,7 +143,8 @@ if (newDark != skyDarken)
for (unsigned int i = 0; i < updatesToReset.size(); i++) {
ResetInfo& r = updatesToReset[i];
if (--r.ticks == 0) {
Level::setTileAndDataNoUpdate(r.x, r.y, r.z, r.tile, r.data);
Level::setTileAndData(r.x, r.y, r.z, r.tile, r.data,
Tile::UPDATE_ALL);
Level::sendTileUpdated(r.x, r.y, r.z);
// updatesToReset.erase(updatesToReset.begin()+i);
@ -387,7 +403,7 @@ void MultiPlayerLevel::tickTiles() {
int xo = cp.x * 16;
int zo = cp.z * 16;
LevelChunk* lc = this->getChunk(cp.x, cp.z);
LevelChunk* lc = getChunk(cp.x, cp.z);
tickClientSideTiles(xo, zo, lc);
}
@ -402,8 +418,8 @@ void MultiPlayerLevel::setChunkVisible(int x, int z, bool visible) {
chunkCache->drop(x, z);
}
if (!visible) {
this->setTilesDirty(x * 16, 0, z * 16, x * 16 + 15,
Level::maxBuildHeight, z * 16 + 15);
setTilesDirty(x * 16, 0, z * 16, x * 16 + 15, Level::maxBuildHeight,
z * 16 + 15);
}
}
@ -456,7 +472,7 @@ void MultiPlayerLevel::putEntity(int id, std::shared_ptr<Entity> e) {
forced.insert(e);
e->entityId = id;
if (!addEntity(e)) {
this->reEntries.insert(e);
reEntries.insert(e);
}
entitiesById[id] = e;
}
@ -498,14 +514,32 @@ void MultiPlayerLevel::removeEntities(
Level::removeEntities(list);
}
bool MultiPlayerLevel::setDataNoUpdate(int x, int y, int z, int data) {
int t = getTile(x, y, z);
bool MultiPlayerLevel::setData(
int x, int y, int z, int data, int updateFlags,
bool forceUpdate /*=false*/) // 4J added forceUpdate)
{
// First check if this isn't going to do anything, because if it isn't then
// the next stage (of unsharing data) is really quite expensive so far
// better to early out here
int d = getData(x, y, z);
if ((d == data)) {
// If we early-out, its important that we still do a checkLight here
// (which would otherwise have happened as part of
// Level::setTileAndDataNoUpdate) This is because since we are
// potentially sharing tile/data but not lighting data, it is possible
// that the server might tell a client of a lighting update that doesn't
// need actioned on the client just because the chunk's data was being
// shared with the server when it was set. However, the lighting data
// will potentially now be out of sync on the client.
checkLight(x, y, z);
return false;
}
// 4J - added - if this is the host, then stop sharing block data with the
// server at this point
unshareChunkAt(x, z);
if (Level::setDataNoUpdate(x, y, z, data)) {
if (Level::setData(x, y, z, data, updateFlags, forceUpdate)) {
// if(m_bEnableResetChanges) updatesToReset.push_back(ResetInfo(x, y, z,
// t, d));
return true;
@ -515,8 +549,8 @@ bool MultiPlayerLevel::setDataNoUpdate(int x, int y, int z, int data) {
return false;
}
bool MultiPlayerLevel::setTileAndDataNoUpdate(int x, int y, int z, int tile,
int data) {
bool MultiPlayerLevel::setTileAndData(int x, int y, int z, int tile, int data,
int updateFlags) {
// First check if this isn't going to do anything, because if it isn't then
// the next stage (of unsharing data) is really quite expensive so far
// better to early out here
@ -539,24 +573,7 @@ bool MultiPlayerLevel::setTileAndDataNoUpdate(int x, int y, int z, int tile,
// server at this point
unshareChunkAt(x, z);
if (Level::setTileAndDataNoUpdate(x, y, z, tile, data)) {
// if(m_bEnableResetChanges) updatesToReset.push_back(ResetInfo(x, y, z,
// t, d));
return true;
}
// Didn't actually need to stop sharing
shareChunkAt(x, z);
return false;
}
bool MultiPlayerLevel::setTileNoUpdate(int x, int y, int z, int tile) {
int t = getTile(x, y, z);
int d = getData(x, y, z);
// 4J - added - if this is the host, then stop sharing block data with the
// server at this point
unshareChunkAt(x, z);
if (Level::setTileNoUpdate(x, y, z, tile)) {
if (Level::setTileAndData(x, y, z, tile, data, updateFlags)) {
// if(m_bEnableResetChanges) updatesToReset.push_back(ResetInfo(x, y, z,
// t, d));
return true;
@ -585,7 +602,7 @@ bool MultiPlayerLevel::doSetTileAndData(int x, int y, int z, int tile,
// If we're the host, need to tell the renderer for updates even if they
// don't change things as the host might have been sharing data and so set
// it already, but the renderer won't know to update
if ((Level::setTileAndData(x, y, z, tile, data) ||
if ((Level::setTileAndData(x, y, z, tile, data, Tile::UPDATE_ALL) ||
g_NetworkManager.IsHost())) {
if (g_NetworkManager.IsHost() && visuallyImportant) {
// 4J Stu - This got removed from the tileUpdated function in TU14.
@ -613,13 +630,15 @@ void MultiPlayerLevel::disconnect(bool sendDisconnect /*= true*/) {
}
}
Tickable* MultiPlayerLevel::makeSoundUpdater(
std::shared_ptr<Minecart> minecart) {
return NULL; // new MinecartSoundUpdater(minecraft->soundEngine, minecart,
// minecraft->player);
}
void MultiPlayerLevel::tickWeather() {
if (dimension->hasCeiling) return;
if (lightningTime > 0) {
lightningTime--;
}
oRainLevel = rainLevel;
if (levelData->isRaining()) {
rainLevel += 0.01;
@ -731,6 +750,7 @@ void MultiPlayerLevel::playSound(std::shared_ptr<Entity> entity, int iSound,
void MultiPlayerLevel::playLocalSound(double x, double y, double z, int iSound,
float volume, float pitch,
bool distanceDelay /*= false */,
float fClipSoundDist) {
// float dd = 16;
if (volume > 1) fClipSoundDist *= volume;
@ -747,11 +767,50 @@ void MultiPlayerLevel::playLocalSound(double x, double y, double z, int iSound,
}
if (minDistSq < fClipSoundDist * fClipSoundDist) {
minecraft->soundEngine->play(iSound, (float)x, (float)y, (float)z,
volume, pitch);
if (distanceDelay && minDistSq > 10 * 10) {
// exhaggerate sound speed effect by making speed of sound ~=
// 40 m/s instead of 300 m/s
double delayInSeconds = sqrt(minDistSq) / 40.0;
minecraft->soundEngine->schedule(
iSound, (float)x, (float)y, (float)z, volume, pitch,
(int)Math::round(delayInSeconds *
SharedConstants::TICKS_PER_SECOND));
} else {
minecraft->soundEngine->play(iSound, (float)x, (float)y, (float)z,
volume, pitch);
}
}
}
void MultiPlayerLevel::createFireworks(double x, double y, double z, double xd,
double yd, double zd,
CompoundTag* infoTag) {
minecraft->particleEngine->add(
std::shared_ptr<FireworksParticles::FireworksStarter>(
new FireworksParticles::FireworksStarter(this, x, y, z, xd, yd, zd,
minecraft->particleEngine,
infoTag)));
}
void MultiPlayerLevel::setScoreboard(Scoreboard* scoreboard) {
this->scoreboard = scoreboard;
}
void MultiPlayerLevel::setDayTime(int64_t newTime) {
// 4J: We send daylight cycle rule with host options so don't need this
/*if (newTime < 0)
{
newTime = -newTime;
getGameRules()->set(GameRules::RULE_DAYLIGHT, L"false");
}
else
{
getGameRules()->set(GameRules::RULE_DAYLIGHT, L"true");
}*/
Level::setDayTime(newTime);
}
void MultiPlayerLevel::removeAllPendingEntityRemovals() {
// entities.removeAll(entitiesToRemove);

View file

@ -18,9 +18,10 @@ private:
ResetInfo(int x, int y, int z, int tile, int data);
};
std::vector<ResetInfo> updatesToReset; // 4J - was linked list but vector
// seems more appropriate
bool m_bEnableResetChanges; // 4J Added
std::vector<ResetInfo>
updatesToReset; // 4J - was linked list but std::vector seems more
// appropriate
bool m_bEnableResetChanges; // 4J Added
public:
void unshareChunkAt(int x, int z); // 4J - added
void shareChunkAt(int x, int z); // 4J - added
@ -34,10 +35,11 @@ private:
int compressCheckX; // 4J - added
int compressCheckZ; // 4J - added
std::vector<ClientConnection*>
connections; // 4J Stu - Made this a vector as we can have more than
// one local connection
connections; // 4J Stu - Made this a std::vector as we can have more
// than one local connection
MultiPlayerChunkCache* chunkCache;
Minecraft* minecraft;
Scoreboard* scoreboard;
public:
MultiPlayerLevel(ClientConnection* connection, LevelSettings* levelSettings,
@ -79,15 +81,16 @@ public:
std::shared_ptr<Entity> removeEntity(int id);
virtual void removeEntities(
std::vector<std::shared_ptr<Entity> >* list); // 4J Added override
virtual bool setDataNoUpdate(int x, int y, int z, int data);
virtual bool setTileAndDataNoUpdate(int x, int y, int z, int tile,
int data);
virtual bool setTileNoUpdate(int x, int y, int z, int tile);
virtual bool setData(int x, int y, int z, int data, int updateFlags,
bool forceUpdate = false);
virtual bool setTileAndData(int x, int y, int z, int tile, int data,
int updateFlags);
bool doSetTileAndData(int x, int y, int z, int tile, int data);
virtual void disconnect(bool sendDisconnect = true);
void animateTick(int xt, int yt, int zt);
protected:
virtual Tickable* makeSoundUpdater(std::shared_ptr<Minecart> minecart);
virtual void tickWeather();
static const int ANIMATE_TICK_MAX_PARTICLES = 500;
@ -104,8 +107,14 @@ public:
virtual void playLocalSound(double x, double y, double z, int iSound,
float volume, float pitch,
bool distanceDelay = false,
float fClipSoundDist = 16.0f);
virtual void createFireworks(double x, double y, double z, double xd,
double yd, double zd, CompoundTag* infoTag);
virtual void setScoreboard(Scoreboard* scoreboard);
virtual void setDayTime(int64_t newTime);
// 4J Stu - Added so we can have multiple local connections
void addClientConnection(ClientConnection* c) { connections.push_back(c); }
void removeClientConnection(ClientConnection* c, bool sendDisconnect);

View file

@ -6,33 +6,36 @@
#include "../Player/ServerPlayer.h"
#include "../Network/PlayerConnection.h"
#include "../Player/EntityTracker.h"
#include "../Network/ServerScoreboard.h"
#include "../../Minecraft.World/Scores/ScoreboardSaveData.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.dimension.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.storage.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.chunk.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.tile.entity.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.biome.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.item.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.entity.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.entity.ai.village.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.entity.player.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.entity.npc.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.entity.global.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.entity.npc.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.entity.player.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.biome.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.chunk.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.dimension.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.levelgen.feature.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.storage.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.tile.entity.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.scores.h"
#include "../../Minecraft.World/Entities/ItemEntity.h"
#include "../../Minecraft.World/Entities/Mobs/Arrow.h"
#include "../../Minecraft.World/Entities/Mobs/PrimedTnt.h"
#include "../../Minecraft.World/Blocks/FallingTile.h"
#include "../../Minecraft.World/Headers/net.minecraft.network.packet.h"
#include "../../Minecraft.World/Util/Mth.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.levelgen.feature.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.item.h"
#include "../../Minecraft.World/WorldGen/Structures/StructurePiece.h"
#include "ServerLevelListener.h"
#include "../Minecraft.Client/ServerLevelListener.h"
#include "../../Minecraft.World/Util/WeighedTreasure.h"
#include "../Textures/Packs/TexturePackRepository.h"
#include "../Textures/Packs/DLCTexturePack.h"
#include "../../Minecraft.World/Util/ProgressListener.h"
#include "../Platform/PS3/PS3Extras/ShutdownManager.h"
#include "PS3/PS3Extras/ShutdownManager.h"
#include "../Network/PlayerChunkMap.h"
WeighedTreasureArray ServerLevel::RANDOM_BONUS_ITEMS;
@ -100,7 +103,7 @@ void ServerLevel::staticCtor() {
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);
new WeighedTreasure(Tile::mushroom_brown_Id, 0, 1, 2, 2);
};
ServerLevel::ServerLevel(MinecraftServer* server,
@ -132,9 +135,25 @@ ServerLevel::ServerLevel(MinecraftServer* server,
// 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 =
// std::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.
@ -171,6 +190,9 @@ ServerLevel::ServerLevel(MinecraftServer* server,
}
ServerLevel::~ServerLevel() {
delete portalForcer;
delete mobSpawner;
EnterCriticalSection(&m_csQueueSendTileUpdates);
for (AUTO_VAR(it, m_queuedSendTileUpdates.begin());
it != m_queuedSendTileUpdates.end(); ++it) {
@ -207,34 +229,47 @@ void ServerLevel::tick() {
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_t 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;
if (!SharedConstants::TEXTURE_LIGHTING) // 4J - change brought forward
@ -247,17 +282,12 @@ 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_t 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
@ -274,7 +304,20 @@ 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) {
@ -296,8 +339,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();
@ -318,8 +367,7 @@ void ServerLevel::updateSleepingPlayerList() {
m_bAtLeastOnePlayerSleeping = false;
AUTO_VAR(itEnd, players.end());
for (std::vector<std::shared_ptr<Player> >::iterator it = players.begin();
it != itEnd; it++) {
for (AUTO_VAR(it, players.begin()); it != itEnd; it++) {
if (!(*it)->isSleeping()) {
allPlayersSleeping = false;
// break;
@ -477,7 +525,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()) {
@ -490,23 +538,21 @@ void ServerLevel::tickTiles() {
if (isRainingAt(x, y, z)) {
addGlobalEntity(std::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) {
// 4jcraft added cast to unsigned
randValue = (unsigned)randValue * 3 + (unsigned)addend;
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);
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);
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()) {
Biome* b = getBiome(x + xo, z + zo);
@ -531,26 +577,42 @@ 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 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()) {
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) {
Tile::tiles[id]->tick(this, td.x, td.y, td.z, random);
int r = 0;
if (getInstaTick() && tileId > 0) {
if (Tile::tiles[tileId]->canInstantlyTick()) {
r = 8;
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) {
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()) {
@ -563,11 +625,12 @@ void ServerLevel::addToTickNextTick(int x, int y, int z, int tileId,
}
void ServerLevel::forceAddTileTick(int x, int y, int z, int tileId,
int tickDelay) {
int tickDelay, int prioTilt) {
TickNextTickData td = TickNextTickData(x, y, z, tileId);
td.setPriorityTilt(prioTilt);
if (tileId > 0) {
td.delay(tickDelay + levelData->getTime());
td.delay(tickDelay + levelData->getGameTime());
}
EnterCriticalSection(&m_tickNextTickCS);
if (tickNextTickSet.find(td) == tickNextTickSet.end()) {
@ -583,12 +646,14 @@ void ServerLevel::tickEntities() {
return;
}
} else {
emptyTime = 0;
resetEmptyTime();
}
Level::tickEntities();
}
void ServerLevel::resetEmptyTime() { emptyTime = 0; }
bool ServerLevel::tickPendingTicks(bool force) {
EnterCriticalSection(&m_tickNextTickCS);
int count = (int)tickNextTickList.size();
@ -602,22 +667,33 @@ bool ServerLevel::tickPendingTicks(bool force) {
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();
@ -640,20 +716,47 @@ std::vector<TickNextTickData>* ServerLevel::fetchTicksInChunk(LevelChunk* chunk,
int south = north + 16;
delete pos;
for (AUTO_VAR(it, tickNextTickSet.begin()); it != tickNextTickSet.end();) {
TickNextTickData td = *it;
for (int i = 0; i < 2; i++) {
if (i == 0) {
for (AUTO_VAR(it, tickNextTickList.begin());
it != tickNextTickList.end();) {
TickNextTickData td = *it;
if (td.x >= west && td.x < east && td.z >= north && td.z < south) {
if (remove) {
tickNextTickList.erase(td);
it = tickNextTickSet.erase(it);
} else {
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);
} else {
it++;
}
}
results->push_back(td);
} 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++;
}
}
}
}
@ -663,19 +766,14 @@ std::vector<TickNextTickData>* ServerLevel::fetchTicksInChunk(LevelChunk* chunk,
void ServerLevel::tick(std::shared_ptr<Entity> e, bool actual) {
if (!server->isAnimals() &&
((e->GetType() & eTYPE_ANIMAL) || (e->GetType() & eTYPE_WATERANIMAL))) {
(e->instanceof(eTYPE_ANIMAL) || e->instanceof(eTYPE_WATERANIMAL))) {
e->remove();
}
if (!server->isNpcsEnabled() &&
(std::dynamic_pointer_cast<Npc>(e) != NULL)) {
e->remove();
}
if (e->rider.lock() == NULL ||
(std::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(std::shared_ptr<Entity> e, bool actual) {
@ -715,10 +813,7 @@ bool ServerLevel::mayInteract(std::shared_ptr<Player> player, int xt, int yt,
return true;
} 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;
}
@ -891,7 +986,7 @@ void ServerLevel::save(bool force, ProgressListener* progressListener,
// if( force && !isClientSide )
//{
// if (progressListener != NULL)
//progressListener->progressStage(IDS_PROGRESS_SAVING_TO_DISC);
// progressListener->progressStage(IDS_PROGRESS_SAVING_TO_DISC);
// levelStorage->flushSaveFile();
// }
}
@ -1073,9 +1168,9 @@ void ServerLevel::runTileEvents() {
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;
}
@ -1101,8 +1196,8 @@ MinecraftServer* ServerLevel::getServer() { return server; }
EntityTracker* ServerLevel::getTracker() { return tracker; }
void ServerLevel::setTimeAndAdjustTileTicks(__int64 newTime) {
__int64 delta = newTime - levelData->getTime();
void ServerLevel::setTimeAndAdjustTileTicks(int64_t newTime) {
int64_t 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
@ -1117,11 +1212,34 @@ void ServerLevel::setTimeAndAdjustTileTicks(__int64 newTime) {
for (unsigned int i = 0; i < temp.size(); i++) {
tickNextTickList.insert(temp[i]);
}
setTime(newTime);
setGameTime(newTime);
}
PlayerChunkMap* ServerLevel::getChunkMap() { return chunkMap; }
PortalForcer* ServerLevel::getPortalForcer() { return portalForcer; }
void ServerLevel::sendParticles(const std::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 std::wstring& name, double x, double y,
double z, int count, double xDist, double yDist,
double zDist, double speed) {
std::shared_ptr<Packet> packet =
std::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) {
std::shared_ptr<ServerPlayer> player =
std::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) {
@ -1146,7 +1264,7 @@ void ServerLevel::runQueuedSendTileUpdates() {
// removed and added so we can limit the number of itementities created
bool ServerLevel::addEntity(std::shared_ptr<Entity> e) {
// If its an item entity, and we've got to our capacity, delete the oldest
if (std::dynamic_pointer_cast<ItemEntity>(e) != NULL) {
if (e->instanceof(eTYPE_ITEMENTITY)) {
// printf("Adding item entity count
//%d\n",m_itemEntities.size());
EnterCriticalSection(&m_limiterCS);
@ -1158,7 +1276,7 @@ bool ServerLevel::addEntity(std::shared_ptr<Entity> e) {
}
// If its an hanging entity, and we've got to our capacity, delete the
// oldest
else if (std::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);
@ -1175,7 +1293,7 @@ bool ServerLevel::addEntity(std::shared_ptr<Entity> e) {
LeaveCriticalSection(&m_limiterCS);
}
// If its an arrow entity, and we've got to our capacity, delete the oldest
else if (std::dynamic_pointer_cast<Arrow>(e) != NULL) {
else if (e->instanceof(eTYPE_ARROW)) {
// printf("Adding arrow entity count
//%d\n",m_arrowEntities.size());
EnterCriticalSection(&m_limiterCS);
@ -1187,7 +1305,7 @@ bool ServerLevel::addEntity(std::shared_ptr<Entity> e) {
}
// If its an experience orb entity, and we've got to our capacity, delete
// the oldest
else if (std::dynamic_pointer_cast<ExperienceOrb>(e) != NULL) {
else if (e->instanceof(eTYPE_EXPERIENCEORB)) {
// printf("Adding arrow entity count
//%d\n",m_arrowEntities.size());
EnterCriticalSection(&m_limiterCS);
@ -1200,37 +1318,65 @@ bool ServerLevel::addEntity(std::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(std::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(std::shared_ptr<Entity> e) {
if (std::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());
LeaveCriticalSection(&m_limiterCS);
} else if (std::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 (std::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());
LeaveCriticalSection(&m_limiterCS);
} else if (std::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());
LeaveCriticalSection(&m_limiterCS);
} else if (std::dynamic_pointer_cast<PrimedTnt>(e) != NULL) {
} else if (e->instanceof(eTYPE_PRIMEDTNT)) {
EnterCriticalSection(&m_limiterCS);
m_primedTntCount++;
LeaveCriticalSection(&m_limiterCS);
} else if (std::dynamic_pointer_cast<FallingTile>(e) != NULL) {
} else if (e->instanceof(eTYPE_FALLINGTILE)) {
EnterCriticalSection(&m_limiterCS);
m_fallingTileCount++;
LeaveCriticalSection(&m_limiterCS);
@ -1240,7 +1386,7 @@ void ServerLevel::entityAddedExtra(std::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(std::shared_ptr<Entity> e) {
if (std::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());
@ -1252,7 +1398,7 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr<Entity> e) {
// printf("entity removed: item entity count now
//%d\n",m_itemEntities.size());
LeaveCriticalSection(&m_limiterCS);
} else if (std::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());
@ -1265,7 +1411,7 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr<Entity> e) {
// printf("entity removed: item entity count now
//%d\n",m_itemEntities.size());
LeaveCriticalSection(&m_limiterCS);
} else if (std::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());
@ -1277,7 +1423,7 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr<Entity> e) {
// printf("entity removed: arrow entity count now
//%d\n",m_arrowEntities.size());
LeaveCriticalSection(&m_limiterCS);
} else if (std::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());
@ -1290,11 +1436,11 @@ void ServerLevel::entityRemovedExtra(std::shared_ptr<Entity> e) {
// printf("entity removed: experience orb entity count now
//%d\n",m_arrowEntities.size());
LeaveCriticalSection(&m_limiterCS);
} else if (std::dynamic_pointer_cast<PrimedTnt>(e) != NULL) {
} else if (e->instanceof(eTYPE_PRIMEDTNT)) {
EnterCriticalSection(&m_limiterCS);
m_primedTntCount--;
LeaveCriticalSection(&m_limiterCS);
} else if (std::dynamic_pointer_cast<FallingTile>(e) != NULL) {
} else if (e->instanceof(eTYPE_FALLINGTILE)) {
EnterCriticalSection(&m_limiterCS);
m_fallingTileCount--;
LeaveCriticalSection(&m_limiterCS);
@ -1438,4 +1584,4 @@ void ServerLevel::flagEntitiesToBeRemoved(unsigned int* flags,
if (chunkMap) {
chunkMap->flagEntitiesToBeRemoved(flags, removedFound);
}
}
}

View file

@ -9,7 +9,8 @@ class PlayerChunkMap;
class ServerLevel : public Level {
private:
static const int EMPTY_TIME_NO_TICK = SharedConstants::TICKS_PER_SECOND * 3;
static const int EMPTY_TIME_NO_TICK =
SharedConstants::TICKS_PER_SECOND * 60;
MinecraftServer* server;
EntityTracker* tracker;
@ -35,6 +36,8 @@ public:
private:
bool allPlayersSleeping;
PortalForcer* portalForcer;
MobSpawner* mobSpawner;
int emptyTime;
bool m_bAtLeastOnePlayerSleeping; // 4J Added
static WeighedTreasureArray
@ -68,10 +71,18 @@ public:
protected:
void tickTiles();
private:
std::vector<TickNextTickData> toBeTicked;
public:
bool isTileToBeTickedAt(int x, int y, int z, int tileId);
void addToTickNextTick(int x, int y, int z, int tileId, int tickDelay);
void forceAddTileTick(int x, int y, int z, int tileId, int tickDelay);
void addToTickNextTick(int x, int y, int z, int tileId, int tickDelay,
int priorityTilt);
void forceAddTileTick(int x, int y, int z, int tileId, int tickDelay,
int prioTilt);
void tickEntities();
void resetEmptyTime();
bool tickPendingTicks(bool force);
std::vector<TickNextTickData>* fetchTicksInChunk(LevelChunk* chunk,
bool remove);
@ -89,7 +100,7 @@ public:
std::vector<std::shared_ptr<TileEntity> >* getTileEntitiesInRegion(
int x0, int y0, int z0, int x1, int y1, int z1);
virtual bool mayInteract(std::shared_ptr<Player> player, int xt, int yt,
int zt, int id);
int zt, int content);
protected:
virtual void initializeLevel(LevelSettings* settings);
@ -141,8 +152,14 @@ protected:
public:
MinecraftServer* getServer();
EntityTracker* getTracker();
void setTimeAndAdjustTileTicks(__int64 newTime);
void setTimeAndAdjustTileTicks(int64_t newTime);
PlayerChunkMap* getChunkMap();
PortalForcer* getPortalForcer();
void sendParticles(const std::wstring& name, double x, double y, double z,
int count);
void sendParticles(const std::wstring& name, double x, double y, double z,
int count, double xDist, double yDist, double zDist,
double speed);
void queueSendTileUpdate(int x, int y, int z); // 4J Added
private:
@ -170,6 +187,8 @@ public:
void entityAddedExtra(std::shared_ptr<Entity> e);
void entityRemovedExtra(std::shared_ptr<Entity> e);
bool atEntityLimit(std::shared_ptr<Entity> e); // 4J: Added
virtual bool newPrimedTntAllowed();
virtual bool newFallingTileAllowed();

View file

@ -19,8 +19,8 @@ ServerLevelListener::ServerLevelListener(MinecraftServer* server,
// 4J removed -
/*
void ServerLevelListener::addParticle(const std::wstring& name, double x, double
y, double z, double xa, double ya, double za)
void ServerLevelListener::addParticle(const wstring& name, double x, double y,
double z, double xa, double ya, double za)
{
}
*/
@ -67,9 +67,11 @@ void ServerLevelListener::playSound(int iSound, double x, double y, double z,
}
}
void ServerLevelListener::playSound(std::shared_ptr<Entity> entity, int iSound,
double x, double y, double z, float volume,
float pitch, float fClipSoundDist) {
void ServerLevelListener::playSoundExceptPlayer(std::shared_ptr<Player> player,
int iSound, double x, double y,
double z, float volume,
float pitch,
float fSoundClipDist) {
if (iSound < 0) {
app.DebugPrintf(
"ServerLevelListener received request for sound less than 0, so "
@ -79,8 +81,6 @@ void ServerLevelListener::playSound(std::shared_ptr<Entity> entity, int iSound,
// since we're already playing these in the LevelRenderer::playSound.
// The PC version does seem to do this and the result is I can stop
// walking , and then I'll hear my footstep sound with a delay
std::shared_ptr<Player> player =
std::dynamic_pointer_cast<Player>(entity);
server->getPlayers()->broadcast(
player, x, y, z, volume > 1 ? 16 * volume : 16,
level->dimension->id,
@ -108,7 +108,13 @@ void ServerLevelListener::levelEvent(std::shared_ptr<Player> source, int type,
server->getPlayers()->broadcast(
source, x, y, z, 64, level->dimension->id,
std::shared_ptr<LevelEventPacket>(
new LevelEventPacket(type, x, y, z, data)));
new LevelEventPacket(type, x, y, z, data, false)));
}
void ServerLevelListener::globalLevelEvent(int type, int sourceX, int sourceY,
int sourceZ, int data) {
server->getPlayers()->broadcastAll(std::shared_ptr<LevelEventPacket>(
new LevelEventPacket(type, sourceX, sourceY, sourceZ, data, true)));
}
void ServerLevelListener::destroyTileProgress(int id, int x, int y, int z,

View file

@ -27,9 +27,10 @@ public:
// level's player array, not just the entity storage
virtual void playSound(int iSound, double x, double y, double z,
float volume, float pitch, float fClipSoundDist);
virtual void playSound(std::shared_ptr<Entity> entity, int iSound, double x,
double y, double z, float volume, float pitch,
float fClipSoundDist);
virtual void playSoundExceptPlayer(std::shared_ptr<Player> player,
int iSound, double x, double y, double z,
float volume, float pitch,
float fSoundClipDist);
virtual void setTilesDirty(int x0, int y0, int z0, int x1, int y1, int z1,
Level* level); // 4J - added level param
virtual void skyColorChanged();
@ -39,5 +40,7 @@ public:
int z);
virtual void levelEvent(std::shared_ptr<Player> source, int type, int x,
int y, int z, int data);
virtual void globalLevelEvent(int type, int sourceX, int sourceY,
int sourceZ, int data);
virtual void destroyTileProgress(int id, int x, int y, int z, int progress);
};