the whole game

This commit is contained in:
Kolyah35
2026-03-02 22:04:18 +03:00
parent 816e9060b4
commit f0617a5d22
2069 changed files with 581500 additions and 0 deletions

View File

@@ -0,0 +1,925 @@
#include "ClientSideNetworkHandler.h"
#include "packet/PacketInclude.h"
#include "RakNetInstance.h"
#include "../world/level/chunk/ChunkSource.h"
#include "../world/level/Level.h"
#include "../world/level/storage/LevelStorageSource.h"
#include "../world/entity/player/Player.h"
#include "../world/entity/player/Inventory.h"
#include "../client/Minecraft.h"
#include "../client/gamemode/GameMode.h"
#ifndef STANDALONE_SERVER
#include "../client/gui/screens/DisconnectionScreen.h"
#endif
#include "../client/player/LocalPlayer.h"
#include "../client/multiplayer/MultiPlayerLevel.h"
#include "../client/player/input/KeyboardInput.h"
#include "../client/sound/SoundEngine.h"
#include "../world/entity/MobFactory.h"
#include "../raknet/RakPeerInterface.h"
#include "../world/level/Explosion.h"
#include "../world/level/tile/entity/FurnaceTileEntity.h"
#include "../world/inventory/BaseContainerMenu.h"
#ifndef STANDALONE_SERVER
#include "../client/particle/TakeAnimationParticle.h"
#endif
#include "../world/entity/EntityFactory.h"
#include "../world/entity/item/PrimedTnt.h"
#include "../world/entity/projectile/Arrow.h"
#include "../world/level/tile/entity/ChestTileEntity.h"
#include "../client/player/RemotePlayer.h"
#include "../world/level/tile/LevelEvent.h"
#include "../world/entity/item/FallingTile.h"
static MultiPlayerLevel* mpcast(Level* l) { return (MultiPlayerLevel*) l; }
ClientSideNetworkHandler::ClientSideNetworkHandler(Minecraft* minecraft, IRakNetInstance* raknetInstance)
: minecraft(minecraft),
raknetInstance(raknetInstance),
level(NULL),
requestNextChunkPosition(0),
requestNextChunkIndex(0)
{
rakPeer = raknetInstance->getPeer();
}
ClientSideNetworkHandler::~ClientSideNetworkHandler()
{
}
void ClientSideNetworkHandler::requestNextChunk()
{
if (requestNextChunkIndex < NumRequestChunks)
{
IntPair& chunk = requestNextChunkIndexList[requestNextChunkIndex];
RequestChunkPacket packet(chunk.x, chunk.y);
raknetInstance->send(packet);
//LOGI("requesting chunks @ (%d, %d)\n", chunk.x, chunk.y);
//raknetInstance->send(new RequestChunkPacket(requestNextChunkPosition % CHUNK_CACHE_WIDTH, requestNextChunkPosition / CHUNK_CACHE_WIDTH));
requestNextChunkIndex++;
requestNextChunkPosition++;
}
}
bool ClientSideNetworkHandler::areAllChunksLoaded()
{
return (requestNextChunkPosition >= (CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH));
}
bool ClientSideNetworkHandler::isChunkLoaded(int x, int z)
{
if (x < 0 || x >= CHUNK_CACHE_WIDTH || z < 0 || z >= CHUNK_CACHE_WIDTH) {
LOGE("Error: Tried to request chunk (%d, %d)\n", x, z);
return true;
}
return chunksLoaded[x * CHUNK_CACHE_WIDTH + z];
//return areAllChunksLoaded();
}
void ClientSideNetworkHandler::onConnect(const RakNet::RakNetGUID& hostGuid)
{
LOGI("onConnect, server guid: %s, local guid: %s\n", hostGuid.ToString(), rakPeer->GetMyGUID().ToString());
serverGuid = hostGuid;
clearChunksLoaded();
LoginPacket packet(minecraft->user->name.c_str(), SharedConstants::NetworkProtocolVersion);
raknetInstance->send(packet);
}
void ClientSideNetworkHandler::onUnableToConnect()
{
LOGI("onUnableToConnect\n");
}
void ClientSideNetworkHandler::onDisconnect(const RakNet::RakNetGUID& guid)
{
LOGI("onDisconnect\n");
if (level)
{
level->isClientSide = false;
for (int i = (int)level->players.size()-1; i >= 0; --i ) {
Player* p = level->players[i];
if (p != minecraft->player) {
p->reallyRemoveIfPlayer = true;
level->removeEntity(p);
}
}
}
#ifndef STANDALONE_SERVER
minecraft->gui.addMessage("Disconnected from server");
#endif
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginStatusPacket* packet) {
if (packet->status == LoginStatus::Success) {
raknetInstance->setIsLoggedIn(true);
return;
}
if (packet->status == LoginStatus::Failed_ClientOld) {
LOGI("Disconnect! Client is outdated!\n");
#ifndef STANDALONE_SERVER
minecraft->setScreen(new DisconnectionScreen("Could not connect: Outdated client!"));
#endif
}
if (packet->status == LoginStatus::Failed_ServerOld) {
LOGI("Disconnect! Server is outdated!\n");
#ifndef STANDALONE_SERVER
minecraft->setScreen(new DisconnectionScreen("Could not connect: Outdated server!"));
#endif
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, StartGamePacket* packet)
{
LOGI("StartGamePacket\n");
#ifdef RPI
if (packet->gameType != GameType::Creative) {
minecraft->setScreen(new DisconnectionScreen("Could not connect: Incompatible server!"));
return;
}
#endif
const std::string& levelId = LevelStorageSource::TempLevelId;
LevelStorageSource* storageSource = minecraft->getLevelSource();
storageSource->deleteLevel(levelId);
//level = new Level(storageSource->selectLevel(levelId, true), "temp", packet->levelSeed, SharedConstants::StorageVersion);
MultiPlayerLevel* level = new MultiPlayerLevel(
storageSource->selectLevel(levelId, true),
"temp",
LevelSettings(packet->levelSeed, LevelSettings::validateGameType(packet->gameType)),
SharedConstants::StorageVersion);
level->isClientSide = true;
bool isCreative = (packet->gameType == GameType::Creative);
LocalPlayer* player = new LocalPlayer(minecraft, level, minecraft->user, level->dimension->id, isCreative);
player->owner = rakPeer->GetMyGUID();
player->entityId = packet->entityId;
player->moveTo(packet->x, packet->y, packet->z, player->yRot, player->xRot);
LOGI("new pos: %f, %f [%f - %f]\n", player->x, player->z, player->bb.y0, player->bb.y1);
minecraft->setLevel(level, "ClientSideNetworkHandler -> setLevel", player);
minecraft->setIsCreativeMode(isCreative);
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MessagePacket* packet)
{
LOGI("MessagePacket\n");
#ifndef STANDALONE_SERVER
minecraft->gui.addMessage(packet->message.C_String());
#endif
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SetTimePacket* packet)
{
if (!level)
return;
LOGI("SetTimePacket\n");
level->setTime(packet->time);
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AddEntityPacket* packet)
{
if (!level)
return;
Entity* e = EntityFactory::CreateEntity(packet->type, level);
if (!e)
return;
e->entityId = packet->entityId;
e->setPos(packet->x, packet->y, packet->z);
// Entity Specific stuff here
switch (packet->type)
{
case EntityTypes::IdFallingTile: {
int data = -packet->data();
FallingTile* ft = (FallingTile*) e;
ft->tile = data & 0xff;
ft->data = data >> 16;
}
case EntityTypes::IdArrow: {
Entity* owner = level->getEntity(packet->data());
if (owner && owner->isMob())
((Arrow*)e)->ownerId = owner->entityId;
break;
}
default:
break;
}
if (packet->hasMovementData()) {
/*
e->xd = packet->xd;
e->yd = packet->yd;
e->zd = packet->zd;
*/
e->lerpMotion(packet->xd, packet->yd, packet->zd);
//LOGI("Client: reading entity with %f, %f, %f\n", e->xd, e->yd, e->zd);
}
mpcast(level)->putEntity(packet->entityId, e);
}
void ClientSideNetworkHandler::handle( const RakNet::RakNetGUID& source, AddPaintingPacket* packet ) {
if (!level)
return;
Painting* painting = new Painting(level, packet->xTile, packet->yTile, packet->zTile, packet->dir, packet->motive);
mpcast(level)->putEntity(packet->entityId, painting);
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AddMobPacket* packet)
{
LOGI("AddMobPacket (%p)\n", level);
if (!level) {
LOGW("Trying to add a mob with no level!\n");
//we skip this since we will get this player anyway when we request level
return;
}
if (!packet->type) {
LOGE("Trying to add a mob without a type id\n");
return;
}
Mob* mob = MobFactory::CreateMob(packet->type, level);
if (!mob) {
LOGE("Server tried to add an unknown mob type! :%d\n", packet->type);
return;
}
mob->entityId = packet->entityId;
mob->moveTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot);
mob->getEntityData()->assignValues(&packet->unpack);
level->addEntity(mob);
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AddPlayerPacket* packet)
{
if (!level) {
//we skip this since we will get this player anyway when we request level
return;
}
LOGI("AddPlayerPacket\n");
Player* player = new RemotePlayer(level, minecraft->isCreativeMode());
minecraft->gameMode->initAbilities(player->abilities);
player->entityId = packet->entityId;
level->addEntity(player);
player->moveTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot);
player->name = packet->name.C_String();
player->owner = packet->owner;
player->getEntityData()->assignValues(&packet->unpack);
int slot = Inventory::MAX_SELECTION_SIZE;
if (packet->carriedItemId == 0) {
player->inventory->clearSlot(slot);
} else {
ItemInstance newItem(packet->carriedItemId, 1, packet->carriedItemAuxValue);
player->inventory->replaceSlot(slot, &newItem);
}
player->inventory->moveToSelectedSlot(slot, true);
//player->resetPos();
std::string message = packet->name.C_String();
message += " joined the game";
#ifndef STANDALONE_SERVER
minecraft->gui.addMessage(message);
#endif
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemovePlayerPacket* packet) {
if (!level || source == minecraft->player->owner) return;
if (Player* player = findPlayer(level, packet->entityId, &packet->owner)) {
player->reallyRemoveIfPlayer = true;
level->removeEntity(player);
}
//for (int i = (int)level->players.size()-1; i >= 0; --i) {
// if (level->players[i]->owner == source) {
// level->players[i]->reallyRemoveIfPlayer = true;
// level->players.erase(level->players.begin() + i);
// break;
// }
//}
//if (!player) return;
//std::string message = packet->name.C_String();
//message += " joined the game";
//minecraft->gui.addMessage(message);
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveEntityPacket* packet)
{
if (!level) return;
Entity* entity = level->getEntity(packet->entityId);
LOGI("RemoveEntityPacket %p %p, %d\n", entity, minecraft->player, entity?(int)(entity->isPlayer()): -1);
if (!entity) return;
level->removeEntity(entity);
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AddItemEntityPacket* packet)
{
if (!level) return;
ItemEntity* entity = new ItemEntity(level, packet->x, packet->y, packet->z, ItemInstance(packet->itemId, packet->itemCount, packet->auxValue));
entity->xd = packet->xa();
entity->yd = packet->ya();
entity->zd = packet->za();
//LOGI("item-entity @ client: %f, %f, %f\n", entity->xd, entity->yd, entity->zd);
mpcast(level)->putEntity(packet->id, entity);
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, TakeItemEntityPacket* packet) {
if (!level) return;
Entity* e = level->getEntity(packet->itemId);
if (!e)
return;
ItemInstance item;
if (e->isItemEntity()) {
item = ((ItemEntity*) e)->item;
#ifndef STANDALONE_SERVER
if (Entity* to = level->getEntity(packet->playerId))
minecraft->particleEngine->add(new TakeAnimationParticle(level, (ItemEntity*)e, to, -0.5f));
#endif
}
else if (e->getEntityTypeId() == EntityTypes::IdArrow)
item = ItemInstance(Item::arrow);
if (item.isNull())
return;
// try take it and if we don't have space; re-throw it
if (minecraft->player->entityId == packet->playerId
&& !minecraft->player->inventory->add(&item)) {
DropItemPacket dropPacket(packet->playerId, item);
minecraft->raknetInstance->send(dropPacket);
}
level->playSound(e, "random.pop", 0.2f, 1.0f * 2.f);
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlayerPacket* packet)
{
if (!level)
return;
//printf("MovePlayerPacket\n");
Entity* entity = level->getEntity(packet->entityId);
if (entity)
{
entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3);
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MoveEntityPacket* packet)
{
if (!level)
return;
//printf("MovePlayerPacket\n");
Entity* entity = level->getEntity(packet->entityId);
if (entity)
{
float xRot = packet->hasRot? packet->xRot : entity->xRot;
float yRot = packet->hasRot? packet->yRot : entity->yRot;
entity->lerpTo(packet->x, packet->y, packet->z, yRot, xRot, 3);
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UpdateBlockPacket* packet)
{
if (!level) return;
//LOGI("UpdateBlockPacket @ %d, %d, %d\n", packet->x, packet->y, packet->z);
int x = packet->x, z = packet->z;
if (isChunkLoaded(x >> 4, z >> 4))
{
//LOGI("chunk is loaded - UPDATE @ %d, %d, %d -- %d, %d\n", x, packet->y, z, packet->blockId, packet->blockData);
int y = packet->y;
int tileId = Tile::transformToValidBlockId(packet->blockId, x, y, z);
level->setTileAndData(x, y, z, tileId, packet->blockData);
} else {
SBufferedBlockUpdate update;
update.blockId = packet->blockId;
update.blockData = packet->blockData;
update.setData = true;
update.x = packet->x;
update.y = packet->y;
update.z = packet->z;
bufferedBlockUpdates.push_back(update);
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ExplodePacket* packet) {
if (!level) return;
Explosion explosion(level, NULL, packet->x, packet->y, packet->z, packet->r);
explosion.toBlow.insert(packet->toBlow.begin(), packet->toBlow.end());
explosion.finalizeExplosion();
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LevelEventPacket* packet) {
if (!level) return;
if(packet->eventId == LevelEvent::ALL_PLAYERS_SLEEPING) {
minecraft->player->setAllPlayersSleeping();
}
else {
minecraft->level->levelEvent(NULL, packet->eventId, packet->x, packet->y, packet->z, packet->data);
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, TileEventPacket* packet) {
if (!level) return;
minecraft->level->tileEvent(packet->x, packet->y, packet->z, packet->b0, packet->b1);
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, EntityEventPacket* packet) {
if (!level) return;
Entity* e = level->getEntity(packet->entityId);
if (e) e->handleEntityEvent(packet->eventId);
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChunkDataPacket* packet)
{
if (!level) {
LOGI("level @ handle ChunkDataPacket is 0\n");
return;
}
//LOGI("ChunkDataPacket\n");
LevelChunk* chunk = level->getChunkSource()->create(packet->x, packet->z);
if (!chunk || chunk->isEmpty())
{
LOGI("Failed to find write-able chunk\n");
return;
}
//unsigned char* blockIds = chunk->getBlockData();
DataLayer& blockData = chunk->data;
const int setSize = LEVEL_HEIGHT / 8;
const int setShift = 4; // power of LEVEL_HEIGHT / 8
bool recalcHeight = false;
int x0 = 16, x1 = 0, z0 = 16, z1 = 0, y0 = LEVEL_HEIGHT, y1 = 0;
int rx = packet->x << 4;
int rz = packet->z << 4;
unsigned char readBlockBuffer[setSize];
unsigned char readDataBuffer[setSize / 2];
for (int i = 0; i < CHUNK_COLUMNS; i++)
{
unsigned char updateBits = 0;
packet->chunkData.Read(updateBits);
if (updateBits > 0)
{
recalcHeight = true;
int colX = (i % CHUNK_WIDTH);
int colZ = (i / CHUNK_WIDTH);
int colDataPosition = colX << 11 | colZ << 7;
for (int set = 0; set < 8; set++)
{
if ((updateBits & (1 << set)) != 0)
{
packet->chunkData.Read((char*)readBlockBuffer, setSize);
packet->chunkData.Read((char*)readDataBuffer, setSize / 2);
for (int part = 0; part < setSize; part++)
{
//if (readBlockBuffer[part] == ((Tile*)Tile::grass)->id)
// readBlockBuffer[part] = 255;
int x = rx + colX;
int y = (set << setShift) + part;
int z = rz + colZ;
int tileId = Tile::transformToValidBlockId(readBlockBuffer[part], x, y, z);
level->setTileNoUpdate(x, y, z, tileId);
}
// ((part & 1) == 0) ? readDataBuffer[part >> 1] & 0xf : (readDataBuffer[part >> 1] & 0xf0) >> 4
//packet->chunkData.Read((char*)(&blockIds[colDataPosition + (set << setShift)]), setSize);
// block data is only 4 bits per block
//packet->chunkData.Read((char*)(&blockData.data[(colDataPosition + (set << setShift)) >> 1]), setSize >> 1);
memcpy(&blockData.data[(colDataPosition + (set << setShift)) >> 1], readDataBuffer, setSize >> 1);
}
if (((1 << set) << setShift) < y0)
{
y0 = ((1 << set) << setShift);
}
if (((1 << set) << setShift) + (LEVEL_HEIGHT / 8) - 1 > y1)
{
y1 = ((1 << set) << setShift) + (LEVEL_HEIGHT / 8) - 1;
}
}
if ((i % CHUNK_WIDTH) < x0)
{
x0 = (i % CHUNK_WIDTH);
}
if ((i % CHUNK_WIDTH) > x1)
{
x1 = (i % CHUNK_WIDTH);
}
if ((i / CHUNK_WIDTH) < z0)
{
z0 = (i / CHUNK_WIDTH);
}
if ((i / CHUNK_WIDTH) > z1)
{
z1 = (i / CHUNK_WIDTH);
}
}
}
if (recalcHeight)
{
// chunk->recalcHeightmap();
// //chunk->recalcBlockLights();
level->setTilesDirty((packet->x << 4) + x0, y0, (packet->z << 4) + z0, (packet->x << 4) + x1, y1, (packet->z << 4) + z1);
// int rx = packet->x << 4;
// int rz = packet->z << 4;
// level->updateLight(LightLayer::Block, x0 + rx - 1, y0, z0 + rz - 1, x1 + rx + 1, y1, z1 + rz + 1);
// //for (int cx = x0; cx < x1; cx++)
// //{
// // for (int cz = z0; cz < z1; cz++)
// // {
// // for (int cy = y0; cy < y1; cy++)
// // {
// //level->updateLight(LightLayer::Sky, cx + rx, cy, cz + rz, cx + rx, cy, cz + rz);
// // level->updateLight(LightLayer::Block, cx + rx - 1, cy, cz + rz - 1, cx + rx + 1, cy, cz + rz + 1);
// // }
// // }
// //}
//
}
//chunk->terrainPopulated = true;
chunk->unsaved = false;
chunksLoaded[packet->x * CHUNK_CACHE_WIDTH + packet->z] = true;
if (areAllChunksLoaded())
{
ReadyPacket packet(ReadyPacket::READY_REQUESTEDCHUNKS);
raknetInstance->send(packet);
for (unsigned int i = 0; i < bufferedBlockUpdates.size(); i++)
{
const SBufferedBlockUpdate& update = bufferedBlockUpdates[i];
int tileId = Tile::transformToValidBlockId( update.blockId, update.x, update.y, update.z );
if (update.setData)
level->setTileAndData(update.x, update.y, update.z, tileId, update.blockData);
else
level->setTile(update.x, update.y, update.z, tileId);
}
bufferedBlockUpdates.clear();
}
else
{
requestNextChunk();
}
}
class _ChunkSorter
{
public:
_ChunkSorter(int x, int z)
: x(x),
y(z)
{
}
bool operator() (const IntPair& a, const IntPair& b) {
const int ax = a.x - x, ay = a.y - y;
const int bx = b.x - x, by = b.y - y;
return (ax*ax + ay*ay) < (bx*bx + by*by);
}
private:
int x;
int y;
};
void ClientSideNetworkHandler::arrangeRequestChunkOrder() {
clearChunksLoaded();
// Default sort is around center of the world
int cx = CHUNK_CACHE_WIDTH / 2;
int cz = CHUNK_CACHE_WIDTH / 2;
// If player exists, let's sort around him
Player* p = minecraft? minecraft->player : NULL;
if (p) {
cx = Mth::floor(p->x / (float)CHUNK_WIDTH);
cz = Mth::floor(p->z / (float)CHUNK_DEPTH);
}
_ChunkSorter sorter(cx, cz);
std::sort(requestNextChunkIndexList, requestNextChunkIndexList + NumRequestChunks, sorter);
}
void ClientSideNetworkHandler::levelGenerated(Level* level)
{
this->level = level;
ReadyPacket packet(ReadyPacket::READY_CLIENTGENERATION);
raknetInstance->send(packet);
arrangeRequestChunkOrder();
requestNextChunk();
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, PlayerEquipmentPacket* packet)
{
if (!level)
return;
Entity* entity = level->getEntity(packet->entityId);
if (!entity || !entity->isPlayer())
return;
Player* player = (Player*)entity;
// make sure it's not our local player
if (player->owner == rakPeer->GetMyGUID())
{
printf("Attempted to modify local player's inventory\n");
return;
}
// override the player's inventory
//int slot = player->inventory->getSlot(packet->itemId, packet->itemAuxValue);
//if (slot >= 0) {
// player->inventory->moveToSelectedSlot(slot, true);
//item->id = packet->itemId;
//item->setAuxValue(packet->itemAuxValue);
//item->count = 63;
int slot = Inventory::MAX_SELECTION_SIZE;
if (slot >= 0) {
if (packet->itemId == 0) {
player->inventory->clearSlot(slot);
} else {
ItemInstance newItem(packet->itemId, 63, packet->itemAuxValue);
player->inventory->replaceSlot(slot, &newItem);
}
player->inventory->moveToSelectedSlot(slot, true);
} else {
LOGW("Warning: Remote player doesn't have his thing, Odd!\n");
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, PlayerArmorEquipmentPacket* packet) {
if (!level)
return;
Entity* entity = level->getEntity(packet->entityId);
if (!entity || !entity->isPlayer())
return;
Player* player = (Player*)entity;
// make sure it's not our local player, since that should be UpdateArmorPacket
if (player->owner == rakPeer->GetMyGUID()) {
printf("Attempted to modify local player's armor visually\n");
return;
}
packet->fillIn(player);
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, InteractPacket* packet)
{
if (!level)
return;
Entity* src = level->getEntity(packet->sourceId);
Entity* entity = level->getEntity(packet->targetId);
if (src && entity && src->isPlayer())
{
Player* player = (Player*) src;
if (InteractPacket::Attack == packet->action)
minecraft->gameMode->attack(player, entity);
if (InteractPacket::Interact == packet->action)
minecraft->gameMode->interact(player, entity);
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SetEntityDataPacket* packet)
{
if (!level)
return;
LOGI("SetEntityDataPacket\n");
Entity* e = level->getEntity(packet->id);
if (e) {
SynchedEntityData* data = e->getEntityData();
if (data)
data->assignValues(&packet->getUnpackedData());
}
}
void ClientSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SetEntityMotionPacket* packet )
{
if (!level)
return;
if (Entity* e = level->getEntity(packet->id)) {
/*
e->xd = packet->xd;
e->yd = packet->yd;
e->zd = packet->zd;
*/
e->lerpMotion(packet->xd, packet->yd, packet->zd);
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AnimatePacket* packet)
{
if (!level)
return;
// Own player - Then don't play... :
if (minecraft->player->entityId == packet->entityId) {
if (packet->action == AnimatePacket::Swing) return;
}
Entity* entity = level->getEntity(packet->entityId);
if (!entity || !entity->isPlayer())
return;
Player* player = (Player*) entity;
switch (packet->action) {
case AnimatePacket::Swing:
player->swing();
break;
case AnimatePacket::WAKE_UP:
player->stopSleepInBed(false, false, false);
break;
default:
LOGW("Unknown Animate action: %d\n", packet->action);
break;
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemPacket* packet)
{
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SetHealthPacket* packet)
{
if (!level || !minecraft->player)
return;
minecraft->player->hurtTo(packet->health);
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SetSpawnPositionPacket* packet) {
if (!level || !minecraft || !minecraft->player) return;
if (!level->inRange(packet->x, packet->y, packet->z)) return;
minecraft->player->setRespawnPosition(Pos(packet->x, packet->y, packet->z));
level->getLevelData()->setSpawn(packet->x, packet->y, packet->z);
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, HurtArmorPacket* packet) {
if (!level || !minecraft->player) {
return;
}
minecraft->player->hurtArmor(packet->dmg);
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RespawnPacket* packet)
{
if (level) {
//LOGI("RespawnPacket! %d\n", findPlayer(level, packet->entityId, NULL));
NetEventCallback::handle(level, source, packet );
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ContainerOpenPacket* packet)
{
if (!level || !minecraft || !minecraft->player)
return;
if (packet->type == ContainerType::FURNACE) {
FurnaceTileEntity* te = new FurnaceTileEntity();
te->clientSideOnly = true;
minecraft->player->openFurnace(te);
if (minecraft->player->containerMenu)
minecraft->player->containerMenu->containerId = packet->containerId;
}
if (packet->type == ContainerType::CONTAINER) {
ChestTileEntity* te = new ChestTileEntity();
te->clientSideOnly = true;
minecraft->player->openContainer(te);
if (minecraft->player->containerMenu)
minecraft->player->containerMenu->containerId = packet->containerId;
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ContainerClosePacket* packet)
{
if (minecraft && minecraft->player && minecraft->player->containerMenu)
minecraft->player->closeContainer();
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ContainerSetContentPacket* packet)
{
if (!minecraft || !minecraft->player)
return;
if (packet->containerId == 0) {
for (unsigned int i = 0; i < packet->items.size(); ++i) {
minecraft->player->inventory->setItem(Inventory::MAX_SELECTION_SIZE + i, &packet->items[i]);
}
} else if (minecraft->player->containerMenu && minecraft->player->containerMenu->containerId == packet->containerId) {
for (unsigned int i = 0; i < packet->items.size(); ++i) {
minecraft->player->containerMenu->setSlot(i, &packet->items[i]);
}
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ContainerSetSlotPacket* packet)
{
//LOGI("ContainerSetSlot\n");
if (!minecraft->player
|| !minecraft->player->containerMenu
|| minecraft->player->containerMenu->containerId != packet->containerId)
return;
//minecraft->player->containerMenu->setSlot(packet->slot, packet->item.isNull()? NULL : &packet->item);
minecraft->player->containerMenu->setSlot(packet->slot, &packet->item);
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ContainerSetDataPacket* packet)
{
//LOGI("ContainerSetData\n");
if (minecraft->player && minecraft->player->containerMenu && minecraft->player->containerMenu->containerId == packet->containerId) {
//LOGI("client: SetData2 %d, %d\n", packet->id, packet->value);
minecraft->player->containerMenu->setData(packet->id, packet->value);
}
}
void ClientSideNetworkHandler::handle( const RakNet::RakNetGUID& source, ChatPacket* packet )
{
#ifndef STANDALONE_SERVER
minecraft->gui.displayClientMessage(packet->message);
#endif
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SignUpdatePacket* packet)
{
if (!level)
return;
TileEntity* te = level->getTileEntity(packet->x, packet->y, packet->z);
if (TileEntity::isType(te, TileEntityType::Sign)) {
SignTileEntity* ste = (SignTileEntity*) te;
if (ste->isEditable()) {
for (int i = 0; i < SignTileEntity::NUM_LINES; i++) {
ste->messages[i] = packet->lines[i];
}
//ste->setChanged();
}
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AdventureSettingsPacket* packet) {
if (!level)
return;
//assert(level != NULL && "level is NULL @ handle(AdventureSettingsPacket*)");
packet->fillIn(level->adventureSettings);
}
void ClientSideNetworkHandler::clearChunksLoaded()
{
// Init the chunk positions
for (int i = 0; i < NumRequestChunks; ++i) {
requestNextChunkIndexList[i].x = i/CHUNK_WIDTH;
requestNextChunkIndexList[i].y = i%CHUNK_WIDTH;
chunksLoaded[i] = false;
}
}

View File

@@ -0,0 +1,107 @@
#ifndef _MINECRAFT_NETWORK_CLIENTSIDENETWORKHANDLER_H_
#define _MINECRAFT_NETWORK_CLIENTSIDENETWORKHANDLER_H_
#include "NetEventCallback.h"
#include "../raknet/RakNetTypes.h"
#include "../world/level/LevelConstants.h"
#include <vector>
class Minecraft;
class Level;
class IRakNetInstance;
struct SBufferedBlockUpdate
{
int x, z;
unsigned char y;
unsigned char blockId;
unsigned char blockData;
bool setData;
};
typedef std::vector<SBufferedBlockUpdate> BlockUpdateList;
typedef struct IntPair {
int x, y;
} IntPair;
class ClientSideNetworkHandler : public NetEventCallback
{
public:
ClientSideNetworkHandler(Minecraft* minecraft, IRakNetInstance* raknetInstance);
virtual ~ClientSideNetworkHandler();
virtual void levelGenerated(Level* level);
virtual void onConnect(const RakNet::RakNetGUID& hostGuid);
virtual void onUnableToConnect();
virtual void onDisconnect(const RakNet::RakNetGUID& guid);
virtual void handle(const RakNet::RakNetGUID& source, LoginStatusPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, StartGamePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, MessagePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, SetTimePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, AddItemEntityPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, AddPaintingPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, TakeItemEntityPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, AddEntityPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, AddMobPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, AddPlayerPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, RemoveEntityPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, RemovePlayerPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, MovePlayerPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, MoveEntityPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, UpdateBlockPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, ExplodePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, LevelEventPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, TileEventPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, EntityEventPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, ChunkDataPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, PlayerEquipmentPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, PlayerArmorEquipmentPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, InteractPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, SetEntityDataPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, SetEntityMotionPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, SetHealthPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, SetSpawnPositionPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, AnimatePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, UseItemPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, HurtArmorPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, RespawnPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, ContainerOpenPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, ContainerClosePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, ContainerSetContentPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, ContainerSetSlotPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, ContainerSetDataPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, ChatPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, AdventureSettingsPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, SignUpdatePacket* packet);
private:
void requestNextChunk();
void arrangeRequestChunkOrder();
bool isChunkLoaded(int x, int z);
bool areAllChunksLoaded();
void clearChunksLoaded();
private:
Minecraft* minecraft;
Level* level;
IRakNetInstance* raknetInstance;
RakNet::RakPeerInterface* rakPeer;
RakNet::RakNetGUID serverGuid;
BlockUpdateList bufferedBlockUpdates;
int requestNextChunkPosition;
static const int NumRequestChunks = CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH;
int requestNextChunkIndex;
IntPair requestNextChunkIndexList[NumRequestChunks];
bool chunksLoaded[NumRequestChunks];
};
#endif

33
src/network/NATPunchHandler.cpp Executable file
View File

@@ -0,0 +1,33 @@
#include "NATPunchHandler.h"
#include "../raknet/TCPInterface.h"
#include "../raknet/HTTPConnection.h"
#include "PHPDirectoryServer2.h"
using namespace RakNet;
NATPuchHandler::NATPuchHandler() {
tcpInterface = new TCPInterface;
}
NATPuchHandler::~NATPuchHandler() {
delete tcpInterface;
}
void NATPuchHandler::initialize() {
tcpInterface->Start(0, 64);
}
void NATPuchHandler::registerToGameList(const RakNet::RakString& serverName, int port) {
HTTPConnection httpConnection;
httpConnection.Init(tcpInterface, "johanbernhardsson.se");
PHPDirectoryServer2 directoryServer;
directoryServer.Init(&httpConnection, "/DirectoryServer.php");
directoryServer.UploadTable("", serverName, port, true);
}
void NATPuchHandler::removeFromGameList() {
}
void NATPuchHandler::close() {
}

24
src/network/NATPunchHandler.h Executable file
View File

@@ -0,0 +1,24 @@
#ifndef _MINECRAFT_NETWORK_NATPUNCHHANDLER_H_
#define _MINECRAFT_NETWORK_NATPUNCHHANDLER_H_
#include "../raknet/TCPInterface.h"
#include "../raknet/RakString.h"
class NATPuchHandler {
public:
enum NATPuchHandlerStatus {
NATPuchInitilized = 0,
NATPuchFetchingServerList = 1,
NATPuchConnecting = 2,
NATPuchConnected = 3,
NATPuchDissconnected = 4
};
NATPuchHandler();
~NATPuchHandler();
void initialize();
void registerToGameList(const RakNet::RakString& serverName, int port);
void removeFromGameList();
void close();
private:
RakNet::TCPInterface *tcpInterface;
};
#endif /* _MINECRAFT_NETWORK_NATPUNCHHANDLER_H_ */

View File

@@ -0,0 +1,59 @@
#include "NetEventCallback.h"
#include "../world/level/Level.h"
#include "packet/RespawnPacket.h"
//
// Common packet handling implementation for Client and Server
//
/*
void NetEventCallback::handle( const RakNet::RakNetGUID& source, AnimatePacket* packet )
{
Entity* entity = level->getEntity(packet->entityId);
if (entity && entity->isPlayer()) {
Player* player = (Player*) entity;
switch (packet->action) {
case AnimatePacket::Swing:
player->swing();
break;
default:
LOGW("Unknown Animate action: %d\n", packet->action);
break;
}
}
}
*/
Player* NetEventCallback::findPlayer(Level* level, int entityId) {
Entity* e = level->getEntity(entityId);
if (e) {
if (e->isPlayer()) return (Player*) e;
LOGE("Entity: %p is supposed to be a player but is not (type %d)!\n", e, e->getEntityTypeId());
}
return NULL;
}
Player* NetEventCallback::findPlayer(Level* level, const RakNet::RakNetGUID* source) {
for (unsigned int i = 0; i < level->players.size(); ++i)
if (level->players[i]->owner == *source) return level->players[i];
return NULL;
}
Player* NetEventCallback::findPlayer( Level* level, int entityId, const RakNet::RakNetGUID* source )
{
if (entityId != -1)
if (Player* p = findPlayer(level, entityId)) return p;
if (source != NULL)
if (Player* p = findPlayer(level, source)) return p;
return NULL;
}
void NetEventCallback::handle( Level* level, const RakNet::RakNetGUID& source, RespawnPacket* packet )
{
if (Player* p = findPlayer(level, packet->entityId, NULL)) {
p->moveTo(packet->x, packet->y, packet->z, p->yRot, p->xRot);
p->reset();
p->resetPos(true);
}
}

134
src/network/NetEventCallback.h Executable file
View File

@@ -0,0 +1,134 @@
#ifndef _MINECRAFT_NETWORK_NETEVENTCALLBACK_H_
#define _MINECRAFT_NETWORK_NETEVENTCALLBACK_H_
class AddItemEntityPacket;
class AddPaintingPacket;
class AdventureSettingsPacket;
class TakeItemEntityPacket;
class LoginPacket;
class ReadyPacket;
class LoginStatusPacket;
class MessagePacket;
class SetTimePacket;
class StartGamePacket;
class AddEntityPacket;
class AddMobPacket;
class AddPlayerPacket;
class RemovePlayerPacket;
class RemoveEntityPacket;
class MoveEntityPacket;
//class TeleportEntityPacket;
class MovePlayerPacket;
class PlaceBlockPacket;
class RemoveBlockPacket;
class UpdateBlockPacket;
class ExplodePacket;
class LevelEventPacket;
class TileEventPacket;
class EntityEventPacket;
class RequestChunkPacket;
class ChunkDataPacket;
class PlayerEquipmentPacket;
class PlayerArmorEquipmentPacket;
class InteractPacket;
class SetEntityDataPacket;
class SetEntityMotionPacket;
class SetHealthPacket;
class SetSpawnPositionPacket;
class SendInventoryPacket;
class DropItemPacket;
class AnimatePacket;
class UseItemPacket;
class PlayerActionPacket;
class HurtArmorPacket;
class RespawnPacket;
class ContainerAckPacket;
class ContainerOpenPacket;
class ContainerClosePacket;
class ContainerSetSlotPacket;
class ContainerSetDataPacket;
class ContainerSetContentPacket;
class ChatPacket;
class SignUpdatePacket;
class Minecraft;
class Level;
#include "../world/level/tile/Tile.h"
namespace RakNet
{
struct RakNetGUID;
}
class NetEventCallback
{
public:
virtual void levelGenerated(Level* level) {}
virtual ~NetEventCallback() {}
virtual void onConnect(const RakNet::RakNetGUID& hostGuid) {};
virtual void onUnableToConnect() {};
virtual void onNewClient(const RakNet::RakNetGUID& clientGuid) {};
virtual void onDisconnect(const RakNet::RakNetGUID& guid) {};
virtual void handle(const RakNet::RakNetGUID& source, LoginPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, ReadyPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, LoginStatusPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, SetTimePacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, MessagePacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, StartGamePacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, AddItemEntityPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, AddPaintingPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, TakeItemEntityPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, AddEntityPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, AddMobPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, AddPlayerPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, RemovePlayerPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, RemoveEntityPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, MoveEntityPacket* packet) {}
//virtual void handle(const RakNet::RakNetGUID& source, TeleportEntityPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, MovePlayerPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, PlaceBlockPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, RemoveBlockPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, UpdateBlockPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, ExplodePacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, LevelEventPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, TileEventPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, EntityEventPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, RequestChunkPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, ChunkDataPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, PlayerEquipmentPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, PlayerArmorEquipmentPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, SetEntityDataPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, SetEntityMotionPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, SetHealthPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, SetSpawnPositionPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, InteractPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, UseItemPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, PlayerActionPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, HurtArmorPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, SendInventoryPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, DropItemPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, ContainerOpenPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, ContainerClosePacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, ContainerAckPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, ContainerSetDataPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, ContainerSetSlotPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, ContainerSetContentPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, ChatPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, SignUpdatePacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, AdventureSettingsPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, AnimatePacket* packet) {}
//
// Common implementation for Client and Server
//
virtual void handle(const RakNet::RakNetGUID& source, RespawnPacket* packet) {}
virtual void handle(Level* level, const RakNet::RakNetGUID& source, RespawnPacket* packet);
Player* findPlayer(Level* level, int entityId);
Player* findPlayer(Level* level, const RakNet::RakNetGUID* source);
Player* findPlayer(Level* level, int entityId, const RakNet::RakNetGUID* source);
};
#endif

View File

@@ -0,0 +1,293 @@
/// \file
/// \brief Contains WebGameList, a client for communicating with a HTTP list of game servers
///
/// This file is part of RakNet Copyright 2008 Kevin Jenkins.
///
/// Usage of RakNet is subject to the appropriate license agreement.
/// Creative Commons Licensees are subject to the
/// license found at
/// http://creativecommons.org/licenses/by-nc/2.5/
/// Single application licensees are subject to the license found at
/// http://www.jenkinssoftware.com/SingleApplicationLicense.html
/// Custom license users are subject to the terms therein.
/// GPL license users are subject to the GNU General Public
/// License as published by the Free
/// Software Foundation
#include "PHPDirectoryServer2.h"
#include "../raknet/HTTPConnection.h"
#include "../raknet/RakSleep.h"
#include "../raknet/RakString.h"
#include "../raknet/RakNetTypes.h"
#include "../raknet/GetTime.h"
#include "../raknet/RakAssert.h"
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include "../raknet/Itoa.h"
// Column with this header contains the name of the game, passed to UploadTable()
static const char *GAME_NAME_COMMAND="__GAME_NAME";
// Column with this header contains the port of the game, passed to UploadTable()
static const char *GAME_PORT_COMMAND="__GAME_PORT";
// Column with this header contains the IP address of the game, passed to UploadTable()
static const char *SYSTEM_ADDRESS_COMMAND="_System_Address";
// Returned from the PHP server indicating when this row was last updated.
static const char *LAST_UPDATE_COMMAND="__SEC_AFTER_EPOCH_SINCE_LAST_UPDATE";
using namespace RakNet;
using namespace DataStructures;
PHPDirectoryServer2::PHPDirectoryServer2()
: nextRepost(0)
{
Map<RakString, RakString>::IMPLEMENT_DEFAULT_COMPARISON();
}
PHPDirectoryServer2::~PHPDirectoryServer2()
{
}
void PHPDirectoryServer2::Init(HTTPConnection *_http, const char *_path)
{
http=_http;
pathToPHP=_path;
}
void PHPDirectoryServer2::SetField( RakNet::RakString columnName, RakNet::RakString value )
{
if (columnName.IsEmpty())
return;
if (columnName==GAME_NAME_COMMAND ||
columnName==GAME_PORT_COMMAND ||
columnName==LAST_UPDATE_COMMAND)
{
RakAssert("PHPDirectoryServer2::SetField attempted to set reserved column name" && 0);
return;
}
fields.Set(columnName, value);
}
unsigned int PHPDirectoryServer2::GetFieldCount(void) const
{
return fields.Size();
}
void PHPDirectoryServer2::GetField(unsigned int index, RakNet::RakString &columnName, RakNet::RakString &value)
{
RakAssert(index < fields.Size());
columnName=fields.GetKeyAtIndex(index);
value=fields[index];
}
void PHPDirectoryServer2::SetFields(DataStructures::Table *table)
{
ClearFields();
unsigned columnIndex, rowIndex;
DataStructures::Table::Row *row;
for (rowIndex=0; rowIndex < table->GetRowCount(); rowIndex++)
{
row = table->GetRowByIndex(rowIndex, 0);
for (columnIndex=0; columnIndex < table->GetColumnCount(); columnIndex++)
{
SetField( table->ColumnName(columnIndex), row->cells[columnIndex]->ToString(table->GetColumnType(columnIndex)) );
}
}
}
void PHPDirectoryServer2::ClearFields(void)
{
fields.Clear();
nextRepost=0;
}
void PHPDirectoryServer2::UploadTable(RakNet::RakString uploadPassword, RakNet::RakString gameName, unsigned short gamePort, bool autoRepost)
{
gameNameParam=gameName;
gamePortParam=gamePort;
currentOperation="";
currentOperation="?query=upload&uploadPassword=";
currentOperation+=uploadPassword;
SendOperation();
if (autoRepost)
nextRepost=RakNet::GetTimeMS()+50000;
else
nextRepost=0;
}
void PHPDirectoryServer2::DownloadTable(RakNet::RakString downloadPassword)
{
currentOperation="?query=download&downloadPassword=";
currentOperation+=downloadPassword;
SendOperation();
}
void PHPDirectoryServer2::UploadAndDownloadTable(RakNet::RakString uploadPassword, RakNet::RakString downloadPassword, RakNet::RakString gameName, unsigned short gamePort, bool autoRepost)
{
gameNameParam=gameName;
gamePortParam=gamePort;
currentOperation="?query=upDown&downloadPassword=";
currentOperation+=downloadPassword;
currentOperation+="&uploadPassword=";
currentOperation+=uploadPassword;
SendOperation();
if (autoRepost)
nextRepost=RakNet::GetTimeMS()+50000;
else
nextRepost=0;
}
HTTPReadResult PHPDirectoryServer2::ProcessHTTPRead(RakNet::RakString httpRead)
{
const char *c = (const char*) httpRead.C_String(); // current position
HTTPReadResult resultCode=HTTP_RESULT_EMPTY;
lastDownloadedTable.Clear();
if (*c=='\n')
c++;
char buff[256];
int buffIndex;
bool isCommand=true;
DataStructures::List<RakNet::RakString> columns;
DataStructures::List<RakNet::RakString> values;
RakNet::RakString curString;
bool isComment=false;
buffIndex=0;
while(c && *c)
{
// 3 is comment
if (*c=='\003')
{
isComment=!isComment;
c++;
continue;
}
if (isComment)
{
c++;
continue;
}
// 1 or 2 separates fields
// 4 separates rows
if (*c=='\001')
{
if (isCommand)
{
buff[buffIndex]=0;
columns.Push(RakString::NonVariadic(buff), _FILE_AND_LINE_);
isCommand=false;
if (buff[0]!=0)
resultCode=HTTP_RESULT_GOT_TABLE;
}
else
{
buff[buffIndex]=0;
values.Push(RakString::NonVariadic(buff), _FILE_AND_LINE_);
isCommand=true;
}
buffIndex=0;
}
else if (*c=='\002')
{
buff[buffIndex]=0;
buffIndex=0;
values.Push(RakString::NonVariadic(buff), _FILE_AND_LINE_);
isCommand=true;
PushColumnsAndValues(columns, values);
columns.Clear(true, _FILE_AND_LINE_);
values.Clear(true, _FILE_AND_LINE_);
}
else
{
if (buffIndex<256-1)
buff[buffIndex++]=*c;
}
c++;
}
if (buff[0] && columns.Size()==values.Size()+1)
{
buff[buffIndex]=0;
values.Push(RakString::NonVariadic(buff), _FILE_AND_LINE_);
}
PushColumnsAndValues(columns, values);
return resultCode;
}
void PHPDirectoryServer2::PushColumnsAndValues(DataStructures::List<RakNet::RakString> &columns, DataStructures::List<RakNet::RakString> &values)
{
DataStructures::Table::Row *row=0;
unsigned int i;
for (i=0; i < columns.Size() && i < values.Size(); i++)
{
if (columns[i].IsEmpty()==false)
{
unsigned col = lastDownloadedTable.ColumnIndex(columns[i]);
if(col == (unsigned)-1)
{
col = lastDownloadedTable.AddColumn(columns[i], DataStructures::Table::STRING);
}
if (row==0)
{
row = lastDownloadedTable.AddRow(lastDownloadedTable.GetAvailableRowId());
}
row->UpdateCell(col,values[i].C_String());
}
}
}
const DataStructures::Table *PHPDirectoryServer2::GetLastDownloadedTable(void) const
{
return &lastDownloadedTable;
}
void PHPDirectoryServer2::SendOperation(void)
{
RakString outgoingMessageBody;
char buff[64];
outgoingMessageBody += GAME_PORT_COMMAND;
outgoingMessageBody += '\001';
outgoingMessageBody += Itoa(gamePortParam,buff,10);
outgoingMessageBody += '\001';
outgoingMessageBody += GAME_NAME_COMMAND;
outgoingMessageBody += '\001';
outgoingMessageBody += gameNameParam;
for (unsigned i = 0; i < fields.Size(); i++)
{
RakString value = fields[i];
value.URLEncode();
outgoingMessageBody += RakString("\001%s\001%s",
fields.GetKeyAtIndex(i).C_String(),
value.C_String());
}
RakString postURL;
postURL+=pathToPHP;
postURL+=currentOperation;
http->Post(postURL.C_String(), outgoingMessageBody, "application/x-www-form-urlencoded");
}
void PHPDirectoryServer2::Update(void)
{
if (http->IsBusy())
return;
if (nextRepost==0 || fields.Size()==0)
return;
RakNet::TimeMS time = GetTimeMS();
// Entry deletes itself after 60 seconds, so keep reposting if set to do so
if (time > nextRepost)
{
nextRepost=RakNet::GetTimeMS()+50000;
SendOperation();
}
}

137
src/network/PHPDirectoryServer2.h Executable file
View File

@@ -0,0 +1,137 @@
/// \file
/// \brief Contains PHPDirectoryServer2, a client for communicating with a HTTP list of game servers
///
/// This file is part of RakNet Copyright 2008 Kevin Jenkins.
///
/// Usage of RakNet is subject to the appropriate license agreement.
/// Creative Commons Licensees are subject to the
/// license found at
/// http://creativecommons.org/licenses/by-nc/2.5/
/// Single application licensees are subject to the license found at
/// http://www.jenkinssoftware.com/SingleApplicationLicense.html
/// Custom license users are subject to the terms therein.
/// GPL license users are subject to the GNU General Public
/// License as published by the Free
/// Software Foundation; either version 2 of the License, or (at your
/// option) any later version.
#ifndef __PHP_DIRECTORY_SERVER_2
#define __PHP_DIRECTORY_SERVER_2
#include "../raknet/RakString.h"
#include "../raknet/HTTPConnection.h"
#include "../raknet/RakNetTypes.h"
#include "../raknet/DS_Queue.h"
#include "../raknet/DS_Table.h"
#include "../raknet/DS_Map.h"
namespace RakNet {
struct SystemAddress;
enum HTTPReadResult
{
HTTP_RESULT_GOT_TABLE,
HTTP_RESULT_EMPTY
};
/// \brief Use PHPDirectoryServer2 as a C++ client to DirectoryServer.php
///
/// PHPDirectoryServer2 works with the HTTPConnection class (which works with the TCPInterface class) in order to communiate with DirectoryServer.php found under Samples/PHPDirectoryServer2
class PHPDirectoryServer2
{
public:
PHPDirectoryServer2();
virtual ~PHPDirectoryServer2();
/// Associate PHPDirectoryServer2 with the HTTPConnection class it will communicate through
/// \param[in] _http The instance of HTTP connection we will communicate through
/// \param[in] _path The path to the PHP file on the remote server. For example, if the path is mysite.com/raknet/DirectoryServer.php then you would enter raknet/DirectoryServer.php
void Init(HTTPConnection *_http, const char *_path);
/// Set a parameter (these are passed to the server)
/// To delete a column, just pass an empty string for value
/// Store the game name and port with UploadTable, rather than SetField, as these columns are required and use reserved column names
/// \param[in] columnName The name of the column to store
/// \param[in] value What value to hold for the uploaded row (only one row can be uploaded at a time)
void SetField(RakNet::RakString columnName, RakNet::RakString value);
/// Returns the number of fields set with SetField()
unsigned int GetFieldCount(void) const;
/// Returns a field set with SetField()
/// \param[in] index The 0 based index into the field list
/// \param[out] columnName The \a columnName parameter passed to SetField()
/// \param[out] value The \a value parameter passed to SetField()
void GetField(unsigned int index, RakNet::RakString &columnName, RakNet::RakString &value);
/// Set all parameters at once from a table
/// \param[in] table A table containing the values you want to send. Note that all values are stored as strings in PHP
void SetFields(DataStructures::Table *table);
/// Clear all fields
void ClearFields(void);
/// Upload the values set with SetFields() or SetField()
/// On success:
/// 1. HTTPConnection::HasRead() will return true.
/// 2. Pass the value returned by HTTPConnection::Read() to PHPDirectoryServer2::ProcessHTTPRead().
/// 3. The return value of PHPDirectoryServer2::ProcessHTTPRead() will be HTTP_RESULT_EMPTY
/// \param[in] uploadPassword The upload password set in the PHP page itself when you first uploaded and viewed it in the webpage.
/// \param[in] gameName Every entry must have a game name. Pass it here.
/// \param[in] gamePort Every entry must have a game port. Pass it here. The IP address will be stored automatically, or you can manually set it by passing a field named _System_Address
/// \param[in] autoRepost Tables must be uploaded every 60 seconds or they get dropped. Set autoRepost to true to automatically reupload the most recent table.
void UploadTable(RakNet::RakString uploadPassword, RakNet::RakString gameName, unsigned short gamePort, bool autoRepost);
/// Send a download request to the PHP server.
/// On success:
/// 1. HTTPConnection::HasRead() will return true.
/// 2. Pass the value returned by HTTPConnection::Read() to PHPDirectoryServer2::ProcessHTTPRead().
/// 3. The return value of PHPDirectoryServer2::ProcessHTTPRead() will be HTTP_RESULT_GOT_TABLE or HTTP_RESULT_EMPTY
/// 4. On HTTP_RESULT_GOT_TABLE, use GetLastDownloadedTable() to read the results.
/// \param[in] downloadPassword The download password set in the PHP page itself when you first uploaded and viewed it in the webpage.
void DownloadTable(RakNet::RakString downloadPassword);
/// Same as calling DownloadTable immediately followed by UploadTable, except only the download result is returned
/// \param[in] uploadPassword The upload password set in the PHP page itself when you first uploaded and viewed it in the webpage.
/// \param[in] downloadPassword The download password set in the PHP page itself when you first uploaded and viewed it in the webpage.
/// \param[in] gameName Every entry must have a game name. Pass it here.
/// \param[in] gamePort Every entry must have a game port. Pass it here. The IP address will be stored automatically, or you can manually set it by passing a field named _System_Address
/// \param[in] autoRepost Tables must be uploaded every 60 seconds or they get dropped. Set autoRepost to true to automatically reupload the most recent table.
void UploadAndDownloadTable(RakNet::RakString uploadPassword, RakNet::RakString downloadPassword, RakNet::RakString gameName, unsigned short gamePort, bool autoRepost);
/// When HTTPConnection::ProcessDataPacket() returns true, and not an error, pass HTTPConnection::Read() to this function
/// The message will be parsed into DataStructures::Table, and a copy stored internally which can be retrieved by GetLastDownloadedTable();
/// \param[in] packetData Returned from HTTPInterface::Read()
/// \return One of the values for HTTPReadResult
HTTPReadResult ProcessHTTPRead(RakNet::RakString httpRead);
/// Returns the last value returned from ProcessHTTPString
/// Default columns are "__GAME_NAME", "__GAME_PORT", "_System_Address"
/// \return The table created by parsing httpString
const DataStructures::Table *GetLastDownloadedTable(void) const;
/// Call this periodically - it will handle connection states and refreshing updates to the server
void Update(void);
private:
HTTPConnection *http;
RakNet::RakString pathToPHP;
RakNet::RakString gameNameParam;
unsigned short gamePortParam;
void SendOperation(void);
void PushColumnsAndValues(DataStructures::List<RakNet::RakString> &columns, DataStructures::List<RakNet::RakString> &values);
DataStructures::Table lastDownloadedTable;
DataStructures::Map<RakNet::RakString, RakNet::RakString> fields;
RakNet::RakString currentOperation;
RakNet::TimeMS nextRepost;
};
} // namespace RakNet
#endif

212
src/network/Packet.cpp Executable file
View File

@@ -0,0 +1,212 @@
#include "Packet.h"
#include "../world/level/chunk/LevelChunk.h"
#include "packet/PacketInclude.h"
Packet::Packet()
: priority(HIGH_PRIORITY),
reliability(RELIABLE)
{}
Packet* MinecraftPackets::createPacket(int id)
{
Packet* packet = NULL;
switch (id - ID_USER_PACKET_ENUM) {
default:
break;
case PACKET_LOGIN:
packet = new LoginPacket();
break;
case PACKET_LOGINSTATUS:
packet = new LoginStatusPacket();
break;
case PACKET_READY:
packet = new ReadyPacket();
break;
case PACKET_SETTIME:
packet = new SetTimePacket();
break;
case PACKET_MESSAGE:
packet = new MessagePacket();
break;
case PACKET_STARTGAME:
packet = new StartGamePacket();
break;
case PACKET_ADDENTITY:
packet = new AddEntityPacket();
break;
case PACKET_ADDITEMENTITY:
packet = new AddItemEntityPacket();
break;
case PACKET_TAKEITEMENTITY:
packet = new TakeItemEntityPacket();
break;
case PACKET_ADDMOB:
packet = new AddMobPacket();
break;
case PACKET_ADDPLAYER:
packet = new AddPlayerPacket();
break;
case PACKET_REMOVEPLAYER:
packet = new RemovePlayerPacket();
break;
case PACKET_MOVEENTITY:
packet = new MoveEntityPacket();
break;
case PACKET_MOVEENTITY_POSROT:
packet = new MoveEntityPacket_PosRot();
break;
//case PACKET_TELEPORTENTITY:
// packet = new TeleportEntityPacket();
// break;
case PACKET_MOVEPLAYER:
packet = new MovePlayerPacket();
break;
case PACKET_RESPAWN:
packet = new RespawnPacket();
break;
case PACKET_REMOVEENTITY:
packet = new RemoveEntityPacket();
break;
case PACKET_PLACEBLOCK:
packet = new PlaceBlockPacket();
break;
case PACKET_REMOVEBLOCK:
packet = new RemoveBlockPacket();
break;
case PACKET_UPDATEBLOCK:
packet = new UpdateBlockPacket();
break;
case PACKET_EXPLODE:
packet = new ExplodePacket();
break;
case PACKET_LEVELEVENT:
packet = new LevelEventPacket();
break;
case PACKET_TILEEVENT:
packet = new TileEventPacket();
break;
case PACKET_ENTITYEVENT:
packet = new EntityEventPacket();
break;
case PACKET_REQUESTCHUNK:
packet = new RequestChunkPacket();
break;
case PACKET_CHUNKDATA:
packet = new ChunkDataPacket();
break;
case PACKET_PLAYEREQUIPMENT:
packet = new PlayerEquipmentPacket();
break;
case PACKET_PLAYERARMOREQUIPMENT:
packet = new PlayerArmorEquipmentPacket();
break;
case PACKET_INTERACT:
packet = new InteractPacket();
break;
case PACKET_USEITEM:
packet = new UseItemPacket();
break;
case PACKET_PLAYERACTION:
packet = new PlayerActionPacket();
break;
case PACKET_HURTARMOR:
packet = new HurtArmorPacket();
break;
case PACKET_SETENTITYDATA:
packet = new SetEntityDataPacket();
break;
case PACKET_SETENTITYMOTION:
packet = new SetEntityMotionPacket();
break;
case PACKET_SETHEALTH:
packet = new SetHealthPacket();
break;
case PACKET_SETSPAWNPOSITION:
packet = new SetSpawnPositionPacket();
break;
case PACKET_ANIMATE:
packet = new AnimatePacket();
break;
case PACKET_SENDINVENTORY:
packet = new SendInventoryPacket();
break;
case PACKET_DROPITEM:
packet = new DropItemPacket();
break;
case PACKET_CONTAINERACK:
packet = new ContainerAckPacket();
break;
case PACKET_CONTAINEROPEN:
packet = new ContainerOpenPacket();
break;
case PACKET_CONTAINERCLOSE:
packet = new ContainerClosePacket();
break;
case PACKET_CONTAINERSETDATA:
packet = new ContainerSetDataPacket();
break;
case PACKET_CONTAINERSETSLOT:
packet = new ContainerSetSlotPacket();
break;
case PACKET_CONTAINERSETCONTENT:
packet = new ContainerSetContentPacket();
break;
case PACKET_CHAT:
packet = new ChatPacket();
break;
case PACKET_SIGNUPDATE:
packet = new SignUpdatePacket();
break;
case PACKET_ADDPAINTING:
packet = new AddPaintingPacket();
break;
case PACKET_ADVENTURESETTINGS:
packet = new AdventureSettingsPacket();
break;
}
return packet;
}
namespace PacketUtil
{
signed char Rot_degreesToChar(float rot) {
return (signed char)(rot / 360.0f * 256.0f);
}
float Rot_charToDegrees(signed char rot) {
return ((float)rot) / 256.0f * 360.0f;
}
void Rot_entityToChar(const Entity* e, signed char& yRot, signed char& xRot) {
xRot = Rot_degreesToChar(e->xRot);
yRot = Rot_degreesToChar(e->yRot);
}
void Rot_charToEntity(Entity* e, signed char yRot, signed char xRot) {
e->xRot = e->xRotO = Rot_charToDegrees(xRot);
e->yRot = e->yRotO = Rot_charToDegrees(yRot);
}
void writeItemInstance(const ItemInstance& item, RakNet::BitStream* stream) {
short id = item.id;
unsigned char count = item.count;
short aux = item.getAuxValue();
stream->Write(id);
stream->Write(count);
stream->Write(aux);
}
ItemInstance readItemInstance(RakNet::BitStream* stream) {
short id, aux;
unsigned char count;
stream->Read(id);
stream->Read(count);
stream->Read(aux);
return ItemInstance(id, count, aux);
}
}

173
src/network/Packet.h Executable file
View File

@@ -0,0 +1,173 @@
#ifndef _MINECRAFT_NETWORK_PACKET_H_
#define _MINECRAFT_NETWORK_PACKET_H_
#include "NetEventCallback.h"
#include "../raknet/MessageIdentifiers.h"
#include "../raknet/RakNetTypes.h"
#include "../raknet/BitStream.h"
#include "../raknet/PacketPriority.h"
class LevelChunk;
enum MinecraftPacketIds
{
PACKET_KEEPALIVE = 0,
PACKET_LOGIN,
PACKET_LOGINSTATUS,
PACKET_READY,
PACKET_MESSAGE,
PACKET_SETTIME,
PACKET_STARTGAME,
PACKET_ADDMOB,
PACKET_ADDPLAYER,
PACKET_REMOVEPLAYER,
PACKET_TELEPORTENTITY,
PACKET_ADDENTITY,
PACKET_REMOVEENTITY,
PACKET_ADDITEMENTITY,
PACKET_TAKEITEMENTITY,
PACKET_MOVEENTITY,
PACKET_MOVEENTITY_POS,
PACKET_MOVEENTITY_ROT,
PACKET_MOVEENTITY_POSROT,
PACKET_MOVEPLAYER,
PACKET_PLACEBLOCK,
PACKET_REMOVEBLOCK,
PACKET_UPDATEBLOCK,
PACKET_ADDPAINTING,
PACKET_EXPLODE,
PACKET_LEVELEVENT,
PACKET_TILEEVENT,
PACKET_ENTITYEVENT,
PACKET_REQUESTCHUNK,
PACKET_CHUNKDATA,
PACKET_PLAYEREQUIPMENT,
PACKET_PLAYERARMOREQUIPMENT,
PACKET_INTERACT,
PACKET_USEITEM,
PACKET_PLAYERACTION,
PACKET_UPDATEARMOR,
PACKET_HURTARMOR,
PACKET_SETENTITYDATA,
PACKET_SETENTITYMOTION,
PACKET_SETHEALTH,
PACKET_SETSPAWNPOSITION,
PACKET_ANIMATE,
PACKET_RESPAWN,
PACKET_SENDINVENTORY,
PACKET_DROPITEM,
PACKET_CONTAINEROPEN,
PACKET_CONTAINERCLOSE,
PACKET_CONTAINERSETSLOT,
PACKET_CONTAINERSETDATA,
PACKET_CONTAINERSETCONTENT,
PACKET_CONTAINERACK,
PACKET_CHAT,
PACKET_SIGNUPDATE,
PACKET_ADVENTURESETTINGS,
/*
PACKET_PRELOGIN,
PACKET_CHAT,
PACKET_SETEQUIPPEDITEM,
PACKET_SETSPAWNPOSITION,
PACKET_PLAYERACTION,
PACKET_SETCARRIEDITEM,
PACKET_ENTITYACTIONATPOSITION,
PACKET_PLAYERCOMMAND,
PACKET_ADDENTITY,
PACKET_ADDMOB,
PACKET_ADDPAINTING,
PACKET_PLAYERINPUT,
PACKET_SETENTITYMOTION,
PACKET_REMOVEENTITY,
PACKET_MOVEENTITY,
PACKET_SETRIDING,
PACKET_ENTITYDATA,
PACKET_CHUNKVISIBILITY,
PACKET_BLOCKREGIONUPDATE,
PACKET_CHUNKBLOCKUPDATE,
PACKET_BLOCKUPDATE,
PACKET_BLOCKEVENT,
PACKET_GAMEEVENT,
PACKET_ADDGLOBALENTITY,
PACKET_CONTAINEROPEN,
PACKET_CONTAINERCLOSE,
PACKET_CONTAINERCLICK,
PACKET_CONTAINERSETSLOT,
PACKET_CONTAINERSETCONTENT,
PACKET_CONTAINERSETDATA,
PACKET_CONTAINERACK,
PACKET_SIGNUPDATE,
PACKET_AWARDSTAT,
PACKET_DISCONNECT,
*/
PACKET_END_ID
};
const int NUM_PACKETS = PACKET_END_ID;
class Packet
{
public:
Packet();
virtual ~Packet() {}
virtual void write(RakNet::BitStream* bitStream) = 0;
virtual void read(RakNet::BitStream* bitStream) = 0;
virtual void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) = 0;
PacketPriority priority;
PacketReliability reliability;
};
class MinecraftPackets
{
public:
static Packet* createPacket(int id);
};
namespace PacketUtil {
signed char Rot_degreesToChar(float rot);
float Rot_charToDegrees(signed char rot);
void Rot_entityToChar(const Entity* e, signed char& yRot, signed char& xRot);
void Rot_charToEntity(Entity* e, signed char yRot, signed char xRot);
void writeItemInstance(const ItemInstance& item, RakNet::BitStream* stream);
ItemInstance readItemInstance(RakNet::BitStream* stream);
}
#endif

740
src/network/RakNetInstance.cpp Executable file
View File

@@ -0,0 +1,740 @@
#include "RakNetInstance.h"
#include "Packet.h"
#include "NetEventCallback.h"
#include "../raknet/RakPeerInterface.h"
#include "../raknet/BitStream.h"
#include "../raknet/MessageIdentifiers.h"
#include "../raknet/GetTime.h"
#include "../AppConstants.h"
#include "../platform/log.h"
#define APP_IDENTIFIER "MCCPP;" APP_VERSION_STRING ";"
#define APP_IDENTIFIER_MINECON "MCCPP;MINECON;"
RakNetInstance::RakNetInstance()
: rakPeer(NULL),
_isServer(false),
_isLoggedIn(false)
{
rakPeer = RakNet::RakPeerInterface::GetInstance();
rakPeer->SetTimeoutTime(20000, RakNet::UNASSIGNED_SYSTEM_ADDRESS);
rakPeer->SetOccasionalPing(true);
}
RakNetInstance::~RakNetInstance()
{
if (rakPeer)
{
rakPeer->Shutdown(100, 0);
RakNet::RakPeerInterface::DestroyInstance(rakPeer);
rakPeer = NULL;
}
}
bool RakNetInstance::host(const std::string& localName, int port, int maxConnections /* = 4 */)
{
if (rakPeer->IsActive())
{
rakPeer->Shutdown(500);
}
RakNet::SocketDescriptor socket(port, 0);
socket.socketFamily = AF_INET;
rakPeer->SetMaximumIncomingConnections(maxConnections);
RakNet::StartupResult result = rakPeer->Startup(maxConnections, &socket, 1);
_isServer = true;
isPingingForServers = false;
return (result == RakNet::RAKNET_STARTED);
}
void RakNetInstance::announceServer(const std::string& localName)
{
if (_isServer && rakPeer->IsActive())
{
RakNet::RakString connectionData;
#if defined(MINECON)
connectionData += APP_IDENTIFIER_MINECON;
#else
connectionData += APP_IDENTIFIER;
#endif
connectionData += localName.c_str();
RakNet::BitStream bitStream;
bitStream.Write(connectionData);
rakPeer->SetOfflinePingResponse((const char*)bitStream.GetData(), bitStream.GetNumberOfBytesUsed());
}
}
bool RakNetInstance::connect(const char* host, int port)
{
_isLoggedIn = false;
RakNet::StartupResult result;
RakNet::SocketDescriptor socket(0, 0);
socket.socketFamily = AF_INET;
if (rakPeer->IsActive())
{
rakPeer->Shutdown(500);
}
result = rakPeer->Startup(4, &socket, 1);
_isServer = false;
isPingingForServers = false;
if (result == RakNet::RAKNET_STARTED)
{
RakNet::ConnectionAttemptResult connectResult = rakPeer->Connect(host, port, NULL, 0, NULL, 0, 12, 500, 0);
return (connectResult == RakNet::CONNECTION_ATTEMPT_STARTED);
}
return false;
}
void RakNetInstance::disconnect()
{
if (rakPeer->IsActive())
{
rakPeer->Shutdown(500);
}
_isLoggedIn = false;
_isServer = false;
isPingingForServers = false;
}
void RakNetInstance::pingForHosts(int basePort)
{
if (!rakPeer->IsActive())
{
RakNet::SocketDescriptor socket(0, 0);
rakPeer->Startup(4, &socket, 1);
}
isPingingForServers = true;
pingPort = basePort;
lastPingTime = RakNet::GetTimeMS();
for (int i = 0; i < 4; ++i)
rakPeer->Ping("255.255.255.255", basePort + i, true);
}
void RakNetInstance::stopPingForHosts()
{
if (isPingingForServers)
{
rakPeer->Shutdown(0);
isPingingForServers = false;
}
}
const ServerList& RakNetInstance::getServerList()
{
return availableServers;
}
void RakNetInstance::clearServerList()
{
availableServers.clear();
/*
for (int i = 0; i < 20; ++i) {
PingedCompatibleServer ps;
ps.isSpecial = false;
ps.name = "Fake-Real";
ps.address.FromString("192.168.1.236|19132");
availableServers.push_back(ps);
}
*/
}
RakNet::RakPeerInterface* RakNetInstance::getPeer()
{
return rakPeer;
}
bool RakNetInstance::isProbablyBroken() {
return rakPeer->errorState < -100;
}
void RakNetInstance::resetIsBroken() {
rakPeer->errorState = 0;
}
bool RakNetInstance::isMyLocalGuid(const RakNet::RakNetGUID& guid)
{
return rakPeer->IsActive() && rakPeer->GetMyGUID() == guid;
}
void RakNetInstance::runEvents(NetEventCallback* callback)
{
RakNet::Packet* currentEvent;
while ((currentEvent = rakPeer->Receive()) != NULL)
{
int packetId = currentEvent->data[0];
int length = currentEvent->length;
RakNet::BitStream activeBitStream(currentEvent->data + 1, length - 1, false);
if (callback) {
if (packetId < ID_USER_PACKET_ENUM)
{
//LOGI("Received event: %s\n", getPacketName(packetId));
switch (packetId)
{
case ID_NEW_INCOMING_CONNECTION:
callback->onNewClient(currentEvent->guid);
break;
case ID_CONNECTION_REQUEST_ACCEPTED:
serverGuid = currentEvent->guid;
callback->onConnect(currentEvent->guid);
break;
case ID_CONNECTION_ATTEMPT_FAILED:
callback->onUnableToConnect();
break;
case ID_DISCONNECTION_NOTIFICATION:
case ID_CONNECTION_LOST:
callback->onDisconnect(currentEvent->guid);
break;
case ID_UNCONNECTED_PONG:
{
RakNet::TimeMS time;
RakNet::RakString data;
activeBitStream.Read(time);
activeBitStream.Read(data);
int index = handleUnconnectedPong(data, currentEvent, APP_IDENTIFIER, false);
if (index < 0) {
// Check if it's an official Mojang MineCon server
index = handleUnconnectedPong(data, currentEvent, APP_IDENTIFIER_MINECON, true);
if (index >= 0) availableServers[index].isSpecial = true;
}
}
break;
}
}
else
{
int userPacketId = packetId - ID_USER_PACKET_ENUM;
bool isStatusPacket = userPacketId <= PACKET_READY;
if (isStatusPacket || _isServer || _isLoggedIn) {
if (Packet* packet = MinecraftPackets::createPacket(packetId)) {
packet->read(&activeBitStream);
packet->handle(currentEvent->guid, callback);
delete packet;
}
}
}
}
rakPeer->DeallocatePacket(currentEvent);
//delete activeBitStream;
}
if (isPingingForServers)
{
if (RakNet::GetTimeMS() - lastPingTime > 1000)
{
// remove servers that hasn't responded for a while
ServerList::iterator it = availableServers.begin();
for (; it != availableServers.end(); )
{
if (RakNet::GetTimeMS() - it->pingTime > 3000)
{
it = availableServers.erase(it);
}
else
{
++it;
}
}
pingForHosts(pingPort);
}
}
}
void RakNetInstance::send(Packet& packet) {
RakNet::BitStream bitStream;
packet.write(&bitStream);
if (_isServer)
{
// broadcast to all connected clients
rakPeer->Send(&bitStream, packet.priority, packet.reliability, 0, RakNet::UNASSIGNED_SYSTEM_ADDRESS, true);
}
else
{
// send to server
rakPeer->Send(&bitStream, packet.priority, packet.reliability, 0, serverGuid, false);
}
}
void RakNetInstance::send(const RakNet::RakNetGUID& guid, Packet& packet) {
RakNet::BitStream bitStream;
packet.write(&bitStream);
rakPeer->Send(&bitStream, packet.priority, packet.reliability, 0, guid, false);
}
void RakNetInstance::send(Packet* packet)
{
send(*packet);
delete packet;
}
void RakNetInstance::send(const RakNet::RakNetGUID& guid, Packet* packet)
{
send(guid, *packet);
delete packet;
}
#ifdef _DEBUG
const char* RakNetInstance::getPacketName(int packetId)
{
switch (packetId)
{
case ID_CONNECTED_PING:
return "ID_CONNECTED_PING";
case ID_UNCONNECTED_PING:
return "ID_UNCONNECTED_PING";
case ID_UNCONNECTED_PING_OPEN_CONNECTIONS:
return "ID_UNCONNECTED_PING_OPEN_CONNECTIONS";
case ID_CONNECTED_PONG:
return "ID_CONNECTED_PONG";
case ID_DETECT_LOST_CONNECTIONS:
return "ID_DETECT_LOST_CONNECTIONS";
case ID_OPEN_CONNECTION_REQUEST_1:
return "ID_OPEN_CONNECTION_REQUEST_1";
case ID_OPEN_CONNECTION_REPLY_1:
return "ID_OPEN_CONNECTION_REPLY_1";
case ID_OPEN_CONNECTION_REQUEST_2:
return "ID_OPEN_CONNECTION_REQUEST_2";
case ID_OPEN_CONNECTION_REPLY_2:
return "ID_OPEN_CONNECTION_REPLY_2";
case ID_CONNECTION_REQUEST:
return "ID_CONNECTION_REQUEST";
case ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY:
return "ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY";
case ID_OUR_SYSTEM_REQUIRES_SECURITY:
return "ID_OUR_SYSTEM_REQUIRES_SECURITY";
case ID_PUBLIC_KEY_MISMATCH:
return "ID_PUBLIC_KEY_MISMATCH";
case ID_OUT_OF_BAND_INTERNAL:
return "ID_OUT_OF_BAND_INTERNAL";
case ID_SND_RECEIPT_ACKED:
return "ID_SND_RECEIPT_ACKED";
case ID_SND_RECEIPT_LOSS:
return "ID_SND_RECEIPT_LOSS";
case ID_CONNECTION_REQUEST_ACCEPTED:
return "ID_CONNECTION_REQUEST_ACCEPTED";
case ID_CONNECTION_ATTEMPT_FAILED:
return "ID_CONNECTION_ATTEMPT_FAILED";
case ID_ALREADY_CONNECTED:
return "ID_ALREADY_CONNECTED";
case ID_NEW_INCOMING_CONNECTION:
return "ID_NEW_INCOMING_CONNECTION";
case ID_NO_FREE_INCOMING_CONNECTIONS:
return "ID_NO_FREE_INCOMING_CONNECTIONS";
case ID_DISCONNECTION_NOTIFICATION:
return "ID_DISCONNECTION_NOTIFICATION";
case ID_CONNECTION_LOST:
return "ID_CONNECTION_LOST";
case ID_CONNECTION_BANNED:
return "ID_CONNECTION_BANNED";
case ID_INVALID_PASSWORD:
return "ID_INVALID_PASSWORD";
case ID_INCOMPATIBLE_PROTOCOL_VERSION:
return "ID_INCOMPATIBLE_PROTOCOL_VERSION";
case ID_IP_RECENTLY_CONNECTED:
return "ID_IP_RECENTLY_CONNECTED";
case ID_TIMESTAMP:
return "ID_TIMESTAMP";
case ID_UNCONNECTED_PONG:
return "ID_UNCONNECTED_PONG";
case ID_ADVERTISE_SYSTEM:
return "ID_ADVERTISE_SYSTEM";
case ID_DOWNLOAD_PROGRESS:
return "ID_DOWNLOAD_PROGRESS";
case ID_REMOTE_DISCONNECTION_NOTIFICATION:
return "ID_REMOTE_DISCONNECTION_NOTIFICATION";
case ID_REMOTE_CONNECTION_LOST:
return "ID_REMOTE_CONNECTION_LOST";
case ID_REMOTE_NEW_INCOMING_CONNECTION:
return "ID_REMOTE_NEW_INCOMING_CONNECTION";
case ID_FILE_LIST_TRANSFER_HEADER:
return "ID_FILE_LIST_TRANSFER_HEADER";
case ID_FILE_LIST_TRANSFER_FILE:
return "ID_FILE_LIST_TRANSFER_FILE";
case ID_FILE_LIST_REFERENCE_PUSH_ACK:
return "ID_FILE_LIST_REFERENCE_PUSH_ACK";
case ID_DDT_DOWNLOAD_REQUEST:
return "ID_DDT_DOWNLOAD_REQUEST";
case ID_TRANSPORT_STRING:
return "ID_TRANSPORT_STRING";
case ID_REPLICA_MANAGER_CONSTRUCTION:
return "ID_REPLICA_MANAGER_CONSTRUCTION";
case ID_REPLICA_MANAGER_SCOPE_CHANGE:
return "ID_REPLICA_MANAGER_SCOPE_CHANGE";
case ID_REPLICA_MANAGER_SERIALIZE:
return "ID_REPLICA_MANAGER_SERIALIZE";
case ID_REPLICA_MANAGER_DOWNLOAD_STARTED:
return "ID_REPLICA_MANAGER_DOWNLOAD_STARTED";
case ID_REPLICA_MANAGER_DOWNLOAD_COMPLETE:
return "ID_REPLICA_MANAGER_DOWNLOAD_COMPLETE";
case ID_RAKVOICE_OPEN_CHANNEL_REQUEST:
return "ID_RAKVOICE_OPEN_CHANNEL_REQUEST";
case ID_RAKVOICE_OPEN_CHANNEL_REPLY:
return "ID_RAKVOICE_OPEN_CHANNEL_REPLY";
case ID_RAKVOICE_CLOSE_CHANNEL:
return "ID_RAKVOICE_CLOSE_CHANNEL";
case ID_RAKVOICE_DATA:
return "ID_RAKVOICE_DATA";
case ID_AUTOPATCHER_GET_CHANGELIST_SINCE_DATE:
return "ID_AUTOPATCHER_GET_CHANGELIST_SINCE_DATE";
case ID_AUTOPATCHER_CREATION_LIST:
return "ID_AUTOPATCHER_CREATION_LIST";
case ID_AUTOPATCHER_DELETION_LIST:
return "ID_AUTOPATCHER_DELETION_LIST";
case ID_AUTOPATCHER_GET_PATCH:
return "ID_AUTOPATCHER_GET_PATCH";
case ID_AUTOPATCHER_PATCH_LIST:
return "ID_AUTOPATCHER_PATCH_LIST";
case ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR:
return "ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR";
case ID_AUTOPATCHER_FINISHED_INTERNAL:
return "ID_AUTOPATCHER_FINISHED_INTERNAL";
case ID_AUTOPATCHER_FINISHED:
return "ID_AUTOPATCHER_FINISHED";
case ID_AUTOPATCHER_RESTART_APPLICATION:
return "ID_AUTOPATCHER_RESTART_APPLICATION";
case ID_NAT_PUNCHTHROUGH_REQUEST:
return "ID_NAT_PUNCHTHROUGH_REQUEST";
case ID_NAT_GROUP_PUNCHTHROUGH_REQUEST:
return "ID_NAT_GROUP_PUNCHTHROUGH_REQUEST";
case ID_NAT_GROUP_PUNCHTHROUGH_REPLY:
return "ID_NAT_GROUP_PUNCHTHROUGH_REPLY";
case ID_NAT_CONNECT_AT_TIME:
return "ID_NAT_CONNECT_AT_TIME";
case ID_NAT_GET_MOST_RECENT_PORT:
return "ID_NAT_GET_MOST_RECENT_PORT";
case ID_NAT_CLIENT_READY:
return "ID_NAT_CLIENT_READY";
case ID_NAT_GROUP_PUNCHTHROUGH_FAILURE_NOTIFICATION:
return "ID_NAT_GROUP_PUNCHTHROUGH_FAILURE_NOTIFICATION";
case ID_NAT_TARGET_NOT_CONNECTED:
return "ID_NAT_TARGET_NOT_CONNECTED";
case ID_NAT_TARGET_UNRESPONSIVE:
return "ID_NAT_TARGET_UNRESPONSIVE";
case ID_NAT_CONNECTION_TO_TARGET_LOST:
return "ID_NAT_CONNECTION_TO_TARGET_LOST";
case ID_NAT_ALREADY_IN_PROGRESS:
return "ID_NAT_ALREADY_IN_PROGRESS";
case ID_NAT_PUNCHTHROUGH_FAILED:
return "ID_NAT_PUNCHTHROUGH_FAILED";
case ID_NAT_PUNCHTHROUGH_SUCCEEDED:
return "ID_NAT_PUNCHTHROUGH_SUCCEEDED";
case ID_NAT_GROUP_PUNCH_FAILED:
return "ID_NAT_GROUP_PUNCH_FAILED";
case ID_NAT_GROUP_PUNCH_SUCCEEDED:
return "ID_NAT_GROUP_PUNCH_SUCCEEDED";
case ID_READY_EVENT_SET:
return "ID_READY_EVENT_SET";
case ID_READY_EVENT_UNSET:
return "ID_READY_EVENT_UNSET";
case ID_READY_EVENT_ALL_SET:
return "ID_READY_EVENT_ALL_SET";
case ID_READY_EVENT_QUERY:
return "ID_READY_EVENT_QUERY";
case ID_LOBBY_GENERAL:
return "ID_LOBBY_GENERAL";
case ID_RPC_REMOTE_ERROR:
return "ID_RPC_REMOTE_ERROR";
case ID_RPC_PLUGIN:
return "ID_RPC_PLUGIN";
case ID_FILE_LIST_REFERENCE_PUSH:
return "ID_FILE_LIST_REFERENCE_PUSH";
case ID_READY_EVENT_FORCE_ALL_SET:
return "ID_READY_EVENT_FORCE_ALL_SET";
case ID_ROOMS_EXECUTE_FUNC:
return "ID_ROOMS_EXECUTE_FUNC";
case ID_ROOMS_LOGON_STATUS:
return "ID_ROOMS_LOGON_STATUS";
case ID_ROOMS_HANDLE_CHANGE:
return "ID_ROOMS_HANDLE_CHANGE";
case ID_LOBBY2_SEND_MESSAGE:
return "ID_LOBBY2_SEND_MESSAGE";
case ID_LOBBY2_SERVER_ERROR:
return "ID_LOBBY2_SERVER_ERROR";
case ID_FCM2_NEW_HOST:
return "ID_FCM2_NEW_HOST";
case ID_FCM2_REQUEST_FCMGUID:
return "ID_FCM2_REQUEST_FCMGUID";
case ID_FCM2_RESPOND_CONNECTION_COUNT:
return "ID_FCM2_RESPOND_CONNECTION_COUNT";
case ID_FCM2_INFORM_FCMGUID:
return "ID_FCM2_INFORM_FCMGUID";
case ID_FCM2_UPDATE_MIN_TOTAL_CONNECTION_COUNT:
return "ID_FCM2_UPDATE_MIN_TOTAL_CONNECTION_COUNT";
case ID_UDP_PROXY_GENERAL:
return "ID_UDP_PROXY_GENERAL";
case ID_SQLite3_EXEC:
return "ID_SQLite3_EXEC";
case ID_SQLite3_UNKNOWN_DB:
return "ID_SQLite3_UNKNOWN_DB";
case ID_SQLLITE_LOGGER:
return "ID_SQLLITE_LOGGER";
case ID_NAT_TYPE_DETECTION_REQUEST:
return "ID_NAT_TYPE_DETECTION_REQUEST";
case ID_NAT_TYPE_DETECTION_RESULT:
return "ID_NAT_TYPE_DETECTION_RESULT";
case ID_ROUTER_2_INTERNAL:
return "ID_ROUTER_2_INTERNAL";
case ID_ROUTER_2_FORWARDING_NO_PATH:
return "ID_ROUTER_2_FORWARDING_NO_PATH";
case ID_ROUTER_2_FORWARDING_ESTABLISHED:
return "ID_ROUTER_2_FORWARDING_ESTABLISHED";
case ID_ROUTER_2_REROUTED:
return "ID_ROUTER_2_REROUTED";
case ID_TEAM_BALANCER_INTERNAL:
return "ID_TEAM_BALANCER_INTERNAL";
case ID_TEAM_BALANCER_REQUESTED_TEAM_CHANGE_PENDING:
return "ID_TEAM_BALANCER_REQUESTED_TEAM_CHANGE_PENDING";
case ID_TEAM_BALANCER_TEAMS_LOCKED:
return "ID_TEAM_BALANCER_TEAMS_LOCKED";
case ID_TEAM_BALANCER_TEAM_ASSIGNED:
return "ID_TEAM_BALANCER_TEAM_ASSIGNED";
case ID_LIGHTSPEED_INTEGRATION:
return "ID_LIGHTSPEED_INTEGRATION";
case ID_XBOX_LOBBY:
return "ID_XBOX_LOBBY";
case ID_TWO_WAY_AUTHENTICATION_INCOMING_CHALLENGE_SUCCESS:
return "ID_TWO_WAY_AUTHENTICATION_INCOMING_CHALLENGE_SUCCESS";
case ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_SUCCESS:
return "ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_SUCCESS";
case ID_TWO_WAY_AUTHENTICATION_INCOMING_CHALLENGE_FAILURE:
return "ID_TWO_WAY_AUTHENTICATION_INCOMING_CHALLENGE_FAILURE";
case ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_FAILURE:
return "ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_FAILURE";
case ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_TIMEOUT:
return "ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_TIMEOUT";
case ID_TWO_WAY_AUTHENTICATION_NEGOTIATION:
return "ID_TWO_WAY_AUTHENTICATION_NEGOTIATION";
case ID_CLOUD_POST_REQUEST:
return "ID_CLOUD_POST_REQUEST";
case ID_CLOUD_RELEASE_REQUEST:
return "ID_CLOUD_RELEASE_REQUEST";
case ID_CLOUD_GET_REQUEST:
return "ID_CLOUD_GET_REQUEST";
case ID_CLOUD_GET_RESPONSE:
return "ID_CLOUD_GET_RESPONSE";
case ID_CLOUD_UNSUBSCRIBE_REQUEST:
return "ID_CLOUD_UNSUBSCRIBE_REQUEST";
case ID_CLOUD_SERVER_TO_SERVER_COMMAND:
return "ID_CLOUD_SERVER_TO_SERVER_COMMAND";
case ID_CLOUD_SUBSCRIPTION_NOTIFICATION:
return "ID_CLOUD_SUBSCRIPTION_NOTIFICATION";
case ID_RESERVED_1:
return "ID_RESERVED_1";
case ID_RESERVED_2:
return "ID_RESERVED_2";
case ID_RESERVED_3:
return "ID_RESERVED_3";
case ID_RESERVED_4:
return "ID_RESERVED_4";
case ID_RESERVED_5:
return "ID_RESERVED_5";
case ID_RESERVED_6:
return "ID_RESERVED_6";
case ID_RESERVED_7:
return "ID_RESERVED_7";
case ID_RESERVED_8:
return "ID_RESERVED_8";
case ID_RESERVED_9:
return "ID_RESERVED_9";
default:
break;
}
return "Unknown or user-defined";
}
#endif
int RakNetInstance::handleUnconnectedPong(const RakNet::RakString& data, const RakNet::Packet* p, const char* appid, bool insertAtBeginning)
{
RakNet::RakString appIdentifier(appid);
// This weird code is a result of RakString.Find being pretty useless
bool emptyNameOrLonger = data.GetLength() >= appIdentifier.GetLength();
if ( !emptyNameOrLonger || appIdentifier.StrCmp(data.SubStr(0, appIdentifier.GetLength())) != 0)
return -1;
bool found = false;
for (unsigned int i = 0; i < availableServers.size(); i++) {
if (availableServers[i].address == p->systemAddress) {
availableServers[i].pingTime = RakNet::GetTimeMS();
bool emptyName = data.GetLength() == appIdentifier.GetLength();
if (emptyName)
availableServers[i].name = "";
else {
availableServers[i].name = data.SubStr(appIdentifier.GetLength(), data.GetLength() - appIdentifier.GetLength());
}
//LOGI("Swapping name: %s\n", availableServers[i].name.C_String());
return i;
}
}
PingedCompatibleServer server;
server.address = p->systemAddress;
server.pingTime = RakNet::GetTimeMS();
server.isSpecial = false;
server.name = data.SubStr(appIdentifier.GetLength(), data.GetLength() - appIdentifier.GetLength());
if (insertAtBeginning) {
availableServers.insert(availableServers.begin(), server);
return 0;
} else {
availableServers.push_back(server);
return availableServers.size() - 1;
}
}
void RakNetInstance::setIsLoggedIn( bool status ) {
_isLoggedIn = status;
}

118
src/network/RakNetInstance.h Executable file
View File

@@ -0,0 +1,118 @@
#ifndef _MINECRAFT_NETWORK_RAKNETINSTANCE_H_
#define _MINECRAFT_NETWORK_RAKNETINSTANCE_H_
#include <vector>
#include <string>
#include "../raknet/RakNetTypes.h"
#include "../raknet/RakString.h"
namespace RakNet
{
class RakPeerInterface;
}
class Packet;
class NetEventCallback;
typedef struct PingedCompatibleServer
{
RakNet::RakString name;
RakNet::SystemAddress address;
RakNet::TimeMS pingTime;
bool isSpecial;
} PingedCompatibleServer;
typedef std::vector<PingedCompatibleServer> ServerList;
class IRakNetInstance
{
public:
virtual ~IRakNetInstance() {}
virtual bool host(const std::string& localName, int port, int maxConnections = 4) { return false; }
virtual bool connect(const char* host, int port) { return false; }
virtual void setIsLoggedIn(bool status) {}
virtual void pingForHosts(int port) {}
virtual void stopPingForHosts() {}
virtual const ServerList& getServerList() { static ServerList l; return l; }
virtual void clearServerList() {}
virtual void disconnect() {}
virtual void announceServer(const std::string& localName) {}
virtual RakNet::RakPeerInterface* getPeer() { return NULL; }
virtual bool isMyLocalGuid(const RakNet::RakNetGUID& guid) { return true; }
virtual void runEvents(NetEventCallback* callback) {}
virtual void send(Packet& packet) {}
virtual void send(const RakNet::RakNetGUID& guid, Packet& packet) {}
// @attn: Those delete the packet
virtual void send(Packet* packet) {}
virtual void send(const RakNet::RakNetGUID& guid, Packet* packet) {}
virtual bool isServer() { return true; }
virtual bool isProbablyBroken() { return false; }
virtual void resetIsBroken() {}
};
class RakNetInstance: public IRakNetInstance
{
public:
RakNetInstance();
virtual ~RakNetInstance();
bool host(const std::string& localName, int port, int maxConnections = 4);
bool connect(const char* host, int port);
void setIsLoggedIn(bool status);
void pingForHosts(int basePort);
void stopPingForHosts();
const ServerList& getServerList();
void clearServerList();
void disconnect();
void announceServer(const std::string& localName);
RakNet::RakPeerInterface* getPeer();
bool isMyLocalGuid(const RakNet::RakNetGUID& guid);
void runEvents(NetEventCallback* callback);
void send(Packet& packet);
void send(const RakNet::RakNetGUID& guid, Packet& packet);
// @attn: Those delete the packet
void send(Packet* packet);
void send(const RakNet::RakNetGUID& guid, Packet* packet);
bool isServer() { return _isServer; }
bool isProbablyBroken();
void resetIsBroken();
#ifdef _DEBUG
const char* getPacketName(int packetId);
#else
const char* getPacketName(int packetId) { return ""; }
#endif
private:
int handleUnconnectedPong(const RakNet::RakString& data, const RakNet::Packet*, const char* appid, bool insertAtBeginning);
RakNet::RakPeerInterface* rakPeer;
RakNet::RakNetGUID serverGuid;
ServerList availableServers;
bool isPingingForServers;
int pingPort;
RakNet::TimeMS lastPingTime;
bool _isServer;
bool _isLoggedIn;
};
#endif /*_MINECRAFT_NETWORK_RAKNETINSTANCE_H_*/

View File

@@ -0,0 +1,705 @@
#include "ServerSideNetworkHandler.h"
#include "../world/level/Level.h"
#include "../world/entity/player/Player.h"
#include "../world/entity/player/Inventory.h"
#include "../world/Container.h"
#include "../world/inventory/BaseContainerMenu.h"
#include "packet/PacketInclude.h"
#include "RakNetInstance.h"
#include "../client/Minecraft.h"
#include "../client/player/LocalPlayer.h"
#include "../client/gamemode/GameMode.h"
#include "../raknet/RakPeerInterface.h"
#include "../raknet/PacketPriority.h"
#ifndef STANDALONE_SERVER
#include "../client/sound/SoundEngine.h"
#endif
#include "../server/ServerPlayer.h"
#include "../world/entity/item/FallingTile.h"
#define TIMES(x) for(int itc ## __LINE__ = 0; itc ## __LINE__ < x; ++ itc ## __LINE__)
ServerSideNetworkHandler::ServerSideNetworkHandler(Minecraft* minecraft, IRakNetInstance* raknetInstance)
: minecraft(minecraft),
raknetInstance(raknetInstance),
level(NULL)
{
allowIncomingConnections(false);
rakPeer = raknetInstance->getPeer();
}
ServerSideNetworkHandler::~ServerSideNetworkHandler()
{
if (level) {
level->removeListener(this);
}
for (unsigned int i = 0; i < _pendingPlayers.size(); ++i)
delete _pendingPlayers[i];
}
void ServerSideNetworkHandler::tileChanged(int x, int y, int z)
{
//LOGI("tileChanged(%d, %d, %d)\n", x, y, z);
// broadcast change event
UpdateBlockPacket packet(x, y, z, level->getTile(x, y, z), level->getData(x, y, z));
RakNet::BitStream bitStream;
packet.write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, RakNet::UNASSIGNED_SYSTEM_ADDRESS, true);
}
Packet* ServerSideNetworkHandler::getAddPacketFromEntity( Entity* entity ) {
if (entity->isMob() && !entity->isPlayer()) { //@fix: This code is duplicated. See if it can be unified.
if (minecraft->player) {
// I guess this should always be true, but it crashed somewhere in this
// function once and I only see this one as a potential problem
return new AddMobPacket((Mob*)entity);
}
}
else if (entity->isPlayer()) {
} else if (entity->isItemEntity()) {
AddItemEntityPacket* packet = new AddItemEntityPacket((ItemEntity*)entity);
entity->xd = packet->xa();
entity->yd = packet->ya();
entity->zd = packet->za();
//LOGI("item-entity @ server: %f, %f, %f\n", e->xd, e->yd, e->zd);
return packet;
} else if(entity->isHangingEntity()) {
return new AddPaintingPacket((Painting*) entity);
} else {
int type = entity->getEntityTypeId();
int data = entity->getAuxData();
if (EntityTypes::IdFallingTile == type) {
FallingTile* ft = (FallingTile*) entity;
data = -(ft->tile | (ft->data << 16));
}
//LOGI("Server: adding entity with %f, %f, %f\n", e->xd, e->yd, e->zd);
AddEntityPacket* packet = new AddEntityPacket(entity, data);
/*
entity->xd = packet->xd;
entity->yd = packet->yd;
entity->zd = packet->zd;
*/
return packet;
}
return NULL;
}
void ServerSideNetworkHandler::entityAdded(Entity* e) {
Packet* packet = getAddPacketFromEntity(e);
if(packet != NULL) {
if (e->isMob() && !e->isPlayer()) {
redistributePacket(packet, rakPeer->GetMyGUID());
delete packet;
} else {
raknetInstance->send(packet);
// raknetInstance->send always deletes package
}
}
}
void ServerSideNetworkHandler::entityRemoved(Entity* e)
{
if (!e->isPlayer()) { //@fix: This code MIGHT be duplicated. See if it can be unified.
RemoveEntityPacket packet(e->entityId);
redistributePacket(&packet, rakPeer->GetMyGUID());
} else { // Is a player
RemovePlayerPacket packet((Player*) e);
redistributePacket(&packet, rakPeer->GetMyGUID());
}
}
void ServerSideNetworkHandler::redistributePacket(Packet* packet, const RakNet::RakNetGUID& fromPlayer)
{
// broadcast the new player to all other players
RakNet::BitStream bitStream;
packet->write(&bitStream);
rakPeer->Send(&bitStream, packet->priority, packet->reliability, 0, fromPlayer, true);
}
void ServerSideNetworkHandler::displayGameMessage(const std::string& message)
{
#ifndef STANDALONE_SERVER
minecraft->gui.addMessage(message);
#else
LOGI("%s\n", message.c_str());
#endif
MessagePacket packet(message.c_str());
raknetInstance->send(packet);
}
void ServerSideNetworkHandler::onNewClient(const RakNet::RakNetGUID& clientGuid)
{
LOGI("onNewClient, client guid: %s\n", clientGuid.ToString());
}
void ServerSideNetworkHandler::onDisconnect(const RakNet::RakNetGUID& guid)
{
if (!level) return;
LOGI("onDisconnect\n");
const PlayerList& players = level->players;
for (unsigned int i = 0; i < players.size(); i++)
{
Player* player = players[i];
if (player->owner == guid)
{
std::string message = player->name;
message += " disconnected from the game";
displayGameMessage(message);
//RemoveEntityPacket packet(player->entityId);
//raknetInstance->send(packet);
player->reallyRemoveIfPlayer = true;
level->removeEntity(player);
//level->removePlayer(player);
LOGI("&e@disc: %p", player);
break;
}
}
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPacket* packet)
{
if (!level) return;
if (!_allowIncoming) return;
LOGI("LoginPacket\n");
int loginStatus = LoginStatus::Success;
//
// Bad/incompatible client version
//
bool oldClient = packet->clientNetworkVersion < SharedConstants::NetworkProtocolLowestSupportedVersion;
bool oldServer = packet->clientNetworkLowestSupportedVersion > SharedConstants::NetworkProtocolVersion;
if (oldClient || oldServer)
loginStatus = oldClient? LoginStatus::Failed_ClientOld : LoginStatus::Failed_ServerOld;
RakNet::BitStream bitStream;
LoginStatusPacket(loginStatus).write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
if (LoginStatus::Success != loginStatus)
return;
//
// Valid client version
//
Player* newPlayer = new ServerPlayer(minecraft, level);
minecraft->gameMode->initAbilities(newPlayer->abilities);
newPlayer->owner = source;
newPlayer->name = packet->clientName.C_String();
_pendingPlayers.push_back(newPlayer);
// Reset the player so he doesn't spawn inside blocks
while (newPlayer->y > 0) {
newPlayer->setPos(newPlayer->x, newPlayer->y, newPlayer->z);
if (level->getCubes(newPlayer, newPlayer->bb).size() == 0) break;
newPlayer->y += 1;
}
newPlayer->moveTo(newPlayer->x, newPlayer->y - newPlayer->heightOffset, newPlayer->z, newPlayer->yRot, newPlayer->xRot);
// send world seed
{
RakNet::BitStream bitStream;
// @todo: Read from LevelData?
int gameType = minecraft->isCreativeMode()
? GameType::Creative
: GameType::Survival;
StartGamePacket(
level->getSeed(),
level->getLevelData()->getGeneratorVersion(),
gameType,
newPlayer->entityId,
newPlayer->x, newPlayer->y - newPlayer->heightOffset, newPlayer->z
).write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
}
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ReadyPacket* packet)
{
if (!level) return;
if (packet->type == ReadyPacket::READY_CLIENTGENERATION)
onReady_ClientGeneration(source);
if (packet->type == ReadyPacket::READY_REQUESTEDCHUNKS)
onReady_RequestedChunks(source);
}
void ServerSideNetworkHandler::onReady_ClientGeneration(const RakNet::RakNetGUID& source)
{
Player* newPlayer = popPendingPlayer(source);
if (!newPlayer) {
for (int i = 0; i < 3; ++i)
LOGE("We don't have a user associated with this player!\n");
return;
}
// Create a bitstream that can be used by everyone (after ::reset() )
RakNet::BitStream bitStream;
// send level info
SetTimePacket(level->getTime()).write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
// send all pre-existing players to the new player
const PlayerList& players = level->players;
for (unsigned int i = 0; i < players.size(); i++) {
Player* player = players[i];
bitStream.Reset();
AddPlayerPacket(player).write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
if (player->getArmorTypeHash()) {
bitStream.Reset();
PlayerArmorEquipmentPacket(player).write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
}
}
level->addEntity(newPlayer);
#ifndef STANDALONE_SERVER
minecraft->gui.addMessage(newPlayer->name + " joined the game");
#else
LOGW("%s joined the game\n", newPlayer->name.c_str());
#endif
// Send all Entities to the new player
for (unsigned int i = 0; i < level->entities.size(); ++i) {
Entity* e = level->entities[i];
Packet* packet = getAddPacketFromEntity(e);
if(packet != NULL) {
bitStream.Reset();
packet->write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
delete packet;
}
}
// Additional packets
// * set spawn
/*
bitStream.Reset();
SetSpawnPositionPacket spawnPacket(level->getSharedSpawnPos());
raknetInstance->send(source, spawnPacket);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
*/
// broadcast the new player to all other players
bitStream.Reset();
AddPlayerPacket(newPlayer).write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, true);
}
//
// Messages to be sent after client has finished applying changes
//
void ServerSideNetworkHandler::onReady_RequestedChunks(const RakNet::RakNetGUID& source)
{
RakNet::BitStream bitStream;
// Send all TileEntities to the new player
for (unsigned int i = 0; i < level->tileEntities.size(); ++i) {
TileEntity* e = level->tileEntities[i];
Packet* packet = e->getUpdatePacket();
if (packet != NULL) {
bitStream.Reset();
packet->write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
delete packet;
}
}
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlayerPacket* packet)
{
if (!level) return;
//LOGI("MovePlayerPacket\n");
if (Entity* entity = level->getEntity(packet->entityId))
{
entity->xd = entity->yd = entity->zd = 0;
entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3);
// broadcast this packet to other clients
redistributePacket(packet, source);
}
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveBlockPacket* packet){
if (!level) return;
Player* player = getPlayer(source);
if (!player) return;
player->swing();
int x = packet->x, y = packet->y, z = packet->z;
// code copied from GameMode.cpp
int oldId = level->getTile(x, y, z);
int data = level->getData(x, y, z);
Tile* oldTile = Tile::tiles[oldId];
bool changed = level->setTile(x, y, z, 0);
if (oldTile != NULL && changed) {
level->playSound(x + 0.5f, y + 0.5f, z + 0.5f, oldTile->soundType->getBreakSound(), (oldTile->soundType->getVolume() + 1) / 2, oldTile->soundType->getPitch() * 0.8f);
if (minecraft->gameMode->isSurvivalType() && player->canDestroy(oldTile))
//oldTile->spawnResources(level, x, y, z, data, 1); //@todo
oldTile->playerDestroy(level, player, x, y, z, data);
oldTile->destroy(level, x, y, z, data);
}
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RequestChunkPacket* packet)
{
if (!level)
return;
LevelChunk* chunk = level->getChunk(packet->x, packet->z);
if (!chunk)
return;
ChunkDataPacket cpacket(chunk->x, chunk->z, chunk);
RakNet::BitStream bitStream;
cpacket.write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
//LOGI("RequestChunkPacket @ (%d, %d). %d bytes\n", packet->x, packet->z, cpacket.chunkData.GetNumberOfBytesUsed());
//LOGI("size: %d\n", bitStream.GetNumberOfBytesUsed());
const LevelChunk::TEMap& teMap = chunk->getTileEntityMap();
for (LevelChunk::TEMapCIterator cit = teMap.begin(); cit != teMap.end(); ++cit) {
TileEntity* te = cit->second;
if (Packet* p = te->getUpdatePacket()) {
bitStream.Reset();
p->write(&bitStream);
raknetInstance->send(source, p);
}
}
}
void ServerSideNetworkHandler::levelGenerated( Level* level )
{
this->level = level;
if (minecraft->player) {
minecraft->player->owner = rakPeer->GetMyGUID();
}
level->addListener(this);
#ifndef STANDALONE_SERVER
allowIncomingConnections(minecraft->options.serverVisible);
#else
allowIncomingConnections(true);
#endif
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, PlayerEquipmentPacket* packet)
{
if (!level) return;
Player* player = getPlayer(source);
if (!player) return;
if (rakPeer->GetMyGUID() == player->owner) return;
// override the player's inventory
//int slot = player->inventory->getSlot(packet->itemId, packet->itemAuxValue);
int slot = Inventory::MAX_SELECTION_SIZE;
if (slot >= 0) {
if (packet->itemId == 0) {
player->inventory->clearSlot(slot);
} else {
// @note: 128 is an ugly hack for depletable items.
// @todo: fix
ItemInstance newItem(packet->itemId, 128, packet->itemAuxValue);
player->inventory->replaceSlot(slot, &newItem);
}
player->inventory->moveToSelectedSlot(slot, true);
redistributePacket(packet, source);
} else {
LOGW("Warning: Remote player doesn't have his thing, Odd!\n");
}
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, PlayerArmorEquipmentPacket* packet) {
if (!level) return;
Player* player = getPlayer(source);
if (!player) return;
if (rakPeer->GetMyGUID() == player->owner) return;
packet->fillIn(player);
redistributePacket(packet, source);
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, InteractPacket* packet) {
if (!level) return;
Entity* src = level->getEntity(packet->sourceId);
Entity* entity = level->getEntity(packet->targetId);
if (src && entity && src->isPlayer())
{
Player* player = (Player*) src;
if (InteractPacket::Attack == packet->action) {
player->swing();
minecraft->gameMode->attack(player, entity);
}
if (InteractPacket::Interact == packet->action) {
player->swing();
minecraft->gameMode->interact(player, entity);
}
redistributePacket(packet, source);
}
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AnimatePacket* packet)
{
if (!level)
return;
// Own player -> invalid
if (minecraft->player && minecraft->player->entityId == packet->entityId) {
return;
}
Entity* entity = level->getEntity(packet->entityId);
if (!entity || !entity->isPlayer())
return;
Player* player = (Player*) entity;
switch (packet->action) {
case AnimatePacket::Swing:
player->swing();
break;
default:
LOGW("Unknown Animate action: %d\n", packet->action);
break;
}
redistributePacket(packet, source);
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemPacket* packet)
{
if (!level) return;
LOGI("UseItemPacket\n");
Entity* entity = level->getEntity(packet->entityId);
if (entity && entity->isPlayer()) {
Player* player = (Player*) entity;
int x = packet->x, y = packet->y, z = packet->z;
Tile* t = Tile::tiles[level->getTile(x, y, z)];
if (t == Tile::invisible_bedrock) return;
if (t && t->use(level, x, y, z, player)) return;
if (packet->item.isNull()) return;
ItemInstance* item = &packet->item;
if(packet->face == 255) {
// Special case: x,y,z means direction-of-action
player->aimDirection.set(packet->x / 32768.0f, packet->y / 32768.0f, packet->z / 32768.0f);
minecraft->gameMode->useItem(player, level, item);
}
else {
minecraft->gameMode->useItemOn(player, level, item, packet->x, packet->y, packet->z, packet->face,
Vec3(packet->clickX + packet->x, packet->clickY + packet->y, packet->clickZ + packet->z));
}
//LOGW("Use Item not working! Out of synch?\n");
// Don't have to redistribute (ugg.. this will mess up), cause tileUpdated is sent
//redistributePacket(packet, source);
}
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, EntityEventPacket* packet) {
if (!level) return;
if (Entity* e = level->getEntity(packet->entityId))
e->handleEntityEvent(packet->eventId);
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, PlayerActionPacket* packet)
{
if (!level) return;
LOGI("PlayerActionPacket\n");
Entity* entity = level->getEntity(packet->entityId);
if (entity && entity->isPlayer()) {
Player* player = (Player*) entity;
if(packet->action == PlayerActionPacket::RELEASE_USE_ITEM) {
minecraft->gameMode->releaseUsingItem(player);
return;
}
else if(packet->action == PlayerActionPacket::STOP_SLEEPING) {
player->stopSleepInBed(true, true, true);
}
}
}
void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, RespawnPacket* packet )
{
if (!level) return;
NetEventCallback::handle(level, source, packet );
redistributePacket(packet, source);
}
void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SendInventoryPacket* packet )
{
if (!level) return;
Entity* entity = level->getEntity(packet->entityId);
if (entity && entity->isPlayer()) {
Player* p = (Player*)entity;
p->inventory->replace(packet->items, packet->numItems);
if ((packet->extra & SendInventoryPacket::ExtraDrop) != 0) {
p->inventory->dropAll(false);
//@todo @armor : Drop armor
}
}
}
void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, DropItemPacket* packet )
{
if (!level) return;
Entity* entity = level->getEntity(packet->entityId);
if (entity && entity->isPlayer()) {
Player* p = (Player*)entity;
p->drop(new ItemInstance(packet->item), packet->dropType != 0);
}
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ContainerClosePacket* packet) {
if (!level) return;
Player* p = findPlayer(level, &source);
if (!p) return;
if (p != minecraft->player)
static_cast<ServerPlayer*>(p)->doCloseContainer();
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ContainerSetSlotPacket* packet) {
if (!level) return;
Player* p = findPlayer(level, &source);
if (!p) return;
if (p->containerMenu == NULL) {
LOGW("User has no container!\n");
return;
}
if (p->containerMenu->containerId != packet->containerId)
{
LOGW("Wrong container id: %d vs %d\n", p->containerMenu->containerId, packet->containerId);
return;
}
if (ContainerType::FURNACE == p->containerMenu->containerType) {
//LOGI("Server:Setting slot %d: %s\n", packet->slot, packet->item.toString().c_str());
p->containerMenu->setSlot(packet->slot, &packet->item);
//p->containerMenu->setSlot(packet->slot, packet->item.isNull()? NULL : &packet->item);
}
if (ContainerType::CONTAINER == p->containerMenu->containerType) {
//LOGI("Server:Setting slot %d: %s\n", packet->slot, packet->item.toString().c_str());
p->containerMenu->setSlot(packet->slot, &packet->item);
//p->containerMenu->setSlot(packet->slot, packet->item.isNull()? NULL : &packet->item);
}
}
void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SetHealthPacket* packet )
{
for (unsigned int i = 0; i < level->players.size(); ++i) {
Player* p = level->players[i];
if (p->owner == source) {
if (packet->health <= -32) {
int diff = packet->health - SetHealthPacket::HEALTH_MODIFY_OFFSET;
if (diff > 0) p->hurt(NULL, diff);
else if (diff < 0) p->heal(-diff);
}
break;
}
}
}
void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SignUpdatePacket* packet ) {
redistributePacket(packet, source);
if (!level)
return;
TileEntity* te = level->getTileEntity(packet->x, packet->y, packet->z);
if (TileEntity::isType(te, TileEntityType::Sign)) {
SignTileEntity* ste = (SignTileEntity*) te;
if (ste->isEditable()) {
for (int i = 0; i < SignTileEntity::NUM_LINES; i++) {
ste->messages[i] = packet->lines[i];
}
//ste->setChanged();
}
}
}
void ServerSideNetworkHandler::allowIncomingConnections( bool doAllow )
{
if (doAllow) {
raknetInstance->announceServer(minecraft->options.username);
} else {
raknetInstance->announceServer("");
}
_allowIncoming = doAllow;
}
Player* ServerSideNetworkHandler::popPendingPlayer( const RakNet::RakNetGUID& source )
{
if (!level) {
LOGE("Could not add player since Level is NULL!\n");
return NULL;
}
for (unsigned int i = 0; i < _pendingPlayers.size(); ++i) {
Player* p = _pendingPlayers[i];
if (p->owner == source) {
_pendingPlayers.erase(_pendingPlayers.begin() + i);
return p;
}
}
return NULL;
}
void ServerSideNetworkHandler::levelEvent( Player* source, int type, int x, int y, int z, int data )
{
LevelEventPacket packet(type, x, y, z, data);
redistributePacket(&packet, source? source->owner : rakPeer->GetMyGUID());
}
void ServerSideNetworkHandler::tileEvent( int x, int y, int z, int b0, int b1 )
{
TileEventPacket packet(x, y, z, b0, b1);
raknetInstance->send(packet);
}
Player* ServerSideNetworkHandler::getPlayer( const RakNet::RakNetGUID& source ) {
for (unsigned int i = 0; i < level->players.size(); ++i)
if (source == level->players[i]->owner) return level->players[i];
return NULL;
}

View File

@@ -0,0 +1,82 @@
#ifndef _MINECRAFT_NETWORK_SERVERSIDENETWORKHANDLER_H_
#define _MINECRAFT_NETWORK_SERVERSIDENETWORKHANDLER_H_
#include "NetEventCallback.h"
#include "../raknet/RakNetTypes.h"
#include "../world/level/LevelListener.h"
#include <vector>
class Minecraft;
class Level;
class IRakNetInstance;
class Packet;
class Player;
class ServerSideNetworkHandler : public NetEventCallback, public LevelListener
{
public:
ServerSideNetworkHandler(Minecraft* minecraft, IRakNetInstance* raknetInstance);
virtual ~ServerSideNetworkHandler();
virtual void levelGenerated(Level* level);
virtual void tileChanged(int x, int y, int z);
virtual void tileBrightnessChanged(int x, int y, int z) { /* do nothing */ }
virtual Packet* getAddPacketFromEntity(Entity* entity);
virtual void entityAdded(Entity* e);
virtual void entityRemoved(Entity* e);
virtual void levelEvent(Player* source, int type, int x, int y, int z, int data);
virtual void tileEvent(int x, int y, int z, int b0, int b1);
virtual void onNewClient(const RakNet::RakNetGUID& clientGuid);
virtual void onDisconnect(const RakNet::RakNetGUID& guid);
void onReady_ClientGeneration(const RakNet::RakNetGUID& source);
void onReady_RequestedChunks(const RakNet::RakNetGUID& source);
virtual void handle(const RakNet::RakNetGUID& source, LoginPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, ReadyPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, MovePlayerPacket* packet);
//virtual void handle(const RakNet::RakNetGUID& source, PlaceBlockPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, RemoveBlockPacket* packet);
//virtual void handle(const RakNet::RakNetGUID& source, ExplodePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, RequestChunkPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, PlayerEquipmentPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, PlayerArmorEquipmentPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, SetHealthPacket* packet);
//virtual void handle(const RakNet::RakNetGUID& source, TeleportEntityPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, InteractPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, AnimatePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, UseItemPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, EntityEventPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, PlayerActionPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, RespawnPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, SendInventoryPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, DropItemPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, ContainerSetSlotPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, ContainerClosePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, SignUpdatePacket* packet);
bool allowsIncomingConnections() { return _allowIncoming; }
void allowIncomingConnections(bool doAllow);
Player* popPendingPlayer(const RakNet::RakNetGUID& source);
private:
void redistributePacket(Packet* packet, const RakNet::RakNetGUID& fromPlayer);
void displayGameMessage(const std::string& message);
Player* getPlayer(const RakNet::RakNetGUID& source);
private:
Minecraft* minecraft;
Level* level;
IRakNetInstance* raknetInstance;
RakNet::RakPeerInterface* rakPeer;
std::vector<Player*> _pendingPlayers;
bool _allowIncoming;
};
#endif

View File

@@ -0,0 +1,721 @@
#include "CommandServer.h"
#include "../../client/Minecraft.h"
#include "../../world/level/Level.h"
#include "../../world/entity/Entity.h"
#ifdef WIN32
#define SERR(x) (WSA ## x)
#else
#define SERR(x) (x)
#include <errno.h>
#include <unistd.h>
#endif
#include "../RakNetInstance.h"
#include "../packet/ChatPacket.h"
#include "../packet/AdventureSettingsPacket.h"
#include "../../world/level/LevelSettings.h"
#include "../../world/entity/player/Player.h"
#include "../../client/gamemode/CreatorMode.h"
#include "../../client/player/LocalPlayer.h"
#include "../RakNetInstance.h"
const std::string NullString;
const std::string CommandServer::Ok("\n");
const std::string CommandServer::Fail("Fail\n");
static bool setSocketBlocking(int socket, bool blocking);
// Return value < 0 means socket is shut down / broken
static int Readline(ConnectedClient* client, std::string& out, int maxlen);
static int Writeline(ConnectedClient* client, const std::string& in, int maxlen);
class CameraEntity: public Mob
{
typedef Mob super;
public:
CameraEntity(Level* level)
: super(level),
followEntityId(-1)
{
moveTo(128, 72, 128, 0, 90.0f);
}
void follow(int entityId) {
followEntityId = entityId;
}
void tick() {
if (followEntityId < 0) return;
xOld = xo = x;
yOld = yo = y;
zOld = zo = z;
xRotO = xRot;
yRotO = yRot;
Entity* e = level->getEntity(followEntityId);
if (!e) return;
setPos(e->x, e->y + 6, e->z);
}
int getEntityTypeId() const { return 0; }
private:
int followEntityId;
};
static int getSocketError() {
#ifdef WIN32
return WSAGetLastError();
#else
return errno;
#endif
}
static int t = 0;
template <typename T>
static std::string ToStringOk(const T& a) {
std::stringstream ss;
ss << a << "\n";
return ss.str();
}
template <typename T>
static std::string ToStringOk(const T& a, const T& b) {
std::stringstream ss;
ss << a << "," << b << "\n";
return ss.str();
}
template <typename T>
static std::string ToStringOk(const T& a, const T& b, const T& c) {
std::stringstream ss;
ss << a << "," << b << "," << c << "\n";
return ss.str();
}
static bool inRange(int c, int lowInclusive, int highInclusive) {
return c >= lowInclusive && c <= highInclusive;
}
CommandServer::CommandServer( Minecraft* mc )
: mc(mc),
serverSocket(0),
restoreBuffer(0),
inited(false)
{
camera = new CameraEntity(mc->level);
Pos p = mc->level->getSharedSpawnPos();
apiPosTranslate = OffsetPosTranslator((float)-p.x, (float)-p.y, (float)-p.z);
}
CommandServer::~CommandServer() {
_close();
delete camera;
delete[] restoreBuffer;
}
void CommandServer::_close()
{
if (inited) {
if (serverSocket > 0) {
#ifdef WIN32
closesocket(serverSocket);
#else
close(serverSocket);
#endif
}
inited = false;
serverSocket = 0;
}
}
bool CommandServer::init(short port) {
_close();
if ((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("Failed creating socket - 1\n");
return false;
}
setSocketBlocking(serverSocket, false);
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddress.sin_port = htons(port);
int enabled = 1;
setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&enabled, sizeof(enabled));
if (bind(serverSocket, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) {
printf("Failed binding socket - 2\n");
return false;
}
if (listen(serverSocket, 128) < 0 ) {
printf("Failed listening on socket - 3\n");
return false;
}
LOGI("Listening on port %d\n", port);
inited = true;
return true;
}
std::string CommandServer::parse(ConnectedClient& client, const std::string& s) {
int b = s.find("(");
if (b == std::string::npos) {
return Fail;
}
int e = s.rfind(")");
if (b == std::string::npos) {
return Fail;
}
std::string cmd = s.substr(0, b);
std::string rest = s.substr(b+1, e-b-1);
//
// Block related get, set and query
//
if (cmd == "world.setBlock") {
int x, y, z, id, data;
bool hasData = true;
int c = sscanf(rest.c_str(), "%d,%d,%d,%d,%d", &x, &y, &z, &id, &data);
if (!inRange(c, 4, 5)) return Fail;
if (c == 4) hasData = false;
id &= 255;
if (id > 0 && !Tile::tiles[id])
return Fail;
apiPosTranslate.from(x, y, z);
if (hasData)
mc->level->setTileAndData(x, y, z, id, data & 15);
else
mc->level->setTile(x, y, z, id);
return NullString;
}
if (cmd == "world.getBlock") {
int x, y, z;
if (3 != sscanf(rest.c_str(), "%d,%d,%d", &x, &y, &z)) {
return Fail;
}
apiPosTranslate.from(x, y, z);
return ToStringOk(mc->level->getTile(x, y, z));
}
if (cmd == "world.setBlocks") {
int x0, y0, z0, x1, y1, z1, id, data;
bool hasData = true;
int c = sscanf(rest.c_str(), "%d,%d,%d,%d,%d,%d,%d,%d", &x0, &y0, &z0, &x1, &y1, &z1, &id, &data);
if (!inRange(c, 7, 8)) return Fail;
if (c == 7) hasData = false;
id &= 255;
if (id > 0 && !Tile::tiles[id])
return Fail;
if (x0 > x1) std::swap(x0, x1);
if (y0 > y1) std::swap(y0, y1);
if (z0 > z1) std::swap(z0, z1);
apiPosTranslate.from(x0, y0, z0);
apiPosTranslate.from(x1, y1, z1);
if (x0 < 0) x0 = 0;
if (y0 < 0) y0 = 0;
if (z0 < 0) z0 = 0;
if (x1 >= LEVEL_WIDTH ) x1 = LEVEL_WIDTH - 1;
if (y1 >= LEVEL_HEIGHT) y1 = LEVEL_HEIGHT - 1;
if (z1 >= LEVEL_DEPTH ) z1 = LEVEL_DEPTH - 1;
for (int y = y0; y <= y1; ++y)
for (int z = z0; z <= z1; ++z)
for (int x = x0; x <= x1; ++x) {
if (hasData)
mc->level->setTileAndData(x, y, z, id, data & 15);
else
mc->level->setTile(x, y, z, id);
}
return NullString;
}
if (cmd == "world.getHeight") {
int x, z;
if (2 != sscanf(rest.c_str(), "%d,%d", &x, &z)) {
return Fail;
}
x -= (int)apiPosTranslate.xo;
z -= (int)apiPosTranslate.zo;
const int y = mc->level->getHeightmap(x, z) + (int)apiPosTranslate.yo;
return ToStringOk(y);
}
//
// Player related get, set and query
//
if (cmd == "player.setTile") {
if (!mc->player)
return Fail;
int x, y, z;
if (3 != sscanf(rest.c_str(), "%d,%d,%d", &x, &y, &z)) {
return Fail;
}
apiPosTranslate.from(x, y, z);
Entity* e = (Entity*) mc->player;
e->moveTo((float)x + 0.5f, (float)y, (float)z + 0.5f, e->yRot, e->xRot);
return NullString;
}
if (cmd == "player.getTile") {
if (!mc->player)
return Fail;
Entity* e = (Entity*) mc->player;
int x = (int)e->x, y = (int)(e->y - e->heightOffset), z = (int)e->z;
apiPosTranslate.to(x, y, z);
return ToStringOk(x, y, z);
}
if (cmd == "player.setPos") {
if (!mc->player)
return Fail;
float x, y, z;
if (3 != sscanf(rest.c_str(), "%f,%f,%f", &x, &y, &z)) {
return Fail;
}
apiPosTranslate.from(x, y, z);
Entity* e = (Entity*) mc->player;
e->moveTo(x, y, z, e->yRot, e->xRot);
return NullString;
}
if (cmd == "player.getPos") {
if (!mc->player)
return Fail;
Entity* e = (Entity*) mc->player;
float x = e->x, y = e->y - e->heightOffset, z = e->z;
apiPosTranslate.to(x, y, z);
return ToStringOk(x, y, z);
}
//
// Entity
//
if (cmd == "entity.setTile") {
int id, x, y, z;
if (4 != sscanf(rest.c_str(), "%d,%d,%d,%d", &id, &x, &y, &z)) {
return Fail;
}
Entity* e = mc->level->getEntity(id);
if (!e) return Fail;
apiPosTranslate.from(x, y, z);
e->moveTo((float)x + 0.5f, (float)y, (float)z + 0.5f, e->yRot, e->xRot);
return NullString;
}
if (cmd == "entity.getTile") {
int id;
if (1 != sscanf(rest.c_str(), "%d", &id))
return Fail;
Entity* e = mc->level->getEntity(id);
if (!e) return Fail;
int x = (int)e->x, y = (int)(e->y - e->heightOffset), z = (int)e->z;
apiPosTranslate.to(x, y, z);
return ToStringOk(x, y, z);
}
if (cmd == "entity.setPos") {
int id;
float x, y, z;
if (4 != sscanf(rest.c_str(), "%d,%f,%f,%f", &id, &x, &y, &z)) {
return Fail;
}
Entity* e = mc->level->getEntity(id);
if (!e) return Fail;
apiPosTranslate.from(x, y, z);
e->moveTo(x, y, z, e->yRot, e->xRot);
return NullString;
}
if (cmd == "entity.getPos") {
int id;
if (1 != sscanf(rest.c_str(), "%d", &id))
return Fail;
Entity* e = mc->level->getEntity(id);
if (!e) return Fail;
float x = e->x, y = e->y - e->heightOffset, z = e->z;
apiPosTranslate.to(x, y, z);
return ToStringOk(x, y, z);
}
//
// Chat
//
if (cmd == "chat.post") {
#ifndef STANDALONE_SERVER
mc->gui.addMessage(rest);
#endif
ChatPacket p(rest, false);
dispatchPacket(p);
return NullString;
}
//
// Camera
//
if (cmd == "camera.mode.setFixed") {
camera->follow(-1);
mc->cameraTargetPlayer = camera;
return NullString;
}
if (cmd == "camera.mode.setNormal") {
int entityId = -1;
if (!rest.empty()) {
if (1 != sscanf(rest.c_str(), "%d", &entityId)) return Fail;
}
if (entityId > 0) {
Entity* e = mc->level->getEntity(entityId);
if (e && e->isMob()) mc->cameraTargetPlayer = (Mob*)e;
} else {
mc->cameraTargetPlayer = (Mob*)mc->player;
}
return NullString;
}
if (cmd == "camera.mode.setFollow") {
int entityId = -1;
if (!rest.empty()) {
if (1 != sscanf(rest.c_str(), "%d", &entityId)) return Fail;
}
if (entityId < 0) entityId = mc->player->entityId;
camera->follow(entityId);
mc->cameraTargetPlayer = camera;
return NullString;
}
if (cmd == "camera.setPos") {
float x, y, z;
if (3 != sscanf(rest.c_str(), "%f,%f,%f", &x, &y, &z)) {
return Fail;
}
apiPosTranslate.from(x, y, z);
Entity* e = (Entity*) mc->cameraTargetPlayer;
e->moveTo((float)x + 0.5f, (float)y, (float)z + 0.5f, e->yRot, e->xRot);
return NullString;
}
//
// Entities
//
if (cmd == "world.getPlayerIds") {
std::stringstream s;
int size = mc->level->players.size();
for (int i = 0; i < size; ++i) {
if (i != 0) s << "|";
s << mc->level->players[i]->entityId;
}
s << "\n";
return s.str();
}
//
// Set and restore Checkpoint
//
if (cmd == "world.checkpoint.save") {
if (mc->player) {
Entity* e = (Entity*) mc->player;
static Stopwatch sw;
sw.start();
// Save a cuboid around the player
const int CSize = CHUNK_CACHE_WIDTH;
int cx = (int)e->x / CSize;
int cz = (int)e->z / CSize;
restorePos = Pos(cx, (int)e->y - 8, cz);
handleCheckpoint(false);
sw.stop();
sw.printEvery(1, "set-checkpoint");
}
}
if (cmd == "world.checkpoint.restore") {
bool success = handleCheckpoint(true);
if (success) {
int xx = 16 * (restorePos.x - 2);
int zz = 16 * (restorePos.z - 2);
mc->level->setTilesDirty(xx, restorePos.y, zz,
xx + 5 * 16, restorePos.y + RestoreHeight, zz + 5 * 16);
}
return success? NullString : Fail;
}
//
// Event queries
//
if (cmd.find("events.") == 0) {
return handleEventPollMessage(client, cmd);
}
// Settings
if (cmd.find("player.setting") == 0
|| cmd.find("world.setting") == 0) {
int value;
static char name[1024];
if (rest.find(",") >= 100) return Fail;
if (2 != sscanf(rest.c_str(), "%[^,],%d", name, &value)) return Fail;
return handleSetSetting(name, value);
}
return NullString;
}
bool CommandServer::handleCheckpoint(bool doRestore ) {
const int cx = restorePos.x;
const int cz = restorePos.z;
const int y0 = restorePos.y;
const int y1 = y0 + RestoreHeight;
const int CSize = CHUNK_CACHE_WIDTH;
const int numChunkBytes = RestoreHeight * CSize * CSize * 20 / 8;
if (!restoreBuffer) {
if (doRestore) return false;
int numBytes = 5 * 5 * numChunkBytes;
restoreBuffer = new unsigned char[numBytes];
}
int offset = 0;
for (int z = cz - 2; z <= cz + 2; ++z)
for (int x = cx - 2; x <= cx + 2; ++x) {
LevelChunk* c = mc->level->getChunk(x, z);
if (!c) continue;
if (doRestore) {
//LOGI("restoring: %d, %d\n", x, z);
c->setBlocksAndData(restoreBuffer, 0, y0, 0, CSize, y1, CSize, offset);
} else {
//LOGI("saving: %d, %d\n", x, z);
c->getBlocksAndData(restoreBuffer, 0, y0, 0, CSize, y1, CSize, offset);
}
offset += numChunkBytes;
}
return true;
}
void CommandServer::tick() {
if (!inited)
return;
_updateAccept();
_updateClients();
++t;
if (mc->cameraTargetPlayer == camera) {
camera->tick();
}
}
void CommandServer::_updateAccept() {
int fd = accept(serverSocket, NULL, NULL);
if (fd == -1) {
int err = getSocketError();
if (err != SERR(EWOULDBLOCK)) {
LOGE("Error when trying to accept connections. Error ID: %d\n", err);
}
return;
}
setSocketBlocking(fd, false);
clients.push_back(ConnectedClient(fd));
ConnectedClient& c = clients[clients.size()-1];
c.lastPoll_blockHit = mc->level->getTime();
}
void CommandServer::_updateClients() {
for (int i = clients.size() - 1; i >= 0; --i) {
if (!_updateClient(clients[i]))
clients.erase(clients.begin() + i);
}
}
bool CommandServer::_updateClient(ConnectedClient& client) {
std::string line;
int maxReadCount = 32;
while (--maxReadCount >= 0) {
int ret = Readline(&client, line, 1024);
//printf("Read: %s @ %d\n", client.data.c_str(), t);
if (ret)
return ret > 0;
std::string response = parse(client, line);
if (NullString != response)
if (Writeline(&client, response, 1024) < 0)
return false;
}
return true;
}
void CommandServer::dispatchPacket( Packet& p ) {
if (!mc->netCallback || !mc->player) return;
const RakNet::RakNetGUID& guid = ((Player*)mc->player)->owner;
mc->raknetInstance->send(p);
//p.handle(guid, mc->netCallback);
}
std::string CommandServer::handleEventPollMessage( ConnectedClient& client, const std::string& cmd ) {
ICreator* c = mc->getCreator();
if (!c) {
return Fail;
}
if (cmd == "events.clear") {
long t = mc->level->getTime();
client.lastPoll_blockHit = t;
return NullString;
}
if (cmd == "events.block.hits") {
ICreator::EventList<ICreator::TileEvent>& events = c->getTileEvents();
std::stringstream ss;
events.write(ss, apiPosTranslate, client.lastPoll_blockHit);
client.lastPoll_blockHit = mc->level->getTime();
ss << "\n";
return ss.str();
}
return Fail;
}
void updateAdventureSettingFlag(Minecraft* mc, AdventureSettingsPacket::Flags flag, bool status) {
AdventureSettingsPacket p(mc->level->adventureSettings);
p.set(flag, status);
p.fillIn(mc->level->adventureSettings);
mc->raknetInstance->send(p);
}
std::string CommandServer::handleSetSetting( const std::string& setting, int value )
{
bool status = value != 0;
if (setting == "autojump") mc->player->autoJumpEnabled = status;
AdventureSettingsPacket::Flags flag = (AdventureSettingsPacket::Flags)0;
if (setting == "nametags_visible") flag = AdventureSettingsPacket::ShowNameTags;
if (setting == "world_immutable") flag = AdventureSettingsPacket::WorldImmutable;
if (flag != 0)
updateAdventureSettingFlag(mc, flag, status);
return NullString;
}
bool setSocketBlocking(int socket, bool blocking) {
if (socket< 0) {
return false;
}
#ifdef WIN32
unsigned long mode = blocking ? 0 : 1;
return (ioctlsocket(socket, FIONBIO, &mode) == 0) ? true : false;
#else
int flags = fcntl(socket, F_GETFL, 0);
if (flags < 0) return false;
flags = blocking ? (flags & ~O_NONBLOCK) : (flags|O_NONBLOCK);
return (fcntl(socket, F_SETFL, flags) == 0) ? true : false;
#endif
}
int Readline(ConnectedClient* client, std::string& out, int maxlen) {
static char data[2048];
char* buffer = data;
if (!client->data.empty()) {
memcpy(data, client->data.c_str(), client->data.length());
client->data.clear();
}
bool socketError = false;
for (int n = 1; n < maxlen; n++ ) {
int rc;
char c;
if ( (rc = recv(client->socket, &c, 1, 0)) == 1 ) {
*buffer++ = c;
if ( c == '\n' ) {
*buffer = 0;
out.assign(data, buffer + 1);
return 0;
}
}
else if ( rc == 0 ) {
socketError = true;
break;
}
else if ( rc == -1) {
int err = getSocketError();
if (err == SERR(EINTR))
continue;
socketError = (err != SERR(EWOULDBLOCK));
break;
} else {
break;
}
}
client->data.assign(data, buffer + 1);
return socketError? -1 : 1;
}
int Writeline(ConnectedClient* client, const std::string& in, int maxlen) {
size_t left = in.length();
const char *buffer = in.c_str();
while ( left > 0 ) {
int n;
if ( (n = send(client->socket, buffer, left, 0)) <= 0 ) {
int err = getSocketError();
if (err == SERR(EINTR))
n = 0;
else
return (err == SERR(EWOULDBLOCK))? 1 : -1;
}
left -= n;
buffer += n;
}
return 0;
}

View File

@@ -0,0 +1,77 @@
#ifndef COMMANDSERVER_H__
#define COMMANDSERVER_H__
#include <string>
#include <vector>
#ifdef WIN32
#include <WinSock2.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include "../../world/PosTranslator.h"
#include "../../world/Pos.h"
class Minecraft;
class Packet;
class CameraEntity;
class ConnectedClient {
public:
ConnectedClient(int socketFd)
: socket(socketFd),
lastPoll_blockHit(0)
{
}
int socket;
std::string data;
int lastPoll_blockHit;
};
class CommandServer {
public:
CommandServer(Minecraft* mc);
~CommandServer();
bool init(short port);
void tick();
//void update();
private:
std::string parse(ConnectedClient& client, const std::string& s);
void _close();
void _updateAccept();
void _updateClients();
// return true if client is in error/should be removed, false if not
bool _updateClient(ConnectedClient& client);
bool handleCheckpoint(bool doRestore);
void dispatchPacket(Packet& p);
std::string handleEventPollMessage( ConnectedClient& client, const std::string& cmd );
std::string handleSetSetting(const std::string& setting, int value);
bool inited;
int serverSocket;
struct sockaddr_in serverAddress;
Minecraft* mc;
OffsetPosTranslator apiPosTranslate;
static const int RestoreHeight = 48;
unsigned char* restoreBuffer;
Pos restorePos;
CameraEntity* camera;
std::vector<ConnectedClient> clients;
static const std::string Ok;
static const std::string Fail;
};
#endif /*COMMANDSERVER_H__*/

View File

@@ -0,0 +1,93 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__AddEntityPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__AddEntityPacket_H__
#include "../Packet.h"
#include "../../world/entity/Entity.h"
class AddEntityPacket : public Packet
{
public:
AddEntityPacket() {}
AddEntityPacket(const Entity* e, int data = 0)
: entityId(e->entityId),
type(e->getEntityTypeId()),
x(e->x),
y(e->y),
z(e->z),
_data(data)
{
if (hasMovementData()) {
xd = e->xd;
yd = e->yd;
zd = e->zd;
}
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_ADDENTITY));
bitStream->Write(entityId);
unsigned char bType = (unsigned char)type;
bitStream->Write(bType);
bitStream->Write(x);
bitStream->Write(y);
bitStream->Write(z);
bitStream->Write(_data);
if (hasMovementData()) {
const float M = 3.9f;
short xa = (short)(8000.0f * Mth::clamp(xd, -M, M));
short ya = (short)(8000.0f * Mth::clamp(yd, -M, M));
short za = (short)(8000.0f * Mth::clamp(zd, -M, M));
bitStream->Write(xa);
bitStream->Write(ya);
bitStream->Write(za);
}
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(entityId);
unsigned char bType;
bitStream->Read(bType);
type = bType;
bitStream->Read(x);
bitStream->Read(y);
bitStream->Read(z);
bitStream->Read(_data);
if (hasMovementData()) {
short xa, ya, za;
bitStream->Read(xa);
bitStream->Read(ya);
bitStream->Read(za);
xd = xa / 8000.0f;
yd = ya / 8000.0f;
zd = za / 8000.0f;
}
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (AddEntityPacket*)this);
}
bool hasMovementData() {
return _data > 0;
}
int data() {
return _data;
}
public:
int entityId;
float x, y, z;
float xd, yd, zd;
int type;
private:
int _data;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__AddEntityPacket_H__*/

