add: add new CLI Console Commands for Dedicated Server

Most of these commands are executed using the command dispatcher implemented on the `Minecraft.World` side. When registering them with the dispatcher, the sender uses a permission-enabled configuration that treats the CLI as a player.

- default game.
- enchant
- experience.
- give
- kill(currently, getting a permission error for some reason)
- time
- weather.
- update tp & gamemode command
This commit is contained in:
kuwacom 2026-03-14 00:55:30 +09:00
parent 465b2b8f14
commit 20c2e4653a
25 changed files with 1099 additions and 43 deletions

View file

@ -114,6 +114,13 @@ list(APPEND MINECRAFT_SERVER_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/tp/CliCommandTp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/tp/CliCommandTp.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/whitelist/CliCommandWhitelist.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/whitelist/CliCommandWhitelist.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/gamemode/CliCommandGamemode.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/gamemode/CliCommandGamemode.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/time/CliCommandTime.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/weather/CliCommandWeather.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/give/CliCommandGive.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/enchant/CliCommandEnchant.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/kill/CliCommandKill.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/defaultgamemode/CliCommandDefaultGamemode.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/experience/CliCommandExperience.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Common/FileUtils.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Common/FileUtils.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Common/StringUtils.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Common/StringUtils.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/ServerLogger.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/ServerLogger.cpp"

View file

@ -8,13 +8,20 @@
#include "commands\ban\CliCommandBan.h" #include "commands\ban\CliCommandBan.h"
#include "commands\ban-ip\CliCommandBanIp.h" #include "commands\ban-ip\CliCommandBanIp.h"
#include "commands\ban-list\CliCommandBanList.h" #include "commands\ban-list\CliCommandBanList.h"
#include "commands\defaultgamemode\CliCommandDefaultGamemode.h"
#include "commands\enchant\CliCommandEnchant.h"
#include "commands\experience\CliCommandExperience.h"
#include "commands\gamemode\CliCommandGamemode.h" #include "commands\gamemode\CliCommandGamemode.h"
#include "commands\give\CliCommandGive.h"
#include "commands\help\CliCommandHelp.h" #include "commands\help\CliCommandHelp.h"
#include "commands\kill\CliCommandKill.h"
#include "commands\list\CliCommandList.h" #include "commands\list\CliCommandList.h"
#include "commands\pardon\CliCommandPardon.h" #include "commands\pardon\CliCommandPardon.h"
#include "commands\pardon-ip\CliCommandPardonIp.h" #include "commands\pardon-ip\CliCommandPardonIp.h"
#include "commands\stop\CliCommandStop.h" #include "commands\stop\CliCommandStop.h"
#include "commands\time\CliCommandTime.h"
#include "commands\tp\CliCommandTp.h" #include "commands\tp\CliCommandTp.h"
#include "commands\weather\CliCommandWeather.h"
#include "commands\whitelist\CliCommandWhitelist.h" #include "commands\whitelist\CliCommandWhitelist.h"
#include "..\Common\StringUtils.h" #include "..\Common\StringUtils.h"
#include "..\ServerShutdown.h" #include "..\ServerShutdown.h"
@ -22,6 +29,8 @@
#include "..\..\Minecraft.Client\MinecraftServer.h" #include "..\..\Minecraft.Client\MinecraftServer.h"
#include "..\..\Minecraft.Client\PlayerList.h" #include "..\..\Minecraft.Client\PlayerList.h"
#include "..\..\Minecraft.Client\ServerPlayer.h" #include "..\..\Minecraft.Client\ServerPlayer.h"
#include "..\..\Minecraft.World\CommandDispatcher.h"
#include "..\..\Minecraft.World\CommandSender.h"
#include "..\..\Minecraft.World\LevelSettings.h" #include "..\..\Minecraft.World\LevelSettings.h"
#include "..\..\Minecraft.World\StringHelpers.h" #include "..\..\Minecraft.World\StringHelpers.h"
@ -30,8 +39,48 @@
namespace ServerRuntime namespace ServerRuntime
{ {
/**
* Create an authorized Sender to make the CLI appear as a user.
* The return value can also be used to display logs.
*/
namespace
{
class ServerCliConsoleCommandSender : public CommandSender
{
public:
explicit ServerCliConsoleCommandSender(const ServerCliEngine *engine)
: m_engine(engine)
{
}
void sendMessage(const wstring &message, ChatPacket::EChatPacketMessage type, int customData, const wstring &additionalMessage) override
{
(void)type;
(void)customData;
(void)additionalMessage;
if (m_engine == nullptr)
{
return;
}
m_engine->LogInfo(StringUtils::WideToUtf8(message));
}
bool hasPermission(EGameCommand command) override
{
(void)command;
return true;
}
private:
const ServerCliEngine *m_engine;
};
}
ServerCliEngine::ServerCliEngine() ServerCliEngine::ServerCliEngine()
: m_registry(new ServerCliRegistry()) : m_registry(new ServerCliRegistry())
, m_consoleSender(std::make_shared<ServerCliConsoleCommandSender>(this))
{ {
RegisterDefaultCommands(); RegisterDefaultCommands();
} }
@ -52,7 +101,14 @@ namespace ServerRuntime
m_registry->Register(std::unique_ptr<IServerCliCommand>(new CliCommandBanList())); m_registry->Register(std::unique_ptr<IServerCliCommand>(new CliCommandBanList()));
m_registry->Register(std::unique_ptr<IServerCliCommand>(new CliCommandWhitelist())); m_registry->Register(std::unique_ptr<IServerCliCommand>(new CliCommandWhitelist()));
m_registry->Register(std::unique_ptr<IServerCliCommand>(new CliCommandTp())); m_registry->Register(std::unique_ptr<IServerCliCommand>(new CliCommandTp()));
m_registry->Register(std::unique_ptr<IServerCliCommand>(new CliCommandTime()));
m_registry->Register(std::unique_ptr<IServerCliCommand>(new CliCommandWeather()));
m_registry->Register(std::unique_ptr<IServerCliCommand>(new CliCommandGive()));
m_registry->Register(std::unique_ptr<IServerCliCommand>(new CliCommandEnchant()));
m_registry->Register(std::unique_ptr<IServerCliCommand>(new CliCommandKill()));
m_registry->Register(std::unique_ptr<IServerCliCommand>(new CliCommandGamemode())); m_registry->Register(std::unique_ptr<IServerCliCommand>(new CliCommandGamemode()));
m_registry->Register(std::unique_ptr<IServerCliCommand>(new CliCommandDefaultGamemode()));
m_registry->Register(std::unique_ptr<IServerCliCommand>(new CliCommandExperience()));
} }
void ServerCliEngine::EnqueueCommandLine(const std::string &line) void ServerCliEngine::EnqueueCommandLine(const std::string &line)
@ -300,9 +356,40 @@ namespace ServerRuntime
return NULL; return NULL;
} }
bool ServerCliEngine::DispatchWorldCommand(EGameCommand command, byteArray commandData, const std::shared_ptr<CommandSender> &sender) const
{
MinecraftServer *server = MinecraftServer::getInstance();
if (server == NULL)
{
LogWarn("MinecraftServer instance is not available.");
return false;
}
CommandDispatcher *dispatcher = server->getCommandDispatcher();
if (dispatcher == NULL)
{
LogWarn("Command dispatcher is not available.");
return false;
}
std::shared_ptr<CommandSender> commandSender = sender;
if (commandSender == nullptr)
{
// fall back to console sender if caller did not provide one
commandSender = m_consoleSender;
}
if (commandSender == nullptr)
{
LogWarn("No command sender is available.");
return false;
}
dispatcher->performCommand(commandSender, command, commandData);
return true;
}
const ServerCliRegistry &ServerCliEngine::Registry() const const ServerCliRegistry &ServerCliEngine::Registry() const
{ {
return *m_registry; return *m_registry;
} }
} }

