FEAT: Ban command, save ops and banned ppl in files

TODO: fix many crashes...
This commit is contained in:
2026-05-09 16:37:11 +02:00
parent dfb3bf1da7
commit 5bc19c4ab2
13 changed files with 187 additions and 29 deletions

View File

@@ -143,6 +143,7 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/commands/Command.cpp \ ../../../src/commands/Command.cpp \
../../../src/commands/CommandHelp.cpp \ ../../../src/commands/CommandHelp.cpp \
../../../src/commands/CommandKick.cpp \ ../../../src/commands/CommandKick.cpp \
../../../src/commands/CommandBan.cpp \
../../../src/commands/CommandManager.cpp \ ../../../src/commands/CommandManager.cpp \
../../../src/commands/CommandOp.cpp \ ../../../src/commands/CommandOp.cpp \
../../../src/server/ServerLevel.cpp \ ../../../src/server/ServerLevel.cpp \

View File

@@ -278,7 +278,10 @@ void Minecraft::setLevel(Level* level, const std::string& message /* ="" */, Loc
} }
this->level = level; this->level = level;
// So uhhh // So uhhh
level->ops.emplace(options.getStringValue(OPTIONS_USERNAME)); std::string op = options.getStringValue(OPTIONS_USERNAME);
std::transform(op.begin(), op.end(), op.begin(), ::tolower);
level->ops.emplace(op);
_hasSignaledGeneratingLevelFinished = false; _hasSignaledGeneratingLevelFinished = false;
#ifdef STANDALONE_SERVER #ifdef STANDALONE_SERVER
const bool threadedLevelCreation = false; const bool threadedLevelCreation = false;
@@ -732,19 +735,19 @@ void Minecraft::tickInput() {
} }
// TODO: replace it with client /give command :face_vomiting: // TODO: replace it with client /give command :face_vomiting:
if (key == Keyboard::KEY_F4) { // if (key == Keyboard::KEY_F4) {
player->inventory->add(new ItemInstance(Tile::redBrick)); // player->inventory->add(new ItemInstance(Tile::redBrick));
player->inventory->add(new ItemInstance(Item::ironIngot, 64)); // player->inventory->add(new ItemInstance(Item::ironIngot, 64));
player->inventory->add(new ItemInstance(Item::ironIngot, 34)); // player->inventory->add(new ItemInstance(Item::ironIngot, 34));
player->inventory->add(new ItemInstance(Tile::stonecutterBench)); // player->inventory->add(new ItemInstance(Tile::stonecutterBench));
player->inventory->add(new ItemInstance(Tile::workBench)); // player->inventory->add(new ItemInstance(Tile::workBench));
player->inventory->add(new ItemInstance(Tile::furnace)); // player->inventory->add(new ItemInstance(Tile::furnace));
player->inventory->add(new ItemInstance(Tile::wood, 54)); // player->inventory->add(new ItemInstance(Tile::wood, 54));
player->inventory->add(new ItemInstance(Item::stick, 14)); // player->inventory->add(new ItemInstance(Item::stick, 14));
player->inventory->add(new ItemInstance(Item::coal, 31)); // player->inventory->add(new ItemInstance(Item::coal, 31));
player->inventory->add(new ItemInstance(Tile::sand, 6)); // player->inventory->add(new ItemInstance(Tile::sand, 6));
} // }
if (key == Keyboard::KEY_F5) { if (key == Keyboard::KEY_F5) {
options.toggle(OPTIONS_THIRD_PERSON_VIEW); options.toggle(OPTIONS_THIRD_PERSON_VIEW);
@@ -1603,6 +1606,6 @@ void Minecraft::addMessage(const std::string& msg) {
#ifndef STANDALONE_SERVER #ifndef STANDALONE_SERVER
gui.addMessage(msg); gui.addMessage(msg);
#else #else
LOGI("%s", msg.c_str()); LOGI("%s \n", msg.c_str());
#endif #endif
} }

View File

@@ -3,5 +3,8 @@
#include <client/Minecraft.h> #include <client/Minecraft.h>
bool Command::isPlayerOp(Minecraft& mc, Player& player) { bool Command::isPlayerOp(Minecraft& mc, Player& player) {
return mc.level->ops.find(player.name) != mc.level->ops.end(); std::string nicknameLower = player.name;
std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower);
return mc.level->ops.find(nicknameLower) != mc.level->ops.end();
} }

View File

@@ -0,0 +1,52 @@
#include "CommandBan.hpp"
#include "commands/Command.hpp"
#include "network/RakNetInstance.h"
#include "raknet/RakPeerInterface.h"
#include "world/level/Level.h"
#include <algorithm>
#include <client/Minecraft.h>
CommandBan::CommandBan() : Command("ban") {}
std::string CommandBan::execute(Minecraft& mc, Player& player, const std::vector<std::string>& args) {
if (!isPlayerOp(mc, player)) {
return "You aren't enough priveleged to run this command";
}
if (args.empty()) {
return help(mc);
}
std::string nicknameLower = args[0];
std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower);
auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args, nicknameLower] (auto& it) -> bool {
std::string lower = it->name;
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
return lower == nicknameLower;
});
if (*it == (Player*)mc.player) {
return "ban: you can't ban urself lol";
}
if (it != mc.level->players.end()) {
mc.level->removePlayer(*it);
(*it)->remove();
mc.raknetInstance->getPeer()->CloseConnection((*it)->owner, true);
} else {
for (auto& banned : mc.level->bannedPpl) {
if (nicknameLower == banned) {
return args[0] + "already banned!";
}
}
}
mc.level->bannedPpl.insert(nicknameLower);
return "ban: successfully banned player " + args[0];
}
std::string CommandBan::help(Minecraft& mc) {
return "Usage: /ban <player>";
}