View File

@@ -0,0 +1,78 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__AddItemEntityPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__AddItemEntityPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
#include "../../world/entity/item/ItemEntity.h"
#include "../../world/item/ItemInstance.h"
#include "../../util/Mth.h"
class AddItemEntityPacket: public Packet {
public:
AddItemEntityPacket() {
}
AddItemEntityPacket(const ItemEntity* itemEntity)
: id(itemEntity->entityId),
itemId(itemEntity->item.id),
itemCount(itemEntity->item.count),
auxValue(itemEntity->item.getAuxValue()),
x(itemEntity->x),
y(itemEntity->y),
z(itemEntity->z),
_xa((signed char) (itemEntity->xd * 128.0)),
_ya((signed char) (itemEntity->yd * 128.0)),
_za((signed char) (itemEntity->zd * 128.0))
{
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(id);
bitStream->Read(itemId);
bitStream->Read(itemCount);
bitStream->Read(auxValue);
bitStream->Read(x);
bitStream->Read(y);
bitStream->Read(z);
bitStream->Read(_xa);
bitStream->Read(_ya);
bitStream->Read(_za);
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_ADDITEMENTITY));
bitStream->Write(id);
bitStream->Write(itemId);
bitStream->Write(itemCount);
bitStream->Write(auxValue);
bitStream->Write(x);
bitStream->Write(y);
bitStream->Write(z);
bitStream->Write(_xa);
bitStream->Write(_ya);
bitStream->Write(_za);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (AddItemEntityPacket*)this);
}
float xa() { return (float)(_xa) / 128.0f; }
float ya() { return (float)(_ya) / 128.0f; }
float za() { return (float)(_za) / 128.0f; }
int id;
float x, y, z;
short itemId;
short auxValue;
unsigned char itemCount;
private:
signed char _xa, _ya, _za;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__AddItemEntityPacket_H__*/