View file

@ -6,8 +6,12 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "..\..\Minecraft.World\ArrayWithLength.h"
#include "..\..\Minecraft.World\CommandsEnum.h"
class GameType; class GameType;
class ServerPlayer; class ServerPlayer;
class CommandSender;
namespace ServerRuntime namespace ServerRuntime
{ {
@ -98,6 +102,17 @@ namespace ServerRuntime
*/ */
GameType *ParseGamemode(const std::string &token) const; GameType *ParseGamemode(const std::string &token) const;
/**
* **Dispatch one Minecraft.World game command**
*
* Uses `Minecraft.World::CommandDispatcher` for actual execution.
* When `sender` is null, an internal console command sender is used.
*
* Minecraft.Worldのコマンドを実行するためのディスパッチャーのラッパー
* senderがnullの場合はコンソールコマンド送信者を使用
*/
bool DispatchWorldCommand(EGameCommand command, byteArray commandData, const std::shared_ptr<CommandSender> &sender = nullptr) const;
const ServerCliRegistry &Registry() const; const ServerCliRegistry &Registry() const;
private: private:
@ -107,5 +122,6 @@ namespace ServerRuntime
mutable std::mutex m_queueMutex; mutable std::mutex m_queueMutex;
std::queue<std::string> m_pendingLines; std::queue<std::string> m_pendingLines;
std::unique_ptr<ServerCliRegistry> m_registry; std::unique_ptr<ServerCliRegistry> m_registry;
std::shared_ptr<CommandSender> m_consoleSender;
}; };
} }

View file

@ -0,0 +1,39 @@
#pragma once
#include <cerrno>
#include <cstdlib>
#include <limits>
#include <string>
namespace ServerRuntime
{
namespace CommandParsing
{
inline bool TryParseInt(const std::string &text, int *outValue)
{
if (outValue == nullptr || text.empty())
{
return false;
}
char *end = nullptr;
errno = 0;
const long parsedValue = std::strtol(text.c_str(), &end, 10);
if (end == text.c_str() || *end != '\0')
{
return false;
}
if (errno == ERANGE)
{
return false;
}
if (parsedValue < (std::numeric_limits<int>::min)() || parsedValue > (std::numeric_limits<int>::max)())
{
return false;
}
*outValue = static_cast<int>(parsedValue);
return true;
}
}
}

View file