View File

@@ -0,0 +1,9 @@
#include "Command.hpp"
class CommandBan : public Command {
public:
CommandBan();
std::string execute(Minecraft& mc, Player& player, const std::vector<std::string>& args);
std::string help(Minecraft& mc);
};

View File

@@ -5,7 +5,6 @@
#include "world/level/Level.h" #include "world/level/Level.h"
#include <algorithm> #include <algorithm>
#include <client/Minecraft.h> #include <client/Minecraft.h>
// RakNet::RakPeerInterface
CommandKick::CommandKick() : Command("kick") {} CommandKick::CommandKick() : Command("kick") {}
@@ -18,8 +17,14 @@ std::string CommandKick::execute(Minecraft& mc, Player& player, const std::vecto
return help(mc); return help(mc);
} }
auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args] (auto& it) -> bool { std::string nicknameLower = args[0];
return it->name == args[0]; std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower);
auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args, nicknameLower] (auto& it) -> bool {
std::string lower = it->name;
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
return lower == nicknameLower;
}); });
if (it == mc.level->players.end()) { if (it == mc.level->players.end()) {
@@ -33,7 +38,7 @@ std::string CommandKick::execute(Minecraft& mc, Player& player, const std::vecto
mc.level->removePlayer(*it); mc.level->removePlayer(*it);
(*it)->remove(); (*it)->remove();
mc.raknetInstance->getPeer()->CloseConnection((*it)->owner, true); mc.raknetInstance->getPeer()->CloseConnection((*it)->owner, true);
mc.addMessage("kick: successfully kicked player " + args[0]); return "kick: successfully kicked player " + args[0];
} }
std::string CommandKick::help(Minecraft& mc) { std::string CommandKick::help(Minecraft& mc) {

View File

@@ -7,6 +7,7 @@
#include "commands/CommandHelp.hpp" #include "commands/CommandHelp.hpp"
#include "commands/CommandKick.hpp" #include "commands/CommandKick.hpp"
#include "commands/CommandOp.hpp" #include "commands/CommandOp.hpp"
#include "commands/CommandBan.hpp"
#include "network/packet/ChatPacket.h" #include "network/packet/ChatPacket.h"
#include "network/RakNetInstance.h" #include "network/RakNetInstance.h"
#include "world/level/Level.h" #include "world/level/Level.h"
@@ -19,6 +20,7 @@ void CommandManager::registerAllCommands() {
m_commands.push_back(new CommandHelp()); m_commands.push_back(new CommandHelp());
m_commands.push_back(new CommandKick()); m_commands.push_back(new CommandKick());
m_commands.push_back(new CommandOp()); m_commands.push_back(new CommandOp());
m_commands.push_back(new CommandBan());
} }
std::vector<std::string> CommandManager::getListAllCommands() { std::vector<std::string> CommandManager::getListAllCommands() {

View File

@@ -15,15 +15,14 @@ std::string CommandOp::execute(Minecraft& mc, Player& player, const std::vector<
return help(mc); return help(mc);
} }
auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args] (auto& it) -> bool { std::string nicknameLower = args[0];
return it->name == args[0]; std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower);
});
if (mc.level->ops.find(nicknameLower) != mc.level->ops.end()) {
if (mc.level->ops.find(args[0]) != mc.level->ops.end()) {
return "op: player " + args[0] + " already opped"; return "op: player " + args[0] + " already opped";
} }
mc.level->ops.emplace((*it)->name); mc.level->ops.emplace(nicknameLower);
return "op: successfully opped player " + args[0]; return "op: successfully opped player " + args[0];
} }

View File