View File

@@ -0,0 +1,78 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__AddMobPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__AddMobPacket_H__
#include "../Packet.h"
#include "../../world/entity/Mob.h"
#include "../../util/RakDataIO.h"
class AddMobPacket : public Packet
{
public:
AddMobPacket()
: _entityData(NULL)
{
}
~AddMobPacket() {
for (unsigned int i = 0; i < unpack.size(); ++i)
delete unpack[i];
}
AddMobPacket(const Mob* mob)
: entityId(mob->entityId),
type(mob->getEntityTypeId()),
x(mob->x),
y(mob->y),
z(mob->z),
xRot(mob->xRot),
yRot(mob->yRot),
_entityData(mob->getEntityData())
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_ADDMOB));
bitStream->Write(entityId);
bitStream->Write(type);
bitStream->Write(x);
bitStream->Write(y);
bitStream->Write(z);
bitStream->Write(PacketUtil::Rot_degreesToChar(yRot));
bitStream->Write(PacketUtil::Rot_degreesToChar(xRot));
RakDataOutput dos(*bitStream);
_entityData->packAll(&dos);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(entityId);
bitStream->Read(type);
bitStream->Read(x);
bitStream->Read(y);
bitStream->Read(z);
char rx, ry;
bitStream->Read(ry);
bitStream->Read(rx);
RakDataInput dis(*bitStream);
unpack = SynchedEntityData::unpack(&dis);
yRot = PacketUtil::Rot_degreesToChar(ry);
xRot = PacketUtil::Rot_charToDegrees(rx);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (AddMobPacket*)this);
}
public:
int entityId;
int type;
float x, y, z;
float xRot, yRot;
SynchedEntityData::DataList unpack;
private:
const SynchedEntityData* _entityData;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__AddMobPacket_H__*/

