TU19: merge Minecraft.Client/Network

This commit is contained in:
Tropical 2026-03-21 21:54:07 -05:00
parent 92fbafe432
commit 3f143811e3
18 changed files with 1802 additions and 491 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,10 @@
#pragma once
#include "../../Minecraft.World/Headers/net.minecraft.network.h"
class Minecraft;
class MultiPlayerLevel;
class SavedDataStorage;
class Socket;
class MultiplayerLocalPlayer;
class SetRidingPacket;
class ClientConnection : public PacketListener {
private:
@ -67,6 +65,8 @@ public:
virtual void handleAddPlayer(std::shared_ptr<AddPlayerPacket> packet);
virtual void handleTeleportEntity(
std::shared_ptr<TeleportEntityPacket> packet);
virtual void handleSetCarriedItem(
std::shared_ptr<SetCarriedItemPacket> packet);
virtual void handleMoveEntity(std::shared_ptr<MoveEntityPacket> packet);
virtual void handleRotateMob(std::shared_ptr<RotateHeadPacket> packet);
virtual void handleMoveEntitySmall(
@ -104,7 +104,8 @@ public:
virtual void handleAddMob(std::shared_ptr<AddMobPacket> packet);
virtual void handleSetTime(std::shared_ptr<SetTimePacket> packet);
virtual void handleSetSpawn(std::shared_ptr<SetSpawnPositionPacket> packet);
virtual void handleRidePacket(std::shared_ptr<SetRidingPacket> packet);
virtual void handleEntityLinkPacket(
std::shared_ptr<SetEntityLinkPacket> packet);
virtual void handleEntityEvent(std::shared_ptr<EntityEventPacket> packet);
private:
@ -124,6 +125,8 @@ public:
virtual void handleContainerAck(std::shared_ptr<ContainerAckPacket> packet);
virtual void handleContainerContent(
std::shared_ptr<ContainerSetContentPacket> packet);
virtual void handleTileEditorOpen(
std::shared_ptr<TileEditorOpenPacket> packet);
virtual void handleSignUpdate(std::shared_ptr<SignUpdatePacket> packet);
virtual void handleTileEntityData(
std::shared_ptr<TileEntityDataPacket> packet);
@ -181,4 +184,30 @@ public:
void displayPrivilegeChanges(std::shared_ptr<MultiplayerLocalPlayer> player,
unsigned int oldPrivileges);
};
virtual void handleAddObjective(std::shared_ptr<SetObjectivePacket> packet);
virtual void handleSetScore(std::shared_ptr<SetScorePacket> packet);
virtual void handleSetDisplayObjective(
std::shared_ptr<SetDisplayObjectivePacket> packet);
virtual void handleSetPlayerTeamPacket(
std::shared_ptr<SetPlayerTeamPacket> packet);
virtual void handleParticleEvent(
std::shared_ptr<LevelParticlesPacket> packet);
virtual void handleUpdateAttributes(
std::shared_ptr<UpdateAttributesPacket> packet);
private:
// 4J: Entity link packet deferred
class DeferredEntityLinkPacket {
public:
DWORD m_recievedTick;
std::shared_ptr<SetEntityLinkPacket> m_packet;
DeferredEntityLinkPacket(std::shared_ptr<SetEntityLinkPacket> packet);
};
std::vector<DeferredEntityLinkPacket> deferredEntityLinkPackets;
static const int MAX_ENTITY_LINK_DEFERRAL_INTERVAL = 1000;
void checkDeferredEntityLinkPackets(int newEntityId);
};

View file

