12 Commits

Author SHA1 Message Date
Kolyah35
5194575092 FEAT: Meet the commands 2026-03-30 14:04:16 +03:00
InviseDivine
3cfa2d9ee7 FIX IT AHTUNG AHTUNG ALL DOESNT WORK FIX IT FIX IT FIX IT FIX IT BIG WARNING BIG WARNING 2026-03-29 16:53:46 +02:00
InviseDivine
f016f00eab idk?? 2026-03-29 00:16:19 +02:00
Kolyah35
470c28d83a I dont know what im doin please help 2026-03-29 00:36:36 +03:00
InviseDivine
4363157cd9 Delete useless class 2026-03-28 21:08:52 +02:00
InviseDivine
ba3ed3b4dd i dont see reason of this error 2026-03-28 18:37:02 +02:00
InviseDivine
5783fb93f3 forgot to comment 2026-03-28 17:39:37 +02:00
InviseDivine
73fb2a2b3d wtf 2026-03-28 17:18:38 +02:00
InviseDivine
bcf48eb5e3 FEAT: Damage on server 2026-03-28 16:41:00 +02:00
Kolyah35
f5fecbc928 Merge remote-tracking branch 'refs/remotes/origin/dedicated-rewrite' into dedicated-rewrite 2026-03-27 22:15:26 +03:00
Kolyah35
77d02fcca2 FIX: workbench compatibility 2026-03-27 22:15:03 +03:00
InviseDivine
6d696af235 FEAT: taken nickname 2026-03-27 21:08:17 +02:00
28 changed files with 374 additions and 238 deletions

View File

@@ -211,6 +211,7 @@ file(GLOB SERVER_SOURCES
"src/world/level/tile/entity/*.cpp" "src/world/level/tile/entity/*.cpp"
"src/world/phys/HitResult.cpp" "src/world/phys/HitResult.cpp"
"src/commands/*.cpp"
) )
file(GLOB CLIENT_SOURCES file(GLOB CLIENT_SOURCES
@@ -292,6 +293,8 @@ file(GLOB CLIENT_SOURCES
"src/AppPlatform_glfw.cpp" "src/AppPlatform_glfw.cpp"
"src/main.cpp" "src/main.cpp"
"src/commands/*.cpp"
) )
if (${PLATFORM} STREQUAL "Desktop") if (${PLATFORM} STREQUAL "Desktop")

View File

@@ -2,6 +2,7 @@
#include "Options.h" #include "Options.h"
#include "client/Options.h" #include "client/Options.h"
#include "client/player/input/IBuildInput.h" #include "client/player/input/IBuildInput.h"
#include "commands/CommandManager.hpp"
#include "platform/input/Keyboard.h" #include "platform/input/Keyboard.h"
#include "world/item/Item.h" #include "world/item/Item.h"
#include "world/item/ItemInstance.h" #include "world/item/ItemInstance.h"
@@ -175,7 +176,8 @@ Minecraft::Minecraft() :
_powerVr(false), _powerVr(false),
commandPort(4711), commandPort(4711),
reserved_d1(0),reserved_d2(0), reserved_d1(0),reserved_d2(0),
reserved_f1(0),reserved_f2(0), options(this) reserved_f1(0),reserved_f2(0), options(this),
m_commandManager()
{ {
//#ifdef ANDROID //#ifdef ANDROID
@@ -1597,3 +1599,11 @@ void Minecraft::optionUpdated(OptionId option, int value ) {
setSize(width, height); setSize(width, height);
} }
} }
void Minecraft::addMessage(const std::string& msg) {
#ifndef STANDALONE_SERVER
gui.addMessage(msg);
#else
LOGI("%s", msg.c_str());
#endif
}

View File

@@ -2,6 +2,7 @@
#define NET_MINECRAFT_CLIENT__Minecraft_H__ #define NET_MINECRAFT_CLIENT__Minecraft_H__
#include "Options.h" #include "Options.h"
#include "commands/CommandManager.hpp"
#ifndef STANDALONE_SERVER #ifndef STANDALONE_SERVER
#include "MouseHandler.h" #include "MouseHandler.h"
#include "gui/Gui.h" #include "gui/Gui.h"
@@ -122,11 +123,15 @@ public:
void optionUpdated(OptionId option, int value); void optionUpdated(OptionId option, int value);
int getTicks() { return ticks; } int getTicks() { return ticks; }
void addMessage(const std::string& msg);
#ifdef __APPLE__ #ifdef __APPLE__
bool _isSuperFast; bool _isSuperFast;
bool isSuperFast() { return _isSuperFast; } bool isSuperFast() { return _isSuperFast; }
#endif #endif
CommandManager& commandManager() { return m_commandManager; }
protected: protected:
void _levelGenerated(); void _levelGenerated();
@@ -227,6 +232,8 @@ private:
PerfRenderer* _perfRenderer; PerfRenderer* _perfRenderer;
CommandServer* _commandServer; CommandServer* _commandServer;
CommandManager m_commandManager;
}; };
#endif /*NET_MINECRAFT_CLIENT__Minecraft_H__*/ #endif /*NET_MINECRAFT_CLIENT__Minecraft_H__*/

