From 4beb5cb0f94b488b4065e1a6b8ec1d43a7e03d0a Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Thu, 26 Mar 2026 23:32:09 +0300 Subject: [PATCH 01/59] i think i fixed player equip --- src/network/ServerSideNetworkHandler.cpp | 63 +++++++++++++++++++----- src/network/packet/SendInventoryPacket.h | 1 + src/server/ServerPlayer.cpp | 18 +++++-- src/world/inventory/FillingContainer.cpp | 5 ++ 4 files changed, 71 insertions(+), 16 deletions(-) diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 7736908..76007f3 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -13,6 +13,7 @@ #include "../client/gamemode/GameMode.h" #include "../raknet/RakPeerInterface.h" #include "../raknet/PacketPriority.h" +#include "platform/log.h" #ifndef STANDALONE_SERVER #include "../client/sound/SoundEngine.h" #endif @@ -244,6 +245,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ReadyPac if (packet->type == ReadyPacket::READY_REQUESTEDCHUNKS) onReady_RequestedChunks(source); + + LOGI("Ready player two ready ready player two!!\n "); } void ServerSideNetworkHandler::onReady_ClientGeneration(const RakNet::RakNetGUID& source) @@ -374,6 +377,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveBl oldTile->destroy(level, x, y, z, data); } + + LOGI("Remove block [%i, %i, %i]\n", packet->x, packet->y, packet->z); } void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RequestChunkPacket* packet) @@ -403,6 +408,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RequestC raknetInstance->send(source, p); } } + + // LOGI("Requested chunk [%i, %i]\n", packet->x, packet->z); } void ServerSideNetworkHandler::levelGenerated( Level* level ) @@ -429,23 +436,36 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, PlayerEq if (!player) return; if (rakPeer->GetMyGUID() == player->owner) return; + LOGI("Equip item: id %i aux %i\n", packet->itemId, packet->itemAuxValue); + // override the player's inventory - //int slot = player->inventory->getSlot(packet->itemId, packet->itemAuxValue); - int slot = Inventory::MAX_SELECTION_SIZE; + int slot = player->inventory->getSlot(packet->itemId, packet->itemAuxValue); + 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); - } + // 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 if (packet->itemId == 0) { + player->inventory->linkEmptySlot(player->inventory->selected); } else { - LOGW("Warning: Remote player doesn't have his thing, Odd!\n"); + LOGW("Warning: Remote player doesn't have his thing (or crafted it)!\n"); + return; } + + LOGI("Inventory:\n"); + for (int i = 0; i < player->inventory->numTotalSlots; i++) { + auto item = player->inventory->getItem(i); + if (item) LOGI("\t %i: %s (%i)\n", i, item->getName().c_str(), item->count); + } + + redistributePacket(packet, source); } void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, PlayerArmorEquipmentPacket* packet) { @@ -455,6 +475,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, PlayerAr if (!player) return; if (rakPeer->GetMyGUID() == player->owner) return; + LOGI("Equip armor: %i %i %i %i\n", packet->head, packet->torso, packet->legs, packet->feet); + packet->fillIn(player); redistributePacket(packet, source); } @@ -466,6 +488,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, Interact Entity* entity = level->getEntity(packet->targetId); if (src && entity && src->isPlayer()) { + LOGI("Interact: source %i target %i\n", packet->sourceId, packet->targetId); + Player* player = (Player*) src; if (InteractPacket::Attack == packet->action) { player->swing(); @@ -544,6 +568,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemP void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, EntityEventPacket* packet) { if (!level) return; + LOGI("EntityEventPacket: id %i\n", packet->eventId); + if (Entity* e = level->getEntity(packet->entityId)) e->handleEntityEvent(packet->eventId); } @@ -577,6 +603,11 @@ void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SendInv { if (!level) return; + LOGI("Sent inventory:\n"); + for (int i = 0; i < packet->numItems; i++) { + LOGI("\t %i: %s (%i)\n", i, packet->items.at(i).getName().c_str(), packet->items.at(i).count); + } + Entity* entity = level->getEntity(packet->entityId); if (entity && entity->isPlayer()) { Player* p = (Player*)entity; @@ -592,6 +623,8 @@ void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, DropIte { if (!level) return; + LOGI("DropItemPacket\n"); + Entity* entity = level->getEntity(packet->entityId); if (entity && entity->isPlayer()) { Player* p = (Player*)entity; @@ -601,6 +634,7 @@ void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, DropIte void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ContainerClosePacket* packet) { if (!level) return; + LOGI("ContainerClosePacket\n"); Player* p = findPlayer(level, &source); if (!p) return; @@ -611,6 +645,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, Containe void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ContainerSetSlotPacket* packet) { if (!level) return; + LOGI("ContainerSetSlot: slot %i item %s\n", packet->slot, packet->item.getName().c_str()); Player* p = findPlayer(level, &source); if (!p) return; @@ -639,6 +674,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, Containe void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SetHealthPacket* packet ) { + LOGI("SetHealthPacket\n"); + for (unsigned int i = 0; i < level->players.size(); ++i) { Player* p = level->players[i]; if (p->owner == source) { @@ -657,6 +694,8 @@ void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SignUpd if (!level) return; + LOGI("SignUpdate: [%i, %i, %i]\n", packet->x, packet->y, packet->z); + TileEntity* te = level->getTileEntity(packet->x, packet->y, packet->z); if (TileEntity::isType(te, TileEntityType::Sign)) { SignTileEntity* ste = (SignTileEntity*) te; diff --git a/src/network/packet/SendInventoryPacket.h b/src/network/packet/SendInventoryPacket.h index 65d12f4..482ef51 100755 --- a/src/network/packet/SendInventoryPacket.h +++ b/src/network/packet/SendInventoryPacket.h @@ -2,6 +2,7 @@ #define NET_MINECRAFT_NETWORK_PACKET__SendInventoryPacket_H__ #include "../Packet.h" +#include "world/entity/player/Inventory.h" class SendInventoryPacket: public Packet { diff --git a/src/server/ServerPlayer.cpp b/src/server/ServerPlayer.cpp index ad3b4a9..c27ae38 100755 --- a/src/server/ServerPlayer.cpp +++ b/src/server/ServerPlayer.cpp @@ -19,6 +19,8 @@ #include "../network/packet/AnimatePacket.h" #include "../world/level/tile/entity/ChestTileEntity.h" #include "../network/packet/HurtArmorPacket.h" +#include "network/packet/SendInventoryPacket.h" +#include "world/entity/player/Inventory.h" ServerPlayer::ServerPlayer( Minecraft* minecraft, Level* level ) : super(level, minecraft->isCreativeMode()), @@ -26,7 +28,7 @@ ServerPlayer::ServerPlayer( Minecraft* minecraft, Level* level ) _prevHealth(-999), _containerCounter(0) { - hasFakeInventory = true; + // hasFakeInventory = true; footSize = 0; } @@ -67,8 +69,16 @@ void ServerPlayer::tick() { void ServerPlayer::take( Entity* e, int orgCount ) { TakeItemEntityPacket packet(e->entityId, entityId); + // SendInventoryPacket packet(this, false); _mc->raknetInstance->send(packet); + LOGI("Inventory:\n"); + for (int i = 0; i < inventory->numLinkedSlots; i++) { + auto item = inventory->getItem(i); + if (item) + LOGI("\t %i: %s (%i)\n", i, item->getName().c_str(), item->count); + } + super::take(e, orgCount); } @@ -118,20 +128,20 @@ bool ServerPlayer::hasResource( int id ) { void ServerPlayer::setContainerData( BaseContainerMenu* menu, int id, int value ) { ContainerSetDataPacket p(menu->containerId, id, value); _mc->raknetInstance->send(owner, p); - //LOGI("Setting container data for id %d: %d\n", id, value); + LOGI("Setting container data for id %d: %d\n", id, value); } void ServerPlayer::slotChanged( BaseContainerMenu* menu, int slot, const ItemInstance& item, bool isResultSlot ) { if (isResultSlot) return; ContainerSetSlotPacket p(menu->containerId, slot, item); _mc->raknetInstance->send(owner, p); - //LOGI("Slot %d changed\n", slot); + LOGI("Slot %d changed\n", slot); } void ServerPlayer::refreshContainer( BaseContainerMenu* menu, const std::vector& items ) { ContainerSetContentPacket p(menu->containerId, menu->getItems()); _mc->raknetInstance->send(owner, p); - //LOGI("Refreshing container with %d items\n", items.size()); + LOGI("Refreshing container with %zu items\n", items.size()); } void ServerPlayer::nextContainerCounter() { diff --git a/src/world/inventory/FillingContainer.cpp b/src/world/inventory/FillingContainer.cpp index 10028b0..e4fcd5d 100755 --- a/src/world/inventory/FillingContainer.cpp +++ b/src/world/inventory/FillingContainer.cpp @@ -141,6 +141,11 @@ bool FillingContainer::add( ItemInstance* item ) // // silently destroy the item when having a full inventory // item->count = 0; // return true; + + LOGI("Inventory:\n"); + for (int i = 0; i < numTotalSlots; i++) { + LOGI("\t %i: %s (%i)\n", i, items.at(i)->getName().c_str(), items.at(i)->count); + } } return false; From 2c1b5e256e699f76dccb807f22e768e6cb87be5f Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Thu, 26 Mar 2026 22:48:50 +0200 Subject: [PATCH 02/59] change proto ver --- src/SharedConstants.h | 5 +++-- src/network/ServerSideNetworkHandler.cpp | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/SharedConstants.h b/src/SharedConstants.h index f97ea36..dcae293 100755 --- a/src/SharedConstants.h +++ b/src/SharedConstants.h @@ -16,8 +16,9 @@ namespace SharedConstants { // 0.5.0 uses NPv8 // 0.6.0 uses NPv9 - const int NetworkProtocolVersion = 9; - const int NetworkProtocolLowestSupportedVersion = 9; + // TODO: Better proto check + const int NetworkProtocolVersion = 10; + const int NetworkProtocolLowestSupportedVersion = 10; const int GameProtocolVersion = 1; const int GameProtocolLowestSupportedVersion = 1; diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 7736908..96e4a4e 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -179,7 +179,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac if (!_allowIncoming) return; LOGI("LoginPacket\n"); - + + printf("%d", packet->clientNetworkVersion); int loginStatus = LoginStatus::Success; // // Bad/incompatible client version From 96e8826f01866d5cdecb051930ee84c1757c4c74 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Fri, 27 Mar 2026 02:14:28 +0200 Subject: [PATCH 03/59] FEAT: Crafting on server --- CMakeLists.txt | 1 - .../screens/crafting/PaneCraftingScreen.cpp | 53 ++++++++------- src/network/ClientSideNetworkHandler.cpp | 37 +++++++++++ src/network/ClientSideNetworkHandler.h | 4 ++ src/network/NetEventCallback.h | 6 ++ src/network/Packet.cpp | 12 +++- src/network/Packet.h | 5 +- src/network/ServerSideNetworkHandler.cpp | 64 +++++++++++++++++++ src/network/ServerSideNetworkHandler.h | 3 +- src/network/packet/PacketInclude.h | 4 +- src/network/packet/RemoveItemPacket.h | 54 ++++++++++++++++ src/network/packet/TakeItemPacket.h | 54 ++++++++++++++++ src/network/packet/WantCreatePacket.h | 54 ++++++++++++++++ 13 files changed, 323 insertions(+), 28 deletions(-) create mode 100644 src/network/packet/RemoveItemPacket.h create mode 100644 src/network/packet/TakeItemPacket.h create mode 100644 src/network/packet/WantCreatePacket.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1711d1c..9c3acea 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,7 +111,6 @@ CPMAddPackage( "ALSOFT_STATIC_LIBGCC ON" ) -# TODO: Clear this paths with * file(GLOB SERVER_SOURCES "project/lib_projects/raknet/jni/RaknetSources/*.cpp" "src/NinecraftApp.cpp" diff --git a/src/client/gui/screens/crafting/PaneCraftingScreen.cpp b/src/client/gui/screens/crafting/PaneCraftingScreen.cpp index 4e3d025..4a23720 100755 --- a/src/client/gui/screens/crafting/PaneCraftingScreen.cpp +++ b/src/client/gui/screens/crafting/PaneCraftingScreen.cpp @@ -16,6 +16,8 @@ #include "../../../../world/level/Level.h" #include "../../../../world/item/DyePowderItem.h" #include "../../../../world/item/crafting/Recipe.h" +#include "network/RakNetInstance.h" +#include "network/packet/WantCreatePacket.h" #include "platform/input/Keyboard.h" static NinePatchLayer* guiPaneFrame = NULL; @@ -439,33 +441,38 @@ void PaneCraftingScreen::craftSelectedItem() ItemInstance resultItem = currentItem->item; if (minecraft->player) { - // Remove all items required for the recipe and ... - for (unsigned int i = 0; i < currentItem->neededItems.size(); ++i) { - CItem::ReqItem& req = currentItem->neededItems[i]; + if (minecraft->isOnline()) { + WantCreatePacket packet(minecraft->player->entityId, resultItem.count, resultItem.getAuxValue(), resultItem.id); + minecraft->raknetInstance->send(packet); + } else { + // Remove all items required for the recipe and ... + for (unsigned int i = 0; i < currentItem->neededItems.size(); ++i) { + CItem::ReqItem& req = currentItem->neededItems[i]; - // If the recipe allows any aux-value as ingredients, first deplete - // aux == 0 from inventory. Since I'm not sure if this always is - // correct, let's only do it for ingredient sandstone for now. - ItemInstance toRemove = req.item; + // If the recipe allows any aux-value as ingredients, first deplete + // aux == 0 from inventory. Since I'm not sure if this always is + // correct, let's only do it for ingredient sandstone for now. + ItemInstance toRemove = req.item; - if (Tile::sandStone->id == req.item.id - && Recipe::ANY_AUX_VALUE == req.item.getAuxValue()) { - toRemove.setAuxValue(0); - toRemove.count = minecraft->player->inventory->removeResource(toRemove, true); - toRemove.setAuxValue(Recipe::ANY_AUX_VALUE); - } + if (Tile::sandStone->id == req.item.id + && Recipe::ANY_AUX_VALUE == req.item.getAuxValue()) { + toRemove.setAuxValue(0); + toRemove.count = minecraft->player->inventory->removeResource(toRemove, true); + toRemove.setAuxValue(Recipe::ANY_AUX_VALUE); + } - if (toRemove.count > 0) { - minecraft->player->inventory->removeResource(toRemove); - } + if (toRemove.count > 0) { + minecraft->player->inventory->removeResource(toRemove); + } + } + // ... add the new one! (in this order, to fill empty slots better) + // if it doesn't fit, throw it on the ground! + if (!minecraft->player->inventory->add(&resultItem)) { + minecraft->player->drop(new ItemInstance(resultItem), false); + } + + recheckRecipes(); } - // ... add the new one! (in this order, to fill empty slots better) - // if it doesn't fit, throw it on the ground! - if (!minecraft->player->inventory->add(&resultItem)) { - minecraft->player->drop(new ItemInstance(resultItem), false); - } - - recheckRecipes(); } } diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index d754b47..fc3a815 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -10,6 +10,7 @@ #include "../world/entity/player/Inventory.h" #include "../client/Minecraft.h" #include "../client/gamemode/GameMode.h" +#include "world/item/ItemInstance.h" #ifndef STANDALONE_SERVER #include "../client/gui/screens/DisconnectionScreen.h" #endif @@ -385,6 +386,38 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3); } } +void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, TakeItemPacket* packet) { + if (!level) return; + + LOGI("TakeItemPacket\n"); + + ItemInstance* item; + + item->count = packet->count; + item->id = packet->itemId; + item->setAuxValue(packet->auxValue); + + // if (minecraft->player->entityId == packet->playerId) { + if (!minecraft->player->inventory->add(item)) { + minecraft->player->drop(new ItemInstance(*item), false); + } + // } +} + +void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveItemPacket* packet) { + // Idk how it works... + if (!level) return; + + ItemInstance item; + + item.count = packet->count; + item.id = packet->itemId; + item.setAuxValue(packet->auxValue); + + // if (minecraft->player->entityId == packet->playerId) { + minecraft->player->inventory->removeResource(item); + // } +} void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MoveEntityPacket* packet) { @@ -782,6 +815,10 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AnimateP } } +void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, WantCreatePacket* packet) +{ +} + void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemPacket* packet) { } diff --git a/src/network/ClientSideNetworkHandler.h b/src/network/ClientSideNetworkHandler.h index 1505ec7..b0cb98f 100755 --- a/src/network/ClientSideNetworkHandler.h +++ b/src/network/ClientSideNetworkHandler.h @@ -77,6 +77,10 @@ public: 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); + virtual void handle(const RakNet::RakNetGUID& source, RemoveItemPacket* packet); + virtual void handle(const RakNet::RakNetGUID& source, TakeItemPacket* packet); + virtual void handle(const RakNet::RakNetGUID& source, WantCreatePacket* packet); + private: void requestNextChunk(); diff --git a/src/network/NetEventCallback.h b/src/network/NetEventCallback.h index 53e5fa4..db3e22b 100755 --- a/src/network/NetEventCallback.h +++ b/src/network/NetEventCallback.h @@ -18,6 +18,8 @@ class RemovePlayerPacket; class RemoveEntityPacket; class MoveEntityPacket; //class TeleportEntityPacket; +class RemoveItemPacket; +class TakeItemPacket; class MovePlayerPacket; class PlaceBlockPacket; class RemoveBlockPacket; @@ -48,6 +50,7 @@ class ContainerClosePacket; class ContainerSetSlotPacket; class ContainerSetDataPacket; class ContainerSetContentPacket; +class WantCreatePacket; class ChatPacket; class SignUpdatePacket; class Minecraft; @@ -119,6 +122,9 @@ public: 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) {} + virtual void handle(const RakNet::RakNetGUID& source, RemoveItemPacket* packet) {} + virtual void handle(const RakNet::RakNetGUID& source, TakeItemPacket* packet) {} + virtual void handle(const RakNet::RakNetGUID& source, WantCreatePacket* packet) {} // // Common implementation for Client and Server diff --git a/src/network/Packet.cpp b/src/network/Packet.cpp index ca1b328..d060356 100755 --- a/src/network/Packet.cpp +++ b/src/network/Packet.cpp @@ -2,6 +2,7 @@ #include "Packet.h" #include "../world/level/chunk/LevelChunk.h" +#include "network/packet/TakeItemPacket.h" #include "packet/PacketInclude.h" Packet::Packet() @@ -41,10 +42,16 @@ Packet* MinecraftPackets::createPacket(int id) case PACKET_ADDITEMENTITY: packet = new AddItemEntityPacket(); break; + case PACKET_REMOVEITEM: + packet = new RemoveItemPacket(); + break; + case PACKET_TAKEITEM: + packet = new TakeItemPacket(); + break; case PACKET_TAKEITEMENTITY: packet = new TakeItemEntityPacket(); break; - case PACKET_ADDMOB: + case PACKET_ADDMOB: packet = new AddMobPacket(); break; case PACKET_ADDPLAYER: @@ -68,6 +75,9 @@ Packet* MinecraftPackets::createPacket(int id) case PACKET_RESPAWN: packet = new RespawnPacket(); break; + case PACKET_WANTCREATEITEM: + packet = new WantCreatePacket(); + break; case PACKET_REMOVEENTITY: packet = new RemoveEntityPacket(); break; diff --git a/src/network/Packet.h b/src/network/Packet.h index e872219..3525bd4 100755 --- a/src/network/Packet.h +++ b/src/network/Packet.h @@ -33,7 +33,10 @@ enum MinecraftPacketIds PACKET_REMOVEENTITY, PACKET_ADDITEMENTITY, PACKET_TAKEITEMENTITY, - + PACKET_TAKEITEM, + PACKET_REMOVEITEM, + PACKET_WANTCREATEITEM, + PACKET_MOVEENTITY, PACKET_MOVEENTITY_POS, PACKET_MOVEENTITY_ROT, diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 883d3a4..bd15ac5 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -5,6 +5,9 @@ #include "../world/entity/player/Inventory.h" #include "../world/Container.h" #include "../world/inventory/BaseContainerMenu.h" +#include "network/packet/RemoveItemPacket.h" +#include "network/packet/TakeItemPacket.h" +#include "network/packet/WantCreatePacket.h" #include "packet/PacketInclude.h" #include "RakNetInstance.h" @@ -14,6 +17,10 @@ #include "../raknet/RakPeerInterface.h" #include "../raknet/PacketPriority.h" #include "platform/log.h" +#include "world/item/ItemInstance.h" +#include "world/item/crafting/Recipe.h" +#include "world/item/crafting/Recipes.h" +#include #ifndef STANDALONE_SERVER #include "../client/sound/SoundEngine.h" #endif @@ -531,6 +538,63 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AnimateP } redistributePacket(packet, source); } +void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, WantCreatePacket* packet) { + LOGI("WantCreatePacket\n"); + Entity* entity = level->getEntity(packet->playerId); + + if (entity && entity->isPlayer()) { + Player* p = (Player*)entity; + + auto playerInv = p->inventory; + + ItemInstance wantCreate; + + wantCreate.id = packet->itemId; + wantCreate.count = packet->count; + wantCreate.setAuxValue(packet->auxValue); + + Recipe* recipe = Recipes::getInstance()->getRecipeFor(wantCreate); + + std::vector items = recipe->getItemPack().getItemInstances(); + + std::vector checkForExists = {}; + + for (int i = Inventory::MAX_SELECTION_SIZE; i < p->inventory->getContainerSize(); ++i) { + auto itm = p->inventory->getItem(i); + + if (itm != NULL) { + for (int y = 0; y < items.size(); y++) { + auto itmRecipe = items.at(y); + + if (itmRecipe.id == itm->id && itmRecipe.count == itm->count) { + checkForExists.push_back(itm->id); + } + } + } + } + + for (int i = 0; i < items.size(); i++) { + auto item = items.at(i); + + auto it = std::find(checkForExists.begin(), checkForExists.end(), item.id); + + if (it == checkForExists.end()) { + return; + } + } + + for (int i = 0; i < items.size(); i++) { + RemoveItemPacket removePacket(packet->playerId, items.at(i).count, items.at(i).getAuxValue(), items.at(i).id); + raknetInstance->send(source, removePacket); + + p->inventory->removeItem(new ItemInstance(items.at(i).id, items.at(i).count, items.at(i).getAuxValue())); + } + TakeItemPacket itemAdd(p->entityId, wantCreate.count, wantCreate.getAuxValue(), wantCreate.id); + raknetInstance->send(source, itemAdd); + + p->inventory->add(new ItemInstance(wantCreate.id, wantCreate.count, wantCreate.getAuxValue())); + } +} void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemPacket* packet) { diff --git a/src/network/ServerSideNetworkHandler.h b/src/network/ServerSideNetworkHandler.h index 51531cf..a65585a 100755 --- a/src/network/ServerSideNetworkHandler.h +++ b/src/network/ServerSideNetworkHandler.h @@ -58,7 +58,8 @@ public: virtual void handle(const RakNet::RakNetGUID& source, ContainerClosePacket* packet); virtual void handle(const RakNet::RakNetGUID& source, SignUpdatePacket* packet); virtual void handle(const RakNet::RakNetGUID& source, ChatPacket* packet); - + virtual void handle(const RakNet::RakNetGUID& source, WantCreatePacket* packet); + bool allowsIncomingConnections() { return _allowIncoming; } void allowIncomingConnections(bool doAllow); diff --git a/src/network/packet/PacketInclude.h b/src/network/packet/PacketInclude.h index 09aeae8..ff884d2 100755 --- a/src/network/packet/PacketInclude.h +++ b/src/network/packet/PacketInclude.h @@ -50,5 +50,7 @@ #include "TileEventPacket.h" #include "UpdateBlockPacket.h" #include "UseItemPacket.h" - +#include "RemoveItemPacket.h" +#include "WantCreatePacket.h" +#include "TakeItemPacket.h" #endif /*NET_MINECRAFT_NETWORK_PACKET__PacketInclude_H__*/ diff --git a/src/network/packet/RemoveItemPacket.h b/src/network/packet/RemoveItemPacket.h new file mode 100644 index 0000000..f4a1d0a --- /dev/null +++ b/src/network/packet/RemoveItemPacket.h @@ -0,0 +1,54 @@ +#ifndef NET_MINECRAFT_NETWORK_PACKET__RemoveItemPacket_H__ +#define NET_MINECRAFT_NETWORK_PACKET__RemoveItemPacket_H__ + +//package net.minecraft.network.packet; + +#include "../Packet.h" + +class RemoveItemPacket: public Packet +{ +public: + RemoveItemPacket() { + } + + RemoveItemPacket(int playerId, int count, int auxValue, int itemId) + : + playerId(playerId), + count(count), + auxValue(auxValue), + itemId(itemId) + { + } + + void write(RakNet::BitStream* bitStream) + { + bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_REMOVEITEM)); + bitStream->Write(itemId); + bitStream->Write(count); + bitStream->Write(auxValue); + + bitStream->Write(playerId); + } + + void read(RakNet::BitStream* bitStream) + { + bitStream->Read(itemId); + bitStream->Read(count); + bitStream->Read(auxValue); + + bitStream->Read(playerId); + } + + void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) + { + callback->handle(source, (RemoveItemPacket*)this); + } + + int playerId; + + int itemId; + int count; + int auxValue; +}; + +#endif /*NET_MINECRAFT_NETWORK_PACKET__RemoveItemPacket_H__*/ diff --git a/src/network/packet/TakeItemPacket.h b/src/network/packet/TakeItemPacket.h new file mode 100644 index 0000000..17eee0f --- /dev/null +++ b/src/network/packet/TakeItemPacket.h @@ -0,0 +1,54 @@ +#ifndef NET_MINECRAFT_NETWORK_PACKET__TakeItemPacket_H__ +#define NET_MINECRAFT_NETWORK_PACKET__TakeItemPacket_H__ + +//package net.minecraft.network.packet; + +#include "../Packet.h" + +class TakeItemPacket: public Packet +{ +public: + TakeItemPacket() { + } + + TakeItemPacket(int playerId, int count, int auxValue, int itemId) + : + playerId(playerId), + count(count), + auxValue(auxValue), + itemId(itemId) + { + } + + void write(RakNet::BitStream* bitStream) + { + bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_TAKEITEM)); + bitStream->Write(itemId); + bitStream->Write(count); + bitStream->Write(auxValue); + + bitStream->Write(playerId); + } + + void read(RakNet::BitStream* bitStream) + { + bitStream->Read(itemId); + bitStream->Read(count); + bitStream->Read(auxValue); + + bitStream->Read(playerId); + } + + void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) + { + callback->handle(source, (TakeItemPacket*)this); + } + + int playerId; + + int itemId; + int count; + int auxValue; +}; + +#endif /*NET_MINECRAFT_NETWORK_PACKET__TakeItemPacket_H__*/ diff --git a/src/network/packet/WantCreatePacket.h b/src/network/packet/WantCreatePacket.h new file mode 100644 index 0000000..48873c5 --- /dev/null +++ b/src/network/packet/WantCreatePacket.h @@ -0,0 +1,54 @@ +#ifndef NET_MINECRAFT_NETWORK_PACKET__WantCreatePacket_H__ +#define NET_MINECRAFT_NETWORK_PACKET__WantCreatePacket_H__ + +//package net.minecraft.network.packet; + +#include "../Packet.h" + +class WantCreatePacket: public Packet +{ +public: + WantCreatePacket() { + } + + WantCreatePacket(int playerId, int count, int auxValue, int itemId) + : + playerId(playerId), + count(count), + auxValue(auxValue), + itemId(itemId) + { + } + + void write(RakNet::BitStream* bitStream) + { + bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_WANTCREATEITEM)); + bitStream->Write(itemId); + bitStream->Write(count); + bitStream->Write(auxValue); + + bitStream->Write(playerId); + } + + void read(RakNet::BitStream* bitStream) + { + bitStream->Read(itemId); + bitStream->Read(count); + bitStream->Read(auxValue); + + bitStream->Read(playerId); + } + + void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) + { + callback->handle(source, (WantCreatePacket*)this); + } + + int playerId; + + int itemId; + int count; + int auxValue; +}; + +#endif /*NET_MINECRAFT_NETWORK_PACKET__WantCreatePacket_H__*/ From 41c5bdf243b257199a4bd993521ae9b76f6fb2f2 Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Fri, 27 Mar 2026 03:33:21 +0300 Subject: [PATCH 04/59] FIX: The end of item cheating --- src/client/Minecraft.cpp | 15 ++ src/client/player/LocalPlayer.cpp | 2 +- src/network/ServerSideNetworkHandler.cpp | 165 +++++++++++++++++---- src/network/packet/PlayerEquipmentPacket.h | 12 +- src/world/entity/player/Inventory.cpp | 9 ++ src/world/entity/player/Inventory.h | 2 + src/world/item/ItemInstance.cpp | 4 + src/world/item/ItemInstance.h | 2 + 8 files changed, 182 insertions(+), 29 deletions(-) diff --git a/src/client/Minecraft.cpp b/src/client/Minecraft.cpp index ccd9ba5..6487664 100755 --- a/src/client/Minecraft.cpp +++ b/src/client/Minecraft.cpp @@ -726,6 +726,21 @@ void Minecraft::tickInput() { if (key == Keyboard::KEY_F3) { options.toggle(OPTIONS_RENDER_DEBUG); } + + // TODO: replace it with client /give command :face_vomiting: + if (key == Keyboard::KEY_F4) { + player->inventory->add(new ItemInstance(Tile::redBrick)); + player->inventory->add(new ItemInstance(Item::ironIngot, 64)); + player->inventory->add(new ItemInstance(Item::ironIngot, 34)); + player->inventory->add(new ItemInstance(Tile::stonecutterBench)); + player->inventory->add(new ItemInstance(Tile::workBench)); + player->inventory->add(new ItemInstance(Tile::furnace)); + player->inventory->add(new ItemInstance(Tile::wood, 54)); + player->inventory->add(new ItemInstance(Item::stick, 14)); + player->inventory->add(new ItemInstance(Item::coal, 31)); + player->inventory->add(new ItemInstance(Tile::sand, 6)); + + } if (key == Keyboard::KEY_F5) { options.toggle(OPTIONS_THIRD_PERSON_VIEW); diff --git a/src/client/player/LocalPlayer.cpp b/src/client/player/LocalPlayer.cpp index 398edcd..a4d3b74 100755 --- a/src/client/player/LocalPlayer.cpp +++ b/src/client/player/LocalPlayer.cpp @@ -456,7 +456,7 @@ void LocalPlayer::tick() { { sentInventoryItemId = newItemId; sentInventoryItemData = newItemData; - PlayerEquipmentPacket packet(entityId, newItemId, newItemData); + PlayerEquipmentPacket packet(entityId, newItemId, newItemData, inventory->selected, inventory->getSlot(newItemId, newItemData)); minecraft->raknetInstance->send(packet); } } diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 76007f3..136086a 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -5,6 +5,9 @@ #include "../world/entity/player/Inventory.h" #include "../world/Container.h" #include "../world/inventory/BaseContainerMenu.h" +#include "network/packet/ContainerSetSlotPacket.h" +#include "network/packet/RemoveBlockPacket.h" +#include "network/packet/UpdateBlockPacket.h" #include "packet/PacketInclude.h" #include "RakNetInstance.h" @@ -14,6 +17,8 @@ #include "../raknet/RakPeerInterface.h" #include "../raknet/PacketPriority.h" #include "platform/log.h" +#include "world/item/ItemInstance.h" +#include "world/phys/Vec3.h" #ifndef STANDALONE_SERVER #include "../client/sound/SoundEngine.h" #endif @@ -207,6 +212,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac newPlayer->name = packet->clientName.C_String(); _pendingPlayers.push_back(newPlayer); + LOGI("Adding new player... isCreative: %i\n", minecraft->isCreativeMode()); + // Reset the player so he doesn't spawn inside blocks while (newPlayer->y > 0) { newPlayer->setPos(newPlayer->x, newPlayer->y, newPlayer->z); @@ -441,29 +448,20 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, PlayerEq // override the player's inventory int slot = player->inventory->getSlot(packet->itemId, packet->itemAuxValue); - 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); - // } + if (slot >= 0 && slot != packet->inventorySlot && packet->itemId != 0) { + LOGW("PlayerEquipmentPacket: Item in player inventory but slots doesn't match!"); + packet->inventorySlot = slot; + } - player->inventory->moveToSelectedSlot(slot, true); - } else if (packet->itemId == 0) { - player->inventory->linkEmptySlot(player->inventory->selected); - } else { - LOGW("Warning: Remote player doesn't have his thing (or crafted it)!\n"); + if (slot < 0 && packet->itemId != 0) { + LOGW("PlayerEquipmentPacket: Remote player doesn't have his thing (or crafted it)!\n"); return; } - LOGI("Inventory:\n"); - for (int i = 0; i < player->inventory->numTotalSlots; i++) { - auto item = player->inventory->getItem(i); - if (item) LOGI("\t %i: %s (%i)\n", i, item->getName().c_str(), item->count); - } + player->inventory->selectSlot(packet->selectedSlot); + player->inventory->linkSlot(packet->selectedSlot, packet->inventorySlot, true); + + player->inventory->print(); redistributePacket(packet, source); } @@ -535,7 +533,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemP { if (!level) return; - LOGI("UseItemPacket\n"); + LOGI("UseItemPacket: id %i data %i\n", packet->itemId, packet->itemData); Entity* entity = level->getEntity(packet->entityId); if (entity && entity->isPlayer()) { Player* player = (Player*) entity; @@ -546,7 +544,30 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemP if (t && t->use(level, x, y, z, player)) return; if (packet->item.isNull()) return; - ItemInstance* item = &packet->item; + ItemInstance* packetItem = &packet->item; + + int slot = player->inventory->getSlot(packet->itemId, packet->itemData); + + if (slot < 0) { + LOGW("UseItemPacket: Player doesn't have this item!\n"); + + auto pos = Vec3(packet->x, packet->y, packet->z); + + if (ItemInstance::isBlock(packetItem)) { + LOGI("UseItemPacket: This is even block!!!\n"); + + pos.x += packet->clickX; + pos.y += packet->clickY; + pos.z += packet->clickZ; + } + + UpdateBlockPacket refuse(pos.x, pos.y, pos.z, level->getTile(pos.x, pos.y, pos.z), level->getData(pos.x, pos.y, pos.z)); + raknetInstance->send(refuse); + + return; + } + + ItemInstance* item = player->inventory->getItem(slot); if(packet->face == 255) { // Special case: x,y,z means direction-of-action @@ -557,6 +578,10 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemP 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)); } + + if (item && item->count <= 0) { + player->inventory->clearSlot(slot); + } //LOGW("Use Item not working! Out of synch?\n"); @@ -603,7 +628,7 @@ void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SendInv { if (!level) return; - LOGI("Sent inventory:\n"); + LOGI("SendInventoryPacket:\n"); for (int i = 0; i < packet->numItems; i++) { LOGI("\t %i: %s (%i)\n", i, packet->items.at(i).getName().c_str(), packet->items.at(i).count); } @@ -628,7 +653,16 @@ void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, DropIte Entity* entity = level->getEntity(packet->entityId); if (entity && entity->isPlayer()) { Player* p = (Player*)entity; - p->drop(new ItemInstance(packet->item), packet->dropType != 0); + // p->drop(new ItemInstance(packet->item), packet->dropType != 0); + + int slot = p->inventory->getSlot(packet->item.id, packet->item.getAuxValue()); + + if (slot < 0) { + LOGW("DropItemPacket: player doesn't have these items!\n"); + return; + } + + p->inventory->dropSlot(slot, false, packet->dropType != 0); } } @@ -645,7 +679,16 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, Containe void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ContainerSetSlotPacket* packet) { if (!level) return; - LOGI("ContainerSetSlot: slot %i item %s\n", packet->slot, packet->item.getName().c_str()); + + const char* type = "unknown"; + + switch (packet->setType) { + case ContainerSetSlotPacket::SETTYPE_ADD: type = "add"; break; + case ContainerSetSlotPacket::SETTYPE_SET: type = "set"; break; + case ContainerSetSlotPacket::SETTYPE_TAKE: type = "take"; break; + }; + + LOGI("ContainerSetSlot: slot %i item %s type %s\n", packet->slot, packet->item.getName().c_str(), type); Player* p = findPlayer(level, &source); if (!p) return; @@ -654,11 +697,79 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, Containe LOGW("User has no container!\n"); return; } - if (p->containerMenu->containerId != packet->containerId) - { + + if (p->containerMenu->containerId != packet->containerId) { LOGW("Wrong container id: %d vs %d\n", p->containerMenu->containerId, packet->containerId); return; } + + if (packet->item.count > 64) { + LOGW("ContainerSetSlotPacket: player tried to put more than 64"); + return; + } + + auto contItems = p->containerMenu->getItems(); + + // find same item in player inventory (used not in all cases) + int invSlot = p->inventory->getSlot(packet->item.id, packet->item.getAuxValue()); + auto invItem = p->inventory->getItem(invSlot); + + if (contItems.at(packet->slot).id == 0 && packet->item.id != 0) { + LOGI("ContainerSetSlotPacket: player tried to put items to slot %i\n", packet->slot); + + if (invSlot < 0) { + LOGW("ContainerSetSlotPacket: player doesn't have this item\n"); + return; + } + + if (invItem->count < packet->item.count) { + LOGW("ContainerSetSlotPacket: player tried to put more than he have\n"); + packet->item.count = invItem->count; + } + + invItem->count -= packet->item.count; + + if (invItem->count <= 0) { + p->inventory->removeItem(invItem); + } + } else if(contItems.at(packet->slot).id == packet->item.id) { + int deltaItem = packet->item.count - contItems.at(packet->slot).count; + + if (deltaItem > 0) { + LOGI("ContainerSetSlotPacket: player tried to add %i items to slot %i\n", deltaItem, packet->slot); + + auto invItem = p->inventory->getItem(invSlot); + + if (invSlot < 0) { + LOGW("ContainerSetSlotPacket: player doesn't have this item\n"); + return; + } + + if (invItem->count < deltaItem) { + LOGW("ContainerSetSlotPacket: player tried to put more than he have"); + packet->item.count -= (deltaItem - invItem->count); + deltaItem = invItem->count; + } + + invItem->count -= deltaItem; + + if (invItem->count <= 0) { + p->inventory->removeItem(invItem); + } + } else if (deltaItem < 0) { + LOGW("ContainerSetSlotPacket: player tried to take %i items from slot %i\n", -deltaItem, packet->slot); + p->inventory->add(new ItemInstance(packet->item.getItem(), -deltaItem, contItems.at(packet->slot).getAuxValue())); + } + } else if(contItems.at(packet->slot).id && !packet->item.id) { + LOGI("ContainerSetSlotPacket: player tried to take all items from slot %i\n", packet->slot); + packet->item.count = 0; + packet->item.setAuxValue(0); + + p->inventory->add(new ItemInstance(contItems.at(packet->slot).getItem(), contItems.at(packet->slot).count, contItems.at(packet->slot).getAuxValue())); + } else { + LOGW("ContainerSetSlotPacket: illegal container operation in slot %i\n", packet->slot); + return; + } if (ContainerType::FURNACE == p->containerMenu->containerType) { //LOGI("Server:Setting slot %d: %s\n", packet->slot, packet->item.toString().c_str()); @@ -670,6 +781,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, Containe p->containerMenu->setSlot(packet->slot, &packet->item); //p->containerMenu->setSlot(packet->slot, packet->item.isNull()? NULL : &packet->item); } + + p->inventory->print(); } void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SetHealthPacket* packet ) diff --git a/src/network/packet/PlayerEquipmentPacket.h b/src/network/packet/PlayerEquipmentPacket.h index 5dfb315..b49974c 100755 --- a/src/network/packet/PlayerEquipmentPacket.h +++ b/src/network/packet/PlayerEquipmentPacket.h @@ -9,15 +9,19 @@ public: int entityId; unsigned short itemId; unsigned short itemAuxValue; + unsigned char selectedSlot; + unsigned char inventorySlot; PlayerEquipmentPacket() { } - PlayerEquipmentPacket(int entityId, int itemId, int data) + PlayerEquipmentPacket(int entityId, int itemId, int data, int selSlot, int invSlot) : entityId(entityId), itemId(itemId), - itemAuxValue(data) + itemAuxValue(data), + selectedSlot(selSlot), + inventorySlot(invSlot) { } @@ -28,6 +32,8 @@ public: bitStream->Write(entityId); bitStream->Write(itemId); bitStream->Write(itemAuxValue); + bitStream->Write(selectedSlot); + bitStream->Write(inventorySlot); } void read(RakNet::BitStream* bitStream) @@ -35,6 +41,8 @@ public: bitStream->Read(entityId); bitStream->Read(itemId); bitStream->Read(itemAuxValue); + bitStream->Read(selectedSlot); + bitStream->Read(inventorySlot); } void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) diff --git a/src/world/entity/player/Inventory.cpp b/src/world/entity/player/Inventory.cpp index 5a46535..c1d6db4 100755 --- a/src/world/entity/player/Inventory.cpp +++ b/src/world/entity/player/Inventory.cpp @@ -357,3 +357,12 @@ bool Inventory::removeItem( const ItemInstance* samePtr ) { } return false; } + +void Inventory::print() { + LOGI("%s's Inventory:\n", player->name.c_str()); + + for (int i = 0; i < numTotalSlots; i++) { + auto item = getItem(i); + if (item) LOGI("\t %i: %s (%i) %s\n", i, item->getName().c_str(), item->count, (player->inventory->getLinked(i))? "(Linked)" : ""); + } +} \ No newline at end of file diff --git a/src/world/entity/player/Inventory.h b/src/world/entity/player/Inventory.h index 3e8696e..e1ad435 100755 --- a/src/world/entity/player/Inventory.h +++ b/src/world/entity/player/Inventory.h @@ -45,6 +45,8 @@ public: int getAttackDamage(Entity* entity); float getDestroySpeed(Tile* tile); bool canDestroy(Tile* tile); + + void print(); private: void setupDefault(); public: diff --git a/src/world/item/ItemInstance.cpp b/src/world/item/ItemInstance.cpp index 9d7d03f..d52d9f1 100755 --- a/src/world/item/ItemInstance.cpp +++ b/src/world/item/ItemInstance.cpp @@ -290,3 +290,7 @@ bool ItemInstance::isArmorItem( const ItemInstance* instance ) { return item->isArmor(); } + +bool ItemInstance::isBlock(const ItemInstance* instance) { + return instance->id < 256; +} \ No newline at end of file diff --git a/src/world/item/ItemInstance.h b/src/world/item/ItemInstance.h index b65a97d..9b1926d 100755 --- a/src/world/item/ItemInstance.h +++ b/src/world/item/ItemInstance.h @@ -81,6 +81,8 @@ public: static bool isArmorItem(const ItemInstance* instance); + static bool isBlock(const ItemInstance* instance); + /** * Checks if this item is the same item as the other one, disregarding the * 'count' value. From c234abe3aa4ecd9cbcfb3021da3fe6a45577b014 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Fri, 27 Mar 2026 02:40:52 +0200 Subject: [PATCH 05/59] FIX: Item crafting --- src/network/ServerSideNetworkHandler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index bd15ac5..c92c834 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -566,7 +566,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, WantCrea for (int y = 0; y < items.size(); y++) { auto itmRecipe = items.at(y); - if (itmRecipe.id == itm->id && itmRecipe.count == itm->count) { + if (itmRecipe.id == itm->id && itm->count >= itmRecipe.count) { checkForExists.push_back(itm->id); } } @@ -578,7 +578,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, WantCrea auto it = std::find(checkForExists.begin(), checkForExists.end(), item.id); - if (it == checkForExists.end()) { + if (it == checkForExists.end() && checkForExists.size() > 1) { return; } } From f0cb6d0b7c6db61280d874fb2c5540f1f9ff7932 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Fri, 27 Mar 2026 02:42:34 +0200 Subject: [PATCH 06/59] Fix compile errors --- src/network/ServerSideNetworkHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 5472b4d..50c5059 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -550,7 +550,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, WantCrea wantCreate.count = packet->count; wantCreate.setAuxValue(packet->auxValue); - Recipe* recipe = Recipe::getInstance()->getRecipeFor(wantCreate); + Recipe* recipe = Recipes::getInstance()->getRecipeFor(wantCreate); std::vector items = recipe->getItemPack().getItemInstances(); From 8098ab890694461b7b07a3cd6e6ade39ade40b25 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Fri, 27 Mar 2026 02:48:56 +0200 Subject: [PATCH 07/59] easy --- src/network/ServerSideNetworkHandler.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 50c5059..593b848 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -569,10 +569,14 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, WantCrea } } } - + + if (checkForExists.empty()) { + return; + } + for (int i = 0; i < items.size(); i++) { auto item = items.at(i); - + auto it = std::find(checkForExists.begin(), checkForExists.end(), item.id); if (it == checkForExists.end() && checkForExists.size() > 1) { From aeef442f7623e3c3bdf4fce270708fd39dae494e Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Fri, 27 Mar 2026 04:02:27 +0300 Subject: [PATCH 08/59] FIX: Server-side item remove when crafting --- src/network/ServerSideNetworkHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 593b848..36b1013 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -588,7 +588,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, WantCrea RemoveItemPacket removePacket(packet->playerId, items.at(i).count, items.at(i).getAuxValue(), items.at(i).id); raknetInstance->send(source, removePacket); - p->inventory->removeItem(new ItemInstance(items.at(i).id, items.at(i).count, items.at(i).getAuxValue())); + p->inventory->removeResource(ItemInstance(items.at(i).id, items.at(i).count, items.at(i).getAuxValue())); } TakeItemPacket itemAdd(p->entityId, wantCreate.count, wantCreate.getAuxValue(), wantCreate.id); raknetInstance->send(source, itemAdd); From 28febb4e63e881d2f61e704a5ef14294d1a2c2aa Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Fri, 27 Mar 2026 14:01:49 +0300 Subject: [PATCH 09/59] FIX: tool durablity mismatch --- src/network/ServerSideNetworkHandler.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 36b1013..9228e0f 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -385,9 +385,24 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveBl 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)) + if (minecraft->gameMode->isSurvivalType() && player->canDestroy(oldTile)) { + // From SurvivalMode.cpp + // Why tf i have to copy this shit from SurvivalMode class + // Why SurvivalMode class locked to LOCAL MINECRAFT PLAYER :sob: :sob: :sob: :sob: :sob: :sob: :sob: :sob: + // @fix @warn @ahtung @alert + ItemInstance* item = player->inventory->getSelected(); + if (item != NULL) { + item->mineBlock(oldTile->id, x, y, z); + if (item->count == 0) { + //item->snap(minecraft->player); + player->inventory->clearSlot(player->inventory->selected); + } + } + //oldTile->spawnResources(level, x, y, z, data, 1); //@todo oldTile->playerDestroy(level, player, x, y, z, data); + } + oldTile->destroy(level, x, y, z, data); } From f9d9a0f0f95fab778d36bfa23529cb8f4ecbab91 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Fri, 27 Mar 2026 13:47:33 +0200 Subject: [PATCH 10/59] FIX: Recheck recipes in MP --- .../screens/crafting/PaneCraftingScreen.cpp | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/client/gui/screens/crafting/PaneCraftingScreen.cpp b/src/client/gui/screens/crafting/PaneCraftingScreen.cpp index 4a23720..b07c1e6 100755 --- a/src/client/gui/screens/crafting/PaneCraftingScreen.cpp +++ b/src/client/gui/screens/crafting/PaneCraftingScreen.cpp @@ -19,6 +19,9 @@ #include "network/RakNetInstance.h" #include "network/packet/WantCreatePacket.h" #include "platform/input/Keyboard.h" +#include +#include +#include static NinePatchLayer* guiPaneFrame = NULL; @@ -195,6 +198,26 @@ void PaneCraftingScreen::setupPositions() { } void PaneCraftingScreen::tick() { + if (minecraft->isOnline()) { + // TODO: Make better algorithm + static std::map oldMap = {}; + std::map newMap = {}; + + for (int i = Inventory::MAX_SELECTION_SIZE; i < minecraft->player->inventory->getContainerSize(); ++i) { + auto itm = minecraft->player->inventory->getItem(i); + + if (itm != NULL) { + newMap[itm->id] += itm->count; + } + } + + if (oldMap != newMap) { + oldMap = newMap; + newMap = {}; + recheckRecipes(); + } + } + if (pane) pane->tick(); } From 6957f144e1e32e1228756907a1bcc6bccda2f6f2 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Fri, 27 Mar 2026 17:05:50 +0200 Subject: [PATCH 11/59] FIX: Inventory change when cheating items (TODO: Linked slots) --- src/network/ClientSideNetworkHandler.cpp | 12 ++++++++++++ src/network/ClientSideNetworkHandler.h | 1 + src/network/ServerSideNetworkHandler.cpp | 6 ++++++ 3 files changed, 19 insertions(+) diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index fc3a815..696e918 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -386,6 +386,18 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3); } } + +void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SendInventoryPacket* packet) { + if (!level) return; + + // TODO: Linked slots + if (packet->entityId == minecraft->player->entityId) { + auto items = packet->items; + + minecraft->player->inventory->replace(items); + } +} + void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, TakeItemPacket* packet) { if (!level) return; diff --git a/src/network/ClientSideNetworkHandler.h b/src/network/ClientSideNetworkHandler.h index b0cb98f..4847c74 100755 --- a/src/network/ClientSideNetworkHandler.h +++ b/src/network/ClientSideNetworkHandler.h @@ -80,6 +80,7 @@ public: virtual void handle(const RakNet::RakNetGUID& source, RemoveItemPacket* packet); virtual void handle(const RakNet::RakNetGUID& source, TakeItemPacket* packet); virtual void handle(const RakNet::RakNetGUID& source, WantCreatePacket* packet); + virtual void handle(const RakNet::RakNetGUID& source, SendInventoryPacket* packet); private: diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 9228e0f..c897591 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -7,6 +7,7 @@ #include "../world/inventory/BaseContainerMenu.h" #include "network/packet/ContainerSetSlotPacket.h" #include "network/packet/RemoveBlockPacket.h" +#include "network/packet/SendInventoryPacket.h" #include "network/packet/UpdateBlockPacket.h" #include "network/packet/RemoveItemPacket.h" #include "network/packet/TakeItemPacket.h" @@ -359,6 +360,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay //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); @@ -477,6 +479,10 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, PlayerEq if (slot < 0 && packet->itemId != 0) { LOGW("PlayerEquipmentPacket: Remote player doesn't have his thing (or crafted it)!\n"); + + SendInventoryPacket newInventory (player, false); + raknetInstance->send(newInventory); + return; } From 8be842a8ac9fe051069b1dfe5d54521caac2c82c Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Fri, 27 Mar 2026 19:41:54 +0200 Subject: [PATCH 12/59] FEAT: player anticheat speed --- src/client/Minecraft.h | 5 ++- src/client/renderer/entity/PlayerRenderer.cpp | 4 +-- src/network/ServerSideNetworkHandler.cpp | 21 +++++++++--- src/server/ServerLevel.cpp | 32 ++++++++++++------- src/server/ServerPlayer.h | 5 +++ 5 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/client/Minecraft.h b/src/client/Minecraft.h index 1a90b12..a7f5abc 100755 --- a/src/client/Minecraft.h +++ b/src/client/Minecraft.h @@ -120,6 +120,8 @@ public: void optionUpdated(OptionId option, bool value); void optionUpdated(OptionId option, float value); void optionUpdated(OptionId option, int value); + + int getTicks() { return ticks; } #ifdef __APPLE__ bool _isSuperFast; bool isSuperFast() { return _isSuperFast; } @@ -197,7 +199,8 @@ public: std::string externalCacheStoragePath; protected: Timer timer; - // @note @attn @warn: this is dangerous as fuck! + + // @note @attn @warn: this is dangerous as fuck! volatile bool isGeneratingLevel; bool _hasSignaledGeneratingLevelFinished; diff --git a/src/client/renderer/entity/PlayerRenderer.cpp b/src/client/renderer/entity/PlayerRenderer.cpp index 96ee2eb..092b9dc 100755 --- a/src/client/renderer/entity/PlayerRenderer.cpp +++ b/src/client/renderer/entity/PlayerRenderer.cpp @@ -77,10 +77,10 @@ void PlayerRenderer::render(Entity* mob_, float x, float y, float z, float rot, model = desired; humanoidModel = desired; } - LOGI("[PlayerRenderer] %s: skin=%s, modelTex=%dx%d, desired=%s\n", + /* LOGI("[PlayerRenderer] %s: skin=%s, modelTex=%dx%d, desired=%s\n", ((Player*)mob)->name.c_str(), mob->getTexture().c_str(), humanoidModel->texWidth, humanoidModel->texHeight, - (desired == playerModel64 ? "64" : "32")); + (desired == playerModel64 ? "64" : "32")); */ HumanoidMobRenderer::render(mob_, x, y, z, rot, a); } diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index c897591..996a567 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -21,6 +21,7 @@ #include "../raknet/RakPeerInterface.h" #include "../raknet/PacketPriority.h" #include "platform/log.h" +#include "util/Mth.h" #include "world/item/ItemInstance.h" #include "world/phys/Vec3.h" #include "world/item/crafting/Recipe.h" @@ -360,12 +361,22 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay //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); + ServerPlayer* player = (ServerPlayer*) getPlayer(source); - // broadcast this packet to other clients - redistributePacket(packet, source); + float vectorDist = sqrt( (packet->x - entity->x) * (packet->x - entity->x) + + (packet->y - entity->y) * (packet->y - entity->y) + + (packet->z - entity->z) * (packet->z - entity->z)); + float speed = vectorDist / (minecraft->getTicks() - player->lastMoveTicks); + + if (speed < 2.5f) { + 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); + } + + player->lastMoveTicks = minecraft->getTicks(); } } diff --git a/src/server/ServerLevel.cpp b/src/server/ServerLevel.cpp index e57d6b8..d65ee86 100755 --- a/src/server/ServerLevel.cpp +++ b/src/server/ServerLevel.cpp @@ -12,16 +12,19 @@ ServerLevel::ServerLevel(LevelStorage* levelStorage, const std::string& levelNam void ServerLevel::updateSleepingPlayerList() { bool allPlayersWasSleeping = allPlayersAreSleeping; allPlayersAreSleeping = !players.empty(); - for(PlayerList::iterator it = players.begin(); it != players.end(); ++it) { + + for (PlayerList::iterator it = players.begin(); it != players.end(); ++it) { Player* player = *it; - if(!player->isSleeping()) { + + if (!player->isSleeping()) { allPlayersAreSleeping = false; break; } } - if(!allPlayersWasSleeping && allPlayersAreSleeping) { + if (!allPlayersWasSleeping && allPlayersAreSleeping) { levelEvent(NULL, LevelEvent::ALL_PLAYERS_SLEEPING, 0, 0, 0, 0); - for(PlayerList::iterator it = players.begin(); it != players.end(); ++it) { + + for (PlayerList::iterator it = players.begin(); it != players.end(); ++it) { (*it)->setAllPlayersSleeping(); } } @@ -29,23 +32,26 @@ void ServerLevel::updateSleepingPlayerList() { void ServerLevel::awakenAllPlayers() { allPlayersAreSleeping = false; - for(PlayerList::iterator it = players.begin(); it != players.end(); ++it) { + + for (PlayerList::iterator it = players.begin(); it != players.end(); ++it) { Player* player = *it; - if(player->isSleeping()) { + + if (player->isSleeping()) { player->stopSleepInBed(false, false, true); player->health = Player::MAX_HEALTH; player->lastHealth = Player::MAX_HEALTH; } } + SetHealthPacket packet(Player::MAX_HEALTH); raknetInstance->send(packet); } bool ServerLevel::allPlayersSleeping() { - if(allPlayersAreSleeping && !isClientSide) { + if (allPlayersAreSleeping && !isClientSide) { // all players are sleeping, but have they slept long enough? - for(PlayerList::iterator it = players.begin(); it != players.end(); ++it) { - if(!(*it)->isSleepingLongEnough()) { + for (PlayerList::iterator it = players.begin(); it != players.end(); ++it) { + if (!(*it)->isSleepingLongEnough()) { return false; } } @@ -55,13 +61,17 @@ bool ServerLevel::allPlayersSleeping() { return false; } -void ServerLevel::tick(){ +void ServerLevel::tick() { super::tick(); - if(allPlayersSleeping()) { + + if (allPlayersSleeping()) { long newTime = levelData.getTime() + TICKS_PER_DAY; + levelData.setTime(newTime - (newTime % TICKS_PER_DAY)); + SetTimePacket packet(levelData.getTime()); raknetInstance->send(packet); + awakenAllPlayers(); } } diff --git a/src/server/ServerPlayer.h b/src/server/ServerPlayer.h index de20661..c95a066 100755 --- a/src/server/ServerPlayer.h +++ b/src/server/ServerPlayer.h @@ -43,6 +43,11 @@ public: virtual void stopSleepInBed(bool forcefulWakeUp, bool updateLevelList, bool saveRespawnPoint); void completeUsingItem(); + + // Getter and setter? Doesnt hear about that + // TODO: Getter and setter :trollface: + int lastMoveTicks = 0; + int ticksInAir = 0; private: void nextContainerCounter(); void setContainerMenu( BaseContainerMenu* menu ); From 97b0fb4d4678f2948c71c7e3e6c95db336c7d496 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Fri, 27 Mar 2026 20:16:59 +0200 Subject: [PATCH 13/59] FEAT: New proto check --- src/SharedConstants.h | 5 ++--- src/network/ClientSideNetworkHandler.cpp | 2 +- src/network/ServerSideNetworkHandler.cpp | 15 +++++++++------ src/network/packet/LoginPacket.h | 15 ++++++++++++--- src/server/ServerPlayer.cpp | 5 +++-- src/server/ServerPlayer.h | 19 ++++++++++++++----- 6 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/SharedConstants.h b/src/SharedConstants.h index dcae293..f97ea36 100755 --- a/src/SharedConstants.h +++ b/src/SharedConstants.h @@ -16,9 +16,8 @@ namespace SharedConstants { // 0.5.0 uses NPv8 // 0.6.0 uses NPv9 - // TODO: Better proto check - const int NetworkProtocolVersion = 10; - const int NetworkProtocolLowestSupportedVersion = 10; + const int NetworkProtocolVersion = 9; + const int NetworkProtocolLowestSupportedVersion = 9; const int GameProtocolVersion = 1; const int GameProtocolLowestSupportedVersion = 1; diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index 696e918..53570d5 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -87,7 +87,7 @@ void ClientSideNetworkHandler::onConnect(const RakNet::RakNetGUID& hostGuid) serverGuid = hostGuid; clearChunksLoaded(); - LoginPacket packet(minecraft->options.getStringValue(OPTIONS_USERNAME).c_str(), SharedConstants::NetworkProtocolVersion); + LoginPacket packet(minecraft->options.getStringValue(OPTIONS_USERNAME).c_str(), SharedConstants::NetworkProtocolVersion, true); raknetInstance->send(packet); } diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 996a567..fbb9308 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -194,7 +194,6 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac LOGI("LoginPacket\n"); - printf("%d", packet->clientNetworkVersion); int loginStatus = LoginStatus::Success; // // Bad/incompatible client version @@ -204,6 +203,9 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac if (oldClient || oldServer) loginStatus = oldClient? LoginStatus::Failed_ClientOld : LoginStatus::Failed_ServerOld; + if (packet->newProto) { + printf("New proto! \n"); + } RakNet::BitStream bitStream; LoginStatusPacket(loginStatus).write(&bitStream); rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false); @@ -214,8 +216,9 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac // // Valid client version // - Player* newPlayer = new ServerPlayer(minecraft, level); - + + Player* newPlayer = new ServerPlayer(minecraft, level, packet->newProto); + minecraft->gameMode->initAbilities(newPlayer->abilities); newPlayer->owner = source; newPlayer->name = packet->clientName.C_String(); @@ -366,7 +369,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay float vectorDist = sqrt( (packet->x - entity->x) * (packet->x - entity->x) + (packet->y - entity->y) * (packet->y - entity->y) + (packet->z - entity->z) * (packet->z - entity->z)); - float speed = vectorDist / (minecraft->getTicks() - player->lastMoveTicks); + float speed = vectorDist / (minecraft->getTicks() - player->getLastMoveTicks()); if (speed < 2.5f) { entity->xd = entity->yd = entity->zd = 0; @@ -376,7 +379,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay redistributePacket(packet, source); } - player->lastMoveTicks = minecraft->getTicks(); + player->setLastMoveTicks(minecraft->getTicks()); } } @@ -512,7 +515,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, PlayerAr if (!player) return; if (rakPeer->GetMyGUID() == player->owner) return; - LOGI("Equip armor: %i %i %i %i\n", packet->head, packet->torso, packet->legs, packet->feet); + // LOGI("Equip armor: %i %i %i %i\n", packet->head, packet->torso, packet->legs, packet->feet); packet->fillIn(player); redistributePacket(packet, source); diff --git a/src/network/packet/LoginPacket.h b/src/network/packet/LoginPacket.h index b44a44a..50caee3 100755 --- a/src/network/packet/LoginPacket.h +++ b/src/network/packet/LoginPacket.h @@ -9,17 +9,20 @@ public: RakNet::RakString clientName; int clientNetworkVersion; int clientNetworkLowestSupportedVersion; + bool newProto; LoginPacket() : clientNetworkVersion(-1), - clientNetworkLowestSupportedVersion(-1) + clientNetworkLowestSupportedVersion(-1), + newProto(false) { } - LoginPacket(const RakNet::RakString& clientName, int clientVersion) + LoginPacket(const RakNet::RakString& clientName, int clientVersion, bool newProto) : clientName(clientName), clientNetworkVersion(clientVersion), - clientNetworkLowestSupportedVersion(clientVersion) + clientNetworkLowestSupportedVersion(clientVersion), + newProto(newProto) { } @@ -29,6 +32,7 @@ public: bitStream->Write(clientName); bitStream->Write(clientNetworkVersion); bitStream->Write(clientNetworkLowestSupportedVersion); + bitStream->Write(newProto); } void read(RakNet::BitStream* bitStream) @@ -39,6 +43,11 @@ public: if (bitStream->GetNumberOfUnreadBits() > 0) { bitStream->Read(clientNetworkVersion); bitStream->Read(clientNetworkLowestSupportedVersion); + + // Checking for new proto + if (bitStream->GetNumberOfUnreadBits() > 0) { + bitStream->Read(newProto); + } } } diff --git a/src/server/ServerPlayer.cpp b/src/server/ServerPlayer.cpp index c27ae38..3f89033 100755 --- a/src/server/ServerPlayer.cpp +++ b/src/server/ServerPlayer.cpp @@ -22,11 +22,12 @@ #include "network/packet/SendInventoryPacket.h" #include "world/entity/player/Inventory.h" -ServerPlayer::ServerPlayer( Minecraft* minecraft, Level* level ) +ServerPlayer::ServerPlayer( Minecraft* minecraft, Level* level, bool proto) : super(level, minecraft->isCreativeMode()), _mc(minecraft), _prevHealth(-999), - _containerCounter(0) + _containerCounter(0), + isNewProto(proto) { // hasFakeInventory = true; footSize = 0; diff --git a/src/server/ServerPlayer.h b/src/server/ServerPlayer.h index c95a066..77579d9 100755 --- a/src/server/ServerPlayer.h +++ b/src/server/ServerPlayer.h @@ -15,7 +15,7 @@ class ServerPlayer: public Player, { typedef Player super; public: - ServerPlayer(Minecraft* minecraft, Level* level); + ServerPlayer(Minecraft* minecraft, Level* level, bool proto); ~ServerPlayer(); @@ -44,10 +44,14 @@ public: void completeUsingItem(); - // Getter and setter? Doesnt hear about that - // TODO: Getter and setter :trollface: - int lastMoveTicks = 0; - int ticksInAir = 0; + void setLastMoveTicks(int lastMoveTicks) { this->lastMoveTicks = lastMoveTicks; } + int getLastMoveTicks() { return lastMoveTicks; } + + void setTicksInAir(int ticksInAir) { this->ticksInAir = ticksInAir; } + int getTicksInAir() { return ticksInAir; } + + void setNewProto(bool proto) { isNewProto = proto; } + bool getProto() { return isNewProto; } private: void nextContainerCounter(); void setContainerMenu( BaseContainerMenu* menu ); @@ -55,6 +59,11 @@ private: Minecraft* _mc; int _prevHealth; int _containerCounter; + + int lastMoveTicks = 0; + int ticksInAir = 0; + + bool isNewProto = false; }; #endif /*ServerPlayer_H__*/ From eed3a6df6142e17ef7c4849259f45df8c44d753f Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Fri, 27 Mar 2026 20:22:05 +0200 Subject: [PATCH 14/59] FEAT: Message for outdated clients --- src/network/ServerSideNetworkHandler.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index fbb9308..5fe00a4 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -203,9 +203,6 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac if (oldClient || oldServer) loginStatus = oldClient? LoginStatus::Failed_ClientOld : LoginStatus::Failed_ServerOld; - if (packet->newProto) { - printf("New proto! \n"); - } RakNet::BitStream bitStream; LoginStatusPacket(loginStatus).write(&bitStream); rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false); @@ -252,6 +249,11 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac ).write(&bitStream); rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false); + + if (!packet->newProto) { + MessagePacket packet("You're using outdated client. Some features disabled."); + raknetInstance->send(packet); + } } } From 61a2349b8bbd0cd67813d8d8ca39dfa90cd268b6 Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Fri, 27 Mar 2026 21:26:25 +0300 Subject: [PATCH 15/59] FEAT: Player data saving/loading --- src/client/gamemode/SurvivalMode.cpp | 1 + src/network/ClientSideNetworkHandler.cpp | 5 ++ src/network/ServerSideNetworkHandler.cpp | 33 +++++++++ src/network/packet/SendInventoryPacket.h | 26 ++++++- .../storage/ExternalFileLevelStorage.cpp | 68 +++++++++++++++++++ .../level/storage/ExternalFileLevelStorage.h | 13 ++++ src/world/level/storage/LevelStorage.h | 3 + 7 files changed, 146 insertions(+), 3 deletions(-) diff --git a/src/client/gamemode/SurvivalMode.cpp b/src/client/gamemode/SurvivalMode.cpp index ac49fda..c53c198 100755 --- a/src/client/gamemode/SurvivalMode.cpp +++ b/src/client/gamemode/SurvivalMode.cpp @@ -68,6 +68,7 @@ bool SurvivalMode::destroyBlock( int x, int y, int z, int face ) { minecraft->player->inventory->clearSlot(minecraft->player->inventory->selected); } } + if (changed && couldDestroy) { ItemInstance instance(t, 1, data); Tile::tiles[t]->playerDestroy(minecraft->level, minecraft->player, x, y, z, data); diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index 696e918..aa15ed3 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -395,6 +395,11 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SendInve auto items = packet->items; minecraft->player->inventory->replace(items); + + for (int i = 0; i < packet->linkedSlot.size(); i++) { + minecraft->player->inventory->linkSlot(i, packet->linkedSlot[i].inventorySlot, true); + LOGI("%i -> %i\n", packet->linkedSlot[i].inventorySlot, i); + } } } diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index c897591..6032c0e 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -22,6 +22,7 @@ #include "../raknet/PacketPriority.h" #include "platform/log.h" #include "world/item/ItemInstance.h" +#include "world/level/storage/LevelStorage.h" #include "world/phys/Vec3.h" #include "world/item/crafting/Recipe.h" #include "world/item/crafting/Recipes.h" @@ -169,6 +170,8 @@ void ServerSideNetworkHandler::onDisconnect(const RakNet::RakNetGUID& guid) if (player->owner == guid) { + minecraft->level->getLevelStorage()->savePlayer(*player); + std::string message = player->name; message += " disconnected from the game"; displayGameMessage(message); @@ -319,6 +322,36 @@ void ServerSideNetworkHandler::onReady_ClientGeneration(const RakNet::RakNetGUID } } + if (!minecraft->level->getLevelStorage()->loadPlayer(*newPlayer)) { + LOGW("Failed to load %s data\n", newPlayer->name.c_str()); + } + + // Credits to EpikIzCool + bitStream.Reset(); + MovePlayerPacket mv(newPlayer->entityId, newPlayer->x, newPlayer->y - newPlayer->heightOffset, + newPlayer->z, newPlayer->xRot, newPlayer->yRot); + mv.write(&bitStream); + + rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false); + + bitStream.Reset(); + SetHealthPacket hp(newPlayer->health); + hp.write(&bitStream); + + rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false); + + if (newPlayer->hasRespawnPosition()) { + bitStream.Reset(); + SetSpawnPositionPacket sp(newPlayer->getRespawnPosition()); + sp.write(&bitStream); + rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false); + } + + bitStream.Reset(); + SendInventoryPacket(newPlayer, false).write(&bitStream); + rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false); + + // Additional packets // * set spawn /* diff --git a/src/network/packet/SendInventoryPacket.h b/src/network/packet/SendInventoryPacket.h index 482ef51..b744b58 100755 --- a/src/network/packet/SendInventoryPacket.h +++ b/src/network/packet/SendInventoryPacket.h @@ -3,13 +3,13 @@ #include "../Packet.h" #include "world/entity/player/Inventory.h" +#include "world/inventory/FillingContainer.h" +#include class SendInventoryPacket: public Packet { public: - SendInventoryPacket() - { - } + SendInventoryPacket() {} SendInventoryPacket(Player* player, bool dropItems) : entityId(player->entityId), @@ -22,10 +22,15 @@ public: 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()); } + + for (int i = 0; i < inv->numLinkedSlots; ++i) { + linkedSlot[i] = inv->linkedSlots[i]; + } } void write(RakNet::BitStream* bitStream) @@ -40,6 +45,13 @@ public: // Armor for (int i = 0; i < NumArmorItems; ++i) PacketUtil::writeItemInstance(items[i + numItems], bitStream); + + int lSlots = Inventory::MAX_SELECTION_SIZE; + + // Linked slots + bitStream->Write(lSlots); + for (int i = 0; i < lSlots; ++i) + bitStream->Write(linkedSlot[i]); } void read(RakNet::BitStream* bitStream) @@ -51,6 +63,12 @@ public: // Inventory, Armor for (int i = 0; i < numItems + NumArmorItems; ++i) items.push_back(PacketUtil::readItemInstance(bitStream)); + + // Linked slots + int lSlots = 0; + bitStream->Read(lSlots); + for (int i = 0; i < lSlots; ++i) + bitStream->Read(linkedSlot[i]); } void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) @@ -63,6 +81,8 @@ public: short numItems; unsigned char extra; + std::array linkedSlot; + static const int ExtraDrop = 1; static const int NumArmorItems = 4; }; diff --git a/src/world/level/storage/ExternalFileLevelStorage.cpp b/src/world/level/storage/ExternalFileLevelStorage.cpp index 91bcf45..03cca08 100755 --- a/src/world/level/storage/ExternalFileLevelStorage.cpp +++ b/src/world/level/storage/ExternalFileLevelStorage.cpp @@ -1,3 +1,6 @@ +#include +#include +#include #if !defined(DEMO_MODE) && !defined(APPLE_DEMO_PROMOTION) #include "LevelData.h" @@ -88,6 +91,9 @@ ExternalFileLevelStorage::ExternalFileLevelStorage(const std::string& levelId, c { createFolderIfNotExists(levelPath.c_str()); + std::string playerFolder = levelPath + "/players"; + createFolderIfNotExists(playerFolder.c_str()); + std::string datFileName = levelPath + "/" + fnLevelDat; std::string levelFileName = levelPath + "/" + fnPlayerDat; loadedLevelData = new LevelData(); @@ -113,6 +119,7 @@ void ExternalFileLevelStorage::saveLevelData(LevelData& levelData, std::vector

