From 08f3aeff5f838fbc25e39fd0d6a62b9b9ad8a733 Mon Sep 17 00:00:00 2001 From: sylvessa <225480449+sylvessa@users.noreply.github.com> Date: Mon, 13 Apr 2026 20:55:02 -0500 Subject: [PATCH] fill in old stubs regaridng chunk stuff & another inv fix --- Minecraft.Client/ServerChunkCache.cpp | 32 +++++++++++ Minecraft.Client/ServerChunkCache.h | 3 + Minecraft.Server.FourKit/Chunk/Chunk.cs | 53 ++++++++++++++++- .../FourKitHost.Callbacks.cs | 4 +- .../Inventory/Inventory.cs | 4 +- Minecraft.Server.FourKit/NativeBridge.cs | 7 ++- Minecraft.Server/FourKitBridge.cpp | 5 +- Minecraft.Server/FourKitNatives.cpp | 57 ++++++++++++++++++- Minecraft.Server/FourKitNatives.h | 1 + Minecraft.Server/cmake/sources/Common.cmake | 1 + 10 files changed, 158 insertions(+), 9 deletions(-) diff --git a/Minecraft.Client/ServerChunkCache.cpp b/Minecraft.Client/ServerChunkCache.cpp index c9292a207..e7369bff2 100644 --- a/Minecraft.Client/ServerChunkCache.cpp +++ b/Minecraft.Client/ServerChunkCache.cpp @@ -388,6 +388,38 @@ void ServerChunkCache::overwriteHellLevelChunkFromSource(int x, int z, int minVa #endif +#ifdef MINECRAFT_SERVER_BUILD +void ServerChunkCache::regenerateChunk(int x, int z) +{ + if (!source) + return; + + LevelChunk *freshChunk = source->getChunk(x, z); + if (!freshChunk) + return; + + LevelChunk *cachedChunk = nullptr; + if (hasChunk(x, z)) + cachedChunk = getChunk(x, z); + + if (cachedChunk && cachedChunk != emptyChunk) + { + for (int lx = 0; lx < 16; lx++) + for (int ly = 0; ly < 128; ly++) + for (int lz = 0; lz < 16; lz++) + cachedChunk->setTileAndData(lx, ly, lz, freshChunk->getTile(lx, ly, lz), freshChunk->getData(lx, ly, lz)); + save(cachedChunk); + } + else + { + save(freshChunk); + } + + freshChunk->unload(false); + delete freshChunk; +} +#endif + // 4J Added // #ifdef _LARGE_WORLDS void ServerChunkCache::dontDrop(int x, int z) diff --git a/Minecraft.Client/ServerChunkCache.h b/Minecraft.Client/ServerChunkCache.h index cf93fdc55..fd559d543 100644 --- a/Minecraft.Client/ServerChunkCache.h +++ b/Minecraft.Client/ServerChunkCache.h @@ -53,6 +53,9 @@ public: #endif virtual LevelChunk **getCache() { return cache; } // 4J added +#ifdef MINECRAFT_SERVER_BUILD + void regenerateChunk(int x, int z); +#endif // 4J-JEV Added; Remove chunk from the toDrop queue. #ifdef _LARGE_WORLDS diff --git a/Minecraft.Server.FourKit/Chunk/Chunk.cs b/Minecraft.Server.FourKit/Chunk/Chunk.cs index 4824cc609..32e1f0aae 100644 --- a/Minecraft.Server.FourKit/Chunk/Chunk.cs +++ b/Minecraft.Server.FourKit/Chunk/Chunk.cs @@ -191,7 +191,58 @@ public class Chunk /// The entities. public Entity.Entity[] getEntities() { - return Array.Empty(); + if (NativeBridge.GetChunkEntities == null) return Array.Empty(); + + int dimId = _world.getDimensionId(); + int count = NativeBridge.GetChunkEntities(dimId, _chunkX, _chunkZ, out IntPtr buf); + if (count <= 0 || buf == IntPtr.Zero) return Array.Empty(); + + var result = new Entity.Entity[count]; + try + { + int[] data = new int[count * 3]; + Marshal.Copy(buf, data, 0, count * 3); + + for (int i = 0; i < count; i++) + { + int entityId = data[i * 3]; + int mappedType = data[i * 3 + 1]; + int isLiving = data[i * 3 + 2]; + + var entityType = Enum.IsDefined(typeof(Entity.EntityType), mappedType) + ? (Entity.EntityType)mappedType + : Entity.EntityType.UNKNOWN; + + if (entityType == Entity.EntityType.PLAYER) + { + var player = FourKit.GetPlayerByEntityId(entityId); + if (player != null) + { + result[i] = player; + continue; + } + } + + if (isLiving == 1) + { + result[i] = new Entity.LivingEntity(entityId, entityType, dimId, 0, 0, 0); + } + else + { + var entity = new Entity.Entity(); + entity.SetEntityIdInternal(entityId); + entity.SetEntityTypeInternal(entityType); + entity.SetDimensionInternal(dimId); + result[i] = entity; + } + } + } + finally + { + Marshal.FreeCoTaskMem(buf); + } + + return result; } /// diff --git a/Minecraft.Server.FourKit/FourKitHost.Callbacks.cs b/Minecraft.Server.FourKit/FourKitHost.Callbacks.cs index 5c2f4230b..575c2e001 100644 --- a/Minecraft.Server.FourKit/FourKitHost.Callbacks.cs +++ b/Minecraft.Server.FourKit/FourKitHost.Callbacks.cs @@ -149,11 +149,11 @@ public static partial class FourKitHost } [UnmanagedCallersOnly] - public static void SetWorldEntityCallbacks(IntPtr getWorldEntities) + public static void SetWorldEntityCallbacks(IntPtr getWorldEntities, IntPtr getChunkEntities) { try { - NativeBridge.SetWorldEntityCallbacks(getWorldEntities); + NativeBridge.SetWorldEntityCallbacks(getWorldEntities, getChunkEntities); } catch (Exception ex) { diff --git a/Minecraft.Server.FourKit/Inventory/Inventory.cs b/Minecraft.Server.FourKit/Inventory/Inventory.cs index 52fda5fc1..ad5b188e2 100644 --- a/Minecraft.Server.FourKit/Inventory/Inventory.cs +++ b/Minecraft.Server.FourKit/Inventory/Inventory.cs @@ -174,7 +174,9 @@ public class Inventory : IEnumerable if (_items[slot] == null) { int added = Math.Min(64, remaining); - setItem(slot, new ItemStack(toAdd.getType(), added, toAdd.getDurability())); + var newItem = new ItemStack(toAdd.getType(), added, toAdd.getDurability()); + newItem.setItemMetaInternal(toAdd.getItemMetaInternal()?.clone()); + setItem(slot, newItem); remaining -= added; } } diff --git a/Minecraft.Server.FourKit/NativeBridge.cs b/Minecraft.Server.FourKit/NativeBridge.cs index 765c69895..753cf898b 100644 --- a/Minecraft.Server.FourKit/NativeBridge.cs +++ b/Minecraft.Server.FourKit/NativeBridge.cs @@ -222,6 +222,9 @@ internal static class NativeBridge [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int NativeGetWorldEntitiesDelegate(int dimId, out IntPtr outBuf); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate int NativeGetChunkEntitiesDelegate(int dimId, int chunkX, int chunkZ, out IntPtr outBuf); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int NativeGetSkyLightDelegate(int dimId, int x, int y, int z); @@ -306,6 +309,7 @@ internal static class NativeBridge internal static NativeRegenerateChunkDelegate? RegenerateChunk; internal static NativeRefreshChunkDelegate? RefreshChunk; internal static NativeGetWorldEntitiesDelegate? GetWorldEntities; + internal static NativeGetChunkEntitiesDelegate? GetChunkEntities; internal static NativeGetSkyLightDelegate? GetSkyLight; internal static NativeGetBlockLightDelegate? GetBlockLight; internal static NativeGetBiomeIdDelegate? GetBiomeId; @@ -422,9 +426,10 @@ internal static class NativeBridge RefreshChunk = Marshal.GetDelegateForFunctionPointer(refreshChunk); } - internal static void SetWorldEntityCallbacks(IntPtr getWorldEntities) + internal static void SetWorldEntityCallbacks(IntPtr getWorldEntities, IntPtr getChunkEntities) { GetWorldEntities = Marshal.GetDelegateForFunctionPointer(getWorldEntities); + GetChunkEntities = Marshal.GetDelegateForFunctionPointer(getChunkEntities); } internal static void SetBlockInfoCallbacks(IntPtr getSkyLight, IntPtr getBlockLight, IntPtr getBiomeId, IntPtr setBiomeId) diff --git a/Minecraft.Server/FourKitBridge.cpp b/Minecraft.Server/FourKitBridge.cpp index 3bf9b96fa..e7f64cd19 100644 --- a/Minecraft.Server/FourKitBridge.cpp +++ b/Minecraft.Server/FourKitBridge.cpp @@ -105,7 +105,7 @@ typedef int(__stdcall *fn_fire_command_preprocess)(int entityId, const char *cmd typedef int(__stdcall *fn_fire_block_from_to)(int dimId, int fromX, int fromY, int fromZ, int toX, int toY, int toZ, int face); typedef void(__stdcall *fn_set_chunk_callbacks)(void *isChunkLoaded, void *loadChunk, void *unloadChunk, void *getLoadedChunks, void *isChunkInUse, void *getChunkSnapshot, void *unloadChunkRequest, void *regenerateChunk, void *refreshChunk); typedef void(__stdcall *fn_set_block_info_callbacks)(void *getSkyLight, void *getBlockLight, void *getBiomeId, void *setBiomeId); -typedef void(__stdcall *fn_set_world_entity_callbacks)(void *getWorldEntities); +typedef void(__stdcall *fn_set_world_entity_callbacks)(void *getWorldEntities, void *getChunkEntities); typedef void(__stdcall *fn_fire_chunk_load)(int dimId, int chunkX, int chunkZ, int isNewChunk); typedef int(__stdcall *fn_fire_chunk_unload)(int dimId, int chunkX, int chunkZ); @@ -369,7 +369,8 @@ void Initialize() (void *)&NativeSetBiomeId); s_managedSetWorldEntityCallbacks( - (void *)&NativeGetWorldEntities); + (void *)&NativeGetWorldEntities, + (void *)&NativeGetChunkEntities); LogInfo("fourkit", "FourKit initialized successfully."); } diff --git a/Minecraft.Server/FourKitNatives.cpp b/Minecraft.Server/FourKitNatives.cpp index 0c33df515..1c522f40b 100644 --- a/Minecraft.Server/FourKitNatives.cpp +++ b/Minecraft.Server/FourKitNatives.cpp @@ -33,6 +33,7 @@ #include "..\Minecraft.World\Player.h" #include "..\Minecraft.World\PlayerAbilitiesPacket.h" #include "..\Minecraft.World\SetCarriedItemPacket.h" +#include "..\Minecraft.World\BlockRegionUpdatePacket.h" #include "..\Minecraft.World\SetExperiencePacket.h" #include "..\Minecraft.World\SetHealthPacket.h" #include "..\Minecraft.World\LevelSoundPacket.h" @@ -1363,6 +1364,39 @@ int __cdecl NativeGetWorldEntities(int dimId, int **outBuf) return count; } +int __cdecl NativeGetChunkEntities(int dimId, int chunkX, int chunkZ, int **outBuf) +{ + *outBuf = nullptr; + ServerLevel *level = GetLevel(dimId); + if (!level) + return 0; + + EnterCriticalSection(&level->m_entitiesCS); + int total = (int)level->entities.size(); + int *buf = (int *)CoTaskMemAlloc(total * 3 * sizeof(int)); + int count = 0; + if (buf) + { + for (auto &entity : level->entities) + { + if (!entity) + continue; + int ecx = Mth::floor(entity->x / 16.0); + int ecz = Mth::floor(entity->z / 16.0); + if (ecx != chunkX || ecz != chunkZ) + continue; + int idx = count * 3; + buf[idx] = entity->entityId; + buf[idx + 1] = MapEntityType((int)entity->GetType()); + buf[idx + 2] = entity->instanceof(eTYPE_LIVINGENTITY) ? 1 : 0; + count++; + } + } + LeaveCriticalSection(&level->m_entitiesCS); + *outBuf = buf; + return count; +} + int __cdecl NativeIsChunkLoaded(int dimId, int chunkX, int chunkZ) { ServerLevel *level = GetLevel(dimId); @@ -1513,12 +1547,31 @@ int __cdecl NativeUnloadChunkRequest(int dimId, int chunkX, int chunkZ, int safe int __cdecl NativeRegenerateChunk(int dimId, int chunkX, int chunkZ) { - return 0; + ServerLevel *level = GetLevel(dimId); + if (!level || !level->cache) + return 0; + level->cache->regenerateChunk(chunkX, chunkZ); + return 1; } int __cdecl NativeRefreshChunk(int dimId, int chunkX, int chunkZ) { - return 0; + ServerLevel *level = GetLevel(dimId); + if (!level) + return 0; + + PlayerList *list = MinecraftServer::getPlayerList(); + if (!list) + return 0; + + auto packet = std::make_shared(chunkX * 16, 0, chunkZ * 16, 16, Level::maxBuildHeight, 16, level); + for (auto &p : list->players) + { + if (!p || p->dimension != dimId || !p->connection || p->connection->isLocal()) + continue; + p->connection->send(packet); + } + return 1; } int __cdecl NativeGetSkyLight(int dimId, int x, int y, int z) diff --git a/Minecraft.Server/FourKitNatives.h b/Minecraft.Server/FourKitNatives.h index 31f67bd9b..fb1050343 100644 --- a/Minecraft.Server/FourKitNatives.h +++ b/Minecraft.Server/FourKitNatives.h @@ -98,6 +98,7 @@ namespace FourKitBridge // world entity bs int __cdecl NativeGetWorldEntities(int dimId, int **outBuf); + int __cdecl NativeGetChunkEntities(int dimId, int chunkX, int chunkZ, int **outBuf); // block info (light, biome) int __cdecl NativeGetSkyLight(int dimId, int x, int y, int z); diff --git a/Minecraft.Server/cmake/sources/Common.cmake b/Minecraft.Server/cmake/sources/Common.cmake index 031ab0548..bbb7de22f 100644 --- a/Minecraft.Server/cmake/sources/Common.cmake +++ b/Minecraft.Server/cmake/sources/Common.cmake @@ -394,6 +394,7 @@ set(_MINECRAFT_SERVER_COMMON_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/ScrolledSelectionList.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/SelectWorldScreen.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/ServerChunkCache.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/ServerChunkCache.h" "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/ServerCommandDispatcher.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/ServerConnection.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/ServerLevel.cpp"