diff --git a/Minecraft.Client/MinecraftServer.cpp b/Minecraft.Client/MinecraftServer.cpp index bdcc9f813..ea8f073fe 100644 --- a/Minecraft.Client/MinecraftServer.cpp +++ b/Minecraft.Client/MinecraftServer.cpp @@ -196,7 +196,7 @@ static bool ExecuteConsoleCommand(MinecraftServer *server, const wstring &rawCom if (action == L"help" || action == L"?") { - server->info(L"Commands: help, stop, list, say , save-all, time , weather [seconds], tp , give [amount] [aux], enchant [level], kill "); + server->info(L"Commands: help, stop, list, say , save-all, time , weather [seconds], tp , give [amount] [aux], enchant [level], kill , summon [dimension]"); return true; } @@ -538,6 +538,135 @@ static bool ExecuteConsoleCommand(MinecraftServer *server, const wstring &rawCom return true; } + if (action == L"summon") + { + if (tokens.size() < 4) + { + server->warn(L"Usage: summon [dimension]"); + server->warn(L"Dimensions: 0=Overworld, -1=Nether, 1=End"); + return false; + } + + wstring entityType = tokens[1]; + int x = 0, y = 0, z = 0; + int dimension = 0; + + if (!TryParseIntValue(tokens[2], x) || !TryParseIntValue(tokens[3], y) || !TryParseIntValue(tokens[4], z)) + { + server->warn(L"Invalid coordinates. Usage: summon "); + return false; + } + + if (tokens.size() >= 5) + { + if (!TryParseIntValue(tokens[5], dimension)) + { + server->warn(L"Invalid dimension. Use: 0=Overworld, -1=Nether, 1=End"); + return false; + } + + if (dimension != 0 && dimension != -1 && dimension != 1) + { + server->warn(L"Invalid dimension. Use: 0=Overworld, -1=Nether, 1=End"); + return false; + } + } + ServerLevel* level = server->getLevel(dimension); + if (level == NULL) + { + server->warn(L"Could not access level"); + return false; + } + + int entityId = -1; + wchar_t* endptr; + long numId = wcstol(entityType.c_str(), &endptr, 10); + if (*endptr == L'\0') + { + entityId = (int)numId; + } + else + { + if (entityType == L"creeper") entityId = 50; + else if (entityType == L"skeleton") entityId = 51; + else if (entityType == L"spider") entityId = 52; + else if (entityType == L"giant") entityId = 53; + else if (entityType == L"zombie") entityId = 54; + else if (entityType == L"slime") entityId = 55; + else if (entityType == L"ghast") entityId = 56; + else if (entityType == L"pigzombie") entityId = 57; + else if (entityType == L"enderman") entityId = 58; + else if (entityType == L"cavespider") entityId = 59; + else if (entityType == L"silverfish") entityId = 60; + else if (entityType == L"blaze") entityId = 61; + else if (entityType == L"lavaslime") entityId = 62; + else if (entityType == L"enderdragon") entityId = 63; + else if (entityType == L"wither") entityId = 64; + else if (entityType == L"bat") entityId = 65; + else if (entityType == L"witch") entityId = 66; + else if (entityType == L"pig") entityId = 90; + else if (entityType == L"sheep") entityId = 91; + else if (entityType == L"cow") entityId = 92; + else if (entityType == L"chicken") entityId = 93; + else if (entityType == L"squid") entityId = 94; + else if (entityType == L"wolf") entityId = 95; + else if (entityType == L"mushroomcow") entityId = 96; + else if (entityType == L"snowman") entityId = 97; + else if (entityType == L"ocelot") entityId = 98; + else if (entityType == L"villagergolem") entityId = 99; + else if (entityType == L"horse") entityId = 100; + else if (entityType == L"villager") entityId = 120; + else if (entityType == L"item") entityId = 1; + else if (entityType == L"xporb") entityId = 2; + else if (entityType == L"painting") entityId = 9; + else if (entityType == L"arrow") entityId = 10; + else if (entityType == L"snowball") entityId = 11; + else if (entityType == L"fireball") entityId = 12; + else if (entityType == L"smallfireball") entityId = 13; + else if (entityType == L"enderpearl") entityId = 14; + else if (entityType == L"potion") entityId = 16; + else if (entityType == L"experiencebottle") entityId = 17; + else if (entityType == L"itemframe") entityId = 18; + else if (entityType == L"witherskull") entityId = 19; + else if (entityType == L"tnt") entityId = 20; + else if (entityType == L"fallingsand") entityId = 21; + else if (entityType == L"fireworks") entityId = 22; + else if (entityType == L"boat") entityId = 41; + else if (entityType == L"minecart") entityId = 42; + else if (entityType == L"chestminecart") entityId = 43; + else if (entityType == L"furnaceminecart") entityId = 44; + else if (entityType == L"tntminecart") entityId = 45; + else if (entityType == L"hopperminecart") entityId = 46; + else if (entityType == L"spawnerminecart") entityId = 47; + else + { + server->warn(L"Unknown entity type: " + entityType); + return false; + } + } + + shared_ptr entity = EntityIO::newById(entityId, level); + + if (entity == NULL) + { + server->warn(L"Failed to summon entity: " + entityType); + return false; + } + + entity->setPos(x + 0.5, y, z + 0.5); + + level->addEntity(entity); + + wstring dimensionName; + if (dimension == 0) dimensionName = L"Overworld"; + else if (dimension == -1) dimensionName = L"Nether"; + else if (dimension == 1) dimensionName = L"End"; + + server->info(L"Summoned " + entityType + L" at (" + + std::to_wstring(x) + L", " + std::to_wstring(y) + L", " + std::to_wstring(z) + L") in " + dimensionName); + return true; + } + server->warn(L"Unknown command: " + command); return false; } diff --git a/Minecraft.Client/PlayerConnection.cpp b/Minecraft.Client/PlayerConnection.cpp index 8e056cd81..0bbc3d1b6 100644 --- a/Minecraft.Client/PlayerConnection.cpp +++ b/Minecraft.Client/PlayerConnection.cpp @@ -9,9 +9,11 @@ #include "..\Minecraft.World\net.minecraft.network.h" #include "..\Minecraft.World\net.minecraft.world.entity.item.h" #include "..\Minecraft.World\net.minecraft.world.level.h" +#include "..\Minecraft.World\net.minecraft.world.level.tile.h" #include "..\Minecraft.World\net.minecraft.world.level.dimension.h" #include "..\Minecraft.World\net.minecraft.world.item.h" #include "..\Minecraft.World\net.minecraft.world.item.trading.h" +#include "..\Minecraft.World\net.minecraft.world.item.enchantment.h" #include "..\Minecraft.World\net.minecraft.world.inventory.h" #include "..\Minecraft.World\net.minecraft.world.level.tile.entity.h" #include "..\Minecraft.World\net.minecraft.world.level.saveddata.h" @@ -633,10 +635,548 @@ void PlayerConnection::handleChat(shared_ptr packet) void PlayerConnection::handleCommand(const wstring& message) { - // 4J - TODO -#if 0 - server.getCommandDispatcher().performCommand(player, message); -#endif + wstring commandStr = message; + stripWhitespaceForHtml(commandStr, true); + + vector args; + if (message.find(' ') >= 0) + { + args = stringSplit(commandStr, ' '); + commandStr = args[0]; + args.erase(args.begin()); + } + + if (commandStr == L"/kill") + { + if (args.size() == 0) + { + // Kill self + server->getCommandDispatcher()->performCommand(player, eGameCommand_Kill, byteArray()); + } + else + { + // Kill target player + shared_ptr targetPlayer = server->getPlayers()->getPlayer(args[0]); + if (!targetPlayer) + { + player->sendMessage(L"Player '" + args[0] + L"' not found!"); + return; + } + + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + dos.writePlayerUID(targetPlayer->getXuid()); + + server->getCommandDispatcher()->performCommand(player, eGameCommand_Kill, baos.toByteArray()); + } + } + else if (commandStr == L"/gamemode") + { + ByteArrayOutputStream baos(2); + DataOutputStream dos(&baos); + + if (args.size() == 0) + { + player->sendMessage(L"Incorrect command usage! Use: /gamemode [player]"); + return; + } + + dos.writeUTF(args[0]); + + if (args.size() >= 2) + { + // Player was specified in the command arguments + shared_ptr serverPlayer = server->getPlayers()->getPlayer(args[1]); + if (!serverPlayer) + { + // Player not found + player->sendMessage(L"Player '" + args[1] + L"' not found!"); + return; + } + + PlayerUID uid = serverPlayer->getXuid(); + dos.writePlayerUID(uid); + } + else + { + // Set own gamemode + dos.writePlayerUID(player->getXuid()); + } + + server->getCommandDispatcher()->performCommand(player, eGameCommand_GameMode, baos.toByteArray()); + } + else if (commandStr == L"/teleport" || commandStr == L"/tp") + { + if (args.size() == 0) + { + player->sendMessage(L"Incorrect command usage! Use: /tp or /tp "); + return; + } + + // tp + if (args.size() == 2) + { + shared_ptr targetPlayer = server->getPlayers()->getPlayer(args[0]); + shared_ptr toPlayer = server->getPlayers()->getPlayer(args[1]); + + if (!targetPlayer) + { + player->sendMessage(L"Target player '" + args[0] + L"' not found!"); + return; + } + if (!toPlayer) + { + player->sendMessage(L"Send to player '" + args[1] + L"' not found!"); + return; + } + + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + dos.writePlayerUID(targetPlayer->getXuid()); + dos.writePlayerUID(toPlayer->getXuid()); + + server->getCommandDispatcher()->performCommand(player, eGameCommand_Teleport, baos.toByteArray()); + } + // tp + else if (args.size() == 4) + { + shared_ptr targetPlayer = server->getPlayers()->getPlayer(args[0]); + if (!targetPlayer) + { + player->sendMessage(L"Target player '" + args[0] + L"' not found!"); + return; + } + + int x = _wtoi(args[1].c_str()); + int y = _wtoi(args[2].c_str()); + int z = _wtoi(args[3].c_str()); + + targetPlayer->connection->teleport(x + 0.5f, y, z + 0.5f, targetPlayer->yRot, targetPlayer->xRot); + + player->sendMessage(L"Teleported " + targetPlayer->getName() + L" to " + args[1] + L" " + args[2] + L" " + args[3]); + } + // tp + else if (args.size() == 1) + { + shared_ptr toPlayer = server->getPlayers()->getPlayer(args[0]); + if (!toPlayer) + { + player->sendMessage(L"Target player '" + args[0] + L"' not found!"); + return; + } + + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + dos.writePlayerUID(player->getXuid()); + dos.writePlayerUID(toPlayer->getXuid()); + + server->getCommandDispatcher()->performCommand(player, eGameCommand_Teleport, baos.toByteArray()); + } + + else + { + player->sendMessage(L"Incorrect command usage! Use: /tp or /tp "); + } + } + else if (commandStr == L"/give" || commandStr == L"/giveitem") + { + if (args.size() < 2) + { + player->sendMessage(L"Incorrect command usage! Use: /give [amount] [aux]"); + return; + } + + shared_ptr targetPlayer = server->getPlayers()->getPlayer(args[0]); + if (!targetPlayer) + { + player->sendMessage(L"Player '" + args[0] + L"' not found!"); + return; + } + + int itemId = _wtoi(args[1].c_str()); + if (itemId <= 0 || itemId >= Item::items.length || Item::items[itemId] == NULL) + { + player->sendMessage(L"Invalid item ID: " + args[1]); + return; + } + + int amount = 1; + if (args.size() >= 3) + { + amount = _wtoi(args[2].c_str()); + if (amount < 1 || amount > 64) + { + player->sendMessage(L"Amount must be between 1 and 64"); + return; + } + } + + int aux = 0; + if (args.size() >= 4) + { + aux = _wtoi(args[3].c_str()); + } + + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + dos.writePlayerUID(targetPlayer->getXuid()); + dos.writeInt(itemId); + dos.writeInt(amount); + dos.writeInt(aux); + dos.writeUTF(L""); + + server->getCommandDispatcher()->performCommand(player, eGameCommand_Give, baos.toByteArray()); + } + else if (commandStr == L"/enchant" || commandStr == L"/enchantitem") + { + if (args.size() < 2) + { + player->sendMessage(L"Incorrect command usage! Use: /enchant [level]"); + return; + } + + shared_ptr targetPlayer = server->getPlayers()->getPlayer(args[0]); + if (!targetPlayer) + { + player->sendMessage(L"Player '" + args[0] + L"' not found!"); + return; + } + + if (targetPlayer->getSelectedItem() == NULL) + { + player->sendMessage(L"Player " + targetPlayer->getName() + L" is not holding an item"); + return; + } + int enchantmentId = -1; + + wchar_t* endptr; + long numId = wcstol(args[1].c_str(), &endptr, 10); + if (*endptr == L'\0') + { + enchantmentId = (int)numId; + } + else + { + wstring enchantName = args[1]; + + if (enchantName == L"protection") enchantmentId = 0; + else if (enchantName == L"fire_protection") enchantmentId = 1; + else if (enchantName == L"feather_falling") enchantmentId = 2; + else if (enchantName == L"blast_protection") enchantmentId = 3; + else if (enchantName == L"projectile_protection") enchantmentId = 4; + else if (enchantName == L"respiration") enchantmentId = 5; + else if (enchantName == L"aqua_affinity") enchantmentId = 6; + else if (enchantName == L"thorns") enchantmentId = 7; + else if (enchantName == L"sharpness") enchantmentId = 16; + else if (enchantName == L"smite") enchantmentId = 17; + else if (enchantName == L"bane_of_arthropods") enchantmentId = 18; + else if (enchantName == L"knockback") enchantmentId = 19; + else if (enchantName == L"fire_aspect") enchantmentId = 20; + else if (enchantName == L"looting") enchantmentId = 21; + else if (enchantName == L"efficiency") enchantmentId = 32; + else if (enchantName == L"silk_touch") enchantmentId = 33; + else if (enchantName == L"unbreaking") enchantmentId = 34; + else if (enchantName == L"fortune") enchantmentId = 35; + else if (enchantName == L"power") enchantmentId = 48; + else if (enchantName == L"punch") enchantmentId = 49; + else if (enchantName == L"flame") enchantmentId = 50; + else if (enchantName == L"infinity") enchantmentId = 51; + else + { + player->sendMessage(L"Unknown enchantment name: " + enchantName); + return; + } + } + + if (enchantmentId < 0 || enchantmentId >= Enchantment::enchantments.length || Enchantment::enchantments[enchantmentId] == NULL) + { + player->sendMessage(L"Invalid enchantment ID: " + args[1]); + return; + } + + int level = 1; + if (args.size() >= 3) + { + level = _wtoi(args[2].c_str()); + Enchantment* e = Enchantment::enchantments[enchantmentId]; + if (level < e->getMinLevel() || level > e->getMaxLevel()) + { + player->sendMessage(L"Enchantment level must be between " + + to_wstring(e->getMinLevel()) + L" and " + + to_wstring(e->getMaxLevel())); + return; + } + } + + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + dos.writePlayerUID(targetPlayer->getXuid()); + dos.writeInt(enchantmentId); + dos.writeInt(level); + + server->getCommandDispatcher()->performCommand(player, eGameCommand_EnchantItem, baos.toByteArray()); + } + else if (commandStr == L"/setblock") + { + if (args.size() == 0) + { + player->sendMessage(L"Incorrect command usage! Use: /setblock "); + return; + } + + // setblock + else if (args.size() == 4) + { + int x = _wtoi(args[0].c_str()); + int y = _wtoi(args[1].c_str()); + int z = _wtoi(args[2].c_str()); + + int blockId = _wtoi(args[3].c_str()); + if (blockId < 0 || blockId >= Tile::TILE_NUM_COUNT || Tile::tiles[blockId] == NULL) + { + player->sendMessage(L"Invalid block ID: " + args[3]); + return; + } + ServerLevel* level = server->getLevel(player->dimension); + if (level == NULL) + { + player->sendMessage(L"Null Dimension"); + return; + } + + level->setTileAndData(x, y, z, blockId, 0, Tile::UPDATE_ALL); + level->sendTileUpdated(x, y, z); + + player->sendMessage(L"Changed the block at "+ args[0] + L", " + args[1] + L", " + args[2] + L","); + } + else + { + player->sendMessage(L"Incorrect command usage! Use: /setblock "); + } + } + else if (commandStr == L"/fill") + { + if (args.size() < 7) + { + player->sendMessage(L"Incorrect command usage! Use: /fill "); + return; + } + + int x1 = _wtoi(args[0].c_str()); + int y1 = _wtoi(args[1].c_str()); + int z1 = _wtoi(args[2].c_str()); + int x2 = _wtoi(args[3].c_str()); + int y2 = _wtoi(args[4].c_str()); + int z2 = _wtoi(args[5].c_str()); + int blockId = _wtoi(args[6].c_str()); + + if (x1 > x2) swap(x1, x2); + if (y1 > y2) swap(y1, y2); + if (z1 > z2) swap(z1, z2); + + if (blockId < 0 || blockId >= Tile::TILE_NUM_COUNT || Tile::tiles[blockId] == NULL) + { + player->sendMessage(L"Invalid block ID: " + args[6]); + return; + } + + int volume = (x2 - x1 + 1) * (y2 - y1 + 1) * (z2 - z1 + 1); + if (volume > 32768) + { + player->sendMessage(L"Changed Block Count is Too Big Maximum is 32768 blocks"); + return; + } + + ServerLevel* level = server->getLevel(player->dimension); + if (level == NULL) + { + player->sendMessage(L"Null Dimension"); + return; + } + + int blocksChanged = 0; + + for (int x = x1; x <= x2; x++) + { + for (int y = y1; y <= y2; y++) + { + for (int z = z1; z <= z2; z++) + { + level->setTileAndData(x, y, z, blockId, 0, Tile::UPDATE_ALL); + blocksChanged++; + } + } + } + + level->sendTileUpdated(x1, y1, z1); + level->sendTileUpdated(x2, y2, z2); + + player->sendMessage(L"Successfully filled " + to_wstring(blocksChanged) + L" blocks with " + args[6]); + } + else if (commandStr == L"/time") + { + if (args.size() < 2) + { + player->sendMessage(L"Incorrect command usage! Use: /time set or /time add "); + return; + } + + wstring operation = args[0]; + int value = _wtoi(args[1].c_str()); + + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + + dos.writeUTF(operation); + dos.writeInt(value); + + server->getCommandDispatcher()->performCommand(player, eGameCommand_Time, baos.toByteArray()); + } + else if (commandStr == L"/weather") + { + if (args.size() == 0) + { + player->sendMessage(L"Incorrect command usage! Use: /weather [duration]"); + return; + } + + wstring weatherType = args[0]; + int duration = -1; + + if (args.size() >= 2) + { + duration = _wtoi(args[1].c_str()); + } + + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + + dos.writeUTF(weatherType); + dos.writeInt(duration); + + server->getCommandDispatcher()->performCommand(player, eGameCommand_Weather, baos.toByteArray()); + } + else if (commandStr == L"/summon") + { + if (args.size() < 1) + { + player->sendMessage(L"Incorrect command usage! Use: /summon [x] [y] [z]"); + return; + } + + wstring entityType = args[0]; + int x = INT_MIN, y = INT_MIN, z = INT_MIN; + + if (args.size() >= 4) + { + x = _wtoi(args[1].c_str()); + y = _wtoi(args[2].c_str()); + z = _wtoi(args[3].c_str()); + } + + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + + dos.writeUTF(entityType); + dos.writeInt(x); + dos.writeInt(y); + dos.writeInt(z); + + server->getCommandDispatcher()->performCommand(player, eGameCommand_Summon, baos.toByteArray()); + } + else if (commandStr == L"/effect") + { + if (args.size() < 2) + { + player->sendMessage(L"Incorrect command usage! Use: /effect (default 30) (optional)"); + return; + } + + shared_ptr targetPlayer = server->getPlayers()->getPlayer(args[0]); + if (!targetPlayer) + { + player->sendMessage(L"Player '" + args[0] + L"' not found!"); + return; + } + + if (targetPlayer->getSelectedItem() == NULL) + { + player->sendMessage(L"Player " + targetPlayer->getName() + L" is not holding an item"); + return; + } + int enchantmentId = -1; + + wchar_t* endptr; + long numId = wcstol(args[1].c_str(), &endptr, 10); + if (*endptr == L'\0') + { + enchantmentId = (int)numId; + } + else + { + wstring enchantName = args[1]; + + if (enchantName == L"protection") enchantmentId = 0; + else if (enchantName == L"fire_protection") enchantmentId = 1; + else if (enchantName == L"feather_falling") enchantmentId = 2; + else if (enchantName == L"blast_protection") enchantmentId = 3; + else if (enchantName == L"projectile_protection") enchantmentId = 4; + else if (enchantName == L"respiration") enchantmentId = 5; + else if (enchantName == L"aqua_affinity") enchantmentId = 6; + else if (enchantName == L"thorns") enchantmentId = 7; + else if (enchantName == L"sharpness") enchantmentId = 16; + else if (enchantName == L"smite") enchantmentId = 17; + else if (enchantName == L"bane_of_arthropods") enchantmentId = 18; + else if (enchantName == L"knockback") enchantmentId = 19; + else if (enchantName == L"fire_aspect") enchantmentId = 20; + else if (enchantName == L"looting") enchantmentId = 21; + else if (enchantName == L"efficiency") enchantmentId = 32; + else if (enchantName == L"silk_touch") enchantmentId = 33; + else if (enchantName == L"unbreaking") enchantmentId = 34; + else if (enchantName == L"fortune") enchantmentId = 35; + else if (enchantName == L"power") enchantmentId = 48; + else if (enchantName == L"punch") enchantmentId = 49; + else if (enchantName == L"flame") enchantmentId = 50; + else if (enchantName == L"infinity") enchantmentId = 51; + else + { + player->sendMessage(L"Unknown enchantment name: " + enchantName); + return; + } + } + + if (enchantmentId < 0 || enchantmentId >= Enchantment::enchantments.length || Enchantment::enchantments[enchantmentId] == NULL) + { + player->sendMessage(L"Invalid enchantment ID: " + args[1]); + return; + } + + int level = 1; + if (args.size() >= 3) + { + level = _wtoi(args[2].c_str()); + Enchantment* e = Enchantment::enchantments[enchantmentId]; + if (level < e->getMinLevel() || level > e->getMaxLevel()) + { + player->sendMessage(L"Enchantment level must be between " + + to_wstring(e->getMinLevel()) + L" and " + + to_wstring(e->getMaxLevel())); + return; + } + } + + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + dos.writePlayerUID(targetPlayer->getXuid()); + dos.writeInt(enchantmentId); + dos.writeInt(level); + + server->getCommandDispatcher()->performCommand(player, eGameCommand_Effect, baos.toByteArray()); + } + else + { + player->sendMessage(L"Unknown command!"); + } } void PlayerConnection::handleAnimate(shared_ptr packet) diff --git a/Minecraft.Client/ServerCommandDispatcher.cpp b/Minecraft.Client/ServerCommandDispatcher.cpp index 0c98aed53..662003219 100644 --- a/Minecraft.Client/ServerCommandDispatcher.cpp +++ b/Minecraft.Client/ServerCommandDispatcher.cpp @@ -5,6 +5,7 @@ #include "..\Minecraft.World\net.minecraft.commands.h" #include "..\Minecraft.World\net.minecraft.commands.common.h" #include "TeleportCommand.h" + #include "ServerCommandDispatcher.h" ServerCommandDispatcher::ServerCommandDispatcher() @@ -18,6 +19,8 @@ ServerCommandDispatcher::ServerCommandDispatcher() addCommand(new TeleportCommand()); addCommand(new GiveItemCommand()); addCommand(new EnchantItemCommand()); + addCommand(new WeatherCommand()); + addCommand(new SummonCommand()); //addCommand(new EmoteCommand()); //addCommand(new ShowSeedCommand()); //addCommand(new HelpCommand()); diff --git a/Minecraft.Client/Windows64/KeyboardMouseInput.cpp b/Minecraft.Client/Windows64/KeyboardMouseInput.cpp index 54191ebcb..1eb428241 100644 --- a/Minecraft.Client/Windows64/KeyboardMouseInput.cpp +++ b/Minecraft.Client/Windows64/KeyboardMouseInput.cpp @@ -4,6 +4,7 @@ #include "KeyboardMouseInput.h" #include +#include KeyboardMouseInput g_KBMInput; @@ -408,4 +409,10 @@ void KeyboardMouseInput::ClearCharBuffer() m_charBufferTail = 0; } +bool KeyboardMouseInput::IsGameInFront() +{ + HWND InFrontWindow = GetForegroundWindow(); + return (InFrontWindow == g_hWnd); +} + #endif // _WINDOWS64 diff --git a/Minecraft.Client/Windows64/KeyboardMouseInput.h b/Minecraft.Client/Windows64/KeyboardMouseInput.h index 0f14dfa1f..82618d8c8 100644 --- a/Minecraft.Client/Windows64/KeyboardMouseInput.h +++ b/Minecraft.Client/Windows64/KeyboardMouseInput.h @@ -139,6 +139,8 @@ class KeyboardMouseInput wchar_t m_charBuffer[CHAR_BUFFER_SIZE]; int m_charBufferHead; int m_charBufferTail; + + bool IsGameInFront(); }; extern KeyboardMouseInput g_KBMInput; diff --git a/Minecraft.World/CommandDispatcher.cpp b/Minecraft.World/CommandDispatcher.cpp index 45b3f5fe6..69444c01d 100644 --- a/Minecraft.World/CommandDispatcher.cpp +++ b/Minecraft.World/CommandDispatcher.cpp @@ -15,9 +15,7 @@ int CommandDispatcher::performCommand(shared_ptr sender, EGameCom } else { -#ifndef _CONTENT_PACKAGE - sender->sendMessage(L"\u00A7cYou do not have permission to use this command."); -#endif + sender->sendMessage(L"You do not have permission to use this command."); } } else diff --git a/Minecraft.World/CommandsEnum.h b/Minecraft.World/CommandsEnum.h index ba46a5ee3..73e442665 100644 --- a/Minecraft.World/CommandsEnum.h +++ b/Minecraft.World/CommandsEnum.h @@ -12,5 +12,7 @@ enum EGameCommand eGameCommand_Time, eGameCommand_ToggleDownfall, eGameCommand_Teleport, + eGameCommand_Weather, + eGameCommand_Summon, eGameCommand_COUNT }; \ No newline at end of file diff --git a/Minecraft.World/GameModeCommand.cpp b/Minecraft.World/GameModeCommand.cpp index 6e4cd858a..5c50c5ef6 100644 --- a/Minecraft.World/GameModeCommand.cpp +++ b/Minecraft.World/GameModeCommand.cpp @@ -1,5 +1,7 @@ #include "stdafx.h" #include "net.minecraft.commands.h" +#include "../Minecraft.Client/ServerPlayer.h" +#include "LevelSettings.h" #include "GameModeCommand.h" EGameCommand GameModeCommand::getId() @@ -12,39 +14,54 @@ int GameModeCommand::getPermissionLevel() return LEVEL_GAMEMASTERS; } -void GameModeCommand::execute(shared_ptr source, byteArray commandData) -{ - //if (args.length > 0) { - // GameType newMode = getModeForString(source, args[0]); - // Player player = args.length >= 2 ? convertToPlayer(source, args[1]) : convertSourceToPlayer(source); - - // player.setGameMode(newMode); - // player.fallDistance = 0; // reset falldistance so flying people do not die :P + void GameModeCommand::execute(shared_ptr source, byteArray commandData) + { - // ChatMessageComponent mode = ChatMessageComponent.forTranslation("gameMode." + newMode.getName()); + ByteArrayInputStream bais(commandData); + DataInputStream dis(&bais); + + wstring gamemodeStr = dis.readUTF(); + PlayerUID uid = dis.readPlayerUID(); - // if (player != source) { - // logAdminAction(source, AdminLogCommand.LOGTYPE_DONT_SHOW_TO_SELF, "commands.gamemode.success.other", player.getAName(), mode); - // } else { - // logAdminAction(source, AdminLogCommand.LOGTYPE_DONT_SHOW_TO_SELF, "commands.gamemode.success.self", mode); - // } + GameType *gamemode = getModeForString(source, gamemodeStr); + shared_ptr player = getPlayer(uid); + + if (gamemode != NULL) + { + player->setGameMode(gamemode); + player->fallDistance = 0; + + //ChatMessageComponent mode = ChatMessageComponent.forTranslation("gameMode." newMode.getName()); - // return; - //} - - //throw new UsageException("commands.gamemode.usage"); -} + if (player != source) + { + logAdminAction(source, ChatPacket::e_ChatCustom, L"Set game mode of " + player->getName() + L" to " + gamemode->getName(), gamemode->getId(), player->getAName()); + //logAdminAction(source, AdminLogCommand::LOGTYPE_DONT_SHOW_TO_SELF, "commands.gamemode.success.other", player->getAName(), mode); + } + else + { + logAdminAction(source, ChatPacket::e_ChatCustom, L"Set own game mode to " + gamemode->getName(), gamemode->getId(), player->getAName()); + //logAdminAction(source, AdminLogCommand::LOGTYPE_DONT_SHOW_TO_SELF, "commands.gamemode.success.self", mode); + } + } + } GameType *GameModeCommand::getModeForString(shared_ptr source, const wstring &name) { - return nullptr; - //if (name.equalsIgnoreCase(GameType.SURVIVAL.getName()) || name.equalsIgnoreCase("s")) { - // return GameType.SURVIVAL; - //} else if (name.equalsIgnoreCase(GameType.CREATIVE.getName()) || name.equalsIgnoreCase("c")) { - // return GameType.CREATIVE; - //} else if (name.equalsIgnoreCase(GameType.ADVENTURE.getName()) || name.equalsIgnoreCase("a")) { - // return GameType.ADVENTURE; - //} else { - // return LevelSettings.validateGameType(convertArgToInt(source, name, 0, GameType.values().length - 2)); - //} + if (equalsIgnoreCase(name, GameType::SURVIVAL->getName()) || equalsIgnoreCase(name, L"s")) + { + return GameType::SURVIVAL; + } + else if (equalsIgnoreCase(name, GameType::CREATIVE->getName()) || equalsIgnoreCase(name, L"c")) + { + return GameType::CREATIVE; + } + else if (equalsIgnoreCase(name, GameType::ADVENTURE->getName()) || equalsIgnoreCase(name, L"a")) + { + return GameType::ADVENTURE; + } + else + { + return nullptr; + } } \ No newline at end of file diff --git a/Minecraft.World/Minecraft.World.vcxproj b/Minecraft.World/Minecraft.World.vcxproj index b6af91538..31d82d865 100644 --- a/Minecraft.World/Minecraft.World.vcxproj +++ b/Minecraft.World/Minecraft.World.vcxproj @@ -2815,6 +2815,7 @@ + @@ -3642,7 +3643,9 @@ + + diff --git a/Minecraft.World/Minecraft.World.vcxproj.filters b/Minecraft.World/Minecraft.World.vcxproj.filters index bf872596b..a465b32c3 100644 --- a/Minecraft.World/Minecraft.World.vcxproj.filters +++ b/Minecraft.World/Minecraft.World.vcxproj.filters @@ -3197,6 +3197,9 @@ net\minecraft\world\inventory + + net\minecraft\commands\common + @@ -5626,5 +5629,11 @@ net\minecraft\world\item + + net\minecraft\commands\common + + + net\minecraft\commands\common + \ No newline at end of file diff --git a/Minecraft.World/SummonCommand.cpp b/Minecraft.World/SummonCommand.cpp new file mode 100644 index 000000000..1ca807c4a --- /dev/null +++ b/Minecraft.World/SummonCommand.cpp @@ -0,0 +1,156 @@ +#include "stdafx.h" +#include "..\Minecraft.Client\MinecraftServer.h" +#include "..\Minecraft.Client\ServerPlayer.h" +#include "..\Minecraft.Client\ServerLevel.h" +#include "..\Minecraft.World\net.minecraft.commands.h" +#include "..\Minecraft.World\net.minecraft.world.level.h" +#include "GameCommandPacket.h" +#include "EntityIO.h" +#include "SummonCommand.h" + +EGameCommand SummonCommand::getId() +{ + return eGameCommand_Summon; +} + +int SummonCommand::getPermissionLevel() +{ + return LEVEL_GAMEMASTERS; +} + +void SummonCommand::execute(shared_ptr source, byteArray commandData) +{ + ByteArrayInputStream bais(commandData); + DataInputStream dis(&bais); + + wstring entityType = dis.readUTF(); + int x = dis.readInt(); + int y = dis.readInt(); + int z = dis.readInt(); + + bais.reset(); + + MinecraftServer* server = MinecraftServer::getInstance(); + ServerLevel* level = NULL; + + shared_ptr player = dynamic_pointer_cast(source); + + if (player != NULL) + { + level = server->getLevel(player->dimension); + + if (x == INT_MIN || y == INT_MIN || z == INT_MIN) + { + x = (int)player->x; + y = (int)player->y; + z = (int)player->z; + } + } + else + { + level = server->getLevel(0); + + if (x == INT_MIN || y == INT_MIN || z == INT_MIN) + { + source->sendMessage(L"Player Not Founded Coords Are Required: /summon "); + return; + } + } + + if (level == NULL) return; + + int entityId = -1; + wchar_t* endptr; + long numId = wcstol(entityType.c_str(), &endptr, 10); + if (*endptr == L'\0') + { + entityId = (int)numId; + } + else + { + if (entityType == L"creeper") entityId = 50; + else if (entityType == L"skeleton") entityId = 51; + else if (entityType == L"spider") entityId = 52; + else if (entityType == L"giant") entityId = 53; + else if (entityType == L"zombie") entityId = 54; + else if (entityType == L"slime") entityId = 55; + else if (entityType == L"ghast") entityId = 56; + else if (entityType == L"pigzombie") entityId = 57; + else if (entityType == L"enderman") entityId = 58; + else if (entityType == L"cavespider") entityId = 59; + else if (entityType == L"silverfish") entityId = 60; + else if (entityType == L"blaze") entityId = 61; + else if (entityType == L"lavaslime") entityId = 62; + else if (entityType == L"enderdragon") entityId = 63; + else if (entityType == L"wither") entityId = 64; + else if (entityType == L"bat") entityId = 65; + else if (entityType == L"witch") entityId = 66; + else if (entityType == L"pig") entityId = 90; + else if (entityType == L"sheep") entityId = 91; + else if (entityType == L"cow") entityId = 92; + else if (entityType == L"chicken") entityId = 93; + else if (entityType == L"squid") entityId = 94; + else if (entityType == L"wolf") entityId = 95; + else if (entityType == L"mushroomcow") entityId = 96; + else if (entityType == L"snowman") entityId = 97; + else if (entityType == L"ocelot") entityId = 98; + else if (entityType == L"villagergolem") entityId = 99; + else if (entityType == L"horse") entityId = 100; + else if (entityType == L"villager") entityId = 120; + else if (entityType == L"item") entityId = 1; + else if (entityType == L"xporb") entityId = 2; + else if (entityType == L"painting") entityId = 9; + else if (entityType == L"arrow") entityId = 10; + else if (entityType == L"snowball") entityId = 11; + else if (entityType == L"fireball") entityId = 12; + else if (entityType == L"smallfireball") entityId = 13; + else if (entityType == L"enderpearl") entityId = 14; + else if (entityType == L"potion") entityId = 16; + else if (entityType == L"experiencebottle") entityId = 17; + else if (entityType == L"itemframe") entityId = 18; + else if (entityType == L"witherskull") entityId = 19; + else if (entityType == L"tnt") entityId = 20; + else if (entityType == L"fallingsand") entityId = 21; + else if (entityType == L"fireworks") entityId = 22; + else if (entityType == L"boat") entityId = 41; + else if (entityType == L"minecart") entityId = 42; + else if (entityType == L"chestminecart") entityId = 43; + else if (entityType == L"furnaceminecart") entityId = 44; + else if (entityType == L"tntminecart") entityId = 45; + else if (entityType == L"hopperminecart") entityId = 46; + else if (entityType == L"spawnerminecart") entityId = 47; + else + { + source->sendMessage(L"Unknown entity type: " + entityType); + return; + } + } + + shared_ptr entity = EntityIO::newById(entityId, level); + + if (entity == NULL) + { + source->sendMessage(L"Failed to summon entity: " + entityType); + return; + } + + entity->setPos(x + 0.5, y, z + 0.5); + level->addEntity(entity); + + wstring successMsg = L"Summoned " + entityType + L" at (" + + to_wstring(x) + L", " + to_wstring(y) + L", " + to_wstring(z) + L")"; + source->sendMessage(successMsg); +} + +shared_ptr SummonCommand::preparePacket(const wstring& entityType, int x, int y, int z) +{ + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + + dos.writeUTF(entityType); + dos.writeInt(x); + dos.writeInt(y); + dos.writeInt(z); + + return shared_ptr(new GameCommandPacket(eGameCommand_Summon, baos.toByteArray())); +} \ No newline at end of file diff --git a/Minecraft.World/SummonCommand.h b/Minecraft.World/SummonCommand.h new file mode 100644 index 000000000..299cd54bd --- /dev/null +++ b/Minecraft.World/SummonCommand.h @@ -0,0 +1,16 @@ +#pragma once + +#include "Command.h" +#include "level.h" + +class GameCommandPacket; + +class SummonCommand : public Command +{ +public: + virtual EGameCommand getId(); + virtual int getPermissionLevel(); + virtual void execute(shared_ptr source, byteArray commandData); + + static shared_ptr preparePacket(const wstring& entityType, int x, int y, int z); +}; \ No newline at end of file diff --git a/Minecraft.World/WeatherCommand.cpp b/Minecraft.World/WeatherCommand.cpp new file mode 100644 index 000000000..2c83465b6 --- /dev/null +++ b/Minecraft.World/WeatherCommand.cpp @@ -0,0 +1,80 @@ +#include "stdafx.h" +#include "..\Minecraft.Client\MinecraftServer.h" +#include "..\Minecraft.Client\ServerLevel.h" +#include "..\Minecraft.World\net.minecraft.commands.h" +#include "..\Minecraft.World\net.minecraft.world.level.h" +#include "..\Minecraft.World\net.minecraft.world.level.storage.h" +#include "..\Minecraft.World\SharedConstants.h" +#include "GameCommandPacket.h" +#include "WeatherCommand.h" + +EGameCommand WeatherCommand::getId() +{ + return eGameCommand_Weather; +} + +int WeatherCommand::getPermissionLevel() +{ + return LEVEL_GAMEMASTERS; +} + +void WeatherCommand::execute(shared_ptr source, byteArray commandData) +{ + ByteArrayInputStream bais(commandData); + DataInputStream dis(&bais); + + wstring weatherType = dis.readUTF(); + int duration = dis.readInt(); + + bais.reset(); + + MinecraftServer* server = MinecraftServer::getInstance(); + ServerLevel* level = server->getLevel(0); + + if (level == NULL) return; + + LevelData* levelData = level->getLevelData(); + + if (duration <= 0) + { + Random random; + duration = (300 + random.nextInt(600)) * SharedConstants::TICKS_PER_SECOND; + } + else + { + duration = duration * SharedConstants::TICKS_PER_SECOND; + } + + levelData->setRainTime(duration); + levelData->setThunderTime(duration); + + if (weatherType == L"clear") + { + levelData->setRaining(false); + levelData->setThundering(false); + logAdminAction(source, ChatPacket::e_ChatCustom, L"commands.weather.clear"); + } + else if (weatherType == L"rain") + { + levelData->setRaining(true); + levelData->setThundering(false); + logAdminAction(source, ChatPacket::e_ChatCustom, L"commands.weather.rain"); + } + else if (weatherType == L"thunder") + { + levelData->setRaining(true); + levelData->setThundering(true); + logAdminAction(source, ChatPacket::e_ChatCustom, L"commands.weather.thunder"); + } +} + +shared_ptr WeatherCommand::preparePacket(const wstring& weatherType, int duration) +{ + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + + dos.writeUTF(weatherType); + dos.writeInt(duration); + + return shared_ptr(new GameCommandPacket(eGameCommand_Weather, baos.toByteArray())); +} \ No newline at end of file diff --git a/Minecraft.World/WeatherCommand.h b/Minecraft.World/WeatherCommand.h index 795b7bdf9..9ced1d65f 100644 --- a/Minecraft.World/WeatherCommand.h +++ b/Minecraft.World/WeatherCommand.h @@ -1,73 +1,14 @@ -/* -package net.minecraft.commands.common; +#pragma once +#include "Command.h" -import java.util.*; +class GameCommandPacket; -import net.minecraft.SharedConstants; -import net.minecraft.commands.*; -import net.minecraft.commands.exceptions.UsageException; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.storage.LevelData; +class WeatherCommand : public Command +{ +public: + virtual EGameCommand getId(); + virtual int getPermissionLevel(); + virtual void execute(shared_ptr source, byteArray commandData); -public class WeatherCommand extends BaseCommand { - @Override - public String getName() { - return "weather"; - } - - @Override - public int getPermissionLevel() { - return LEVEL_GAMEMASTERS; - } - - @Override - public String getUsage(CommandSender source) { - return "commands.weather.usage"; - } - - @Override - public void execute(CommandSender source, String[] args) { - if (args.length < 1 || args.length > 2) { - throw new UsageException("commands.weather.usage"); - } - - int duration = (300 + new Random().nextInt(600)) * SharedConstants.TICKS_PER_SECOND; - if (args.length >= 2) { - duration = convertArgToInt(source, args[1], 1, 1000000) * SharedConstants.TICKS_PER_SECOND; - } - - Level level = MinecraftServer.getInstance().levels[0]; - LevelData levelData = level.getLevelData(); - levelData.setRainTime(duration); - levelData.setThunderTime(duration); - - if ("clear".equalsIgnoreCase(args[0])) { - levelData.setRaining(false); - levelData.setThundering(false); - logAdminAction(source, "commands.weather.clear"); - } else if ("rain".equalsIgnoreCase(args[0])) { - levelData.setRaining(true); - levelData.setThundering(false); - logAdminAction(source, "commands.weather.rain"); - } else if ("thunder".equalsIgnoreCase(args[0])) { - levelData.setRaining(true); - levelData.setThundering(true); - logAdminAction(source, "commands.weather.thunder"); - } else { - throw new UsageException("commands.weather.usage"); - } - } - - @Override - public List matchArguments(CommandSender source, String[] args) { - if (args.length == 1) { - return matchArguments(args, "clear", "rain", "thunder"); - } - - return null; - } - -} - -*/ \ No newline at end of file + static shared_ptr preparePacket(const wstring& weatherType, int duration = -1); +}; \ No newline at end of file diff --git a/Minecraft.World/net.minecraft.commands.common.h b/Minecraft.World/net.minecraft.commands.common.h index 83b0dca5c..3fb948c9c 100644 --- a/Minecraft.World/net.minecraft.commands.common.h +++ b/Minecraft.World/net.minecraft.commands.common.h @@ -8,4 +8,6 @@ #include "GiveItemCommand.h" #include "KillCommand.h" #include "TimeCommand.h" -#include "ToggleDownfallCommand.h" \ No newline at end of file +#include "ToggleDownfallCommand.h" +#include "WeatherCommand.h" +#include "SummonCommand.h" \ No newline at end of file