mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
feat: dedicated server command addition and enhancement for some parity with java/bedrock, console prettification(?), you can FINALLY have a proper server seed, tools for moderation.
This commit is contained in:
parent
c998346312
commit
58bc706520
|
|
@ -5699,6 +5699,9 @@ bool CMinecraftApp::isXuidDeadmau5(PlayerUID xuid)
|
|||
|
||||
void CMinecraftApp::AddMemoryTextureFile(const wstring &wName,PBYTE pbData,DWORD dwBytes)
|
||||
{
|
||||
#ifdef _WINDOWS64
|
||||
extern bool g_Win64Verbose;
|
||||
#endif
|
||||
EnterCriticalSection(&csMemFilesLock);
|
||||
// check it's not already in
|
||||
PMEMDATA pData=nullptr;
|
||||
|
|
@ -5706,6 +5709,9 @@ void CMinecraftApp::AddMemoryTextureFile(const wstring &wName,PBYTE pbData,DWORD
|
|||
if(it != m_MEM_Files.end())
|
||||
{
|
||||
#ifndef _CONTENT_PACKAGE
|
||||
#ifdef _WINDOWS64
|
||||
if (g_Win64Verbose)
|
||||
#endif
|
||||
wprintf(L"Incrementing the memory texture file count for %ls\n", wName.c_str());
|
||||
#endif
|
||||
pData = (*it).second;
|
||||
|
|
|
|||
|
|
@ -195,8 +195,8 @@ void IUIScene_HUD::renderPlayerHealth()
|
|||
// Update health
|
||||
bool blink = pMinecraft->localplayers[iPad]->invulnerableTime / 3 % 2 == 1;
|
||||
if (pMinecraft->localplayers[iPad]->invulnerableTime < 10) blink = false;
|
||||
int currentHealth = pMinecraft->localplayers[iPad]->getHealth();
|
||||
int oldHealth = pMinecraft->localplayers[iPad]->lastHealth;
|
||||
int currentHealth = static_cast<int>(ceil(pMinecraft->localplayers[iPad]->getHealth()));
|
||||
int oldHealth = static_cast<int>(ceil(pMinecraft->localplayers[iPad]->lastHealth));
|
||||
bool bHasPoison = pMinecraft->localplayers[iPad]->hasEffect(MobEffect::poison);
|
||||
bool bHasWither = pMinecraft->localplayers[iPad]->hasEffect(MobEffect::wither);
|
||||
AttributeInstance *maxHealthAttribute = pMinecraft->localplayers[iPad]->getAttribute(SharedMonsterAttributes::MAX_HEALTH);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
#include "DispenserBootstrap.h"
|
||||
#include "EntityTracker.h"
|
||||
#include "MinecraftServer.h"
|
||||
#ifdef _WINDOWS64
|
||||
#include "ServerConsole.h"
|
||||
#endif
|
||||
#include "Options.h"
|
||||
#include "PlayerList.h"
|
||||
#include "ServerChunkCache.h"
|
||||
|
|
@ -58,6 +61,9 @@
|
|||
#include "..\Minecraft.World\BiomeSource.h"
|
||||
#include "PlayerChunkMap.h"
|
||||
#include "Common\Telemetry\TelemetryManager.h"
|
||||
#include "ServerCommands.h"
|
||||
#ifdef _WINDOWS64
|
||||
#endif
|
||||
#include "PlayerConnection.h"
|
||||
#ifdef _XBOX_ONE
|
||||
#include "Durango\Network\NetworkPlayerDurango.h"
|
||||
|
|
@ -726,6 +732,19 @@ bool MinecraftServer::initServer(int64_t seed, NetworkGameInitData *initData, DW
|
|||
ProgressRenderer *mcprogress = Minecraft::GetInstance()->progressRenderer;
|
||||
mcprogress->progressStart(IDS_PROGRESS_INITIALISING_SERVER);
|
||||
|
||||
if (ShouldUseDedicatedServerProperties())
|
||||
{
|
||||
wstring seedStr = GetDedicatedServerString(settings, L"seed", L"");
|
||||
if (!seedStr.empty())
|
||||
{
|
||||
int64_t parsedSeed = _wtoi64(seedStr.c_str());
|
||||
if (parsedSeed != 0)
|
||||
seed = parsedSeed;
|
||||
}
|
||||
if (seed == 0 && !findSeed)
|
||||
findSeed = true;
|
||||
}
|
||||
|
||||
if( findSeed )
|
||||
{
|
||||
#ifdef __PSVITA__
|
||||
|
|
@ -733,6 +752,10 @@ bool MinecraftServer::initServer(int64_t seed, NetworkGameInitData *initData, DW
|
|||
#else
|
||||
seed = BiomeSource::findSeed(pLevelType);
|
||||
#endif
|
||||
if (ShouldUseDedicatedServerProperties() && settings != nullptr)
|
||||
{
|
||||
settings->setStringAndSave(L"seed", std::to_wstring(seed));
|
||||
}
|
||||
}
|
||||
|
||||
setMaxBuildHeight(GetDedicatedServerInt(settings, L"max-build-height", Level::maxBuildHeight));
|
||||
|
|
@ -2208,10 +2231,13 @@ void MinecraftServer::handleConsoleInputs()
|
|||
pendingInputs.swap(consoleInput);
|
||||
LeaveCriticalSection(&m_consoleInputCS);
|
||||
|
||||
ServerCommands::initialize();
|
||||
|
||||
for (size_t i = 0; i < pendingInputs.size(); ++i)
|
||||
{
|
||||
ConsoleInput *input = pendingInputs[i];
|
||||
ExecuteConsoleCommand(this, input->msg);
|
||||
CommandSource source(this, input->source, CommandSource::CONSOLE, L"CONSOLE");
|
||||
ServerCommands::execute(this, input->msg, source);
|
||||
delete input;
|
||||
}
|
||||
}
|
||||
|
|
@ -2245,11 +2271,25 @@ File *MinecraftServer::getFile(const wstring& name)
|
|||
|
||||
void MinecraftServer::info(const wstring& string)
|
||||
{
|
||||
#ifdef _WINDOWS64
|
||||
if (ServerConsole::getInstance())
|
||||
{
|
||||
ServerConsole::logInfo(string.c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
PrintConsoleLine(L"[INFO] ", string);
|
||||
}
|
||||
|
||||
void MinecraftServer::warn(const wstring& string)
|
||||
{
|
||||
#ifdef _WINDOWS64
|
||||
if (ServerConsole::getInstance())
|
||||
{
|
||||
ServerConsole::logWarn(string.c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
PrintConsoleLine(L"[WARN] ", string);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ private:
|
|||
bool loadLevel(LevelStorageSource *storageSource, const wstring& name, int64_t levelSeed, LevelType *pLevelType, NetworkGameInitData *initData);
|
||||
void setProgress(const wstring& status, int progress);
|
||||
void endProgress();
|
||||
void saveAllChunks();
|
||||
void saveAllChunks();
|
||||
void saveGameRules();
|
||||
void stopServer(bool didInit);
|
||||
#ifdef _LARGE_WORLDS
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "ServerLevel.h"
|
||||
#include "PlayerList.h"
|
||||
#include "MinecraftServer.h"
|
||||
#include "ServerCommands.h"
|
||||
#include "..\Minecraft.World\net.minecraft.network.h"
|
||||
#include "..\Minecraft.World\pos.h"
|
||||
#include "..\Minecraft.World\net.minecraft.world.level.dimension.h"
|
||||
|
|
@ -188,6 +189,10 @@ void PendingConnection::handleLogin(shared_ptr<LoginPacket> packet)
|
|||
{
|
||||
disconnect(DisconnectPacket::eDisconnect_Banned);
|
||||
}
|
||||
else if (ServerCommands::getBanList().isBanned(name))
|
||||
{
|
||||
disconnect(DisconnectPacket::eDisconnect_Banned);
|
||||
}
|
||||
else if (duplicateXuid)
|
||||
{
|
||||
// Reject the incoming connection — a player with this UID is already
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
// 4J Added
|
||||
#include "..\Minecraft.World\net.minecraft.world.item.crafting.h"
|
||||
#include "Options.h"
|
||||
#include "ServerCommands.h"
|
||||
|
||||
Random PlayerConnection::random;
|
||||
|
||||
|
|
@ -633,10 +634,9 @@ void PlayerConnection::handleChat(shared_ptr<ChatPacket> packet)
|
|||
|
||||
void PlayerConnection::handleCommand(const wstring& message)
|
||||
{
|
||||
// 4J - TODO
|
||||
#if 0
|
||||
server.getCommandDispatcher().performCommand(player, message);
|
||||
#endif
|
||||
ServerCommands::initialize();
|
||||
CommandSource source(server, player);
|
||||
ServerCommands::execute(server, message, source);
|
||||
}
|
||||
|
||||
void PlayerConnection::handleAnimate(shared_ptr<AnimatePacket> packet)
|
||||
|
|
|
|||
1642
Minecraft.Client/ServerCommands.cpp
Normal file
1642
Minecraft.Client/ServerCommands.cpp
Normal file
File diff suppressed because it is too large
Load diff
144
Minecraft.Client/ServerCommands.h
Normal file
144
Minecraft.Client/ServerCommands.h
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <functional>
|
||||
|
||||
class MinecraftServer;
|
||||
class ServerPlayer;
|
||||
class ConsoleInputSource;
|
||||
class PlayerList;
|
||||
|
||||
// Command sender abstraction - can be server console or a player
|
||||
class CommandSource
|
||||
{
|
||||
public:
|
||||
enum Type { CONSOLE, PLAYER };
|
||||
|
||||
CommandSource(MinecraftServer* server, ConsoleInputSource* source, Type type, const wstring& name);
|
||||
CommandSource(MinecraftServer* server, shared_ptr<ServerPlayer> player);
|
||||
|
||||
void sendMessage(const wstring& message);
|
||||
void sendSuccess(const wstring& message);
|
||||
void sendError(const wstring& message);
|
||||
|
||||
bool isConsole() const { return m_type == CONSOLE; }
|
||||
bool isPlayer() const { return m_type == PLAYER; }
|
||||
bool isOp() const;
|
||||
|
||||
MinecraftServer* getServer() const { return m_server; }
|
||||
shared_ptr<ServerPlayer> getPlayer() const { return m_player; }
|
||||
wstring getName() const { return m_name; }
|
||||
|
||||
private:
|
||||
MinecraftServer* m_server;
|
||||
ConsoleInputSource* m_consoleSource;
|
||||
shared_ptr<ServerPlayer> m_player;
|
||||
Type m_type;
|
||||
wstring m_name;
|
||||
};
|
||||
|
||||
// Server-side op list management
|
||||
class OpList
|
||||
{
|
||||
public:
|
||||
void addOp(const wstring& name);
|
||||
void removeOp(const wstring& name);
|
||||
bool isOp(const wstring& name) const;
|
||||
const unordered_set<wstring>& getOps() const { return m_ops; }
|
||||
|
||||
void save() const;
|
||||
void load();
|
||||
|
||||
private:
|
||||
unordered_set<wstring> m_ops;
|
||||
};
|
||||
|
||||
// Server-side ban list management (persistent)
|
||||
class BanList
|
||||
{
|
||||
public:
|
||||
void ban(const wstring& name, const wstring& reason = L"");
|
||||
void unban(const wstring& name);
|
||||
bool isBanned(const wstring& name) const;
|
||||
wstring getBanReason(const wstring& name) const;
|
||||
const unordered_map<wstring, wstring>& getBans() const { return m_bans; }
|
||||
|
||||
void save() const;
|
||||
void load();
|
||||
|
||||
private:
|
||||
unordered_map<wstring, wstring> m_bans; // name -> reason
|
||||
};
|
||||
|
||||
// Vanish manager
|
||||
class VanishManager
|
||||
{
|
||||
public:
|
||||
void setVanished(const wstring& name, bool vanished);
|
||||
bool isVanished(const wstring& name) const;
|
||||
const unordered_set<wstring>& getVanished() const { return m_vanished; }
|
||||
|
||||
private:
|
||||
unordered_set<wstring> m_vanished;
|
||||
};
|
||||
|
||||
// Main command registry and execution engine
|
||||
class ServerCommands
|
||||
{
|
||||
public:
|
||||
static void initialize();
|
||||
|
||||
// Execute a command string (with or without leading /)
|
||||
static bool execute(MinecraftServer* server, const wstring& rawCommand, CommandSource& source);
|
||||
|
||||
// Access op and vanish managers
|
||||
static OpList& getOpList() { return s_opList; }
|
||||
static VanishManager& getVanishManager() { return s_vanishManager; }
|
||||
static BanList& getBanList() { return s_banList; }
|
||||
|
||||
private:
|
||||
// Utility functions
|
||||
static vector<wstring> splitCommand(const wstring& command);
|
||||
static wstring joinTokens(const vector<wstring>& tokens, size_t startIndex);
|
||||
static bool tryParseInt(const wstring& text, int& value);
|
||||
static bool tryParseDouble(const wstring& text, double& value);
|
||||
static shared_ptr<ServerPlayer> findPlayer(PlayerList* playerList, const wstring& name);
|
||||
static vector<shared_ptr<ServerPlayer>> resolvePlayerSelector(MinecraftServer* server, const wstring& selector, CommandSource& source);
|
||||
|
||||
// Command handlers
|
||||
static bool cmdHelp(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdStop(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdList(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdSay(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdSaveAll(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdKill(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdGamemode(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdTeleport(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdGive(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdEnchant(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdTime(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdWeather(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdSummon(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdSetblock(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdFill(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdEffect(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdClear(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdVanish(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdOp(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdDeop(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdKick(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdBan(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdUnban(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
static bool cmdBanList(MinecraftServer* server, const vector<wstring>& tokens, CommandSource& source);
|
||||
|
||||
// Command handler map
|
||||
typedef bool (*CommandHandler)(MinecraftServer*, const vector<wstring>&, CommandSource&);
|
||||
static unordered_map<wstring, CommandHandler> s_commands;
|
||||
static unordered_set<wstring> s_opOnlyCommands;
|
||||
static OpList s_opList;
|
||||
static BanList s_banList;
|
||||
static VanishManager s_vanishManager;
|
||||
static bool s_initialized;
|
||||
};
|
||||
766
Minecraft.Client/ServerConsole.cpp
Normal file
766
Minecraft.Client/ServerConsole.cpp
Normal file
|
|
@ -0,0 +1,766 @@
|
|||
#include "stdafx.h"
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
|
||||
#include "ServerConsole.h"
|
||||
#include "MinecraftServer.h"
|
||||
#include "PlayerList.h"
|
||||
#include "ServerPlayer.h"
|
||||
#include "..\Minecraft.World\StringHelpers.h"
|
||||
#include "..\Minecraft.World\EntityIO.h"
|
||||
#include "..\Minecraft.World\Tile.h"
|
||||
#include "..\Minecraft.World\MobEffect.h"
|
||||
#include "..\Minecraft.World\LevelSettings.h"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <cstdio>
|
||||
|
||||
ServerConsole* ServerConsole::s_instance = nullptr;
|
||||
|
||||
const char* ServerConsole::Color::Reset = "\033[0m";
|
||||
const char* ServerConsole::Color::Red = "\033[31m";
|
||||
const char* ServerConsole::Color::Green = "\033[32m";
|
||||
const char* ServerConsole::Color::Yellow = "\033[33m";
|
||||
const char* ServerConsole::Color::Blue = "\033[34m";
|
||||
const char* ServerConsole::Color::Magenta = "\033[35m";
|
||||
const char* ServerConsole::Color::Cyan = "\033[36m";
|
||||
const char* ServerConsole::Color::White = "\033[37m";
|
||||
const char* ServerConsole::Color::Gray = "\033[90m";
|
||||
const char* ServerConsole::Color::BrightRed = "\033[91m";
|
||||
const char* ServerConsole::Color::BrightGreen = "\033[92m";
|
||||
const char* ServerConsole::Color::BrightYellow= "\033[93m";
|
||||
const char* ServerConsole::Color::BrightBlue = "\033[94m";
|
||||
const char* ServerConsole::Color::BrightMagenta="\033[95m";
|
||||
const char* ServerConsole::Color::BrightCyan = "\033[96m";
|
||||
const char* ServerConsole::Color::BrightWhite = "\033[97m";
|
||||
|
||||
// Known command names for completion and highlighting
|
||||
static const char* s_commandNames[] = {
|
||||
"help", "stop", "list", "say", "save-all",
|
||||
"kill", "gamemode", "teleport", "tp", "give", "giveitem",
|
||||
"enchant", "enchantitem", "time", "weather", "summon",
|
||||
"setblock", "fill", "effect", "clear", "vanish", "op", "deop",
|
||||
"kick", "ban", "unban", "pardon", "banlist",
|
||||
nullptr
|
||||
};
|
||||
|
||||
// Subcommand completions for specific commands
|
||||
static const char* s_timeSubcmds[] = { "set", "add", "query", nullptr };
|
||||
static const char* s_timeSetValues[] = { "day", "night", "noon", "midnight", nullptr };
|
||||
static const char* s_weatherTypes[] = { "clear", "rain", "thunder", nullptr };
|
||||
static const char* s_gamemodeNames[] = { "survival", "creative", "adventure", "0", "1", "2", "s", "c", "a", nullptr };
|
||||
static const char* s_effectActions[] = { "give", "clear", nullptr };
|
||||
|
||||
ServerConsole::ServerConsole(MinecraftServer* server)
|
||||
: m_server(server)
|
||||
, m_cursorPos(0)
|
||||
, m_historyIndex(-1)
|
||||
, m_tabIndex(-1)
|
||||
, m_running(true)
|
||||
{
|
||||
m_hConsoleIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||
m_hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
s_instance = this;
|
||||
}
|
||||
|
||||
ServerConsole::~ServerConsole()
|
||||
{
|
||||
if (s_instance == this)
|
||||
s_instance = nullptr;
|
||||
}
|
||||
|
||||
void ServerConsole::enableVirtualTerminal()
|
||||
{
|
||||
DWORD dwMode = 0;
|
||||
if (GetConsoleMode(m_hConsoleOut, &dwMode))
|
||||
{
|
||||
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
SetConsoleMode(m_hConsoleOut, dwMode);
|
||||
}
|
||||
|
||||
if (GetConsoleMode(m_hConsoleIn, &dwMode))
|
||||
{
|
||||
// Disable line input and echo so we can handle raw key events
|
||||
dwMode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT);
|
||||
dwMode |= ENABLE_WINDOW_INPUT;
|
||||
SetConsoleMode(m_hConsoleIn, dwMode);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerConsole::logInfo(const char* fmt, ...)
|
||||
{
|
||||
ServerConsole* sc = getInstance();
|
||||
if (sc) sc->clearInputLine();
|
||||
|
||||
char buf[2048];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
printf("%s[INFO]%s %s\n", Color::BrightCyan, Color::Reset, buf);
|
||||
fflush(stdout);
|
||||
|
||||
if (sc) sc->redrawInputLine();
|
||||
}
|
||||
|
||||
void ServerConsole::logWarn(const char* fmt, ...)
|
||||
{
|
||||
ServerConsole* sc = getInstance();
|
||||
if (sc) sc->clearInputLine();
|
||||
|
||||
char buf[2048];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
printf("%s[WARN]%s %s%s%s\n", Color::BrightYellow, Color::Reset, Color::Yellow, buf, Color::Reset);
|
||||
fflush(stdout);
|
||||
|
||||
if (sc) sc->redrawInputLine();
|
||||
}
|
||||
|
||||
void ServerConsole::logError(const char* fmt, ...)
|
||||
{
|
||||
ServerConsole* sc = getInstance();
|
||||
if (sc) sc->clearInputLine();
|
||||
|
||||
char buf[2048];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
printf("%s[ERROR]%s %s%s%s\n", Color::BrightRed, Color::Reset, Color::Red, buf, Color::Reset);
|
||||
fflush(stdout);
|
||||
|
||||
if (sc) sc->redrawInputLine();
|
||||
}
|
||||
|
||||
void ServerConsole::logSuccess(const char* fmt, ...)
|
||||
{
|
||||
ServerConsole* sc = getInstance();
|
||||
if (sc) sc->clearInputLine();
|
||||
|
||||
char buf[2048];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
printf("%s[INFO]%s %s%s%s\n", Color::BrightGreen, Color::Reset, Color::Green, buf, Color::Reset);
|
||||
fflush(stdout);
|
||||
|
||||
if (sc) sc->redrawInputLine();
|
||||
}
|
||||
|
||||
void ServerConsole::logCommand(const char* label, const char* message)
|
||||
{
|
||||
ServerConsole* sc = getInstance();
|
||||
if (sc) sc->clearInputLine();
|
||||
|
||||
printf("%s[%s]%s %s\n", Color::BrightMagenta, label, Color::Reset, message);
|
||||
fflush(stdout);
|
||||
|
||||
if (sc) sc->redrawInputLine();
|
||||
}
|
||||
|
||||
void ServerConsole::logInfo(const wchar_t* message)
|
||||
{
|
||||
ServerConsole* sc = getInstance();
|
||||
if (sc) sc->clearInputLine();
|
||||
|
||||
printf("%s[INFO]%s %ls\n", Color::BrightCyan, Color::Reset, message);
|
||||
fflush(stdout);
|
||||
|
||||
if (sc) sc->redrawInputLine();
|
||||
}
|
||||
|
||||
void ServerConsole::logWarn(const wchar_t* message)
|
||||
{
|
||||
ServerConsole* sc = getInstance();
|
||||
if (sc) sc->clearInputLine();
|
||||
|
||||
printf("%s[WARN]%s %s%ls%s\n", Color::BrightYellow, Color::Reset, Color::Yellow, message, Color::Reset);
|
||||
fflush(stdout);
|
||||
|
||||
if (sc) sc->redrawInputLine();
|
||||
}
|
||||
|
||||
void ServerConsole::logError(const wchar_t* message)
|
||||
{
|
||||
ServerConsole* sc = getInstance();
|
||||
if (sc) sc->clearInputLine();
|
||||
|
||||
printf("%s[ERROR]%s %s%ls%s\n", Color::BrightRed, Color::Reset, Color::Red, message, Color::Reset);
|
||||
fflush(stdout);
|
||||
|
||||
if (sc) sc->redrawInputLine();
|
||||
}
|
||||
|
||||
void ServerConsole::printPrompt()
|
||||
{
|
||||
printf("%s> %s", Color::BrightGreen, Color::Reset);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void ServerConsole::clearInputLine()
|
||||
{
|
||||
// Move to start of line, clear it
|
||||
printf("\r\033[K");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void ServerConsole::redrawInputLine()
|
||||
{
|
||||
printf("\r\033[K");
|
||||
printPrompt();
|
||||
|
||||
if (!m_inputBuffer.empty())
|
||||
{
|
||||
std::string highlighted = highlightCommand(m_inputBuffer);
|
||||
printf("%s", highlighted.c_str());
|
||||
}
|
||||
|
||||
// Position cursor correctly
|
||||
int promptLen = 2; // "> "
|
||||
int targetCol = promptLen + m_cursorPos;
|
||||
printf("\r\033[%dC", targetCol);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
std::string ServerConsole::highlightCommand(const std::string& input)
|
||||
{
|
||||
if (input.empty()) return input;
|
||||
|
||||
std::string result;
|
||||
std::istringstream stream(input);
|
||||
std::string token;
|
||||
bool firstToken = true;
|
||||
size_t pos = 0;
|
||||
|
||||
// Find the first word (command name)
|
||||
size_t firstSpace = input.find(' ');
|
||||
std::string cmdName = (firstSpace != std::string::npos) ? input.substr(0, firstSpace) : input;
|
||||
std::string cmdLower = cmdName;
|
||||
std::transform(cmdLower.begin(), cmdLower.end(), cmdLower.begin(), ::tolower);
|
||||
|
||||
// Check if it starts with /
|
||||
size_t cmdStart = 0;
|
||||
if (!cmdLower.empty() && cmdLower[0] == '/')
|
||||
{
|
||||
result += Color::Gray;
|
||||
result += '/';
|
||||
cmdLower = cmdLower.substr(1);
|
||||
cmdName = cmdName.substr(1);
|
||||
cmdStart = 1;
|
||||
}
|
||||
|
||||
// Highlight command name
|
||||
bool knownCmd = false;
|
||||
for (int i = 0; s_commandNames[i] != nullptr; ++i)
|
||||
{
|
||||
if (cmdLower == s_commandNames[i])
|
||||
{
|
||||
knownCmd = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (knownCmd)
|
||||
result += std::string(Color::BrightGreen) + cmdName + Color::Reset;
|
||||
else
|
||||
result += std::string(Color::BrightRed) + cmdName + Color::Reset;
|
||||
|
||||
// Highlight rest (arguments)
|
||||
if (firstSpace != std::string::npos)
|
||||
{
|
||||
std::string rest = input.substr(firstSpace);
|
||||
// Color numbers differently from strings
|
||||
std::string argResult;
|
||||
bool inNumber = false;
|
||||
for (size_t i = 0; i < rest.size(); ++i)
|
||||
{
|
||||
char c = rest[i];
|
||||
if (c == ' ')
|
||||
{
|
||||
if (inNumber) { argResult += Color::Reset; inNumber = false; }
|
||||
argResult += c;
|
||||
}
|
||||
else if ((c >= '0' && c <= '9') || c == '-' || c == '.')
|
||||
{
|
||||
if (!inNumber) { argResult += Color::BrightYellow; inNumber = true; }
|
||||
argResult += c;
|
||||
}
|
||||
else if (c == '~')
|
||||
{
|
||||
if (inNumber) { argResult += Color::Reset; inNumber = false; }
|
||||
argResult += Color::BrightMagenta;
|
||||
argResult += c;
|
||||
argResult += Color::Reset;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inNumber) { argResult += Color::Reset; inNumber = false; }
|
||||
argResult += Color::BrightWhite;
|
||||
argResult += c;
|
||||
argResult += Color::Reset;
|
||||
}
|
||||
}
|
||||
if (inNumber) argResult += Color::Reset;
|
||||
result += argResult;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string toLowerStr(const std::string& s)
|
||||
{
|
||||
std::string r = s;
|
||||
std::transform(r.begin(), r.end(), r.begin(), ::tolower);
|
||||
return r;
|
||||
}
|
||||
|
||||
std::vector<std::string> ServerConsole::getCompletions(const std::string& partial)
|
||||
{
|
||||
std::vector<std::string> results;
|
||||
if (partial.empty()) return results;
|
||||
|
||||
// Parse the input to figure out what we're completing
|
||||
std::string input = partial;
|
||||
bool hasSlash = false;
|
||||
if (!input.empty() && input[0] == '/')
|
||||
{
|
||||
hasSlash = true;
|
||||
input = input.substr(1);
|
||||
}
|
||||
|
||||
// Split into tokens
|
||||
std::vector<std::string> tokens;
|
||||
{
|
||||
std::istringstream ss(input);
|
||||
std::string tok;
|
||||
while (ss >> tok) tokens.push_back(tok);
|
||||
}
|
||||
|
||||
// If input ends with a space, we're completing the NEXT token
|
||||
bool completingNext = (!partial.empty() && partial.back() == ' ');
|
||||
if (completingNext) tokens.push_back("");
|
||||
|
||||
if (tokens.empty())
|
||||
{
|
||||
// Complete command names
|
||||
for (int i = 0; s_commandNames[i] != nullptr; ++i)
|
||||
{
|
||||
std::string name = s_commandNames[i];
|
||||
results.push_back(hasSlash ? ("/" + name) : name);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
if (tokens.size() == 1)
|
||||
{
|
||||
// Complete command name
|
||||
std::string prefix = toLowerStr(tokens[0]);
|
||||
for (int i = 0; s_commandNames[i] != nullptr; ++i)
|
||||
{
|
||||
std::string name = s_commandNames[i];
|
||||
if (name.find(prefix) == 0)
|
||||
{
|
||||
results.push_back(hasSlash ? ("/" + name) : name);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
// Token 1+ : subcommand or argument completions
|
||||
std::string cmdName = toLowerStr(tokens[0]);
|
||||
std::string argPrefix = toLowerStr(tokens.back());
|
||||
|
||||
// Subcommand completions
|
||||
const char** subCmds = nullptr;
|
||||
if (tokens.size() == 2)
|
||||
{
|
||||
if (cmdName == "time") subCmds = s_timeSubcmds;
|
||||
else if (cmdName == "weather") subCmds = s_weatherTypes;
|
||||
else if (cmdName == "gamemode") subCmds = s_gamemodeNames;
|
||||
else if (cmdName == "effect") subCmds = s_effectActions;
|
||||
}
|
||||
else if (tokens.size() == 3 && cmdName == "time" && toLowerStr(tokens[1]) == "set")
|
||||
{
|
||||
subCmds = s_timeSetValues;
|
||||
}
|
||||
|
||||
if (subCmds != nullptr)
|
||||
{
|
||||
for (int i = 0; subCmds[i] != nullptr; ++i)
|
||||
{
|
||||
std::string sub = subCmds[i];
|
||||
if (sub.find(argPrefix) == 0)
|
||||
{
|
||||
results.push_back(sub);
|
||||
}
|
||||
}
|
||||
// Don't return yet - also try player names
|
||||
}
|
||||
|
||||
// Player name completions for commands that take player names
|
||||
bool wantsPlayerName = false;
|
||||
if (cmdName == "kill" || cmdName == "tp" || cmdName == "teleport" ||
|
||||
cmdName == "give" || cmdName == "giveitem" || cmdName == "enchant" || cmdName == "enchantitem" ||
|
||||
cmdName == "gamemode" || cmdName == "effect" || cmdName == "clear" ||
|
||||
cmdName == "vanish" || cmdName == "op" || cmdName == "deop" ||
|
||||
cmdName == "kick" || cmdName == "ban")
|
||||
{
|
||||
// Most commands take a player name as the first or second arg
|
||||
wantsPlayerName = true;
|
||||
}
|
||||
|
||||
if (wantsPlayerName)
|
||||
{
|
||||
MinecraftServer* server = MinecraftServer::getInstance();
|
||||
if (server != nullptr)
|
||||
{
|
||||
PlayerList* playerList = server->getPlayers();
|
||||
if (playerList != nullptr)
|
||||
{
|
||||
for (size_t i = 0; i < playerList->players.size(); ++i)
|
||||
{
|
||||
if (playerList->players[i] != nullptr)
|
||||
{
|
||||
wstring wname = playerList->players[i]->getName();
|
||||
// Convert to narrow string
|
||||
std::string name(wname.begin(), wname.end());
|
||||
std::string nameLower = toLowerStr(name);
|
||||
if (nameLower.find(argPrefix) == 0)
|
||||
{
|
||||
results.push_back(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add @a, @p, @r, @s selectors
|
||||
const char* selectors[] = { "@a", "@p", "@r", "@s", nullptr };
|
||||
for (int i = 0; selectors[i] != nullptr; ++i)
|
||||
{
|
||||
std::string sel = selectors[i];
|
||||
if (sel.find(argPrefix) == 0)
|
||||
results.push_back(sel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Entity name completions for summon (use public idsSpawnableInCreative)
|
||||
if (cmdName == "summon" && tokens.size() == 2)
|
||||
{
|
||||
for (auto& pair : EntityIO::idsSpawnableInCreative)
|
||||
{
|
||||
wstring wname = EntityIO::getEncodeId(pair.first);
|
||||
if (!wname.empty())
|
||||
{
|
||||
std::string name(wname.begin(), wname.end());
|
||||
std::string nameLower = toLowerStr(name);
|
||||
if (nameLower.find(argPrefix) == 0)
|
||||
{
|
||||
results.push_back(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
void ServerConsole::handleTabCompletion()
|
||||
{
|
||||
if (m_tabIndex == -1)
|
||||
{
|
||||
// Start new tab completion
|
||||
m_tabPartial = m_inputBuffer;
|
||||
m_tabCompletions = getCompletions(m_tabPartial);
|
||||
if (m_tabCompletions.empty()) return;
|
||||
m_tabIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tabIndex = (m_tabIndex + 1) % (int)m_tabCompletions.size();
|
||||
}
|
||||
|
||||
if (m_tabCompletions.empty()) return;
|
||||
|
||||
// Figure out what portion to replace
|
||||
// Find the last space in the partial to know what word we're completing
|
||||
std::string completion = m_tabCompletions[m_tabIndex];
|
||||
|
||||
size_t lastSpace = m_tabPartial.rfind(' ');
|
||||
if (lastSpace == std::string::npos)
|
||||
{
|
||||
// Replacing the whole input
|
||||
m_inputBuffer = completion;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Replacing the last word
|
||||
m_inputBuffer = m_tabPartial.substr(0, lastSpace + 1) + completion;
|
||||
}
|
||||
|
||||
m_cursorPos = (int)m_inputBuffer.size();
|
||||
|
||||
// If there are multiple completions, show them
|
||||
if (m_tabCompletions.size() > 1)
|
||||
{
|
||||
clearInputLine();
|
||||
printf("\r\n");
|
||||
for (size_t i = 0; i < m_tabCompletions.size(); ++i)
|
||||
{
|
||||
if ((int)i == m_tabIndex)
|
||||
printf("%s%s%s ", Color::BrightGreen, m_tabCompletions[i].c_str(), Color::Reset);
|
||||
else
|
||||
printf("%s ", m_tabCompletions[i].c_str());
|
||||
}
|
||||
printf("\r\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
redrawInputLine();
|
||||
}
|
||||
|
||||
void ServerConsole::insertChar(char c)
|
||||
{
|
||||
if ((int)m_inputBuffer.size() >= MAX_INPUT_LENGTH) return;
|
||||
|
||||
m_inputBuffer.insert(m_inputBuffer.begin() + m_cursorPos, c);
|
||||
m_cursorPos++;
|
||||
m_tabIndex = -1; // Reset tab completion
|
||||
redrawInputLine();
|
||||
}
|
||||
|
||||
void ServerConsole::deleteCharBack()
|
||||
{
|
||||
if (m_cursorPos > 0)
|
||||
{
|
||||
m_inputBuffer.erase(m_cursorPos - 1, 1);
|
||||
m_cursorPos--;
|
||||
m_tabIndex = -1;
|
||||
redrawInputLine();
|
||||
}
|
||||
}
|
||||
|
||||
void ServerConsole::deleteCharForward()
|
||||
{
|
||||
if (m_cursorPos < (int)m_inputBuffer.size())
|
||||
{
|
||||
m_inputBuffer.erase(m_cursorPos, 1);
|
||||
m_tabIndex = -1;
|
||||
redrawInputLine();
|
||||
}
|
||||
}
|
||||
|
||||
void ServerConsole::moveCursorLeft()
|
||||
{
|
||||
if (m_cursorPos > 0)
|
||||
{
|
||||
m_cursorPos--;
|
||||
redrawInputLine();
|
||||
}
|
||||
}
|
||||
|
||||
void ServerConsole::moveCursorRight()
|
||||
{
|
||||
if (m_cursorPos < (int)m_inputBuffer.size())
|
||||
{
|
||||
m_cursorPos++;
|
||||
redrawInputLine();
|
||||
}
|
||||
}
|
||||
|
||||
void ServerConsole::moveCursorHome()
|
||||
{
|
||||
m_cursorPos = 0;
|
||||
redrawInputLine();
|
||||
}
|
||||
|
||||
void ServerConsole::moveCursorEnd()
|
||||
{
|
||||
m_cursorPos = (int)m_inputBuffer.size();
|
||||
redrawInputLine();
|
||||
}
|
||||
|
||||
void ServerConsole::historyUp()
|
||||
{
|
||||
if (m_history.empty()) return;
|
||||
|
||||
if (m_historyIndex == -1)
|
||||
{
|
||||
m_savedInput = m_inputBuffer;
|
||||
m_historyIndex = 0;
|
||||
}
|
||||
else if (m_historyIndex < (int)m_history.size() - 1)
|
||||
{
|
||||
m_historyIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return; // at oldest entry
|
||||
}
|
||||
|
||||
m_inputBuffer = m_history[m_historyIndex];
|
||||
m_cursorPos = (int)m_inputBuffer.size();
|
||||
m_tabIndex = -1;
|
||||
redrawInputLine();
|
||||
}
|
||||
|
||||
void ServerConsole::historyDown()
|
||||
{
|
||||
if (m_historyIndex == -1) return;
|
||||
|
||||
m_historyIndex--;
|
||||
if (m_historyIndex < 0)
|
||||
{
|
||||
m_historyIndex = -1;
|
||||
m_inputBuffer = m_savedInput;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_inputBuffer = m_history[m_historyIndex];
|
||||
}
|
||||
|
||||
m_cursorPos = (int)m_inputBuffer.size();
|
||||
m_tabIndex = -1;
|
||||
redrawInputLine();
|
||||
}
|
||||
|
||||
void ServerConsole::readInputLine(std::string& outLine)
|
||||
{
|
||||
m_inputBuffer.clear();
|
||||
m_cursorPos = 0;
|
||||
m_historyIndex = -1;
|
||||
m_tabIndex = -1;
|
||||
m_savedInput.clear();
|
||||
|
||||
printPrompt();
|
||||
|
||||
while (m_running)
|
||||
{
|
||||
INPUT_RECORD ir;
|
||||
DWORD count = 0;
|
||||
|
||||
if (!ReadConsoleInputA(m_hConsoleIn, &ir, 1, &count) || count == 0)
|
||||
{
|
||||
Sleep(10);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ir.EventType != KEY_EVENT || !ir.Event.KeyEvent.bKeyDown)
|
||||
continue;
|
||||
|
||||
KEY_EVENT_RECORD& key = ir.Event.KeyEvent;
|
||||
WORD vk = key.wVirtualKeyCode;
|
||||
char ch = key.uChar.AsciiChar;
|
||||
|
||||
if (vk == VK_RETURN)
|
||||
{
|
||||
printf("\r\n");
|
||||
fflush(stdout);
|
||||
outLine = m_inputBuffer;
|
||||
return;
|
||||
}
|
||||
else if (vk == VK_TAB)
|
||||
{
|
||||
handleTabCompletion();
|
||||
}
|
||||
else if (vk == VK_BACK)
|
||||
{
|
||||
deleteCharBack();
|
||||
}
|
||||
else if (vk == VK_DELETE)
|
||||
{
|
||||
deleteCharForward();
|
||||
}
|
||||
else if (vk == VK_LEFT)
|
||||
{
|
||||
moveCursorLeft();
|
||||
}
|
||||
else if (vk == VK_RIGHT)
|
||||
{
|
||||
moveCursorRight();
|
||||
}
|
||||
else if (vk == VK_UP)
|
||||
{
|
||||
historyUp();
|
||||
}
|
||||
else if (vk == VK_DOWN)
|
||||
{
|
||||
historyDown();
|
||||
}
|
||||
else if (vk == VK_HOME)
|
||||
{
|
||||
moveCursorHome();
|
||||
}
|
||||
else if (vk == VK_END)
|
||||
{
|
||||
moveCursorEnd();
|
||||
}
|
||||
else if (vk == VK_ESCAPE)
|
||||
{
|
||||
m_inputBuffer.clear();
|
||||
m_cursorPos = 0;
|
||||
m_tabIndex = -1;
|
||||
redrawInputLine();
|
||||
}
|
||||
else if (ch >= 32 && ch < 127)
|
||||
{
|
||||
insertChar(ch);
|
||||
}
|
||||
}
|
||||
|
||||
outLine.clear();
|
||||
}
|
||||
|
||||
void ServerConsole::run()
|
||||
{
|
||||
enableVirtualTerminal();
|
||||
|
||||
printf("\n%s========================================%s\n", Color::BrightCyan, Color::Reset);
|
||||
printf("%s Minecraft Legacy Console Server%s\n", Color::BrightWhite, Color::Reset);
|
||||
printf("%s========================================%s\n", Color::BrightCyan, Color::Reset);
|
||||
printf("Type %shelp%s for available commands.\n", Color::BrightGreen, Color::Reset);
|
||||
printf("Use %sTab%s for auto-completion.\n\n", Color::BrightYellow, Color::Reset);
|
||||
|
||||
while (m_running && !MinecraftServer::serverHalted())
|
||||
{
|
||||
std::string line;
|
||||
readInputLine(line);
|
||||
|
||||
if (!m_running || MinecraftServer::serverHalted()) break;
|
||||
|
||||
// Trim
|
||||
size_t start = line.find_first_not_of(" \t");
|
||||
size_t end = line.find_last_not_of(" \t");
|
||||
if (start == std::string::npos) continue;
|
||||
line = line.substr(start, end - start + 1);
|
||||
|
||||
if (line.empty()) continue;
|
||||
|
||||
// Add to history (avoid duplicates at front)
|
||||
if (m_history.empty() || m_history.front() != line)
|
||||
{
|
||||
m_history.push_front(line);
|
||||
if ((int)m_history.size() > MAX_HISTORY)
|
||||
m_history.pop_back();
|
||||
}
|
||||
|
||||
// Convert to wstring and send to server
|
||||
wstring command = convStringToWstring(line);
|
||||
|
||||
if (m_server != nullptr)
|
||||
{
|
||||
m_server->handleConsoleInput(command, m_server);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _WINDOWS64
|
||||
92
Minecraft.Client/ServerConsole.h
Normal file
92
Minecraft.Client/ServerConsole.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
#pragma once
|
||||
#ifdef _WINDOWS64
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
#include <windows.h>
|
||||
|
||||
class MinecraftServer;
|
||||
|
||||
class ServerConsole
|
||||
{
|
||||
public:
|
||||
static const int MAX_HISTORY = 500;
|
||||
static const int MAX_INPUT_LENGTH = 512;
|
||||
|
||||
struct Color
|
||||
{
|
||||
static const char* Reset;
|
||||
static const char* Red;
|
||||
static const char* Green;
|
||||
static const char* Yellow;
|
||||
static const char* Blue;
|
||||
static const char* Magenta;
|
||||
static const char* Cyan;
|
||||
static const char* White;
|
||||
static const char* Gray;
|
||||
static const char* BrightRed;
|
||||
static const char* BrightGreen;
|
||||
static const char* BrightYellow;
|
||||
static const char* BrightBlue;
|
||||
static const char* BrightMagenta;
|
||||
static const char* BrightCyan;
|
||||
static const char* BrightWhite;
|
||||
};
|
||||
|
||||
ServerConsole(MinecraftServer* server);
|
||||
~ServerConsole();
|
||||
|
||||
void enableVirtualTerminal();
|
||||
|
||||
void run();
|
||||
static void logInfo(const char* fmt, ...);
|
||||
static void logWarn(const char* fmt, ...);
|
||||
static void logError(const char* fmt, ...);
|
||||
static void logSuccess(const char* fmt, ...);
|
||||
static void logCommand(const char* label, const char* message);
|
||||
static void logInfo(const wchar_t* message);
|
||||
static void logWarn(const wchar_t* message);
|
||||
static void logError(const wchar_t* message);
|
||||
|
||||
std::vector<std::string> getCompletions(const std::string& partial);
|
||||
|
||||
static ServerConsole* getInstance() { return s_instance; }
|
||||
|
||||
private:
|
||||
void readInputLine(std::string& outLine);
|
||||
void redrawInputLine();
|
||||
void clearInputLine();
|
||||
void handleTabCompletion();
|
||||
void insertChar(char c);
|
||||
void deleteCharBack();
|
||||
void deleteCharForward();
|
||||
void moveCursorLeft();
|
||||
void moveCursorRight();
|
||||
void moveCursorHome();
|
||||
void moveCursorEnd();
|
||||
void historyUp();
|
||||
void historyDown();
|
||||
std::string highlightCommand(const std::string& input);
|
||||
void printPrompt();
|
||||
|
||||
MinecraftServer* m_server;
|
||||
std::string m_inputBuffer;
|
||||
int m_cursorPos;
|
||||
std::deque<std::string> m_history;
|
||||
int m_historyIndex;
|
||||
std::string m_savedInput;
|
||||
|
||||
std::vector<std::string> m_tabCompletions;
|
||||
int m_tabIndex;
|
||||
std::string m_tabPartial;
|
||||
|
||||
HANDLE m_hConsoleIn;
|
||||
HANDLE m_hConsoleOut;
|
||||
bool m_running;
|
||||
|
||||
static ServerConsole* s_instance;
|
||||
};
|
||||
|
||||
#endif // _WINDOWS64
|
||||
|
|
@ -124,4 +124,10 @@ void Settings::setBooleanAndSave(const wstring& key, bool value)
|
|||
{
|
||||
properties[key] = value ? L"true" : L"false";
|
||||
saveProperties();
|
||||
}
|
||||
|
||||
void Settings::setStringAndSave(const wstring& key, const wstring& value)
|
||||
{
|
||||
properties[key] = value;
|
||||
saveProperties();
|
||||
}
|
||||
|
|
@ -18,4 +18,5 @@ public:
|
|||
int getInt(const wstring& key, int defaultValue);
|
||||
bool getBoolean(const wstring& key, bool defaultValue);
|
||||
void setBooleanAndSave(const wstring& key, bool value);
|
||||
void setStringAndSave(const wstring& key, const wstring& value);
|
||||
};
|
||||
|
|
@ -375,6 +375,11 @@ TexturePack *TexturePackRepository::addTexturePackFromDLC(DLCPack *dlcPack, DWOR
|
|||
cacheById[dwParentID] = newPack;
|
||||
|
||||
#ifndef _CONTENT_PACKAGE
|
||||
#ifdef _WINDOWS64
|
||||
extern bool g_Win64Verbose;
|
||||
if (g_Win64Verbose)
|
||||
{
|
||||
#endif
|
||||
if(dlcPack->hasPurchasedFile(DLCManager::e_DLCType_TexturePack,L""))
|
||||
{
|
||||
wprintf(L"Added new FULL DLCTexturePack: %ls - id=%d\n", dlcPack->getName().c_str(),dwParentID );
|
||||
|
|
@ -383,6 +388,9 @@ TexturePack *TexturePackRepository::addTexturePackFromDLC(DLCPack *dlcPack, DWOR
|
|||
{
|
||||
wprintf(L"Added new TRIAL DLCTexturePack: %ls - id=%d\n", dlcPack->getName().c_str(),dwParentID );
|
||||
}
|
||||
#ifdef _WINDOWS64
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
return newPack;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ char g_Win64MultiplayerIP[256] = "127.0.0.1";
|
|||
bool g_Win64DedicatedServer = false;
|
||||
int g_Win64DedicatedServerPort = WIN64_NET_DEFAULT_PORT;
|
||||
char g_Win64DedicatedServerBindIP[256] = "";
|
||||
bool g_Win64Verbose = false;
|
||||
|
||||
bool WinsockNetLayer::Initialize()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -170,5 +170,6 @@ extern char g_Win64MultiplayerIP[256];
|
|||
extern bool g_Win64DedicatedServer;
|
||||
extern int g_Win64DedicatedServerPort;
|
||||
extern char g_Win64DedicatedServerBindIP[256];
|
||||
extern bool g_Win64Verbose;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "..\..\Minecraft.World\ThreadName.h"
|
||||
#include "..\..\Minecraft.Client\StatsCounter.h"
|
||||
#include "..\ConnectScreen.h"
|
||||
#include "..\ServerConsole.h"
|
||||
//#include "Social\SocialManager.h"
|
||||
//#include "Leaderboards\LeaderboardManager.h"
|
||||
//#include "XUI\XUI_Scene_Container.h"
|
||||
|
|
@ -123,6 +124,7 @@ struct Win64LaunchOptions
|
|||
int screenMode;
|
||||
bool serverMode;
|
||||
bool fullscreen;
|
||||
bool verbose;
|
||||
};
|
||||
|
||||
static void CopyWideArgToAnsi(LPCWSTR source, char* dest, size_t destSize)
|
||||
|
|
@ -208,6 +210,7 @@ static Win64LaunchOptions ParseLaunchOptions()
|
|||
Win64LaunchOptions options = {};
|
||||
options.screenMode = 0;
|
||||
options.serverMode = false;
|
||||
options.verbose = false;
|
||||
|
||||
g_Win64MultiplayerJoin = false;
|
||||
g_Win64MultiplayerPort = WIN64_NET_DEFAULT_PORT;
|
||||
|
|
@ -271,6 +274,8 @@ static Win64LaunchOptions ParseLaunchOptions()
|
|||
}
|
||||
else if (_wcsicmp(argv[i], L"-fullscreen") == 0)
|
||||
options.fullscreen = true;
|
||||
else if (_wcsicmp(argv[i], L"-v") == 0 || _wcsicmp(argv[i], L"-verbose") == 0)
|
||||
options.verbose = true;
|
||||
}
|
||||
|
||||
LocalFree(argv);
|
||||
|
|
@ -1354,30 +1359,19 @@ static int HeadlessServerConsoleThreadProc(void* lpParameter)
|
|||
{
|
||||
UNREFERENCED_PARAMETER(lpParameter);
|
||||
|
||||
std::string line;
|
||||
MinecraftServer* server = nullptr;
|
||||
while (!app.m_bShutdown)
|
||||
{
|
||||
if (!std::getline(std::cin, line))
|
||||
{
|
||||
if (std::cin.eof())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
std::cin.clear();
|
||||
Sleep(50);
|
||||
continue;
|
||||
}
|
||||
|
||||
wstring command = trimString(convStringToWstring(line));
|
||||
if (command.empty())
|
||||
continue;
|
||||
|
||||
MinecraftServer* server = MinecraftServer::getInstance();
|
||||
server = MinecraftServer::getInstance();
|
||||
if (server != nullptr)
|
||||
{
|
||||
server->handleConsoleInput(command, server);
|
||||
}
|
||||
break;
|
||||
Sleep(100);
|
||||
}
|
||||
|
||||
if (server != nullptr && !app.m_bShutdown)
|
||||
{
|
||||
ServerConsole console(server);
|
||||
console.run();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1564,6 +1558,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
|||
|
||||
// Load stuff from launch options, including username
|
||||
const Win64LaunchOptions launchOptions = ParseLaunchOptions();
|
||||
g_Win64Verbose = launchOptions.verbose;
|
||||
ApplyScreenMode(launchOptions.screenMode);
|
||||
|
||||
// Ensure uid.dat exists from startup in client mode (before any multiplayer/login path).
|
||||
|
|
|
|||
|
|
@ -397,7 +397,9 @@ set(MINECRAFT_CLIENT_SOURCES
|
|||
"SelectWorldScreen.cpp"
|
||||
"ServerChunkCache.cpp"
|
||||
"ServerCommandDispatcher.cpp"
|
||||
"ServerCommands.cpp"
|
||||
"ServerConnection.cpp"
|
||||
"ServerConsole.cpp"
|
||||
"ServerLevel.cpp"
|
||||
"ServerLevelListener.cpp"
|
||||
"ServerPlayer.cpp"
|
||||
|
|
|
|||
Loading…
Reference in a new issue