View File

@@ -730,7 +730,6 @@ void Gui::renderDebugInfo() {
// Position // Position
float px = p->x, py = p->y - p->heightOffset, pz = p->z; float px = p->x, py = p->y - p->heightOffset, pz = p->z;
posTranslator.to(px, py, pz);
int bx = (int)floorf(px), by = (int)floorf(py), bz = (int)floorf(pz); int bx = (int)floorf(px), by = (int)floorf(py), bz = (int)floorf(pz);
int cx = bx >> 4, cz = bz >> 4; int cx = bx >> 4, cz = bz >> 4;

View File

@@ -8,6 +8,7 @@
#include "../../../network/ServerSideNetworkHandler.h" #include "../../../network/ServerSideNetworkHandler.h"
#include "../../../network/packet/ChatPacket.h" #include "../../../network/packet/ChatPacket.h"
#include "../../../platform/log.h" #include "../../../platform/log.h"
#include "util/StringUtils.h"
#include <sstream> #include <sstream>
#include <cstdlib> #include <cstdlib>
@@ -54,141 +55,33 @@ void ConsoleScreen::charPressed(char inputChar)
_input += inputChar; _input += inputChar;
} }
// ---------------------------------------------------------------------------
// execute: run _input as a command, print result, close screen
// ---------------------------------------------------------------------------
void ConsoleScreen::execute() void ConsoleScreen::execute()
{ {
if (!minecraft->level) return;
if (_input.empty()) { if (_input.empty()) {
minecraft->setScreen(NULL); return minecraft->setScreen(NULL);
return;
} }
if (_input[0] == '/') { if (_input[0] == '/') {
// Command // Command
std::string result = processCommand(_input); _input = Util::stringTrim(_input.substr(1));
if (!result.empty()) minecraft->commandManager().execute(*minecraft, _input);
minecraft->gui.addMessage(result);
} else { } else {
// Chat message: <name> message // @ai @rewrite
std::string msg = std::string("<") + minecraft->player->name + "> " + _input;
if (minecraft->netCallback && minecraft->raknetInstance->isServer()) { if (minecraft->netCallback && minecraft->raknetInstance->isServer()) {
// Hosting a LAN game: displayGameMessage shows locally + broadcasts MessagePacket to clients static_cast<ServerSideNetworkHandler*>(minecraft->netCallback)->displayGameMessage(_input);
static_cast<ServerSideNetworkHandler*>(minecraft->netCallback)->displayGameMessage(msg);
} else if (minecraft->netCallback) { } else if (minecraft->netCallback) {
// Connected client: send ChatPacket to server; server echoes it back as MessagePacket ChatPacket chatPkt(_input);
ChatPacket chatPkt(msg);
minecraft->raknetInstance->send(chatPkt); minecraft->raknetInstance->send(chatPkt);
} else { } else {
// Singleplayer: show locally only minecraft->gui.addMessage(_input);
minecraft->gui.addMessage(msg);
} }
} }
minecraft->setScreen(NULL); minecraft->setScreen(NULL);
} }
// ---------------------------------------------------------------------------
// processCommand
// ---------------------------------------------------------------------------
static std::string trim(const std::string& s) {
size_t a = s.find_first_not_of(" \t");
if (a == std::string::npos) return "";
size_t b = s.find_last_not_of(" \t");
return s.substr(a, b - a + 1);
}
std::string ConsoleScreen::processCommand(const std::string& raw)
{
// strip leading '/'
std::string line = raw;
if (!line.empty() && line[0] == '/') line = line.substr(1);
line = trim(line);
// tokenise
std::vector<std::string> args;
{
std::istringstream ss(line);
std::string tok;
while (ss >> tok) args.push_back(tok);
}
if (args.empty()) return "";
Level* level = minecraft->level;
if (!level) return "No level loaded.";
// -----------------------------------------------------------------------
// /time ...
// -----------------------------------------------------------------------
if (args[0] == "time") {
if (args.size() < 2)
return "Usage: /time <add|set|query> ...";
const std::string& sub = args[1];
// -- time add <value> -----------------------------------------------
if (sub == "add") {
if (args.size() < 3) return "Usage: /time add <value>";
long delta = std::atol(args[2].c_str());
long newTime = level->getTime() + delta;
level->setTime(newTime);
std::ostringstream out;
out << "Set the time to " << (newTime % Level::TICKS_PER_DAY);
return out.str();
}
// -- time set <value|day|night|noon|midnight> -----------------------
if (sub == "set") {
if (args.size() < 3) return "Usage: /time set <value|day|night|noon|midnight>";
const std::string& val = args[2];
long t = -1;
if (val == "day") t = 1000;
else if (val == "noon") t = 6000;
else if (val == "night") t = 13000;
else if (val == "midnight") t = 18000;
else {
// numeric — accept positive integers only
bool numeric = true;
for (char c : val)
if (!std::isdigit((unsigned char)c)) { numeric = false; break; }
if (!numeric) return std::string("Unknown value: ") + val;
t = std::atol(val.c_str());
}
// Preserve the total day count so only the time-of-day changes
long dayCount = level->getTime() / Level::TICKS_PER_DAY;
long newTime = dayCount * Level::TICKS_PER_DAY + (t % Level::TICKS_PER_DAY);
level->setTime(newTime);
std::ostringstream out;
out << "Set the time to " << t;
return out.str();
}
// -- time query <daytime|gametime|day> ------------------------------
if (sub == "query") {
if (args.size() < 3) return "Usage: /time query <daytime|gametime|day>";
const std::string& what = args[2];
long total = level->getTime();
long daytime = total % Level::TICKS_PER_DAY;
long day = total / Level::TICKS_PER_DAY;
std::ostringstream out;
if (what == "daytime") { out << "The time of day is " << daytime; }
else if (what == "gametime") { out << "The game time is " << total; }
else if (what == "day") { out << "The day is " << day; }
else return std::string("Unknown query: ") + what;
return out.str();
}
return "Unknown sub-command. Usage: /time <add|set|query> ...";
}
return std::string("Unknown command: /") + args[0];
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// render // render
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@@ -25,7 +25,6 @@ public:
private: private:
void execute(); void execute();
std::string processCommand(const std::string& cmd);
std::string _input; std::string _input;
int _cursorBlink; // tick counter for cursor blink int _cursorBlink; // tick counter for cursor blink

View File

@@ -467,35 +467,34 @@ void PaneCraftingScreen::craftSelectedItem()
if (minecraft->isOnline()) { if (minecraft->isOnline()) {
WantCreatePacket packet(minecraft->player->entityId, resultItem.count, resultItem.getAuxValue(), resultItem.id); WantCreatePacket packet(minecraft->player->entityId, resultItem.count, resultItem.getAuxValue(), resultItem.id);
minecraft->raknetInstance->send(packet); minecraft->raknetInstance->send(packet);
} else {
// Remove all items required for the recipe and ...
for (unsigned int i = 0; i < currentItem->neededItems.size(); ++i) {
CItem::ReqItem& req = currentItem->neededItems[i];
// If the recipe allows any aux-value as ingredients, first deplete
// aux == 0 from inventory. Since I'm not sure if this always is
// correct, let's only do it for ingredient sandstone for now.
ItemInstance toRemove = req.item;
if (Tile::sandStone->id == req.item.id
&& Recipe::ANY_AUX_VALUE == req.item.getAuxValue()) {
toRemove.setAuxValue(0);
toRemove.count = minecraft->player->inventory->removeResource(toRemove, true);
toRemove.setAuxValue(Recipe::ANY_AUX_VALUE);
}
if (toRemove.count > 0) {
minecraft->player->inventory->removeResource(toRemove);
}
}
// ... add the new one! (in this order, to fill empty slots better)
// if it doesn't fit, throw it on the ground!
if (!minecraft->player->inventory->add(&resultItem)) {
minecraft->player->drop(new ItemInstance(resultItem), false);
}
recheckRecipes();
} }
// Remove all items required for the recipe and ...
for (unsigned int i = 0; i < currentItem->neededItems.size(); ++i) {
CItem::ReqItem& req = currentItem->neededItems[i];
// If the recipe allows any aux-value as ingredients, first deplete
// aux == 0 from inventory. Since I'm not sure if this always is
// correct, let's only do it for ingredient sandstone for now.
ItemInstance toRemove = req.item;
if (Tile::sandStone->id == req.item.id
&& Recipe::ANY_AUX_VALUE == req.item.getAuxValue()) {
toRemove.setAuxValue(0);
toRemove.count = minecraft->player->inventory->removeResource(toRemove, true);
toRemove.setAuxValue(Recipe::ANY_AUX_VALUE);
}
if (toRemove.count > 0) {
minecraft->player->inventory->removeResource(toRemove);
}
}
// ... add the new one! (in this order, to fill empty slots better)
// if it doesn't fit, throw it on the ground!
if (!minecraft->player->inventory->add(&resultItem)) {
minecraft->player->drop(new ItemInstance(resultItem), false);
}
recheckRecipes();
} }
} }

