diff --git a/project/android/jni/Android.mk b/project/android/jni/Android.mk index 632c1372..ec493d0a 100755 --- a/project/android/jni/Android.mk +++ b/project/android/jni/Android.mk @@ -143,6 +143,7 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \ ../../../src/commands/Command.cpp \ ../../../src/commands/CommandHelp.cpp \ ../../../src/commands/CommandKick.cpp \ +../../../src/commands/CommandBan.cpp \ ../../../src/commands/CommandManager.cpp \ ../../../src/commands/CommandOp.cpp \ ../../../src/server/ServerLevel.cpp \ diff --git a/src/client/Minecraft.cpp b/src/client/Minecraft.cpp index d428879b..bb2f579e 100755 --- a/src/client/Minecraft.cpp +++ b/src/client/Minecraft.cpp @@ -278,7 +278,10 @@ void Minecraft::setLevel(Level* level, const std::string& message /* ="" */, Loc } this->level = level; // 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; #ifdef STANDALONE_SERVER const bool threadedLevelCreation = false; @@ -732,19 +735,19 @@ void Minecraft::tickInput() { } // TODO: replace it with client /give command :face_vomiting: - if (key == Keyboard::KEY_F4) { - player->inventory->add(new ItemInstance(Tile::redBrick)); - player->inventory->add(new ItemInstance(Item::ironIngot, 64)); - player->inventory->add(new ItemInstance(Item::ironIngot, 34)); - player->inventory->add(new ItemInstance(Tile::stonecutterBench)); - player->inventory->add(new ItemInstance(Tile::workBench)); - player->inventory->add(new ItemInstance(Tile::furnace)); - player->inventory->add(new ItemInstance(Tile::wood, 54)); - player->inventory->add(new ItemInstance(Item::stick, 14)); - player->inventory->add(new ItemInstance(Item::coal, 31)); - player->inventory->add(new ItemInstance(Tile::sand, 6)); + // if (key == Keyboard::KEY_F4) { + // player->inventory->add(new ItemInstance(Tile::redBrick)); + // player->inventory->add(new ItemInstance(Item::ironIngot, 64)); + // player->inventory->add(new ItemInstance(Item::ironIngot, 34)); + // player->inventory->add(new ItemInstance(Tile::stonecutterBench)); + // player->inventory->add(new ItemInstance(Tile::workBench)); + // player->inventory->add(new ItemInstance(Tile::furnace)); + // player->inventory->add(new ItemInstance(Tile::wood, 54)); + // player->inventory->add(new ItemInstance(Item::stick, 14)); + // player->inventory->add(new ItemInstance(Item::coal, 31)); + // player->inventory->add(new ItemInstance(Tile::sand, 6)); - } + // } if (key == Keyboard::KEY_F5) { options.toggle(OPTIONS_THIRD_PERSON_VIEW); @@ -1603,6 +1606,6 @@ void Minecraft::addMessage(const std::string& msg) { #ifndef STANDALONE_SERVER gui.addMessage(msg); #else - LOGI("%s", msg.c_str()); + LOGI("%s \n", msg.c_str()); #endif } \ No newline at end of file diff --git a/src/commands/Command.cpp b/src/commands/Command.cpp index ebcbf3d2..187267c1 100644 --- a/src/commands/Command.cpp +++ b/src/commands/Command.cpp @@ -3,5 +3,8 @@ #include 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(); } \ No newline at end of file diff --git a/src/commands/CommandBan.cpp b/src/commands/CommandBan.cpp new file mode 100644 index 00000000..0373d5b1 --- /dev/null +++ b/src/commands/CommandBan.cpp @@ -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 +#include + +CommandBan::CommandBan() : Command("ban") {} + +std::string CommandBan::execute(Minecraft& mc, Player& player, const std::vector& 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 "; +} \ No newline at end of file diff --git a/src/commands/CommandBan.hpp b/src/commands/CommandBan.hpp new file mode 100644 index 00000000..b6888009 --- /dev/null +++ b/src/commands/CommandBan.hpp @@ -0,0 +1,9 @@ +#include "Command.hpp" + +class CommandBan : public Command { +public: + CommandBan(); + + std::string execute(Minecraft& mc, Player& player, const std::vector& args); + std::string help(Minecraft& mc); +}; \ No newline at end of file diff --git a/src/commands/CommandKick.cpp b/src/commands/CommandKick.cpp index df8c113f..b876d9ac 100644 --- a/src/commands/CommandKick.cpp +++ b/src/commands/CommandKick.cpp @@ -5,7 +5,6 @@ #include "world/level/Level.h" #include #include -// RakNet::RakPeerInterface CommandKick::CommandKick() : Command("kick") {} @@ -18,8 +17,14 @@ std::string CommandKick::execute(Minecraft& mc, Player& player, const std::vecto return help(mc); } - auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args] (auto& it) -> bool { - return it->name == args[0]; + 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 == mc.level->players.end()) { @@ -33,7 +38,7 @@ std::string CommandKick::execute(Minecraft& mc, Player& player, const std::vecto mc.level->removePlayer(*it); (*it)->remove(); 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) { diff --git a/src/commands/CommandManager.cpp b/src/commands/CommandManager.cpp index 9087c420..fbb93244 100644 --- a/src/commands/CommandManager.cpp +++ b/src/commands/CommandManager.cpp @@ -7,6 +7,7 @@ #include "commands/CommandHelp.hpp" #include "commands/CommandKick.hpp" #include "commands/CommandOp.hpp" +#include "commands/CommandBan.hpp" #include "network/packet/ChatPacket.h" #include "network/RakNetInstance.h" #include "world/level/Level.h" @@ -19,6 +20,7 @@ void CommandManager::registerAllCommands() { m_commands.push_back(new CommandHelp()); m_commands.push_back(new CommandKick()); m_commands.push_back(new CommandOp()); + m_commands.push_back(new CommandBan()); } std::vector CommandManager::getListAllCommands() { diff --git a/src/commands/CommandOp.cpp b/src/commands/CommandOp.cpp index e50e1307..7fc2c308 100644 --- a/src/commands/CommandOp.cpp +++ b/src/commands/CommandOp.cpp @@ -15,15 +15,14 @@ std::string CommandOp::execute(Minecraft& mc, Player& player, const std::vector< return help(mc); } - auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args] (auto& it) -> bool { - return it->name == args[0]; - }); - - if (mc.level->ops.find(args[0]) != mc.level->ops.end()) { + std::string nicknameLower = args[0]; + std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower); + + if (mc.level->ops.find(nicknameLower) != mc.level->ops.end()) { 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]; } diff --git a/src/main_dedicated.cpp b/src/main_dedicated.cpp index 2c429ed6..4c667b5a 100755 --- a/src/main_dedicated.cpp +++ b/src/main_dedicated.cpp @@ -161,6 +161,44 @@ int main(int numArguments, char* pszArgs[]) { ((MAIN_CLASS*)g_app)->selectLevel(levelDir, levelName, settings); ((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; ((MAIN_CLASS*)g_app)->level->saveLevelData(); std::cout << "Level has been saved!" << std::endl; @@ -171,7 +209,30 @@ int main(int numArguments, char* pszArgs[]) { 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(); + delete app; appContext.platform->finish(); delete appContext.platform; diff --git a/src/network/ClientSideNetworkHandler.cpp b/src/network/ClientSideNetworkHandler.cpp index fd0b5f3e..493ddfe3 100755 --- a/src/network/ClientSideNetworkHandler.cpp +++ b/src/network/ClientSideNetworkHandler.cpp @@ -149,6 +149,12 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginSta LOGI("Disconnect! Nickname is taken!\n"); #ifndef STANDALONE_SERVER 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 } } diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index b184d8bf..20d375b4 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -159,7 +159,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChatPack { auto player = getPlayer(source); - if (player == nullptr) return; // TODO maybe kick? + if (player == nullptr) return; // @todo maybe kick? if (packet->message[0] == '/') { // This is a command @@ -223,11 +223,27 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac if (oldClient || oldServer || !packet->newProto) 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++) { 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; + break; + } + } + + for (auto& banned : level->bannedPpl) { + if (nicknameLower == banned) { + loginStatus = packet->newProto ? LoginStatus::Failed_Banned : LoginStatus::Failed_ClientOld; + break; } } diff --git a/src/network/packet/LoginStatusPacket.h b/src/network/packet/LoginStatusPacket.h index efa10f57..e2e09570 100755 --- a/src/network/packet/LoginStatusPacket.h +++ b/src/network/packet/LoginStatusPacket.h @@ -9,6 +9,7 @@ namespace LoginStatus { const int Failed_ClientOld = 1; const int Failed_ServerOld = 2; const int Failed_TakenNickname = 3; + const int Failed_Banned = 4; } class LoginStatusPacket : public Packet { diff --git a/src/world/level/Level.h b/src/world/level/Level.h index edf17471..a7196ed8 100755 --- a/src/world/level/Level.h +++ b/src/world/level/Level.h @@ -309,7 +309,7 @@ public: Random random; std::set ops; - + std::set bannedPpl; protected: bool isFindingSpawn;