* players ) { + // @todo: completely rewrite std::string directory = levelPath + "/"; std::string tmpFile = directory + fnLevelDatNew; std::string datFile = directory + fnLevelDat; @@ -141,6 +148,67 @@ void ExternalFileLevelStorage::saveLevelData( const std::string& levelPath, Leve // Remove the temporary save, if the rename didn't do it remove(tmpFile.c_str()); + + // Save players + // fuck mojang for that + if (!players || players->empty()) { + return; + } + + for (auto& player : *players) { + if (player != NULL) { + savePlayer(*player, directory); + } + } +} + +void ExternalFileLevelStorage::savePlayer(Player& player, const std::string& worldDir) { + std::string playerPath = worldDir + "/players/" + player.name + ".dat"; + + LOGI("Saving player %s to %s...\n", player.name.c_str(), playerPath.c_str()); + + RakNet::BitStream data; + RakDataOutput buf(data); + CompoundTag playerTag; + player.saveWithoutId(&playerTag); + + NbtIo::write(&playerTag, &buf); + + std::ofstream file(playerPath, std::ios::out | std::ios::binary); + file.write((const char*)data.GetData(), (size_t)data.GetNumberOfBytesUsed()); +} + +bool ExternalFileLevelStorage::loadPlayer(Player& player, const std::string& worldDir) { + std::string playerPath = worldDir + "/players/" + player.name + ".dat"; + + LOGI("Loading player %s from %s...\n", player.name.c_str(), playerPath.c_str()); + + std::ifstream file(playerPath, std::ios::in | std::ios::binary); + if (!file.is_open()) { + return false; + } + + std::vector data((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + + RakNet::BitStream bitStream(data.data(), data.size(), false); + RakDataInput stream(bitStream); + + CompoundTag* tag = NbtIo::read(&stream); + if (tag) { + player.load(tag); + tag->deleteChildren(); + delete tag; + } + + return true; +} + +void ExternalFileLevelStorage::savePlayer(Player& player) { + ExternalFileLevelStorage::savePlayer(player, levelPath); +} + +bool ExternalFileLevelStorage::loadPlayer(Player& player) { + return ExternalFileLevelStorage::loadPlayer(player, levelPath); } LevelData* ExternalFileLevelStorage::prepareLevel(Level* _level) diff --git a/src/world/level/storage/ExternalFileLevelStorage.h b/src/world/level/storage/ExternalFileLevelStorage.h index b7dd960..9aad448 100755 --- a/src/world/level/storage/ExternalFileLevelStorage.h +++ b/src/world/level/storage/ExternalFileLevelStorage.h @@ -67,6 +67,19 @@ public: void saveGame(Level* level); void saveAll(Level* level, std::vector& levelChunks); + /** + * @brief Save player to /player/.dat file + */ + static void savePlayer(Player& player, const std::string& worldDir); + + /** + * @brief Load player from /player/.dat file + */ + static bool loadPlayer(Player& player, const std::string& worldDir); + + virtual void savePlayer(Player& player); + virtual bool loadPlayer(Player& player); + virtual void tick(); virtual void flush() {} private: diff --git a/src/world/level/storage/LevelStorage.h b/src/world/level/storage/LevelStorage.h index 84c0f62..d3098d2 100755 --- a/src/world/level/storage/LevelStorage.h +++ b/src/world/level/storage/LevelStorage.h @@ -32,6 +32,9 @@ public: virtual void saveGame(Level* level) {} virtual void loadEntities(Level* level, LevelChunk* levelChunk) {} + virtual void savePlayer(Player& player) = 0; + virtual bool loadPlayer(Player& player) = 0; + //void checkSession() throws LevelConflictException; //PlayerIO getPlayerIO(); }; From 6d696af2358a9f216934e6c8dce3edd73562393c Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Fri, 27 Mar 2026 21:08:17 +0200 Subject: [PATCH 16/59] FEAT: taken nickname --- src/network/ClientSideNetworkHandler.cpp | 7 +++++++ src/network/ServerSideNetworkHandler.cpp | 9 +++++++++ src/network/packet/LoginStatusPacket.h | 2 ++ 3 files changed, 18 insertions(+) diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index c2eb5a7..df0a02d 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -1,6 +1,7 @@ #include "ClientSideNetworkHandler.h" #include "client/Options.h" +#include "network/packet/LoginStatusPacket.h" #include "packet/PacketInclude.h" #include "RakNetInstance.h" #include "../world/level/chunk/ChunkSource.h" @@ -131,6 +132,12 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginSta LOGI("Disconnect! Server is outdated!\n"); #ifndef STANDALONE_SERVER minecraft->setScreen(new DisconnectionScreen("Could not connect: Outdated server!")); +#endif + } + if (packet->status == LoginStatus::Failed_TakenNickname) { + LOGI("Disconnect! Nickname is taken!\n"); +#ifndef STANDALONE_SERVER + minecraft->setScreen(new DisconnectionScreen("Could not connect: Nickname is taken!")); #endif } } diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 0a2fe13..a75b796 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -6,6 +6,7 @@ #include "../world/Container.h" #include "../world/inventory/BaseContainerMenu.h" #include "network/packet/ContainerSetSlotPacket.h" +#include "network/packet/LoginStatusPacket.h" #include "network/packet/RemoveBlockPacket.h" #include "network/packet/SendInventoryPacket.h" #include "network/packet/UpdateBlockPacket.h" @@ -206,6 +207,14 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac if (oldClient || oldServer) loginStatus = oldClient? LoginStatus::Failed_ClientOld : LoginStatus::Failed_ServerOld; + for (int i = 0; i < level->players.size(); i++) { + ServerPlayer* player = (ServerPlayer*) level->players.at(i); + + if (player->name == packet->clientName.C_String()) { + loginStatus = packet->newProto ? LoginStatus::Failed_TakenNickname : LoginStatus::Failed_ClientOld; + } + } + RakNet::BitStream bitStream; LoginStatusPacket(loginStatus).write(&bitStream); rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false); diff --git a/src/network/packet/LoginStatusPacket.h b/src/network/packet/LoginStatusPacket.h index b194f8f..efa10f5 100755 --- a/src/network/packet/LoginStatusPacket.h +++ b/src/network/packet/LoginStatusPacket.h @@ -3,10 +3,12 @@ #include "../Packet.h" +// wtf why not enum namespace LoginStatus { const int Success = 0; const int Failed_ClientOld = 1; const int Failed_ServerOld = 2; + const int Failed_TakenNickname = 3; } class LoginStatusPacket : public Packet { From 77d02fcca23398d904d8420b9ecf8c909d4d08e9 Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Fri, 27 Mar 2026 22:15:03 +0300 Subject: [PATCH 17/59] FIX: workbench compatibility --- .../screens/crafting/PaneCraftingScreen.cpp | 55 +++++++++---------- src/network/ServerSideNetworkHandler.cpp | 14 ++--- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/client/gui/screens/crafting/PaneCraftingScreen.cpp b/src/client/gui/screens/crafting/PaneCraftingScreen.cpp index b07c1e6..6d6e407 100755 --- a/src/client/gui/screens/crafting/PaneCraftingScreen.cpp +++ b/src/client/gui/screens/crafting/PaneCraftingScreen.cpp @@ -467,35 +467,34 @@ void PaneCraftingScreen::craftSelectedItem() if (minecraft->isOnline()) { WantCreatePacket packet(minecraft->player->entityId, resultItem.count, resultItem.getAuxValue(), resultItem.id); minecraft->raknetInstance->send(packet); - } else { - // Remove all items required for the recipe and ... - for (unsigned int i = 0; i < currentItem->neededItems.size(); ++i) { - CItem::ReqItem& req = currentItem->neededItems[i]; - - // If the recipe allows any aux-value as ingredients, first deplete - // aux == 0 from inventory. Since I'm not sure if this always is - // correct, let's only do it for ingredient sandstone for now. - ItemInstance toRemove = req.item; - - if (Tile::sandStone->id == req.item.id - && Recipe::ANY_AUX_VALUE == req.item.getAuxValue()) { - toRemove.setAuxValue(0); - toRemove.count = minecraft->player->inventory->removeResource(toRemove, true); - toRemove.setAuxValue(Recipe::ANY_AUX_VALUE); - } - - if (toRemove.count > 0) { - minecraft->player->inventory->removeResource(toRemove); - } - } - // ... add the new one! (in this order, to fill empty slots better) - // if it doesn't fit, throw it on the ground! - if (!minecraft->player->inventory->add(&resultItem)) { - minecraft->player->drop(new ItemInstance(resultItem), false); - } - - recheckRecipes(); } + // Remove all items required for the recipe and ... + for (unsigned int i = 0; i < currentItem->neededItems.size(); ++i) { + CItem::ReqItem& req = currentItem->neededItems[i]; + + // If the recipe allows any aux-value as ingredients, first deplete + // aux == 0 from inventory. Since I'm not sure if this always is + // correct, let's only do it for ingredient sandstone for now. + ItemInstance toRemove = req.item; + + if (Tile::sandStone->id == req.item.id + && Recipe::ANY_AUX_VALUE == req.item.getAuxValue()) { + toRemove.setAuxValue(0); + toRemove.count = minecraft->player->inventory->removeResource(toRemove, true); + toRemove.setAuxValue(Recipe::ANY_AUX_VALUE); + } + + if (toRemove.count > 0) { + minecraft->player->inventory->removeResource(toRemove); + } + } + // ... add the new one! (in this order, to fill empty slots better) + // if it doesn't fit, throw it on the ground! + if (!minecraft->player->inventory->add(&resultItem)) { + minecraft->player->drop(new ItemInstance(resultItem), false); + } + + recheckRecipes(); } } diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 0a2fe13..5ac2ebd 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -654,14 +654,14 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, WantCrea } } - for (int i = 0; i < items.size(); i++) { - RemoveItemPacket removePacket(packet->playerId, items.at(i).count, items.at(i).getAuxValue(), items.at(i).id); - raknetInstance->send(source, removePacket); + // for (int i = 0; i < items.size(); i++) { + // RemoveItemPacket removePacket(packet->playerId, items.at(i).count, items.at(i).getAuxValue(), items.at(i).id); + // raknetInstance->send(source, removePacket); - p->inventory->removeResource(ItemInstance(items.at(i).id, items.at(i).count, items.at(i).getAuxValue())); - } - TakeItemPacket itemAdd(p->entityId, wantCreate.count, wantCreate.getAuxValue(), wantCreate.id); - raknetInstance->send(source, itemAdd); + // p->inventory->removeResource(ItemInstance(items.at(i).id, items.at(i).count, items.at(i).getAuxValue())); + // } + // TakeItemPacket itemAdd(p->entityId, wantCreate.count, wantCreate.getAuxValue(), wantCreate.id); + // raknetInstance->send(source, itemAdd); p->inventory->add(new ItemInstance(wantCreate.id, wantCreate.count, wantCreate.getAuxValue())); } From bcf48eb5e3284d6bbfda72e9542c0052f16ae597 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Sat, 28 Mar 2026 16:41:00 +0200 Subject: [PATCH 18/59] FEAT: Damage on server --- src/client/Minecraft.cpp | 2 +- src/main_dedicated.cpp | 9 ++++++ src/network/ClientSideNetworkHandler.cpp | 2 ++ src/network/ServerSideNetworkHandler.cpp | 38 +++++++++++++----------- src/server/ArgumentsSettings.cpp | 8 +++++ src/server/ArgumentsSettings.h | 7 +++++ src/server/ServerPlayer.cpp | 1 + 7 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/client/Minecraft.cpp b/src/client/Minecraft.cpp index 6487664..51ad3a3 100755 --- a/src/client/Minecraft.cpp +++ b/src/client/Minecraft.cpp @@ -553,7 +553,7 @@ void Minecraft::tick(int nTick, int maxTick) { level->tickEntities(); level->tick(); #ifndef STANDALONE_SERVER - TIMER_POP_PUSH("animateTick"); + TIMER_POP_PUSH("animateTick"); if (player) { level->animateTick(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z)); } diff --git a/src/main_dedicated.cpp b/src/main_dedicated.cpp index 8aa14cb..9c0e812 100755 --- a/src/main_dedicated.cpp +++ b/src/main_dedicated.cpp @@ -30,20 +30,29 @@ void signal_callback_handler(int signum) { int main(int numArguments, char* pszArgs[]) { ArgumentsSettings aSettings(numArguments, pszArgs); if(aSettings.getShowHelp()) { + // TODO: Map with args and print it with std::cout and for loop + // TODO: World size setting + ArgumentsSettings defaultSettings(0, NULL); + printf("Minecraft Pockect Edition Server %s\n", Common::getGameVersionString("").c_str()); printf("-------------------------------------------------------\n"); + printf("--cachepath - Path to where the server can store temp stuff (not sure if this is used) [default: \"%s\"]\n", defaultSettings.getCachePath().c_str()); printf("--externalpath - The path to the place where the server should store the levels. [default: \"%s\"]\n", defaultSettings.getExternalPath().c_str()); printf("--levelname - The name of the server [default: \"%s\"]\n", defaultSettings.getLevelName().c_str()); + printf("--gamemode - The name of the gamemode [default: \"%s\"]\n", defaultSettings.getGamemode().c_str()); printf("--leveldir - The name of the server [default: \"%s\"]\n", defaultSettings.getLevelDir().c_str()); printf("--help - Shows this message.\n"); printf("--port - The port to run the server on. [default: %d]\n", defaultSettings.getPort()); printf("--serverkey - The key that the server should use for API calls. [default: \"%s\"]\n", defaultSettings.getServerKey().c_str()); + printf("-------------------------------------------------------\n"); + return 0; } printf("Level Name: %s\n", aSettings.getLevelName().c_str()); + AppContext appContext; appContext.platform = new AppPlatform(); App* app = new MAIN_CLASS(); diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index df0a02d..213ff28 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -352,6 +352,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AddItemE } void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, TakeItemEntityPacket* packet) { + printf("TakeItemEntityPacket \n"); if (!level) return; Entity* e = level->getEntity(packet->itemId); @@ -852,6 +853,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SetHealt if (!level || !minecraft->player) return; + printf("SetHealthPacket \n"); minecraft->player->hurtTo(packet->health); } diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index c2ae85c..78f02db 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -414,14 +414,16 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay (packet->y - entity->y) * (packet->y - entity->y) + (packet->z - entity->z) * (packet->z - entity->z)); float speed = vectorDist / (minecraft->getTicks() - player->getLastMoveTicks()); - - if (speed < 2.5f) { - entity->xd = entity->yd = entity->zd = 0; - entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3); + // TODO: Replace with Entity::move() + // if (speed < 2.5f) { + entity->xd = entity->yd = entity->zd = 0; + entity->move(packet->x - entity->x, packet->y - entity->y, packet->z - entity->z); + // entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3); + // broadcast this packet to other clients redistributePacket(packet, source); - } + //} player->setLastMoveTicks(minecraft->getTicks()); } @@ -459,7 +461,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveBl } } - //oldTile->spawnResources(level, x, y, z, data, 1); //@todo + oldTile->spawnResources(level, x, y, z, data, 1); //@todo oldTile->playerDestroy(level, player, x, y, z, data); } @@ -934,19 +936,19 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, Containe void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SetHealthPacket* packet ) { - LOGI("SetHealthPacket\n"); + LOGI("net idi nahui\n"); - 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; - } - } + // 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 ) { diff --git a/src/server/ArgumentsSettings.cpp b/src/server/ArgumentsSettings.cpp index 88bcd51..d41633c 100755 --- a/src/server/ArgumentsSettings.cpp +++ b/src/server/ArgumentsSettings.cpp @@ -17,6 +17,11 @@ ArgumentsSettings::ArgumentsSettings(int numArguments, char** arguments) levelName = std::string(arguments[a+1]); a++; // Skip the next argument since it's part of this one. } + } else if(strcmp(arguments[a], "--gamemode") == 0) { + if(a + 1 < numArguments) { + gamemode = std::string(arguments[a+1]); + a++; // Skip the next argument since it's part of this one. + } } else if(strcmp(arguments[a], "--leveldir") == 0) { if(a + 1 < numArguments) { levelDir = std::string(arguments[a+1]); @@ -51,6 +56,9 @@ std::string ArgumentsSettings::getServerKey() { std::string ArgumentsSettings::getCachePath() { return cachePath; } +std::string ArgumentsSettings::getGamemode() { + return gamemode; +} std::string ArgumentsSettings::getLevelDir() { return levelDir; } diff --git a/src/server/ArgumentsSettings.h b/src/server/ArgumentsSettings.h index 0dcd781..2861b48 100755 --- a/src/server/ArgumentsSettings.h +++ b/src/server/ArgumentsSettings.h @@ -4,20 +4,27 @@ class ArgumentsSettings { public: ArgumentsSettings(int numArguments, char** arguments); + std::string getExternalPath(); std::string getLevelName(); std::string getServerKey(); std::string getCachePath(); std::string getLevelDir(); + std::string getGamemode(); + bool getShowHelp(); + int getPort(); private: std::string cachePath; std::string externalPath; std::string levelName; + std::string gamemode; std::string levelDir; std::string serverKey; + bool showHelp; + int port; }; diff --git a/src/server/ServerPlayer.cpp b/src/server/ServerPlayer.cpp index 3f89033..da47976 100755 --- a/src/server/ServerPlayer.cpp +++ b/src/server/ServerPlayer.cpp @@ -72,6 +72,7 @@ void ServerPlayer::take( Entity* e, int orgCount ) { TakeItemEntityPacket packet(e->entityId, entityId); // SendInventoryPacket packet(this, false); _mc->raknetInstance->send(packet); + printf("TakeItemEntityPacket \n"); LOGI("Inventory:\n"); for (int i = 0; i < inventory->numLinkedSlots; i++) { From 73fb2a2b3dd57cf9fdcfa4abd06923163649a367 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Sat, 28 Mar 2026 17:18:38 +0200 Subject: [PATCH 19/59] wtf --- src/server/ServerPlayer.cpp | 9 +++++++++ src/server/ServerPlayer.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/src/server/ServerPlayer.cpp b/src/server/ServerPlayer.cpp index da47976..9f4f1dc 100755 --- a/src/server/ServerPlayer.cpp +++ b/src/server/ServerPlayer.cpp @@ -175,3 +175,12 @@ void ServerPlayer::displayClientMessage( const std::string& messageId ) { ChatPacket package(messageId); _mc->raknetInstance->send(owner, package); } + +void ServerPlayer::causeFallDamage(float distance) { + int dmg = (int) ceil((distance - 3)); + if (dmg > 0) { + SetHealthPacket packet(SetHealthPacket::HEALTH_MODIFY_OFFSET + dmg); + _mc->raknetInstance->send(owner, packet); + } + super::causeFallDamage(distance); +} \ No newline at end of file diff --git a/src/server/ServerPlayer.h b/src/server/ServerPlayer.h index 77579d9..c578025 100755 --- a/src/server/ServerPlayer.h +++ b/src/server/ServerPlayer.h @@ -52,6 +52,8 @@ public: void setNewProto(bool proto) { isNewProto = proto; } bool getProto() { return isNewProto; } + + virtual void causeFallDamage(float distance); private: void nextContainerCounter(); void setContainerMenu( BaseContainerMenu* menu ); From 5783fb93f369d6d4e4999a7df21863eb296cbb41 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Sat, 28 Mar 2026 17:39:37 +0200 Subject: [PATCH 20/59] forgot to comment --- src/network/ServerSideNetworkHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 78f02db..c01677a 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -461,7 +461,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveBl } } - oldTile->spawnResources(level, x, y, z, data, 1); //@todo + // oldTile->spawnResources(level, x, y, z, data, 1); //@todo oldTile->playerDestroy(level, player, x, y, z, data); } From ba3ed3b4dd4c373e9d8f7f5e5be90bbed9ddc51f Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Sat, 28 Mar 2026 18:37:02 +0200 Subject: [PATCH 21/59] i dont see reason of this error --- src/network/ClientSideNetworkHandler.cpp | 2 +- src/network/ServerSideNetworkHandler.cpp | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index 213ff28..2ae545a 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -99,6 +99,7 @@ void ClientSideNetworkHandler::onUnableToConnect() void ClientSideNetworkHandler::onDisconnect(const RakNet::RakNetGUID& guid) { + // TODO: Good disconnecting LOGI("onDisconnect\n"); if (level) { @@ -398,7 +399,6 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SendInventoryPacket* packet) { if (!level) return; - // TODO: Linked slots if (packet->entityId == minecraft->player->entityId) { auto items = packet->items; diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index c01677a..22f54e1 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -29,6 +29,7 @@ #include "world/item/crafting/Recipe.h" #include "world/item/crafting/Recipes.h" #include +#include #ifndef STANDALONE_SERVER #include "../client/sound/SoundEngine.h" #endif @@ -410,17 +411,20 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay { ServerPlayer* player = (ServerPlayer*) getPlayer(source); - float vectorDist = sqrt( (packet->x - entity->x) * (packet->x - entity->x) + - (packet->y - entity->y) * (packet->y - entity->y) + - (packet->z - entity->z) * (packet->z - entity->z)); - float speed = vectorDist / (minecraft->getTicks() - player->getLastMoveTicks()); + // float vectorDist = sqrt( (packet->x - entity->x) * (packet->x - entity->x) + + // (packet->y - entity->y) * (packet->y - entity->y) + + // (packet->z - entity->z) * (packet->z - entity->z)); + // float speed = vectorDist / (minecraft->getTicks() - player->getLastMoveTicks()); // TODO: Replace with Entity::move() // if (speed < 2.5f) { - entity->xd = entity->yd = entity->zd = 0; - entity->move(packet->x - entity->x, packet->y - entity->y, packet->z - entity->z); + printf("Packet do: %f, %f, %f \n", packet->x, packet->y, packet->z); + printf("Entity do: %f, %f, %f \n", entity->x, entity->y, entity->z); + printf("Delta: %f %f %f \n", packet->x - entity->x, packet->y - entity->y, packet->z - entity->z); + player->xd = player->yd = player->zd = 0; + player->move(packet->x - entity->x, packet->y - entity->y, packet->z - entity->z); + printf("Entity after: %f, %f, %f \n", entity->x, entity->y, entity->z); // entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3); - // broadcast this packet to other clients redistributePacket(packet, source); //} From 4363157cd90f2ba9bfe94930614a7c717bf36c16 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Sat, 28 Mar 2026 21:08:52 +0200 Subject: [PATCH 22/59] Delete useless class --- src/network/NATPunchHandler.cpp | 33 ------------------------ src/network/NATPunchHandler.h | 24 ----------------- src/network/ServerSideNetworkHandler.cpp | 4 +-- 3 files changed, 2 insertions(+), 59 deletions(-) delete mode 100755 src/network/NATPunchHandler.cpp delete mode 100755 src/network/NATPunchHandler.h diff --git a/src/network/NATPunchHandler.cpp b/src/network/NATPunchHandler.cpp deleted file mode 100755 index 35108b0..0000000 --- a/src/network/NATPunchHandler.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#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() { - -} - diff --git a/src/network/NATPunchHandler.h b/src/network/NATPunchHandler.h deleted file mode 100755 index 0246c0d..0000000 --- a/src/network/NATPunchHandler.h +++ /dev/null @@ -1,24 +0,0 @@ -#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_ */ diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 22f54e1..1e999c8 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -418,8 +418,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay // TODO: Replace with Entity::move() // if (speed < 2.5f) { - printf("Packet do: %f, %f, %f \n", packet->x, packet->y, packet->z); - printf("Entity do: %f, %f, %f \n", entity->x, entity->y, entity->z); + printf("Packet before: %f, %f, %f \n", packet->x, packet->y, packet->z); + printf("Entity before: %f, %f, %f \n", entity->x, entity->y, entity->z); printf("Delta: %f %f %f \n", packet->x - entity->x, packet->y - entity->y, packet->z - entity->z); player->xd = player->yd = player->zd = 0; player->move(packet->x - entity->x, packet->y - entity->y, packet->z - entity->z); From 470c28d83a1c4710220fa0beb398517a737bf02c Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Sun, 29 Mar 2026 00:36:36 +0300 Subject: [PATCH 23/59] I dont know what im doin please help --- src/network/ServerSideNetworkHandler.cpp | 30 +++++++++++++++--------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 1e999c8..fa61054 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -7,6 +7,7 @@ #include "../world/inventory/BaseContainerMenu.h" #include "network/packet/ContainerSetSlotPacket.h" #include "network/packet/LoginStatusPacket.h" +#include "network/packet/MovePlayerPacket.h" #include "network/packet/RemoveBlockPacket.h" #include "network/packet/SendInventoryPacket.h" #include "network/packet/UpdateBlockPacket.h" @@ -411,23 +412,30 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay { ServerPlayer* player = (ServerPlayer*) getPlayer(source); - // float vectorDist = sqrt( (packet->x - entity->x) * (packet->x - entity->x) + - // (packet->y - entity->y) * (packet->y - entity->y) + - // (packet->z - entity->z) * (packet->z - entity->z)); - // float speed = vectorDist / (minecraft->getTicks() - player->getLastMoveTicks()); + float vectorDist = sqrt( (packet->x - entity->x) * (packet->x - entity->x) + + (packet->z - entity->z) * (packet->z - entity->z)); + float speed = vectorDist / (minecraft->getTicks() - player->getLastMoveTicks()); - // TODO: Replace with Entity::move() - // if (speed < 2.5f) { - printf("Packet before: %f, %f, %f \n", packet->x, packet->y, packet->z); - printf("Entity before: %f, %f, %f \n", entity->x, entity->y, entity->z); - printf("Delta: %f %f %f \n", packet->x - entity->x, packet->y - entity->y, packet->z - entity->z); + player->xRot = packet->xRot; + player->yRot = packet->yRot; + + packet->y += 1.62f; + + if (speed < 2.5f) { + LOGI("Packet before: %f, %f, %f \n", packet->x, packet->y, packet->z); + LOGI("Entity before: %f, %f, %f \n", entity->x, entity->y, entity->z); + LOGI("Delta: %f %f %f \n", packet->x - entity->x, packet->y - entity->y, packet->z - entity->z); player->xd = player->yd = player->zd = 0; player->move(packet->x - entity->x, packet->y - entity->y, packet->z - entity->z); - printf("Entity after: %f, %f, %f \n", entity->x, entity->y, entity->z); + // player->travel(packet->x - entity->x, packet->z - entity->z); + LOGI("Entity after: %f, %f, %f \n", entity->x, entity->y, entity->z); // entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3); // broadcast this packet to other clients redistributePacket(packet, source); - //} + } else { + MovePlayerPacket refuse(player->entityId, player->x, player->y, player->z, player->xRot, player->yRot); + raknetInstance->send(refuse); + } player->setLastMoveTicks(minecraft->getTicks()); } From f016f00eab485939cc07d53c12bb124f6f4cbfc0 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Sun, 29 Mar 2026 00:16:19 +0200 Subject: [PATCH 24/59] idk?? --- src/client/player/LocalPlayer.cpp | 2 +- src/network/ServerSideNetworkHandler.cpp | 31 ++++++++++++++---------- src/server/ServerPlayer.cpp | 1 + src/world/entity/Mob.cpp | 2 +- src/world/entity/Mob.h | 3 +++ 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/client/player/LocalPlayer.cpp b/src/client/player/LocalPlayer.cpp index a4d3b74..88f7835 100755 --- a/src/client/player/LocalPlayer.cpp +++ b/src/client/player/LocalPlayer.cpp @@ -438,7 +438,7 @@ void LocalPlayer::tick() { { if (std::abs(x - sentX) > .1f || std::abs(y - sentY) > .01f || std::abs(z - sentZ) > .1f || std::abs(sentRotX - xRot) > 1 || std::abs(sentRotY - yRot) > 1) { - MovePlayerPacket packet(entityId, x, y - heightOffset, z, xRot, yRot); + MovePlayerPacket packet(entityId, xxa, y - heightOffset, yya, xRot, yRot); minecraft->raknetInstance->send(packet); sentX = x; sentY = y; diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index fa61054..1981b87 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -416,26 +416,31 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay (packet->z - entity->z) * (packet->z - entity->z)); float speed = vectorDist / (minecraft->getTicks() - player->getLastMoveTicks()); - player->xRot = packet->xRot; - player->yRot = packet->yRot; + player->xRot = player->xRotO = packet->xRot; + player->yRot = player->yRotO = packet->yRot; - packet->y += 1.62f; + // packet->y += 1.62f; - if (speed < 2.5f) { - LOGI("Packet before: %f, %f, %f \n", packet->x, packet->y, packet->z); + // if (speed < 2.5f) { + LOGI("Packets: %f, %f, %f \n", packet->x, packet->y, packet->z); LOGI("Entity before: %f, %f, %f \n", entity->x, entity->y, entity->z); - LOGI("Delta: %f %f %f \n", packet->x - entity->x, packet->y - entity->y, packet->z - entity->z); - player->xd = player->yd = player->zd = 0; - player->move(packet->x - entity->x, packet->y - entity->y, packet->z - entity->z); + LOGI("OnGround: %d \n", entity->onGround); + //player->xd = player->yd = player->zd = 0; + + player->setxxa(packet->x); + player->setYya(packet->z); + // player->move(packet->x - entity->x, packet->y - entity->y, packet->z - entity->z); + // player->travel(packet->x - entity->x, packet->z - entity->z); - LOGI("Entity after: %f, %f, %f \n", entity->x, entity->y, entity->z); // entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3); + LOGI("Entity after: %f, %f, %f \n", entity->x, entity->y, entity->z); + // broadcast this packet to other clients redistributePacket(packet, source); - } else { - MovePlayerPacket refuse(player->entityId, player->x, player->y, player->z, player->xRot, player->yRot); - raknetInstance->send(refuse); - } + // } else { + //MovePlayerPacket refuse(player->entityId, player->x, player->y, player->z, player->xRot, player->yRot); + //raknetInstance->send(refuse); + // } player->setLastMoveTicks(minecraft->getTicks()); } diff --git a/src/server/ServerPlayer.cpp b/src/server/ServerPlayer.cpp index 9f4f1dc..085fa8b 100755 --- a/src/server/ServerPlayer.cpp +++ b/src/server/ServerPlayer.cpp @@ -49,6 +49,7 @@ void ServerPlayer::stopSleepInBed(bool forcefulWakeUp, bool updateLevelList, boo void ServerPlayer::aiStep() { updateAttackAnim(); super::aiStep(); + Mob::aiStep(); } void ServerPlayer::tick() { diff --git a/src/world/entity/Mob.cpp b/src/world/entity/Mob.cpp index cc784f0..aed03dd 100755 --- a/src/world/entity/Mob.cpp +++ b/src/world/entity/Mob.cpp @@ -728,8 +728,8 @@ bool Mob::isWaterMob() void Mob::aiStep() { + printf("%f %f \n", xxa, yya); //@todo? 30 lines of code here in java version - TIMER_PUSH("ai"); if (isImmobile()) { jumping = false; diff --git a/src/world/entity/Mob.h b/src/world/entity/Mob.h index 7e90196..50045cb 100755 --- a/src/world/entity/Mob.h +++ b/src/world/entity/Mob.h @@ -223,6 +223,9 @@ protected: double xc, yc, zc; public: + void setxxa(float xxa) { this->xxa = xxa; } + void setyya(float yya) { this->yya = yya; } + // Cape position accessors (for renderers) double getCapeX() const { return xCape; } double getCapeY() const { return yCape; } From 3cfa2d9ee7e9567503228e7e8f7a1384e7a9a43c Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Sun, 29 Mar 2026 16:53:46 +0200 Subject: [PATCH 25/59] FIX IT AHTUNG AHTUNG ALL DOESNT WORK FIX IT FIX IT FIX IT FIX IT BIG WARNING BIG WARNING --- src/client/gui/Gui.cpp | 1 - src/network/ServerSideNetworkHandler.cpp | 41 ++++++++++++++---------- src/server/ServerPlayer.cpp | 1 - src/world/entity/Entity.h | 2 +- src/world/entity/Mob.cpp | 1 - 5 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/client/gui/Gui.cpp b/src/client/gui/Gui.cpp index ccc9c26..7685813 100755 --- a/src/client/gui/Gui.cpp +++ b/src/client/gui/Gui.cpp @@ -730,7 +730,6 @@ void Gui::renderDebugInfo() { // Position float px = p->x, py = p->y - p->heightOffset, pz = p->z; - posTranslator.to(px, py, pz); int bx = (int)floorf(px), by = (int)floorf(py), bz = (int)floorf(pz); int cx = bx >> 4, cz = bz >> 4; diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 1981b87..40ac4a1 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -406,38 +406,45 @@ void ServerSideNetworkHandler::onReady_RequestedChunks(const RakNet::RakNetGUID& void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlayerPacket* packet) { if (!level) return; - + //LOGI("MovePlayerPacket\n"); - if (Entity* entity = level->getEntity(packet->entityId)) - { + if (Entity* entity = level->getEntity(packet->entityId)) { ServerPlayer* player = (ServerPlayer*) getPlayer(source); float vectorDist = sqrt( (packet->x - entity->x) * (packet->x - entity->x) + (packet->z - entity->z) * (packet->z - entity->z)); float speed = vectorDist / (minecraft->getTicks() - player->getLastMoveTicks()); - - player->xRot = player->xRotO = packet->xRot; - player->yRot = player->yRotO = packet->yRot; - // packet->y += 1.62f; - - // if (speed < 2.5f) { - LOGI("Packets: %f, %f, %f \n", packet->x, packet->y, packet->z); + if (speed < 1.f) { + LOGI("Packet: %f, %f, %f \n", packet->x, packet->y, packet->z); LOGI("Entity before: %f, %f, %f \n", entity->x, entity->y, entity->z); LOGI("OnGround: %d \n", entity->onGround); - //player->xd = player->yd = player->zd = 0; - player->setxxa(packet->x); - player->setYya(packet->z); - // player->move(packet->x - entity->x, packet->y - entity->y, packet->z - entity->z); + // @note: packet->y contains y with subtracted entity->heightOffset + float ya = packet->y - entity->y - entity->heightOffset; + + LOGI("y: %f \n", ya); + + float yaOrg = ya; + + // @BIGWARNING @fixme: blocks around work as shit + std::vector& aABBs = level->getCubes(entity, entity->bb.expand(0, ya, 0)); - // player->travel(packet->x - entity->x, packet->z - entity->z); - // entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3); + for (unsigned int i = 0; i < aABBs.size(); i++) + ya = aABBs[i].clipYCollide(entity->bb, ya); + + bool og = yaOrg != ya && yaOrg < 0; + + entity->onGround = og; + entity->checkFallDamage(ya, og); + entity->xd = entity->yd = entity->zd = 0; + entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3); + LOGI("Entity after: %f, %f, %f \n", entity->x, entity->y, entity->z); // broadcast this packet to other clients redistributePacket(packet, source); - // } else { + } // else { //MovePlayerPacket refuse(player->entityId, player->x, player->y, player->z, player->xRot, player->yRot); //raknetInstance->send(refuse); // } diff --git a/src/server/ServerPlayer.cpp b/src/server/ServerPlayer.cpp index 085fa8b..9f4f1dc 100755 --- a/src/server/ServerPlayer.cpp +++ b/src/server/ServerPlayer.cpp @@ -49,7 +49,6 @@ void ServerPlayer::stopSleepInBed(bool forcefulWakeUp, bool updateLevelList, boo void ServerPlayer::aiStep() { updateAttackAnim(); super::aiStep(); - Mob::aiStep(); } void ServerPlayer::tick() { diff --git a/src/world/entity/Entity.h b/src/world/entity/Entity.h index 23c229f..b865902 100755 --- a/src/world/entity/Entity.h +++ b/src/world/entity/Entity.h @@ -129,6 +129,7 @@ public: virtual bool isHangingEntity(); virtual int getAuxData(); + virtual void checkFallDamage(float ya, bool onGround); protected: virtual void setRot(float yRot, float xRot); @@ -137,7 +138,6 @@ protected: virtual void resetPos(bool clearMore); virtual void outOfWorld(); - virtual void checkFallDamage(float ya, bool onGround); virtual void causeFallDamage(float fallDamage2); virtual void markHurt(); diff --git a/src/world/entity/Mob.cpp b/src/world/entity/Mob.cpp index aed03dd..614ccdd 100755 --- a/src/world/entity/Mob.cpp +++ b/src/world/entity/Mob.cpp @@ -728,7 +728,6 @@ bool Mob::isWaterMob() void Mob::aiStep() { - printf("%f %f \n", xxa, yya); //@todo? 30 lines of code here in java version TIMER_PUSH("ai"); if (isImmobile()) { From 51945750925a827dd853e9d1c2d50d54797458a6 Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Mon, 30 Mar 2026 14:04:16 +0300 Subject: [PATCH 26/59] FEAT: Meet the commands --- CMakeLists.txt | 3 + src/client/Minecraft.cpp | 12 ++- src/client/Minecraft.h | 7 ++ src/client/gui/screens/ConsoleScreen.cpp | 127 ++--------------------- src/client/gui/screens/ConsoleScreen.h | 1 - src/commands/Command.hpp | 25 +++++ src/commands/CommandHelp.cpp | 27 +++++ src/commands/CommandHelp.hpp | 9 ++ src/commands/CommandKick.cpp | 37 +++++++ src/commands/CommandKick.hpp | 9 ++ src/commands/CommandManager.cpp | 71 +++++++++++++ src/commands/CommandManager.hpp | 21 ++++ 12 files changed, 230 insertions(+), 119 deletions(-) create mode 100644 src/commands/Command.hpp create mode 100644 src/commands/CommandHelp.cpp create mode 100644 src/commands/CommandHelp.hpp create mode 100644 src/commands/CommandKick.cpp create mode 100644 src/commands/CommandKick.hpp create mode 100644 src/commands/CommandManager.cpp create mode 100644 src/commands/CommandManager.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c3acea..7650b9a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -211,6 +211,7 @@ file(GLOB SERVER_SOURCES "src/world/level/tile/entity/*.cpp" "src/world/phys/HitResult.cpp" + "src/commands/*.cpp" ) file(GLOB CLIENT_SOURCES @@ -292,6 +293,8 @@ file(GLOB CLIENT_SOURCES "src/AppPlatform_glfw.cpp" "src/main.cpp" + + "src/commands/*.cpp" ) if (${PLATFORM} STREQUAL "Desktop") diff --git a/src/client/Minecraft.cpp b/src/client/Minecraft.cpp index 51ad3a3..2b0075e 100755 --- a/src/client/Minecraft.cpp +++ b/src/client/Minecraft.cpp @@ -2,6 +2,7 @@ #include "Options.h" #include "client/Options.h" #include "client/player/input/IBuildInput.h" +#include "commands/CommandManager.hpp" #include "platform/input/Keyboard.h" #include "world/item/Item.h" #include "world/item/ItemInstance.h" @@ -175,7 +176,8 @@ Minecraft::Minecraft() : _powerVr(false), commandPort(4711), reserved_d1(0),reserved_d2(0), - reserved_f1(0),reserved_f2(0), options(this) + reserved_f1(0),reserved_f2(0), options(this), + m_commandManager() { //#ifdef ANDROID @@ -1597,3 +1599,11 @@ void Minecraft::optionUpdated(OptionId option, int value ) { setSize(width, height); } } + +void Minecraft::addMessage(const std::string& msg) { +#ifndef STANDALONE_SERVER + gui.addMessage(msg); +#else + LOGI("%s", msg.c_str()); +#endif +} \ No newline at end of file diff --git a/src/client/Minecraft.h b/src/client/Minecraft.h index a7f5abc..61768cb 100755 --- a/src/client/Minecraft.h +++ b/src/client/Minecraft.h @@ -2,6 +2,7 @@ #define NET_MINECRAFT_CLIENT__Minecraft_H__ #include "Options.h" +#include "commands/CommandManager.hpp" #ifndef STANDALONE_SERVER #include "MouseHandler.h" #include "gui/Gui.h" @@ -122,11 +123,15 @@ public: void optionUpdated(OptionId option, int value); int getTicks() { return ticks; } + + void addMessage(const std::string& msg); #ifdef __APPLE__ bool _isSuperFast; bool isSuperFast() { return _isSuperFast; } #endif + CommandManager& commandManager() { return m_commandManager; } + protected: void _levelGenerated(); @@ -227,6 +232,8 @@ private: PerfRenderer* _perfRenderer; CommandServer* _commandServer; + + CommandManager m_commandManager; }; #endif /*NET_MINECRAFT_CLIENT__Minecraft_H__*/ diff --git a/src/client/gui/screens/ConsoleScreen.cpp b/src/client/gui/screens/ConsoleScreen.cpp index 939cb74..6380f48 100644 --- a/src/client/gui/screens/ConsoleScreen.cpp +++ b/src/client/gui/screens/ConsoleScreen.cpp @@ -8,6 +8,7 @@ #include "../../../network/ServerSideNetworkHandler.h" #include "../../../network/packet/ChatPacket.h" #include "../../../platform/log.h" +#include "util/StringUtils.h" #include #include @@ -54,141 +55,33 @@ void ConsoleScreen::charPressed(char inputChar) _input += inputChar; } -// --------------------------------------------------------------------------- -// execute: run _input as a command, print result, close screen -// --------------------------------------------------------------------------- void ConsoleScreen::execute() { + if (!minecraft->level) return; + if (_input.empty()) { - minecraft->setScreen(NULL); - return; + return minecraft->setScreen(NULL); } if (_input[0] == '/') { // Command - std::string result = processCommand(_input); - if (!result.empty()) - minecraft->gui.addMessage(result); + _input = Util::stringTrim(_input.substr(1)); + minecraft->commandManager().execute(*minecraft, _input); } else { - // Chat message: message - std::string msg = std::string("<") + minecraft->player->name + "> " + _input; + // @ai @rewrite if (minecraft->netCallback && minecraft->raknetInstance->isServer()) { - // Hosting a LAN game: displayGameMessage shows locally + broadcasts MessagePacket to clients - static_cast(minecraft->netCallback)->displayGameMessage(msg); + static_cast(minecraft->netCallback)->displayGameMessage(_input); } else if (minecraft->netCallback) { - // Connected client: send ChatPacket to server; server echoes it back as MessagePacket - ChatPacket chatPkt(msg); + ChatPacket chatPkt(_input); minecraft->raknetInstance->send(chatPkt); } else { - // Singleplayer: show locally only - minecraft->gui.addMessage(msg); + minecraft->gui.addMessage(_input); } } minecraft->setScreen(NULL); } -// --------------------------------------------------------------------------- -// processCommand -// --------------------------------------------------------------------------- -static std::string trim(const std::string& s) { - size_t a = s.find_first_not_of(" \t"); - if (a == std::string::npos) return ""; - size_t b = s.find_last_not_of(" \t"); - return s.substr(a, b - a + 1); -} - -std::string ConsoleScreen::processCommand(const std::string& raw) -{ - // strip leading '/' - std::string line = raw; - if (!line.empty() && line[0] == '/') line = line.substr(1); - line = trim(line); - - // tokenise - std::vector args; - { - std::istringstream ss(line); - std::string tok; - while (ss >> tok) args.push_back(tok); - } - - if (args.empty()) return ""; - - Level* level = minecraft->level; - if (!level) return "No level loaded."; - - // ----------------------------------------------------------------------- - // /time ... - // ----------------------------------------------------------------------- - if (args[0] == "time") { - if (args.size() < 2) - return "Usage: /time ..."; - - const std::string& sub = args[1]; - - // -- time add ----------------------------------------------- - if (sub == "add") { - if (args.size() < 3) return "Usage: /time add "; - long delta = std::atol(args[2].c_str()); - long newTime = level->getTime() + delta; - level->setTime(newTime); - std::ostringstream out; - out << "Set the time to " << (newTime % Level::TICKS_PER_DAY); - return out.str(); - } - - // -- time set ----------------------- - if (sub == "set") { - if (args.size() < 3) return "Usage: /time set "; - const std::string& val = args[2]; - - long t = -1; - if (val == "day") t = 1000; - else if (val == "noon") t = 6000; - else if (val == "night") t = 13000; - else if (val == "midnight") t = 18000; - else { - // numeric — accept positive integers only - bool numeric = true; - for (char c : val) - if (!std::isdigit((unsigned char)c)) { numeric = false; break; } - if (!numeric) return std::string("Unknown value: ") + val; - t = std::atol(val.c_str()); - } - - // Preserve the total day count so only the time-of-day changes - long dayCount = level->getTime() / Level::TICKS_PER_DAY; - long newTime = dayCount * Level::TICKS_PER_DAY + (t % Level::TICKS_PER_DAY); - level->setTime(newTime); - std::ostringstream out; - out << "Set the time to " << t; - return out.str(); - } - - // -- time query ------------------------------ - if (sub == "query") { - if (args.size() < 3) return "Usage: /time query "; - const std::string& what = args[2]; - - long total = level->getTime(); - long daytime = total % Level::TICKS_PER_DAY; - long day = total / Level::TICKS_PER_DAY; - - std::ostringstream out; - if (what == "daytime") { out << "The time of day is " << daytime; } - else if (what == "gametime") { out << "The game time is " << total; } - else if (what == "day") { out << "The day is " << day; } - else return std::string("Unknown query: ") + what; - return out.str(); - } - - return "Unknown sub-command. Usage: /time ..."; - } - - return std::string("Unknown command: /") + args[0]; -} - // --------------------------------------------------------------------------- // render // --------------------------------------------------------------------------- diff --git a/src/client/gui/screens/ConsoleScreen.h b/src/client/gui/screens/ConsoleScreen.h index e0074b9..f0c1fd5 100644 --- a/src/client/gui/screens/ConsoleScreen.h +++ b/src/client/gui/screens/ConsoleScreen.h @@ -25,7 +25,6 @@ public: private: void execute(); - std::string processCommand(const std::string& cmd); std::string _input; int _cursorBlink; // tick counter for cursor blink diff --git a/src/commands/Command.hpp b/src/commands/Command.hpp new file mode 100644 index 0000000..ee2a5e2 --- /dev/null +++ b/src/commands/Command.hpp @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +enum CommandFlags { + COMMAND_FLAG_SINGLEPLAYER_ONLY = (1 << 1), + COMMAND_FLAG_NO_ARGS = (1 << 2), +}; + +class Minecraft; + +class Command { +public: + const std::string& getName() { return m_name; } + const CommandFlags getFlags() { return m_flags; } + + virtual void execute(Minecraft& mc, const std::vector& args) = 0; + virtual void printHelp(Minecraft& mc) = 0; + +protected: + Command(const std::string& name, CommandFlags flags = (CommandFlags)0) : m_name(name), m_flags(flags) {} + + const std::string m_name; + const CommandFlags m_flags; +}; \ No newline at end of file diff --git a/src/commands/CommandHelp.cpp b/src/commands/CommandHelp.cpp new file mode 100644 index 0000000..c922b4b --- /dev/null +++ b/src/commands/CommandHelp.cpp @@ -0,0 +1,27 @@ +#include "CommandHelp.hpp" +#include "commands/Command.hpp" +#include "CommandManager.hpp" +#include + +CommandHelp::CommandHelp() : Command("help") {} + +void CommandHelp::execute(Minecraft& mc, const std::vector& args) { + if (args.empty()) { + auto cmds = mc.commandManager().getListAllCommands(); + + mc.addMessage("Usage: /help "); + mc.addMessage("List of all commands:"); + + for (auto& cmd : cmds) { + mc.addMessage(" - " + cmd); + } + } else { + Command* cmd = mc.commandManager().getCommand(args[0]); + + if (cmd != nullptr) { + cmd->printHelp(mc); + } + } +} + +void CommandHelp::printHelp(Minecraft& mc) {} \ No newline at end of file diff --git a/src/commands/CommandHelp.hpp b/src/commands/CommandHelp.hpp new file mode 100644 index 0000000..88bee09 --- /dev/null +++ b/src/commands/CommandHelp.hpp @@ -0,0 +1,9 @@ +#include "Command.hpp" + +class CommandHelp : public Command { +public: + CommandHelp(); + + void execute(Minecraft& mc, const std::vector& args); + void printHelp(Minecraft& mc); +}; \ No newline at end of file diff --git a/src/commands/CommandKick.cpp b/src/commands/CommandKick.cpp new file mode 100644 index 0000000..ed167e4 --- /dev/null +++ b/src/commands/CommandKick.cpp @@ -0,0 +1,37 @@ +#include "CommandKick.hpp" +#include "commands/Command.hpp" +#include "network/RakNetInstance.h" +#include "raknet/RakPeer.h" +#include "world/level/Level.h" +#include +#include + + +CommandKick::CommandKick() : Command("kick") {} + +void CommandKick::execute(Minecraft& mc, const std::vector& args) { + if (args.empty()) { + return printHelp(mc); + } + + auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args] (auto& it) -> bool { + return it->name == args[0]; + }); + + if (it == mc.level->players.end()) { + return mc.addMessage("kick: can't find player with name " + args[0]); + } + + if (*it == (Player*)mc.player) { + return mc.addMessage("kick: you can't kick urself lol"); + } + + mc.level->removePlayer(*it); + (*it)->remove(); + mc.raknetInstance->getPeer()->CloseConnection((*it)->owner, true); + mc.addMessage("kick: successfully kicked player " + args[0]); +} + +void CommandKick::printHelp(Minecraft& mc) { + mc.addMessage("Usage: /kick "); +} \ No newline at end of file diff --git a/src/commands/CommandKick.hpp b/src/commands/CommandKick.hpp new file mode 100644 index 0000000..c743aa4 --- /dev/null +++ b/src/commands/CommandKick.hpp @@ -0,0 +1,9 @@ +#include "Command.hpp" + +class CommandKick : public Command { +public: + CommandKick(); + + void execute(Minecraft& mc, const std::vector& args); + void printHelp(Minecraft& mc); +}; \ No newline at end of file diff --git a/src/commands/CommandManager.cpp b/src/commands/CommandManager.cpp new file mode 100644 index 0000000..8ed2d18 --- /dev/null +++ b/src/commands/CommandManager.cpp @@ -0,0 +1,71 @@ +#include "CommandManager.hpp" +#include +#include +#include +#include "client/Minecraft.h" +#include "commands/Command.hpp" +#include "commands/CommandHelp.hpp" +#include "commands/CommandKick.hpp" +#include "network/packet/ChatPacket.h" +#include "network/RakNetInstance.h" +#include "world/level/Level.h" + + + +CommandManager::CommandManager() { + registerAllCommands(); +} + +void CommandManager::registerAllCommands() { + m_commands.push_back(new CommandHelp()); + m_commands.push_back(new CommandKick()); +} + +std::vector CommandManager::getListAllCommands() { + std::vector ret; + + for (auto& cmd : m_commands) { + ret.push_back(cmd->getName()); + } + + return ret; +} + +void CommandManager::execute(Minecraft& mc, const std::string& input) { + std::istringstream ss(input); + std::string cmd; + + ss >> cmd; + + auto it = std::find_if(m_commands.begin(), m_commands.end(), [cmd](auto& it) -> bool { + return it->getName() == cmd; + }); + + if (it == m_commands.end()) { + return mc.addMessage("Command /" + cmd + " not found"); + } + + std::vector args; + + std::string tok; + while (ss >> tok) args.push_back(tok); + + if (!mc.level->isClientSide || (*it)->getFlags() & CommandFlags::COMMAND_FLAG_SINGLEPLAYER_ONLY) { + (*it)->execute(mc, args); + } else { + ChatPacket packet("/" + input); + mc.raknetInstance->send(packet); + } +} + +Command* CommandManager::getCommand(const std::string& name) { + auto it = std::find_if(m_commands.begin(), m_commands.end(), [name](auto& it) -> bool { + return it->getName() == name; + }); + + if (it == m_commands.end()) { + return *it; + } + + return nullptr; +} \ No newline at end of file diff --git a/src/commands/CommandManager.hpp b/src/commands/CommandManager.hpp new file mode 100644 index 0000000..1304877 --- /dev/null +++ b/src/commands/CommandManager.hpp @@ -0,0 +1,21 @@ +#pragma once +#include +#include + +#include "Command.hpp" + +class CommandManager { +public: + CommandManager(); + + std::vector getListAllCommands(); + + void execute(Minecraft& mc, const std::string& input); + + Command* getCommand(const std::string& name); + +private: + void registerAllCommands(); + + std::vector m_commands; +}; \ No newline at end of file From 1ec347d5d55934faf2a220d98b66c7796c379286 Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Tue, 31 Mar 2026 00:40:10 +0300 Subject: [PATCH 27/59] FEAT: Server operators --- src/client/Minecraft.cpp | 2 ++ src/client/gui/screens/ConsoleScreen.cpp | 2 +- src/commands/Command.cpp | 7 +++++ src/commands/Command.hpp | 5 +++- src/commands/CommandHelp.cpp | 2 +- src/commands/CommandHelp.hpp | 2 +- src/commands/CommandKick.cpp | 6 +++- src/commands/CommandKick.hpp | 2 +- src/commands/CommandManager.cpp | 6 ++-- src/commands/CommandManager.hpp | 2 +- src/commands/CommandOp.cpp | 35 ++++++++++++++++++++++++ src/commands/CommandOp.hpp | 9 ++++++ src/world/level/Level.h | 3 ++ 13 files changed, 74 insertions(+), 9 deletions(-) create mode 100644 src/commands/Command.cpp create mode 100644 src/commands/CommandOp.cpp create mode 100644 src/commands/CommandOp.hpp diff --git a/src/client/Minecraft.cpp b/src/client/Minecraft.cpp index 2b0075e..05e397b 100755 --- a/src/client/Minecraft.cpp +++ b/src/client/Minecraft.cpp @@ -277,6 +277,8 @@ void Minecraft::setLevel(Level* level, const std::string& message /* ="" */, Loc } } this->level = level; + // So uhhh + level->ops.emplace(options.getStringValue(OPTIONS_USERNAME)); _hasSignaledGeneratingLevelFinished = false; #ifdef STANDALONE_SERVER const bool threadedLevelCreation = false; diff --git a/src/client/gui/screens/ConsoleScreen.cpp b/src/client/gui/screens/ConsoleScreen.cpp index 6380f48..9821f99 100644 --- a/src/client/gui/screens/ConsoleScreen.cpp +++ b/src/client/gui/screens/ConsoleScreen.cpp @@ -66,7 +66,7 @@ void ConsoleScreen::execute() if (_input[0] == '/') { // Command _input = Util::stringTrim(_input.substr(1)); - minecraft->commandManager().execute(*minecraft, _input); + minecraft->commandManager().execute(*minecraft, *minecraft->player, _input); } else { // @ai @rewrite if (minecraft->netCallback && minecraft->raknetInstance->isServer()) { diff --git a/src/commands/Command.cpp b/src/commands/Command.cpp new file mode 100644 index 0000000..ebcbf3d --- /dev/null +++ b/src/commands/Command.cpp @@ -0,0 +1,7 @@ +#include "Command.hpp" +#include "world/level/Level.h" +#include + +bool Command::isPlayerOp(Minecraft& mc, Player& player) { + return mc.level->ops.find(player.name) != mc.level->ops.end(); +} \ No newline at end of file diff --git a/src/commands/Command.hpp b/src/commands/Command.hpp index ee2a5e2..f44c3df 100644 --- a/src/commands/Command.hpp +++ b/src/commands/Command.hpp @@ -8,13 +8,16 @@ enum CommandFlags { }; class Minecraft; +class Player; class Command { public: const std::string& getName() { return m_name; } const CommandFlags getFlags() { return m_flags; } - virtual void execute(Minecraft& mc, const std::vector& args) = 0; + bool isPlayerOp(Minecraft& mc, Player& player); + + virtual void execute(Minecraft& mc, Player& player, const std::vector& args) = 0; virtual void printHelp(Minecraft& mc) = 0; protected: diff --git a/src/commands/CommandHelp.cpp b/src/commands/CommandHelp.cpp index c922b4b..18f7741 100644 --- a/src/commands/CommandHelp.cpp +++ b/src/commands/CommandHelp.cpp @@ -5,7 +5,7 @@ CommandHelp::CommandHelp() : Command("help") {} -void CommandHelp::execute(Minecraft& mc, const std::vector& args) { +void CommandHelp::execute(Minecraft& mc, Player& player, const std::vector& args) { if (args.empty()) { auto cmds = mc.commandManager().getListAllCommands(); diff --git a/src/commands/CommandHelp.hpp b/src/commands/CommandHelp.hpp index 88bee09..48e1f1f 100644 --- a/src/commands/CommandHelp.hpp +++ b/src/commands/CommandHelp.hpp @@ -4,6 +4,6 @@ class CommandHelp : public Command { public: CommandHelp(); - void execute(Minecraft& mc, const std::vector& args); + void execute(Minecraft& mc, Player& player, const std::vector& args); void printHelp(Minecraft& mc); }; \ No newline at end of file diff --git a/src/commands/CommandKick.cpp b/src/commands/CommandKick.cpp index ed167e4..b08ba86 100644 --- a/src/commands/CommandKick.cpp +++ b/src/commands/CommandKick.cpp @@ -9,7 +9,11 @@ CommandKick::CommandKick() : Command("kick") {} -void CommandKick::execute(Minecraft& mc, const std::vector& args) { +void CommandKick::execute(Minecraft& mc, Player& player, const std::vector& args) { + if (!isPlayerOp(mc, player)) { + return mc.addMessage("You aren't enough priveleged to run this command"); + } + if (args.empty()) { return printHelp(mc); } diff --git a/src/commands/CommandKick.hpp b/src/commands/CommandKick.hpp index c743aa4..80225a8 100644 --- a/src/commands/CommandKick.hpp +++ b/src/commands/CommandKick.hpp @@ -4,6 +4,6 @@ class CommandKick : public Command { public: CommandKick(); - void execute(Minecraft& mc, const std::vector& args); + void execute(Minecraft& mc, Player& player, const std::vector& args); void printHelp(Minecraft& mc); }; \ No newline at end of file diff --git a/src/commands/CommandManager.cpp b/src/commands/CommandManager.cpp index 8ed2d18..2b7f7f0 100644 --- a/src/commands/CommandManager.cpp +++ b/src/commands/CommandManager.cpp @@ -6,6 +6,7 @@ #include "commands/Command.hpp" #include "commands/CommandHelp.hpp" #include "commands/CommandKick.hpp" +#include "commands/CommandOp.hpp" #include "network/packet/ChatPacket.h" #include "network/RakNetInstance.h" #include "world/level/Level.h" @@ -19,6 +20,7 @@ CommandManager::CommandManager() { void CommandManager::registerAllCommands() { m_commands.push_back(new CommandHelp()); m_commands.push_back(new CommandKick()); + m_commands.push_back(new CommandOp()); } std::vector CommandManager::getListAllCommands() { @@ -31,7 +33,7 @@ std::vector CommandManager::getListAllCommands() { return ret; } -void CommandManager::execute(Minecraft& mc, const std::string& input) { +void CommandManager::execute(Minecraft& mc, Player& player, const std::string& input) { std::istringstream ss(input); std::string cmd; @@ -51,7 +53,7 @@ void CommandManager::execute(Minecraft& mc, const std::string& input) { while (ss >> tok) args.push_back(tok); if (!mc.level->isClientSide || (*it)->getFlags() & CommandFlags::COMMAND_FLAG_SINGLEPLAYER_ONLY) { - (*it)->execute(mc, args); + (*it)->execute(mc, player, args); } else { ChatPacket packet("/" + input); mc.raknetInstance->send(packet); diff --git a/src/commands/CommandManager.hpp b/src/commands/CommandManager.hpp index 1304877..28817ea 100644 --- a/src/commands/CommandManager.hpp +++ b/src/commands/CommandManager.hpp @@ -10,7 +10,7 @@ public: std::vector getListAllCommands(); - void execute(Minecraft& mc, const std::string& input); + void execute(Minecraft& mc, Player& player, const std::string& input); Command* getCommand(const std::string& name); diff --git a/src/commands/CommandOp.cpp b/src/commands/CommandOp.cpp new file mode 100644 index 0000000..b53646e --- /dev/null +++ b/src/commands/CommandOp.cpp @@ -0,0 +1,35 @@ +#include "CommandOp.hpp" +#include "commands/Command.hpp" +#include "network/RakNetInstance.h" +#include "raknet/RakPeer.h" +#include "world/level/Level.h" +#include +#include + + +CommandOp::CommandOp() : Command("op") {} + +void CommandOp::execute(Minecraft& mc, Player& player, const std::vector& args) { + if (!isPlayerOp(mc, player)) { + return mc.addMessage("You aren't enough priveleged to run this command"); + } + + if (args.empty()) { + return printHelp(mc); + } + + auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args] (auto& it) -> bool { + return it->name == args[0]; + }); + + if (mc.level->ops.find(args[0]) != mc.level->ops.end()) { + return mc.addMessage("op: player " + args[0] + " already opped"); + } + + mc.level->ops.emplace((*it)->name); + mc.addMessage("op: successfully opped player " + args[0]); +} + +void CommandOp::printHelp(Minecraft& mc) { + mc.addMessage("Usage: /op "); +} \ No newline at end of file diff --git a/src/commands/CommandOp.hpp b/src/commands/CommandOp.hpp new file mode 100644 index 0000000..ef5b30a --- /dev/null +++ b/src/commands/CommandOp.hpp @@ -0,0 +1,9 @@ +#include "Command.hpp" + +class CommandOp : public Command { +public: + CommandOp(); + + void execute(Minecraft& mc, Player& player, const std::vector& args); + void printHelp(Minecraft& mc); +}; \ No newline at end of file diff --git a/src/world/level/Level.h b/src/world/level/Level.h index fb76474..e6ea67c 100755 --- a/src/world/level/Level.h +++ b/src/world/level/Level.h @@ -307,6 +307,9 @@ public: Dimension* dimension; IRakNetInstance* raknetInstance; Random random; + + std::set ops; + protected: bool isFindingSpawn; From 4dc7055d9de9dcd3c6b9220a68d7d811621cbd4a Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Tue, 31 Mar 2026 23:34:41 +0300 Subject: [PATCH 28/59] FIX: make antispeedhack working --- src/client/player/LocalPlayer.cpp | 2 +- src/network/ServerSideNetworkHandler.cpp | 50 ++++++++---------------- 2 files changed, 17 insertions(+), 35 deletions(-) diff --git a/src/client/player/LocalPlayer.cpp b/src/client/player/LocalPlayer.cpp index 88f7835..a4d3b74 100755 --- a/src/client/player/LocalPlayer.cpp +++ b/src/client/player/LocalPlayer.cpp @@ -438,7 +438,7 @@ void LocalPlayer::tick() { { if (std::abs(x - sentX) > .1f || std::abs(y - sentY) > .01f || std::abs(z - sentZ) > .1f || std::abs(sentRotX - xRot) > 1 || std::abs(sentRotY - yRot) > 1) { - MovePlayerPacket packet(entityId, xxa, y - heightOffset, yya, xRot, yRot); + MovePlayerPacket packet(entityId, x, y - heightOffset, z, xRot, yRot); minecraft->raknetInstance->send(packet); sentX = x; sentY = y; diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 40ac4a1..a069b0f 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -411,45 +411,27 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay if (Entity* entity = level->getEntity(packet->entityId)) { ServerPlayer* player = (ServerPlayer*) getPlayer(source); - float vectorDist = sqrt( (packet->x - entity->x) * (packet->x - entity->x) + - (packet->z - entity->z) * (packet->z - entity->z)); - float speed = vectorDist / (minecraft->getTicks() - player->getLastMoveTicks()); + int timeElapsed = minecraft->getTicks() - player->getLastMoveTicks(); - if (speed < 1.f) { - LOGI("Packet: %f, %f, %f \n", packet->x, packet->y, packet->z); - LOGI("Entity before: %f, %f, %f \n", entity->x, entity->y, entity->z); - LOGI("OnGround: %d \n", entity->onGround); + if (timeElapsed > 0) { + float dist = player->distanceTo(packet->x, player->y, packet->z); + float speed = dist / (minecraft->getTicks() - player->getLastMoveTicks()); + player->setLastMoveTicks(minecraft->getTicks()); - // @note: packet->y contains y with subtracted entity->heightOffset - float ya = packet->y - entity->y - entity->heightOffset; + float maxSpeed = (minecraft->isCreativeMode()) ? 1.65f : 1.f; - LOGI("y: %f \n", ya); + if (speed > maxSpeed) { + MovePlayerPacket refuse(player->entityId, player->x, player->y, player->z, player->xRot, player->yRot); + return raknetInstance->send(refuse); + } + } - float yaOrg = ya; - - // @BIGWARNING @fixme: blocks around work as shit - std::vector& aABBs = level->getCubes(entity, entity->bb.expand(0, ya, 0)); - - for (unsigned int i = 0; i < aABBs.size(); i++) - ya = aABBs[i].clipYCollide(entity->bb, ya); - - bool og = yaOrg != ya && yaOrg < 0; - - entity->onGround = og; - entity->checkFallDamage(ya, og); - entity->xd = entity->yd = entity->zd = 0; - entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3); - - LOGI("Entity after: %f, %f, %f \n", entity->x, entity->y, entity->z); - - // broadcast this packet to other clients - redistributePacket(packet, source); - } // else { - //MovePlayerPacket refuse(player->entityId, player->x, player->y, player->z, player->xRot, player->yRot); - //raknetInstance->send(refuse); - // } + 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); - player->setLastMoveTicks(minecraft->getTicks()); } } From 4023d7068784549bdfb02e9d080feaadfea66ee7 Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Sat, 4 Apr 2026 01:13:56 +0300 Subject: [PATCH 29/59] FEAT: server-side commands --- src/client/gui/screens/ConsoleScreen.cpp | 8 +++++-- src/commands/Command.hpp | 4 ++-- src/commands/CommandHelp.cpp | 28 +++++++++++++++--------- src/commands/CommandHelp.hpp | 4 ++-- src/commands/CommandKick.cpp | 14 ++++++------ src/commands/CommandKick.hpp | 4 ++-- src/commands/CommandManager.cpp | 8 ++++--- src/commands/CommandManager.hpp | 2 +- src/commands/CommandOp.cpp | 14 ++++++------ src/commands/CommandOp.hpp | 4 ++-- src/network/ClientSideNetworkHandler.cpp | 6 ++++- src/network/ServerSideNetworkHandler.cpp | 21 +++++++++++++++++- src/network/ServerSideNetworkHandler.h | 6 +++++ 13 files changed, 83 insertions(+), 40 deletions(-) diff --git a/src/client/gui/screens/ConsoleScreen.cpp b/src/client/gui/screens/ConsoleScreen.cpp index 9821f99..42f47ee 100644 --- a/src/client/gui/screens/ConsoleScreen.cpp +++ b/src/client/gui/screens/ConsoleScreen.cpp @@ -66,7 +66,11 @@ void ConsoleScreen::execute() if (_input[0] == '/') { // Command _input = Util::stringTrim(_input.substr(1)); - minecraft->commandManager().execute(*minecraft, *minecraft->player, _input); + + std::istringstream iss(minecraft->commandManager().execute(*minecraft, *minecraft->player, _input)); + for (std::string line; std::getline(iss, line); ) { + minecraft->gui.addMessage(line); + } } else { // @ai @rewrite if (minecraft->netCallback && minecraft->raknetInstance->isServer()) { @@ -75,7 +79,7 @@ void ConsoleScreen::execute() ChatPacket chatPkt(_input); minecraft->raknetInstance->send(chatPkt); } else { - minecraft->gui.addMessage(_input); + minecraft->gui.addMessage("<" + minecraft->player->name + "> " + _input); } } diff --git a/src/commands/Command.hpp b/src/commands/Command.hpp index f44c3df..fb3fdd0 100644 --- a/src/commands/Command.hpp +++ b/src/commands/Command.hpp @@ -17,8 +17,8 @@ public: bool isPlayerOp(Minecraft& mc, Player& player); - virtual void execute(Minecraft& mc, Player& player, const std::vector& args) = 0; - virtual void printHelp(Minecraft& mc) = 0; + virtual std::string execute(Minecraft& mc, Player& player, const std::vector& args) = 0; + virtual std::string help(Minecraft& mc) = 0; protected: Command(const std::string& name, CommandFlags flags = (CommandFlags)0) : m_name(name), m_flags(flags) {} diff --git a/src/commands/CommandHelp.cpp b/src/commands/CommandHelp.cpp index 18f7741..9f09da4 100644 --- a/src/commands/CommandHelp.cpp +++ b/src/commands/CommandHelp.cpp @@ -2,26 +2,34 @@ #include "commands/Command.hpp" #include "CommandManager.hpp" #include +#include CommandHelp::CommandHelp() : Command("help") {} -void CommandHelp::execute(Minecraft& mc, Player& player, const std::vector& args) { +std::string CommandHelp::execute(Minecraft& mc, Player& player, const std::vector& args) { if (args.empty()) { auto cmds = mc.commandManager().getListAllCommands(); - mc.addMessage("Usage: /help "); - mc.addMessage("List of all commands:"); + std::ostringstream output; + + output << "List of all commands:" << std::endl; for (auto& cmd : cmds) { - mc.addMessage(" - " + cmd); + output << " - " + cmd << std::endl;; } - } else { - Command* cmd = mc.commandManager().getCommand(args[0]); - if (cmd != nullptr) { - cmd->printHelp(mc); - } + return output.str(); } + + Command* cmd = mc.commandManager().getCommand(args[0]); + + if (cmd != nullptr) { + return cmd->help(mc); + } + + return "help: command " + args[0] + " not found"; } -void CommandHelp::printHelp(Minecraft& mc) {} \ No newline at end of file +std::string CommandHelp::help(Minecraft& mc) { + return "Usage: /help "; +} \ No newline at end of file diff --git a/src/commands/CommandHelp.hpp b/src/commands/CommandHelp.hpp index 48e1f1f..4c2349a 100644 --- a/src/commands/CommandHelp.hpp +++ b/src/commands/CommandHelp.hpp @@ -4,6 +4,6 @@ class CommandHelp : public Command { public: CommandHelp(); - void execute(Minecraft& mc, Player& player, const std::vector& args); - void printHelp(Minecraft& mc); + std::string execute(Minecraft& mc, Player& player, const std::vector& args); + std::string help(Minecraft& mc); }; \ No newline at end of file diff --git a/src/commands/CommandKick.cpp b/src/commands/CommandKick.cpp index b08ba86..2dad690 100644 --- a/src/commands/CommandKick.cpp +++ b/src/commands/CommandKick.cpp @@ -9,13 +9,13 @@ CommandKick::CommandKick() : Command("kick") {} -void CommandKick::execute(Minecraft& mc, Player& player, const std::vector& args) { +std::string CommandKick::execute(Minecraft& mc, Player& player, const std::vector& args) { if (!isPlayerOp(mc, player)) { - return mc.addMessage("You aren't enough priveleged to run this command"); + return "You aren't enough priveleged to run this command"; } if (args.empty()) { - return printHelp(mc); + return help(mc); } auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args] (auto& it) -> bool { @@ -23,11 +23,11 @@ void CommandKick::execute(Minecraft& mc, Player& player, const std::vectorplayers.end()) { - return mc.addMessage("kick: can't find player with name " + args[0]); + return "kick: can't find player with name " + args[0]; } if (*it == (Player*)mc.player) { - return mc.addMessage("kick: you can't kick urself lol"); + return "kick: you can't kick urself lol"; } mc.level->removePlayer(*it); @@ -36,6 +36,6 @@ void CommandKick::execute(Minecraft& mc, Player& player, const std::vector"); +std::string CommandKick::help(Minecraft& mc) { + return "Usage: /kick "; } \ No newline at end of file diff --git a/src/commands/CommandKick.hpp b/src/commands/CommandKick.hpp index 80225a8..5b94819 100644 --- a/src/commands/CommandKick.hpp +++ b/src/commands/CommandKick.hpp @@ -4,6 +4,6 @@ class CommandKick : public Command { public: CommandKick(); - void execute(Minecraft& mc, Player& player, const std::vector& args); - void printHelp(Minecraft& mc); + std::string execute(Minecraft& mc, Player& player, const std::vector& args); + std::string help(Minecraft& mc); }; \ No newline at end of file diff --git a/src/commands/CommandManager.cpp b/src/commands/CommandManager.cpp index 2b7f7f0..f92f380 100644 --- a/src/commands/CommandManager.cpp +++ b/src/commands/CommandManager.cpp @@ -33,7 +33,7 @@ std::vector CommandManager::getListAllCommands() { return ret; } -void CommandManager::execute(Minecraft& mc, Player& player, const std::string& input) { +std::string CommandManager::execute(Minecraft& mc, Player& player, const std::string& input) { std::istringstream ss(input); std::string cmd; @@ -44,7 +44,7 @@ void CommandManager::execute(Minecraft& mc, Player& player, const std::string& i }); if (it == m_commands.end()) { - return mc.addMessage("Command /" + cmd + " not found"); + return "Command /" + cmd + " not found"; } std::vector args; @@ -53,11 +53,13 @@ void CommandManager::execute(Minecraft& mc, Player& player, const std::string& i while (ss >> tok) args.push_back(tok); if (!mc.level->isClientSide || (*it)->getFlags() & CommandFlags::COMMAND_FLAG_SINGLEPLAYER_ONLY) { - (*it)->execute(mc, player, args); + return (*it)->execute(mc, player, args); } else { ChatPacket packet("/" + input); mc.raknetInstance->send(packet); } + + return ""; } Command* CommandManager::getCommand(const std::string& name) { diff --git a/src/commands/CommandManager.hpp b/src/commands/CommandManager.hpp index 28817ea..c33b363 100644 --- a/src/commands/CommandManager.hpp +++ b/src/commands/CommandManager.hpp @@ -10,7 +10,7 @@ public: std::vector getListAllCommands(); - void execute(Minecraft& mc, Player& player, const std::string& input); + std::string execute(Minecraft& mc, Player& player, const std::string& input); Command* getCommand(const std::string& name); diff --git a/src/commands/CommandOp.cpp b/src/commands/CommandOp.cpp index b53646e..df28db5 100644 --- a/src/commands/CommandOp.cpp +++ b/src/commands/CommandOp.cpp @@ -9,13 +9,13 @@ CommandOp::CommandOp() : Command("op") {} -void CommandOp::execute(Minecraft& mc, Player& player, const std::vector& args) { +std::string CommandOp::execute(Minecraft& mc, Player& player, const std::vector& args) { if (!isPlayerOp(mc, player)) { - return mc.addMessage("You aren't enough priveleged to run this command"); + return "You aren't enough priveleged to run this command"; } if (args.empty()) { - return printHelp(mc); + return help(mc); } auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args] (auto& it) -> bool { @@ -23,13 +23,13 @@ void CommandOp::execute(Minecraft& mc, Player& player, const std::vectorops.find(args[0]) != mc.level->ops.end()) { - return mc.addMessage("op: player " + args[0] + " already opped"); + return "op: player " + args[0] + " already opped"; } mc.level->ops.emplace((*it)->name); - mc.addMessage("op: successfully opped player " + args[0]); + return "op: successfully opped player " + args[0]; } -void CommandOp::printHelp(Minecraft& mc) { - mc.addMessage("Usage: /op "); +std::string CommandOp::help(Minecraft& mc) { + return "Usage: /op "; } \ No newline at end of file diff --git a/src/commands/CommandOp.hpp b/src/commands/CommandOp.hpp index ef5b30a..e91eea9 100644 --- a/src/commands/CommandOp.hpp +++ b/src/commands/CommandOp.hpp @@ -4,6 +4,6 @@ class CommandOp : public Command { public: CommandOp(); - void execute(Minecraft& mc, Player& player, const std::vector& args); - void printHelp(Minecraft& mc); + std::string execute(Minecraft& mc, Player& player, const std::vector& args); + std::string help(Minecraft& mc); }; \ No newline at end of file diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index 2ae545a..ecfc12d 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -949,7 +949,11 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, Containe void ClientSideNetworkHandler::handle( const RakNet::RakNetGUID& source, ChatPacket* packet ) { #ifndef STANDALONE_SERVER - minecraft->gui.displayClientMessage(packet->message); + // minecraft->gui.displayClientMessage(packet->message); + std::istringstream iss(packet->message); + for (std::string line; std::getline(iss, line); ) { + minecraft->gui.addMessage(line); + } #endif } diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index a069b0f..69793b4 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -5,6 +5,7 @@ #include "../world/entity/player/Inventory.h" #include "../world/Container.h" #include "../world/inventory/BaseContainerMenu.h" +#include "network/packet/ChatPacket.h" #include "network/packet/ContainerSetSlotPacket.h" #include "network/packet/LoginStatusPacket.h" #include "network/packet/MovePlayerPacket.h" @@ -24,6 +25,7 @@ #include "../raknet/PacketPriority.h" #include "platform/log.h" #include "util/Mth.h" +#include "util/StringUtils.h" #include "world/item/ItemInstance.h" #include "world/level/storage/LevelStorage.h" #include "world/phys/Vec3.h" @@ -154,7 +156,18 @@ void ServerSideNetworkHandler::displayGameMessage(const std::string& message) void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChatPacket* packet) { - displayGameMessage(packet->message); + auto player = getPlayer(source); + + if (player == nullptr) return; // TODO maybe kick? + + if (packet->message[0] == '/') { + // This is a command + + ChatPacket resp(minecraft->commandManager().execute(*minecraft, *player, Util::stringTrim(packet->message.substr(1)))); + return sendPrivate(resp, source); + } + + displayGameMessage("<" + player->name + "> " + packet->message); } void ServerSideNetworkHandler::onNewClient(const RakNet::RakNetGUID& clientGuid) @@ -1020,3 +1033,9 @@ Player* ServerSideNetworkHandler::getPlayer( const RakNet::RakNetGUID& source ) if (source == level->players[i]->owner) return level->players[i]; return NULL; } + +void ServerSideNetworkHandler::sendPrivate(Packet& packet, const RakNet::RakNetGUID& source) { + RakNet::BitStream bitStream; + packet.write(&bitStream); + rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false); +} \ No newline at end of file diff --git a/src/network/ServerSideNetworkHandler.h b/src/network/ServerSideNetworkHandler.h index a65585a..1e9585d 100755 --- a/src/network/ServerSideNetworkHandler.h +++ b/src/network/ServerSideNetworkHandler.h @@ -71,6 +71,12 @@ private: * @brief Send packet to all players */ void redistributePacket(Packet* packet, const RakNet::RakNetGUID& fromPlayer); + + /** + * @brief Send packer private with GUID + */ + void sendPrivate(Packet& packet, const RakNet::RakNetGUID& source); + Player* getPlayer(const RakNet::RakNetGUID& source); Minecraft* minecraft; From 0645905fc618075dc643f93b22df9790b73f9e99 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Mon, 27 Apr 2026 22:18:18 +0200 Subject: [PATCH 30/59] eeee it doesnt work :sob: --- src/network/ClientSideNetworkHandler.cpp | 20 +++++++++++++- src/network/ClientSideNetworkHandler.h | 6 ++--- src/network/ServerSideNetworkHandler.cpp | 13 ++++------ src/network/packet/StartGamePacket.h | 12 +++++++-- src/world/level/LevelConstants.h | 12 +++------ src/world/level/chunk/ChunkCache.h | 33 ++++++++++++------------ src/world/level/chunk/LevelChunk.h | 4 +-- 7 files changed, 60 insertions(+), 40 deletions(-) diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index ecfc12d..14e87cf 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -12,6 +12,7 @@ #include "../client/Minecraft.h" #include "../client/gamemode/GameMode.h" #include "world/item/ItemInstance.h" +#include "world/level/LevelConstants.h" #ifndef STANDALONE_SERVER #include "../client/gui/screens/DisconnectionScreen.h" #endif @@ -99,6 +100,10 @@ void ClientSideNetworkHandler::onUnableToConnect() void ClientSideNetworkHandler::onDisconnect(const RakNet::RakNetGUID& guid) { + CHUNK_CACHE_WIDTH = 16; + LEVEL_WIDTH = CHUNK_CACHE_WIDTH * CHUNK_WIDTH; + LEVEL_DEPTH = CHUNK_CACHE_WIDTH * CHUNK_DEPTH; + // TODO: Good disconnecting LOGI("onDisconnect\n"); if (level) @@ -155,6 +160,19 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, StartGam } #endif + // @todo @note i think its trash + // we can put it directly to selectLevel? + if (packet->chunkCacheWidth != 0) { + printf("lol \n"); + CHUNK_CACHE_WIDTH = packet->chunkCacheWidth; + LEVEL_WIDTH = CHUNK_CACHE_WIDTH * CHUNK_WIDTH; + LEVEL_DEPTH = CHUNK_CACHE_WIDTH * CHUNK_DEPTH; + + } + NumRequestChunks = CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH; + requestNextChunkIndexList.resize(NumRequestChunks); + chunksLoaded.resize(NumRequestChunks); + const std::string& levelId = LevelStorageSource::TempLevelId; LevelStorageSource* storageSource = minecraft->getLevelSource(); storageSource->deleteLevel(levelId); @@ -696,7 +714,7 @@ void ClientSideNetworkHandler::arrangeRequestChunkOrder() { } _ChunkSorter sorter(cx, cz); - std::sort(requestNextChunkIndexList, requestNextChunkIndexList + NumRequestChunks, sorter); + std::sort(requestNextChunkIndexList.begin(), requestNextChunkIndexList.end(), sorter); } void ClientSideNetworkHandler::levelGenerated(Level* level) diff --git a/src/network/ClientSideNetworkHandler.h b/src/network/ClientSideNetworkHandler.h index 4847c74..57e0d81 100755 --- a/src/network/ClientSideNetworkHandler.h +++ b/src/network/ClientSideNetworkHandler.h @@ -102,11 +102,11 @@ private: BlockUpdateList bufferedBlockUpdates; int requestNextChunkPosition; - static const int NumRequestChunks = CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH; + int NumRequestChunks; int requestNextChunkIndex; - IntPair requestNextChunkIndexList[NumRequestChunks]; - bool chunksLoaded[NumRequestChunks]; + std::vector requestNextChunkIndexList; + std::vector chunksLoaded; }; #endif diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 69793b4..0a70530 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -27,6 +27,7 @@ #include "util/Mth.h" #include "util/StringUtils.h" #include "world/item/ItemInstance.h" +#include "world/level/LevelConstants.h" #include "world/level/storage/LevelStorage.h" #include "world/phys/Vec3.h" #include "world/item/crafting/Recipe.h" @@ -219,8 +220,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac // bool oldClient = packet->clientNetworkVersion < SharedConstants::NetworkProtocolLowestSupportedVersion; bool oldServer = packet->clientNetworkLowestSupportedVersion > SharedConstants::NetworkProtocolVersion; - if (oldClient || oldServer) - loginStatus = oldClient? LoginStatus::Failed_ClientOld : LoginStatus::Failed_ServerOld; + if (oldClient || oldServer || !packet->newProto) + loginStatus = oldClient || !packet->newProto? LoginStatus::Failed_ClientOld : LoginStatus::Failed_ServerOld; for (int i = 0; i < level->players.size(); i++) { ServerPlayer* player = (ServerPlayer*) level->players.at(i); @@ -272,15 +273,11 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac level->getLevelData()->getGeneratorVersion(), gameType, newPlayer->entityId, - newPlayer->x, newPlayer->y - newPlayer->heightOffset, newPlayer->z + newPlayer->x, newPlayer->y - newPlayer->heightOffset, newPlayer->z, + CHUNK_CACHE_WIDTH ).write(&bitStream); rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false); - - if (!packet->newProto) { - MessagePacket packet("You're using outdated client. Some features disabled."); - raknetInstance->send(packet); - } } } diff --git a/src/network/packet/StartGamePacket.h b/src/network/packet/StartGamePacket.h index 24adead..e1b037e 100755 --- a/src/network/packet/StartGamePacket.h +++ b/src/network/packet/StartGamePacket.h @@ -2,6 +2,7 @@ #define NET_MINECRAFT_NETWORK_PACKET__StartGamePacket_H__ #include "../Packet.h" +#include "world/level/LevelConstants.h" #include class StartGamePacket : public Packet @@ -14,18 +15,20 @@ public: int entityId; float x, y, z; + int chunkCacheWidth = 0; StartGamePacket() { } - StartGamePacket(long seed, int levelGeneratorVersion, int gameType, int entityId, float x, float y, float z) + StartGamePacket(long seed, int levelGeneratorVersion, int gameType, int entityId, float x, float y, float z, int chunkCacheWidth) : levelSeed((int32_t)seed), levelGeneratorVersion(levelGeneratorVersion), gameType(gameType), entityId(entityId), x(x), y(y), - z(z) + z(z), + chunkCacheWidth(chunkCacheWidth) { } @@ -40,6 +43,7 @@ public: bitStream->Write(x); bitStream->Write(y); bitStream->Write(z); + bitStream->Write(CHUNK_CACHE_WIDTH); } void read(RakNet::BitStream* bitStream) @@ -51,6 +55,10 @@ public: bitStream->Read(x); bitStream->Read(y); bitStream->Read(z); + + if (bitStream->GetNumberOfUnreadBits() > 0) { + bitStream->Read(chunkCacheWidth); + } } void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) diff --git a/src/world/level/LevelConstants.h b/src/world/level/LevelConstants.h index 4d6865b..18f3a0b 100755 --- a/src/world/level/LevelConstants.h +++ b/src/world/level/LevelConstants.h @@ -1,14 +1,10 @@ -#ifndef _MINECRAFT_WORLD_LEVELCONSTANTS_H_ -#define _MINECRAFT_WORLD_LEVELCONSTANTS_H_ - +#pragma once const int LEVEL_HEIGHT = 128; -const int CHUNK_CACHE_WIDTH = 16; // in chunks +int CHUNK_CACHE_WIDTH = 16; // in chunks const int CHUNK_WIDTH = 16; // in blocks const int CHUNK_DEPTH = 16; -const int LEVEL_WIDTH = CHUNK_CACHE_WIDTH * CHUNK_WIDTH; -const int LEVEL_DEPTH = CHUNK_CACHE_WIDTH * CHUNK_DEPTH; +int LEVEL_WIDTH = CHUNK_CACHE_WIDTH * CHUNK_WIDTH; +int LEVEL_DEPTH = CHUNK_CACHE_WIDTH * CHUNK_DEPTH; const int CHUNK_COLUMNS = CHUNK_WIDTH * CHUNK_DEPTH; const int CHUNK_BLOCK_COUNT = CHUNK_COLUMNS * LEVEL_HEIGHT; - -#endif diff --git a/src/world/level/chunk/ChunkCache.h b/src/world/level/chunk/ChunkCache.h index b1b16fe..1401905 100755 --- a/src/world/level/chunk/ChunkCache.h +++ b/src/world/level/chunk/ChunkCache.h @@ -24,7 +24,8 @@ public: isChunkCache = true; //emptyChunk = new EmptyLevelChunk(level_, emptyChunkBlocks, 0, 0); emptyChunk = new EmptyLevelChunk(level_, NULL, 0, 0); - memset(chunks, 0, sizeof(LevelChunk*) * CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH); + + chunks = (LevelChunk *)malloc(CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH); } ~ChunkCache() { @@ -33,10 +34,10 @@ public: for (int i = 0; i < CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH; i++) { - if (chunks[i]) + if (&chunks[i]) { - chunks[i]->deleteBlockData(); - delete chunks[i]; + chunks[i].deleteBlockData(); + delete &chunks[i]; } } } @@ -55,7 +56,7 @@ public: int xs = x & (CHUNK_CACHE_WIDTH - 1); int zs = z & (CHUNK_CACHE_WIDTH - 1); int slot = xs + zs * CHUNK_CACHE_WIDTH; - return chunks[slot] != NULL && (chunks[slot] == emptyChunk || chunks[slot]->isAt(x, z)); + return &chunks[slot] != NULL && (&chunks[slot] == emptyChunk || chunks[slot].isAt(x, z)); } LevelChunk* create(int x, int z) { @@ -75,10 +76,10 @@ public: int zs = z & (CHUNK_CACHE_WIDTH - 1); int slot = xs + zs * CHUNK_CACHE_WIDTH; if (!hasChunk(x, z)) { - if (chunks[slot] != NULL) { - chunks[slot]->unload(); - save(chunks[slot]); - saveEntities(chunks[slot]); + if (&chunks[slot] != NULL) { + chunks[slot].unload(); + save(&chunks[slot]); + saveEntities(&chunks[slot]); } LevelChunk* newChunk = load(x, z); @@ -93,7 +94,7 @@ public: //return emptyChunk; updateLights = true; } - chunks[slot] = newChunk; + chunks[slot] = *newChunk; newChunk->lightLava(); if (updateLights) @@ -114,23 +115,23 @@ public: //level->updateLight(LightLayer::Block, x * 16, 0, z * 16, x * 16 + 15, 128, z * 16 + 15); } - if (chunks[slot] != NULL) { - chunks[slot]->load(); + if (&chunks[slot] != NULL) { + chunks[slot].load(); } - if (!chunks[slot]->terrainPopulated && hasChunk(x + 1, z + 1) && hasChunk(x, z + 1) && hasChunk(x + 1, z)) postProcess(this, x, z); + if (!chunks[slot].terrainPopulated && hasChunk(x + 1, z + 1) && hasChunk(x, z + 1) && hasChunk(x + 1, z)) postProcess(this, x, z); if (hasChunk(x - 1, z) && !getChunk(x - 1, z)->terrainPopulated && hasChunk(x - 1, z + 1) && hasChunk(x, z + 1) && hasChunk(x - 1, z)) postProcess(this, x - 1, z); if (hasChunk(x, z - 1) && !getChunk(x, z - 1)->terrainPopulated && hasChunk(x + 1, z - 1) && hasChunk(x, z - 1) && hasChunk(x + 1, z)) postProcess(this, x, z - 1); if (hasChunk(x - 1, z - 1) && !getChunk(x - 1, z - 1)->terrainPopulated && hasChunk(x - 1, z - 1) && hasChunk(x, z - 1) && hasChunk(x - 1, z)) postProcess(this, x - 1, z - 1); } xLast = x; zLast = z; - last = chunks[slot]; + last = &chunks[slot]; //sw.stop(); //sw.printEvery(500000, "ChunkCache::load: "); - return chunks[slot]; + return &chunks[slot]; } Biome::MobList getMobsAt(const MobCategory& mobCategory, int x, int y, int z) { @@ -254,7 +255,7 @@ private: LevelChunk* emptyChunk; ChunkSource* source; ChunkStorage* storage; - LevelChunk* chunks[CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH]; + LevelChunk* chunks; Level* level; LevelChunk* last; diff --git a/src/world/level/chunk/LevelChunk.h b/src/world/level/chunk/LevelChunk.h index 5735744..c06819e 100755 --- a/src/world/level/chunk/LevelChunk.h +++ b/src/world/level/chunk/LevelChunk.h @@ -122,8 +122,8 @@ public: unsigned char updateMap[CHUNK_COLUMNS]; // marks regions within block columns that have been modified int minHeight; - const int x, z; - const int xt, zt; + int x, z; + int xt, zt; bool terrainPopulated; bool unsaved; From de72a9a3b79cd907240d0ab41691e16e9558c03f Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Mon, 27 Apr 2026 23:43:36 +0200 Subject: [PATCH 31/59] all was broken :\ --- src/client/Minecraft.cpp | 10 +-- src/client/renderer/LevelRenderer.cpp | 2 +- src/network/ClientSideNetworkHandler.cpp | 68 +++++++++---------- src/network/ServerSideNetworkHandler.cpp | 2 +- src/network/command/CommandServer.cpp | 10 +-- src/network/packet/ChunkDataPacket.h | 8 +-- src/network/packet/StartGamePacket.h | 4 +- src/world/entity/Entity.cpp | 4 +- src/world/level/Level.cpp | 24 +++---- src/world/level/Level.h | 4 +- src/world/level/LevelConstants.cpp | 7 ++ src/world/level/LevelConstants.h | 20 +++--- src/world/level/chunk/ChunkCache.h | 26 +++---- src/world/level/chunk/LevelChunk.cpp | 11 +-- src/world/level/chunk/LevelChunk.h | 10 +-- .../level/levelgen/RandomLevelSource.cpp | 16 ++--- .../storage/ExternalFileLevelStorage.cpp | 34 +++++----- src/world/level/tile/Mushroom.cpp | 2 +- src/world/level/tile/NetherReactor.cpp | 2 +- .../tile/entity/NetherReactorTileEntity.cpp | 4 +- 20 files changed, 141 insertions(+), 127 deletions(-) create mode 100644 src/world/level/LevelConstants.cpp diff --git a/src/client/Minecraft.cpp b/src/client/Minecraft.cpp index 05e397b..6698c3d 100755 --- a/src/client/Minecraft.cpp +++ b/src/client/Minecraft.cpp @@ -362,10 +362,10 @@ void Minecraft::prepareLevel(const std::string& title) { if (!level->isNew()) level->setUpdateLights(false); - int Max = CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH; + int Max = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH; int pp = 0; - for (int x = 8; x < (CHUNK_CACHE_WIDTH * CHUNK_WIDTH); x += CHUNK_WIDTH) { - for (int z = 8; z < (CHUNK_CACHE_WIDTH * CHUNK_WIDTH); z += CHUNK_WIDTH) { + for (int x = 8; x < (LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_WIDTH); x += LevelConstants::CHUNK_WIDTH) { + for (int z = 8; z < (LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_WIDTH); z += LevelConstants::CHUNK_WIDTH) { progressStagePercentage = 100 * pp++ / Max; //printf("level generation progress %d\n", progressStagePercentage); B.start(); @@ -382,9 +382,9 @@ void Minecraft::prepareLevel(const std::string& title) { level->setUpdateLights(true); C.start(); - for (int x = 0; x < CHUNK_CACHE_WIDTH; x++) + for (int x = 0; x < LevelConstants::CHUNK_CACHE_WIDTH; x++) { - for (int z = 0; z < CHUNK_CACHE_WIDTH; z++) + for (int z = 0; z < LevelConstants::CHUNK_CACHE_WIDTH; z++) { LevelChunk* chunk = level->getChunk(x, z); if (chunk && !chunk->createdFromSave) diff --git a/src/client/renderer/LevelRenderer.cpp b/src/client/renderer/LevelRenderer.cpp index 3520732..c3f1161 100755 --- a/src/client/renderer/LevelRenderer.cpp +++ b/src/client/renderer/LevelRenderer.cpp @@ -65,7 +65,7 @@ LevelRenderer::LevelRenderer( Minecraft* mc) destroyProgress(0) { #ifdef OPENGL_ES - int maxChunksWidth = 2 * LEVEL_WIDTH / CHUNK_SIZE + 1; + int maxChunksWidth = 2 * LevelConstants::LEVEL_WIDTH / CHUNK_SIZE + 1; numListsOrBuffers = maxChunksWidth * maxChunksWidth * (128/CHUNK_SIZE) * 3; chunkBuffers = new GLuint[numListsOrBuffers]; glGenBuffers2(numListsOrBuffers, chunkBuffers); diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index 14e87cf..c1515f7 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -62,7 +62,7 @@ void ClientSideNetworkHandler::requestNextChunk() //LOGI("requesting chunks @ (%d, %d)\n", chunk.x, chunk.y); - //raknetInstance->send(new RequestChunkPacket(requestNextChunkPosition % CHUNK_CACHE_WIDTH, requestNextChunkPosition / CHUNK_CACHE_WIDTH)); + //raknetInstance->send(new RequestChunkPacket(requestNextChunkPosition % LevelConstants::CHUNK_CACHE_WIDTH, requestNextChunkPosition / LevelConstants::CHUNK_CACHE_WIDTH)); requestNextChunkIndex++; requestNextChunkPosition++; } @@ -70,16 +70,16 @@ void ClientSideNetworkHandler::requestNextChunk() bool ClientSideNetworkHandler::areAllChunksLoaded() { - return (requestNextChunkPosition >= (CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH)); + return (requestNextChunkPosition >= (LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH)); } bool ClientSideNetworkHandler::isChunkLoaded(int x, int z) { - if (x < 0 || x >= CHUNK_CACHE_WIDTH || z < 0 || z >= CHUNK_CACHE_WIDTH) { + if (x < 0 || x >= LevelConstants::CHUNK_CACHE_WIDTH || z < 0 || z >= LevelConstants::CHUNK_CACHE_WIDTH) { LOGE("Error: Tried to request chunk (%d, %d)\n", x, z); return true; } - return chunksLoaded[x * CHUNK_CACHE_WIDTH + z]; + return chunksLoaded[x * LevelConstants::CHUNK_CACHE_WIDTH + z]; //return areAllChunksLoaded(); } @@ -100,9 +100,9 @@ void ClientSideNetworkHandler::onUnableToConnect() void ClientSideNetworkHandler::onDisconnect(const RakNet::RakNetGUID& guid) { - CHUNK_CACHE_WIDTH = 16; - LEVEL_WIDTH = CHUNK_CACHE_WIDTH * CHUNK_WIDTH; - LEVEL_DEPTH = CHUNK_CACHE_WIDTH * CHUNK_DEPTH; + LevelConstants::CHUNK_CACHE_WIDTH = 16; + LevelConstants::LEVEL_WIDTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_WIDTH; + LevelConstants::LEVEL_DEPTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_DEPTH; // TODO: Good disconnecting LOGI("onDisconnect\n"); @@ -164,12 +164,12 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, StartGam // we can put it directly to selectLevel? if (packet->chunkCacheWidth != 0) { printf("lol \n"); - CHUNK_CACHE_WIDTH = packet->chunkCacheWidth; - LEVEL_WIDTH = CHUNK_CACHE_WIDTH * CHUNK_WIDTH; - LEVEL_DEPTH = CHUNK_CACHE_WIDTH * CHUNK_DEPTH; + LevelConstants::CHUNK_CACHE_WIDTH = packet->chunkCacheWidth; + LevelConstants::LEVEL_WIDTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_WIDTH; + LevelConstants::LEVEL_DEPTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_DEPTH; } - NumRequestChunks = CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH; + NumRequestChunks = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH; requestNextChunkIndexList.resize(NumRequestChunks); chunksLoaded.resize(NumRequestChunks); @@ -551,19 +551,19 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChunkDat //unsigned char* blockIds = chunk->getBlockData(); DataLayer& blockData = chunk->data; - const int setSize = LEVEL_HEIGHT / 8; - const int setShift = 4; // power of LEVEL_HEIGHT / 8 + const int setSize = LevelConstants::LEVEL_HEIGHT / 8; + const int setShift = 4; // power of LevelConstants::LEVEL_HEIGHT / 8 bool recalcHeight = false; - int x0 = 16, x1 = 0, z0 = 16, z1 = 0, y0 = LEVEL_HEIGHT, y1 = 0; + int x0 = 16, x1 = 0, z0 = 16, z1 = 0, y0 = LevelConstants::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++) + for (int i = 0; i < LevelConstants::CHUNK_COLUMNS; i++) { unsigned char updateBits = 0; packet->chunkData.Read(updateBits); @@ -572,8 +572,8 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChunkDat { recalcHeight = true; - int colX = (i % CHUNK_WIDTH); - int colZ = (i / CHUNK_WIDTH); + int colX = (i % LevelConstants::CHUNK_WIDTH); + int colZ = (i / LevelConstants::CHUNK_WIDTH); int colDataPosition = colX << 11 | colZ << 7; for (int set = 0; set < 8; set++) @@ -607,26 +607,26 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChunkDat { y0 = ((1 << set) << setShift); } - if (((1 << set) << setShift) + (LEVEL_HEIGHT / 8) - 1 > y1) + if (((1 << set) << setShift) + (LevelConstants::LEVEL_HEIGHT / 8) - 1 > y1) { - y1 = ((1 << set) << setShift) + (LEVEL_HEIGHT / 8) - 1; + y1 = ((1 << set) << setShift) + (LevelConstants::LEVEL_HEIGHT / 8) - 1; } } - if ((i % CHUNK_WIDTH) < x0) + if ((i % LevelConstants::CHUNK_WIDTH) < x0) { - x0 = (i % CHUNK_WIDTH); + x0 = (i % LevelConstants::CHUNK_WIDTH); } - if ((i % CHUNK_WIDTH) > x1) + if ((i % LevelConstants::CHUNK_WIDTH) > x1) { - x1 = (i % CHUNK_WIDTH); + x1 = (i % LevelConstants::CHUNK_WIDTH); } - if ((i / CHUNK_WIDTH) < z0) + if ((i / LevelConstants::CHUNK_WIDTH) < z0) { - z0 = (i / CHUNK_WIDTH); + z0 = (i / LevelConstants::CHUNK_WIDTH); } - if ((i / CHUNK_WIDTH) > z1) + if ((i / LevelConstants::CHUNK_WIDTH) > z1) { - z1 = (i / CHUNK_WIDTH); + z1 = (i / LevelConstants::CHUNK_WIDTH); } } } @@ -655,7 +655,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChunkDat //chunk->terrainPopulated = true; chunk->unsaved = false; - chunksLoaded[packet->x * CHUNK_CACHE_WIDTH + packet->z] = true; + chunksLoaded[packet->x * LevelConstants::CHUNK_CACHE_WIDTH + packet->z] = true; if (areAllChunksLoaded()) { @@ -703,14 +703,14 @@ void ClientSideNetworkHandler::arrangeRequestChunkOrder() { clearChunksLoaded(); // Default sort is around center of the world - int cx = CHUNK_CACHE_WIDTH / 2; - int cz = CHUNK_CACHE_WIDTH / 2; + int cx = LevelConstants::CHUNK_CACHE_WIDTH / 2; + int cz = LevelConstants::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); + cx = Mth::floor(p->x / (float)LevelConstants::CHUNK_WIDTH); + cz = Mth::floor(p->z / (float)LevelConstants::CHUNK_DEPTH); } _ChunkSorter sorter(cx, cz); @@ -1004,8 +1004,8 @@ 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; + requestNextChunkIndexList[i].x = i / LevelConstants::CHUNK_WIDTH; + requestNextChunkIndexList[i].y = i % LevelConstants::CHUNK_WIDTH; chunksLoaded[i] = false; } } diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 0a70530..e7e10fb 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -274,7 +274,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac gameType, newPlayer->entityId, newPlayer->x, newPlayer->y - newPlayer->heightOffset, newPlayer->z, - CHUNK_CACHE_WIDTH + LevelConstants::CHUNK_CACHE_WIDTH ).write(&bitStream); rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false); diff --git a/src/network/command/CommandServer.cpp b/src/network/command/CommandServer.cpp index 14417c2..280b0a9 100755 --- a/src/network/command/CommandServer.cpp +++ b/src/network/command/CommandServer.cpp @@ -236,9 +236,9 @@ std::string CommandServer::parse(ConnectedClient& client, const std::string& s) 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; + if (x1 >= LevelConstants::LEVEL_WIDTH ) x1 = LevelConstants::LEVEL_WIDTH - 1; + if (y1 >= LevelConstants::LEVEL_HEIGHT) y1 = LevelConstants::LEVEL_HEIGHT - 1; + if (z1 >= LevelConstants::LEVEL_DEPTH ) z1 = LevelConstants::LEVEL_DEPTH - 1; for (int y = y0; y <= y1; ++y) for (int z = z0; z <= z1; ++z) @@ -456,7 +456,7 @@ std::string CommandServer::parse(ConnectedClient& client, const std::string& s) sw.start(); // Save a cuboid around the player - const int CSize = CHUNK_CACHE_WIDTH; + const int CSize = LevelConstants::CHUNK_CACHE_WIDTH; int cx = (int)e->x / CSize; int cz = (int)e->z / CSize; @@ -504,7 +504,7 @@ bool CommandServer::handleCheckpoint(bool doRestore ) { const int cz = restorePos.z; const int y0 = restorePos.y; const int y1 = y0 + RestoreHeight; - const int CSize = CHUNK_CACHE_WIDTH; + const int CSize = LevelConstants::CHUNK_CACHE_WIDTH; const int numChunkBytes = RestoreHeight * CSize * CSize * 20 / 8; if (!restoreBuffer) { diff --git a/src/network/packet/ChunkDataPacket.h b/src/network/packet/ChunkDataPacket.h index 51f1719..b272685 100755 --- a/src/network/packet/ChunkDataPacket.h +++ b/src/network/packet/ChunkDataPacket.h @@ -33,18 +33,18 @@ public: unsigned char* blockIds = chunk->getBlockData(); DataLayer& blockData = chunk->data; - const int setSize = LEVEL_HEIGHT / 8; - const int setShift = 4; // power of LEVEL_HEIGHT / 8 + const int setSize = LevelConstants::LEVEL_HEIGHT / 8; + const int setShift = 4; // power of LevelConstants::LEVEL_HEIGHT / 8 chunkData.Reset(); - for (int i = 0; i < CHUNK_COLUMNS; i++) + for (int i = 0; i < LevelConstants::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; + int colDataPosition = (i % LevelConstants::CHUNK_WIDTH) << 11 | (i / LevelConstants::CHUNK_WIDTH) << 7; for (int set = 0; set < 8; set++) { diff --git a/src/network/packet/StartGamePacket.h b/src/network/packet/StartGamePacket.h index e1b037e..f2ce50f 100755 --- a/src/network/packet/StartGamePacket.h +++ b/src/network/packet/StartGamePacket.h @@ -43,7 +43,7 @@ public: bitStream->Write(x); bitStream->Write(y); bitStream->Write(z); - bitStream->Write(CHUNK_CACHE_WIDTH); + bitStream->Write(LevelConstants::CHUNK_CACHE_WIDTH); } void read(RakNet::BitStream* bitStream) @@ -55,7 +55,7 @@ public: bitStream->Read(x); bitStream->Read(y); bitStream->Read(z); - + if (bitStream->GetNumberOfUnreadBits() > 0) { bitStream->Read(chunkCacheWidth); } diff --git a/src/world/entity/Entity.cpp b/src/world/entity/Entity.cpp index bfccad7..a4e77e7 100755 --- a/src/world/entity/Entity.cpp +++ b/src/world/entity/Entity.cpp @@ -871,8 +871,8 @@ bool Entity::load( CompoundTag* tag ) // Add a small padding if standing next to the world edges const float padding = bbWidth * 0.5f + 0.001f; - xx = Mth::clamp(xx, padding, (float)LEVEL_WIDTH - padding); - zz = Mth::clamp(zz, padding, (float)LEVEL_DEPTH - padding); + xx = Mth::clamp(xx, padding, (float)LevelConstants::LEVEL_WIDTH - padding); + zz = Mth::clamp(zz, padding, (float)LevelConstants::LEVEL_DEPTH - padding); xo = xOld = x = xx; yo = yOld = y = yy; diff --git a/src/world/level/Level.cpp b/src/world/level/Level.cpp index 96255eb..35fbd7e 100755 --- a/src/world/level/Level.cpp +++ b/src/world/level/Level.cpp @@ -278,8 +278,8 @@ void Level::tickTiles() { for (int i = 0; i < pollChunkOffsetsSize; i += 2) { const int xp = xx + pollChunkOffsets[i]; const int zp = zz + pollChunkOffsets[i+1]; - if (xp >= 0 && xp < CHUNK_CACHE_WIDTH && - zp >= 0 && zp < CHUNK_CACHE_WIDTH) + if (xp >= 0 && xp < LevelConstants::CHUNK_CACHE_WIDTH && + zp >= 0 && zp < LevelConstants::CHUNK_CACHE_WIDTH) _chunksToPoll.insert(ChunkPos(xp, zp)); } } @@ -428,17 +428,17 @@ bool Level::findPath(Path* path, Entity* from, int xBest, int yBest, int zBest, /*protected*/ void Level::setInitialSpawn() { isFindingSpawn = true; - int xSpawn = CHUNK_CACHE_WIDTH * CHUNK_WIDTH / 2; // (Level.MAX_LEVEL_SIZE - 100) * 0; + int xSpawn = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_WIDTH / 2; // (Level.MAX_LEVEL_SIZE - 100) * 0; int ySpawn = 64; - int zSpawn = CHUNK_CACHE_WIDTH * CHUNK_DEPTH / 2; // (Level.MAX_LEVEL_SIZE - 100) * 0; + int zSpawn = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_DEPTH / 2; // (Level.MAX_LEVEL_SIZE - 100) * 0; while (!dimension->isValidSpawn(xSpawn, zSpawn)) { xSpawn += random.nextInt(32) - random.nextInt(32); zSpawn += random.nextInt(32) - random.nextInt(32); if (xSpawn < 4) xSpawn += 32; - if (xSpawn >= LEVEL_WIDTH-4) xSpawn -= 32; + if (xSpawn >= LevelConstants::LEVEL_WIDTH-4) xSpawn -= 32; if (zSpawn < 4) zSpawn += 32; - if (zSpawn >= LEVEL_DEPTH-4) zSpawn -= 32; + if (zSpawn >= LevelConstants::LEVEL_DEPTH-4) zSpawn -= 32; } levelData.setSpawn(xSpawn, ySpawn, zSpawn); isFindingSpawn = false; @@ -456,9 +456,9 @@ void Level::validateSpawn() { zSpawn += random.nextInt(8) - random.nextInt(8); if (xSpawn < 4) xSpawn += 8; - if (xSpawn >= LEVEL_WIDTH-4) xSpawn -= 8; + if (xSpawn >= LevelConstants::LEVEL_WIDTH-4) xSpawn -= 8; if (zSpawn < 4) zSpawn += 8; - if (zSpawn >= LEVEL_DEPTH-4) zSpawn -= 8; + if (zSpawn >= LevelConstants::LEVEL_DEPTH-4) zSpawn -= 8; } levelData.setXSpawn(xSpawn); levelData.setZSpawn(zSpawn); @@ -944,7 +944,7 @@ HitResult Level::clip(const Vec3& A, const Vec3& b, bool liquid /*= false*/, boo if (solidOnly && tile != NULL && tile->getAABB(this, xTile0, yTile0, zTile0) == NULL) { // No collision } else if (t > 0 && tile->mayPick(data, liquid)) { - if(xTile0 >= 0 && zTile0 >= 0 && xTile0 < LEVEL_WIDTH && zTile0 < LEVEL_WIDTH) { + if(xTile0 >= 0 && zTile0 >= 0 && xTile0 < LevelConstants::LEVEL_WIDTH && zTile0 < LevelConstants::LEVEL_WIDTH) { HitResult r = tile->clip(this, xTile0, yTile0, zTile0, a, b); if (r.isHit()) return r; } @@ -2222,9 +2222,9 @@ void Level::setNightMode( bool isNightMode ) { } bool Level::inRange( int x, int y, int z ) { - return x >= 0 && x < LEVEL_WIDTH - && y >= 0 && y < LEVEL_HEIGHT - && z >= 0 && z < LEVEL_DEPTH; + return x >= 0 && x < LevelConstants::LEVEL_WIDTH + && y >= 0 && y < LevelConstants::LEVEL_HEIGHT + && z >= 0 && z < LevelConstants::LEVEL_DEPTH; } // diff --git a/src/world/level/Level.h b/src/world/level/Level.h index e6ea67c..082cb07 100755 --- a/src/world/level/Level.h +++ b/src/world/level/Level.h @@ -67,8 +67,8 @@ class Level: public LevelSource public: static const int MAX_LEVEL_SIZE = 32000000; - static const short DEPTH = LEVEL_HEIGHT; - static const short SEA_LEVEL = DEPTH / 2 - 1; + const short DEPTH = LevelConstants::LEVEL_HEIGHT; + const short SEA_LEVEL = DEPTH / 2 - 1; static const int MAX_BRIGHTNESS = 15; static const int TICKS_PER_DAY = SharedConstants::TicksPerSecond * 60 * 16;// SharedConstants::TicksPerSecond * 60 * 12; // ORG:20*60*20 diff --git a/src/world/level/LevelConstants.cpp b/src/world/level/LevelConstants.cpp new file mode 100644 index 0000000..864ce32 --- /dev/null +++ b/src/world/level/LevelConstants.cpp @@ -0,0 +1,7 @@ +#include "LevelConstants.h" + +int LevelConstants::LEVEL_HEIGHT = 128; +int LevelConstants::CHUNK_WIDTH = 16; // in blocks +int LevelConstants::CHUNK_DEPTH = 16; +int LevelConstants::CHUNK_COLUMNS = LevelConstants::CHUNK_WIDTH * LevelConstants::CHUNK_DEPTH; +int LevelConstants::CHUNK_BLOCK_COUNT = LevelConstants::CHUNK_COLUMNS * LevelConstants::LEVEL_HEIGHT; \ No newline at end of file diff --git a/src/world/level/LevelConstants.h b/src/world/level/LevelConstants.h index 18f3a0b..0b00053 100755 --- a/src/world/level/LevelConstants.h +++ b/src/world/level/LevelConstants.h @@ -1,10 +1,14 @@ #pragma once -const int LEVEL_HEIGHT = 128; -int CHUNK_CACHE_WIDTH = 16; // in chunks -const int CHUNK_WIDTH = 16; // in blocks -const int CHUNK_DEPTH = 16; -int LEVEL_WIDTH = CHUNK_CACHE_WIDTH * CHUNK_WIDTH; -int LEVEL_DEPTH = CHUNK_CACHE_WIDTH * CHUNK_DEPTH; -const int CHUNK_COLUMNS = CHUNK_WIDTH * CHUNK_DEPTH; -const int CHUNK_BLOCK_COUNT = CHUNK_COLUMNS * LEVEL_HEIGHT; +class LevelConstants { +public: + static int CHUNK_CACHE_WIDTH; // in chunks + static int LEVEL_WIDTH; + static int LEVEL_DEPTH; + + static int LEVEL_HEIGHT; + static int CHUNK_WIDTH; // in blocks + static int CHUNK_DEPTH; + static int CHUNK_COLUMNS; + static int CHUNK_BLOCK_COUNT; +}; \ No newline at end of file diff --git a/src/world/level/chunk/ChunkCache.h b/src/world/level/chunk/ChunkCache.h index 1401905..13f81e9 100755 --- a/src/world/level/chunk/ChunkCache.h +++ b/src/world/level/chunk/ChunkCache.h @@ -10,7 +10,7 @@ #include "../LevelConstants.h" class ChunkCache: public ChunkSource { - //static const int CHUNK_CACHE_WIDTH = CHUNK_CACHE_WIDTH; // WAS 32; + //static const int LevelConstants::CHUNK_CACHE_WIDTH = LevelConstants::CHUNK_CACHE_WIDTH; // WAS 32; static const int MAX_SAVES = 2; public: ChunkCache(Level* level_, ChunkStorage* storage_, ChunkSource* source_) @@ -25,14 +25,14 @@ public: //emptyChunk = new EmptyLevelChunk(level_, emptyChunkBlocks, 0, 0); emptyChunk = new EmptyLevelChunk(level_, NULL, 0, 0); - chunks = (LevelChunk *)malloc(CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH); + chunks = (LevelChunk *)malloc(LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH); } ~ChunkCache() { delete source; delete emptyChunk; - for (int i = 0; i < CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH; i++) + for (int i = 0; i < LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH; i++) { if (&chunks[i]) { @@ -43,7 +43,7 @@ public: } bool fits(int x, int z) { - return (x >= 0 && z >= 0 && x < CHUNK_CACHE_WIDTH && z < CHUNK_CACHE_WIDTH); + return (x >= 0 && z >= 0 && x < LevelConstants::CHUNK_CACHE_WIDTH && z < LevelConstants::CHUNK_CACHE_WIDTH); } bool hasChunk(int x, int z) { @@ -53,9 +53,9 @@ public: if (x == xLast && z == zLast && last != NULL) { return true; } - int xs = x & (CHUNK_CACHE_WIDTH - 1); - int zs = z & (CHUNK_CACHE_WIDTH - 1); - int slot = xs + zs * CHUNK_CACHE_WIDTH; + int xs = x & (LevelConstants::CHUNK_CACHE_WIDTH - 1); + int zs = z & (LevelConstants::CHUNK_CACHE_WIDTH - 1); + int slot = xs + zs * LevelConstants::CHUNK_CACHE_WIDTH; return &chunks[slot] != NULL && (&chunks[slot] == emptyChunk || chunks[slot].isAt(x, z)); } @@ -72,9 +72,9 @@ public: } if (!fits(x, z)) return emptyChunk; //if (!level->isFindingSpawn && !fits(x, z)) return emptyChunk; - int xs = x & (CHUNK_CACHE_WIDTH - 1); - int zs = z & (CHUNK_CACHE_WIDTH - 1); - int slot = xs + zs * CHUNK_CACHE_WIDTH; + int xs = x & (LevelConstants::CHUNK_CACHE_WIDTH - 1); + int zs = z & (LevelConstants::CHUNK_CACHE_WIDTH - 1); + int slot = xs + zs * LevelConstants::CHUNK_CACHE_WIDTH; if (!hasChunk(x, z)) { if (&chunks[slot] != NULL) { chunks[slot].unload(); @@ -200,8 +200,8 @@ public: void saveAll(bool onlyUnsaved) { if (storage != NULL) { std::vector chunks; - for (int z = 0; z < CHUNK_CACHE_WIDTH; ++z) - for (int x = 0; x < CHUNK_CACHE_WIDTH; ++x) { + for (int z = 0; z < LevelConstants::CHUNK_CACHE_WIDTH; ++z) + for (int x = 0; x < LevelConstants::CHUNK_CACHE_WIDTH; ++x) { LevelChunk* chunk = level->getChunk(x, z); if (!onlyUnsaved || chunk->shouldSave(false)) chunks.push_back( chunk ); @@ -212,7 +212,7 @@ public: private: LevelChunk* load(int x, int z) { if (storage == NULL) return emptyChunk; - if (x < 0 || x >= CHUNK_CACHE_WIDTH || z < 0 || z >= CHUNK_CACHE_WIDTH) + if (x < 0 || x >= LevelConstants::CHUNK_CACHE_WIDTH || z < 0 || z >= LevelConstants::CHUNK_CACHE_WIDTH) { return emptyChunk; } diff --git a/src/world/level/chunk/LevelChunk.cpp b/src/world/level/chunk/LevelChunk.cpp index bb373fb..2710f21 100755 --- a/src/world/level/chunk/LevelChunk.cpp +++ b/src/world/level/chunk/LevelChunk.cpp @@ -17,8 +17,8 @@ LevelChunk::LevelChunk( Level* level, int x, int z ) : level(level), x(x), z(z), - xt(x * CHUNK_WIDTH), - zt(z * CHUNK_DEPTH) + xt(x * LevelConstants::CHUNK_WIDTH), + zt(z * LevelConstants::CHUNK_DEPTH) { init(); } @@ -27,8 +27,8 @@ LevelChunk::LevelChunk( Level* level, unsigned char* blocks, int x, int z ) : level(level), x(x), z(z), - xt(x * CHUNK_WIDTH), - zt(z * CHUNK_DEPTH), + xt(x * LevelConstants::CHUNK_WIDTH), + zt(z * LevelConstants::CHUNK_DEPTH), blocks(blocks), data(ChunkBlockCount), skyLight(ChunkBlockCount), @@ -45,6 +45,9 @@ LevelChunk::~LevelChunk() void LevelChunk::init() { + heightmap = (char*)malloc(LevelConstants::CHUNK_COLUMNS * sizeof(char)); + updateMap = (unsigned char*)malloc(LevelConstants::CHUNK_COLUMNS * sizeof(unsigned char)); + terrainPopulated = false; dontSave = false; unsaved = false; diff --git a/src/world/level/chunk/LevelChunk.h b/src/world/level/chunk/LevelChunk.h index c06819e..0ab8d68 100755 --- a/src/world/level/chunk/LevelChunk.h +++ b/src/world/level/chunk/LevelChunk.h @@ -106,9 +106,9 @@ private: void recalcHeight(int x, int yStart, int z); public: static bool touchedSky; - static const int ChunkBlockCount = CHUNK_BLOCK_COUNT; - static const int ChunkSize = ChunkBlockCount; - static const int UpdateMapBitShift = 4; // power of (LEVEL_HEIGHT / 8) == 16 + const int ChunkBlockCount = LevelConstants::CHUNK_BLOCK_COUNT; + const int ChunkSize = ChunkBlockCount; + static const int UpdateMapBitShift = 4; // power of (LevelConstants::LEVEL_HEIGHT / 8) == 16 int blocksLength; // ? needed or not? (i.e. are all chunks the same size?) @@ -118,8 +118,8 @@ public: DataLayer skyLight; DataLayer blockLight; - char heightmap[CHUNK_COLUMNS]; - unsigned char updateMap[CHUNK_COLUMNS]; // marks regions within block columns that have been modified + char* heightmap; // [LevelConstants::CHUNK_COLUMNS] + unsigned char* updateMap; // marks regions within block columns that have been modified [LevelConstants::CHUNK_COLUMNS] int minHeight; int x, z; diff --git a/src/world/level/levelgen/RandomLevelSource.cpp b/src/world/level/levelgen/RandomLevelSource.cpp index 7ef40e3..da94dd3 100755 --- a/src/world/level/levelgen/RandomLevelSource.cpp +++ b/src/world/level/levelgen/RandomLevelSource.cpp @@ -64,7 +64,7 @@ RandomLevelSource::~RandomLevelSource() { /*public*/ void RandomLevelSource::prepareHeights(int xOffs, int zOffs, unsigned char* blocks, /*Biome*/void* biomes, float* temperatures) { - int xChunks = 16 / CHUNK_WIDTH; + int xChunks = 16 / LevelConstants::CHUNK_WIDTH; int waterHeight = Level::DEPTH - 64; int xSize = xChunks + 1; @@ -87,23 +87,23 @@ void RandomLevelSource::prepareHeights(int xOffs, int zOffs, unsigned char* bloc float s3a = (buffer[((xc + 1) * zSize + (zc + 1)) * ySize + (yc + 1)] - s3) * yStep; for (int y = 0; y < CHUNK_HEIGHT; y++) { - float xStep = 1 / (float) CHUNK_WIDTH; + float xStep = 1 / (float) LevelConstants::CHUNK_WIDTH; float _s0 = s0; float _s1 = s1; float _s0a = (s2 - s0) * xStep; float _s1a = (s3 - s1) * xStep; - for (int x = 0; x < CHUNK_WIDTH; x++) { - int offs = (x + xc * CHUNK_WIDTH) << 11 | (0 + zc * CHUNK_WIDTH) << 7 | (yc * CHUNK_HEIGHT + y); + for (int x = 0; x < LevelConstants::CHUNK_WIDTH; x++) { + int offs = (x + xc * LevelConstants::CHUNK_WIDTH) << 11 | (0 + zc * LevelConstants::CHUNK_WIDTH) << 7 | (yc * CHUNK_HEIGHT + y); int step = 1 << 7; - float zStep = 1 / (float) CHUNK_WIDTH; + float zStep = 1 / (float) LevelConstants::CHUNK_WIDTH; float val = _s0; float vala = (_s1 - _s0) * zStep; - for (int z = 0; z < CHUNK_WIDTH; z++) { -// + (zc * CHUNK_WIDTH + z)]; - float temp = temperatures[(xc * CHUNK_WIDTH + x) * 16 + (zc * CHUNK_WIDTH + z)]; + for (int z = 0; z < LevelConstants::CHUNK_WIDTH; z++) { +// + (zc * LevelConstants::CHUNK_WIDTH + z)]; + float temp = temperatures[(xc * LevelConstants::CHUNK_WIDTH + x) * 16 + (zc * LevelConstants::CHUNK_WIDTH + z)]; int tileId = 0; if (yc * CHUNK_HEIGHT + y < waterHeight) { if (temp < SNOW_CUTOFF && yc * CHUNK_HEIGHT + y >= waterHeight - 1) { diff --git a/src/world/level/storage/ExternalFileLevelStorage.cpp b/src/world/level/storage/ExternalFileLevelStorage.cpp index 03cca08..93ee9f1 100755 --- a/src/world/level/storage/ExternalFileLevelStorage.cpp +++ b/src/world/level/storage/ExternalFileLevelStorage.cpp @@ -343,8 +343,8 @@ bool ExternalFileLevelStorage::readPlayerData(const std::string& filename, Level Vec3& pos = dest.playerData.pos; if (pos.x < 0.5f) pos.x = 0.5f; if (pos.z < 0.5f) pos.z = 0.5f; - if (pos.x > (LEVEL_WIDTH - 0.5f)) pos.x = LEVEL_WIDTH - 0.5f; - if (pos.z > (LEVEL_DEPTH - 0.5f)) pos.z = LEVEL_DEPTH - 0.5f; + if (pos.x > (LevelConstants::LEVEL_WIDTH - 0.5f)) pos.x = LevelConstants::LEVEL_WIDTH - 0.5f; + if (pos.z > (LevelConstants::LEVEL_DEPTH - 0.5f)) pos.z = LevelConstants::LEVEL_DEPTH - 0.5f; if (pos.y < 0) pos.y = 64; dest.playerDataVersion = version; @@ -362,14 +362,14 @@ void ExternalFileLevelStorage::tick() LOGI("Saving level...\n"); // look for chunks that needs to be saved - for (int z = 0; z < CHUNK_CACHE_WIDTH; z++) + for (int z = 0; z < LevelConstants::CHUNK_CACHE_WIDTH; z++) { - for (int x = 0; x < CHUNK_CACHE_WIDTH; x++) + for (int x = 0; x < LevelConstants::CHUNK_CACHE_WIDTH; x++) { LevelChunk* chunk = level->getChunk(x, z); if (chunk && chunk->unsaved) { - int pos = x + z * CHUNK_CACHE_WIDTH; + int pos = x + z * LevelConstants::CHUNK_CACHE_WIDTH; UnsavedChunkList::iterator prev = unsavedChunkList.begin(); for ( ; prev != unsavedChunkList.end(); ++prev) { @@ -415,13 +415,13 @@ void ExternalFileLevelStorage::save(Level* level, LevelChunk* levelChunk) // Write chunk RakNet::BitStream chunkData; - chunkData.Write((const char*)levelChunk->getBlockData(), CHUNK_BLOCK_COUNT); - chunkData.Write((const char*)levelChunk->data.data, CHUNK_BLOCK_COUNT / 2); + chunkData.Write((const char*)levelChunk->getBlockData(), LevelConstants::CHUNK_BLOCK_COUNT); + chunkData.Write((const char*)levelChunk->data.data, LevelConstants::CHUNK_BLOCK_COUNT / 2); - chunkData.Write((const char*)levelChunk->skyLight.data, CHUNK_BLOCK_COUNT / 2); - chunkData.Write((const char*)levelChunk->blockLight.data, CHUNK_BLOCK_COUNT / 2); + chunkData.Write((const char*)levelChunk->skyLight.data, LevelConstants::CHUNK_BLOCK_COUNT / 2); + chunkData.Write((const char*)levelChunk->blockLight.data, LevelConstants::CHUNK_BLOCK_COUNT / 2); - chunkData.Write((const char*)levelChunk->updateMap, CHUNK_COLUMNS); + chunkData.Write((const char*)levelChunk->updateMap, LevelConstants::CHUNK_COLUMNS); regionFile->writeChunk(levelChunk->x, levelChunk->z, chunkData); @@ -453,16 +453,16 @@ LevelChunk* ExternalFileLevelStorage::load(Level* level, int x, int z) chunkData->ResetReadPointer(); - unsigned char* blockIds = new unsigned char[CHUNK_BLOCK_COUNT]; - chunkData->Read((char*)blockIds, CHUNK_BLOCK_COUNT); + unsigned char* blockIds = new unsigned char[LevelConstants::CHUNK_BLOCK_COUNT]; + chunkData->Read((char*)blockIds, LevelConstants::CHUNK_BLOCK_COUNT); LevelChunk* levelChunk = new LevelChunk(level, blockIds, x, z); - chunkData->Read((char*)levelChunk->data.data, CHUNK_BLOCK_COUNT / 2); + chunkData->Read((char*)levelChunk->data.data, LevelConstants::CHUNK_BLOCK_COUNT / 2); if (loadedStorageVersion >= ChunkVersion_Light) { - chunkData->Read((char*)levelChunk->skyLight.data, CHUNK_BLOCK_COUNT / 2); - chunkData->Read((char*)levelChunk->blockLight.data, CHUNK_BLOCK_COUNT / 2); + chunkData->Read((char*)levelChunk->skyLight.data, LevelConstants::CHUNK_BLOCK_COUNT / 2); + chunkData->Read((char*)levelChunk->blockLight.data, LevelConstants::CHUNK_BLOCK_COUNT / 2); } - chunkData->Read((char*)levelChunk->updateMap, CHUNK_COLUMNS); + chunkData->Read((char*)levelChunk->updateMap, LevelConstants::CHUNK_COLUMNS); // This will be difficult to maintain.. Storage version could be per chunk // too (but probably better to just read all -> write all, so that all // chunks got same version anyway) @@ -485,7 +485,7 @@ LevelChunk* ExternalFileLevelStorage::load(Level* level, int x, int z) //bool dbg = (x == 7 && z == 9); //int t = 0; - //for (int i = 0; i < CHUNK_COLUMNS; ++i) { + //for (int i = 0; i < LevelConstants::CHUNK_COLUMNS; ++i) { // char bits = levelChunk->updateMap[i]; // t += (bits != 0); // int xx = x * 16 + i%16; diff --git a/src/world/level/tile/Mushroom.cpp b/src/world/level/tile/Mushroom.cpp index 6de05ce..2992405 100755 --- a/src/world/level/tile/Mushroom.cpp +++ b/src/world/level/tile/Mushroom.cpp @@ -47,7 +47,7 @@ bool Mushroom::mayPlaceOn( int tile ) { } bool Mushroom::canSurvive( Level* level, int x, int y, int z ) { - if (y < 0 || y >= LEVEL_HEIGHT/*Level::maxBuildHeight*/) + if (y < 0 || y >= LevelConstants::LEVEL_HEIGHT/*Level::maxBuildHeight*/) return false; int below = level->getTile(x, y - 1, z); diff --git a/src/world/level/tile/NetherReactor.cpp b/src/world/level/tile/NetherReactor.cpp index 04404eb..00849b9 100755 --- a/src/world/level/tile/NetherReactor.cpp +++ b/src/world/level/tile/NetherReactor.cpp @@ -53,7 +53,7 @@ bool NetherReactor::canSpawnStartNetherReactor( Level* level, int x, int y, int if(!allPlayersCloseToReactor(level, x, y, z)) { player->displayClientMessage("All players need to be close to the reactor."); return false; - } else if(y > LEVEL_HEIGHT - 28) { + } else if(y > LevelConstants::LEVEL_HEIGHT - 28) { player->displayClientMessage("The nether reactor needs to be built lower down."); return false; } else if(y < 2) { diff --git a/src/world/level/tile/entity/NetherReactorTileEntity.cpp b/src/world/level/tile/entity/NetherReactorTileEntity.cpp index f55c12d..5b4728a 100755 --- a/src/world/level/tile/entity/NetherReactorTileEntity.cpp +++ b/src/world/level/tile/entity/NetherReactorTileEntity.cpp @@ -130,7 +130,7 @@ Vec3 NetherReactorTileEntity::getSpawnPosition( float minDistance, float varible void NetherReactorTileEntity::spawnEnemy() { Mob* mob = MobFactory::CreateMob(MobTypes::PigZombie, level); Vec3 enemyPosition = getSpawnPosition(3, 4, -1); - while(enemyPosition.x < 0 || enemyPosition.z < 0 || enemyPosition.x >= LEVEL_WIDTH || enemyPosition.z >= LEVEL_DEPTH) { + while(enemyPosition.x < 0 || enemyPosition.z < 0 || enemyPosition.x >= LevelConstants::LEVEL_WIDTH || enemyPosition.z >= LevelConstants::LEVEL_DEPTH) { enemyPosition = getSpawnPosition(3, 4, -1); } MobSpawner::addMob(level, mob, enemyPosition.x, enemyPosition.y, enemyPosition.z, 0, 0, true); @@ -140,7 +140,7 @@ void NetherReactorTileEntity::spawnEnemy() { void NetherReactorTileEntity::spawnItem() { Vec3 itemPosition= getSpawnPosition(3, 4, -1); - while(itemPosition.x < 0 || itemPosition.z < 0 || itemPosition.x >= LEVEL_WIDTH || itemPosition.z >= LEVEL_DEPTH) { + while(itemPosition.x < 0 || itemPosition.z < 0 || itemPosition.x >= LevelConstants::LEVEL_WIDTH || itemPosition.z >= LevelConstants::LEVEL_DEPTH) { itemPosition = getSpawnPosition(3, 4, -1); } ItemEntity* item = new ItemEntity(level, itemPosition.x, itemPosition.y, itemPosition.z, getSpawnItem()); From 3e48c7fabd69ddd098b719d4726678e7ad67fedf Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Sat, 2 May 2026 21:31:48 +0300 Subject: [PATCH 32/59] FIX: compilation --- src/network/ClientSideNetworkHandler.cpp | 7 ++++-- src/world/level/Level.cpp | 3 +++ src/world/level/Level.h | 4 ++-- src/world/level/LevelConstants.cpp | 3 +++ src/world/level/LevelConstants.h | 2 +- src/world/level/chunk/ChunkCache.h | 30 ++++++++++++------------ src/world/level/chunk/LevelChunk.cpp | 5 ++-- src/world/level/chunk/LevelChunk.h | 2 +- 8 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index c1515f7..f988fdd 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -560,8 +560,8 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChunkDat int rx = packet->x << 4; int rz = packet->z << 4; - unsigned char readBlockBuffer[setSize]; - unsigned char readDataBuffer[setSize / 2]; + unsigned char* readBlockBuffer = new unsigned char[setSize]; + unsigned char* readDataBuffer = new unsigned char[setSize / 2]; for (int i = 0; i < LevelConstants::CHUNK_COLUMNS; i++) { @@ -631,6 +631,9 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChunkDat } } + delete[] readBlockBuffer; + delete[] readDataBuffer; + if (recalcHeight) { // chunk->recalcHeightmap(); diff --git a/src/world/level/Level.cpp b/src/world/level/Level.cpp index 35fbd7e..cb6d688 100755 --- a/src/world/level/Level.cpp +++ b/src/world/level/Level.cpp @@ -29,6 +29,9 @@ #include "../Difficulty.h" #include "../../network/packet/ExplodePacket.h" +const int Level::DEPTH = LevelConstants::LEVEL_HEIGHT; +const int Level::SEA_LEVEL = Level::DEPTH / 2 - 1; + Level::Level(LevelStorage* levelStorage, const std::string& levelName, const LevelSettings& settings, int generatorVersion, Dimension* fixedDimension /* = NULL */) : levelStorage(levelStorage), isClientSide(false), diff --git a/src/world/level/Level.h b/src/world/level/Level.h index 082cb07..edf1747 100755 --- a/src/world/level/Level.h +++ b/src/world/level/Level.h @@ -67,8 +67,8 @@ class Level: public LevelSource public: static const int MAX_LEVEL_SIZE = 32000000; - const short DEPTH = LevelConstants::LEVEL_HEIGHT; - const short SEA_LEVEL = DEPTH / 2 - 1; + static const int DEPTH; + static const int SEA_LEVEL; static const int MAX_BRIGHTNESS = 15; static const int TICKS_PER_DAY = SharedConstants::TicksPerSecond * 60 * 16;// SharedConstants::TicksPerSecond * 60 * 12; // ORG:20*60*20 diff --git a/src/world/level/LevelConstants.cpp b/src/world/level/LevelConstants.cpp index 864ce32..6a36246 100644 --- a/src/world/level/LevelConstants.cpp +++ b/src/world/level/LevelConstants.cpp @@ -1,7 +1,10 @@ #include "LevelConstants.h" int LevelConstants::LEVEL_HEIGHT = 128; +int LevelConstants::CHUNK_CACHE_WIDTH = 16; // in chunks int LevelConstants::CHUNK_WIDTH = 16; // in blocks int LevelConstants::CHUNK_DEPTH = 16; +int LevelConstants::LEVEL_WIDTH = LevelConstants::CHUNK_CACHE_WIDTH * CHUNK_WIDTH; +int LevelConstants::LEVEL_DEPTH = LevelConstants::CHUNK_CACHE_WIDTH * CHUNK_DEPTH; int LevelConstants::CHUNK_COLUMNS = LevelConstants::CHUNK_WIDTH * LevelConstants::CHUNK_DEPTH; int LevelConstants::CHUNK_BLOCK_COUNT = LevelConstants::CHUNK_COLUMNS * LevelConstants::LEVEL_HEIGHT; \ No newline at end of file diff --git a/src/world/level/LevelConstants.h b/src/world/level/LevelConstants.h index 0b00053..ed77861 100755 --- a/src/world/level/LevelConstants.h +++ b/src/world/level/LevelConstants.h @@ -5,8 +5,8 @@ public: static int CHUNK_CACHE_WIDTH; // in chunks static int LEVEL_WIDTH; static int LEVEL_DEPTH; - static int LEVEL_HEIGHT; + static int CHUNK_WIDTH; // in blocks static int CHUNK_DEPTH; static int CHUNK_COLUMNS; diff --git a/src/world/level/chunk/ChunkCache.h b/src/world/level/chunk/ChunkCache.h index 13f81e9..ee5fc49 100755 --- a/src/world/level/chunk/ChunkCache.h +++ b/src/world/level/chunk/ChunkCache.h @@ -25,7 +25,7 @@ public: //emptyChunk = new EmptyLevelChunk(level_, emptyChunkBlocks, 0, 0); emptyChunk = new EmptyLevelChunk(level_, NULL, 0, 0); - chunks = (LevelChunk *)malloc(LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH); + chunks = new LevelChunk *[LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH]; } ~ChunkCache() { @@ -36,8 +36,8 @@ public: { if (&chunks[i]) { - chunks[i].deleteBlockData(); - delete &chunks[i]; + chunks[i]->deleteBlockData(); + delete chunks[i]; } } } @@ -56,7 +56,7 @@ public: int xs = x & (LevelConstants::CHUNK_CACHE_WIDTH - 1); int zs = z & (LevelConstants::CHUNK_CACHE_WIDTH - 1); int slot = xs + zs * LevelConstants::CHUNK_CACHE_WIDTH; - return &chunks[slot] != NULL && (&chunks[slot] == emptyChunk || chunks[slot].isAt(x, z)); + return chunks[slot] != NULL && (chunks[slot] == emptyChunk || chunks[slot]->isAt(x, z)); } LevelChunk* create(int x, int z) { @@ -76,10 +76,10 @@ public: int zs = z & (LevelConstants::CHUNK_CACHE_WIDTH - 1); int slot = xs + zs * LevelConstants::CHUNK_CACHE_WIDTH; if (!hasChunk(x, z)) { - if (&chunks[slot] != NULL) { - chunks[slot].unload(); - save(&chunks[slot]); - saveEntities(&chunks[slot]); + if (chunks[slot] != NULL) { + chunks[slot]->unload(); + save(chunks[slot]); + saveEntities(chunks[slot]); } LevelChunk* newChunk = load(x, z); @@ -94,7 +94,7 @@ public: //return emptyChunk; updateLights = true; } - chunks[slot] = *newChunk; + chunks[slot] = newChunk; newChunk->lightLava(); if (updateLights) @@ -115,23 +115,23 @@ public: //level->updateLight(LightLayer::Block, x * 16, 0, z * 16, x * 16 + 15, 128, z * 16 + 15); } - if (&chunks[slot] != NULL) { - chunks[slot].load(); + if (chunks[slot] != NULL) { + chunks[slot]->load(); } - if (!chunks[slot].terrainPopulated && hasChunk(x + 1, z + 1) && hasChunk(x, z + 1) && hasChunk(x + 1, z)) postProcess(this, x, z); + if (!chunks[slot]->terrainPopulated && hasChunk(x + 1, z + 1) && hasChunk(x, z + 1) && hasChunk(x + 1, z)) postProcess(this, x, z); if (hasChunk(x - 1, z) && !getChunk(x - 1, z)->terrainPopulated && hasChunk(x - 1, z + 1) && hasChunk(x, z + 1) && hasChunk(x - 1, z)) postProcess(this, x - 1, z); if (hasChunk(x, z - 1) && !getChunk(x, z - 1)->terrainPopulated && hasChunk(x + 1, z - 1) && hasChunk(x, z - 1) && hasChunk(x + 1, z)) postProcess(this, x, z - 1); if (hasChunk(x - 1, z - 1) && !getChunk(x - 1, z - 1)->terrainPopulated && hasChunk(x - 1, z - 1) && hasChunk(x, z - 1) && hasChunk(x - 1, z)) postProcess(this, x - 1, z - 1); } xLast = x; zLast = z; - last = &chunks[slot]; + last = chunks[slot]; //sw.stop(); //sw.printEvery(500000, "ChunkCache::load: "); - return &chunks[slot]; + return chunks[slot]; } Biome::MobList getMobsAt(const MobCategory& mobCategory, int x, int y, int z) { @@ -255,7 +255,7 @@ private: LevelChunk* emptyChunk; ChunkSource* source; ChunkStorage* storage; - LevelChunk* chunks; + LevelChunk** chunks; Level* level; LevelChunk* last; diff --git a/src/world/level/chunk/LevelChunk.cpp b/src/world/level/chunk/LevelChunk.cpp index 2710f21..5cf3ae6 100755 --- a/src/world/level/chunk/LevelChunk.cpp +++ b/src/world/level/chunk/LevelChunk.cpp @@ -12,6 +12,7 @@ /*static*/ bool LevelChunk::touchedSky = false; +const int LevelChunk::ChunkBlockCount = LevelConstants::CHUNK_BLOCK_COUNT; LevelChunk::LevelChunk( Level* level, int x, int z ) : level(level), @@ -45,8 +46,8 @@ LevelChunk::~LevelChunk() void LevelChunk::init() { - heightmap = (char*)malloc(LevelConstants::CHUNK_COLUMNS * sizeof(char)); - updateMap = (unsigned char*)malloc(LevelConstants::CHUNK_COLUMNS * sizeof(unsigned char)); + heightmap = new char[LevelConstants::CHUNK_COLUMNS]; + updateMap = new unsigned char[LevelConstants::CHUNK_COLUMNS]; terrainPopulated = false; dontSave = false; diff --git a/src/world/level/chunk/LevelChunk.h b/src/world/level/chunk/LevelChunk.h index 0ab8d68..b88cb7a 100755 --- a/src/world/level/chunk/LevelChunk.h +++ b/src/world/level/chunk/LevelChunk.h @@ -106,7 +106,7 @@ private: void recalcHeight(int x, int yStart, int z); public: static bool touchedSky; - const int ChunkBlockCount = LevelConstants::CHUNK_BLOCK_COUNT; + static const int ChunkBlockCount; const int ChunkSize = ChunkBlockCount; static const int UpdateMapBitShift = 4; // power of (LevelConstants::LEVEL_HEIGHT / 8) == 16 From 18793a6e052214c1bd1b480a19841ad53ffed9de Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Tue, 5 May 2026 20:40:41 +0200 Subject: [PATCH 33/59] idk? --- src/main_dedicated.cpp | 1 + src/network/ClientSideNetworkHandler.cpp | 2 +- src/network/ServerSideNetworkHandler.cpp | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main_dedicated.cpp b/src/main_dedicated.cpp index 9c0e812..37ce2d0 100755 --- a/src/main_dedicated.cpp +++ b/src/main_dedicated.cpp @@ -76,6 +76,7 @@ int main(int numArguments, char* pszArgs[]) { //pthread_yield(); sleepMs(20); } + ((MAIN_CLASS*)g_app)->level->saveLevelData(); delete app; appContext.platform->finish(); diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index f988fdd..9c3a6b5 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -163,7 +163,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, StartGam // @todo @note i think its trash // we can put it directly to selectLevel? if (packet->chunkCacheWidth != 0) { - printf("lol \n"); + printf("lol \n"); LevelConstants::CHUNK_CACHE_WIDTH = packet->chunkCacheWidth; LevelConstants::LEVEL_WIDTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_WIDTH; LevelConstants::LEVEL_DEPTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_DEPTH; diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index e7e10fb..b184d8b 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -74,11 +74,11 @@ void ServerSideNetworkHandler::tileChanged(int x, int y, int z) Packet* ServerSideNetworkHandler::getAddPacketFromEntity( Entity* entity ) { if (entity->isMob() && !entity->isPlayer()) { //@fix: This code is duplicated. See if it can be unified. - if (minecraft->player) { + // 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()) { From 26b2c196fa8dd40eb0f664f58760934717f7856b Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Tue, 5 May 2026 21:09:42 +0200 Subject: [PATCH 34/59] :\ --- project/android_java/jni/Android.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/project/android_java/jni/Android.mk b/project/android_java/jni/Android.mk index 04720a6..db61279 100755 --- a/project/android_java/jni/Android.mk +++ b/project/android_java/jni/Android.mk @@ -228,6 +228,7 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \ ../../../src/world/level/tile/entity/TileEntity.cpp \ ../../../src/world/level/tile/entity/FurnaceTileEntity.cpp \ ../../../src/world/phys/HitResult.cpp +../../../src/world/level/LevelConstants.cpp LOCAL_CFLAGS := -Wno-psabi $(LOCAL_CFLAGS) From 2465292473878f344e829531a314a85d42610de3 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Tue, 5 May 2026 21:14:17 +0200 Subject: [PATCH 35/59] jopa --- project/android/jni/Android.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/project/android/jni/Android.mk b/project/android/jni/Android.mk index 9bff609..60db5e8 100755 --- a/project/android/jni/Android.mk +++ b/project/android/jni/Android.mk @@ -109,6 +109,7 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \ ../../../src/client/renderer/Textures.cpp \ ../../../src/client/renderer/TileRenderer.cpp \ ../../../src/client/renderer/gles.cpp \ +../../../src/world/level/LevelConstants.cpp \ ../../../src/client/renderer/culling/Frustum.cpp \ ../../../src/client/renderer/entity/ArrowRenderer.cpp \ ../../../src/client/renderer/entity/ChickenRenderer.cpp \ From 7e9de7a461f073131b5add7787c9225cc9836e30 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Tue, 5 May 2026 21:19:08 +0200 Subject: [PATCH 36/59] fck android build!!! --- project/android/jni/Android.mk | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/project/android/jni/Android.mk b/project/android/jni/Android.mk index 60db5e8..24d0dfb 100755 --- a/project/android/jni/Android.mk +++ b/project/android/jni/Android.mk @@ -135,6 +135,13 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \ ../../../src/locale/I18n.cpp \ ../../../src/nbt/Tag.cpp \ ../../../src/network/command/CommandServer.cpp \ +../../../src/network/command/CommandServer.cpp \ +../../../src/commands/Command.cpp \ +../../../src/commands/CommandHelp.cpp \ +../../../src/commands/CommandKick.cpp \ +../../../src/commands/CommandManager.cpp \ +../../../src/commands/CommandOp.cpp \ +../../../src/network/command/CommandServer.cpp \ ../../../src/network/ClientSideNetworkHandler.cpp \ ../../../src/network/NetEventCallback.cpp \ ../../../src/network/Packet.cpp \ From 30dd3442081091aa88fe38f9298d4d9508133ec5 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Tue, 5 May 2026 21:33:28 +0200 Subject: [PATCH 37/59] 123 --- project/android/jni/Android.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/android/jni/Android.mk b/project/android/jni/Android.mk index 24d0dfb..4093feb 100755 --- a/project/android/jni/Android.mk +++ b/project/android/jni/Android.mk @@ -134,14 +134,14 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \ ../../../src/client/sound/SoundEngine.cpp \ ../../../src/locale/I18n.cpp \ ../../../src/nbt/Tag.cpp \ -../../../src/network/command/CommandServer.cpp \ -../../../src/network/command/CommandServer.cpp \ ../../../src/commands/Command.cpp \ ../../../src/commands/CommandHelp.cpp \ ../../../src/commands/CommandKick.cpp \ ../../../src/commands/CommandManager.cpp \ ../../../src/commands/CommandOp.cpp \ ../../../src/network/command/CommandServer.cpp \ +../../../src/network/command/CommandServer.cpp \ +../../../src/network/command/CommandServer.cpp \ ../../../src/network/ClientSideNetworkHandler.cpp \ ../../../src/network/NetEventCallback.cpp \ ../../../src/network/Packet.cpp \ From 4047fd71e1cc7cae37b8c9fe5e7bf8e2fecab0b7 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Tue, 5 May 2026 21:36:35 +0200 Subject: [PATCH 38/59] oi --- project/android/jni/Android.mk | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/project/android/jni/Android.mk b/project/android/jni/Android.mk index 4093feb..632c137 100755 --- a/project/android/jni/Android.mk +++ b/project/android/jni/Android.mk @@ -134,19 +134,17 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \ ../../../src/client/sound/SoundEngine.cpp \ ../../../src/locale/I18n.cpp \ ../../../src/nbt/Tag.cpp \ -../../../src/commands/Command.cpp \ -../../../src/commands/CommandHelp.cpp \ -../../../src/commands/CommandKick.cpp \ -../../../src/commands/CommandManager.cpp \ -../../../src/commands/CommandOp.cpp \ -../../../src/network/command/CommandServer.cpp \ -../../../src/network/command/CommandServer.cpp \ ../../../src/network/command/CommandServer.cpp \ ../../../src/network/ClientSideNetworkHandler.cpp \ ../../../src/network/NetEventCallback.cpp \ ../../../src/network/Packet.cpp \ ../../../src/network/RakNetInstance.cpp \ ../../../src/network/ServerSideNetworkHandler.cpp \ +../../../src/commands/Command.cpp \ +../../../src/commands/CommandHelp.cpp \ +../../../src/commands/CommandKick.cpp \ +../../../src/commands/CommandManager.cpp \ +../../../src/commands/CommandOp.cpp \ ../../../src/server/ServerLevel.cpp \ ../../../src/server/ServerPlayer.cpp \ ../../../src/util/DataIO.cpp \ From 27b22d81081b87f179cd1af0ba3630e858373767 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Tue, 5 May 2026 21:41:26 +0200 Subject: [PATCH 39/59] vegetables --- src/commands/CommandKick.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/CommandKick.cpp b/src/commands/CommandKick.cpp index 2dad690..c05a1f9 100644 --- a/src/commands/CommandKick.cpp +++ b/src/commands/CommandKick.cpp @@ -1,11 +1,11 @@ #include "CommandKick.hpp" +#include "RakPeerInterface.h" #include "commands/Command.hpp" #include "network/RakNetInstance.h" -#include "raknet/RakPeer.h" #include "world/level/Level.h" #include #include - +// RakNet::RakPeerInterface CommandKick::CommandKick() : Command("kick") {} From 830549791a4c0b1970e36ec7dcdcd9e1f19f52c9 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Tue, 5 May 2026 21:51:35 +0200 Subject: [PATCH 40/59] 121 --- src/commands/CommandKick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/CommandKick.cpp b/src/commands/CommandKick.cpp index c05a1f9..df8c113 100644 --- a/src/commands/CommandKick.cpp +++ b/src/commands/CommandKick.cpp @@ -1,7 +1,7 @@ #include "CommandKick.hpp" -#include "RakPeerInterface.h" #include "commands/Command.hpp" #include "network/RakNetInstance.h" +#include "raknet/RakPeerInterface.h" #include "world/level/Level.h" #include #include From 70308d415157947ed00e5260e285748047856d99 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Tue, 5 May 2026 21:55:03 +0200 Subject: [PATCH 41/59] qqqqqq --- src/commands/CommandManager.cpp | 2 -- src/commands/CommandOp.cpp | 3 --- 2 files changed, 5 deletions(-) diff --git a/src/commands/CommandManager.cpp b/src/commands/CommandManager.cpp index f92f380..9087c42 100644 --- a/src/commands/CommandManager.cpp +++ b/src/commands/CommandManager.cpp @@ -11,8 +11,6 @@ #include "network/RakNetInstance.h" #include "world/level/Level.h" - - CommandManager::CommandManager() { registerAllCommands(); } diff --git a/src/commands/CommandOp.cpp b/src/commands/CommandOp.cpp index df28db5..e50e130 100644 --- a/src/commands/CommandOp.cpp +++ b/src/commands/CommandOp.cpp @@ -1,12 +1,9 @@ #include "CommandOp.hpp" #include "commands/Command.hpp" -#include "network/RakNetInstance.h" -#include "raknet/RakPeer.h" #include "world/level/Level.h" #include #include - CommandOp::CommandOp() : Command("op") {} std::string CommandOp::execute(Minecraft& mc, Player& player, const std::vector& args) { From 43f0d1f75ff5e82fa11457234248374dffce36c6 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Fri, 8 May 2026 23:42:41 +0200 Subject: [PATCH 42/59] server config --- src/main_dedicated.cpp | 151 +++++++++++++++++++++++++++++++++++------ 1 file changed, 129 insertions(+), 22 deletions(-) diff --git a/src/main_dedicated.cpp b/src/main_dedicated.cpp index 37ce2d0..05cab6a 100755 --- a/src/main_dedicated.cpp +++ b/src/main_dedicated.cpp @@ -1,3 +1,4 @@ +#include #include #include "NinecraftApp.h" #include "AppPlatform.h" @@ -27,45 +28,151 @@ void signal_callback_handler(int signum) { } } +std::string findStringInConfig(std::string line, std::string config) { + auto valuePos = config.find(line); + + if (line.empty()) { + throw std::runtime_error("Key cannot be empty"); + } + + if (valuePos == std::string::npos) { + throw std::runtime_error("Cannot find value"); + } + + std::string valueStr = ""; + + valuePos += 1 + line.size(); + + + while (true) { + auto sym = config.at(valuePos); + + if (sym == '\n') { + break; + } + + if (valuePos == config.size()) { + throw std::runtime_error("Cannot end line"); + } + + valueStr += sym; + valuePos++; + } + + return valueStr; +} + + int main(int numArguments, char* pszArgs[]) { ArgumentsSettings aSettings(numArguments, pszArgs); - if(aSettings.getShowHelp()) { - // TODO: Map with args and print it with std::cout and for loop - // TODO: World size setting + // if(aSettings.getShowHelp()) { + // // TODO: Map with args and print it with std::cout and for loop + // // TODO: World size setting - ArgumentsSettings defaultSettings(0, NULL); + // ArgumentsSettings defaultSettings(0, NULL); - printf("Minecraft Pockect Edition Server %s\n", Common::getGameVersionString("").c_str()); - printf("-------------------------------------------------------\n"); + // printf("Minecraft Pockect Edition Server %s\n", Common::getGameVersionString("").c_str()); + // printf("-------------------------------------------------------\n"); - printf("--cachepath - Path to where the server can store temp stuff (not sure if this is used) [default: \"%s\"]\n", defaultSettings.getCachePath().c_str()); - printf("--externalpath - The path to the place where the server should store the levels. [default: \"%s\"]\n", defaultSettings.getExternalPath().c_str()); - printf("--levelname - The name of the server [default: \"%s\"]\n", defaultSettings.getLevelName().c_str()); - printf("--gamemode - The name of the gamemode [default: \"%s\"]\n", defaultSettings.getGamemode().c_str()); - printf("--leveldir - The name of the server [default: \"%s\"]\n", defaultSettings.getLevelDir().c_str()); - printf("--help - Shows this message.\n"); - printf("--port - The port to run the server on. [default: %d]\n", defaultSettings.getPort()); - printf("--serverkey - The key that the server should use for API calls. [default: \"%s\"]\n", defaultSettings.getServerKey().c_str()); + // printf("--cachepath - Path to where the server can store temp stuff (not sure if this is used) [default: \"%s\"]\n", defaultSettings.getCachePath().c_str()); + // printf("--externalpath - The path to the place where the server should store the levels. [default: \"%s\"]\n", defaultSettings.getExternalPath().c_str()); + // printf("--levelname - The name of the server [default: \"%s\"]\n", defaultSettings.getLevelName().c_str()); + // printf("--gamemode - The name of the gamemode [default: \"%s\"]\n", defaultSettings.getGamemode().c_str()); + // printf("--leveldir - The name of the server [default: \"%s\"]\n", defaultSettings.getLevelDir().c_str()); + // printf("--help - Shows this message.\n"); + // printf("--port - The port to run the server on. [default: %d]\n", defaultSettings.getPort()); + // printf("--serverkey - The key that the server should use for API calls. [default: \"%s\"]\n", defaultSettings.getServerKey().c_str()); - printf("-------------------------------------------------------\n"); + // printf("-------------------------------------------------------\n"); - return 0; + // return 0; + // } + + std::ifstream serverProperties("server.properties"); + + int port = 0; + int gamemode = 0; + + std::string levelDir = ""; + std::string cachePath = ""; + std::string externalPath = ""; + std::string levelName = ""; + + if (serverProperties.is_open()) { + std::string propString; + std::string line; + + while (std::getline(serverProperties, line)) { + propString += line; + propString += "\n"; + } + + if (propString.empty()) { + throw std::runtime_error("Config cannot be empty"); + } + + port = std::stoi(findStringInConfig("port", propString)); + cachePath = findStringInConfig("level-cachepath", propString); + externalPath = findStringInConfig("level-externalpath", propString); + levelName = findStringInConfig("level-name", propString); + levelDir = findStringInConfig("level-dir", propString); + + std::string gamemodeStr = findStringInConfig("gamemode", propString); + + if (gamemodeStr == "survival") { + gamemode = GameType::Survival; + } else if (gamemodeStr == "creative") { + gamemode = GameType::Creative; + } else { + gamemode = GameType::Survival; + } + + printf("%d %s %s %d \n", port, cachePath.c_str(), externalPath.c_str(), gamemode); + } else { + std::ofstream defaultProperties("server.properties"); + + if (defaultProperties.is_open()) { + ArgumentsSettings defaultSettings(0, NULL); + + std::stringstream buffer; + + buffer << "// MCPE Server properties" << std::endl; + buffer << "port=" << defaultSettings.getPort() << std::endl; + buffer << "level-dir=" << defaultSettings.getLevelDir() << std::endl; + buffer << "level-cachepath=" << defaultSettings.getCachePath() << std::endl; + buffer << "level-externalpath=" << defaultSettings.getExternalPath() << std::endl; + buffer << "gamemode=survival" << std::endl; + buffer << "level-name=" << defaultSettings.getLevelName() << std::endl; + buffer << "world-size=16" << std::endl; + + defaultProperties << buffer.str(); + + printf("%s \n", buffer.str().c_str()); + + printf("Edit a config file first!"); + + defaultProperties.close(); + exit(0); + } else { + throw std::runtime_error("Cannot create default config."); + } } - printf("Level Name: %s\n", aSettings.getLevelName().c_str()); + + printf("Level Name: %s\n", levelName.c_str()); AppContext appContext; appContext.platform = new AppPlatform(); App* app = new MAIN_CLASS(); signal(SIGINT, signal_callback_handler); g_app = app; - ((MAIN_CLASS*)g_app)->externalStoragePath = aSettings.getExternalPath(); - ((MAIN_CLASS*)g_app)->externalCacheStoragePath = aSettings.getCachePath(); + ((MAIN_CLASS*)g_app)->externalStoragePath = externalPath; + ((MAIN_CLASS*)g_app)->externalCacheStoragePath = cachePath; g_app->init(appContext); - LevelSettings settings(getEpochTimeS(), GameType::Creative); + LevelSettings settings(getEpochTimeS(), gamemode); float startTime = getTimeS(); - ((MAIN_CLASS*)g_app)->selectLevel(aSettings.getLevelDir(), aSettings.getLevelName(), settings); - ((MAIN_CLASS*)g_app)->hostMultiplayer(aSettings.getPort()); + ((MAIN_CLASS*)g_app)->selectLevel(levelDir, levelName, settings); + ((MAIN_CLASS*)g_app)->hostMultiplayer(port); std::cout << "Level has been generated in " << getTimeS() - startTime << std::endl; ((MAIN_CLASS*)g_app)->level->saveLevelData(); From 1d0264a9c507c0ea14a5cad991f2defad63f714e Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Sat, 9 May 2026 01:45:19 +0200 Subject: [PATCH 43/59] FEAT: World size --- src/main_dedicated.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main_dedicated.cpp b/src/main_dedicated.cpp index 05cab6a..f1a0921 100755 --- a/src/main_dedicated.cpp +++ b/src/main_dedicated.cpp @@ -12,6 +12,7 @@ #include "server/ArgumentsSettings.h" #include "platform/time.h" #include "SharedConstants.h" +#include "world/level/LevelConstants.h" #define MAIN_CLASS NinecraftApp static App* g_app = 0; @@ -40,9 +41,8 @@ std::string findStringInConfig(std::string line, std::string config) { } std::string valueStr = ""; - - valuePos += 1 + line.size(); + valuePos += 1 + line.size(); while (true) { auto sym = config.at(valuePos); @@ -92,6 +92,7 @@ int main(int numArguments, char* pszArgs[]) { int port = 0; int gamemode = 0; + int worldSize = 0; std::string levelDir = ""; std::string cachePath = ""; @@ -112,6 +113,16 @@ int main(int numArguments, char* pszArgs[]) { } port = std::stoi(findStringInConfig("port", propString)); + worldSize = std::stoi(findStringInConfig("world-size", propString)); + + if (worldSize < 16 || worldSize > 32) { + throw std::runtime_error("Incorrect world size."); + } + + LevelConstants::CHUNK_CACHE_WIDTH = worldSize; + LevelConstants::LEVEL_WIDTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_WIDTH; + LevelConstants::LEVEL_DEPTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_DEPTH; + cachePath = findStringInConfig("level-cachepath", propString); externalPath = findStringInConfig("level-externalpath", propString); levelName = findStringInConfig("level-name", propString); @@ -144,7 +155,7 @@ int main(int numArguments, char* pszArgs[]) { buffer << "gamemode=survival" << std::endl; buffer << "level-name=" << defaultSettings.getLevelName() << std::endl; buffer << "world-size=16" << std::endl; - + defaultProperties << buffer.str(); printf("%s \n", buffer.str().c_str()); From 263118f2e058a87186fba3e992fbb995115aa8b6 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Sat, 9 May 2026 13:09:45 +0200 Subject: [PATCH 44/59] Fix --- src/client/Minecraft.cpp | 3 --- src/main_dedicated.cpp | 32 +++--------------------- src/network/ClientSideNetworkHandler.cpp | 3 +++ 3 files changed, 7 insertions(+), 31 deletions(-) diff --git a/src/client/Minecraft.cpp b/src/client/Minecraft.cpp index 6698c3d..d428879 100755 --- a/src/client/Minecraft.cpp +++ b/src/client/Minecraft.cpp @@ -1322,12 +1322,9 @@ bool Minecraft::joinMultiplayerFromString( const std::string& server ) } else { ip = server; } - - printf("%s \n", port.c_str()); if (isLookingForMultiplayer && netCallback) { isLookingForMultiplayer = false; - printf("test"); int portNum = atoi(port.c_str()); return raknetInstance->connect(ip.c_str(), portNum); } diff --git a/src/main_dedicated.cpp b/src/main_dedicated.cpp index f1a0921..2c429ed 100755 --- a/src/main_dedicated.cpp +++ b/src/main_dedicated.cpp @@ -52,7 +52,7 @@ std::string findStringInConfig(std::string line, std::string config) { } if (valuePos == config.size()) { - throw std::runtime_error("Cannot end line"); + throw std::runtime_error("Cannot find end of the line"); } valueStr += sym; @@ -63,31 +63,7 @@ std::string findStringInConfig(std::string line, std::string config) { } -int main(int numArguments, char* pszArgs[]) { - ArgumentsSettings aSettings(numArguments, pszArgs); - // if(aSettings.getShowHelp()) { - // // TODO: Map with args and print it with std::cout and for loop - // // TODO: World size setting - - // ArgumentsSettings defaultSettings(0, NULL); - - // printf("Minecraft Pockect Edition Server %s\n", Common::getGameVersionString("").c_str()); - // printf("-------------------------------------------------------\n"); - - // printf("--cachepath - Path to where the server can store temp stuff (not sure if this is used) [default: \"%s\"]\n", defaultSettings.getCachePath().c_str()); - // printf("--externalpath - The path to the place where the server should store the levels. [default: \"%s\"]\n", defaultSettings.getExternalPath().c_str()); - // printf("--levelname - The name of the server [default: \"%s\"]\n", defaultSettings.getLevelName().c_str()); - // printf("--gamemode - The name of the gamemode [default: \"%s\"]\n", defaultSettings.getGamemode().c_str()); - // printf("--leveldir - The name of the server [default: \"%s\"]\n", defaultSettings.getLevelDir().c_str()); - // printf("--help - Shows this message.\n"); - // printf("--port - The port to run the server on. [default: %d]\n", defaultSettings.getPort()); - // printf("--serverkey - The key that the server should use for API calls. [default: \"%s\"]\n", defaultSettings.getServerKey().c_str()); - - // printf("-------------------------------------------------------\n"); - - // return 0; - // } - +int main(int numArguments, char* pszArgs[]) { std::ifstream serverProperties("server.properties"); int port = 0; @@ -138,7 +114,7 @@ int main(int numArguments, char* pszArgs[]) { gamemode = GameType::Survival; } - printf("%d %s %s %d \n", port, cachePath.c_str(), externalPath.c_str(), gamemode); + printf("%d %s %s %d %d\n", port, cachePath.c_str(), externalPath.c_str(), gamemode, LevelConstants::CHUNK_CACHE_WIDTH); } else { std::ofstream defaultProperties("server.properties"); @@ -160,7 +136,7 @@ int main(int numArguments, char* pszArgs[]) { printf("%s \n", buffer.str().c_str()); - printf("Edit a config file first!"); + printf("Edit a config file first!\n"); defaultProperties.close(); exit(0); diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index 9c3a6b5..e5db2b7 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -45,6 +45,9 @@ ClientSideNetworkHandler::ClientSideNetworkHandler(Minecraft* minecraft, IRakNet requestNextChunkPosition(0), requestNextChunkIndex(0) { + NumRequestChunks = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH; + requestNextChunkIndexList.resize(NumRequestChunks); + chunksLoaded.resize(NumRequestChunks); rakPeer = raknetInstance->getPeer(); } From dfb3bf1da7992326bb5773c2c2f6d2ec49aba3a0 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Sat, 9 May 2026 14:41:31 +0200 Subject: [PATCH 45/59] FIX: render ty shredder --- src/network/ClientSideNetworkHandler.cpp | 4 +++- src/world/level/tile/Tile.cpp | 10 ++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index e5db2b7..fd0b5f3 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -13,6 +13,7 @@ #include "../client/gamemode/GameMode.h" #include "world/item/ItemInstance.h" #include "world/level/LevelConstants.h" +#include #ifndef STANDALONE_SERVER #include "../client/gui/screens/DisconnectionScreen.h" #endif @@ -120,6 +121,7 @@ void ClientSideNetworkHandler::onDisconnect(const RakNet::RakNetGUID& guid) } } } + minecraft->setLevel(NULL); #ifndef STANDALONE_SERVER minecraft->gui.addMessage("Disconnected from server"); #endif @@ -354,7 +356,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveEn if (!level) return; Entity* entity = level->getEntity(packet->entityId); - LOGI("RemoveEntityPacket %p %p, %d\n", entity, minecraft->player, entity?(int)(entity->isPlayer()): -1); + // LOGI("RemoveEntityPacket %p %p, %d\n", entity, minecraft->player, entity?(int)(entity->isPlayer()): -1); if (!entity) return; level->removeEntity(entity); diff --git a/src/world/level/tile/Tile.cpp b/src/world/level/tile/Tile.cpp index a5acf7a..6736bc7 100755 --- a/src/world/level/tile/Tile.cpp +++ b/src/world/level/tile/Tile.cpp @@ -22,6 +22,7 @@ #include "../../item/StoneSlabTileItem.h" #include "../../item/SaplingTileItem.h" #include "../../item/ItemCategory.h" +#include "world/level/LevelConstants.h" const int Tile::RENDERLAYER_OPAQUE = 0; const int Tile::RENDERLAYER_ALPHATEST = 1; @@ -512,10 +513,15 @@ bool Tile::shouldRenderFace( LevelSource* level, int x, int y, int z, int face ) { if (face == 0 && y == -1) return false; // For fixed size worlds //@todo: external constants rather than magic numbers + // @fixme @ahtung temp fix + + auto xz = LevelConstants::CHUNK_CACHE_WIDTH == 16 ? 256 : + LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH / (LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH / 256 / 2); + if (face == 2 && z == -1) return false; - if (face == 3 && z == 256) return false; + if (face == 3 && z == xz) return false; if (face == 4 && x == -1) return false; - if (face == 5 && x == 256) return false; + if (face == 5 && x == xz) return false; // Common if (face == 0 && yy0 > 0) return true; if (face == 1 && yy1 < 1) return true; From 5bc19c4ab26066271e59965aae21e7454c0605a5 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Sat, 9 May 2026 16:37:11 +0200 Subject: [PATCH 46/59] FEAT: Ban command, save ops and banned ppl in files TODO: fix many crashes... --- project/android/jni/Android.mk | 1 + src/client/Minecraft.cpp | 31 ++++++------ src/commands/Command.cpp | 5 +- src/commands/CommandBan.cpp | 52 ++++++++++++++++++++ src/commands/CommandBan.hpp | 9 ++++ src/commands/CommandKick.cpp | 13 +++-- src/commands/CommandManager.cpp | 2 + src/commands/CommandOp.cpp | 11 ++--- src/main_dedicated.cpp | 61 ++++++++++++++++++++++++ src/network/ClientSideNetworkHandler.cpp | 6 +++ src/network/ServerSideNetworkHandler.cpp | 22 +++++++-- src/network/packet/LoginStatusPacket.h | 1 + src/world/level/Level.h | 2 +- 13 files changed, 187 insertions(+), 29 deletions(-) create mode 100644 src/commands/CommandBan.cpp create mode 100644 src/commands/CommandBan.hpp diff --git a/project/android/jni/Android.mk b/project/android/jni/Android.mk index 632c137..ec493d0 100755 --- a/project/android/jni/Android.mk +++ b/project/android/jni/Android.mk @@ -143,6 +143,7 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \ ../../../src/commands/Command.cpp \ ../../../src/commands/CommandHelp.cpp \ ../../../src/commands/CommandKick.cpp \ +../../../src/commands/CommandBan.cpp \ ../../../src/commands/CommandManager.cpp \ ../../../src/commands/CommandOp.cpp \ ../../../src/server/ServerLevel.cpp \ diff --git a/src/client/Minecraft.cpp b/src/client/Minecraft.cpp index d428879..bb2f579 100755 --- a/src/client/Minecraft.cpp +++ b/src/client/Minecraft.cpp @@ -278,7 +278,10 @@ void Minecraft::setLevel(Level* level, const std::string& message /* ="" */, Loc } this->level = level; // So uhhh - level->ops.emplace(options.getStringValue(OPTIONS_USERNAME)); + std::string op = options.getStringValue(OPTIONS_USERNAME); + std::transform(op.begin(), op.end(), op.begin(), ::tolower); + + level->ops.emplace(op); _hasSignaledGeneratingLevelFinished = false; #ifdef STANDALONE_SERVER const bool threadedLevelCreation = false; @@ -732,19 +735,19 @@ void Minecraft::tickInput() { } // TODO: replace it with client /give command :face_vomiting: - if (key == Keyboard::KEY_F4) { - player->inventory->add(new ItemInstance(Tile::redBrick)); - player->inventory->add(new ItemInstance(Item::ironIngot, 64)); - player->inventory->add(new ItemInstance(Item::ironIngot, 34)); - player->inventory->add(new ItemInstance(Tile::stonecutterBench)); - player->inventory->add(new ItemInstance(Tile::workBench)); - player->inventory->add(new ItemInstance(Tile::furnace)); - player->inventory->add(new ItemInstance(Tile::wood, 54)); - player->inventory->add(new ItemInstance(Item::stick, 14)); - player->inventory->add(new ItemInstance(Item::coal, 31)); - player->inventory->add(new ItemInstance(Tile::sand, 6)); + // if (key == Keyboard::KEY_F4) { + // player->inventory->add(new ItemInstance(Tile::redBrick)); + // player->inventory->add(new ItemInstance(Item::ironIngot, 64)); + // player->inventory->add(new ItemInstance(Item::ironIngot, 34)); + // player->inventory->add(new ItemInstance(Tile::stonecutterBench)); + // player->inventory->add(new ItemInstance(Tile::workBench)); + // player->inventory->add(new ItemInstance(Tile::furnace)); + // player->inventory->add(new ItemInstance(Tile::wood, 54)); + // player->inventory->add(new ItemInstance(Item::stick, 14)); + // player->inventory->add(new ItemInstance(Item::coal, 31)); + // player->inventory->add(new ItemInstance(Tile::sand, 6)); - } + // } if (key == Keyboard::KEY_F5) { options.toggle(OPTIONS_THIRD_PERSON_VIEW); @@ -1603,6 +1606,6 @@ void Minecraft::addMessage(const std::string& msg) { #ifndef STANDALONE_SERVER gui.addMessage(msg); #else - LOGI("%s", msg.c_str()); + LOGI("%s \n", msg.c_str()); #endif } \ No newline at end of file diff --git a/src/commands/Command.cpp b/src/commands/Command.cpp index ebcbf3d..187267c 100644 --- a/src/commands/Command.cpp +++ b/src/commands/Command.cpp @@ -3,5 +3,8 @@ #include bool Command::isPlayerOp(Minecraft& mc, Player& player) { - return mc.level->ops.find(player.name) != mc.level->ops.end(); + std::string nicknameLower = player.name; + std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower); + + return mc.level->ops.find(nicknameLower) != mc.level->ops.end(); } \ No newline at end of file diff --git a/src/commands/CommandBan.cpp b/src/commands/CommandBan.cpp new file mode 100644 index 0000000..0373d5b --- /dev/null +++ b/src/commands/CommandBan.cpp @@ -0,0 +1,52 @@ +#include "CommandBan.hpp" +#include "commands/Command.hpp" +#include "network/RakNetInstance.h" +#include "raknet/RakPeerInterface.h" +#include "world/level/Level.h" +#include +#include + +CommandBan::CommandBan() : Command("ban") {} + +std::string CommandBan::execute(Minecraft& mc, Player& player, const std::vector& args) { + if (!isPlayerOp(mc, player)) { + return "You aren't enough priveleged to run this command"; + } + + if (args.empty()) { + return help(mc); + } + + std::string nicknameLower = args[0]; + std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower); + + auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args, nicknameLower] (auto& it) -> bool { + std::string lower = it->name; + std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); + + return lower == nicknameLower; + }); + + if (*it == (Player*)mc.player) { + return "ban: you can't ban urself lol"; + } + + if (it != mc.level->players.end()) { + mc.level->removePlayer(*it); + (*it)->remove(); + mc.raknetInstance->getPeer()->CloseConnection((*it)->owner, true); + } else { + for (auto& banned : mc.level->bannedPpl) { + if (nicknameLower == banned) { + return args[0] + "already banned!"; + } + } + } + + mc.level->bannedPpl.insert(nicknameLower); + return "ban: successfully banned player " + args[0]; +} + +std::string CommandBan::help(Minecraft& mc) { + return "Usage: /ban "; +} \ No newline at end of file diff --git a/src/commands/CommandBan.hpp b/src/commands/CommandBan.hpp new file mode 100644 index 0000000..b688800 --- /dev/null +++ b/src/commands/CommandBan.hpp @@ -0,0 +1,9 @@ +#include "Command.hpp" + +class CommandBan : public Command { +public: + CommandBan(); + + std::string execute(Minecraft& mc, Player& player, const std::vector& args); + std::string help(Minecraft& mc); +}; \ No newline at end of file diff --git a/src/commands/CommandKick.cpp b/src/commands/CommandKick.cpp index df8c113..b876d9a 100644 --- a/src/commands/CommandKick.cpp +++ b/src/commands/CommandKick.cpp @@ -5,7 +5,6 @@ #include "world/level/Level.h" #include #include -// RakNet::RakPeerInterface CommandKick::CommandKick() : Command("kick") {} @@ -18,8 +17,14 @@ std::string CommandKick::execute(Minecraft& mc, Player& player, const std::vecto return help(mc); } - auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args] (auto& it) -> bool { - return it->name == args[0]; + std::string nicknameLower = args[0]; + std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower); + + auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args, nicknameLower] (auto& it) -> bool { + std::string lower = it->name; + std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); + + return lower == nicknameLower; }); if (it == mc.level->players.end()) { @@ -33,7 +38,7 @@ std::string CommandKick::execute(Minecraft& mc, Player& player, const std::vecto mc.level->removePlayer(*it); (*it)->remove(); mc.raknetInstance->getPeer()->CloseConnection((*it)->owner, true); - mc.addMessage("kick: successfully kicked player " + args[0]); + return "kick: successfully kicked player " + args[0]; } std::string CommandKick::help(Minecraft& mc) { diff --git a/src/commands/CommandManager.cpp b/src/commands/CommandManager.cpp index 9087c42..fbb9324 100644 --- a/src/commands/CommandManager.cpp +++ b/src/commands/CommandManager.cpp @@ -7,6 +7,7 @@ #include "commands/CommandHelp.hpp" #include "commands/CommandKick.hpp" #include "commands/CommandOp.hpp" +#include "commands/CommandBan.hpp" #include "network/packet/ChatPacket.h" #include "network/RakNetInstance.h" #include "world/level/Level.h" @@ -19,6 +20,7 @@ void CommandManager::registerAllCommands() { m_commands.push_back(new CommandHelp()); m_commands.push_back(new CommandKick()); m_commands.push_back(new CommandOp()); + m_commands.push_back(new CommandBan()); } std::vector CommandManager::getListAllCommands() { diff --git a/src/commands/CommandOp.cpp b/src/commands/CommandOp.cpp index e50e130..7fc2c30 100644 --- a/src/commands/CommandOp.cpp +++ b/src/commands/CommandOp.cpp @@ -15,15 +15,14 @@ std::string CommandOp::execute(Minecraft& mc, Player& player, const std::vector< return help(mc); } - auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args] (auto& it) -> bool { - return it->name == args[0]; - }); - - if (mc.level->ops.find(args[0]) != mc.level->ops.end()) { + std::string nicknameLower = args[0]; + std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower); + + if (mc.level->ops.find(nicknameLower) != mc.level->ops.end()) { return "op: player " + args[0] + " already opped"; } - mc.level->ops.emplace((*it)->name); + mc.level->ops.emplace(nicknameLower); return "op: successfully opped player " + args[0]; } diff --git a/src/main_dedicated.cpp b/src/main_dedicated.cpp index 2c429ed..4c667b5 100755 --- a/src/main_dedicated.cpp +++ b/src/main_dedicated.cpp @@ -161,6 +161,44 @@ int main(int numArguments, char* pszArgs[]) { ((MAIN_CLASS*)g_app)->selectLevel(levelDir, levelName, settings); ((MAIN_CLASS*)g_app)->hostMultiplayer(port); + // Reading ops + std::ifstream ops("ops.txt"); + + if (ops.is_open()) { + std::string line; + + while (std::getline(ops, line)) { + if (!line.empty()) { + ((MAIN_CLASS*)g_app)->level->ops.insert(line); + } + } + } else { + std::ofstream opsDefault("ops.txt"); + + if (!opsDefault.is_open()) { + throw std::runtime_error("Cannot create ops list."); + } + } + + // Reading banned ppl + std::ifstream banned("banned-players.txt"); + + if (banned.is_open()) { + std::string line; + + while (std::getline(banned, line)) { + if (!line.empty()) { + ((MAIN_CLASS*)g_app)->level->bannedPpl.insert(line); + } + } + } else { + std::ofstream bannedPpl("banned-players.txt"); + + if (!bannedPpl.is_open()) { + throw std::runtime_error("Cannot create banned players list."); + } + } + std::cout << "Level has been generated in " << getTimeS() - startTime << std::endl; ((MAIN_CLASS*)g_app)->level->saveLevelData(); std::cout << "Level has been saved!" << std::endl; @@ -171,7 +209,30 @@ int main(int numArguments, char* pszArgs[]) { sleepMs(20); } + std::ofstream opsWrite("ops.txt"); + + if (opsWrite.is_open()) { + for (auto& op : ((MAIN_CLASS*)g_app)->level->ops) { + opsWrite << op << std::endl; + } + opsWrite.close(); + } else { + throw std::runtime_error("Cannot open ops list."); + } + + std::ofstream bannedWrite("banned-players.txt"); + + if (bannedWrite.is_open()) { + for (auto& banned : ((MAIN_CLASS*)g_app)->level->bannedPpl) { + bannedWrite << banned << std::endl; + } + bannedWrite.close(); + } else { + throw std::runtime_error("Cannot open banned players list."); + } + ((MAIN_CLASS*)g_app)->level->saveLevelData(); + delete app; appContext.platform->finish(); delete appContext.platform; diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index fd0b5f3..493ddfe 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -149,6 +149,12 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginSta LOGI("Disconnect! Nickname is taken!\n"); #ifndef STANDALONE_SERVER minecraft->setScreen(new DisconnectionScreen("Could not connect: Nickname is taken!")); +#endif + } + if (packet->status == LoginStatus::Failed_Banned) { + LOGI("Disconnect! You're banned from this server!\n"); +#ifndef STANDALONE_SERVER + minecraft->setScreen(new DisconnectionScreen("Could not connect: You're banned from this server!")); #endif } } diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index b184d8b..20d375b 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -159,7 +159,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChatPack { auto player = getPlayer(source); - if (player == nullptr) return; // TODO maybe kick? + if (player == nullptr) return; // @todo maybe kick? if (packet->message[0] == '/') { // This is a command @@ -223,11 +223,27 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac if (oldClient || oldServer || !packet->newProto) loginStatus = oldClient || !packet->newProto? LoginStatus::Failed_ClientOld : LoginStatus::Failed_ServerOld; + std::string nicknameLower = packet->clientName.C_String(); + std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower); + + printf("%s lower \n", nicknameLower.c_str()); for (int i = 0; i < level->players.size(); i++) { ServerPlayer* player = (ServerPlayer*) level->players.at(i); - - if (player->name == packet->clientName.C_String()) { + + std::string clientLower = player->name; + std::transform(clientLower.begin(), clientLower.end(), clientLower.begin(), ::tolower); + + // @todo to lower case + if (nicknameLower == clientLower) { loginStatus = packet->newProto ? LoginStatus::Failed_TakenNickname : LoginStatus::Failed_ClientOld; + break; + } + } + + for (auto& banned : level->bannedPpl) { + if (nicknameLower == banned) { + loginStatus = packet->newProto ? LoginStatus::Failed_Banned : LoginStatus::Failed_ClientOld; + break; } } diff --git a/src/network/packet/LoginStatusPacket.h b/src/network/packet/LoginStatusPacket.h index efa10f5..e2e0957 100755 --- a/src/network/packet/LoginStatusPacket.h +++ b/src/network/packet/LoginStatusPacket.h @@ -9,6 +9,7 @@ namespace LoginStatus { const int Failed_ClientOld = 1; const int Failed_ServerOld = 2; const int Failed_TakenNickname = 3; + const int Failed_Banned = 4; } class LoginStatusPacket : public Packet { diff --git a/src/world/level/Level.h b/src/world/level/Level.h index edf1747..a7196ed 100755 --- a/src/world/level/Level.h +++ b/src/world/level/Level.h @@ -309,7 +309,7 @@ public: Random random; std::set ops; - + std::set bannedPpl; protected: bool isFindingSpawn; From 5e19ef778eb01262944f6d2f1410f387d97761d2 Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Tue, 12 May 2026 22:12:52 +0300 Subject: [PATCH 47/59] FIX: memset ._. --- src/world/level/chunk/ChunkCache.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/world/level/chunk/ChunkCache.h b/src/world/level/chunk/ChunkCache.h index ee5fc49..ea4933e 100755 --- a/src/world/level/chunk/ChunkCache.h +++ b/src/world/level/chunk/ChunkCache.h @@ -26,6 +26,8 @@ public: emptyChunk = new EmptyLevelChunk(level_, NULL, 0, 0); chunks = new LevelChunk *[LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH]; + memset(chunks, 0, sizeof(LevelChunk*) * LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH); + LOGI("Chunks allocated."); } ~ChunkCache() { @@ -34,7 +36,7 @@ public: for (int i = 0; i < LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH; i++) { - if (&chunks[i]) + if (chunks[i]) { chunks[i]->deleteBlockData(); delete chunks[i]; From b73f7f121d1507e251a2d88d4d8f9898665568e2 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Tue, 12 May 2026 21:29:17 +0200 Subject: [PATCH 48/59] ee --- src/network/ServerSideNetworkHandler.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 20d375b..71c4902 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -968,19 +968,17 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, Containe void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SetHealthPacket* packet ) { - LOGI("net idi nahui\n"); - - // 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; - // } - // } + 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 ) { From 3ebed84cdbe619817580dc433176d07431867a70 Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Thu, 2 Jul 2026 16:32:17 +0300 Subject: [PATCH 49/59] FIX: crash while joining to large world server --- src/client/Minecraft.cpp | 1 + src/network/ClientSideNetworkHandler.cpp | 2 +- src/world/level/chunk/LevelChunk.cpp | 2 +- src/world/level/chunk/LevelChunk.h | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/client/Minecraft.cpp b/src/client/Minecraft.cpp index bb2f579..4e1a1ad 100755 --- a/src/client/Minecraft.cpp +++ b/src/client/Minecraft.cpp @@ -1137,6 +1137,7 @@ bool Minecraft::supportNonTouchScreen() { } void Minecraft::init() { + LevelChunk::ChunkBlockCount = LevelConstants::CHUNK_BLOCK_COUNT; #ifndef STANDALONE_SERVER checkGlError("Init enter"); diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index 493ddfe..4b384de 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -178,7 +178,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, StartGam LevelConstants::CHUNK_CACHE_WIDTH = packet->chunkCacheWidth; LevelConstants::LEVEL_WIDTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_WIDTH; LevelConstants::LEVEL_DEPTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_DEPTH; - + LevelChunk::ChunkBlockCount = LevelConstants::CHUNK_BLOCK_COUNT; } NumRequestChunks = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH; requestNextChunkIndexList.resize(NumRequestChunks); diff --git a/src/world/level/chunk/LevelChunk.cpp b/src/world/level/chunk/LevelChunk.cpp index 5cf3ae6..499a7ae 100755 --- a/src/world/level/chunk/LevelChunk.cpp +++ b/src/world/level/chunk/LevelChunk.cpp @@ -12,7 +12,7 @@ /*static*/ bool LevelChunk::touchedSky = false; -const int LevelChunk::ChunkBlockCount = LevelConstants::CHUNK_BLOCK_COUNT; +int LevelChunk::ChunkBlockCount; LevelChunk::LevelChunk( Level* level, int x, int z ) : level(level), diff --git a/src/world/level/chunk/LevelChunk.h b/src/world/level/chunk/LevelChunk.h index b88cb7a..8fe7281 100755 --- a/src/world/level/chunk/LevelChunk.h +++ b/src/world/level/chunk/LevelChunk.h @@ -106,7 +106,7 @@ private: void recalcHeight(int x, int yStart, int z); public: static bool touchedSky; - static const int ChunkBlockCount; + static int ChunkBlockCount; const int ChunkSize = ChunkBlockCount; static const int UpdateMapBitShift = 4; // power of (LevelConstants::LEVEL_HEIGHT / 8) == 16 From f0df3fe2570d20bc31b8ee279665b97ac89a71e2 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Fri, 10 Jul 2026 00:46:36 +0200 Subject: [PATCH 50/59] Server for windows wow --- CMakeLists.txt | 17 +++++++---------- src/NinecraftApp.cpp | 2 +- src/main_dedicated.cpp | 2 ++ 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7650b9a..eab2ada 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,7 +149,6 @@ file(GLOB SERVER_SOURCES "src/platform/CThread.cpp" "src/platform/HttpClient.cpp" - "src/platform/PngLoader.cpp" "src/platform/time.cpp" "src/platform/input/Controller.cpp" @@ -302,18 +301,16 @@ if (${PLATFORM} STREQUAL "Desktop") endif() # Server -if(UNIX) - add_executable("${PROJECT_NAME}-server" ${SERVER_SOURCES}) +add_executable("${PROJECT_NAME}-server" ${SERVER_SOURCES}) - target_compile_definitions("${PROJECT_NAME}-server" PUBLIC "STANDALONE_SERVER" "SERVER_PROFILER") +target_compile_definitions("${PROJECT_NAME}-server" PUBLIC "STANDALONE_SERVER" "SERVER_PROFILER") - target_include_directories("${PROJECT_NAME}-server" PUBLIC - "${CMAKE_SOURCE_DIR}/src/" - "project/lib_projects/raknet/jni/RaknetSources" - ) +target_include_directories("${PROJECT_NAME}-server" PUBLIC + "${CMAKE_SOURCE_DIR}/src/" + "project/lib_projects/raknet/jni/RaknetSources" +) - target_link_libraries("${PROJECT_NAME}-server" ${CMAKE_THREAD_LIBS_INIT}) -endif() +target_link_libraries("${PROJECT_NAME}-server" ${CMAKE_THREAD_LIBS_INIT}) add_executable(${PROJECT_NAME} ${CLIENT_SOURCES}) diff --git a/src/NinecraftApp.cpp b/src/NinecraftApp.cpp index d2feea6..60e9fee 100755 --- a/src/NinecraftApp.cpp +++ b/src/NinecraftApp.cpp @@ -136,7 +136,7 @@ void NinecraftApp::teardown() Recipes ::teardownRecipes(); TileEntity::teardownTileEntities(); #endif -#ifdef WIN32 +#if defined(WIN32) && !defined(STANDALONE_SERVER) ItemRenderer::teardown_static(); if (EntityTileRenderer::instance != NULL) { delete EntityTileRenderer::instance; diff --git a/src/main_dedicated.cpp b/src/main_dedicated.cpp index 4c667b5..fcf14ce 100755 --- a/src/main_dedicated.cpp +++ b/src/main_dedicated.cpp @@ -5,7 +5,9 @@ #include #include #include +#ifdef __linux__ #include +#endif #include "world/level/LevelSettings.h" #include "world/level/Level.h" From d3d9b1a23845c83eb9d74cecb6ddd8e31c2e7491 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Fri, 10 Jul 2026 00:59:26 +0200 Subject: [PATCH 51/59] anticheat sucks xdxd --- src/network/ServerSideNetworkHandler.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 71c4902..9892131 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -433,24 +433,24 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay { if (!level) return; - //LOGI("MovePlayerPacket\n"); + LOGI("MovePlayerPacket\n"); if (Entity* entity = level->getEntity(packet->entityId)) { ServerPlayer* player = (ServerPlayer*) getPlayer(source); - int timeElapsed = minecraft->getTicks() - player->getLastMoveTicks(); + // int timeElapsed = minecraft->getTicks() - player->getLastMoveTicks(); - if (timeElapsed > 0) { - float dist = player->distanceTo(packet->x, player->y, packet->z); - float speed = dist / (minecraft->getTicks() - player->getLastMoveTicks()); - player->setLastMoveTicks(minecraft->getTicks()); + // if (timeElapsed > 0) { + // float dist = player->distanceTo(packet->x, player->y, packet->z); + // float speed = dist / (minecraft->getTicks() - player->getLastMoveTicks()); + // player->setLastMoveTicks(minecraft->getTicks()); - float maxSpeed = (minecraft->isCreativeMode()) ? 1.65f : 1.f; + // float maxSpeed = (minecraft->isCreativeMode()) ? 1.65f : 1.f; - if (speed > maxSpeed) { - MovePlayerPacket refuse(player->entityId, player->x, player->y, player->z, player->xRot, player->yRot); - return raknetInstance->send(refuse); - } - } + // if (speed > maxSpeed) { + // MovePlayerPacket refuse(player->entityId, player->x, player->y, player->z, player->xRot, player->yRot); + // return raknetInstance->send(refuse); + // } + // } entity->xd = entity->yd = entity->zd = 0; entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3); From 26e53760309e8c61ee15698544e01980f134749e Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Fri, 10 Jul 2026 21:45:52 +0200 Subject: [PATCH 52/59] FIX: Crash when server is disaibling --- src/client/Minecraft.cpp | 3 +- src/client/renderer/LevelRenderer.cpp | 73 ++++++++++++------------ src/network/ClientSideNetworkHandler.cpp | 4 +- src/network/ServerSideNetworkHandler.cpp | 9 +-- 4 files changed, 45 insertions(+), 44 deletions(-) diff --git a/src/client/Minecraft.cpp b/src/client/Minecraft.cpp index 4e1a1ad..26a8bb9 100755 --- a/src/client/Minecraft.cpp +++ b/src/client/Minecraft.cpp @@ -258,9 +258,10 @@ void Minecraft::selectLevel( const std::string& levelId, const std::string& leve void Minecraft::setLevel(Level* level, const std::string& message /* ="" */, LocalPlayer* forceInsertPlayer /* = NULL */) { cameraTargetPlayer = NULL; - LOGI("Seed is %ld\n", level->getSeed()); if (level != NULL) { + LOGI("Seed is %ld\n", level->getSeed()); + level->raknetInstance = raknetInstance; gameMode->initLevel(level); diff --git a/src/client/renderer/LevelRenderer.cpp b/src/client/renderer/LevelRenderer.cpp index c3f1161..240ab9b 100755 --- a/src/client/renderer/LevelRenderer.cpp +++ b/src/client/renderer/LevelRenderer.cpp @@ -1077,53 +1077,54 @@ void LevelRenderer::playSound(const std::string& name, float x, float y, float z float dd = 16; if (volume > 1) dd *= volume; - if (mc->cameraTargetPlayer->distanceToSqr(x, y, z) < dd * dd) { + if (mc->cameraTargetPlayer != NULL && mc->cameraTargetPlayer->distanceToSqr(x, y, z) < dd * dd) { mc->soundEngine->play(name, x, y, z, volume, pitch); } } void LevelRenderer::addParticle(const std::string& name, float x, float y, float z, float xa, float ya, float za, int data) { + if (mc->cameraTargetPlayer != NULL) { + float xd = mc->cameraTargetPlayer->x - x; + float yd = mc->cameraTargetPlayer->y - y; + float zd = mc->cameraTargetPlayer->z - z; + float distanceSquared = xd * xd + yd * yd + zd * zd; - float xd = mc->cameraTargetPlayer->x - x; - float yd = mc->cameraTargetPlayer->y - y; - float zd = mc->cameraTargetPlayer->z - z; - float distanceSquared = xd * xd + yd * yd + zd * zd; + //Particle* p = NULL; + //if (name == "hugeexplosion") p = new HugeExplosionSeedParticle(level, x, y, z, xa, ya, za); + //else if (name == "largeexplode") p = new HugeExplosionParticle(textures, level, x, y, z, xa, ya, za); - //Particle* p = NULL; - //if (name == "hugeexplosion") p = new HugeExplosionSeedParticle(level, x, y, z, xa, ya, za); - //else if (name == "largeexplode") p = new HugeExplosionParticle(textures, level, x, y, z, xa, ya, za); + //if (p) { + // if (distanceSquared < 32 * 32) { + // mc->particleEngine->add(p); + // } else { delete p; } + // return; + //} - //if (p) { - // if (distanceSquared < 32 * 32) { - // mc->particleEngine->add(p); - // } else { delete p; } - // return; - //} + const float particleDistance = 16; + if (distanceSquared > particleDistance * particleDistance) return; - const float particleDistance = 16; - if (distanceSquared > particleDistance * particleDistance) return; + //static Stopwatch sw; + //sw.start(); - //static Stopwatch sw; - //sw.start(); + if (name == "bubble") mc->particleEngine->add(new BubbleParticle(level, x, y, z, xa, ya, za)); + else if (name == "crit") mc->particleEngine->add(new CritParticle2(level, x, y, z, xa, ya, za)); + else if (name == "smoke") mc->particleEngine->add(new SmokeParticle(level, x, y, z, xa, ya, za)); + //else if (name == "note") mc->particleEngine->add(new NoteParticle(level, x, y, z, xa, ya, za)); + else if (name == "explode") mc->particleEngine->add(new ExplodeParticle(level, x, y, z, xa, ya, za)); + else if (name == "flame") mc->particleEngine->add(new FlameParticle(level, x, y, z, xa, ya, za)); + else if (name == "lava") mc->particleEngine->add(new LavaParticle(level, x, y, z)); + //else if (name == "splash") mc->particleEngine->add(new SplashParticle(level, x, y, z, xa, ya, za)); + else if (name == "largesmoke") mc->particleEngine->add(new SmokeParticle(level, x, y, z, xa, ya, za, 2.5f)); + else if (name == "reddust") mc->particleEngine->add(new RedDustParticle(level, x, y, z, xa, ya, za)); + else if (name == "iconcrack") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, xa, ya, za, Item::items[data])); + else if (name == "snowballpoof") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, Item::snowBall)); + //else if (name == "snowballpoof") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, Item::snowBall)); + //else if (name == "slime") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, Item::slimeBall)); + //else if (name == "heart") mc->particleEngine->add(new HeartParticle(level, x, y, z, xa, ya, za)); - if (name == "bubble") mc->particleEngine->add(new BubbleParticle(level, x, y, z, xa, ya, za)); - else if (name == "crit") mc->particleEngine->add(new CritParticle2(level, x, y, z, xa, ya, za)); - else if (name == "smoke") mc->particleEngine->add(new SmokeParticle(level, x, y, z, xa, ya, za)); - //else if (name == "note") mc->particleEngine->add(new NoteParticle(level, x, y, z, xa, ya, za)); - else if (name == "explode") mc->particleEngine->add(new ExplodeParticle(level, x, y, z, xa, ya, za)); - else if (name == "flame") mc->particleEngine->add(new FlameParticle(level, x, y, z, xa, ya, za)); - else if (name == "lava") mc->particleEngine->add(new LavaParticle(level, x, y, z)); - //else if (name == "splash") mc->particleEngine->add(new SplashParticle(level, x, y, z, xa, ya, za)); - else if (name == "largesmoke") mc->particleEngine->add(new SmokeParticle(level, x, y, z, xa, ya, za, 2.5f)); - else if (name == "reddust") mc->particleEngine->add(new RedDustParticle(level, x, y, z, xa, ya, za)); - else if (name == "iconcrack") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, xa, ya, za, Item::items[data])); - else if (name == "snowballpoof") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, Item::snowBall)); - //else if (name == "snowballpoof") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, Item::snowBall)); - //else if (name == "slime") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, Item::slimeBall)); - //else if (name == "heart") mc->particleEngine->add(new HeartParticle(level, x, y, z, xa, ya, za)); - - //sw.stop(); - //sw.printEvery(50, "add-particle-string"); + //sw.stop(); + //sw.printEvery(50, "add-particle-string"); + } } /* diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index 4b384de..807dd1a 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -120,10 +120,12 @@ void ClientSideNetworkHandler::onDisconnect(const RakNet::RakNetGUID& guid) level->removeEntity(p); } } - } + } minecraft->setLevel(NULL); #ifndef STANDALONE_SERVER minecraft->gui.addMessage("Disconnected from server"); + // TODO: screen with error + minecraft->screenChooser.setScreen(SCREEN_STARTMENU); #endif } diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 9892131..cc49754 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -697,12 +697,9 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, WantCrea } } - // for (int i = 0; i < items.size(); i++) { - // RemoveItemPacket removePacket(packet->playerId, items.at(i).count, items.at(i).getAuxValue(), items.at(i).id); - // raknetInstance->send(source, removePacket); - - // p->inventory->removeResource(ItemInstance(items.at(i).id, items.at(i).count, items.at(i).getAuxValue())); - // } + for (int i = 0; i < items.size(); i++) { + p->inventory->removeResource(ItemInstance(items.at(i).id, items.at(i).count, items.at(i).getAuxValue())); + } // TakeItemPacket itemAdd(p->entityId, wantCreate.count, wantCreate.getAuxValue(), wantCreate.id); // raknetInstance->send(source, itemAdd); From 381196468951975d3e4dd4dd424cd8355325ee35 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Sat, 18 Jul 2026 14:02:45 +0200 Subject: [PATCH 53/59] ffqwfqwfw --- src/client/gamemode/GameMode.cpp | 8 +++++--- src/network/ClientSideNetworkHandler.cpp | 2 +- src/network/ServerSideNetworkHandler.cpp | 11 ++++++++++- src/network/packet/UseItemPacket.h | 23 ++++++++++++++++++----- src/world/item/TileItem.h | 2 +- src/world/level/Level.cpp | 2 +- 6 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/client/gamemode/GameMode.cpp b/src/client/gamemode/GameMode.cpp index de6df50..6877d7c 100755 --- a/src/client/gamemode/GameMode.cpp +++ b/src/client/gamemode/GameMode.cpp @@ -90,8 +90,10 @@ bool GameMode::useItemOn(Player* player, Level* level, ItemInstance* item, int x float clickY = hit.y - y; float clickZ = hit.z - z; if (level->isClientSide) { + LOGI("%f %f %f \n", player->x, player->y, player->z); + item = player->inventory->getSelected(); - UseItemPacket packet(x, y, z, face, item, player->entityId, clickX, clickY, clickZ); + UseItemPacket packet(x, y, z, face, item, player->entityId, clickX, clickY, clickZ, player->x, player->y, player->z); minecraft->raknetInstance->send(packet); } int t = level->getTile(x, y, z); @@ -100,7 +102,7 @@ bool GameMode::useItemOn(Player* player, Level* level, ItemInstance* item, int x return true; if (item == NULL) return false; - if(isCreativeType()) { + if (isCreativeType()) { int aux = item->getAuxValue(); int count = item->count; bool success = item->useOn(player, level, x, y, z, face, clickX, clickY, clickZ); @@ -117,7 +119,7 @@ bool GameMode::useItem( Player* player, Level* level, ItemInstance* item ) { ItemInstance* itemInstance = item->use(level, player); if(level->isClientSide) { - UseItemPacket packet(item, player->entityId, player->aimDirection); + UseItemPacket packet(item, player->entityId, player->aimDirection, player->x, player->y, player->z); minecraft->raknetInstance->send(packet); } if (itemInstance != item || (itemInstance != NULL && itemInstance->count != oldCount)) { diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index 807dd1a..ee61184 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -820,7 +820,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SetEntit if (!level) return; - LOGI("SetEntityDataPacket\n"); + // LOGI("SetEntityDataPacket\n"); Entity* e = level->getEntity(packet->id); if (e) { diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index cc49754..1c4a1ac 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -433,7 +433,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay { if (!level) return; - LOGI("MovePlayerPacket\n"); + // LOGI("MovePlayerPacket\n"); if (Entity* entity = level->getEntity(packet->entityId)) { ServerPlayer* player = (ServerPlayer*) getPlayer(source); @@ -713,7 +713,10 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemP LOGI("UseItemPacket: id %i data %i\n", packet->itemId, packet->itemData); Entity* entity = level->getEntity(packet->entityId); + if (entity && entity->isPlayer()) { + LOGI("%f %f %f \n", entity->x, entity->y, entity->z); + Player* player = (Player*) entity; int x = packet->x, y = packet->y, z = packet->z; Tile* t = Tile::tiles[level->getTile(x, y, z)]; @@ -747,6 +750,12 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemP ItemInstance* item = player->inventory->getItem(slot); + player->x = packet->playerX; + player->y = packet->playerY; + player->z = packet->playerZ; + LOGI("upd: %f %f %f \n", packet->playerX, packet->playerY, packet->playerZ); + LOGI("plr new: %f %f %f \n", player->x, player->y, player->z); + 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); diff --git a/src/network/packet/UseItemPacket.h b/src/network/packet/UseItemPacket.h index e1583de..bfef1f2 100755 --- a/src/network/packet/UseItemPacket.h +++ b/src/network/packet/UseItemPacket.h @@ -16,10 +16,12 @@ public: short itemId; unsigned char itemData; ItemInstance item; + float playerX, playerY, playerZ; UseItemPacket() {} - UseItemPacket(int x, int y, int z, int face, const ItemInstance* item, int entityId, float clickX, float clickY, float clickZ) + UseItemPacket(int x, int y, int z, int face, const ItemInstance* item, int entityId, float clickX, float clickY, float clickZ, + float plrX, float plrY, float plrZ) : x(x), y(y), z(z), @@ -29,17 +31,23 @@ public: entityId(entityId), clickX(clickX), clickY(clickY), - clickZ(clickZ) + clickZ(clickZ), + playerX(plrX), + playerY(plrY), + playerZ(plrZ) {} - UseItemPacket(const ItemInstance* item, int entityId, const Vec3& aim) + UseItemPacket(const ItemInstance* item, int entityId, const Vec3& aim, float plrX, float plrY, float plrZ) : 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)) + z((int)(aim.z * 32768.0f)), + playerX(plrX), + playerY(plrY), + playerZ(plrZ) { } @@ -57,6 +65,9 @@ public: bitStream->Write(clickX); bitStream->Write(clickY); bitStream->Write(clickZ); + bitStream->Write(playerX); + bitStream->Write(playerY); + bitStream->Write(playerZ); } void read(RakNet::BitStream* bitStream) @@ -74,7 +85,9 @@ public: item.id = itemId; item.setAuxValue(itemData); item.count = (itemId == 0 && itemData == 0)? 0 : 1; - + bitStream->Read(playerX); + bitStream->Read(playerY); + bitStream->Read(playerZ); } void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) diff --git a/src/world/item/TileItem.h b/src/world/item/TileItem.h index c75084e..08bd1d0 100755 --- a/src/world/item/TileItem.h +++ b/src/world/item/TileItem.h @@ -61,7 +61,7 @@ public: if (level->setTileAndData(x, y, z, tileId, data)) { Tile::tiles[tileId]->setPlacedBy(level, x, y, z, player); level->playSound(x + 0.5f, y + 0.5f, z + 0.5f, tile->soundType->getStepSound(), (tile->soundType->getVolume() + 1) / 2, tile->soundType->getPitch() * 0.8f); - + printf("%f %f %f \n", player->x, player->y, player->z); /* PlaceBlockPacket packet(player->entityId, x, y, z, face, tileId, instance->getAuxValue()); //LOGI("Place block at @ %d, %d, %d\n", x, y, z); diff --git a/src/world/level/Level.cpp b/src/world/level/Level.cpp index cb6d688..2c7fffd 100755 --- a/src/world/level/Level.cpp +++ b/src/world/level/Level.cpp @@ -1962,7 +1962,7 @@ void Level::prepare() { ; } -bool Level::mayPlace(int tileId, int x, int y, int z, bool ignoreEntities,unsigned char face) { +bool Level::mayPlace(int tileId, int x, int y, int z, bool ignoreEntities,unsigned char face) { int targetType = getTile(x, y, z); const Tile* targetTile = Tile::tiles[targetType]; Tile* tile = Tile::tiles[tileId]; From 50d1de49e012531e0d8d9e640c53d3c42ed7d955 Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Sat, 18 Jul 2026 15:24:58 +0300 Subject: [PATCH 54/59] FIX: multiplayer leave crash and compilation --- .../raknet/jni/RaknetSources/GetTime.cpp | 2 +- src/network/ClientSideNetworkHandler.cpp | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/project/lib_projects/raknet/jni/RaknetSources/GetTime.cpp b/project/lib_projects/raknet/jni/RaknetSources/GetTime.cpp index 4f868f8..effd244 100755 --- a/project/lib_projects/raknet/jni/RaknetSources/GetTime.cpp +++ b/project/lib_projects/raknet/jni/RaknetSources/GetTime.cpp @@ -140,7 +140,7 @@ RakNet::TimeUS GetTimeUS_Windows( void ) #if _MSC_VER >= 1400 && defined (_M_X64) GetProcessAffinityMask(mProc, (PDWORD_PTR)&mProcMask, (PDWORD_PTR)&mSysMask); #else - GetProcessAffinityMask(mProc, &mProcMask, &mSysMask); + GetProcessAffinityMask(mProc, (PDWORD_PTR)&mProcMask, (PDWORD_PTR)&mSysMask); #endif mThread = GetCurrentThread(); diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index ee61184..a5bb960 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -120,13 +120,14 @@ void ClientSideNetworkHandler::onDisconnect(const RakNet::RakNetGUID& guid) level->removeEntity(p); } } - } - minecraft->setLevel(NULL); -#ifndef STANDALONE_SERVER - minecraft->gui.addMessage("Disconnected from server"); - // TODO: screen with error - minecraft->screenChooser.setScreen(SCREEN_STARTMENU); -#endif + } + minecraft->leaveGame(); +// minecraft->setLevel(NULL); +// #ifndef STANDALONE_SERVER +// minecraft->gui.addMessage("Disconnected from server"); +// // TODO: screen with error +// minecraft->screenChooser.setScreen(SCREEN_STARTMENU); +// #endif } void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginStatusPacket* packet) { From fcf7427fb259c8737634f9fb4ba44f5c0f0fa40b Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Sat, 18 Jul 2026 19:14:16 +0200 Subject: [PATCH 55/59] gg fixed --- src/client/gamemode/GameMode.cpp | 7 +++-- src/network/ServerSideNetworkHandler.cpp | 11 ++++++-- src/network/packet/UseItemPacket.h | 35 +++++++++++++++++++++--- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/client/gamemode/GameMode.cpp b/src/client/gamemode/GameMode.cpp index 6877d7c..8009d64 100755 --- a/src/client/gamemode/GameMode.cpp +++ b/src/client/gamemode/GameMode.cpp @@ -93,7 +93,9 @@ bool GameMode::useItemOn(Player* player, Level* level, ItemInstance* item, int x LOGI("%f %f %f \n", player->x, player->y, player->z); item = player->inventory->getSelected(); - UseItemPacket packet(x, y, z, face, item, player->entityId, clickX, clickY, clickZ, player->x, player->y, player->z); + UseItemPacket packet(x, y, z, face, item, player->entityId, clickX, clickY, clickZ, player->x, player->y, player->z, + player->bb.x0, player->bb.y0, player->bb.z0, player->bb.x1, player->bb.y1, player->bb.z1); + minecraft->raknetInstance->send(packet); } int t = level->getTile(x, y, z); @@ -119,7 +121,8 @@ bool GameMode::useItem( Player* player, Level* level, ItemInstance* item ) { ItemInstance* itemInstance = item->use(level, player); if(level->isClientSide) { - UseItemPacket packet(item, player->entityId, player->aimDirection, player->x, player->y, player->z); + UseItemPacket packet(item, player->entityId, player->aimDirection, player->x, player->y, player->z, + player->bb.x0, player->bb.y0, player->bb.z0, player->bb.x1, player->bb.y1, player->bb.z1); minecraft->raknetInstance->send(packet); } if (itemInstance != item || (itemInstance != NULL && itemInstance->count != oldCount)) { diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 1c4a1ac..2f3f237 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -749,12 +749,17 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemP } ItemInstance* item = player->inventory->getItem(slot); - player->x = packet->playerX; player->y = packet->playerY; player->z = packet->playerZ; - LOGI("upd: %f %f %f \n", packet->playerX, packet->playerY, packet->playerZ); - LOGI("plr new: %f %f %f \n", player->x, player->y, player->z); + + player->bb.x0 = packet->playerX0; + player->bb.y0 = packet->playerY0; + player->bb.z0 = packet->playerZ0; + + player->bb.x1 = packet->playerX1; + player->bb.y1 = packet->playerY1; + player->bb.z1 = packet->playerZ1; if(packet->face == 255) { // Special case: x,y,z means direction-of-action diff --git a/src/network/packet/UseItemPacket.h b/src/network/packet/UseItemPacket.h index bfef1f2..3f67c41 100755 --- a/src/network/packet/UseItemPacket.h +++ b/src/network/packet/UseItemPacket.h @@ -17,11 +17,13 @@ public: unsigned char itemData; ItemInstance item; float playerX, playerY, playerZ; + float playerX0, playerY0, playerZ0; + float playerX1, playerY1, playerZ1; UseItemPacket() {} UseItemPacket(int x, int y, int z, int face, const ItemInstance* item, int entityId, float clickX, float clickY, float clickZ, - float plrX, float plrY, float plrZ) + float plrX, float plrY, float plrZ, float plrX0, float plrY0, float plrZ0, float plrX1, float plrY1, float plrZ1) : x(x), y(y), z(z), @@ -34,10 +36,17 @@ public: clickZ(clickZ), playerX(plrX), playerY(plrY), - playerZ(plrZ) + playerZ(plrZ), + playerX0(plrX0), + playerY0(plrY0), + playerZ0(plrZ0), + playerX1(plrX1), + playerY1(plrY1), + playerZ1(plrZ1) {} - UseItemPacket(const ItemInstance* item, int entityId, const Vec3& aim, float plrX, float plrY, float plrZ) + UseItemPacket(const ItemInstance* item, int entityId, const Vec3& aim, float plrX, float plrY, float plrZ, + float plrX0, float plrY0, float plrZ0, float plrX1, float plrY1, float plrZ1) : face(255), itemId(item? item->id : 0), itemData(item? item->getAuxValue() : 0), @@ -47,7 +56,13 @@ public: z((int)(aim.z * 32768.0f)), playerX(plrX), playerY(plrY), - playerZ(plrZ) + playerZ(plrZ), + playerX0(plrX0), + playerY0(plrY0), + playerZ0(plrZ0), + playerX1(plrX1), + playerY1(plrY1), + playerZ1(plrZ1) { } @@ -68,6 +83,12 @@ public: bitStream->Write(playerX); bitStream->Write(playerY); bitStream->Write(playerZ); + bitStream->Write(playerX0); + bitStream->Write(playerY0); + bitStream->Write(playerZ0); + bitStream->Write(playerX1); + bitStream->Write(playerY1); + bitStream->Write(playerZ1); } void read(RakNet::BitStream* bitStream) @@ -88,6 +109,12 @@ public: bitStream->Read(playerX); bitStream->Read(playerY); bitStream->Read(playerZ); + bitStream->Read(playerX0); + bitStream->Read(playerY0); + bitStream->Read(playerZ0); + bitStream->Read(playerX1); + bitStream->Read(playerY1); + bitStream->Read(playerZ1); } void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback) From 4f21343e3bd34d4fbc01251af70607bf53b011b5 Mon Sep 17 00:00:00 2001 From: InviseDivine Date: Sat, 18 Jul 2026 21:01:13 +0200 Subject: [PATCH 56/59] release soon but we need to fix large world in mp --- .github/workflows/build.yml | 9 ++++++++- src/network/ClientSideNetworkHandler.cpp | 6 +++--- src/network/ServerSideNetworkHandler.cpp | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index eba5db7..c7593cd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -60,13 +60,14 @@ jobs: - name: Build working-directory: ${{github.workspace}}/build - run: cmake --build . --config $BUILD_TYPE --target MinecraftPE --parallel + run: cmake --build . --config $BUILD_TYPE --parallel - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: mcpe-windows path: | + ${{github.workspace}}/build/MinecraftPE-server.exe ${{github.workspace}}/build/MinecraftPE.exe ${{github.workspace}}/build/libpng16.dll ${{github.workspace}}/build/OpenAL32.dll @@ -298,6 +299,12 @@ jobs: with: files: mcpe-linux/MinecraftPE-server dest: minecraftpe-server-${{ steps.ref.outputs.hash }}.zip + + - name: Zip Windows Server Artifacts + uses: vimtor/action-zip@v1.2 + with: + files: mcpe-windows/MinecraftPE-server.exe + dest: minecraftpe-server-${{ steps.ref.outputs.hash }}.zip - name: Zip Android arm64-v8a Artifact uses: vimtor/action-zip@v1.2 diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index a5bb960..022b35f 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -223,7 +223,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SetTimeP if (!level) return; - LOGI("SetTimePacket\n"); + // LOGI("SetTimePacket\n"); level->setTime(packet->time); } @@ -279,7 +279,7 @@ void ClientSideNetworkHandler::handle( const RakNet::RakNetGUID& source, AddPain } void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AddMobPacket* packet) { - LOGI("AddMobPacket (%p)\n", level); + // LOGI("AddMobPacket (%p)\n", level); if (!level) { LOGW("Trying to add a mob with no level!\n"); @@ -385,7 +385,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AddItemE } void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, TakeItemEntityPacket* packet) { - printf("TakeItemEntityPacket \n"); + // printf("TakeItemEntityPacket \n"); if (!level) return; Entity* e = level->getEntity(packet->itemId); diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 2f3f237..474d9ad 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -368,7 +368,7 @@ void ServerSideNetworkHandler::onReady_ClientGeneration(const RakNet::RakNetGUID if (!minecraft->level->getLevelStorage()->loadPlayer(*newPlayer)) { LOGW("Failed to load %s data\n", newPlayer->name.c_str()); } - + // Credits to EpikIzCool bitStream.Reset(); MovePlayerPacket mv(newPlayer->entityId, newPlayer->x, newPlayer->y - newPlayer->heightOffset, From 8955b6ea47431c6222b044a834a28fa6ca85df8d Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Sat, 18 Jul 2026 22:31:15 +0300 Subject: [PATCH 57/59] ADD: server build for windows --- .github/workflows/build.yml | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c7593cd..ce3a9f9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -60,7 +60,9 @@ jobs: - name: Build working-directory: ${{github.workspace}}/build - run: cmake --build . --config $BUILD_TYPE --parallel + run: | + cmake --build . --config $BUILD_TYPE --target MinecraftPE --parallel + cmake --build . --config $BUILD_TYPE --target MinecraftPE-server --parallel - name: Upload Artifact uses: actions/upload-artifact@v4 @@ -287,6 +289,12 @@ jobs: with: files: mcpe-windows/MinecraftPE.exe mcpe-windows/libpng16.dll mcpe-windows/OpenAL32.dll mcpe-windows/libz.dll dest: minecraftpe-${{ steps.ref.outputs.hash }}-windows.zip + + - name: Zip Windows Server Artifacts + uses: vimtor/action-zip@v1.2 + with: + files: mcpe-windows/MinecraftPE-server.exe + dest: minecraftpe-server-${{ steps.ref.outputs.hash }}-windows.zip - name: Zip Linux Artifacts uses: vimtor/action-zip@v1.2 @@ -298,13 +306,7 @@ jobs: uses: vimtor/action-zip@v1.2 with: files: mcpe-linux/MinecraftPE-server - dest: minecraftpe-server-${{ steps.ref.outputs.hash }}.zip - - - name: Zip Windows Server Artifacts - uses: vimtor/action-zip@v1.2 - with: - files: mcpe-windows/MinecraftPE-server.exe - dest: minecraftpe-server-${{ steps.ref.outputs.hash }}.zip + dest: minecraftpe-server-${{ steps.ref.outputs.hash }}-linux.zip - name: Zip Android arm64-v8a Artifact uses: vimtor/action-zip@v1.2 @@ -343,8 +345,9 @@ jobs: files: | ./data.zip ./minecraftpe-${{ steps.ref.outputs.hash }}-windows.zip + ./minecraftpe-server-${{ steps.ref.outputs.hash }}-windows.zip ./minecraftpe-${{ steps.ref.outputs.hash }}-linux.zip - ./minecraftpe-server-${{ steps.ref.outputs.hash }}.zip + ./minecraftpe-server-${{ steps.ref.outputs.hash }}-linux.zip ./minecraftpe-${{ steps.ref.outputs.hash }}-android-arm64-v8a.zip ./minecraftpe-${{ steps.ref.outputs.hash }}-android-armeabi-v7a.zip ./minecraftpe-${{ steps.ref.outputs.hash }}-web.zip \ No newline at end of file From 3fcf3e34181601d57ea7b40bf19faf3656fe5e1b Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Sat, 18 Jul 2026 22:47:41 +0300 Subject: [PATCH 58/59] link WSA with server --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eab2ada..0d367ed 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ if (${PLATFORM} STREQUAL "Desktop") add_definitions(-D_CRT_SECURE_NO_WARNINGS) include_directories(misc/windows) set(EXTRA_LIBS ws2_32 winhttp) + set(SERVER_EXTRA_LIBS ws2_32) elseif(UNIX) find_library(pthread NAMES pthread) set(EXTRA_LIBS pthread m) @@ -310,7 +311,7 @@ target_include_directories("${PROJECT_NAME}-server" PUBLIC "project/lib_projects/raknet/jni/RaknetSources" ) -target_link_libraries("${PROJECT_NAME}-server" ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries("${PROJECT_NAME}-server" ${CMAKE_THREAD_LIBS_INIT} ${SERVER_EXTRA_LIBS}) add_executable(${PROJECT_NAME} ${CLIENT_SOURCES}) From e43da17d66e9140275487fa16b6e8d717646ba29 Mon Sep 17 00:00:00 2001 From: Kolyah35 Date: Sat, 18 Jul 2026 23:02:25 +0300 Subject: [PATCH 59/59] oh i didnt know --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d367ed..b60e6b5 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,7 +34,6 @@ if (${PLATFORM} STREQUAL "Desktop") add_definitions(-D_CRT_SECURE_NO_WARNINGS) include_directories(misc/windows) set(EXTRA_LIBS ws2_32 winhttp) - set(SERVER_EXTRA_LIBS ws2_32) elseif(UNIX) find_library(pthread NAMES pthread) set(EXTRA_LIBS pthread m) @@ -311,7 +310,7 @@ target_include_directories("${PROJECT_NAME}-server" PUBLIC "project/lib_projects/raknet/jni/RaknetSources" ) -target_link_libraries("${PROJECT_NAME}-server" ${CMAKE_THREAD_LIBS_INIT} ${SERVER_EXTRA_LIBS}) +target_link_libraries("${PROJECT_NAME}-server" ${CMAKE_THREAD_LIBS_INIT} ${EXTRA_LIBS}) add_executable(${PROJECT_NAME} ${CLIENT_SOURCES})