View File

@@ -0,0 +1,48 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__AddPaintingPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__AddPaintingPacket_H__
#include "../Packet.h"
#include "../../world/entity/Painting.h"
class AddPaintingPacket : public Packet {
public:
AddPaintingPacket() : entityId(0), xTile(0), yTile(0), zTile(0), dir(-1) {
}
AddPaintingPacket(Painting* painting) {
entityId = painting->entityId;
xTile = painting->xTile;
yTile = painting->yTile;
zTile = painting->zTile;
dir = painting->dir;
motive = painting->motive->name;
}
void write(RakNet::BitStream* bitStream) {
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_ADDPAINTING));
bitStream->Write(entityId);
bitStream->Write(xTile);
bitStream->Write(yTile);
bitStream->Write(zTile);
bitStream->Write(dir);
RakNet::RakString rakMotive(motive.c_str());
bitStream->Write(rakMotive);
}
void read(RakNet::BitStream* bitStream) {
bitStream->Read(entityId);
bitStream->Read(xTile);
bitStream->Read(yTile);
bitStream->Read(zTile);
bitStream->Read(dir);
RakNet::RakString rakMotive;
bitStream->Read(rakMotive);
motive = std::string(rakMotive.C_String());
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) {
callback->handle(source, (AddPaintingPacket*)this);
}
public:
int entityId;
int xTile, yTile, zTile;
int dir;
std::string motive;
};
#endif /* NET_MINECRAFT_NETWORK_PACKET__AddPaintingPacket_H__ */