@ -44,7 +44,7 @@ MultiPlayerChunkCache::MultiPlayerChunkCache(Level* level) {
for (int z = 0; z < 16; z++) {
unsigned char tileId = 0;
if (y <= (level->getSeaLevel() - 10))
tileId = Tile::rock_Id;
tileId = Tile::stone_Id;
else if (y < level->getSeaLevel())
tileId = Tile::calmWater_Id;
@ -195,8 +195,7 @@ LevelChunk* MultiPlayerChunkCache::create(int x, int z) {
// 4J - changed to use new methods for lighting
chunk->setSkyLightDataAllBright();
// Arrays::fill(chunk->skyLight->data, (uint8_t)
//255);
// Arrays::fill(chunk->skyLight->data, (byte) 255);
}
chunk->loaded = true;
@ -278,6 +277,9 @@ TilePos* MultiPlayerChunkCache::findNearestMapFeature(
return NULL;
}
void MultiPlayerChunkCache::recreateLogicStructuresForChunk(int chunkX,
int chunkZ) {}
std::wstring MultiPlayerChunkCache::gatherStats() {
EnterCriticalSection(&m_csLoadCreate);
int size = (int)loadedChunkList.size();

View file

@ -44,6 +44,7 @@ public:
virtual TilePos* findNearestMapFeature(Level* level,
const std::wstring& featureName,
int x, int y, int z);
virtual void recreateLogicStructuresForChunk(int chunkX, int chunkZ);
virtual void dataReceived(int x, int z); // 4J added
virtual LevelChunk** getCache() { return cache; } // 4J added

View file

@ -258,3 +258,5 @@ std::wstring PendingConnection::getName() {
}
bool PendingConnection::isServerPacketListener() { return true; }
bool PendingConnection::isDisconnected() { return done; }

View file

@ -46,6 +46,7 @@ public:
void send(std::shared_ptr<Packet> packet);
std::wstring getName();
virtual bool isServerPacketListener();
virtual bool isDisconnected();
private:
void sendPreLoginResponse();

View file

@ -7,6 +7,7 @@
#include "../MinecraftServer.h"
#include "../../Minecraft.World/Headers/net.minecraft.network.packet.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.chunk.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.tile.h"
#include "../../Minecraft.World/Util/ArrayWithLength.h"
#include "../../Minecraft.World/Platform/System.h"
@ -23,19 +24,12 @@ PlayerChunkMap::PlayerChunk::PlayerChunk(int x, int z, PlayerChunkMap* pcm)
parent = pcm; // 4J added
ticksToNextRegionUpdate = 0; // 4J added
prioritised = false; // 4J added
firstInhabitedTime = 0;
parent->getLevel()->cache->create(x, z);
// 4J - added make sure our lights are up to date as soon as we make it.
// This is of particular concern for local clients, who have their data
// shared as soon as the chunkvisibilitypacket is sent, and so could
// potentially create render data for this chunk before it has been properly
// lit.
while (parent->getLevel()->updateLights());
}
PlayerChunkMap::PlayerChunk::~PlayerChunk() {
delete[] changedTiles.data; // 4jcraft, changed to []
}
PlayerChunkMap::PlayerChunk::~PlayerChunk() { delete changedTiles.data; }
// 4J added - construct an an array of flags that indicate which entities are
// still waiting to have network packets sent out to say that they have been
@ -77,6 +71,10 @@ void PlayerChunkMap::PlayerChunk::add(std::shared_ptr<ServerPlayer> player,
player->connection->send(std::shared_ptr<ChunkVisibilityPacket>(
new ChunkVisibilityPacket(pos.x, pos.z, true)));
if (players.empty()) {
firstInhabitedTime = parent->level->getGameTime();
}
players.push_back(player);
player->chunksToSend.push_back(pos);
@ -103,7 +101,14 @@ void PlayerChunkMap::PlayerChunk::remove(std::shared_ptr<ServerPlayer> player) {
players.erase(it);
if (players.size() == 0) {
__int64 id = (pos.x + 0x7fffffffLL) | ((pos.z + 0x7fffffffLL) << 32);
{
LevelChunk* chunk = parent->level->getChunk(pos.x, pos.z);
updateInhabitedTime(chunk);
AUTO_VAR(it, find(parent->knownChunks.begin(),
parent->knownChunks.end(), this));
if (it != parent->knownChunks.end()) parent->knownChunks.erase(it);
}
int64_t id = (pos.x + 0x7fffffffLL) | ((pos.z + 0x7fffffffLL) << 32);
AUTO_VAR(it, parent->chunks.find(id));
if (it != parent->chunks.end()) {
toDelete = it->second; // Don't delete until the end of the
@ -157,6 +162,16 @@ void PlayerChunkMap::PlayerChunk::remove(std::shared_ptr<ServerPlayer> player) {
delete toDelete;
}
void PlayerChunkMap::PlayerChunk::updateInhabitedTime() {
updateInhabitedTime(parent->level->getChunk(pos.x, pos.z));
}
void PlayerChunkMap::PlayerChunk::updateInhabitedTime(LevelChunk* chunk) {
chunk->inhabitedTime += parent->level->getGameTime() - firstInhabitedTime;
firstInhabitedTime = parent->level->getGameTime();
}
void PlayerChunkMap::PlayerChunk::tileChanged(int x, int y, int z) {
if (changes == 0) {
parent->changedChunks.push_back(this);
@ -386,6 +401,7 @@ PlayerChunkMap::PlayerChunkMap(ServerLevel* level, int dimension, int radius) {
this->radius = radius;
this->level = level;
this->dimension = dimension;
lastInhabitedUpdate = 0;
}
PlayerChunkMap::~PlayerChunkMap() {
@ -397,6 +413,22 @@ PlayerChunkMap::~PlayerChunkMap() {
ServerLevel* PlayerChunkMap::getLevel() { return level; }
void PlayerChunkMap::tick() {
int64_t time = level->getGameTime();
if (time - lastInhabitedUpdate > Level::TICKS_PER_DAY / 3) {
lastInhabitedUpdate = time;
for (int i = 0; i < knownChunks.size(); i++) {
PlayerChunk* chunk = knownChunks.at(i);
// 4J Stu - Going to let our changeChunks handler below deal with
// this
// chunk.broadcastChanges();
chunk->updateInhabitedTime();
}
}
// 4J - some changes here so that we only send one region update per tick.
// The chunks themselves also limit their resend rate to once every
// MIN_TICKS_BETWEEN_REGION_UPDATE ticks
@ -432,13 +464,13 @@ void PlayerChunkMap::tick() {
}
bool PlayerChunkMap::hasChunk(int x, int z) {
__int64 id = (x + 0x7fffffffLL) | ((z + 0x7fffffffLL) << 32);
int64_t id = (x + 0x7fffffffLL) | ((z + 0x7fffffffLL) << 32);
return chunks.find(id) != chunks.end();
}
PlayerChunkMap::PlayerChunk* PlayerChunkMap::getChunk(int x, int z,
bool create) {
__int64 id = (x + 0x7fffffffLL) | ((z + 0x7fffffffLL) << 32);
int64_t id = (x + 0x7fffffffLL) | ((z + 0x7fffffffLL) << 32);
AUTO_VAR(it, chunks.find(id));
PlayerChunk* chunk = NULL;
@ -447,6 +479,7 @@ PlayerChunkMap::PlayerChunk* PlayerChunkMap::getChunk(int x, int z,
} else if (create) {
chunk = new PlayerChunk(x, z, this);
chunks[id] = chunk;
knownChunks.push_back(chunk);
}
return chunk;
@ -456,7 +489,7 @@ PlayerChunkMap::PlayerChunk* PlayerChunkMap::getChunk(int x, int z,
// doesn't exist, queue a request for it to be created.
void PlayerChunkMap::getChunkAndAddPlayer(
int x, int z, std::shared_ptr<ServerPlayer> player) {
__int64 id = (x + 0x7fffffffLL) | ((z + 0x7fffffffLL) << 32);
int64_t id = (x + 0x7fffffffLL) | ((z + 0x7fffffffLL) << 32);
AUTO_VAR(it, chunks.find(id));
if (it != chunks.end()) {
@ -476,7 +509,7 @@ void PlayerChunkMap::getChunkAndRemovePlayer(
return;
}
}
__int64 id = (x + 0x7fffffffLL) | ((z + 0x7fffffffLL) << 32);
int64_t id = (x + 0x7fffffffLL) | ((z + 0x7fffffffLL) << 32);
AUTO_VAR(it, chunks.find(id));
if (it != chunks.end()) {
@ -510,7 +543,6 @@ void PlayerChunkMap::tickAddRequests(std::shared_ptr<ServerPlayer> player) {
if (itNearest != addRequests.end()) {
getChunk(itNearest->x, itNearest->z, true)->add(itNearest->player);
addRequests.erase(itNearest);
return;
}
}
}
@ -582,6 +614,14 @@ void PlayerChunkMap::add(std::shared_ptr<ServerPlayer> player) {
minX = maxX = xc;
minZ = maxZ = zc;
// 4J - added so that we don't fully create/send every chunk at this stage.
// Particularly since moving on to large worlds, where we can be adding 1024
// chunks here of which a large % might need to be fully created, this can
// take a long time. Instead use the getChunkAndAddPlayer for anything but
// the central region of chunks, which adds them to a queue of chunks which
// are added one per tick per player.
const int maxLegSizeToAddNow = 14;
// All but the last leg
for (int legSize = 1; legSize <= size * 2; legSize++) {
for (int leg = 0; leg < 2; leg++) {
@ -594,12 +634,19 @@ void PlayerChunkMap::add(std::shared_ptr<ServerPlayer> player) {
int targetX, targetZ;
targetX = xc + dx;
targetZ = zc + dz;
if (targetX > maxX) maxX = targetX;
if (targetX < minX) minX = targetX;
if (targetZ > maxZ) maxZ = targetZ;
if (targetZ < minZ) minZ = targetZ;
getChunk(targetX, targetZ, true)->add(player, false);
if ((legSize < maxLegSizeToAddNow) ||
((legSize == maxLegSizeToAddNow) &&
((leg == 0) || (k < (legSize - 1))))) {
if (targetX > maxX) maxX = targetX;
if (targetX < minX) minX = targetX;
if (targetZ > maxZ) maxZ = targetZ;
if (targetZ < minZ) minZ = targetZ;
getChunk(targetX, targetZ, true)->add(player, false);
} else {
getChunkAndAddPlayer(targetX, targetZ, player);
}
}
}
}
@ -613,12 +660,16 @@ void PlayerChunkMap::add(std::shared_ptr<ServerPlayer> player) {
int targetX, targetZ;
targetX = xc + dx;
targetZ = zc + dz;
if (targetX > maxX) maxX = targetX;
if (targetX < minX) minX = targetX;
if (targetZ > maxZ) maxZ = targetZ;
if (targetZ < minZ) minZ = targetZ;
if ((size * 2) <= maxLegSizeToAddNow) {
if (targetX > maxX) maxX = targetX;
if (targetX < minX) minX = targetX;
if (targetZ > maxZ) maxZ = targetZ;
if (targetZ < minZ) minZ = targetZ;
getChunk(targetX, targetZ, true)->add(player, false);
getChunk(targetX, targetZ, true)->add(player, false);
} else {
getChunkAndAddPlayer(targetX, targetZ, player);
}
}
// CraftBukkit end
@ -753,4 +804,4 @@ void PlayerChunkMap::setRadius(int newRadius) {
assert(radius >= MIN_VIEW_DISTANCE);
this->radius = newRadius;
}
}
}

View file

@ -44,6 +44,7 @@ public:
int zChangeMin, zChangeMax;
int ticksToNextRegionUpdate; // 4J added
bool prioritised; // 4J added
int64_t firstInhabitedTime;
public:
PlayerChunk(int x, int z, PlayerChunkMap* pcm);
@ -53,6 +54,12 @@ public:
// one much smaller packet
void add(std::shared_ptr<ServerPlayer> player, bool sendPacket = true);
void remove(std::shared_ptr<ServerPlayer> player);
void updateInhabitedTime();
private:
void updateInhabitedTime(LevelChunk* chunk);
public:
void tileChanged(int x, int y, int z);
void prioritiseTileChanges(); // 4J added
void broadcast(std::shared_ptr<Packet> packet);
@ -67,15 +74,17 @@ public:
void flagEntitiesToBeRemoved(unsigned int* flags,
bool* removedFound); // 4J added
private:
std::unordered_map<__int64, PlayerChunk*, LongKeyHash, LongKeyEq>
std::unordered_map<int64_t, PlayerChunk*, LongKeyHash, LongKeyEq>
chunks; // 4J - was LongHashMap
std::vector<PlayerChunk*> changedChunks;
std::vector<PlayerChunk*> knownChunks;
std::vector<PlayerChunkAddRequest> addRequests; // 4J added
void tickAddRequests(std::shared_ptr<ServerPlayer> player); // 4J added
ServerLevel* level;
int radius;
int dimension;
int64_t lastInhabitedUpdate;
public:
PlayerChunkMap(ServerLevel* level, int dimension, int radius);

View file

@ -15,6 +15,7 @@
#include "../../Minecraft.World/Headers/net.minecraft.world.inventory.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.tile.entity.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.saveddata.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.entity.animal.h"
#include "../../Minecraft.World/Headers/net.minecraft.network.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.food.h"
#include "../../Minecraft.World/Util/AABB.h"
@ -55,7 +56,7 @@ PlayerConnection::PlayerConnection(MinecraftServer* server,
connection->setListener(this);
this->player = player;
// player->connection = this; // 4J - moved out as we can't
//assign in a ctor
// assign in a ctor
InitializeCriticalSection(&done_cs);
m_bCloseOnTick = false;
@ -95,9 +96,6 @@ void PlayerConnection::tick() {
send(std::shared_ptr<KeepAlivePacket>(
new KeepAlivePacket(lastKeepAliveId)));
}
// if (!didTick) {
// player->doTick(false);
// }
if (chatSpamTickCount > 0) {
chatSpamTickCount--;
@ -142,9 +140,8 @@ void PlayerConnection::disconnect(DisconnectPacket::eDisconnectReason reason) {
void PlayerConnection::handlePlayerInput(
std::shared_ptr<PlayerInputPacket> packet) {
player->setPlayerInput(packet->getXa(), packet->getYa(),
packet->isJumping(), packet->isSneaking(),
packet->getXRot(), packet->getYRot());
player->setPlayerInput(packet->getXxa(), packet->getYya(),
packet->isJumping(), packet->isSneaking());
}
void PlayerConnection::handleMovePlayer(
@ -172,45 +169,27 @@ void PlayerConnection::handleMovePlayer(
double xt = player->x;
double yt = player->y;
double zt = player->z;
double xxa = 0;
double zza = 0;
if (packet->hasRot) {
yRotT = packet->yRot;
xRotT = packet->xRot;
}
if (packet->hasPos && packet->y == -999 && packet->yView == -999) {
// CraftBukkit start
if (abs(packet->x) > 1 || abs(packet->z) > 1) {
// System.err.println(player.name + " was caught trying to
// crash the server with an invalid position.");
#ifndef _CONTENT_PACKAGE
wprintf(
L"%ls was caught trying to crash the server with an "
L"invalid position.",
player->name.c_str());
#endif
disconnect(DisconnectPacket::
eDisconnect_IllegalPosition); //"Nope!");
return;
}
// CraftBukkit end
xxa = packet->x;
zza = packet->z;
}
player->onGround = packet->onGround;
player->doTick(false);
player->move(xxa, 0, zza);
player->ySlideOffset = 0;
player->absMoveTo(xt, yt, zt, yRotT, xRotT);
player->xd = xxa;
player->zd = zza;
if (player->riding != NULL) level->forceTick(player->riding, true);
if (player->riding != NULL) player->riding->positionRider();
server->getPlayers()->move(player);
xLastOk = player->x;
yLastOk = player->y;
zLastOk = player->z;
// player may have been kicked off the mount during the tick, so
// only copy valid coordinates if the player still is "synched"
if (synched) {
xLastOk = player->x;
yLastOk = player->y;
zLastOk = player->z;
}
((Level*)level)->tick(player);
return;
@ -283,12 +262,12 @@ void PlayerConnection::handleMovePlayer(
// 4J-PB - removing this one for now
/*if (dist > 100.0f)
{
// logger.warning(player->name + " moved too quickly!");
disconnect(DisconnectPacket::eDisconnect_MovedTooQuickly);
// System.out.println("Moved too quickly at " + xt + ", " + yt +
", " + zt);
// teleport(player->x, player->y, player->z, player->yRot,
player->xRot); return;
// logger.warning(player->name + " moved too quickly!");
disconnect(DisconnectPacket::eDisconnect_MovedTooQuickly);
// System.out.println("Moved too quickly at " + xt + ", "
+ yt + ", " + zt);
// teleport(player->x, player->y, player->z,
player->yRot, player->xRot); return;
}
*/
@ -332,10 +311,10 @@ player->xRot); return;
if (dist > 0.25 * 0.25 && !player->isSleeping() &&
!player->gameMode->isCreative() && !player->isAllowedToFly()) {
fail = true;
// logger.warning(player->name + " moved wrongly!");
// System.out.println("Got position " + xt + ", " + yt + ", " + zt);
// System.out.println("Expected " + player->x + ", " + player->y + ",
// " + player->z);
// logger.warning(player->name + " moved wrongly!");
// System.out.println("Got position " + xt + ", " + yt +
// ", " + zt); System.out.println("Expected " + player->x
// + ", " + player->y + ", " + player->z);
#ifndef _CONTENT_PACKAGE
wprintf(L"%ls moved wrongly!\n", player->name.c_str());
app.DebugPrintf("Got position %f, %f, %f\n", xt, yt, zt);
@ -359,8 +338,8 @@ player->xRot); return;
if (oyDist >= (-0.5f / 16.0f)) {
aboveGroundTickCount++;
if (aboveGroundTickCount > 80) {
// logger.warning(player->name + " was kicked for floating
// too long!");
// logger.warning(player->name + " was
// kicked for floating too long!");
#ifndef _CONTENT_PACKAGE
wprintf(L"%ls was kicked for floating too long!\n",
player->name.c_str());
@ -376,6 +355,8 @@ player->xRot); return;
player->onGround = packet->onGround;
server->getPlayers()->move(player);
player->doCheckFallDamage(player->y - startY, packet->onGround);
} else if ((tickCount % SharedConstants::TICKS_PER_SECOND) == 0) {
teleport(xLastOk, yLastOk, zLastOk, player->yRot, player->xRot);
}
}
@ -399,21 +380,24 @@ void PlayerConnection::teleport(double x, double y, double z, float yRot,
void PlayerConnection::handlePlayerAction(
std::shared_ptr<PlayerActionPacket> packet) {
ServerLevel* level = server->getLevel(player->dimension);
player->resetLastActionTime();
if (packet->action == PlayerActionPacket::DROP_ITEM) {
player->drop();
player->drop(false);
return;
} else if (packet->action == PlayerActionPacket::DROP_ALL_ITEMS) {
player->drop(true);
return;
} else if (packet->action == PlayerActionPacket::RELEASE_USE_ITEM) {
player->releaseUsingItem();
return;
}
// 4J Stu - We don't have ops, so just use the levels setting
bool canEditSpawn =
level->canEditSpawn; // = level->dimension->id != 0 ||
// server->players->isOp(player->name);
bool shouldVerifyLocation = false;
if (packet->action == PlayerActionPacket::START_DESTROY_BLOCK)
shouldVerifyLocation = true;
if (packet->action == PlayerActionPacket::ABORT_DESTROY_BLOCK)
shouldVerifyLocation = true;
if (packet->action == PlayerActionPacket::STOP_DESTROY_BLOCK)
shouldVerifyLocation = true;
@ -434,14 +418,15 @@ void PlayerConnection::handlePlayerAction(
return;
}
}
Pos* spawnPos = level->getSharedSpawnPos();
int xd = (int)Mth::abs((float)(x - spawnPos->x));
int zd = (int)Mth::abs((float)(z - spawnPos->z));
delete spawnPos;
if (xd > zd) zd = xd;
if (packet->action == PlayerActionPacket::START_DESTROY_BLOCK) {
if (zd > 16 || canEditSpawn)
player->gameMode->startDestroyBlock(x, y, z, packet->face);
if (true)
player->gameMode->startDestroyBlock(
x, y, z,
packet->face); // 4J - condition was
// !server->isUnderSpawnProtection(level,
// x, y, z, player) (from Java 1.6.4)
// but putting back to old behaviour
else
player->connection->send(std::shared_ptr<TileUpdatePacket>(
new TileUpdatePacket(x, y, z, level)));
@ -461,19 +446,7 @@ void PlayerConnection::handlePlayerAction(
if (level->getTile(x, y, z) != 0)
player->connection->send(std::shared_ptr<TileUpdatePacket>(
new TileUpdatePacket(x, y, z, level)));
} else if (packet->action == PlayerActionPacket::GET_UPDATED_BLOCK) {
double xDist = player->x - (x + 0.5);
double yDist = player->y - (y + 0.5);
double zDist = player->z - (z + 0.5);
double dist = xDist * xDist + yDist * yDist + zDist * zDist;
if (dist < 16 * 16) {
player->connection->send(std::shared_ptr<TileUpdatePacket>(
new TileUpdatePacket(x, y, z, level)));
}
}
// 4J Stu - Don't change the levels state
// level->canEditSpawn = false;
}
void PlayerConnection::handleUseItem(std::shared_ptr<UseItemPacket> packet) {
@ -484,6 +457,7 @@ void PlayerConnection::handleUseItem(std::shared_ptr<UseItemPacket> packet) {
int y = packet->getY();
int z = packet->getZ();
int face = packet->getFace();
player->resetLastActionTime();
// 4J Stu - We don't have ops, so just use the levels setting
bool canEditSpawn =
@ -495,14 +469,13 @@ void PlayerConnection::handleUseItem(std::shared_ptr<UseItemPacket> packet) {
} else if ((packet->getY() < server->getMaxBuildHeight() - 1) ||
(packet->getFace() != Facing::UP &&
packet->getY() < server->getMaxBuildHeight())) {
Pos* spawnPos = level->getSharedSpawnPos();
int xd = (int)Mth::abs((float)(x - spawnPos->x));
int zd = (int)Mth::abs((float)(z - spawnPos->z));
delete spawnPos;
if (xd > zd) zd = xd;
if (synched &&
player->distanceToSqr(x + 0.5, y + 0.5, z + 0.5) < 8 * 8) {
if (zd > 16 || canEditSpawn) {
if (true) // 4J - condition was
// !server->isUnderSpawnProtection(level, x, y, z,
// player) (from java 1.6.4) but putting back to old
// behaviour
{
player->gameMode->useItemOn(
player, level, item, x, y, z, face, packet->getClickX(),
packet->getClickY(), packet->getClickZ());
@ -511,7 +484,7 @@ void PlayerConnection::handleUseItem(std::shared_ptr<UseItemPacket> packet) {
informClient = true;
} else {
// player->connection->send(std::shared_ptr<ChatPacket>(new
// player->connection->send(shared_ptr<ChatPacket>(new
// ChatPacket("\u00A77Height limit for building is " +
// server->maxBuildHeight)));
informClient = true;
@ -546,6 +519,11 @@ void PlayerConnection::handleUseItem(std::shared_ptr<UseItemPacket> packet) {
}
item = player->inventory->getSelected();
bool forceClientUpdate = false;
if (item != NULL && packet->getItem() == NULL) {
forceClientUpdate = true;
}
if (item != NULL && item->count == 0) {
player->inventory->items[player->inventory->selected] = nullptr;
item = nullptr;
@ -561,7 +539,8 @@ void PlayerConnection::handleUseItem(std::shared_ptr<UseItemPacket> packet) {
player->containerMenu->broadcastChanges();
player->ignoreSlotUpdateHack = false;
if (!ItemInstance::matches(player->inventory->getSelected(),
if (forceClientUpdate ||
!ItemInstance::matches(player->inventory->getSelected(),
packet->getItem())) {
send(std::shared_ptr<ContainerSetSlotPacket>(
new ContainerSetSlotPacket(player->containerMenu->containerId,
@ -569,9 +548,6 @@ void PlayerConnection::handleUseItem(std::shared_ptr<UseItemPacket> packet) {
player->inventory->getSelected())));
}
}
// 4J Stu - Don't change the levels state
// level->canEditSpawn = false;
}
void PlayerConnection::onDisconnect(DisconnectPacket::eDisconnectReason reason,
@ -641,6 +617,7 @@ void PlayerConnection::handleSetCarriedItem(
return;
}
player->inventory->selected = packet->slot;
player->resetLastActionTime();
}
void PlayerConnection::handleChat(std::shared_ptr<ChatPacket> packet) {
@ -686,6 +663,7 @@ void PlayerConnection::handleCommand(const std::wstring& message) {
}
void PlayerConnection::handleAnimate(std::shared_ptr<AnimatePacket> packet) {
player->resetLastActionTime();
if (packet->action == AnimatePacket::SWING) {
player->swing();
}
@ -693,6 +671,7 @@ void PlayerConnection::handleAnimate(std::shared_ptr<AnimatePacket> packet) {
void PlayerConnection::handlePlayerCommand(
std::shared_ptr<PlayerCommandPacket> packet) {
player->resetLastActionTime();
if (packet->action == PlayerCommandPacket::START_SNEAKING) {
player->setSneaking(true);
} else if (packet->action == PlayerCommandPacket::STOP_SNEAKING) {
@ -704,6 +683,20 @@ void PlayerConnection::handlePlayerCommand(
} else if (packet->action == PlayerCommandPacket::STOP_SLEEPING) {
player->stopSleepInBed(false, true, true);
synched = false;
} else if (packet->action == PlayerCommandPacket::RIDING_JUMP) {
// currently only supported by horses...
if ((player->riding != NULL) &&
player->riding->GetType() == eTYPE_HORSE) {
std::dynamic_pointer_cast<EntityHorse>(player->riding)
->onPlayerJump(packet->data);
}
} else if (packet->action == PlayerCommandPacket::OPEN_INVENTORY) {
// also only supported by horses...
if ((player->riding != NULL) &&
player->riding->instanceof(eTYPE_HORSE)) {
std::dynamic_pointer_cast<EntityHorse>(player->riding)
->openInventory(player);
}
} else if (packet->action == PlayerCommandPacket::START_IDLEANIM) {
player->setIsIdle(true);
} else if (packet->action == PlayerCommandPacket::STOP_IDLEANIM) {
@ -737,11 +730,12 @@ void PlayerConnection::warn(const std::wstring& string) {
// send( std::shared_ptr<ChatPacket>( new ChatPacket(L"§9" + string) ) );
}
std::wstring PlayerConnection::getConsoleName() { return player->name; }
std::wstring PlayerConnection::getConsoleName() { return player->getName(); }
void PlayerConnection::handleInteract(std::shared_ptr<InteractPacket> packet) {
ServerLevel* level = server->getLevel(player->dimension);
std::shared_ptr<Entity> target = level->getEntity(packet->target);
player->resetLastActionTime();
// Fix for #8218 - Gameplay: Attacking zombies from a different level often
// results in no hits being registered 4J Stu - If the client says that we
@ -763,6 +757,14 @@ void PlayerConnection::handleInteract(std::shared_ptr<InteractPacket> packet) {
if (packet->action == InteractPacket::INTERACT) {
player->interact(target);
} else if (packet->action == InteractPacket::ATTACK) {
if ((target->GetType() == eTYPE_ITEMENTITY) ||
(target->GetType() == eTYPE_EXPERIENCEORB) ||
(target->GetType() == eTYPE_ARROW) || target == player) {
// disconnect("Attempting to attack an invalid entity");
// server.warn("Player " + player.getName() + " tried to attack
// an invalid entity");
return;
}
player->attack(target);
}
//}
@ -1033,6 +1035,33 @@ void PlayerConnection::handleServerSettingsChanged(
app.SetGameHostOption(
eGameHostOption_TNT,
app.GetGameHostOption(packet->data, eGameHostOption_TNT));
app.SetGameHostOption(
eGameHostOption_MobGriefing,
app.GetGameHostOption(packet->data,
eGameHostOption_MobGriefing));
app.SetGameHostOption(
eGameHostOption_KeepInventory,
app.GetGameHostOption(packet->data,
eGameHostOption_KeepInventory));
app.SetGameHostOption(
eGameHostOption_DoMobSpawning,
app.GetGameHostOption(packet->data,
eGameHostOption_DoMobSpawning));
app.SetGameHostOption(
eGameHostOption_DoMobLoot,
app.GetGameHostOption(packet->data, eGameHostOption_DoMobLoot));
app.SetGameHostOption(
eGameHostOption_DoTileDrops,
app.GetGameHostOption(packet->data,
eGameHostOption_DoTileDrops));
app.SetGameHostOption(
eGameHostOption_DoDaylightCycle,
app.GetGameHostOption(packet->data,
eGameHostOption_DoDaylightCycle));
app.SetGameHostOption(
eGameHostOption_NaturalRegeneration,
app.GetGameHostOption(packet->data,
eGameHostOption_NaturalRegeneration));
server->getPlayers()->broadcastAll(
std::shared_ptr<ServerSettingsChangedPacket>(
@ -1063,6 +1092,7 @@ void PlayerConnection::handleGameCommand(
void PlayerConnection::handleClientCommand(
std::shared_ptr<ClientCommandPacket> packet) {
player->resetLastActionTime();
if (packet->action == ClientCommandPacket::PERFORM_RESPAWN) {
if (player->wonGame) {
player = server->getPlayers()->respawn(
@ -1072,10 +1102,10 @@ void PlayerConnection::handleClientCommand(
// else if (player.getLevel().getLevelData().isHardcore())
//{
// if (server.isSingleplayer() &&
//player.name.equals(server.getSingleplayerName()))
// player.name.equals(server.getSingleplayerName()))
// {
// player.connection.disconnect("You have died. Game over,
//man, it's game over!"); server.selfDestruct();
// man, it's game over!"); server.selfDestruct();
// }
// else
// {
@ -1084,7 +1114,7 @@ void PlayerConnection::handleClientCommand(
// server.getPlayers().getBans().add(ban);
// player.connection.disconnect("You have died. Game over,
//man, it's game over!");
// man, it's game over!");
// }
//}
else {
@ -1135,13 +1165,11 @@ void PlayerConnection::handleContainerSetSlot(
void PlayerConnection::handleContainerClick(
std::shared_ptr<ContainerClickPacket> packet) {
player->resetLastActionTime();
if (player->containerMenu->containerId == packet->containerId &&
player->containerMenu->isSynched(player)) {
std::shared_ptr<ItemInstance> clicked = player->containerMenu->clicked(
packet->slotNum, packet->buttonNum,
packet->quickKey ? AbstractContainerMenu::CLICK_QUICK_MOVE
: AbstractContainerMenu::CLICK_PICKUP,
player);
packet->slotNum, packet->buttonNum, packet->clickType, player);
if (ItemInstance::matches(packet->item, clicked)) {
// Yep, you sure did click what you claimed to click!
@ -1161,9 +1189,9 @@ void PlayerConnection::handleContainerClick(
player->containerMenu->setSynched(player, false);
std::vector<std::shared_ptr<ItemInstance> > items;
for (unsigned int i = 0; i < player->containerMenu->slots->size();
for (unsigned int i = 0; i < player->containerMenu->slots.size();
i++) {
items.push_back(player->containerMenu->slots->at(i)->getItem());
items.push_back(player->containerMenu->slots.at(i)->getItem());
}
player->refreshContainer(player->containerMenu, &items);
@ -1174,6 +1202,7 @@ void PlayerConnection::handleContainerClick(
void PlayerConnection::handleContainerButtonClick(
std::shared_ptr<ContainerButtonClickPacket> packet) {
player->resetLastActionTime();
if (player->containerMenu->containerId == packet->containerId &&
player->containerMenu->isSynched(player)) {
player->containerMenu->clickMenuButton(player, packet->buttonId);
@ -1261,9 +1290,9 @@ void PlayerConnection::handleSetCreativeModeSlot(
// as the client also incorrectly predicts the auxvalue of the
// mapItem
std::vector<std::shared_ptr<ItemInstance> > items;
for (unsigned int i = 0; i < player->inventoryMenu->slots->size();
for (unsigned int i = 0; i < player->inventoryMenu->slots.size();
i++) {
items.push_back(player->inventoryMenu->slots->at(i)->getItem());
items.push_back(player->inventoryMenu->slots.at(i)->getItem());
}
player->refreshContainer(player->inventoryMenu, &items);
}
@ -1283,6 +1312,7 @@ void PlayerConnection::handleContainerAck(
void PlayerConnection::handleSignUpdate(
std::shared_ptr<SignUpdatePacket> packet) {
player->resetLastActionTime();
app.DebugPrintf("PlayerConnection::handleSignUpdate\n");
ServerLevel* level = server->getLevel(player->dimension);
@ -1293,8 +1323,8 @@ void PlayerConnection::handleSignUpdate(
if (std::dynamic_pointer_cast<SignTileEntity>(te) != NULL) {
std::shared_ptr<SignTileEntity> ste =
std::dynamic_pointer_cast<SignTileEntity>(te);
if (!ste->isEditable()) {
server->warn(L"Player " + player->name +
if (!ste->isEditable() || ste->getPlayerWhoMayEdit() != player) {
server->warn(L"Player " + player->getName() +
L" just tried to change non-editable sign");
return;
}
@ -1552,7 +1582,7 @@ void PlayerConnection::handleCustomPayload(
ItemInstance carried = player.inventory.getSelected();
if (sentItem != null && sentItem.id == Item.writingBook.id && sentItem.id == carried.id)
{
carried.setTag(sentItem.getTag());
carried.addTagElement(WrittenBookItem.TAG_PAGES, sentItem.getTag().getList(WrittenBookItem.TAG_PAGES));
}
}
else if (CustomPayloadPacket.CUSTOM_BOOK_SIGN_PACKET.equals(customPayloadPacket.identifier))
@ -1569,7 +1599,9 @@ void PlayerConnection::handleCustomPayload(
ItemInstance carried = player.inventory.getSelected();
if (sentItem != null && sentItem.id == Item.writtenBook.id && carried.id == Item.writingBook.id)
{
carried.setTag(sentItem.getTag());
carried.addTagElement(WrittenBookItem.TAG_AUTHOR, new StringTag(WrittenBookItem.TAG_AUTHOR, player.getName()));
carried.addTagElement(WrittenBookItem.TAG_TITLE, new StringTag(WrittenBookItem.TAG_TITLE, sentItem.getTag().getString(WrittenBookItem.TAG_TITLE)));
carried.addTagElement(WrittenBookItem.TAG_PAGES, sentItem.getTag().getList(WrittenBookItem.TAG_PAGES));
carried.id = Item.writtenBook.id;
}
}
@ -1585,9 +1617,55 @@ void PlayerConnection::handleCustomPayload(
if (dynamic_cast<MerchantMenu*>(menu)) {
((MerchantMenu*)menu)->setSelectionHint(selection);
}
} else if (CustomPayloadPacket::SET_ADVENTURE_COMMAND_PACKET.compare(
customPayloadPacket->identifier) == 0) {
if (!server->isCommandBlockEnabled()) {
app.DebugPrintf("Command blocks not enabled");
// player->sendMessage(ChatMessageComponent.forTranslation("advMode.notEnabled"));
} else if (player->hasPermission(eGameCommand_Effect) &&
player->abilities.instabuild) {
ByteArrayInputStream bais(customPayloadPacket->data);
DataInputStream input(&bais);
int x = input.readInt();
int y = input.readInt();
int z = input.readInt();
std::wstring command = Packet::readUtf(&input, 256);
std::shared_ptr<TileEntity> tileEntity =
player->level->getTileEntity(x, y, z);
std::shared_ptr<CommandBlockEntity> cbe =
std::dynamic_pointer_cast<CommandBlockEntity>(tileEntity);
if (tileEntity != NULL && cbe != NULL) {
cbe->setCommand(command);
player->level->sendTileUpdated(x, y, z);
// player->sendMessage(ChatMessageComponent.forTranslation("advMode.setCommand.success",
// command));
}
} else {
// player.sendMessage(ChatMessageComponent.forTranslation("advMode.notAllowed"));
}
} else if (CustomPayloadPacket::SET_BEACON_PACKET.compare(
customPayloadPacket->identifier) == 0) {
if (dynamic_cast<BeaconMenu*>(player->containerMenu) != NULL) {
ByteArrayInputStream bais(customPayloadPacket->data);
DataInputStream input(&bais);
int primary = input.readInt();
int secondary = input.readInt();
BeaconMenu* beaconMenu = (BeaconMenu*)player->containerMenu;
Slot* slot = beaconMenu->getSlot(0);
if (slot->hasItem()) {
slot->remove(1);
std::shared_ptr<BeaconTileEntity> beacon =
beaconMenu->getBeacon();
beacon->setPrimaryPower(primary);
beacon->setSecondaryPower(secondary);
beacon->setChanged();
}
}
} else if (CustomPayloadPacket::SET_ITEM_NAME_PACKET.compare(
customPayloadPacket->identifier) == 0) {
RepairMenu* menu = dynamic_cast<RepairMenu*>(player->containerMenu);
AnvilMenu* menu = dynamic_cast<AnvilMenu*>(player->containerMenu);
if (menu) {
if (customPayloadPacket->data.data == NULL ||
customPayloadPacket->data.length < 1) {
@ -1604,6 +1682,8 @@ void PlayerConnection::handleCustomPayload(
}
}
bool PlayerConnection::isDisconnected() { return done; }
// 4J Added
void PlayerConnection::handleDebugOptions(
@ -1634,6 +1714,10 @@ void PlayerConnection::handleCraftItem(
// no room in inventory, so throw it down
player->drop(pTempItemInst);
}
} else if (pTempItemInst->id == Item::fireworksCharge_Id ||
pTempItemInst->id == Item::fireworks_Id) {
CraftingMenu* menu = (CraftingMenu*)player->containerMenu;
player->openFireworks(menu->getX(), menu->getY(), menu->getZ());
} else {
// TODO 4J Stu - Assume at the moment that the client can work this out
// for us...
@ -1692,9 +1776,9 @@ void PlayerConnection::handleCraftItem(
// as the client also incorrectly predicts the auxvalue of the
// mapItem
std::vector<std::shared_ptr<ItemInstance> > items;
for (unsigned int i = 0; i < player->containerMenu->slots->size();
for (unsigned int i = 0; i < player->containerMenu->slots.size();
i++) {
items.push_back(player->containerMenu->slots->at(i)->getItem());
items.push_back(player->containerMenu->slots.at(i)->getItem());
}
player->refreshContainer(player->containerMenu, &items);
} else {

View file

@ -28,9 +28,9 @@ private:
bool didTick;
int lastKeepAliveId;
__int64 lastKeepAliveTime;
int64_t lastKeepAliveTime;
static Random random;
__int64 lastKeepAliveTick;
int64_t lastKeepAliveTick;
int chatSpamTickCount;
int dropSpamTickCount;
@ -108,6 +108,7 @@ public:
std::shared_ptr<PlayerAbilitiesPacket> playerAbilitiesPacket);
virtual void handleCustomPayload(
std::shared_ptr<CustomPayloadPacket> customPayloadPacket);
virtual bool isDisconnected();
// 4J Added
virtual void handleCraftItem(std::shared_ptr<CraftItemPacket> packet);
@ -156,4 +157,4 @@ private:
std::vector<std::wstring> m_texturesRequested;
bool m_bWasKicked;
};
};

View file

@ -25,6 +25,7 @@
#include "../../Minecraft.World/Headers/net.minecraft.world.level.storage.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.saveddata.h"
#include "../../Minecraft.World/Util/JavaMath.h"
#include "../../Minecraft.World/Level/Storage/EntityIO.h"
#ifdef _XBOX
#include "../Platform/Xbox/Network/NetworkPlayerXbox.h"
#elif defined(__PS3__) || defined(__ORBIS__)
@ -76,7 +77,10 @@ PlayerList::~PlayerList() {
void PlayerList::placeNewPlayer(Connection* connection,
std::shared_ptr<ServerPlayer> player,
std::shared_ptr<LoginPacket> packet) {
bool newPlayer = load(player);
CompoundTag* playerTag = load(player);
bool newPlayer = playerTag == NULL;
player->setLevel(server->getLevel(player->dimension));
player->gameMode->setLevel((ServerLevel*)player->level);
@ -240,19 +244,22 @@ void PlayerList::placeNewPlayer(Connection* connection,
playerConnection->send(std::shared_ptr<LoginPacket>(new LoginPacket(
L"", player->entityId, level->getLevelData()->getGenerator(),
level->getSeed(), player->gameMode->getGameModeForPlayer()->getId(),
(std::uint8_t)level->dimension->id,
(std::uint8_t)level->getMaxBuildHeight(), (std::uint8_t)getMaxPlayers(),
level->difficulty, TelemetryManager->GetMultiplayerInstanceID(),
playerIndex, level->useNewSeaLevel(),
player->getAllPlayerGamePrivileges(),
(uint8_t)level->dimension->id, (uint8_t)level->getMaxBuildHeight(),
(uint8_t)getMaxPlayers(), level->difficulty,
TelemetryManager->GetMultiplayerInstanceID(), (BYTE)playerIndex,
level->useNewSeaLevel(), player->getAllPlayerGamePrivileges(),
level->getLevelData()->getXZSize(),
level->getLevelData()->getHellScale())));
playerConnection->send(std::shared_ptr<SetSpawnPositionPacket>(
new SetSpawnPositionPacket(spawnPos->x, spawnPos->y, spawnPos->z)));
playerConnection->send(std::shared_ptr<PlayerAbilitiesPacket>(
new PlayerAbilitiesPacket(&player->abilities)));
playerConnection->send(std::shared_ptr<SetCarriedItemPacket>(
new SetCarriedItemPacket(player->inventory->selected)));
delete spawnPos;
updateEntireScoreboard((ServerScoreboard*)level->getScoreboard(), player);
sendLevelInfo(player, level);
// 4J-PB - removed, since it needs to be localised in the language the
@ -274,8 +281,9 @@ void PlayerList::placeNewPlayer(Connection* connection,
player->xRot);
server->getConnection()->addPlayerConnection(playerConnection);
playerConnection->send(
std::shared_ptr<SetTimePacket>(new SetTimePacket(level->getTime())));
playerConnection->send(std::shared_ptr<SetTimePacket>(new SetTimePacket(
level->getGameTime(), level->getDayTime(),
level->getGameRules()->getBoolean(GameRules::RULE_DAYLIGHT))));
AUTO_VAR(activeEffects, player->getActiveEffects());
for (AUTO_VAR(it, activeEffects->begin()); it != activeEffects->end();
@ -287,6 +295,18 @@ void PlayerList::placeNewPlayer(Connection* connection,
player->initMenu();
if (playerTag != NULL && playerTag->contains(Entity::RIDING_TAG)) {
// this player has been saved with a mount tag
std::shared_ptr<Entity> mount = EntityIO::loadStatic(
playerTag->getCompound(Entity::RIDING_TAG), level);
if (mount != NULL) {
mount->forcedLoading = true;
level->addEntity(mount);
player->ride(mount);
mount->forcedLoading = false;
}
}
// If we are joining at the same time as someone in the end on this system
// is travelling through the win portal, then we should set our wonGame flag
// to true so that respawning works when the EndPoem is closed
@ -305,6 +325,35 @@ void PlayerList::placeNewPlayer(Connection* connection,
}
}
void PlayerList::updateEntireScoreboard(ServerScoreboard* scoreboardstd::,
std::shared_ptr<ServerPlayer> player) {
// unordered_set<Objective *> objectives;
// for (PlayerTeam team : scoreboard->getPlayerTeams())
//{
// player->connection->send( shared_ptr<SetPlayerTeamPacket>(new
// SetPlayerTeamPacket(team, SetPlayerTeamPacket::METHOD_ADD)));
// }
// for (int slot = 0; slot < Scoreboard::DISPLAY_SLOTS; slot++)
//{
// Objective objective = scoreboard->getDisplayObjective(slot);
// if (objective != NULL && !objectives->contains(objective))
// {
// vector<shared_ptr<Packet> > *packets =
// scoreboard->getStartTrackingPackets(objective);
// for (Packet packet : packets)
// {
// player->connection->send(packet);
// }
// objectives->add(objective);
// }
//}
}
void PlayerList::setLevel(ServerLevelArray levels) {
playerIo = levels[0]->getLevelStorage()->getPlayerIO();
}
@ -323,8 +372,7 @@ int PlayerList::getMaxRange() {
return PlayerChunkMap::convertChunkRangeToBlock(getViewDistance());
}
// 4J Changed return val to bool to check if new player or loaded player
bool PlayerList::load(std::shared_ptr<ServerPlayer> player) {
CompoundTag* PlayerList::load(std::shared_ptr<ServerPlayer> player) {
return playerIo->load(player);
}
@ -346,6 +394,8 @@ void PlayerList::validatePlayerSpawnPosition(
app.DebugPrintf("Original pos is %f, %f, %f in dimension %d\n", player->x,
player->y, player->z, player->dimension);
bool spawnForced = player->isRespawnForced();
double targetX = 0;
if (player->x < 0)
targetX = Mth::ceil(player->x) - 0.5;
@ -397,12 +447,12 @@ void PlayerList::validatePlayerSpawnPosition(
Pos* bedPosition = player->getRespawnPosition();
if (bedPosition != NULL) {
Pos* respawnPosition = Player::checkBedValidRespawnPosition(
server->getLevel(player->dimension), bedPosition);
server->getLevel(player->dimension), bedPosition, spawnForced);
if (respawnPosition != NULL) {
player->moveTo(respawnPosition->x + 0.5f,
respawnPosition->y + 0.1f,
respawnPosition->z + 0.5f, 0, 0);
player->setRespawnPosition(bedPosition);
player->setRespawnPosition(bedPosition, spawnForced);
}
delete bedPosition;
}
@ -480,6 +530,13 @@ void PlayerList::remove(std::shared_ptr<ServerPlayer> player) {
// sure that the player is gone delete the map
if (player->isGuest()) playerIo->deleteMapFilesForPlayer(player);
ServerLevel* level = player->getLevel();
if (player->riding != NULL) {
// remove mount first because the player unmounts when being
// removed, also remove mount because it's saved in the player's
// save tag
level->removeEntityImmediately(player->riding);
app.DebugPrintf("removing player mount");
}
level->removeEntity(player);
level->getChunkMap()->remove(player);
AUTO_VAR(it, find(players.begin(), players.end(), player));
@ -601,6 +658,7 @@ std::shared_ptr<ServerPlayer> PlayerList::respawn(
->removeEntityImmediately(serverPlayer);
Pos* bedPosition = serverPlayer->getRespawnPosition();
bool spawnForced = serverPlayer->isRespawnForced();
removePlayerFromReceiving(serverPlayer);
serverPlayer->dimension = targetDimension;
@ -613,9 +671,10 @@ std::shared_ptr<ServerPlayer> PlayerList::respawn(
std::shared_ptr<ServerPlayer> player = std::shared_ptr<ServerPlayer>(
new ServerPlayer(server, server->getLevel(serverPlayer->dimension),
serverPlayer->name,
serverPlayer->getName(),
new ServerPlayerGameMode(
server->getLevel(serverPlayer->dimension))));
player->connection = serverPlayer->connection;
player->restoreFrom(serverPlayer, keepAllPlayerData);
if (keepAllPlayerData) {
// Fix for #81759 - TU9: Content: Gameplay: Entering The End Exit Portal
@ -633,7 +692,6 @@ std::shared_ptr<ServerPlayer> PlayerList::respawn(
// packet
// player->entityId = serverPlayer->entityId;
player->connection = serverPlayer->connection;
player->setPlayerDefaultSkin(skin);
player->setIsGuest(serverPlayer->isGuest());
player->setPlayerIndex(playerIndex);
@ -665,7 +723,7 @@ std::shared_ptr<ServerPlayer> PlayerList::respawn(
player->moveTo(serverPlayer->x, serverPlayer->y, serverPlayer->z,
serverPlayer->yRot, serverPlayer->xRot);
if (bedPosition != NULL) {
player->setRespawnPosition(bedPosition);
player->setRespawnPosition(bedPosition, spawnForced);
delete bedPosition;
}
// Fix for #81759 - TU9: Content: Gameplay: Entering The End Exit Portal
@ -674,11 +732,12 @@ std::shared_ptr<ServerPlayer> PlayerList::respawn(
player->inventory->selected = serverPlayer->inventory->selected;
} else if (bedPosition != NULL) {
Pos* respawnPosition = Player::checkBedValidRespawnPosition(
server->getLevel(serverPlayer->dimension), bedPosition);
server->getLevel(serverPlayer->dimension), bedPosition,
spawnForced);
if (respawnPosition != NULL) {
player->moveTo(respawnPosition->x + 0.5f, respawnPosition->y + 0.1f,
respawnPosition->z + 0.5f, 0, 0);
player->setRespawnPosition(bedPosition);
player->setRespawnPosition(bedPosition, spawnForced);
} else {
player->connection->send(
std::shared_ptr<GameEventPacket>(new GameEventPacket(
@ -703,6 +762,10 @@ std::shared_ptr<ServerPlayer> PlayerList::respawn(
level->getLevelData()->getHellScale())));
player->connection->teleport(player->x, player->y, player->z, player->yRot,
player->xRot);
player->connection->send(
std::shared_ptr<SetExperiencePacket>(new SetExperiencePacket(
player->experienceProgress, player->totalExperience,
player->experienceLevel)));
if (keepAllPlayerData) {
std::vector<MobEffectInstance*>* activeEffects =
@ -725,6 +788,7 @@ std::shared_ptr<ServerPlayer> PlayerList::respawn(
players.push_back(player);
player->initMenu();
player->setHealth(player->getHealth());
// 4J-JEV - Dying before this point in the tutorial is pretty annoying,
// making sure to remove health/hunger and give you back your meat.
@ -772,9 +836,9 @@ void PlayerList::toggleDimension(std::shared_ptr<ServerPlayer> player,
// (1) if this isn't the primary player, then we just need to remove it from
// the entity tracker (2) if this Is the primary player then:
// (a) if isEmptying is true, then remove the player from the
//tracker, and send "remove entity" packets for anything seen (this is the
//original behaviour of the code) (b) if isEmptying is false, then we'll be
//transferring control of entity tracking to another player
// tracker, and send "remove entity" packets for anything seen (this is the
// original behaviour of the code) (b) if isEmptying is false, then
// we'll be transferring control of entity tracking to another player
if (isPrimary) {
if (isEmptying) {
@ -824,58 +888,7 @@ void PlayerList::toggleDimension(std::shared_ptr<ServerPlayer> player,
oldLevel->removeEntityImmediately(player);
player->removed = false;
double xt = player->x;
double zt = player->z;
double scale =
newLevel->getLevelData()
->getHellScale(); // 4J Scale was 8 but this is all we can fit in
if (player->dimension == -1) {
xt /= scale;
zt /= scale;
player->moveTo(xt, player->y, zt, player->yRot, player->xRot);
if (player->isAlive()) {
oldLevel->tick(player, false);
}
} else if (player->dimension == 0) {
xt *= scale;
zt *= scale;
player->moveTo(xt, player->y, zt, player->yRot, player->xRot);
if (player->isAlive()) {
oldLevel->tick(player, false);
}
} else {
Pos* p = newLevel->getDimensionSpecificSpawn();
xt = p->x;
player->y = p->y;
zt = p->z;
delete p;
player->moveTo(xt, player->y, zt, 90, 0);
if (player->isAlive()) {
oldLevel->tick(player, false);
}
}
removePlayerFromReceiving(player, false, lastDimension);
addPlayerToReceiving(player);
if (lastDimension == 1) {
} else {
xt = (double)Mth::clamp((int)xt, -Level::MAX_LEVEL_SIZE + 128,
Level::MAX_LEVEL_SIZE - 128);
zt = (double)Mth::clamp((int)zt, -Level::MAX_LEVEL_SIZE + 128,
Level::MAX_LEVEL_SIZE - 128);
if (player->isAlive()) {
newLevel->addEntity(player);
player->moveTo(xt, player->y, zt, player->yRot, player->xRot);
newLevel->tick(player, false);
newLevel->cache->autoCreate = true;
(new PortalForcer())->force(newLevel, player);
newLevel->cache->autoCreate = false;
}
}
player->setLevel(newLevel);
repositionAcrossDimension(player, lastDimension, oldLevel, newLevel);
changeDimension(player, oldLevel);
player->gameMode->setLevel(newLevel);
@ -912,6 +925,80 @@ void PlayerList::toggleDimension(std::shared_ptr<ServerPlayer> player,
sendAllPlayerInfo(player);
}
void PlayerList::repositionAcrossDimension(std::shared_ptr<Entity> entity,
int lastDimension,
ServerLevel* oldLevel,
ServerLevel* newLevel) {
double xt = entity->x;
double zt = entity->z;
double xOriginal = entity->x;
double yOriginal = entity->y;
double zOriginal = entity->z;
float yRotOriginal = entity->yRot;
double scale =
newLevel->getLevelData()
->getHellScale(); // 4J Scale was 8 but this is all we can fit in
if (entity->dimension == -1) {
xt /= scale;
zt /= scale;
entity->moveTo(xt, entity->y, zt, entity->yRot, entity->xRot);
if (entity->isAlive()) {
oldLevel->tick(entity, false);
}
} else if (entity->dimension == 0) {
xt *= scale;
zt *= scale;
entity->moveTo(xt, entity->y, zt, entity->yRot, entity->xRot);
if (entity->isAlive()) {
oldLevel->tick(entity, false);
}
} else {
Pos* p;
if (lastDimension == 1) {
// Coming from the end
p = newLevel->getSharedSpawnPos();
} else {
// Going to the end
p = newLevel->getDimensionSpecificSpawn();
}
xt = p->x;
entity->y = p->y;
zt = p->z;
delete p;
entity->moveTo(xt, entity->y, zt, 90, 0);
if (entity->isAlive()) {
oldLevel->tick(entity, false);
}
}
if (entity->GetType() == eTYPE_SERVERPLAYER) {
std::shared_ptr<ServerPlayer> player =
std::dynamic_pointer_cast<ServerPlayer>(entity);
removePlayerFromReceiving(player, false, lastDimension);
addPlayerToReceiving(player);
}
if (lastDimension != 1) {
xt = (double)Mth::clamp((int)xt, -Level::MAX_LEVEL_SIZE + 128,
Level::MAX_LEVEL_SIZE - 128);
zt = (double)Mth::clamp((int)zt, -Level::MAX_LEVEL_SIZE + 128,
Level::MAX_LEVEL_SIZE - 128);
if (entity->isAlive()) {
newLevel->addEntity(entity);
entity->moveTo(xt, entity->y, zt, entity->yRot, entity->xRot);
newLevel->tick(entity, false);
newLevel->cache->autoCreate = true;
newLevel->getPortalForcer()->force(entity, xOriginal, yOriginal,
zOriginal, yRotOriginal);
newLevel->cache->autoCreate = false;
}
}
entity->setLevel(newLevel);
}
void PlayerList::tick() {
// 4J - brought changes to how often this is sent forward from 1.2.3
if (++sendAllPlayerInfoIn > SEND_PLAYER_INFO_INTERVAL) {
@ -1095,6 +1182,121 @@ std::shared_ptr<ServerPlayer> PlayerList::getPlayer(PlayerUID uid) {
return nullptr;
}
std::shared_ptr<ServerPlayer> PlayerList::getNearestPlayer(Pos* position,
int range) {
if (players.empty()) return nullptr;
if (position == NULL) return players.at(0);
std::shared_ptr<ServerPlayer> current = nullptr;
double dist = -1;
int rangeSqr = range * range;
for (int i = 0; i < players.size(); i++) {
std::shared_ptr<ServerPlayer> next = players.at(i);
double newDist =
position->distSqr(next->getCommandSenderWorldPosition());
if ((dist == -1 || newDist < dist) &&
(range <= 0 || newDist <= rangeSqr)) {
dist = newDist;
current = next;
}
}
return current;
}
std::vector<ServerPlayer>* PlayerList::getPlayers(
Pos* position, int rangeMin, int rangeMax, int count, int mode,
int levelMin, int levelMax,
std::unordered_map<std::wstring, int>* scoreRequirements,
const std::wstring& playerName, const std::wstring& teamName,
Level* level) {
app.DebugPrintf("getPlayers NOT IMPLEMENTED!");
return NULL;
/*if (players.empty()) return NULL;
vector<shared_ptr<ServerPlayer> > result = new
vector<shared_ptr<ServerPlayer> >(); bool reverse = count < 0; bool
playerNameNot = !playerName.empty() && playerName.startsWith("!"); bool
teamNameNot = !teamName.empty() && teamName.startsWith("!"); int rangeMinSqr
= rangeMin * rangeMin; int rangeMaxSqr = rangeMax * rangeMax; count =
Mth.abs(count);
if (playerNameNot) playerName = playerName.substring(1);
if (teamNameNot) teamName = teamName.substring(1);
for (int i = 0; i < players.size(); i++) {
ServerPlayer player = players.get(i);
if (level != null && player.level != level) continue;
if (playerName != null) {
if (playerNameNot == playerName.equalsIgnoreCase(player.getAName()))
continue;
}
if (teamName != null) {
Team team = player.getTeam();
String actualName = team == null ? "" : team.getName();
if (teamNameNot == teamName.equalsIgnoreCase(actualName)) continue;
}
if (position != null && (rangeMin > 0 || rangeMax > 0)) {
float distance = position.distSqr(player.getCommandSenderWorldPosition());
if (rangeMin > 0 && distance < rangeMinSqr) continue;
if (rangeMax > 0 && distance > rangeMaxSqr) continue;
}
if (!meetsScoreRequirements(player, scoreRequirements)) continue;
if (mode != GameType.NOT_SET.getId() && mode !=
player.gameMode.getGameModeForPlayer().getId()) continue; if (levelMin > 0
&& player.experienceLevel < levelMin) continue; if (player.experienceLevel >
levelMax) continue;
result.add(player);
}
if (position != null) Collections.sort(result, new
PlayerDistanceComparator(position)); if (reverse)
Collections.reverse(result); if (count > 0) result = result.subList(0,
Math.min(count, result.size()));
return result;*/
}
bool PlayerList::meetsScoreRequirements(
std::shared_ptr<Player> player,
std::unordered_map<std::wstring, int> scoreRequirements) {
app.DebugPrintf("meetsScoreRequirements NOT IMPLEMENTED!");
return false;
// if (scoreRequirements == null || scoreRequirements.size() == 0) return
// true;
// for (Map.Entry<String, Integer> requirement :
// scoreRequirements.entrySet()) { String name = requirement.getKey();
// boolean min = false;
// if (name.endsWith("_min") && name.length() > 4) {
// min = true;
// name = name.substring(0, name.length() - 4);
// }
// Scoreboard scoreboard = player.getScoreboard();
// Objective objective = scoreboard.getObjective(name);
// if (objective == null) return false;
// Score score = player.getScoreboard().getPlayerScore(player.getAName(),
// objective); int value = score.getScore();
// if (value < requirement.getValue() && min) {
// return false;
// } else if (value > requirement.getValue() && !min) {
// return false;
// }
//}
// return true;
}
void PlayerList::sendMessage(const std::wstring& name,
const std::wstring& message) {
std::shared_ptr<ServerPlayer> player = getPlayer(name);
@ -1168,27 +1370,6 @@ void PlayerList::broadcast(std::shared_ptr<Player> except, double x, double y,
}
}
void PlayerList::broadcastToAllOps(const std::wstring& message) {
std::shared_ptr<Packet> chatPacket =
std::shared_ptr<ChatPacket>(new ChatPacket(message));
for (unsigned int i = 0; i < players.size(); i++) {
std::shared_ptr<ServerPlayer> p = players[i];
if (isOp(p->name)) {
p->connection->send(chatPacket);
}
}
}
bool PlayerList::sendTo(const std::wstring& name,
std::shared_ptr<Packet> packet) {
std::shared_ptr<ServerPlayer> player = getPlayer(name);
if (player != NULL) {
player->connection->send(packet);
return true;
}
return false;
}
void PlayerList::saveAll(ProgressListener* progressListener,
bool bDeleteGuestMaps /*= false*/) {
if (progressListener != NULL)
@ -1222,8 +1403,9 @@ void PlayerList::reloadWhitelist() {}
void PlayerList::sendLevelInfo(std::shared_ptr<ServerPlayer> player,
ServerLevel* level) {
player->connection->send(
std::shared_ptr<SetTimePacket>(new SetTimePacket(level->getTime())));
player->connection->send(std::shared_ptr<SetTimePacket>(new SetTimePacket(
level->getGameTime(), level->getDayTime(),
level->getGameRules()->getBoolean(GameRules::RULE_DAYLIGHT))));
if (level->isRaining()) {
player->connection->send(std::shared_ptr<GameEventPacket>(
new GameEventPacket(GameEventPacket::START_RAINING, 0)));
@ -1247,6 +1429,8 @@ void PlayerList::sendLevelInfo(std::shared_ptr<ServerPlayer> player,
void PlayerList::sendAllPlayerInfo(std::shared_ptr<ServerPlayer> player) {
player->refreshContainer(player->inventoryMenu);
player->resetSentInfo();
player->connection->send(std::shared_ptr<SetCarriedItemPacket>(
new SetCarriedItemPacket(player->inventory->selected)));
}
int PlayerList::getPlayerCount() { return (int)players.size(); }
@ -1268,7 +1452,7 @@ MinecraftServer* PlayerList::getServer() { return server; }
int PlayerList::getViewDistance() { return viewDistance; }
void PlayerList::setOverrideGameMode(GameType* gameMode) {
this->overrideGameMode = gameMode;
overrideGameMode = gameMode;
}
void PlayerList::updatePlayerGameMode(std::shared_ptr<ServerPlayer> newPlayer,

View file

@ -14,6 +14,7 @@ class TileEntity;
class ProgressListener;
class GameType;
class LoginPacket;
class ServerScoreboard;
class PlayerList {
private:
@ -70,13 +71,18 @@ public:
void placeNewPlayer(Connection* connection,
std::shared_ptr<ServerPlayer> player,
std::shared_ptr<LoginPacket> packet);
protected:
void updateEntireScoreboard(ServerScoreboard* scoreboard,
std::shared_ptr<ServerPlayer> player);
public:
void setLevel(ServerLevelArray levels);
void changeDimension(std::shared_ptr<ServerPlayer> player,
ServerLevel* from);
int getMaxRange();
bool load(std::shared_ptr<ServerPlayer>
player); // 4J Changed return val to bool to check if new
// player or loaded player
CompoundTag* load(std::shared_ptr<ServerPlayer> player);
protected:
void save(std::shared_ptr<ServerPlayer> player);
@ -94,6 +100,9 @@ public:
bool keepAllPlayerData);
void toggleDimension(std::shared_ptr<ServerPlayer> player,
int targetDimension);
void repositionAcrossDimension(std::shared_ptr<Entity> entity,
int lastDimension, ServerLevel* oldLevel,
ServerLevel* newLevel);
void tick();
bool isTrackingTile(int x, int y, int z, int dimension); // 4J added
void prioritiseTileChanges(int x, int y, int z, int dimension); // 4J added
@ -108,13 +117,25 @@ public:
bool isOp(std::shared_ptr<ServerPlayer> player); // 4J Added
std::shared_ptr<ServerPlayer> getPlayer(const std::wstring& name);
std::shared_ptr<ServerPlayer> getPlayer(PlayerUID uid);
std::shared_ptr<ServerPlayer> getNearestPlayer(Pos* position, int range);
std::vector<ServerPlayer>* getPlayers(
Pos* position, int rangeMin, int rangeMax, int count, int mode,
int levelMin, int levelMax,
std::unordered_map<std::wstring, int>* scoreRequirements,
const std::wstring& playerName, const std::wstring& teamName,
Level* level);
private:
bool meetsScoreRequirements(
std::shared_ptr<Player> player,
std::unordered_map<std::wstring, int> scoreRequirements);
public:
void sendMessage(const std::wstring& name, const std::wstring& message);
void broadcast(double x, double y, double z, double range, int dimension,
std::shared_ptr<Packet> packet);
void broadcast(std::shared_ptr<Player> except, double x, double y, double z,
double range, int dimension, std::shared_ptr<Packet> packet);
void broadcastToAllOps(const std::wstring& message);
bool sendTo(const std::wstring& name, std::shared_ptr<Packet> packet);
// 4J Added ProgressListener *progressListener param and bDeleteGuestMaps
// param
void saveAll(ProgressListener* progressListener,

View file

@ -11,6 +11,7 @@
#include "../../Minecraft.World/Util/ThreadName.h"
#include "../../Minecraft.World/IO/Streams/Compression.h"
#include "../../Minecraft.World/Level/Storage/OldChunkStorage.h"
#include "../../Minecraft.World/Blocks/Tile.h"
ServerChunkCache::ServerChunkCache(ServerLevel* level, ChunkStorage* storage,
ChunkSource* source) {
@ -40,6 +41,7 @@ ServerChunkCache::ServerChunkCache(ServerLevel* level, ChunkStorage* storage,
// 4J-PB added
ServerChunkCache::~ServerChunkCache() {
storage->WaitForAll(); // MGH - added to fix crash bug 175183
delete emptyChunk;
delete cache;
delete source;
@ -336,6 +338,76 @@ LevelChunk* ServerChunkCache::getChunkLoadedOrUnloaded(int x, int z) {
}
#endif
// 4J MGH added, for expanding worlds, to kill any player changes and reset the
// chunk
#ifdef _LARGE_WORLDS
void ServerChunkCache::overwriteLevelChunkFromSource(int x, int z) {
int ix = x + XZOFFSET;
int iz = z + XZOFFSET;
// Check we're in range of the stored level
if ((ix < 0) || (ix >= XZSIZE)) assert(0);
if ((iz < 0) || (iz >= XZSIZE)) assert(0);
int idx = ix * XZSIZE + iz;
LevelChunk* chunk = NULL;
chunk = source->getChunk(x, z);
assert(chunk);
if (chunk) {
save(chunk);
}
}
void ServerChunkCache::updateOverwriteHellChunk(LevelChunk* origChunk,
LevelChunk* playerChunk,
int xMin, int xMax, int zMin,
int zMax) {
// replace a section of the chunk with the original source data, if it
// hasn't already changed
for (int x = xMin; x < xMax; x++) {
for (int z = zMin; z < zMax; z++) {
for (int y = 0; y < 256; y++) {
int playerTile = playerChunk->getTile(x, y, z);
if (playerTile ==
Tile::unbreakable_Id) // if the tile is still unbreakable,
// the player hasn't changed it, so
// we can replace with the source
playerChunk->setTileAndData(x, y, z,
origChunk->getTile(x, y, z),
origChunk->getData(x, y, z));
}
}
}
}
void ServerChunkCache::overwriteHellLevelChunkFromSource(int x, int z,
int minVal,
int maxVal) {
int ix = x + XZOFFSET;
int iz = z + XZOFFSET;
// Check we're in range of the stored level
if ((ix < 0) || (ix >= XZSIZE)) assert(0);
if ((iz < 0) || (iz >= XZSIZE)) assert(0);
int idx = ix * XZSIZE + iz;
autoCreate = true;
LevelChunk* playerChunk = getChunk(x, z);
autoCreate = false;
LevelChunk* origChunk = source->getChunk(x, z);
assert(origChunk);
if (playerChunk != emptyChunk) {
if (x == minVal)
updateOverwriteHellChunk(origChunk, playerChunk, 0, 4, 0, 16);
if (x == maxVal)
updateOverwriteHellChunk(origChunk, playerChunk, 12, 16, 0, 16);
if (z == minVal)
updateOverwriteHellChunk(origChunk, playerChunk, 0, 16, 0, 4);
if (z == maxVal)
updateOverwriteHellChunk(origChunk, playerChunk, 0, 16, 12, 16);
}
save(playerChunk);
}
#endif
// 4J Added //
#ifdef _LARGE_WORLDS
void ServerChunkCache::dontDrop(int x, int z) {
@ -362,7 +434,7 @@ LevelChunk* ServerChunkCache::load(int x, int z) {
levelChunk = storage->load(level, x, z);
}
if (levelChunk != NULL) {
levelChunk->lastSaveTime = level->getTime();
levelChunk->lastSaveTime = level->getGameTime();
}
return levelChunk;
}
@ -376,7 +448,7 @@ void ServerChunkCache::saveEntities(LevelChunk* levelChunk) {
void ServerChunkCache::save(LevelChunk* levelChunk) {
if (storage == NULL) return;
levelChunk->lastSaveTime = level->getTime();
levelChunk->lastSaveTime = level->getGameTime();
storage->save(level, levelChunk);
}
@ -710,6 +782,7 @@ bool ServerChunkCache::save(bool force, ProgressListener* progressListener) {
notificationEvent[3]; // These are signalled by the threads to let
// us know they are complete
C4JThread* saveThreads[3];
DWORD threadId[3];
SaveThreadData threadData[3];
ZeroMemory(&threadData[0], sizeof(SaveThreadData));
ZeroMemory(&threadData[1], sizeof(SaveThreadData));
@ -787,7 +860,7 @@ bool ServerChunkCache::save(bool force, ProgressListener* progressListener) {
if (saveThreads[j] == NULL) {
char threadName[256];
sprintf(threadName, "Save thread %d\n", j);
SetThreadName(0, threadName);
SetThreadName(threadId[j], threadName);
// saveThreads[j] =
// CreateThread(NULL,0,runSaveThreadProc,&threadData[j],CREATE_SUSPENDED,&threadId[j]);
@ -926,22 +999,37 @@ bool ServerChunkCache::tick() {
if (!m_toDrop.empty()) {
LevelChunk* chunk = m_toDrop.front();
if (!chunk->isUnloaded()) {
save(chunk);
saveEntities(chunk);
chunk->unload(true);
// Don't unload a chunk that contains a player, as this will
// cause their entity to be removed from the level itself
// and they will never tick again. This can happen if a
// player moves a long distance in one tick, for example
// when the server thread has locked up doing something for
// a while whilst a player kept moving. In this case, the
// player is moved in the player chunk map (driven by the
// network packets being processed for their new position)
// before the player's tick is called to remove them from
// the chunk they used to be in, and add them to their
// current chunk. This will only be a temporary state and we
// should be able to unload the chunk on the next call to
// this tick.
if (!chunk->containsPlayer()) {
save(chunk);
saveEntities(chunk);
chunk->unload(true);
// loadedChunks.remove(cp);
// loadedChunkList.remove(chunk);
AUTO_VAR(it, std::find(m_loadedChunkList.begin(),
m_loadedChunkList.end(), chunk));
if (it != m_loadedChunkList.end())
m_loadedChunkList.erase(it);
// loadedChunks.remove(cp);
// loadedChunkList.remove(chunk);
AUTO_VAR(it, find(m_loadedChunkList.begin(),
m_loadedChunkList.end(), chunk));
if (it != m_loadedChunkList.end())
m_loadedChunkList.erase(it);
int ix = chunk->x + XZOFFSET;
int iz = chunk->z + XZOFFSET;
int idx = ix * XZSIZE + iz;
m_unloadedCache[idx] = chunk;
cache[idx] = NULL;
int ix = chunk->x + XZOFFSET;
int iz = chunk->z + XZOFFSET;
int idx = ix * XZSIZE + iz;
m_unloadedCache[idx] = chunk;
cache[idx] = NULL;
}
}
m_toDrop.pop_front();
}
@ -970,8 +1058,11 @@ TilePos* ServerChunkCache::findNearestMapFeature(
return source->findNearestMapFeature(level, featureName, x, y, z);
}
int ServerChunkCache::runSaveThreadProc(void* lpParam) {
SaveThreadData* params = static_cast<SaveThreadData*>(lpParam);
void ServerChunkCache::recreateLogicStructuresForChunk(int chunkX, int chunkZ) {
}
int ServerChunkCache::runSaveThreadProc(LPVOID lpParam) {
SaveThreadData* params = (SaveThreadData*)lpParam;
if (params->useSharedThreadStorage) {
Compression::UseDefaultThreadStorage();

View file

@ -10,7 +10,7 @@ class ServerLevel;
class ServerChunkCache : public ChunkSource {
private:
// std::unordered_set<int,IntKeyHash, IntKeyEq> toDrop;
// unordered_set<int,IntKeyHash, IntKeyEq> toDrop;
private:
LevelChunk* emptyChunk;
ChunkSource* source;
@ -48,6 +48,17 @@ public:
virtual LevelChunk* getChunk(int x, int z);
#ifdef _LARGE_WORLDS
LevelChunk* getChunkLoadedOrUnloaded(int x, int z); // 4J added
void overwriteLevelChunkFromSource(
int x, int z); // 4J MGH added, for expanding worlds, to kill any
// player changes and reset the chunk
void overwriteHellLevelChunkFromSource(
int x, int z, int minVal,
int maxVal); // 4J MGH added, for expanding worlds, to reset the outer
// tiles in the chunk
void updateOverwriteHellChunk(LevelChunk* origChunk,
LevelChunk* playerChunk, int xMin, int xMax,
int zMin, int zMax);
#endif
virtual LevelChunk** getCache() { return cache; } // 4J added
@ -89,6 +100,7 @@ public:
virtual TilePos* findNearestMapFeature(Level* level,
const std::wstring& featureName,
int x, int y, int z);
virtual void recreateLogicStructuresForChunk(int chunkX, int chunkZ);
private:
typedef struct _SaveThreadData {

View file

@ -88,14 +88,10 @@ void ServerConnection::tick() {
std::shared_ptr<PlayerConnection> player = players[i];
std::shared_ptr<ServerPlayer> serverPlayer = player->getPlayer();
if (serverPlayer) {
serverPlayer->updateFrameTick();
serverPlayer->doChunkSendingTick(false);
}
// try { // 4J - removed try/catch
player->tick();
// } catch (Exception e) {
// logger.log(Level.WARNING, "Failed to handle packet: " + e,
// e); player.disconnect("Internal server error");
// }
if (player->done) {
players.erase(players.begin() + i);
i--;
@ -187,9 +183,14 @@ void ServerConnection::handleServerSettingsChanged(
//
// for (unsigned int i = 0; i < players.size(); i++)
// {
// std::shared_ptr<PlayerConnection> playerconnection =
// shared_ptr<PlayerConnection> playerconnection =
// players[i];
// playerconnection->setShowOnMaps(pMinecraft->options->GetGamertagSetting());
// }
// }
}
std::vector<std::shared_ptr<PlayerConnection> >*
ServerConnection::getPlayers() {
return &players;
}

View file

@ -53,4 +53,5 @@ public:
void handleTextureAndGeometryReceived(const std::wstring& textureName);
void handleServerSettingsChanged(
std::shared_ptr<ServerSettingsChangedPacket> packet);
std::vector<std::shared_ptr<PlayerConnection> >* getPlayers();
};

View file

@ -0,0 +1,233 @@
#include "../Platform/stdafx.h"
#include "ServerScoreboard.h"
ServerScoreboard::ServerScoreboard(MinecraftServer* server) {
this->server = server;
}
MinecraftServer* ServerScoreboard::getServer() { return server; }
void ServerScoreboard::onScoreChanged(Score* score) {
// Scoreboard::onScoreChanged(score);
// if (trackedObjectives.contains(score.getObjective()))
//{
// server->getPlayers()->broadcastAll( shared_ptr<SetScorePacket>( new
// SetScorePacket(score, SetScorePacket::METHOD_CHANGE)));
// }
// setDirty();
}
void ServerScoreboard::onPlayerRemoved(const std::wstring& player) {
// Scoreboard::onPlayerRemoved(player);
// server->getPlayers()->broadcastAll( shared_ptr<SetScorePacket>( new
// SetScorePacket(player))); setDirty();
}
void ServerScoreboard::setDisplayObjective(int slot, Objective* objective) {
// Objective *old = getDisplayObjective(slot);
// Scoreboard::setDisplayObjective(slot, objective);
// if (old != objective && old != NULL)
//{
// if (getObjectiveDisplaySlotCount(old) > 0)
// {
// server->getPlayers()->broadcastAll(
// shared_ptr<SetDisplayObjectivePacket>( new
// SetDisplayObjectivePacket(slot, objective)));
// }
// else
// {
// stopTrackingObjective(old);
// }
// }
// if (objective != NULL)
//{
// if (trackedObjectives.contains(objective))
// {
// server->getPlayers()->broadcastAll(
// shared_ptr<SetDisplayObjectivePacket>( new
// SetDisplayObjectivePacket(slot, objective)));
// }
// else
// {
// startTrackingObjective(objective);
// }
// }
// setDirty();
}
void ServerScoreboard::addPlayerToTeam(const std::wstring& player,
PlayerTeam* team) {
// Scoreboard::addPlayerToTeam(player, team);
// server->getPlayers()->broadcastAll( shared_ptr<SetPlayerTeamPacket>( new
// SetPlayerTeamPacket(team, Arrays::asList(player),
// SetPlayerTeamPacket::METHOD_JOIN)));
// setDirty();
}
void ServerScoreboard::removePlayerFromTeam(const std::wstring& player,
PlayerTeam* team) {
// Scoreboard::removePlayerFromTeam(player, team);
// server->getPlayers()->broadcastAll( shared_ptr<SetPlayerTeamPacket>( new
// SetPlayerTeamPacket(team, Arrays::asList(player),
// SetPlayerTeamPacket::METHOD_LEAVE)));
// setDirty();
}
void ServerScoreboard::onObjectiveAdded(Objective* objective) {
// Scoreboard::onObjectiveAdded(objective);
// setDirty();
}
void ServerScoreboard::onObjectiveChanged(Objective* objective) {
// Scoreaboard::onObjectiveChanged(objective);
// if (trackedObjectives.contains(objective))
//{
// server->getPlayers()->broadcastAll( shared_ptr<SetObjectivePacket>( new
// SetObjectivePacket(objective, SetObjectivePacket::METHOD_CHANGE)));
// }
// setDirty();
}
void ServerScoreboard::onObjectiveRemoved(Objective* objective) {
// Scoreboard::onObjectiveRemoved(objective);
// if (trackedObjectives.contains(objective))
//{
// stopTrackingObjective(objective);
// }
// setDirty();
}
void ServerScoreboard::onTeamAdded(PlayerTeam* team) {
// Scoreboard::onTeamAdded(team);
// server->getPlayers()->broadcastAll( shared_ptr<SetPlayerTeamPacket>( new
// SetPlayerTeamPacket(team, SetPlayerTeamPacket::METHOD_ADD)) );
// setDirty();
}
void ServerScoreboard::onTeamChanged(PlayerTeam* team) {
// Scoreboard::onTeamChanged(team);
// server->getPlayers()->broadcastAll( shared_ptr<SetPlayerTeamPacket>( new
// SetPlayerTeamPacket(team, SetPlayerTeamPacket::METHOD_CHANGE)));
// setDirty();
}
void ServerScoreboard::onTeamRemoved(PlayerTeam* team) {
// Scoreboard::onTeamRemoved(team);
// server->getPlayers()->broadcastAll( shared_ptr<SetPlayerTeamPacket>( new
// SetPlayerTeamPacket(team, SetPlayerTeamPacket::METHOD_REMOVE)) );
// setDirty();
}
void ServerScoreboard::setSaveData(ScoreboardSaveData* data) {
// saveData = data;
}
void ServerScoreboard::setDirty() {
// if (saveData != NULL)
//{
// saveData->setDirty();
// }
}
std::vector<std::shared_ptr<Packet> >*
ServerScoreboard::getStartTrackingPackets(Objective* objective) {
return NULL;
// vector<shared_ptr<Packet> > *packets = new vector<shared_ptr<Packet> >();
// packets.push_back( shared_ptr<SetObjectivePacket>( new
// SetObjectivePacket(objective, SetObjectivePacket::METHOD_ADD)));
// for (int slot = 0; slot < DISPLAY_SLOTS; slot++)
//{
// if (getDisplayObjective(slot) == objective) packets.push_back(
// shared_ptr<SetDisplayObjectivePacket>( new
// SetDisplayObjectivePacket(slot, objective)));
// }
// for (Score score : getPlayerScores(objective))
//{
// packets.push_back( shared_ptr<SetScorePacket>( new SetScorePacket(score,
// SetScorePacket::METHOD_CHANGE)));
// }
// return packets;
}
void ServerScoreboard::startTrackingObjective(Objective* objective) {
// vector<shared_ptr<Packet> > *packets =
// getStartTrackingPackets(objective);
// for (ServerPlayer player : server.getPlayers().players)
//{
// for (Packet packet : packets)
// {
// player.connection.send(packet);
// }
// }
// trackedObjectives.push_back(objective);
}
std::vector<std::shared_ptr<Packet> >* ServerScoreboard::getStopTrackingPackets(
Objective* objective) {
return NULL;
// vector<shared_ptr<Packet> > *packets = new ArrayList<Packet>();
// packets->push_back( shared_ptr<SetObjectivePacket( new
// SetObjectivePacket(objective, SetObjectivePacket.METHOD_REMOVE)));
// for (int slot = 0; slot < DISPLAY_SLOTS; slot++)
//{
// if (getDisplayObjective(slot) == objective) packets.add(new
// SetDisplayObjectivePacket(slot, objective));
// }
// return packets;
}
void ServerScoreboard::stopTrackingObjective(Objective* objective) {
// vector<shared_ptr<Packet> > *packets = getStopTrackingPackets(objective);
// for (ServerPlayer player : server.getPlayers().players)
//{
// for (Packet packet : packets)
// {
// player->connection->send(packet);
// }
// }
// trackedObjectives.remove(objective);
}
int ServerScoreboard::getObjectiveDisplaySlotCount(Objective* objective) {
return 0;
// int count = 0;
// for (int slot = 0; slot < DISPLAY_SLOTS; slot++)
//{
// if (getDisplayObjective(slot) == objective) count++;
// }
// return count;
}

View file

@ -0,0 +1,45 @@
#pragma once
#include "../../Minecraft.World/Scores/Scoreboard.h"
class MinecraftServer;
class ScoreboardSaveData;
class Score;
class Objective;
class PlayerTeam;
class ServerScoreboard : public Scoreboard {
private:
MinecraftServer* server;
std::unordered_set<Objective*> trackedObjectives;
ScoreboardSaveData* saveData;
public:
ServerScoreboard(MinecraftServer* server);
MinecraftServer* getServer();
void onScoreChanged(Score* score);
void onPlayerRemoved(const std::wstring& player);
void setDisplayObjective(int slot, Objective* objective);
void addPlayerToTeam(const std::wstring& player, PlayerTeam* team);
void removePlayerFromTeam(const std::wstring& player, PlayerTeam* team);
void onObjectiveAdded(Objective* objective);
void onObjectiveChanged(Objective* objective);
void onObjectiveRemoved(Objective* objective);
void onTeamAdded(PlayerTeam* team);
void onTeamChanged(PlayerTeam* team);
void onTeamRemoved(PlayerTeam* team);
void setSaveData(ScoreboardSaveData* data);
protected:
void setDirty();
public:
std::vector<std::shared_ptr<Packet> >* getStartTrackingPackets(
Objective* objective);
void startTrackingObjective(Objective* objective);
std::vector<std::shared_ptr<Packet> >* getStopTrackingPackets(
Objective* objective);
void stopTrackingObjective(Objective* objective);
int getObjectiveDisplaySlotCount(Objective* objective);
};