View File

@@ -438,7 +438,7 @@ void LocalPlayer::tick() {
{ {
if (std::abs(x - sentX) > .1f || std::abs(y - sentY) > .01f || std::abs(z - sentZ) > .1f || std::abs(sentRotX - xRot) > 1 || std::abs(sentRotY - yRot) > 1) if (std::abs(x - sentX) > .1f || std::abs(y - sentY) > .01f || std::abs(z - sentZ) > .1f || std::abs(sentRotX - xRot) > 1 || std::abs(sentRotY - yRot) > 1)
{ {
MovePlayerPacket packet(entityId, x, y - heightOffset, z, xRot, yRot); MovePlayerPacket packet(entityId, xxa, y - heightOffset, yya, xRot, yRot);
minecraft->raknetInstance->send(packet); minecraft->raknetInstance->send(packet);
sentX = x; sentX = x;
sentY = y; sentY = y;

25
src/commands/Command.hpp Normal file
View File

@@ -0,0 +1,25 @@
#pragma once
#include <string>
#include <vector>
enum CommandFlags {
COMMAND_FLAG_SINGLEPLAYER_ONLY = (1 << 1),
COMMAND_FLAG_NO_ARGS = (1 << 2),
};
class Minecraft;
class Command {
public:
const std::string& getName() { return m_name; }
const CommandFlags getFlags() { return m_flags; }
virtual void execute(Minecraft& mc, const std::vector<std::string>& args) = 0;
virtual void printHelp(Minecraft& mc) = 0;
protected:
Command(const std::string& name, CommandFlags flags = (CommandFlags)0) : m_name(name), m_flags(flags) {}
const std::string m_name;
const CommandFlags m_flags;
};

View File

@@ -0,0 +1,27 @@
#include "CommandHelp.hpp"
#include "commands/Command.hpp"
#include "CommandManager.hpp"
#include <client/Minecraft.h>
CommandHelp::CommandHelp() : Command("help") {}
void CommandHelp::execute(Minecraft& mc, const std::vector<std::string>& args) {
if (args.empty()) {
auto cmds = mc.commandManager().getListAllCommands();
mc.addMessage("Usage: /help <command>");
mc.addMessage("List of all commands:");
for (auto& cmd : cmds) {
mc.addMessage(" - " + cmd);
}
} else {
Command* cmd = mc.commandManager().getCommand(args[0]);
if (cmd != nullptr) {
cmd->printHelp(mc);
}
}
}
void CommandHelp::printHelp(Minecraft& mc) {}

View File

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

View File

@@ -0,0 +1,37 @@
#include "CommandKick.hpp"
#include "commands/Command.hpp"
#include "network/RakNetInstance.h"
#include "raknet/RakPeer.h"
#include "world/level/Level.h"
#include <algorithm>
#include <client/Minecraft.h>
CommandKick::CommandKick() : Command("kick") {}
void CommandKick::execute(Minecraft& mc, const std::vector<std::string>& args) {
if (args.empty()) {
return printHelp(mc);
}
auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args] (auto& it) -> bool {
return it->name == args[0];
});
if (it == mc.level->players.end()) {
return mc.addMessage("kick: can't find player with name " + args[0]);
}
if (*it == (Player*)mc.player) {
return mc.addMessage("kick: you can't kick urself lol");
}
mc.level->removePlayer(*it);
(*it)->remove();
mc.raknetInstance->getPeer()->CloseConnection((*it)->owner, true);
mc.addMessage("kick: successfully kicked player " + args[0]);
}
void CommandKick::printHelp(Minecraft& mc) {
mc.addMessage("Usage: /kick <player>");
}

View File

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

View File

@@ -0,0 +1,71 @@
#include "CommandManager.hpp"
#include <algorithm>
#include <string>
#include <vector>
#include "client/Minecraft.h"
#include "commands/Command.hpp"
#include "commands/CommandHelp.hpp"
#include "commands/CommandKick.hpp"
#include "network/packet/ChatPacket.h"
#include "network/RakNetInstance.h"
#include "world/level/Level.h"
CommandManager::CommandManager() {
registerAllCommands();
}
void CommandManager::registerAllCommands() {
m_commands.push_back(new CommandHelp());
m_commands.push_back(new CommandKick());
}
std::vector<std::string> CommandManager::getListAllCommands() {
std::vector<std::string> ret;
for (auto& cmd : m_commands) {
ret.push_back(cmd->getName());
}
return ret;
}
void CommandManager::execute(Minecraft& mc, const std::string& input) {
std::istringstream ss(input);
std::string cmd;
ss >> cmd;
auto it = std::find_if(m_commands.begin(), m_commands.end(), [cmd](auto& it) -> bool {
return it->getName() == cmd;
});
if (it == m_commands.end()) {
return mc.addMessage("Command /" + cmd + " not found");
}
std::vector<std::string> args;
std::string tok;
while (ss >> tok) args.push_back(tok);
if (!mc.level->isClientSide || (*it)->getFlags() & CommandFlags::COMMAND_FLAG_SINGLEPLAYER_ONLY) {
(*it)->execute(mc, args);
} else {
ChatPacket packet("/" + input);
mc.raknetInstance->send(packet);
}
}
Command* CommandManager::getCommand(const std::string& name) {
auto it = std::find_if(m_commands.begin(), m_commands.end(), [name](auto& it) -> bool {
return it->getName() == name;
});
if (it == m_commands.end()) {
return *it;
}
return nullptr;
}

View File

@@ -0,0 +1,21 @@
#pragma once
#include <string>
#include <vector>
#include "Command.hpp"
class CommandManager {
public:
CommandManager();
std::vector<std::string> getListAllCommands();
void execute(Minecraft& mc, const std::string& input);
Command* getCommand(const std::string& name);
private:
void registerAllCommands();
std::vector<Command*> m_commands;
};

View File

@@ -30,20 +30,29 @@ void signal_callback_handler(int signum) {
int main(int numArguments, char* pszArgs[]) { int main(int numArguments, char* pszArgs[]) {
ArgumentsSettings aSettings(numArguments, pszArgs); ArgumentsSettings aSettings(numArguments, pszArgs);
if(aSettings.getShowHelp()) { if(aSettings.getShowHelp()) {
// TODO: Map with args and print it with std::cout and for loop
// TODO: World size setting
ArgumentsSettings defaultSettings(0, NULL); ArgumentsSettings defaultSettings(0, NULL);
printf("Minecraft Pockect Edition Server %s\n", Common::getGameVersionString("").c_str()); printf("Minecraft Pockect Edition Server %s\n", Common::getGameVersionString("").c_str());
printf("-------------------------------------------------------\n"); printf("-------------------------------------------------------\n");
printf("--cachepath - Path to where the server can store temp stuff (not sure if this is used) [default: \"%s\"]\n", defaultSettings.getCachePath().c_str()); printf("--cachepath - Path to where the server can store temp stuff (not sure if this is used) [default: \"%s\"]\n", defaultSettings.getCachePath().c_str());
printf("--externalpath - The path to the place where the server should store the levels. [default: \"%s\"]\n", defaultSettings.getExternalPath().c_str()); printf("--externalpath - The path to the place where the server should store the levels. [default: \"%s\"]\n", defaultSettings.getExternalPath().c_str());
printf("--levelname - The name of the server [default: \"%s\"]\n", defaultSettings.getLevelName().c_str()); printf("--levelname - The name of the server [default: \"%s\"]\n", defaultSettings.getLevelName().c_str());
printf("--gamemode - The name of the gamemode [default: \"%s\"]\n", defaultSettings.getGamemode().c_str());
printf("--leveldir - The name of the server [default: \"%s\"]\n", defaultSettings.getLevelDir().c_str()); printf("--leveldir - The name of the server [default: \"%s\"]\n", defaultSettings.getLevelDir().c_str());
printf("--help - Shows this message.\n"); printf("--help - Shows this message.\n");
printf("--port - The port to run the server on. [default: %d]\n", defaultSettings.getPort()); printf("--port - The port to run the server on. [default: %d]\n", defaultSettings.getPort());
printf("--serverkey - The key that the server should use for API calls. [default: \"%s\"]\n", defaultSettings.getServerKey().c_str()); printf("--serverkey - The key that the server should use for API calls. [default: \"%s\"]\n", defaultSettings.getServerKey().c_str());
printf("-------------------------------------------------------\n"); printf("-------------------------------------------------------\n");
return 0; return 0;
} }
printf("Level Name: %s\n", aSettings.getLevelName().c_str()); printf("Level Name: %s\n", aSettings.getLevelName().c_str());
AppContext appContext; AppContext appContext;
appContext.platform = new AppPlatform(); appContext.platform = new AppPlatform();
App* app = new MAIN_CLASS(); App* app = new MAIN_CLASS();

View File

@@ -1,6 +1,7 @@
#include "ClientSideNetworkHandler.h" #include "ClientSideNetworkHandler.h"
#include "client/Options.h" #include "client/Options.h"
#include "network/packet/LoginStatusPacket.h"
#include "packet/PacketInclude.h" #include "packet/PacketInclude.h"
#include "RakNetInstance.h" #include "RakNetInstance.h"
#include "../world/level/chunk/ChunkSource.h" #include "../world/level/chunk/ChunkSource.h"
@@ -98,6 +99,7 @@ void ClientSideNetworkHandler::onUnableToConnect()
void ClientSideNetworkHandler::onDisconnect(const RakNet::RakNetGUID& guid) void ClientSideNetworkHandler::onDisconnect(const RakNet::RakNetGUID& guid)
{ {
// TODO: Good disconnecting
LOGI("onDisconnect\n"); LOGI("onDisconnect\n");
if (level) if (level)
{ {
@@ -131,6 +133,12 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginSta
LOGI("Disconnect! Server is outdated!\n"); LOGI("Disconnect! Server is outdated!\n");
#ifndef STANDALONE_SERVER #ifndef STANDALONE_SERVER
minecraft->setScreen(new DisconnectionScreen("Could not connect: Outdated server!")); minecraft->setScreen(new DisconnectionScreen("Could not connect: Outdated server!"));
#endif
}
if (packet->status == LoginStatus::Failed_TakenNickname) {
LOGI("Disconnect! Nickname is taken!\n");
#ifndef STANDALONE_SERVER
minecraft->setScreen(new DisconnectionScreen("Could not connect: Nickname is taken!"));
#endif #endif
} }
} }
@@ -345,6 +353,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AddItemE
} }
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, TakeItemEntityPacket* packet) { void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, TakeItemEntityPacket* packet) {
printf("TakeItemEntityPacket \n");
if (!level) return; if (!level) return;
Entity* e = level->getEntity(packet->itemId); Entity* e = level->getEntity(packet->itemId);
@@ -390,7 +399,6 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SendInventoryPacket* packet) { void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SendInventoryPacket* packet) {
if (!level) return; if (!level) return;
// TODO: Linked slots
if (packet->entityId == minecraft->player->entityId) { if (packet->entityId == minecraft->player->entityId) {
auto items = packet->items; auto items = packet->items;
@@ -845,6 +853,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SetHealt
if (!level || !minecraft->player) if (!level || !minecraft->player)
return; return;
printf("SetHealthPacket \n");
minecraft->player->hurtTo(packet->health); minecraft->player->hurtTo(packet->health);
} }

View File

@@ -1,33 +0,0 @@
#include "NATPunchHandler.h"
#include "../raknet/TCPInterface.h"
#include "../raknet/HTTPConnection.h"
#include "PHPDirectoryServer2.h"
using namespace RakNet;
NATPuchHandler::NATPuchHandler() {
tcpInterface = new TCPInterface;
}
NATPuchHandler::~NATPuchHandler() {
delete tcpInterface;
}
void NATPuchHandler::initialize() {
tcpInterface->Start(0, 64);
}
void NATPuchHandler::registerToGameList(const RakNet::RakString& serverName, int port) {
HTTPConnection httpConnection;
httpConnection.Init(tcpInterface, "johanbernhardsson.se");
PHPDirectoryServer2 directoryServer;
directoryServer.Init(&httpConnection, "/DirectoryServer.php");
directoryServer.UploadTable("", serverName, port, true);
}
void NATPuchHandler::removeFromGameList() {
}
void NATPuchHandler::close() {
}

View File

@@ -1,24 +0,0 @@
#ifndef _MINECRAFT_NETWORK_NATPUNCHHANDLER_H_
#define _MINECRAFT_NETWORK_NATPUNCHHANDLER_H_
#include "../raknet/TCPInterface.h"
#include "../raknet/RakString.h"
class NATPuchHandler {
public:
enum NATPuchHandlerStatus {
NATPuchInitilized = 0,
NATPuchFetchingServerList = 1,
NATPuchConnecting = 2,
NATPuchConnected = 3,
NATPuchDissconnected = 4
};
NATPuchHandler();
~NATPuchHandler();
void initialize();
void registerToGameList(const RakNet::RakString& serverName, int port);
void removeFromGameList();
void close();
private:
RakNet::TCPInterface *tcpInterface;
};
#endif /* _MINECRAFT_NETWORK_NATPUNCHHANDLER_H_ */

View File

@@ -6,6 +6,8 @@
#include "../world/Container.h" #include "../world/Container.h"
#include "../world/inventory/BaseContainerMenu.h" #include "../world/inventory/BaseContainerMenu.h"
#include "network/packet/ContainerSetSlotPacket.h" #include "network/packet/ContainerSetSlotPacket.h"
#include "network/packet/LoginStatusPacket.h"
#include "network/packet/MovePlayerPacket.h"
#include "network/packet/RemoveBlockPacket.h" #include "network/packet/RemoveBlockPacket.h"
#include "network/packet/SendInventoryPacket.h" #include "network/packet/SendInventoryPacket.h"
#include "network/packet/UpdateBlockPacket.h" #include "network/packet/UpdateBlockPacket.h"
@@ -28,6 +30,7 @@
#include "world/item/crafting/Recipe.h" #include "world/item/crafting/Recipe.h"
#include "world/item/crafting/Recipes.h" #include "world/item/crafting/Recipes.h"
#include <cstddef> #include <cstddef>
#include <cstdio>
#ifndef STANDALONE_SERVER #ifndef STANDALONE_SERVER
#include "../client/sound/SoundEngine.h" #include "../client/sound/SoundEngine.h"
#endif #endif
@@ -206,6 +209,14 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac
if (oldClient || oldServer) if (oldClient || oldServer)
loginStatus = oldClient? LoginStatus::Failed_ClientOld : LoginStatus::Failed_ServerOld; loginStatus = oldClient? LoginStatus::Failed_ClientOld : LoginStatus::Failed_ServerOld;
for (int i = 0; i < level->players.size(); i++) {
ServerPlayer* player = (ServerPlayer*) level->players.at(i);
if (player->name == packet->clientName.C_String()) {
loginStatus = packet->newProto ? LoginStatus::Failed_TakenNickname : LoginStatus::Failed_ClientOld;
}
}
RakNet::BitStream bitStream; RakNet::BitStream bitStream;
LoginStatusPacket(loginStatus).write(&bitStream); LoginStatusPacket(loginStatus).write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false); rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
@@ -397,22 +408,46 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay
if (!level) return; if (!level) return;
//LOGI("MovePlayerPacket\n"); //LOGI("MovePlayerPacket\n");
if (Entity* entity = level->getEntity(packet->entityId)) if (Entity* entity = level->getEntity(packet->entityId)) {
{
ServerPlayer* player = (ServerPlayer*) getPlayer(source); ServerPlayer* player = (ServerPlayer*) getPlayer(source);
float vectorDist = sqrt( (packet->x - entity->x) * (packet->x - entity->x) + float vectorDist = sqrt( (packet->x - entity->x) * (packet->x - entity->x) +
(packet->y - entity->y) * (packet->y - entity->y) +
(packet->z - entity->z) * (packet->z - entity->z)); (packet->z - entity->z) * (packet->z - entity->z));
float speed = vectorDist / (minecraft->getTicks() - player->getLastMoveTicks()); float speed = vectorDist / (minecraft->getTicks() - player->getLastMoveTicks());
if (speed < 2.5f) { if (speed < 1.f) {
LOGI("Packet: %f, %f, %f \n", packet->x, packet->y, packet->z);
LOGI("Entity before: %f, %f, %f \n", entity->x, entity->y, entity->z);
LOGI("OnGround: %d \n", entity->onGround);
// @note: packet->y contains y with subtracted entity->heightOffset
float ya = packet->y - entity->y - entity->heightOffset;
LOGI("y: %f \n", ya);
float yaOrg = ya;
// @BIGWARNING @fixme: blocks around work as shit
std::vector<AABB>& aABBs = level->getCubes(entity, entity->bb.expand(0, ya, 0));
for (unsigned int i = 0; i < aABBs.size(); i++)
ya = aABBs[i].clipYCollide(entity->bb, ya);
bool og = yaOrg != ya && yaOrg < 0;
entity->onGround = og;
entity->checkFallDamage(ya, og);
entity->xd = entity->yd = entity->zd = 0; entity->xd = entity->yd = entity->zd = 0;
entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3); entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3);
LOGI("Entity after: %f, %f, %f \n", entity->x, entity->y, entity->z);
// broadcast this packet to other clients // broadcast this packet to other clients
redistributePacket(packet, source); redistributePacket(packet, source);
} } // else {
//MovePlayerPacket refuse(player->entityId, player->x, player->y, player->z, player->xRot, player->yRot);
//raknetInstance->send(refuse);
// }
player->setLastMoveTicks(minecraft->getTicks()); player->setLastMoveTicks(minecraft->getTicks());
} }
@@ -450,7 +485,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveBl
} }
} }
//oldTile->spawnResources(level, x, y, z, data, 1); //@todo // oldTile->spawnResources(level, x, y, z, data, 1); //@todo
oldTile->playerDestroy(level, player, x, y, z, data); oldTile->playerDestroy(level, player, x, y, z, data);
} }
@@ -654,14 +689,14 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, WantCrea
} }
} }
for (int i = 0; i < items.size(); i++) { // for (int i = 0; i < items.size(); i++) {
RemoveItemPacket removePacket(packet->playerId, items.at(i).count, items.at(i).getAuxValue(), items.at(i).id); // RemoveItemPacket removePacket(packet->playerId, items.at(i).count, items.at(i).getAuxValue(), items.at(i).id);
raknetInstance->send(source, removePacket); // raknetInstance->send(source, removePacket);
p->inventory->removeResource(ItemInstance(items.at(i).id, items.at(i).count, items.at(i).getAuxValue())); // p->inventory->removeResource(ItemInstance(items.at(i).id, items.at(i).count, items.at(i).getAuxValue()));
} // }
TakeItemPacket itemAdd(p->entityId, wantCreate.count, wantCreate.getAuxValue(), wantCreate.id); // TakeItemPacket itemAdd(p->entityId, wantCreate.count, wantCreate.getAuxValue(), wantCreate.id);
raknetInstance->send(source, itemAdd); // raknetInstance->send(source, itemAdd);
p->inventory->add(new ItemInstance(wantCreate.id, wantCreate.count, wantCreate.getAuxValue())); p->inventory->add(new ItemInstance(wantCreate.id, wantCreate.count, wantCreate.getAuxValue()));
} }
@@ -925,19 +960,19 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, Containe
void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SetHealthPacket* packet ) void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SetHealthPacket* packet )
{ {
LOGI("SetHealthPacket\n"); LOGI("net idi nahui\n");
for (unsigned int i = 0; i < level->players.size(); ++i) { // for (unsigned int i = 0; i < level->players.size(); ++i) {
Player* p = level->players[i]; // Player* p = level->players[i];
if (p->owner == source) { // if (p->owner == source) {
if (packet->health <= -32) { // if (packet->health <= -32) {
int diff = packet->health - SetHealthPacket::HEALTH_MODIFY_OFFSET; // int diff = packet->health - SetHealthPacket::HEALTH_MODIFY_OFFSET;
if (diff > 0) p->hurt(NULL, diff); // if (diff > 0) p->hurt(NULL, diff);
else if (diff < 0) p->heal(-diff); // else if (diff < 0) p->heal(-diff);
} // }
break; // break;
} // }
} // }
} }
void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SignUpdatePacket* packet ) { void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SignUpdatePacket* packet ) {

View File

@@ -3,10 +3,12 @@
#include "../Packet.h" #include "../Packet.h"
// wtf why not enum
namespace LoginStatus { namespace LoginStatus {
const int Success = 0; const int Success = 0;
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;
} }
class LoginStatusPacket : public Packet { class LoginStatusPacket : public Packet {

View File

@@ -17,6 +17,11 @@ ArgumentsSettings::ArgumentsSettings(int numArguments, char** arguments)
levelName = std::string(arguments[a+1]); levelName = std::string(arguments[a+1]);
a++; // Skip the next argument since it's part of this one. a++; // Skip the next argument since it's part of this one.
} }
} else if(strcmp(arguments[a], "--gamemode") == 0) {
if(a + 1 < numArguments) {
gamemode = std::string(arguments[a+1]);
a++; // Skip the next argument since it's part of this one.
}
} else if(strcmp(arguments[a], "--leveldir") == 0) { } else if(strcmp(arguments[a], "--leveldir") == 0) {
if(a + 1 < numArguments) { if(a + 1 < numArguments) {
levelDir = std::string(arguments[a+1]); levelDir = std::string(arguments[a+1]);
@@ -51,6 +56,9 @@ std::string ArgumentsSettings::getServerKey() {
std::string ArgumentsSettings::getCachePath() { std::string ArgumentsSettings::getCachePath() {
return cachePath; return cachePath;
} }
std::string ArgumentsSettings::getGamemode() {
return gamemode;
}
std::string ArgumentsSettings::getLevelDir() { std::string ArgumentsSettings::getLevelDir() {
return levelDir; return levelDir;
} }

View File

@@ -4,20 +4,27 @@
class ArgumentsSettings { class ArgumentsSettings {
public: public:
ArgumentsSettings(int numArguments, char** arguments); ArgumentsSettings(int numArguments, char** arguments);
std::string getExternalPath(); std::string getExternalPath();
std::string getLevelName(); std::string getLevelName();
std::string getServerKey(); std::string getServerKey();
std::string getCachePath(); std::string getCachePath();
std::string getLevelDir(); std::string getLevelDir();
std::string getGamemode();
bool getShowHelp(); bool getShowHelp();
int getPort(); int getPort();
private: private:
std::string cachePath; std::string cachePath;
std::string externalPath; std::string externalPath;
std::string levelName; std::string levelName;
std::string gamemode;
std::string levelDir; std::string levelDir;
std::string serverKey; std::string serverKey;
bool showHelp; bool showHelp;
int port; int port;
}; };

View File

@@ -72,6 +72,7 @@ void ServerPlayer::take( Entity* e, int orgCount ) {
TakeItemEntityPacket packet(e->entityId, entityId); TakeItemEntityPacket packet(e->entityId, entityId);
// SendInventoryPacket packet(this, false); // SendInventoryPacket packet(this, false);
_mc->raknetInstance->send(packet); _mc->raknetInstance->send(packet);
printf("TakeItemEntityPacket \n");
LOGI("Inventory:\n"); LOGI("Inventory:\n");
for (int i = 0; i < inventory->numLinkedSlots; i++) { for (int i = 0; i < inventory->numLinkedSlots; i++) {
@@ -174,3 +175,12 @@ void ServerPlayer::displayClientMessage( const std::string& messageId ) {
ChatPacket package(messageId); ChatPacket package(messageId);
_mc->raknetInstance->send(owner, package); _mc->raknetInstance->send(owner, package);
} }
void ServerPlayer::causeFallDamage(float distance) {
int dmg = (int) ceil((distance - 3));
if (dmg > 0) {
SetHealthPacket packet(SetHealthPacket::HEALTH_MODIFY_OFFSET + dmg);
_mc->raknetInstance->send(owner, packet);
}
super::causeFallDamage(distance);
}

View File

@@ -52,6 +52,8 @@ public:
void setNewProto(bool proto) { isNewProto = proto; } void setNewProto(bool proto) { isNewProto = proto; }
bool getProto() { return isNewProto; } bool getProto() { return isNewProto; }
virtual void causeFallDamage(float distance);
private: private:
void nextContainerCounter(); void nextContainerCounter();
void setContainerMenu( BaseContainerMenu* menu ); void setContainerMenu( BaseContainerMenu* menu );

View File

@@ -129,6 +129,7 @@ public:
virtual bool isHangingEntity(); virtual bool isHangingEntity();
virtual int getAuxData(); virtual int getAuxData();
virtual void checkFallDamage(float ya, bool onGround);
protected: protected:
virtual void setRot(float yRot, float xRot); virtual void setRot(float yRot, float xRot);
@@ -137,7 +138,6 @@ protected:
virtual void resetPos(bool clearMore); virtual void resetPos(bool clearMore);
virtual void outOfWorld(); virtual void outOfWorld();
virtual void checkFallDamage(float ya, bool onGround);
virtual void causeFallDamage(float fallDamage2); virtual void causeFallDamage(float fallDamage2);
virtual void markHurt(); virtual void markHurt();

View File

@@ -729,7 +729,6 @@ bool Mob::isWaterMob()
void Mob::aiStep() void Mob::aiStep()
{ {
//@todo? 30 lines of code here in java version //@todo? 30 lines of code here in java version
TIMER_PUSH("ai"); TIMER_PUSH("ai");
if (isImmobile()) { if (isImmobile()) {
jumping = false; jumping = false;

View File

@@ -223,6 +223,9 @@ protected:
double xc, yc, zc; double xc, yc, zc;
public: public:
void setxxa(float xxa) { this->xxa = xxa; }
void setyya(float yya) { this->yya = yya; }
// Cape position accessors (for renderers) // Cape position accessors (for renderers)
double getCapeX() const { return xCape; } double getCapeX() const { return xCape; }
double getCapeY() const { return yCape; } double getCapeY() const { return yCape; }