View File

@@ -0,0 +1,93 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__AddPlayerPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__AddPlayerPacket_H__
#include "../Packet.h"
#include "../../world/entity/player/Player.h"
#include "../../world/entity/player/Inventory.h"
class AddPlayerPacket : public Packet
{
public:
AddPlayerPacket()
: _entityData(NULL)
{}
AddPlayerPacket(const Player* p)
: owner(p->owner),
name(p->name.c_str()),
entityId(p->entityId),
x(p->x),
y(p->y - p->heightOffset),
z(p->z),
xRot(p->xRot),
yRot(p->yRot),
carriedItemId(0),
carriedItemAuxValue(0),
_entityData(p->getEntityData())
{
if (ItemInstance* item = p->inventory->getSelected()) {
carriedItemId = item->id;
carriedItemAuxValue = item->getAuxValue();
}
}
~AddPlayerPacket() {
for (unsigned int i = 0; i < unpack.size(); ++i)
delete unpack[i];
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_ADDPLAYER));
bitStream->Write(owner);
bitStream->Write(name);
bitStream->Write(entityId);
bitStream->Write(x);
bitStream->Write(y);
bitStream->Write(z);
bitStream->Write(PacketUtil::Rot_degreesToChar(yRot));
bitStream->Write(PacketUtil::Rot_degreesToChar(xRot));
bitStream->Write(carriedItemId);
bitStream->Write(carriedItemAuxValue);
RakDataOutput dos(*bitStream);
_entityData->packAll(&dos);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(owner);
bitStream->Read(name);
bitStream->Read(entityId);
bitStream->Read(x);
bitStream->Read(y);
bitStream->Read(z);
char rx, ry;
bitStream->Read(ry);
bitStream->Read(rx);
bitStream->Read(carriedItemId);
bitStream->Read(carriedItemAuxValue);
RakDataInput dis(*bitStream);
unpack = SynchedEntityData::unpack(&dis);
yRot = PacketUtil::Rot_degreesToChar(ry);
xRot = PacketUtil::Rot_charToDegrees(rx);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (AddPlayerPacket*)this);
}
RakNet::RakNetGUID owner;
RakNet::RakString name;
int entityId;
float x, y, z;
float xRot, yRot;
short carriedItemId;
short carriedItemAuxValue;
SynchedEntityData::DataList unpack;
private:
const SynchedEntityData* _entityData;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__AddPlayerPacket_H__*/

