diff --git a/Minecraft.Client/ServerPlayer.cpp b/Minecraft.Client/ServerPlayer.cpp index 1ffbfdeaf..2ae8431ce 100644 --- a/Minecraft.Client/ServerPlayer.cpp +++ b/Minecraft.Client/ServerPlayer.cpp @@ -37,63 +37,147 @@ #include "..\Minecraft.Server\FourKitBridge.h" #include "..\Minecraft.World\ChatPacket.h" -// todo: rework this to use string localization funcs instead of hardcoded static std::wstring FormatDeathMessage(const shared_ptr& packet) { if (!packet) return L""; - const std::wstring& player = packet->m_stringArgs.size() > 0 ? packet->m_stringArgs[0] : L""; - const std::wstring& killer = packet->m_stringArgs.size() > 1 ? packet->m_stringArgs[1] : L""; - const std::wstring& item = packet->m_stringArgs.size() > 2 ? packet->m_stringArgs[2] : L""; + std::wstring message; + bool replacePlayer = false; + bool replaceEntitySource = false; + bool replaceItem = false; + // coug chough + // de hättn echt an gscheidern string konverter für de todesmeldungen macha soin + // a globaler helfer waar wahrscheinlich ganz bärig gwen + // waaaah switch (packet->m_messageType) { - case ChatPacket::e_ChatCustom: return player; - case ChatPacket::e_ChatDeathInFire: return player + L" went up in flames"; - case ChatPacket::e_ChatDeathOnFire: return player + L" burned to death"; - case ChatPacket::e_ChatDeathLava: return player + L" tried to swim in lava"; - case ChatPacket::e_ChatDeathInWall: return player + L" suffocated in a wall"; - case ChatPacket::e_ChatDeathDrown: return player + L" drowned"; - case ChatPacket::e_ChatDeathStarve: return player + L" starved to death"; - case ChatPacket::e_ChatDeathCactus: return player + L" was pricked to death"; - case ChatPacket::e_ChatDeathFall: return player + L" hit the ground too hard"; - case ChatPacket::e_ChatDeathOutOfWorld: return player + L" fell out of the world"; - case ChatPacket::e_ChatDeathGeneric: return player + L" died"; - case ChatPacket::e_ChatDeathExplosion: return player + L" blew up"; - case ChatPacket::e_ChatDeathMagic: return player + L" was killed by magic"; - case ChatPacket::e_ChatDeathWither: return player + L" withered away"; - case ChatPacket::e_ChatDeathDragonBreath: return player + L" was killed by Ender Dragon breath"; - case ChatPacket::e_ChatDeathAnvil: return player + L" was squashed by a falling Anvil."; - case ChatPacket::e_ChatDeathFallingBlock: return player + L" was squashed by a falling block."; - case ChatPacket::e_ChatDeathFellAccidentLadder: return player + L" fell off a ladder"; - case ChatPacket::e_ChatDeathFellAccidentVines: return player + L" fell off some vines"; - case ChatPacket::e_ChatDeathFellAccidentWater: return player + L" fell out of the water"; - case ChatPacket::e_ChatDeathFellAccidentGeneric:return player + L" fell from a high place"; - case ChatPacket::e_ChatDeathFellKiller: return player + L" was doomed to fall"; + case ChatPacket::e_ChatCustom: + return packet->m_stringArgs.size() > 0 ? packet->m_stringArgs[0] : L""; + case ChatPacket::e_ChatDeathInFire: + message = app.GetString(IDS_DEATH_INFIRE); replacePlayer = true; break; + case ChatPacket::e_ChatDeathOnFire: + message = app.GetString(IDS_DEATH_ONFIRE); replacePlayer = true; break; + case ChatPacket::e_ChatDeathLava: + message = app.GetString(IDS_DEATH_LAVA); replacePlayer = true; break; + case ChatPacket::e_ChatDeathInWall: + message = app.GetString(IDS_DEATH_INWALL); replacePlayer = true; break; + case ChatPacket::e_ChatDeathDrown: + message = app.GetString(IDS_DEATH_DROWN); replacePlayer = true; break; + case ChatPacket::e_ChatDeathStarve: + message = app.GetString(IDS_DEATH_STARVE); replacePlayer = true; break; + case ChatPacket::e_ChatDeathCactus: + message = app.GetString(IDS_DEATH_CACTUS); replacePlayer = true; break; + case ChatPacket::e_ChatDeathFall: + message = app.GetString(IDS_DEATH_FALL); replacePlayer = true; break; + case ChatPacket::e_ChatDeathOutOfWorld: + message = app.GetString(IDS_DEATH_OUTOFWORLD); replacePlayer = true; break; + case ChatPacket::e_ChatDeathGeneric: + message = app.GetString(IDS_DEATH_GENERIC); replacePlayer = true; break; + case ChatPacket::e_ChatDeathExplosion: + message = app.GetString(IDS_DEATH_EXPLOSION); replacePlayer = true; break; + case ChatPacket::e_ChatDeathMagic: + message = app.GetString(IDS_DEATH_MAGIC); replacePlayer = true; break; + case ChatPacket::e_ChatDeathWither: + message = app.GetString(IDS_DEATH_WITHER); replacePlayer = true; break; + case ChatPacket::e_ChatDeathDragonBreath: + message = app.GetString(IDS_DEATH_DRAGON_BREATH); replacePlayer = true; break; + case ChatPacket::e_ChatDeathAnvil: + message = app.GetString(IDS_DEATH_FALLING_ANVIL); replacePlayer = true; break; + case ChatPacket::e_ChatDeathFallingBlock: + message = app.GetString(IDS_DEATH_FALLING_TILE); replacePlayer = true; break; + case ChatPacket::e_ChatDeathFellAccidentLadder: + message = app.GetString(IDS_DEATH_FELL_ACCIDENT_LADDER); replacePlayer = true; break; + case ChatPacket::e_ChatDeathFellAccidentVines: + message = app.GetString(IDS_DEATH_FELL_ACCIDENT_VINES); replacePlayer = true; break; + case ChatPacket::e_ChatDeathFellAccidentWater: + message = app.GetString(IDS_DEATH_FELL_ACCIDENT_WATER); replacePlayer = true; break; + case ChatPacket::e_ChatDeathFellAccidentGeneric: + message = app.GetString(IDS_DEATH_FELL_ACCIDENT_GENERIC); replacePlayer = true; break; + case ChatPacket::e_ChatDeathFellKiller: + message = app.GetString(IDS_DEATH_FALL); replacePlayer = true; break; case ChatPacket::e_ChatDeathMob: - case ChatPacket::e_ChatDeathPlayer: return killer.empty() ? player + L" was slain" : player + L" was slain by " + killer; - case ChatPacket::e_ChatDeathArrow: return killer.empty() ? player + L" was shot" : player + L" was shot by " + killer; - case ChatPacket::e_ChatDeathFireball: return killer.empty() ? player + L" was fireballed" : player + L" was fireballed by " + killer; - case ChatPacket::e_ChatDeathThrown: return killer.empty() ? player + L" was pummeled" : player + L" was pummeled by " + killer; - case ChatPacket::e_ChatDeathIndirectMagic: return killer.empty() ? player + L" was killed by magic" : player + L" was killed by " + killer + L" using magic"; - case ChatPacket::e_ChatDeathThorns: return killer.empty() ? player + L" died" : player + L" was killed trying to hurt " + killer; - case ChatPacket::e_ChatDeathExplosionPlayer: return killer.empty() ? player + L" blew up" : player + L" was blown up by " + killer; - case ChatPacket::e_ChatDeathInFirePlayer: return killer.empty() ? player + L" went up in flames" : player + L" walked into fire whilst fighting " + killer; - case ChatPacket::e_ChatDeathOnFirePlayer: return killer.empty() ? player + L" burned to death" : player + L" was burnt to a crisp whilst fighting " + killer; - case ChatPacket::e_ChatDeathLavaPlayer: return killer.empty() ? player + L" tried to swim in lava" : player + L" tried to swim in lava to escape " + killer; - case ChatPacket::e_ChatDeathDrownPlayer: return killer.empty() ? player + L" drowned" : player + L" drowned whilst trying to escape " + killer; - case ChatPacket::e_ChatDeathCactusPlayer: return killer.empty() ? player + L" was pricked to death" : player + L" walked into a cactus whilst trying to escape " + killer; - case ChatPacket::e_ChatDeathFellAssist: return killer.empty() ? player + L" was doomed to fall" : player + L" was doomed to fall by " + killer; - case ChatPacket::e_ChatDeathFellFinish: return killer.empty() ? player + L" fell too far" : player + L" fell too far and was finished by " + killer; - case ChatPacket::e_ChatDeathPlayerItem: return (killer.empty() ? player + L" was slain" : player + L" was slain by " + killer) + (item.empty() ? L"" : L" using " + item); - case ChatPacket::e_ChatDeathArrowItem: return (killer.empty() ? player + L" was shot" : player + L" was shot by " + killer) + (item.empty() ? L"" : L" with " + item); - case ChatPacket::e_ChatDeathFireballItem: return (killer.empty() ? player + L" was fireballed" : player + L" was fireballed by " + killer) + (item.empty() ? L"" : L" with " + item); - case ChatPacket::e_ChatDeathThrownItem: return (killer.empty() ? player + L" was pummeled" : player + L" was pummeled by " + killer) + (item.empty() ? L"" : L" using " + item); - case ChatPacket::e_ChatDeathIndirectMagicItem: return (killer.empty() ? player + L" was killed by magic" : player + L" was killed by " + killer) + (item.empty() ? L"" : L" using " + item); - case ChatPacket::e_ChatDeathFellAssistItem: return (killer.empty() ? player + L" was doomed to fall" : player + L" was doomed to fall by " + killer) + (item.empty() ? L"" : L" using " + item); - case ChatPacket::e_ChatDeathFellFinishItem: return (killer.empty() ? player + L" fell too far" : player + L" fell too far and was finished by " + killer) + (item.empty() ? L"" : L" using " + item); - default: return player + L" died"; + message = app.GetString(IDS_DEATH_MOB); replacePlayer = true; replaceEntitySource = true; break; + case ChatPacket::e_ChatDeathPlayer: + message = app.GetString(IDS_DEATH_PLAYER); replacePlayer = true; replaceEntitySource = true; break; + case ChatPacket::e_ChatDeathArrow: + message = app.GetString(IDS_DEATH_ARROW); replacePlayer = true; replaceEntitySource = true; break; + case ChatPacket::e_ChatDeathFireball: + message = app.GetString(IDS_DEATH_FIREBALL); replacePlayer = true; replaceEntitySource = true; break; + case ChatPacket::e_ChatDeathThrown: + message = app.GetString(IDS_DEATH_THROWN); replacePlayer = true; replaceEntitySource = true; break; + case ChatPacket::e_ChatDeathIndirectMagic: + message = app.GetString(IDS_DEATH_INDIRECT_MAGIC); replacePlayer = true; replaceEntitySource = true; break; + case ChatPacket::e_ChatDeathThorns: + message = app.GetString(IDS_DEATH_THORNS); replacePlayer = true; replaceEntitySource = true; break; + case ChatPacket::e_ChatDeathExplosionPlayer: + message = app.GetString(IDS_DEATH_EXPLOSION_PLAYER); replacePlayer = true; replaceEntitySource = true; break; + case ChatPacket::e_ChatDeathInFirePlayer: + message = app.GetString(IDS_DEATH_INFIRE_PLAYER); replacePlayer = true; replaceEntitySource = true; break; + case ChatPacket::e_ChatDeathOnFirePlayer: + message = app.GetString(IDS_DEATH_ONFIRE_PLAYER); replacePlayer = true; replaceEntitySource = true; break; + case ChatPacket::e_ChatDeathLavaPlayer: + message = app.GetString(IDS_DEATH_LAVA_PLAYER); replacePlayer = true; replaceEntitySource = true; break; + case ChatPacket::e_ChatDeathDrownPlayer: + message = app.GetString(IDS_DEATH_DROWN_PLAYER); replacePlayer = true; replaceEntitySource = true; break; + case ChatPacket::e_ChatDeathCactusPlayer: + message = app.GetString(IDS_DEATH_CACTUS_PLAYER); replacePlayer = true; replaceEntitySource = true; break; + case ChatPacket::e_ChatDeathFellAssist: + message = app.GetString(IDS_DEATH_FELL_ASSIST); replacePlayer = true; replaceEntitySource = true; break; + case ChatPacket::e_ChatDeathFellFinish: + message = app.GetString(IDS_DEATH_FELL_FINISH); replacePlayer = true; replaceEntitySource = true; break; + case ChatPacket::e_ChatDeathPlayerItem: + message = app.GetString(IDS_DEATH_PLAYER_ITEM); replacePlayer = true; replaceEntitySource = true; replaceItem = true; break; + case ChatPacket::e_ChatDeathArrowItem: + message = app.GetString(IDS_DEATH_ARROW_ITEM); replacePlayer = true; replaceEntitySource = true; replaceItem = true; break; + case ChatPacket::e_ChatDeathFireballItem: + message = app.GetString(IDS_DEATH_FIREBALL_ITEM); replacePlayer = true; replaceEntitySource = true; replaceItem = true; break; + case ChatPacket::e_ChatDeathThrownItem: + message = app.GetString(IDS_DEATH_THROWN_ITEM); replacePlayer = true; replaceEntitySource = true; replaceItem = true; break; + case ChatPacket::e_ChatDeathIndirectMagicItem: + message = app.GetString(IDS_DEATH_INDIRECT_MAGIC_ITEM); replacePlayer = true; replaceEntitySource = true; replaceItem = true; break; + case ChatPacket::e_ChatDeathFellAssistItem: + message = app.GetString(IDS_DEATH_FELL_ASSIST_ITEM); replacePlayer = true; replaceEntitySource = true; replaceItem = true; break; + case ChatPacket::e_ChatDeathFellFinishItem: + message = app.GetString(IDS_DEATH_FELL_FINISH_ITEM); replacePlayer = true; replaceEntitySource = true; replaceItem = true; break; + default: + message = app.GetString(IDS_DEATH_GENERIC); replacePlayer = true; break; } + + if (replacePlayer) + { + std::wstring playerName = packet->m_stringArgs.size() > 0 ? packet->m_stringArgs[0] : L""; + message = replaceAll(message, L"{*PLAYER*}", playerName); + } + + if (replaceEntitySource) + { + std::wstring sourceName; + if (!packet->m_intArgs.empty() && packet->m_intArgs[0] == eTYPE_SERVERPLAYER) + { + sourceName = packet->m_stringArgs.size() > 1 ? packet->m_stringArgs[1] : L""; + } + else + { + if (packet->m_stringArgs.size() > 1 && !packet->m_stringArgs[1].empty()) + { + sourceName = packet->m_stringArgs[1]; + } + else if (!packet->m_intArgs.empty()) + { + sourceName = app.getEntityName((eINSTANCEOF)packet->m_intArgs[0]); + } + } + message = replaceAll(message, L"{*SOURCE*}", sourceName); + } + + if (replaceItem) + { + std::wstring itemName = packet->m_stringArgs.size() > 2 ? packet->m_stringArgs[2] : L""; + message = replaceAll(message, L"{*ITEM*}", itemName); + } + + return message; } #endif diff --git a/Minecraft.Server.FourKit/Block/Block.cs b/Minecraft.Server.FourKit/Block/Block.cs index ab8d1af31..022b9b616 100644 --- a/Minecraft.Server.FourKit/Block/Block.cs +++ b/Minecraft.Server.FourKit/Block/Block.cs @@ -93,6 +93,15 @@ public class Block return true; } + /// + /// Gets the metadata value for this block. + /// + /// Block specific metadata. + public byte getData() + { + return (byte)NativeBridge.GetTileData(_world.getDimensionId(), _x, _y, _z); + } + /// /// Sets the metadata value for this block. /// diff --git a/Minecraft.Server.FourKit/FourKitHost.cs b/Minecraft.Server.FourKit/FourKitHost.cs index cd0751f33..8293af672 100644 --- a/Minecraft.Server.FourKit/FourKitHost.cs +++ b/Minecraft.Server.FourKit/FourKitHost.cs @@ -553,11 +553,11 @@ public static class FourKitHost } [UnmanagedCallersOnly] - public static void SetWorldCallbacks(IntPtr getTileId, IntPtr setTile, IntPtr setTileData, IntPtr breakBlock, IntPtr getHighestBlockY, IntPtr getWorldInfo, IntPtr setWorldTime, IntPtr setWeather, IntPtr createExplosion, IntPtr strikeLightning, IntPtr setSpawnLocation, IntPtr dropItem) + public static void SetWorldCallbacks(IntPtr getTileId, IntPtr getTileData, IntPtr setTile, IntPtr setTileData, IntPtr breakBlock, IntPtr getHighestBlockY, IntPtr getWorldInfo, IntPtr setWorldTime, IntPtr setWeather, IntPtr createExplosion, IntPtr strikeLightning, IntPtr setSpawnLocation, IntPtr dropItem) { try { - NativeBridge.SetWorldCallbacks(getTileId, setTile, setTileData, breakBlock, getHighestBlockY, getWorldInfo, setWorldTime, setWeather, createExplosion, strikeLightning, setSpawnLocation, dropItem); + NativeBridge.SetWorldCallbacks(getTileId, getTileData, setTile, setTileData, breakBlock, getHighestBlockY, getWorldInfo, setWorldTime, setWeather, createExplosion, strikeLightning, setSpawnLocation, dropItem); //ServerLog.Info("fourkit", "World native callbacks registered."); } catch (Exception ex) diff --git a/Minecraft.Server.FourKit/NativeBridge.cs b/Minecraft.Server.FourKit/NativeBridge.cs index f85b21c83..8dee54294 100644 --- a/Minecraft.Server.FourKit/NativeBridge.cs +++ b/Minecraft.Server.FourKit/NativeBridge.cs @@ -39,6 +39,9 @@ internal static class NativeBridge [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int NativeGetTileIdDelegate(int dimId, int x, int y, int z); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate int NativeGetTileDataDelegate(int dimId, int x, int y, int z); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate void NativeSetTileDelegate(int dimId, int x, int y, int z, int tileId, int data); @@ -118,6 +121,7 @@ internal static class NativeBridge internal static NativeTeleportEntityDelegate? TeleportEntity; internal static NativeGetTileIdDelegate? GetTileId; + internal static NativeGetTileDataDelegate? GetTileData; internal static NativeSetTileDelegate? SetTile; internal static NativeSetTileDataDelegate? SetTileData; internal static NativeBreakBlockDelegate? BreakBlock; @@ -155,9 +159,10 @@ internal static class NativeBridge TeleportEntity = Marshal.GetDelegateForFunctionPointer(teleportEntity); } - internal static void SetWorldCallbacks(IntPtr getTileId, IntPtr setTile, IntPtr setTileData, IntPtr breakBlock, IntPtr getHighestBlockY, IntPtr getWorldInfo, IntPtr setWorldTime, IntPtr setWeather, IntPtr createExplosion, IntPtr strikeLightning, IntPtr setSpawnLocation, IntPtr dropItem) + internal static void SetWorldCallbacks(IntPtr getTileId, IntPtr getTileData, IntPtr setTile, IntPtr setTileData, IntPtr breakBlock, IntPtr getHighestBlockY, IntPtr getWorldInfo, IntPtr setWorldTime, IntPtr setWeather, IntPtr createExplosion, IntPtr strikeLightning, IntPtr setSpawnLocation, IntPtr dropItem) { GetTileId = Marshal.GetDelegateForFunctionPointer(getTileId); + GetTileData = Marshal.GetDelegateForFunctionPointer(getTileData); SetTile = Marshal.GetDelegateForFunctionPointer(setTile); SetTileData = Marshal.GetDelegateForFunctionPointer(setTileData); BreakBlock = Marshal.GetDelegateForFunctionPointer(breakBlock); diff --git a/Minecraft.Server/FourKitBridge.cpp b/Minecraft.Server/FourKitBridge.cpp index d4d74917a..10ad4b067 100644 --- a/Minecraft.Server/FourKitBridge.cpp +++ b/Minecraft.Server/FourKitBridge.cpp @@ -112,7 +112,7 @@ typedef int(__stdcall *fn_fire_player_move)(int entityId, double toX, double toY, double toZ, double *outCoords); typedef void(__stdcall *fn_set_native_callbacks)(void *damage, void *setHealth, void *teleport, void *setGameMode, void *broadcastMessage, void *setFallDistance, void *getPlayerSnapshot, void *sendMessage, void *setWalkSpeed, void *teleportEntity); -typedef void(__stdcall *fn_set_world_callbacks)(void *getTileId, void *setTile, void *setTileData, void *breakBlock, void *getHighestBlockY, void *getWorldInfo, void *setWorldTime, void *setWeather, void *createExplosion, void *strikeLightning, void *setSpawnLocation, void *dropItem); +typedef void(__stdcall *fn_set_world_callbacks)(void *getTileId, void *getTileData, void *setTile, void *setTileData, void *breakBlock, void *getHighestBlockY, void *getWorldInfo, void *setWorldTime, void *setWeather, void *createExplosion, void *strikeLightning, void *setSpawnLocation, void *dropItem); typedef void(__stdcall *fn_update_entity_id)(int oldEntityId, int newEntityId); typedef int(__stdcall *fn_fire_player_chat)(int entityId, const char *msgUtf8, int msgByteLen, char *outBuf, int outBufSize, int *outLen); typedef int(__stdcall *fn_fire_block_place)(int entityId, int dimId, @@ -448,6 +448,16 @@ static void __cdecl NativeSetTile(int dimId, int x, int y, int z, int tileId, in level->setTileAndData(x, y, z, tileId, data, Tile::UPDATE_ALL); } +static int __cdecl NativeGetTileData(int dimId, int x, int y, int z) +{ + ServerLevel *level = GetLevel(dimId); + if (!level) + { + return 0; + } + return level->getData(x, y, z); +} + static void __cdecl NativeSetTileData(int dimId, int x, int y, int z, int data) { ServerLevel *level = GetLevel(dimId); @@ -1318,6 +1328,7 @@ void Initialize() s_managedSetWorldCallbacks( (void *)&NativeGetTileId, + (void *)&NativeGetTileData, (void *)&NativeSetTile, (void *)&NativeSetTileData, (void *)&NativeBreakBlock, diff --git a/Minecraft.Server/FourKitBridge.h b/Minecraft.Server/FourKitBridge.h index ecd268e5e..8fd62737d 100644 --- a/Minecraft.Server/FourKitBridge.h +++ b/Minecraft.Server/FourKitBridge.h @@ -19,6 +19,7 @@ namespace FourKitBridge void UpdatePlayerEntityId(int oldEntityId, int newEntityId); int GetTileId(int dimId, int x, int y, int z); + int GetTileData(int dimId, int x, int y, int z); void SetTile(int dimId, int x, int y, int z, int tileId, int data); void SetTileData(int dimId, int x, int y, int z, int data); int BreakBlock(int dimId, int x, int y, int z);