@ -17,12 +17,12 @@ namespace ServerRuntime
class IServerCliCommand class IServerCliCommand
{ {
public: public:
virtual ~IServerCliCommand() {} virtual ~IServerCliCommand() = default;
/** Primary command name */ /** Primary command name */
virtual const char *Name() const = 0; virtual const char *Name() const = 0;
/** Optional aliases */ /** Optional aliases */
virtual std::vector<std::string> Aliases() const { return std::vector<std::string>(); } virtual std::vector<std::string> Aliases() const { return {}; }
/** Usage text for help */ /** Usage text for help */
virtual const char *Usage() const = 0; virtual const char *Usage() const = 0;
/** Short command description*/ /** Short command description*/

View file

@ -0,0 +1,117 @@
#include "stdafx.h"
#include "CliCommandDefaultGamemode.h"
#include "..\..\ServerCliEngine.h"
#include "..\..\ServerCliParser.h"
#include "..\..\..\..\Minecraft.Client\MinecraftServer.h"
#include "..\..\..\..\Minecraft.Client\PlayerList.h"
#include "..\..\..\..\Minecraft.Client\ServerLevel.h"
#include "..\..\..\..\Minecraft.Client\ServerPlayer.h"
#include "..\..\..\..\Minecraft.World\net.minecraft.world.level.storage.h"
namespace ServerRuntime
{
namespace
{
constexpr const char *kDefaultGamemodeUsage = "defaultgamemode <survival|creative|0|1>";
static std::string ModeLabel(GameType *mode)
{
if (mode == GameType::SURVIVAL)
{
return "survival";
}
if (mode == GameType::CREATIVE)
{
return "creative";
}
if (mode == GameType::ADVENTURE)
{
return "adventure";
}
return std::to_string(mode != nullptr ? mode->getId() : -1);
}
}
const char *CliCommandDefaultGamemode::Name() const
{
return "defaultgamemode";
}
const char *CliCommandDefaultGamemode::Usage() const
{
return kDefaultGamemodeUsage;
}
const char *CliCommandDefaultGamemode::Description() const
{
return "Set the default game mode (server-side implementation).";
}
bool CliCommandDefaultGamemode::Execute(const ServerCliParsedLine &line, ServerCliEngine *engine)
{
if (line.tokens.size() != 2)
{
engine->LogWarn(std::string("Usage: ") + kDefaultGamemodeUsage);
return false;
}
GameType *mode = engine->ParseGamemode(line.tokens[1]);
if (mode == nullptr)
{
engine->LogWarn("Unknown gamemode: " + line.tokens[1]);
return false;
}
MinecraftServer *server = MinecraftServer::getInstance();
if (server == nullptr)
{
engine->LogWarn("MinecraftServer instance is not available.");
return false;
}
PlayerList *players = server->getPlayers();
if (players == nullptr)
{
engine->LogWarn("Player list is not available.");
return false;
}
players->setOverrideGameMode(mode);
for (unsigned int i = 0; i < server->levels.length; ++i)
{
ServerLevel *level = server->levels[i];
if (level != nullptr && level->getLevelData() != nullptr)
{
level->getLevelData()->setGameType(mode);
}
}
if (server->getForceGameType())
{
for (size_t i = 0; i < players->players.size(); ++i)
{
std::shared_ptr<ServerPlayer> player = players->players[i];
if (player != nullptr)
{
player->setGameMode(mode);
player->fallDistance = 0.0f;
}
}
}
engine->LogInfo("Default gamemode set to " + ModeLabel(mode) + ".");
return true;
}
void CliCommandDefaultGamemode::Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const
{
if (context.currentTokenIndex == 1)
{
engine->SuggestGamemodes(context.prefix, context.linePrefix, out);
}
}
}

View file

@ -0,0 +1,16 @@
#pragma once
#include "..\IServerCliCommand.h"
namespace ServerRuntime
{
class CliCommandDefaultGamemode : public IServerCliCommand
{
public:
const char *Name() const override;
const char *Usage() const override;
const char *Description() const override;
bool Execute(const ServerCliParsedLine &line, ServerCliEngine *engine) override;
void Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const override;
};
}

View file

@ -0,0 +1,87 @@
#include "stdafx.h"
#include "CliCommandEnchant.h"
#include "..\..\ServerCliEngine.h"
#include "..\..\ServerCliParser.h"
#include "..\CommandParsing.h"
#include "..\..\..\..\Minecraft.World\GameCommandPacket.h"
#include "..\..\..\..\Minecraft.World\EnchantItemCommand.h"
#include "..\..\..\..\Minecraft.World\net.minecraft.world.entity.player.h"
#include "..\..\..\..\Minecraft.Client\ServerPlayer.h"
namespace ServerRuntime
{
namespace
{
constexpr const char *kEnchantUsage = "enchant <player> <enchantId> [level]";
}
const char *CliCommandEnchant::Name() const
{
return "enchant";
}
const char *CliCommandEnchant::Usage() const
{
return kEnchantUsage;
}
const char *CliCommandEnchant::Description() const
{
return "Enchant held item via Minecraft.World command dispatcher.";
}
bool CliCommandEnchant::Execute(const ServerCliParsedLine &line, ServerCliEngine *engine)
{
if (line.tokens.size() < 3 || line.tokens.size() > 4)
{
engine->LogWarn(std::string("Usage: ") + kEnchantUsage);
return false;
}
std::shared_ptr<ServerPlayer> target = engine->FindPlayerByNameUtf8(line.tokens[1]);
if (target == nullptr)
{
engine->LogWarn("Unknown player: " + line.tokens[1]);
return false;
}
int enchantmentId = 0;
int enchantmentLevel = 1;
if (!CommandParsing::TryParseInt(line.tokens[2], &enchantmentId))
{
engine->LogWarn("Invalid enchantment id: " + line.tokens[2]);
return false;
}
if (line.tokens.size() >= 4 && !CommandParsing::TryParseInt(line.tokens[3], &enchantmentLevel))
{
engine->LogWarn("Invalid enchantment level: " + line.tokens[3]);
return false;
}
std::shared_ptr<Player> player = std::dynamic_pointer_cast<Player>(target);
if (player == nullptr)
{
engine->LogWarn("Cannot resolve target player entity.");
return false;
}
std::shared_ptr<GameCommandPacket> packet = EnchantItemCommand::preparePacket(player, enchantmentId, enchantmentLevel);
if (packet == nullptr)
{
engine->LogError("Failed to build enchant command packet.");
return false;
}
return engine->DispatchWorldCommand(packet->command, packet->data);
}
void CliCommandEnchant::Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const
{
if (context.currentTokenIndex == 1)
{
engine->SuggestPlayers(context.prefix, context.linePrefix, out);
}
}
}

View file

@ -0,0 +1,16 @@
#pragma once
#include "..\IServerCliCommand.h"
namespace ServerRuntime
{
class CliCommandEnchant : public IServerCliCommand
{
public:
const char *Name() const override;
const char *Usage() const override;
const char *Description() const override;
bool Execute(const ServerCliParsedLine &line, ServerCliEngine *engine) override;
void Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const override;
};
}

View file

@ -0,0 +1,184 @@
#include "stdafx.h"
#include "CliCommandExperience.h"
#include "..\..\ServerCliEngine.h"
#include "..\..\ServerCliParser.h"
#include "..\CommandParsing.h"
#include "..\..\..\Common\StringUtils.h"
#include "..\..\..\..\Minecraft.Client\MinecraftServer.h"
#include "..\..\..\..\Minecraft.Client\PlayerList.h"
#include "..\..\..\..\Minecraft.Client\ServerPlayer.h"
#include <limits>
namespace ServerRuntime
{
namespace
{
constexpr const char *kExperienceUsage = "xp <amount>[L] [player]";
constexpr const char *kExperienceUsageWithPlayer = "xp <amount>[L] <player>";
struct ExperienceAmount
{
int amount = 0;
bool levels = false;
bool take = false;
};
static bool TryParseExperienceAmount(const std::string &token, ExperienceAmount *outValue)
{
if (outValue == nullptr || token.empty())
{
return false;
}
ExperienceAmount parsed;
std::string numericToken = token;
const char suffix = token[token.size() - 1];
if (suffix == 'l' || suffix == 'L')
{
parsed.levels = true;
numericToken = token.substr(0, token.size() - 1);
if (numericToken.empty())
{
return false;
}
}
int signedAmount = 0;
if (!CommandParsing::TryParseInt(numericToken, &signedAmount))
{
return false;
}
if (signedAmount == (std::numeric_limits<int>::min)())
{
return false;
}
parsed.take = signedAmount < 0;
parsed.amount = parsed.take ? -signedAmount : signedAmount;
*outValue = parsed;
return true;
}
static std::shared_ptr<ServerPlayer> ResolveTargetPlayer(const ServerCliParsedLine &line, ServerCliEngine *engine)
{
if (line.tokens.size() >= 3)
{
return engine->FindPlayerByNameUtf8(line.tokens[2]);
}
MinecraftServer *server = MinecraftServer::getInstance();
if (server == nullptr || server->getPlayers() == nullptr)
{
return nullptr;
}
PlayerList *players = server->getPlayers();
if (players->players.size() == 1 && players->players[0] != nullptr)
{
return players->players[0];
}
return nullptr;
}
}
const char *CliCommandExperience::Name() const
{
return "xp";
}
std::vector<std::string> CliCommandExperience::Aliases() const
{
return { "experience" };
}
const char *CliCommandExperience::Usage() const
{
return kExperienceUsage;
}
const char *CliCommandExperience::Description() const
{
return "Grant or remove experience (server-side implementation).";
}
bool CliCommandExperience::Execute(const ServerCliParsedLine &line, ServerCliEngine *engine)
{
if (line.tokens.size() < 2 || line.tokens.size() > 3)
{
engine->LogWarn(std::string("Usage: ") + kExperienceUsage);
return false;
}
ExperienceAmount amount;
if (!TryParseExperienceAmount(line.tokens[1], &amount))
{
engine->LogWarn(std::string("Usage: ") + kExperienceUsage);
return false;
}
std::shared_ptr<ServerPlayer> target = ResolveTargetPlayer(line, engine);
if (target == nullptr)
{
if (line.tokens.size() >= 3)
{
engine->LogWarn("Unknown player: " + line.tokens[2]);
}
else
{
engine->LogWarn(std::string("Usage: ") + kExperienceUsageWithPlayer);
}
return false;
}
if (amount.levels)
{
target->giveExperienceLevels(amount.take ? -amount.amount : amount.amount);
if (amount.take)
{
engine->LogInfo("Removed " + std::to_string(amount.amount) + " level(s) from " + StringUtils::WideToUtf8(target->getName()) + ".");
}
else
{
engine->LogInfo("Added " + std::to_string(amount.amount) + " level(s) to " + StringUtils::WideToUtf8(target->getName()) + ".");
}
return true;
}
if (amount.take)
{
engine->LogWarn("Removing raw experience points is not supported. Use negative levels (example: xp -5L <player>).");
return false;
}
target->increaseXp(amount.amount);
engine->LogInfo("Added " + std::to_string(amount.amount) + " experience points to " + StringUtils::WideToUtf8(target->getName()) + ".");
return true;
}
void CliCommandExperience::Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const
{
if (context.currentTokenIndex == 1)
{
if (StringUtils::StartsWithIgnoreCase("10", context.prefix))
{
out->push_back(context.linePrefix + "10");
}
if (StringUtils::StartsWithIgnoreCase("10L", context.prefix))
{
out->push_back(context.linePrefix + "10L");
}
if (StringUtils::StartsWithIgnoreCase("-5L", context.prefix))
{
out->push_back(context.linePrefix + "-5L");
}
}
else if (context.currentTokenIndex == 2)
{
engine->SuggestPlayers(context.prefix, context.linePrefix, out);
}
}
}

View file

@ -0,0 +1,17 @@
#pragma once
#include "..\IServerCliCommand.h"
namespace ServerRuntime
{
class CliCommandExperience : public IServerCliCommand
{
public:
const char *Name() const override;
std::vector<std::string> Aliases() const override;
const char *Usage() const override;
const char *Description() const override;
bool Execute(const ServerCliParsedLine &line, ServerCliEngine *engine) override;
void Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const override;
};
}

View file

@ -4,14 +4,18 @@
#include "..\..\ServerCliEngine.h" #include "..\..\ServerCliEngine.h"
#include "..\..\ServerCliParser.h" #include "..\..\ServerCliParser.h"
#include "..\..\..\Common\StringUtils.h"
#include "..\..\..\..\Minecraft.Client\MinecraftServer.h" #include "..\..\..\..\Minecraft.Client\MinecraftServer.h"
#include "..\..\..\..\Minecraft.Client\PlayerList.h" #include "..\..\..\..\Minecraft.Client\PlayerList.h"
#include "..\..\..\..\Minecraft.Client\ServerPlayer.h" #include "..\..\..\..\Minecraft.Client\ServerPlayer.h"
#include "..\..\..\..\Minecraft.World\LevelSettings.h"
namespace ServerRuntime namespace ServerRuntime
{ {
namespace
{
constexpr const char *kGamemodeUsage = "gamemode <survival|creative|0|1> [player]";
constexpr const char *kGamemodeUsageWithPlayer = "gamemode <survival|creative|0|1> <player>";
}
const char *CliCommandGamemode::Name() const const char *CliCommandGamemode::Name() const
{ {
return "gamemode"; return "gamemode";
@ -24,7 +28,7 @@ namespace ServerRuntime
const char *CliCommandGamemode::Usage() const const char *CliCommandGamemode::Usage() const
{ {
return "gamemode <survival|creative|0|1> [player]"; return kGamemodeUsage;
} }
const char *CliCommandGamemode::Description() const const char *CliCommandGamemode::Description() const
@ -34,14 +38,14 @@ namespace ServerRuntime
bool CliCommandGamemode::Execute(const ServerCliParsedLine &line, ServerCliEngine *engine) bool CliCommandGamemode::Execute(const ServerCliParsedLine &line, ServerCliEngine *engine)
{ {
if (line.tokens.size() < 2) if (line.tokens.size() < 2 || line.tokens.size() > 3)
{ {
engine->LogWarn("Usage: gamemode <survival|creative|0|1> [player]"); engine->LogWarn(std::string("Usage: ") + kGamemodeUsage);
return false; return false;
} }
GameType *mode = engine->ParseGamemode(line.tokens[1]); GameType *mode = engine->ParseGamemode(line.tokens[1]);
if (mode == NULL) if (mode == nullptr)
{ {
engine->LogWarn("Unknown gamemode: " + line.tokens[1]); engine->LogWarn("Unknown gamemode: " + line.tokens[1]);
return false; return false;
@ -51,7 +55,7 @@ namespace ServerRuntime
if (line.tokens.size() >= 3) if (line.tokens.size() >= 3)
{ {
target = engine->FindPlayerByNameUtf8(line.tokens[2]); target = engine->FindPlayerByNameUtf8(line.tokens[2]);
if (target == NULL) if (target == nullptr)
{ {
engine->LogWarn("Unknown player: " + line.tokens[2]); engine->LogWarn("Unknown player: " + line.tokens[2]);
return false; return false;
@ -60,16 +64,16 @@ namespace ServerRuntime
else else
{ {
MinecraftServer *server = MinecraftServer::getInstance(); MinecraftServer *server = MinecraftServer::getInstance();
if (server == NULL || server->getPlayers() == NULL) if (server == nullptr || server->getPlayers() == nullptr)
{ {
engine->LogWarn("Player list is not available."); engine->LogWarn("Player list is not available.");
return false; return false;
} }
PlayerList *players = server->getPlayers(); PlayerList *players = server->getPlayers();
if (players->players.size() != 1 || players->players[0] == NULL) if (players->players.size() != 1 || players->players[0] == nullptr)
{ {
engine->LogWarn("Usage: gamemode <survival|creative|0|1> <player>"); engine->LogWarn(std::string("Usage: ") + kGamemodeUsageWithPlayer);
return false; return false;
} }
target = players->players[0]; target = players->players[0];
@ -77,9 +81,15 @@ namespace ServerRuntime
target->setGameMode(mode); target->setGameMode(mode);
target->fallDistance = 0.0f; target->fallDistance = 0.0f;
engine->LogInfo(
"Set " + StringUtils::WideToUtf8(target->getName()) + " gamemode to " + if (line.tokens.size() >= 3)
StringUtils::WideToUtf8(mode->getName()) + "."); {
engine->LogInfo("Set " + line.tokens[2] + " gamemode to " + line.tokens[1] + ".");
}
else
{
engine->LogInfo("Set gamemode to " + line.tokens[1] + ".");
}
return true; return true;
} }

View file

@ -7,12 +7,12 @@ namespace ServerRuntime
class CliCommandGamemode : public IServerCliCommand class CliCommandGamemode : public IServerCliCommand
{ {
public: public:
virtual const char *Name() const; const char *Name() const override;
virtual std::vector<std::string> Aliases() const; std::vector<std::string> Aliases() const override;
virtual const char *Usage() const; const char *Usage() const override;
virtual const char *Description() const; const char *Description() const override;
virtual bool Execute(const ServerCliParsedLine &line, ServerCliEngine *engine); bool Execute(const ServerCliParsedLine &line, ServerCliEngine *engine) override;
virtual void Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const; void Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const override;
}; };
} }

View file

@ -0,0 +1,103 @@
#include "stdafx.h"
#include "CliCommandGive.h"
#include "..\..\ServerCliEngine.h"
#include "..\..\ServerCliParser.h"
#include "..\CommandParsing.h"
#include "..\..\..\..\Minecraft.World\GameCommandPacket.h"
#include "..\..\..\..\Minecraft.World\GiveItemCommand.h"
#include "..\..\..\..\Minecraft.World\net.minecraft.world.entity.player.h"
#include "..\..\..\..\Minecraft.Client\ServerPlayer.h"
namespace ServerRuntime
{
namespace
{
constexpr const char *kGiveUsage = "give <player> <itemId> [amount] [aux]";
}
const char *CliCommandGive::Name() const
{
return "give";
}
const char *CliCommandGive::Usage() const
{
return kGiveUsage;
}
const char *CliCommandGive::Description() const
{
return "Give an item via Minecraft.World command dispatcher.";
}
bool CliCommandGive::Execute(const ServerCliParsedLine &line, ServerCliEngine *engine)
{
if (line.tokens.size() < 3 || line.tokens.size() > 5)
{
engine->LogWarn(std::string("Usage: ") + kGiveUsage);
return false;
}
std::shared_ptr<ServerPlayer> target = engine->FindPlayerByNameUtf8(line.tokens[1]);
if (target == nullptr)
{
engine->LogWarn("Unknown player: " + line.tokens[1]);
return false;
}
int itemId = 0;
int amount = 1;
int aux = 0;
if (!CommandParsing::TryParseInt(line.tokens[2], &itemId))
{
engine->LogWarn("Invalid item id: " + line.tokens[2]);
return false;
}
if (itemId <= 0)
{
engine->LogWarn("Item id must be greater than 0.");
return false;
}
if (line.tokens.size() >= 4 && !CommandParsing::TryParseInt(line.tokens[3], &amount))
{
engine->LogWarn("Invalid amount: " + line.tokens[3]);
return false;
}
if (line.tokens.size() >= 5 && !CommandParsing::TryParseInt(line.tokens[4], &aux))
{
engine->LogWarn("Invalid aux value: " + line.tokens[4]);
return false;
}
if (amount <= 0)
{
engine->LogWarn("Amount must be greater than 0.");
return false;
}
std::shared_ptr<Player> player = std::dynamic_pointer_cast<Player>(target);
if (player == nullptr)
{
engine->LogWarn("Cannot resolve target player entity.");
return false;
}
std::shared_ptr<GameCommandPacket> packet = GiveItemCommand::preparePacket(player, itemId, amount, aux);
if (packet == nullptr)
{
engine->LogError("Failed to build give command packet.");
return false;
}
return engine->DispatchWorldCommand(packet->command, packet->data);
}
void CliCommandGive::Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const
{
if (context.currentTokenIndex == 1)
{
engine->SuggestPlayers(context.prefix, context.linePrefix, out);
}
}
}

View file

@ -0,0 +1,16 @@
#pragma once
#include "..\IServerCliCommand.h"
namespace ServerRuntime
{
class CliCommandGive : public IServerCliCommand
{
public:
const char *Name() const override;
const char *Usage() const override;
const char *Description() const override;
bool Execute(const ServerCliParsedLine &line, ServerCliEngine *engine) override;
void Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const override;
};
}

View file

@ -0,0 +1,64 @@
#include "stdafx.h"
#include "CliCommandKill.h"
#include "..\..\ServerCliEngine.h"
#include "..\..\ServerCliParser.h"
#include "..\..\..\..\Minecraft.World\CommandSender.h"
#include "..\..\..\..\Minecraft.Client\ServerPlayer.h"
namespace ServerRuntime
{
namespace
{
constexpr const char *kKillUsage = "kill <player>";
}
const char *CliCommandKill::Name() const
{
return "kill";
}
const char *CliCommandKill::Usage() const
{
return kKillUsage;
}
const char *CliCommandKill::Description() const
{
return "Kill a player via Minecraft.World command dispatcher.";
}
bool CliCommandKill::Execute(const ServerCliParsedLine &line, ServerCliEngine *engine)
{
if (line.tokens.size() != 2)
{
engine->LogWarn(std::string("Usage: ") + kKillUsage);
return false;
}
std::shared_ptr<ServerPlayer> target = engine->FindPlayerByNameUtf8(line.tokens[1]);
if (target == nullptr)
{
engine->LogWarn("Unknown player: " + line.tokens[1]);
return false;
}
std::shared_ptr<CommandSender> sender = std::dynamic_pointer_cast<CommandSender>(target);
if (sender == nullptr)
{
engine->LogWarn("Cannot resolve target command sender.");
return false;
}
return engine->DispatchWorldCommand(eGameCommand_Kill, byteArray(), sender);
}
void CliCommandKill::Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const
{
if (context.currentTokenIndex == 1)
{
engine->SuggestPlayers(context.prefix, context.linePrefix, out);
}
}
}

View file

@ -0,0 +1,16 @@
#pragma once
#include "..\IServerCliCommand.h"
namespace ServerRuntime
{
class CliCommandKill : public IServerCliCommand
{
public:
const char *Name() const override;
const char *Usage() const override;
const char *Description() const override;
bool Execute(const ServerCliParsedLine &line, ServerCliEngine *engine) override;
void Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const override;
};
}

View file

@ -0,0 +1,118 @@
#include "stdafx.h"
#include "CliCommandTime.h"
#include "..\..\ServerCliEngine.h"
#include "..\..\ServerCliParser.h"
#include "..\..\..\Common\StringUtils.h"
#include "..\..\..\..\Minecraft.World\GameCommandPacket.h"
#include "..\..\..\..\Minecraft.World\TimeCommand.h"
namespace ServerRuntime
{
namespace
{
constexpr const char *kTimeUsage = "time <day|night|set day|set night>";
static bool TryResolveNightFlag(const std::vector<std::string> &tokens, bool *outNight)
{
if (outNight == nullptr)
{
return false;
}
std::string value;
if (tokens.size() == 2)
{
value = StringUtils::ToLowerAscii(tokens[1]);
}
else if (tokens.size() == 3 && StringUtils::ToLowerAscii(tokens[1]) == "set")
{
value = StringUtils::ToLowerAscii(tokens[2]);
}
else
{
return false;
}
if (value == "day")
{
*outNight = false;
return true;
}
if (value == "night")
{
*outNight = true;
return true;
}
return false;
}
static void SuggestLiteral(const char *candidate, const ServerCliCompletionContext &context, std::vector<std::string> *out)
{
if (candidate == nullptr || out == nullptr)
{
return;
}
const std::string text(candidate);
if (StringUtils::StartsWithIgnoreCase(text, context.prefix))
{
out->push_back(context.linePrefix + text);
}
}
}
const char *CliCommandTime::Name() const
{
return "time";
}
const char *CliCommandTime::Usage() const
{
return kTimeUsage;
}
const char *CliCommandTime::Description() const
{
return "Set day or night via Minecraft.World command dispatcher.";
}
bool CliCommandTime::Execute(const ServerCliParsedLine &line, ServerCliEngine *engine)
{
bool night = false;
if (!TryResolveNightFlag(line.tokens, &night))
{
engine->LogWarn(std::string("Usage: ") + kTimeUsage);
return false;
}
std::shared_ptr<GameCommandPacket> packet = TimeCommand::preparePacket(night);
if (packet == nullptr)
{
engine->LogError("Failed to build time command packet.");
return false;
}
return engine->DispatchWorldCommand(packet->command, packet->data);
}
void CliCommandTime::Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const
{
(void)engine;
if (context.currentTokenIndex == 1)
{
SuggestLiteral("day", context, out);
SuggestLiteral("night", context, out);
SuggestLiteral("set", context, out);
}
else if (context.currentTokenIndex == 2 &&
context.parsed.tokens.size() >= 2 &&
StringUtils::ToLowerAscii(context.parsed.tokens[1]) == "set")
{
SuggestLiteral("day", context, out);
SuggestLiteral("night", context, out);
}
}
}

View file

@ -0,0 +1,16 @@
#pragma once
#include "..\IServerCliCommand.h"
namespace ServerRuntime
{
class CliCommandTime : public IServerCliCommand
{
public:
const char *Name() const override;
const char *Usage() const override;
const char *Description() const override;
bool Execute(const ServerCliParsedLine &line, ServerCliEngine *engine) override;
void Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const override;
};
}

View file

@ -5,12 +5,17 @@
#include "..\..\ServerCliEngine.h" #include "..\..\ServerCliEngine.h"
#include "..\..\ServerCliParser.h" #include "..\..\ServerCliParser.h"
#include "..\..\..\..\Minecraft.Client\PlayerConnection.h" #include "..\..\..\..\Minecraft.Client\PlayerConnection.h"
#include "..\..\..\..\Minecraft.Client\TeleportCommand.h"
#include "..\..\..\..\Minecraft.Client\ServerPlayer.h" #include "..\..\..\..\Minecraft.Client\ServerPlayer.h"
#include "..\..\..\..\Minecraft.World\net.minecraft.world.level.h" #include "..\..\..\..\Minecraft.World\GameCommandPacket.h"
#include "..\..\..\..\Minecraft.World\net.minecraft.world.level.dimension.h"
namespace ServerRuntime namespace ServerRuntime
{ {
namespace
{
constexpr const char *kTpUsage = "tp <player> <target>";
}
const char *CliCommandTp::Name() const const char *CliCommandTp::Name() const
{ {
return "tp"; return "tp";
@ -23,49 +28,47 @@ namespace ServerRuntime
const char *CliCommandTp::Usage() const const char *CliCommandTp::Usage() const
{ {
return "tp <player> <target>"; return kTpUsage;
} }
const char *CliCommandTp::Description() const const char *CliCommandTp::Description() const
{ {
return "Teleport one player to another player."; return "Teleport one player to another via Minecraft.World command dispatcher.";
} }
bool CliCommandTp::Execute(const ServerCliParsedLine &line, ServerCliEngine *engine) bool CliCommandTp::Execute(const ServerCliParsedLine &line, ServerCliEngine *engine)
{ {
if (line.tokens.size() < 3) if (line.tokens.size() != 3)
{ {
engine->LogWarn("Usage: tp <player> <target>"); engine->LogWarn(std::string("Usage: ") + kTpUsage);
return false; return false;
} }
std::shared_ptr<ServerPlayer> subject = engine->FindPlayerByNameUtf8(line.tokens[1]); std::shared_ptr<ServerPlayer> subject = engine->FindPlayerByNameUtf8(line.tokens[1]);
std::shared_ptr<ServerPlayer> destination = engine->FindPlayerByNameUtf8(line.tokens[2]); std::shared_ptr<ServerPlayer> destination = engine->FindPlayerByNameUtf8(line.tokens[2]);
if (subject == NULL) if (subject == nullptr)
{ {
engine->LogWarn("Unknown player: " + line.tokens[1]); engine->LogWarn("Unknown player: " + line.tokens[1]);
return false; return false;
} }
if (destination == NULL) if (destination == nullptr)
{ {
engine->LogWarn("Unknown player: " + line.tokens[2]); engine->LogWarn("Unknown player: " + line.tokens[2]);
return false; return false;
} }
if (subject->connection == NULL) if (subject->connection == nullptr)
{ {
engine->LogWarn("Cannot teleport because source player connection is inactive."); engine->LogWarn("Cannot teleport because source player connection is inactive.");
return false; return false;
} }
if (subject->level == NULL || destination->level == NULL || subject->level->dimension->id != destination->level->dimension->id || !subject->isAlive()) std::shared_ptr<GameCommandPacket> packet = TeleportCommand::preparePacket(subject->getXuid(), destination->getXuid());
if (packet == nullptr)
{ {
engine->LogWarn("Teleport failed because players are in different dimensions or source player is dead."); engine->LogError("Failed to build teleport command packet.");
return false; return false;
} }
subject->ride(nullptr); return engine->DispatchWorldCommand(packet->command, packet->data);
subject->connection->teleport(destination->x, destination->y, destination->z, destination->yRot, destination->xRot);
engine->LogInfo("Teleported " + line.tokens[1] + " to " + line.tokens[2] + ".");
return true;
} }
void CliCommandTp::Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const void CliCommandTp::Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const

View file

@ -7,12 +7,12 @@ namespace ServerRuntime
class CliCommandTp : public IServerCliCommand class CliCommandTp : public IServerCliCommand
{ {
public: public:
virtual const char *Name() const; const char *Name() const override;
virtual std::vector<std::string> Aliases() const; std::vector<std::string> Aliases() const override;
virtual const char *Usage() const; const char *Usage() const override;
virtual const char *Description() const; const char *Description() const override;
virtual bool Execute(const ServerCliParsedLine &line, ServerCliEngine *engine); bool Execute(const ServerCliParsedLine &line, ServerCliEngine *engine) override;
virtual void Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const; void Complete(const ServerCliCompletionContext &context, const ServerCliEngine *engine, std::vector<std::string> *out) const override;
}; };
} }

View file

@ -0,0 +1,49 @@
#include "stdafx.h"
#include "CliCommandWeather.h"
#include "..\..\ServerCliEngine.h"
#include "..\..\ServerCliParser.h"
#include "..\..\..\..\Minecraft.World\GameCommandPacket.h"
#include "..\..\..\..\Minecraft.World\ToggleDownfallCommand.h"
namespace ServerRuntime
{
namespace
{
constexpr const char *kWeatherUsage = "weather";
}
const char *CliCommandWeather::Name() const
{
return "weather";
}
const char *CliCommandWeather::Usage() const
{
return kWeatherUsage;
}
const char *CliCommandWeather::Description() const
{
return "Toggle weather via Minecraft.World command dispatcher.";
}
bool CliCommandWeather::Execute(const ServerCliParsedLine &line, ServerCliEngine *engine)
{
if (line.tokens.size() != 1)
{
engine->LogWarn(std::string("Usage: ") + kWeatherUsage);
return false;
}
std::shared_ptr<GameCommandPacket> packet = ToggleDownfallCommand::preparePacket();
if (packet == nullptr)
{
engine->LogError("Failed to build weather command packet.");
return false;
}
return engine->DispatchWorldCommand(packet->command, packet->data);
}
}

View file

@ -0,0 +1,15 @@
#pragma once
#include "..\IServerCliCommand.h"
namespace ServerRuntime
{
class CliCommandWeather : public IServerCliCommand
{
public:
const char *Name() const override;
const char *Usage() const override;
const char *Description() const override;
bool Execute(const ServerCliParsedLine &line, ServerCliEngine *engine) override;
};
}

View file

@ -656,13 +656,20 @@
<ClCompile Include="Console\commands\ban\CliCommandBan.cpp" /> <ClCompile Include="Console\commands\ban\CliCommandBan.cpp" />
<ClCompile Include="Console\commands\ban-ip\CliCommandBanIp.cpp" /> <ClCompile Include="Console\commands\ban-ip\CliCommandBanIp.cpp" />
<ClCompile Include="Console\commands\ban-list\CliCommandBanList.cpp" /> <ClCompile Include="Console\commands\ban-list\CliCommandBanList.cpp" />
<ClCompile Include="Console\commands\defaultgamemode\CliCommandDefaultGamemode.cpp" />
<ClCompile Include="Console\commands\enchant\CliCommandEnchant.cpp" />
<ClCompile Include="Console\commands\experience\CliCommandExperience.cpp" />
<ClCompile Include="Console\commands\gamemode\CliCommandGamemode.cpp" /> <ClCompile Include="Console\commands\gamemode\CliCommandGamemode.cpp" />
<ClCompile Include="Console\commands\give\CliCommandGive.cpp" />
<ClCompile Include="Console\commands\help\CliCommandHelp.cpp" /> <ClCompile Include="Console\commands\help\CliCommandHelp.cpp" />
<ClCompile Include="Console\commands\kill\CliCommandKill.cpp" />
<ClCompile Include="Console\commands\list\CliCommandList.cpp" /> <ClCompile Include="Console\commands\list\CliCommandList.cpp" />
<ClCompile Include="Console\commands\pardon\CliCommandPardon.cpp" /> <ClCompile Include="Console\commands\pardon\CliCommandPardon.cpp" />
<ClCompile Include="Console\commands\pardon-ip\CliCommandPardonIp.cpp" /> <ClCompile Include="Console\commands\pardon-ip\CliCommandPardonIp.cpp" />
<ClCompile Include="Console\commands\stop\CliCommandStop.cpp" /> <ClCompile Include="Console\commands\stop\CliCommandStop.cpp" />
<ClCompile Include="Console\commands\time\CliCommandTime.cpp" />
<ClCompile Include="Console\commands\tp\CliCommandTp.cpp" /> <ClCompile Include="Console\commands\tp\CliCommandTp.cpp" />
<ClCompile Include="Console\commands\weather\CliCommandWeather.cpp" />
<ClCompile Include="Console\commands\whitelist\CliCommandWhitelist.cpp" /> <ClCompile Include="Console\commands\whitelist\CliCommandWhitelist.cpp" />
<ClCompile Include="Console\ServerCliEngine.cpp" /> <ClCompile Include="Console\ServerCliEngine.cpp" />
<ClCompile Include="Console\ServerCliParser.cpp" /> <ClCompile Include="Console\ServerCliParser.cpp" />
@ -692,13 +699,21 @@
<ClInclude Include="Console\commands\ban\CliCommandBan.h" /> <ClInclude Include="Console\commands\ban\CliCommandBan.h" />
<ClInclude Include="Console\commands\ban-ip\CliCommandBanIp.h" /> <ClInclude Include="Console\commands\ban-ip\CliCommandBanIp.h" />
<ClInclude Include="Console\commands\ban-list\CliCommandBanList.h" /> <ClInclude Include="Console\commands\ban-list\CliCommandBanList.h" />
<ClInclude Include="Console\commands\defaultgamemode\CliCommandDefaultGamemode.h" />
<ClInclude Include="Console\commands\enchant\CliCommandEnchant.h" />
<ClInclude Include="Console\commands\experience\CliCommandExperience.h" />
<ClInclude Include="Console\commands\gamemode\CliCommandGamemode.h" /> <ClInclude Include="Console\commands\gamemode\CliCommandGamemode.h" />
<ClInclude Include="Console\commands\give\CliCommandGive.h" />
<ClInclude Include="Console\commands\help\CliCommandHelp.h" /> <ClInclude Include="Console\commands\help\CliCommandHelp.h" />
<ClInclude Include="Console\commands\CommandParsing.h" />
<ClInclude Include="Console\commands\kill\CliCommandKill.h" />
<ClInclude Include="Console\commands\list\CliCommandList.h" /> <ClInclude Include="Console\commands\list\CliCommandList.h" />
<ClInclude Include="Console\commands\pardon\CliCommandPardon.h" /> <ClInclude Include="Console\commands\pardon\CliCommandPardon.h" />
<ClInclude Include="Console\commands\pardon-ip\CliCommandPardonIp.h" /> <ClInclude Include="Console\commands\pardon-ip\CliCommandPardonIp.h" />
<ClInclude Include="Console\commands\stop\CliCommandStop.h" /> <ClInclude Include="Console\commands\stop\CliCommandStop.h" />
<ClInclude Include="Console\commands\time\CliCommandTime.h" />
<ClInclude Include="Console\commands\tp\CliCommandTp.h" /> <ClInclude Include="Console\commands\tp\CliCommandTp.h" />
<ClInclude Include="Console\commands\weather\CliCommandWeather.h" />
<ClInclude Include="Console\commands\whitelist\CliCommandWhitelist.h" /> <ClInclude Include="Console\commands\whitelist\CliCommandWhitelist.h" />
<ClInclude Include="Console\commands\IServerCliCommand.h" /> <ClInclude Include="Console\commands\IServerCliCommand.h" />
<ClInclude Include="Console\ServerCliEngine.h" /> <ClInclude Include="Console\ServerCliEngine.h" />

View file

@ -570,12 +570,27 @@
<ClCompile Include="Console\commands\ban-list\CliCommandBanList.cpp"> <ClCompile Include="Console\commands\ban-list\CliCommandBanList.cpp">
<Filter>Server\Console\Commands</Filter> <Filter>Server\Console\Commands</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Console\commands\defaultgamemode\CliCommandDefaultGamemode.cpp">
<Filter>Server\Console\Commands</Filter>
</ClCompile>
<ClCompile Include="Console\commands\enchant\CliCommandEnchant.cpp">
<Filter>Server\Console\Commands</Filter>
</ClCompile>
<ClCompile Include="Console\commands\experience\CliCommandExperience.cpp">
<Filter>Server\Console\Commands</Filter>
</ClCompile>
<ClCompile Include="Console\commands\gamemode\CliCommandGamemode.cpp"> <ClCompile Include="Console\commands\gamemode\CliCommandGamemode.cpp">
<Filter>Server\Console\Commands</Filter> <Filter>Server\Console\Commands</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Console\commands\give\CliCommandGive.cpp">
<Filter>Server\Console\Commands</Filter>
</ClCompile>
<ClCompile Include="Console\commands\help\CliCommandHelp.cpp"> <ClCompile Include="Console\commands\help\CliCommandHelp.cpp">
<Filter>Server\Console\Commands</Filter> <Filter>Server\Console\Commands</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Console\commands\kill\CliCommandKill.cpp">
<Filter>Server\Console\Commands</Filter>
</ClCompile>
<ClCompile Include="Console\commands\list\CliCommandList.cpp"> <ClCompile Include="Console\commands\list\CliCommandList.cpp">
<Filter>Server\Console\Commands</Filter> <Filter>Server\Console\Commands</Filter>
</ClCompile> </ClCompile>
@ -588,9 +603,15 @@
<ClCompile Include="Console\commands\stop\CliCommandStop.cpp"> <ClCompile Include="Console\commands\stop\CliCommandStop.cpp">
<Filter>Server\Console\Commands</Filter> <Filter>Server\Console\Commands</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Console\commands\time\CliCommandTime.cpp">
<Filter>Server\Console\Commands</Filter>
</ClCompile>
<ClCompile Include="Console\commands\tp\CliCommandTp.cpp"> <ClCompile Include="Console\commands\tp\CliCommandTp.cpp">
<Filter>Server\Console\Commands</Filter> <Filter>Server\Console\Commands</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Console\commands\weather\CliCommandWeather.cpp">
<Filter>Server\Console\Commands</Filter>
</ClCompile>
<ClCompile Include="Console\commands\whitelist\CliCommandWhitelist.cpp"> <ClCompile Include="Console\commands\whitelist\CliCommandWhitelist.cpp">
<Filter>Server\Console\Commands</Filter> <Filter>Server\Console\Commands</Filter>
</ClCompile> </ClCompile>
@ -654,12 +675,30 @@
<ClInclude Include="Console\commands\ban-list\CliCommandBanList.h"> <ClInclude Include="Console\commands\ban-list\CliCommandBanList.h">
<Filter>Server\Console\Commands</Filter> <Filter>Server\Console\Commands</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Console\commands\defaultgamemode\CliCommandDefaultGamemode.h">
<Filter>Server\Console\Commands</Filter>
</ClInclude>
<ClInclude Include="Console\commands\enchant\CliCommandEnchant.h">
<Filter>Server\Console\Commands</Filter>
</ClInclude>
<ClInclude Include="Console\commands\experience\CliCommandExperience.h">
<Filter>Server\Console\Commands</Filter>
</ClInclude>
<ClInclude Include="Console\commands\gamemode\CliCommandGamemode.h"> <ClInclude Include="Console\commands\gamemode\CliCommandGamemode.h">
<Filter>Server\Console\Commands</Filter> <Filter>Server\Console\Commands</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Console\commands\give\CliCommandGive.h">
<Filter>Server\Console\Commands</Filter>
</ClInclude>
<ClInclude Include="Console\commands\help\CliCommandHelp.h"> <ClInclude Include="Console\commands\help\CliCommandHelp.h">
<Filter>Server\Console\Commands</Filter> <Filter>Server\Console\Commands</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Console\commands\CommandParsing.h">
<Filter>Server\Console\Commands</Filter>
</ClInclude>
<ClInclude Include="Console\commands\kill\CliCommandKill.h">
<Filter>Server\Console\Commands</Filter>
</ClInclude>
<ClInclude Include="Console\commands\list\CliCommandList.h"> <ClInclude Include="Console\commands\list\CliCommandList.h">
<Filter>Server\Console\Commands</Filter> <Filter>Server\Console\Commands</Filter>
</ClInclude> </ClInclude>
@ -672,9 +711,15 @@
<ClInclude Include="Console\commands\stop\CliCommandStop.h"> <ClInclude Include="Console\commands\stop\CliCommandStop.h">
<Filter>Server\Console\Commands</Filter> <Filter>Server\Console\Commands</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Console\commands\time\CliCommandTime.h">
<Filter>Server\Console\Commands</Filter>
</ClInclude>
<ClInclude Include="Console\commands\tp\CliCommandTp.h"> <ClInclude Include="Console\commands\tp\CliCommandTp.h">
<Filter>Server\Console\Commands</Filter> <Filter>Server\Console\Commands</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Console\commands\weather\CliCommandWeather.h">
<Filter>Server\Console\Commands</Filter>
</ClInclude>
<ClInclude Include="Console\commands\whitelist\CliCommandWhitelist.h"> <ClInclude Include="Console\commands\whitelist\CliCommandWhitelist.h">
<Filter>Server\Console\Commands</Filter> <Filter>Server\Console\Commands</Filter>
</ClInclude> </ClInclude>