View File

@@ -0,0 +1,67 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__AdventureSettingsPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__AdventureSettingsPacket_H__
#include "../Packet.h"
#include "../../world/level/Level.h"
class AdventureSettingsPacket: public Packet
{
public:
enum Flags {
WorldImmutable = 1,
NoPvP = 2,
NoPvM = 4,
NoMvP = 8,
StaticTime = 16,
ShowNameTags = 32,
};
AdventureSettingsPacket() {}
AdventureSettingsPacket(const AdventureSettings& settings)
: flags(0)
{
set(WorldImmutable, settings.immutableWorld);
set(NoPvP, settings.noPvP);
set(NoPvM, settings.noPvM);
set(NoMvP, settings.noMvP);
set(StaticTime, !settings.doTickTime);
set(ShowNameTags, settings.showNameTags);
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_ADVENTURESETTINGS));
bitStream->Write(flags);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(flags);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (AdventureSettingsPacket*)this);
}
void fillIn( AdventureSettings& adventureSettings ) const
{
adventureSettings.immutableWorld= isSet(WorldImmutable);
adventureSettings.noPvP = isSet(NoPvP);
adventureSettings.noPvM = isSet(NoPvM);
adventureSettings.noMvP = isSet(NoMvP);
adventureSettings.doTickTime = !isSet(StaticTime);
adventureSettings.showNameTags = isSet(ShowNameTags);
}
unsigned int flags;
void set(Flags flag, bool status) { status? set(flag) : clear(flag); }
void set(Flags flag) { flags |= flag; }
void toggle(Flags flag){ flags ^= flag; }
void clear(Flags flag) { flags &= ~flag; }
bool isSet(Flags flag) const { return (flags & flag) != 0; }
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__AdventureSettingsPacket_H__*/