@@ -161,6 +161,44 @@ int main(int numArguments, char* pszArgs[]) {
((MAIN_CLASS*)g_app)->selectLevel(levelDir, levelName, settings); ((MAIN_CLASS*)g_app)->selectLevel(levelDir, levelName, settings);
((MAIN_CLASS*)g_app)->hostMultiplayer(port); ((MAIN_CLASS*)g_app)->hostMultiplayer(port);
// Reading ops
std::ifstream ops("ops.txt");
if (ops.is_open()) {
std::string line;
while (std::getline(ops, line)) {
if (!line.empty()) {
((MAIN_CLASS*)g_app)->level->ops.insert(line);
}
}
} else {
std::ofstream opsDefault("ops.txt");
if (!opsDefault.is_open()) {
throw std::runtime_error("Cannot create ops list.");
}
}
// Reading banned ppl
std::ifstream banned("banned-players.txt");
if (banned.is_open()) {
std::string line;
while (std::getline(banned, line)) {
if (!line.empty()) {
((MAIN_CLASS*)g_app)->level->bannedPpl.insert(line);
}
}
} else {
std::ofstream bannedPpl("banned-players.txt");
if (!bannedPpl.is_open()) {
throw std::runtime_error("Cannot create banned players list.");
}
}
std::cout << "Level has been generated in " << getTimeS() - startTime << std::endl; std::cout << "Level has been generated in " << getTimeS() - startTime << std::endl;
((MAIN_CLASS*)g_app)->level->saveLevelData(); ((MAIN_CLASS*)g_app)->level->saveLevelData();
std::cout << "Level has been saved!" << std::endl; std::cout << "Level has been saved!" << std::endl;
@@ -171,7 +209,30 @@ int main(int numArguments, char* pszArgs[]) {
sleepMs(20); sleepMs(20);
} }
std::ofstream opsWrite("ops.txt");
if (opsWrite.is_open()) {
for (auto& op : ((MAIN_CLASS*)g_app)->level->ops) {
opsWrite << op << std::endl;
}
opsWrite.close();
} else {
throw std::runtime_error("Cannot open ops list.");
}
std::ofstream bannedWrite("banned-players.txt");
if (bannedWrite.is_open()) {
for (auto& banned : ((MAIN_CLASS*)g_app)->level->bannedPpl) {
bannedWrite << banned << std::endl;
}
bannedWrite.close();
} else {
throw std::runtime_error("Cannot open banned players list.");
}
((MAIN_CLASS*)g_app)->level->saveLevelData(); ((MAIN_CLASS*)g_app)->level->saveLevelData();
delete app; delete app;
appContext.platform->finish(); appContext.platform->finish();
delete appContext.platform; delete appContext.platform;

View File

@@ -149,6 +149,12 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginSta
LOGI("Disconnect! Nickname is taken!\n"); LOGI("Disconnect! Nickname is taken!\n");
#ifndef STANDALONE_SERVER #ifndef STANDALONE_SERVER
minecraft->setScreen(new DisconnectionScreen("Could not connect: Nickname is taken!")); minecraft->setScreen(new DisconnectionScreen("Could not connect: Nickname is taken!"));
#endif
}
if (packet->status == LoginStatus::Failed_Banned) {
LOGI("Disconnect! You're banned from this server!\n");
#ifndef STANDALONE_SERVER
minecraft->setScreen(new DisconnectionScreen("Could not connect: You're banned from this server!"));
#endif #endif
} }
} }

View File

@@ -159,7 +159,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChatPack
{ {
auto player = getPlayer(source); auto player = getPlayer(source);
if (player == nullptr) return; // TODO maybe kick? if (player == nullptr) return; // @todo maybe kick?
if (packet->message[0] == '/') { if (packet->message[0] == '/') {
// This is a command // This is a command
@@ -223,11 +223,27 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac
if (oldClient || oldServer || !packet->newProto) if (oldClient || oldServer || !packet->newProto)
loginStatus = oldClient || !packet->newProto? LoginStatus::Failed_ClientOld : LoginStatus::Failed_ServerOld; loginStatus = oldClient || !packet->newProto? LoginStatus::Failed_ClientOld : LoginStatus::Failed_ServerOld;
std::string nicknameLower = packet->clientName.C_String();
std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower);
printf("%s lower \n", nicknameLower.c_str());
for (int i = 0; i < level->players.size(); i++) { for (int i = 0; i < level->players.size(); i++) {
ServerPlayer* player = (ServerPlayer*) level->players.at(i); ServerPlayer* player = (ServerPlayer*) level->players.at(i);
if (player->name == packet->clientName.C_String()) { std::string clientLower = player->name;
std::transform(clientLower.begin(), clientLower.end(), clientLower.begin(), ::tolower);
// @todo to lower case
if (nicknameLower == clientLower) {
loginStatus = packet->newProto ? LoginStatus::Failed_TakenNickname : LoginStatus::Failed_ClientOld; loginStatus = packet->newProto ? LoginStatus::Failed_TakenNickname : LoginStatus::Failed_ClientOld;
break;
}
}
for (auto& banned : level->bannedPpl) {
if (nicknameLower == banned) {
loginStatus = packet->newProto ? LoginStatus::Failed_Banned : LoginStatus::Failed_ClientOld;
break;
} }
} }

View File

@@ -9,6 +9,7 @@ namespace LoginStatus {
const int Failed_ClientOld = 1; const int Failed_ClientOld = 1;
const int Failed_ServerOld = 2; const int Failed_ServerOld = 2;
const int Failed_TakenNickname = 3; const int Failed_TakenNickname = 3;
const int Failed_Banned = 4;
} }
class LoginStatusPacket : public Packet { class LoginStatusPacket : public Packet {

View File

@@ -309,7 +309,7 @@ public:
Random random; Random random;
std::set<std::string> ops; std::set<std::string> ops;
std::set<std::string> bannedPpl;
protected: protected:
bool isFindingSpawn; bool isFindingSpawn;