View File

@@ -0,0 +1,46 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__AnimatePacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__AnimatePacket_H__
#include "../Packet.h"
class AnimatePacket: public Packet
{
public:
static const int Swing = 1;
static const int WAKE_UP = 3;
int entityId;
char action;
AnimatePacket() {}
AnimatePacket(int action, int entityId)
: action(action),
entityId(entityId)
{}
AnimatePacket(int action, Entity* e)
: action(action),
entityId(e->entityId)
{}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_ANIMATE));
bitStream->Write(action);
bitStream->Write(entityId);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(action);
bitStream->Read(entityId);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (AnimatePacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__AnimatePacket_H__*/

41
src/network/packet/ChatPacket.h Executable file
View File

@@ -0,0 +1,41 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__ChatPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__ChatPacket_H__
#include "../Packet.h"
#include "../..//world/entity/player/Player.h"
class ChatPacket: public Packet
{
public:
static const int MAX_CHAT_LENGTH = 100;
static const int MAX_LENGTH = MAX_CHAT_LENGTH + Player::MAX_NAME_LENGTH;
ChatPacket() {
}
ChatPacket(std::string message, bool isSystem = true) {
if(message.length() > MAX_LENGTH) {
message = message.substr(0, MAX_LENGTH);
}
this->message = message;
this->isSystem = isSystem;
}
void write(RakNet::BitStream* bitStream) {
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_CHAT));
bitStream->Write(message.c_str());
}
void read(RakNet::BitStream* bitStream) {
char buff[MAX_LENGTH + 30];
bitStream->Read(buff);
message = buff;
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) {
callback->handle(source, (ChatPacket*)this);
}
std::string message;
bool isSystem;
};
#endif /* NET_MINECRAFT_NETWORK_PACKET__ChatPacket_H__ */

View File

@@ -0,0 +1,77 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__ChunkDataPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__ChunkDataPacket_H__
#include "../Packet.h"
#include "../../world/level/chunk/LevelChunk.h"
class ChunkDataPacket : public Packet
{
public:
int x, z;
RakNet::BitStream chunkData;
LevelChunk* chunk;
ChunkDataPacket()
{
}
ChunkDataPacket(int x, int z, LevelChunk* chunk)
: x(x),
z(z),
chunk(chunk)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_CHUNKDATA));
bitStream->Write(x);
bitStream->Write(z);
unsigned char* blockIds = chunk->getBlockData();
DataLayer& blockData = chunk->data;
const int setSize = LEVEL_HEIGHT / 8;
const int setShift = 4; // power of LEVEL_HEIGHT / 8
chunkData.Reset();
for (int i = 0; i < CHUNK_COLUMNS; i++)
{
unsigned char updateBits = chunk->updateMap[i];
chunkData.Write(updateBits);
if (updateBits > 0)
{
int colDataPosition = (i % CHUNK_WIDTH) << 11 | (i / CHUNK_WIDTH) << 7;
for (int set = 0; set < 8; set++)
{
if ((updateBits & (1 << set)) != 0)
{
chunkData.Write((const char*)(&blockIds[colDataPosition + (set << setShift)]), setSize);
// block data is only 4 bits per block
chunkData.Write((const char*)(&blockData.data[(colDataPosition + (set << setShift)) >> 1]), setSize >> 1);
}
}
}
}
bitStream->Write(chunkData);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(x);
bitStream->Read(z);
bitStream->Read(chunkData);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (ChunkDataPacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__ChunkDataPacket_H__*/

View File

@@ -0,0 +1,43 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__ContainerAckPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__ContainerAckPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
class ContainerAckPacket: public Packet
{
public:
ContainerAckPacket() {
}
ContainerAckPacket(int containerId, short uid, bool accepted)
: containerId(containerId),
uid(uid),
accepted(accepted)
{
}
void write(RakNet::BitStream* bitStream) {
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_CONTAINERACK));
bitStream->Write(containerId);
bitStream->Write(uid);
bitStream->Write(accepted);
}
void read(RakNet::BitStream* bitStream) {
bitStream->Read(containerId);
bitStream->Read(uid);
bitStream->Read(accepted);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) {
callback->handle(source, (ContainerAckPacket*)this);
}
short uid;
unsigned char containerId;
bool accepted;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__ContainerAckPacket_H__*/

View File

@@ -0,0 +1,35 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__ContainerClosePacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__ContainerClosePacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
class ContainerClosePacket: public Packet
{
public:
ContainerClosePacket() {
}
ContainerClosePacket(int containerId)
: containerId(containerId)
{
}
void read(RakNet::BitStream* bitStream) {
bitStream->Read(containerId);
}
void write(RakNet::BitStream* bitStream) {
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_CONTAINERCLOSE));
bitStream->Write(containerId);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) {
callback->handle(source, (ContainerClosePacket*)this);
}
unsigned char containerId;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__ContainerClosePacket_H__*/

View File

@@ -0,0 +1,47 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__ContainerOpenPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__ContainerOpenPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
class ContainerOpenPacket: public Packet
{
public:
ContainerOpenPacket() {
}
ContainerOpenPacket(int containerId, int type, const std::string& title, int size)
: containerId(containerId),
type(type),
title(title.c_str()),
size(size)
{
}
void write(RakNet::BitStream* bitStream) {
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_CONTAINEROPEN));
bitStream->Write(containerId);
bitStream->Write(type);
bitStream->Write(size);
bitStream->Write(title);
}
void read(RakNet::BitStream* bitStream) {
bitStream->Read(containerId);
bitStream->Read(type);
bitStream->Read(size);
bitStream->Read(title);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) {
callback->handle(source, (ContainerOpenPacket*)this);
}
RakNet::RakString title;
unsigned char containerId;
unsigned char type;
unsigned char size;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__ContainerOpenPacket_H__*/

View File

@@ -0,0 +1,44 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__ContainerSetContentPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__ContainerSetContentPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
class ContainerSetContentPacket: public Packet
{
public:
ContainerSetContentPacket() {
}
ContainerSetContentPacket(int containerId, const std::vector<ItemInstance>& newItems)
: containerId(containerId),
items(newItems.begin(), newItems.end())
{
}
void write(RakNet::BitStream* bitStream) {
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_CONTAINERSETCONTENT));
bitStream->Write(containerId);
bitStream->Write((short)items.size());
for (unsigned int i = 0; i < items.size(); ++i)
PacketUtil::writeItemInstance(items[i], bitStream);
}
void read(RakNet::BitStream* bitStream) {
bitStream->Read(containerId);
short numItems;
bitStream->Read(numItems);
for (int i = 0; i < numItems; ++i)
items.push_back( PacketUtil::readItemInstance(bitStream) );
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) {
callback->handle(source, (ContainerSetContentPacket*)this);
}
unsigned char containerId;
std::vector<ItemInstance> items;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__ContainerSetContentPacket_H__*/

View File

@@ -0,0 +1,43 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__ContainerSetDataPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__ContainerSetDataPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
class ContainerSetDataPacket: public Packet
{
public:
ContainerSetDataPacket() {
}
ContainerSetDataPacket(int containerId, int id, int value)
: containerId(containerId),
id(id),
value(value)
{
}
void write(RakNet::BitStream* bitStream) {
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_CONTAINERSETDATA));
bitStream->Write(containerId);
bitStream->Write(id);
bitStream->Write(value);
}
void read(RakNet::BitStream* bitStream) {
bitStream->Read(containerId);
bitStream->Read(id);
bitStream->Read(value);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) {
callback->handle(source, (ContainerSetDataPacket*)this);
}
short id;
short value;
unsigned char containerId;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__ContainerSetDataPacket_H__*/

View File

@@ -0,0 +1,64 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__ContainerSetSlotPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__ContainerSetSlotPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
#include "../../world/item/ItemInstance.h"
// Note: This can be seen as "ContainerWantSetSlotPacket" when sent from
// client to server. Currently, the client handles side-effects relating
// to it's own inventory, regardless of the success of the operation.
class ContainerSetSlotPacket: public Packet
{
public:
static const char SETTYPE_SET = 0;
static const char SETTYPE_ADD = 1;
//static const int SETTYPE_SUB = 2;
static const char SETTYPE_TAKE = 5;
ContainerSetSlotPacket() {
}
//@todo: pointer parameter?
ContainerSetSlotPacket(int containerId, int slot, const ItemInstance& item)
: containerId(containerId),
slot(slot),
item(item),
setType(SETTYPE_SET)
//item(item? *item : ItemInstance())
{
}
ContainerSetSlotPacket(char setType, int containerId, int slot, const ItemInstance& item)
: setType(setType),
containerId(containerId),
slot(slot),
item(item)
//item(item? *item : ItemInstance())
{
}
void write(RakNet::BitStream* bitStream) {
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_CONTAINERSETSLOT));
bitStream->Write(containerId);
bitStream->Write(slot);
PacketUtil::writeItemInstance(item, bitStream);
}
void read(RakNet::BitStream* bitStream) {
bitStream->Read(containerId);
bitStream->Read(slot);
item = PacketUtil::readItemInstance(bitStream);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) {
callback->handle(source, (ContainerSetSlotPacket*)this);
}
unsigned char setType;
unsigned char containerId;
short slot;
ItemInstance item;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__ContainerSetSlotPacket_H__*/

View File

@@ -0,0 +1,45 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__DropItemPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__DropItemPacket_H__
#include "../Packet.h"
class DropItemPacket: public Packet
{
public:
DropItemPacket()
{
}
DropItemPacket(int entityId, const ItemInstance& item)
: entityId(entityId),
item(item),
dropType(0)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_DROPITEM));
bitStream->Write(entityId);
bitStream->Write(dropType);
PacketUtil::writeItemInstance(item, bitStream);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(entityId);
bitStream->Read(dropType);
item = PacketUtil::readItemInstance(bitStream);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (DropItemPacket*)this);
}
int entityId;
unsigned char dropType;
ItemInstance item;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__DropItemPacket_H__*/

View File

@@ -0,0 +1,40 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__EntityEventPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__EntityEventPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
class EntityEventPacket: public Packet {
public:
EntityEventPacket() {}
EntityEventPacket(int entityId, char eventId)
: entityId(entityId),
eventId(eventId)
{}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_ENTITYEVENT));
bitStream->Write(entityId);
bitStream->Write(eventId);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(entityId);
bitStream->Read(eventId);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (EntityEventPacket*)this);
}
int entityId;
unsigned char eventId;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__EntityEventPacket_H__*/

View File

@@ -0,0 +1,76 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__ExplodePacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__ExplodePacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
#include "../../world/level/Explosion.h"
class ExplodePacket: public Packet
{
public:
float x, y, z;
float r;
std::vector<TilePos> toBlow;
ExplodePacket() {}
ExplodePacket(float x, float y, float z, float r, const TilePosSet& tiles)
: x(x),
y(y),
z(z),
r(r),
toBlow(tiles.begin(), tiles.end())
{}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_EXPLODE));
bitStream->Write(x);
bitStream->Write(y);
bitStream->Write(z);
bitStream->Write(r);
int xp = (int)x;
int yp = (int)y;
int zp = (int)z;
int count = (int)toBlow.size();
bitStream->Write(count);
for (int i = 0; i < count; ++i) {
const TilePos& tp = toBlow[i];
bitStream->Write((signed char)(tp.x - xp));
bitStream->Write((signed char)(tp.y - yp));
bitStream->Write((signed char)(tp.z - zp));
}
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(x);
bitStream->Read(y);
bitStream->Read(z);
bitStream->Read(r);
int xp = (int)x;
int yp = (int)y;
int zp = (int)z;
// Write the tileset for the exploded tiles
int count;
bitStream->Read(count);
toBlow.reserve(count);
for (int i = 0; i < count; ++i) {
signed char xx,yy,zz;
bitStream->Read(xx);
bitStream->Read(yy);
bitStream->Read(zz);
toBlow.push_back( TilePos(xp + xx, yp + yy, zp + zz) );
}
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (ExplodePacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__ExplodePacket_H__*/

View File

@@ -0,0 +1,32 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__HurtArmorPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__HurtArmorPacket_H__
#include "../Packet.h"
class HurtArmorPacket: public Packet
{
public:
HurtArmorPacket() {}
HurtArmorPacket(int dmg)
: dmg(dmg)
{}
void write(RakNet::BitStream* bitStream) {
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_HURTARMOR));
bitStream->Write(dmg);
}
void read(RakNet::BitStream* bitStream) {
bitStream->Read(dmg);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) {
callback->handle(source, (HurtArmorPacket*)this);
}
signed char dmg;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__HurtArmorPacket_H__*/

View File

@@ -0,0 +1,47 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__InteractPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__InteractPacket_H__
#include "../Packet.h"
class InteractPacket : public Packet
{
public:
static const int Interact = 1;
static const int Attack = 2;
char action;
int sourceId;
int targetId;
InteractPacket() {
}
InteractPacket(char action, int sourceId, int targetId)
: action(action),
sourceId(sourceId),
targetId(targetId)
{}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_INTERACT));
bitStream->Write(action);
bitStream->Write(sourceId);
bitStream->Write(targetId);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(action);
bitStream->Read(sourceId);
bitStream->Read(targetId);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (InteractPacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__InteractPacket_H__*/

View File

@@ -0,0 +1,49 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__LevelEventPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__LevelEventPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
class LevelEventPacket: public Packet {
public:
LevelEventPacket() {}
LevelEventPacket(int eventId, int x, int y, int z, int data)
: eventId(eventId),
x(x),
y(y),
z(z),
data(data)
{}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_LEVELEVENT));
bitStream->Write(eventId);
bitStream->Write(x);
bitStream->Write(y);
bitStream->Write(z);
bitStream->Write(data);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(eventId);
bitStream->Read(x);
bitStream->Read(y);
bitStream->Read(z);
bitStream->Read(data);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (LevelEventPacket*)this);
}
short eventId;
short x, y, z;
int data;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__LevelEventPacket_H__*/

View File

@@ -0,0 +1,51 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__LoginPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__LoginPacket_H__
#include "../Packet.h"
class LoginPacket : public Packet
{
public:
RakNet::RakString clientName;
int clientNetworkVersion;
int clientNetworkLowestSupportedVersion;
LoginPacket()
: clientNetworkVersion(-1),
clientNetworkLowestSupportedVersion(-1)
{
}
LoginPacket(const RakNet::RakString& clientName, int clientVersion)
: clientName(clientName),
clientNetworkVersion(clientVersion),
clientNetworkLowestSupportedVersion(clientVersion)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_LOGIN));
bitStream->Write(clientName);
bitStream->Write(clientNetworkVersion);
bitStream->Write(clientNetworkLowestSupportedVersion);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(clientName);
// First versions didn't send the client version
//LOGI("unread: %d\n", bitStream->GetNumberOfUnreadBits());
if (bitStream->GetNumberOfUnreadBits() > 0) {
bitStream->Read(clientNetworkVersion);
bitStream->Read(clientNetworkLowestSupportedVersion);
}
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (LoginPacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__LoginPacket_H__*/

View File

@@ -0,0 +1,40 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__LoginStatusPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__LoginStatusPacket_H__
#include "../Packet.h"
namespace LoginStatus {
const int Success = 0;
const int Failed_ClientOld = 1;
const int Failed_ServerOld = 2;
}
class LoginStatusPacket : public Packet {
public:
LoginStatusPacket()
{
}
LoginStatusPacket(int status)
: status(status)
{}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_LOGINSTATUS));
bitStream->Write(status);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(status);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (LoginStatusPacket*)this);
}
int status;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__LoginStatusPacket_H__*/

View File

@@ -0,0 +1,39 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__MessagePacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__MessagePacket_H__
#include "../Packet.h"
class MessagePacket : public Packet
{
public:
RakNet::RakString message;
MessagePacket()
{
}
MessagePacket(const RakNet::RakString& message)
: message(message)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_MESSAGE));
bitStream->Write(message);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(message);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (MessagePacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__MessagePacket_H__*/

View File

@@ -0,0 +1,78 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__MoveEntityPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__MoveEntityPacket_H__
#include "../Packet.h"
class MoveEntityPacket: public Packet
{
public:
MoveEntityPacket()
: hasRot(false)
{}
// PACKET_MOVEENTITY is unknown and undefined (and not used)
void write(RakNet::BitStream* bitStream) {
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_MOVEENTITY));
}
void read(RakNet::BitStream* bitStream) {};
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (MoveEntityPacket*)this);
}
int entityId;
float x, y, z;
float xRot;
float yRot;
bool hasRot;
};
class MoveEntityPacket_PosRot: public MoveEntityPacket
{
typedef MoveEntityPacket super;
public:
MoveEntityPacket_PosRot() {
hasRot = true;
}
//MoveEntityPacket_PosRot(int entityId, float x, float y, float z, float yRot, float xRot) {
// set(entityId, x, y, z, yRot, xRot);
//}
MoveEntityPacket_PosRot(const Entity* e) {
set(e->entityId, e->x, e->y - e->heightOffset, e->z, e->yRot, e->xRot);
}
void set(int entityId, float x, float y, float z, float yRot, float xRot) {
this->entityId = entityId;
this->x = x;
this->y = y;
this->z = z;
this->xRot = xRot;
this->yRot = yRot;
}
void write(RakNet::BitStream* bitStream) {
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_MOVEENTITY_POSROT));
bitStream->Write(entityId);
bitStream->Write(x);
bitStream->Write(y);
bitStream->Write(z);
bitStream->Write(yRot);
bitStream->Write(xRot);
}
void read(RakNet::BitStream* bitStream) {
bitStream->Read(entityId);
bitStream->Read(x);
bitStream->Read(y);
bitStream->Read(z);
bitStream->Read(yRot);
bitStream->Read(xRot);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__MoveEntityPacket_H__*/

View File

@@ -0,0 +1,54 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__MovePlayerPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__MovePlayerPacket_H__
#include "../Packet.h"
class MovePlayerPacket : public Packet
{
public:
int entityId;
float x, y, z, xRot, yRot;
MovePlayerPacket()
{
}
MovePlayerPacket(int entityId, float x, float y, float z, float xRot, float yRot)
: entityId(entityId),
x(x),
y(y),
z(z),
xRot(xRot),
yRot(yRot)
{}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_MOVEPLAYER));
bitStream->Write(entityId);
bitStream->Write(x);
bitStream->Write(y);
bitStream->Write(z);
bitStream->Write(yRot);
bitStream->Write(xRot);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(entityId);
bitStream->Read(x);
bitStream->Read(y);
bitStream->Read(z);
bitStream->Read(yRot);
bitStream->Read(xRot);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (MovePlayerPacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__MovePlayerPacket_H__*/

View File

@@ -0,0 +1,54 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__PacketInclude_H__
#define NET_MINECRAFT_NETWORK_PACKET__PacketInclude_H__
#include "AddEntityPacket.h"
#include "AddItemEntityPacket.h"
#include "AddMobPacket.h"
#include "AddPaintingPacket.h"
#include "AddPlayerPacket.h"
#include "AnimatePacket.h"
#include "AdventureSettingsPacket.h"
#include "ChatPacket.h"
#include "ContainerAckPacket.h"
#include "ContainerOpenPacket.h"
#include "ContainerClosePacket.h"
#include "ContainerSetDataPacket.h"
#include "ContainerSetSlotPacket.h"
#include "ContainerSetContentPacket.h"
#include "ChunkDataPacket.h"
#include "DropItemPacket.h"
#include "EntityEventPacket.h"
#include "ExplodePacket.h"
#include "HurtArmorPacket.h"
#include "InteractPacket.h"
#include "LevelEventPacket.h"
#include "LoginPacket.h"
#include "LoginStatusPacket.h"
#include "MessagePacket.h"
#include "MoveEntityPacket.h"
#include "MovePlayerPacket.h"
#include "PlaceBlockPacket.h"
#include "PlayerActionPacket.h"
#include "PlayerEquipmentPacket.h"
#include "PlayerArmorEquipmentPacket.h"
#include "ReadyPacket.h"
#include "RemoveBlockPacket.h"
#include "RemoveEntityPacket.h"
#include "RemovePlayerPacket.h"
#include "RespawnPacket.h"
#include "RequestChunkPacket.h"
#include "SendInventoryPacket.h"
#include "SetEntityDataPacket.h"
#include "SetEntityMotionPacket.h"
#include "SetHealthPacket.h"
#include "SetSpawnPositionPacket.h"
#include "SetTimePacket.h"
#include "SignUpdatePacket.h"
#include "StartGamePacket.h"
#include "TakeItemEntityPacket.h"
//#include "TeleportEntityPacket.h"
#include "TileEventPacket.h"
#include "UpdateBlockPacket.h"
#include "UseItemPacket.h"
#endif /*NET_MINECRAFT_NETWORK_PACKET__PacketInclude_H__*/

View File

@@ -0,0 +1,60 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__PlaceBlockPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__PlaceBlockPacket_H__
#include "../Packet.h"
class PlaceBlockPacket : public Packet
{
public:
// the id of the player who is placing the block, used to animate the player
int entityId;
int x, z;
unsigned char y, facing, blockId, blockData;
PlaceBlockPacket()
{
}
PlaceBlockPacket(int entityId, int x, int y, int z, int facing, int blockId, int blockData)
: entityId(entityId),
x(x),
y((unsigned char)(y & 0xff)),
z(z),
facing ((unsigned char)(facing & 0xff)),
blockId((unsigned char)(blockId & 0xff)),
blockData((unsigned char)(blockData & 0xff))
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_PLACEBLOCK));
bitStream->Write(entityId);
bitStream->Write(x);
bitStream->Write(z);
bitStream->Write(y);
bitStream->Write(facing);
bitStream->Write(blockId);
bitStream->Write(blockData);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(entityId);
bitStream->Read(x);
bitStream->Read(z);
bitStream->Read(y);
bitStream->Read(facing);
bitStream->Read(blockId);
bitStream->Read(blockData);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (PlaceBlockPacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__PlaceBlockPacket_H__*/

View File

@@ -0,0 +1,62 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__PlayerActionPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__PlayerActionPacket_H__
#include "../Packet.h"
class PlayerActionPacket : public Packet
{
public:
static const int START_DESTROY_BLOCK = 0;
static const int ABORT_DESTROY_BLOCK = 1;
static const int STOP_DESTROY_BLOCK = 2;
static const int GET_UPDATED_BLOCK = 3;
static const int DROP_ITEM = 4;
static const int RELEASE_USE_ITEM = 5;
static const int STOP_SLEEPING = 6;
PlayerActionPacket()
: x(0),
y(0),
z(0),
action(0),
face(0),
entityId(0)
{}
PlayerActionPacket(int action, int x, int y, int z, int face, int entityId)
: x(x),
y(y),
z(z),
face(face),
action(action),
entityId(entityId)
{}
void read(RakNet::BitStream* bitStream) {
bitStream->Read(action);
bitStream->Read(x);
bitStream->Read(y);
bitStream->Read(z);
bitStream->Read(face);
bitStream->Read(entityId);
}
void write(RakNet::BitStream* bitStream) {
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_PLAYERACTION));
bitStream->Write(action);
bitStream->Write(x);
bitStream->Write(y);
bitStream->Write(z);
bitStream->Write(face);
bitStream->Write(entityId);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) {
callback->handle(source, (PlayerActionPacket*)this);
}
int x, y, z, face, action, entityId;
};
#endif /* NET_MINECRAFT_NETWORK_PACKET__PlayerActionPacket_H__ */

View File

@@ -0,0 +1,78 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__PlayerArmorEquipmentPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__PlayerArmorEquipmentPacket_H__
#include "../Packet.h"
#include "../../world/entity/player/Player.h"
#include "../../world/item/ArmorItem.h"
#include "../../world/item/ItemInstance.h"
// @note: A visual update only
class PlayerArmorEquipmentPacket : public Packet
{
public:
int entityId;
signed char head;
signed char torso;
signed char legs;
signed char feet;
PlayerArmorEquipmentPacket() {
}
PlayerArmorEquipmentPacket(Player* player)
: entityId(player->entityId)
{
get(head, player->getArmor(ArmorItem::SLOT_HEAD));
get(torso, player->getArmor(ArmorItem::SLOT_TORSO));
get(legs, player->getArmor(ArmorItem::SLOT_LEGS));
get(feet, player->getArmor(ArmorItem::SLOT_FEET));
}
void write(RakNet::BitStream* bitStream) {
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_PLAYERARMOREQUIPMENT));
bitStream->Write(entityId);
bitStream->Write(head);
bitStream->Write(torso);
bitStream->Write(legs);
bitStream->Write(feet);
}
void read(RakNet::BitStream* bitStream) {
bitStream->Read(entityId);
bitStream->Read(head);
bitStream->Read(torso);
bitStream->Read(legs);
bitStream->Read(feet);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) {
callback->handle(source, (PlayerArmorEquipmentPacket*)this);
}
void fillIn(Player* player) {
set(player, head, ArmorItem::SLOT_HEAD);
set(player, torso, ArmorItem::SLOT_TORSO);
set(player, legs, ArmorItem::SLOT_LEGS);
set(player, feet, ArmorItem::SLOT_FEET);
}
private:
void get(signed char& s, const ItemInstance* item) {
if (item) {
s = item->id - 256;
} else {
s = -1;
}
}
void set(Player* p, signed char s, int slot) {
if (s < 0) p->setArmor(slot, NULL);
else {
ItemInstance item((int)s + 256, 1, 0);
p->setArmor(slot, &item);
}
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__PlayerArmorEquipmentPacket_H__*/

View File

@@ -0,0 +1,46 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__PlayerEquipmentPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__PlayerEquipmentPacket_H__
#include "../Packet.h"
class PlayerEquipmentPacket : public Packet
{
public:
int entityId;
unsigned short itemId;
unsigned short itemAuxValue;
PlayerEquipmentPacket()
{
}
PlayerEquipmentPacket(int entityId, int itemId, int data)
: entityId(entityId),
itemId(itemId),
itemAuxValue(data)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_PLAYEREQUIPMENT));
bitStream->Write(entityId);
bitStream->Write(itemId);
bitStream->Write(itemAuxValue);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(entityId);
bitStream->Read(itemId);
bitStream->Read(itemAuxValue);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (PlayerEquipmentPacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__PlayerEquipmentPacket_H__*/

View File

@@ -0,0 +1,42 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__ReadyPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__ReadyPacket_H__
#include "../Packet.h"
class ReadyPacket: public Packet
{
public:
static const char READY_UNDEFINED = 0;
static const char READY_CLIENTGENERATION = 1;
static const char READY_REQUESTEDCHUNKS = 2;
ReadyPacket()
: type(READY_UNDEFINED)
{
}
ReadyPacket(char type)
: type(type)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_READY));
bitStream->Write(type);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(type);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (ReadyPacket*)this);
}
char type;
};
#endif /*#NET_MINECRAFT_NETWORK_PACKET__ReadyPacket_H__*/

View File

@@ -0,0 +1,52 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__RemoveBlockPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__RemoveBlockPacket_H__
#include "../Packet.h"
#include "../../world/entity/player/Player.h"
class RemoveBlockPacket : public Packet
{
public:
// the id of the player who is placing the block, used to animate the player
int entityId;
int x, z;
unsigned char y;
RemoveBlockPacket()
{
}
RemoveBlockPacket(Player* p, int x, int y, int z)
: entityId(p->entityId),
x(x),
y((unsigned char)(y & 0xff)),
z(z)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_REMOVEBLOCK));
bitStream->Write(entityId);
bitStream->Write(x);
bitStream->Write(z);
bitStream->Write(y);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(entityId);
bitStream->Read(x);
bitStream->Read(z);
bitStream->Read(y);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (RemoveBlockPacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__RemoveBlockPacket_H__*/

View File

@@ -0,0 +1,39 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__RemoveEntityPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__RemoveEntityPacket_H__
#include "../Packet.h"
class RemoveEntityPacket : public Packet
{
public:
int entityId;
RemoveEntityPacket()
{
}
RemoveEntityPacket(int entityId)
: entityId(entityId)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_REMOVEENTITY));
bitStream->Write(entityId);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(entityId);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (RemoveEntityPacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__RemoveEntityPacket_H__*/

View File

@@ -0,0 +1,41 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__RemovePlayerPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__RemovePlayerPacket_H__
#include "../Packet.h"
#include "../../world/entity/player/Player.h"
class RemovePlayerPacket : public Packet
{
public:
RemovePlayerPacket() {}
RemovePlayerPacket(const Player* p)
: entityId(p->entityId),
owner(p->owner)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_REMOVEPLAYER));
bitStream->Write(entityId);
bitStream->Write(owner);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(entityId);
bitStream->Read(owner);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (RemovePlayerPacket*)this);
}
int entityId;
RakNet::RakNetGUID owner;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__RemovePlayerPacket_H__*/

View File

@@ -0,0 +1,42 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__RequestChunkPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__RequestChunkPacket_H__
#include "../Packet.h"
class RequestChunkPacket : public Packet
{
public:
int x, z;
RequestChunkPacket()
{
}
RequestChunkPacket(int _x, int _z)
{
x = _x;
z = _z;
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_REQUESTCHUNK));
bitStream->Write(x);
bitStream->Write(z);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(x);
bitStream->Read(z);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (RequestChunkPacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__RequestChunkPacket_H__*/

View File

@@ -0,0 +1,47 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__RespawnPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__RespawnPacket_H__
#include "../Packet.h"
class RespawnPacket: public Packet
{
public:
RespawnPacket()
{
}
RespawnPacket(const Player* p)
: x(p->x),y(p->y),z(p->z),
entityId(p->entityId)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_RESPAWN));
bitStream->Write(entityId);
bitStream->Write(x);
bitStream->Write(y);
bitStream->Write(z);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(entityId);
bitStream->Read(x);
bitStream->Read(y);
bitStream->Read(z);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (RespawnPacket*)this);
}
float x;
float y;
float z;
int entityId;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__RespawnPacket_H__*/

View File

@@ -0,0 +1,69 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__SendInventoryPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__SendInventoryPacket_H__
#include "../Packet.h"
class SendInventoryPacket: public Packet
{
public:
SendInventoryPacket()
{
}
SendInventoryPacket(Player* player, bool dropItems)
: entityId(player->entityId),
extra(dropItems? ExtraDrop : 0)
{
Inventory* inv = player->inventory;
numItems = 0;
for (int i = Inventory::MAX_SELECTION_SIZE; i < inv->getContainerSize(); ++i) {
++numItems;
ItemInstance* item = inv->getItem(i);
items.push_back(item? *item : ItemInstance());
}
for (int i = 0; i < NumArmorItems; ++i) {
ItemInstance* item = player->getArmor(i);
items.push_back(item? *item : ItemInstance());
}
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_SENDINVENTORY));
bitStream->Write(entityId);
bitStream->Write(extra);
bitStream->Write(numItems);
// Inventory
for (int i = 0; i < numItems; ++i)
PacketUtil::writeItemInstance(items[i], bitStream);
// Armor
for (int i = 0; i < NumArmorItems; ++i)
PacketUtil::writeItemInstance(items[i + numItems], bitStream);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(entityId);
bitStream->Read(extra);
bitStream->Read(numItems);
items.clear();
// Inventory, Armor
for (int i = 0; i < numItems + NumArmorItems; ++i)
items.push_back(PacketUtil::readItemInstance(bitStream));
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (SendInventoryPacket*)this);
}
int entityId;
std::vector<ItemInstance> items;
short numItems;
unsigned char extra;
static const int ExtraDrop = 1;
static const int NumArmorItems = 4;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__SendInventoryPacket_H__*/

View File

@@ -0,0 +1,64 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__SetEntityDataPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__SetEntityDataPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
#include "../../world/entity/SynchedEntityData.h"
#include "../../util/RakDataIO.h"
class SetEntityDataPacket: public Packet
{
public:
SetEntityDataPacket()
: deletePackedItems(false)
{}
SetEntityDataPacket(int id, SynchedEntityData& entityData)
: id(id),
deletePackedItems(false),
packedItems(entityData.packDirty())
{
}
~SetEntityDataPacket() {
if (deletePackedItems)
for (unsigned int i = 0; i < packedItems.size(); ++i)
delete packedItems[i];
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_SETENTITYDATA));
bitStream->Write(id);
RakDataOutput dos(*bitStream);
SynchedEntityData::pack(&packedItems, &dos);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(id);
RakDataInput dis(*bitStream);
packedItems = SynchedEntityData::unpack(&dis);
deletePackedItems = true;
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (SetEntityDataPacket*)this);
}
SynchedEntityData::DataList& getUnpackedData() {
return packedItems;
}
public:
int id;
private:
bool deletePackedItems;
SynchedEntityData::DataList packedItems;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__SetEntityDataPacket_H__*/

View File

@@ -0,0 +1,68 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__SetEntityMotionPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__SetEntityMotionPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
#include "../../world/entity/Entity.h"
class SetEntityMotionPacket: public Packet
{
public:
SetEntityMotionPacket() {}
SetEntityMotionPacket(Entity* e) {
init(e->entityId, e->xd, e->yd, e->zd);
}
SetEntityMotionPacket(int id, float xd, float yd, float zd) {
init(id, xd, yd, zd);
}
void write(RakNet::BitStream* bitStream)
{
const float M = 3.9f;
short xa = (short)(8000.0f * Mth::clamp(xd, -M, M));
short ya = (short)(8000.0f * Mth::clamp(yd, -M, M));
short za = (short)(8000.0f * Mth::clamp(zd, -M, M));
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_SETENTITYMOTION));
bitStream->Write(id);
bitStream->Write(xa);
bitStream->Write(ya);
bitStream->Write(za);
}
void read(RakNet::BitStream* bitStream)
{
short xa, ya, za;
bitStream->Read(id);
bitStream->Read(xa);
bitStream->Read(ya);
bitStream->Read(za);
xd = xa / 8000.0f;
yd = ya / 8000.0f;
zd = za / 8000.0f;
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (SetEntityMotionPacket*)this);
}
private:
void init(int entityId, float xd, float yd, float zd) {
this->id = entityId;
this->xd = xd;
this->yd = yd;
this->zd = zd;
}
public:
int id;
float xd, yd, zd;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__SetEntityMotionPacket_H__*/

View File

@@ -0,0 +1,41 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__SetHealthPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__SetHealthPacket_H__
#include "../Packet.h"
//package net.minecraft.network.packet;
class SetHealthPacket: public Packet {
public:
static const int HEALTH_MODIFY_OFFSET = -64;
SetHealthPacket() {
}
SetHealthPacket(int health)
: health(health)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_SETHEALTH));
bitStream->Write((signed char)health);
}
void read(RakNet::BitStream* bitStream)
{
signed char tmpHealth;
bitStream->Read(tmpHealth);
health = tmpHealth;
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (SetHealthPacket*)this);
}
int health;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__SetHealthPacket_H__*/

View File

@@ -0,0 +1,52 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__SetSpawnPositionPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__SetSpawnPositionPacket_H__
#include "../Packet.h"
class SetSpawnPositionPacket : public Packet
{
public:
int entityId;
int x, z;
unsigned char y;
SetSpawnPositionPacket()
{
}
SetSpawnPositionPacket(int x, int y, int z)
: x(x),
y((unsigned char)(y & 0xff)),
z(z)
{
}
SetSpawnPositionPacket(const Pos& pos)
: x(pos.x),
y((unsigned char)(pos.y & 0xff)),
z(pos.z)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_SETSPAWNPOSITION));
bitStream->Write(x);
bitStream->Write(z);
bitStream->Write(y);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(x);
bitStream->Read(z);
bitStream->Read(y);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (SetSpawnPositionPacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__SetSpawnPositionPacket_H__*/

View File

@@ -0,0 +1,36 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__SetTimePacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__SetTimePacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
class SetTimePacket: public Packet {
public:
SetTimePacket() {
}
SetTimePacket(long time)
: time(time)
{}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_SETTIME));
bitStream->Write(time);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(time);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (SetTimePacket*)this);
}
long time;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__SetTimePacket_H__*/

View File

@@ -0,0 +1,68 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__SignUpdatePacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__SignUpdatePacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
#include "../../util/RakDataIO.h"
#include "../../world/level/tile/entity/SignTileEntity.h"
class SignUpdatePacket: public Packet
{
public:
SignUpdatePacket() {}
SignUpdatePacket(int x, int y, int z, const std::string lines[])
: x(x),
y(y),
z(z)
{
for (int i = 0; i < 4; ++i)
this->lines[i] = lines[i];
}
/*@Override*/
void read(RakNet::BitStream* bitStream) {
short xx, zz;
unsigned char yy;
bitStream->Read(xx);
bitStream->Read(yy);
bitStream->Read(zz);
x = xx;
z = zz;
y = yy;
RakDataInput dis(*bitStream);
for (int i = 0; i < 4; ++i) {
lines[i] = dis.readString();
if (lines[i].length() > SignTileEntity::MAX_LINE_LENGTH)
lines[i].resize(SignTileEntity::MAX_LINE_LENGTH);
}
}
/*@Override*/
void write(RakNet::BitStream* bitStream) {
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_SIGNUPDATE));
short xx = x;
short zz = z;
unsigned char yy = y;
bitStream->Write(xx);
bitStream->Write(yy);
bitStream->Write(zz);
RakDataOutput dos(*bitStream);
for (int i = 0; i < 4; ++i)
dos.writeString(lines[i]);
}
/*@Override*/
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) {
callback->handle(source, (SignUpdatePacket*)this);
}
public:
int x, y, z;
std::string lines[4];
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__SignUpdatePacket_H__*/

View File

@@ -0,0 +1,61 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__StartGamePacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__StartGamePacket_H__
#include "../Packet.h"
class StartGamePacket : public Packet
{
public:
long levelSeed;
int levelGeneratorVersion;
int gameType;
int entityId;
float x, y, z;
StartGamePacket()
{
}
StartGamePacket(long seed, int levelGeneratorVersion, int gameType, int entityId, float x, float y, float z)
: levelSeed(seed),
levelGeneratorVersion(levelGeneratorVersion),
gameType(gameType),
entityId(entityId),
x(x),
y(y),
z(z)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_STARTGAME));
bitStream->Write(levelSeed);
bitStream->Write(levelGeneratorVersion);
bitStream->Write(gameType);
bitStream->Write(entityId);
bitStream->Write(x);
bitStream->Write(y);
bitStream->Write(z);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(levelSeed);
bitStream->Read(levelGeneratorVersion);
bitStream->Read(gameType);
bitStream->Read(entityId);
bitStream->Read(x);
bitStream->Read(y);
bitStream->Read(z);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (StartGamePacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__StartGamePacket_H__*/

View File

@@ -0,0 +1,42 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__TakeItemEntityPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__TakeItemEntityPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
class TakeItemEntityPacket: public Packet
{
public:
TakeItemEntityPacket() {
}
TakeItemEntityPacket(int itemId, int playerId)
: itemId(itemId),
playerId(playerId)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_TAKEITEMENTITY));
bitStream->Write(itemId);
bitStream->Write(playerId);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(itemId);
bitStream->Read(playerId);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (TakeItemEntityPacket*)this);
}
int itemId;
int playerId;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__TakeItemEntityPacket_H__*/

View File

@@ -0,0 +1,77 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__TeleportEntityPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__TeleportEntityPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
#include "../../world/entity/Entity.h"
#include "../../util/Mth.h"
class TeleportEntityPacket: public Packet
{
public:
TeleportEntityPacket() {
}
TeleportEntityPacket(Entity* e, char cause)
: id(e->entityId),
x(e->x),
y(e->y),
z(e->z),
yRot(e->yRot),
xRot(e->xRot),
cause(cause)
{
}
TeleportEntityPacket(int id, float x, float y, float z, float yRot, float xRot, char cause)
: id(id),
x(x),
y(y),
z(z),
yRot(yRot),
xRot(xRot),
cause(cause)
{
}
void write(RakNet::BitStream* bitStream) {
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_TELEPORTENTITY));
bitStream->Write(id);
bitStream->Write(x);
bitStream->Write(y);
bitStream->Write(z);
bitStream->Write(PacketUtil::Rot_degreesToChar(yRot));
bitStream->Write(PacketUtil::Rot_degreesToChar(xRot));
bitStream->Write(cause);
}
void read(RakNet::BitStream* bitStream) {
bitStream->Read(id);
bitStream->Read(x);
bitStream->Read(y);
bitStream->Read(z);
char rx, ry;
bitStream->Read(ry);
bitStream->Read(rx);
bitStream->Read(cause);
yRot = PacketUtil::Rot_degreesToChar(ry);
xRot = PacketUtil::Rot_charToDegrees(rx);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (TeleportEntityPacket*)this);
}
int id;
float x, y, z;
float xRot, yRot; // sent as byte
char cause;
static const int WANT_RESPAWN = 1;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__TeleportEntityPacket_H__*/

View File

@@ -0,0 +1,48 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__TileEventPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__TileEventPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
class TileEventPacket: public Packet {
public:
TileEventPacket() {}
TileEventPacket(int x, int y, int z, int b0, int b1)
: x(x),
y(y),
z(z),
b0(b0),
b1(b1)
{}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_TILEEVENT));
bitStream->Write(x);
bitStream->Write(y);
bitStream->Write(z);
bitStream->Write(b0);
bitStream->Write(b1);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(x);
bitStream->Read(y);
bitStream->Read(z);
bitStream->Read(b0);
bitStream->Read(b1);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (TileEventPacket*)this);
}
int x, y, z;
int b0, b1;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__TileEventPacket_H__*/

View File

@@ -0,0 +1,28 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__UpdateArmorPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__UpdateArmorPacket_H__
#include "../Packet.h"
class UpdateArmorPacket: public Packet
{
public:
UpdateArmorPacket(Player* player)
{
}
void write(RakNet::BitStream* bitStream){
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_UPDATEARMOR));
//bitStream->Write();
}
void read(RakNet::BitStream* bitStream) {
//bitStream->Read();
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) {
callback->handle(source, (UpdateArmorPacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__UpdateArmorPacket_H__*/

View File

@@ -0,0 +1,55 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__UpdateBlockPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__UpdateBlockPacket_H__
#include "../Packet.h"
class UpdateBlockPacket : public Packet
{
public:
int x, z;
unsigned char y;
unsigned char blockId;
unsigned char blockData;
UpdateBlockPacket()
{
}
UpdateBlockPacket(int _x, int _y, int _z, int _blockId, int _blockData)
{
x = _x;
y = (unsigned char)(_y & 0xff);
z = _z;
blockId = (unsigned char)(_blockId & 0xff);
blockData = (unsigned char)(_blockData & 0xff);
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_UPDATEBLOCK));
bitStream->Write(x);
bitStream->Write(z);
bitStream->Write(y);
bitStream->Write(blockId);
bitStream->Write(blockData);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(x);
bitStream->Read(z);
bitStream->Read(y);
bitStream->Read(blockId);
bitStream->Read(blockData);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (UpdateBlockPacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__UpdateBlockPacket_H__*/

View File

@@ -0,0 +1,86 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__UseItemPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__UseItemPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
#include "../../world/item/ItemInstance.h"
class UseItemPacket: public Packet
{
public:
int x, y, z, face;
float clickX, clickY, clickZ;
int entityId;
short itemId;
unsigned char itemData;
ItemInstance item;
UseItemPacket() {}
UseItemPacket(int x, int y, int z, int face, const ItemInstance* item, int entityId, float clickX, float clickY, float clickZ)
: x(x),
y(y),
z(z),
face(face),
itemId(item? item->id : 0),
itemData(item? item->getAuxValue() : 0),
entityId(entityId),
clickX(clickX),
clickY(clickY),
clickZ(clickZ)
{}
UseItemPacket(const ItemInstance* item, int entityId, const Vec3& aim)
: face(255),
itemId(item? item->id : 0),
itemData(item? item->getAuxValue() : 0),
entityId(entityId),
x((int)(aim.x * 32768.0f)),
y((int)(aim.y * 32768.0f)),
z((int)(aim.z * 32768.0f))
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_USEITEM));
bitStream->Write(x);
bitStream->Write(y);
bitStream->Write(z);
bitStream->Write(face);
bitStream->Write(itemId);
bitStream->Write(itemData);
bitStream->Write(entityId);
bitStream->Write(clickX);
bitStream->Write(clickY);
bitStream->Write(clickZ);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(x);
bitStream->Read(y);
bitStream->Read(z);
bitStream->Read(face);
bitStream->Read(itemId);
bitStream->Read(itemData);
bitStream->Read(entityId);
bitStream->Read(clickX);
bitStream->Read(clickY);
bitStream->Read(clickZ);
item.id = itemId;
item.setAuxValue(itemData);
item.count = (itemId == 0 && itemData == 0)? 0 : 1;
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (UseItemPacket*)this);
}
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__UseItemPacket_H__*/