diff --git a/apps/openmw-mp/Script/Functions/World.cpp b/apps/openmw-mp/Script/Functions/World.cpp index b8403155a..f5cd6962d 100644 --- a/apps/openmw-mp/Script/Functions/World.cpp +++ b/apps/openmw-mp/Script/Functions/World.cpp @@ -163,6 +163,11 @@ void WorldFunctions::SetEventAction(unsigned char action) noexcept writeEvent.action = action; } +void WorldFunctions::SetEventConsoleCommand(const char* consoleCommand) noexcept +{ + writeEvent.consoleCommand = consoleCommand; +} + void WorldFunctions::SetObjectRefId(const char* refId) noexcept { tempWorldObject.refId = refId; @@ -237,6 +242,15 @@ void WorldFunctions::SetObjectRotation(double x, double y, double z) noexcept tempWorldObject.position.rot[2] = z; } +void WorldFunctions::SetPlayerAsObject(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + tempWorldObject.guid = player->guid; + tempWorldObject.isPlayer = true; +} + void WorldFunctions::SetContainerItemRefId(const char* refId) noexcept { tempContainerItem.refId = refId; @@ -320,6 +334,12 @@ void WorldFunctions::SendContainer() noexcept mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_CONTAINER)->Send(writeEvent.guid); } +void WorldFunctions::SendConsoleCommand() noexcept +{ + mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_CONSOLE_COMMAND)->setEvent(&writeEvent); + mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_CONSOLE_COMMAND)->Send(writeEvent.guid); +} + void WorldFunctions::SetHour(unsigned short pid, double hour) noexcept { Player *player; diff --git a/apps/openmw-mp/Script/Functions/World.hpp b/apps/openmw-mp/Script/Functions/World.hpp index cfed8953c..7b343301f 100644 --- a/apps/openmw-mp/Script/Functions/World.hpp +++ b/apps/openmw-mp/Script/Functions/World.hpp @@ -33,6 +33,7 @@ \ {"SetEventCell", WorldFunctions::SetEventCell},\ {"SetEventAction", WorldFunctions::SetEventAction},\ + {"SetEventConsoleCommand", WorldFunctions::SetEventConsoleCommand},\ \ {"SetObjectRefId", WorldFunctions::SetObjectRefId},\ {"SetObjectRefNumIndex", WorldFunctions::SetObjectRefNumIndex},\ @@ -48,6 +49,7 @@ {"SetObjectMasterState", WorldFunctions::SetObjectMasterState},\ {"SetObjectPosition", WorldFunctions::SetObjectPosition},\ {"SetObjectRotation", WorldFunctions::SetObjectRotation},\ + {"SetPlayerAsObject", WorldFunctions::SetPlayerAsObject},\ \ {"SetContainerItemRefId", WorldFunctions::SetContainerItemRefId},\ {"SetContainerItemCount", WorldFunctions::SetContainerItemCount},\ @@ -65,6 +67,7 @@ {"SendObjectState", WorldFunctions::SendObjectState},\ {"SendDoorState", WorldFunctions::SendDoorState},\ {"SendContainer", WorldFunctions::SendContainer},\ + {"SendConsoleCommand", WorldFunctions::SendConsoleCommand},\ \ {"SetHour", WorldFunctions::SetHour},\ {"SetMonth", WorldFunctions::SetMonth},\ @@ -313,6 +316,17 @@ public: */ static void SetEventAction(unsigned char action) noexcept; + /** + * \brief Set the console command of the temporary event stored on the server. + * + * When sent, the command will run once on every object added to the event. If no objects + * have been added, it will run once without any object reference. + * + * \param consoleCommand The console command. + * \return void + */ + static void SetEventConsoleCommand(const char* consoleCommand) noexcept; + /** * \brief Set the refId of the temporary world object stored on the server. * @@ -457,6 +471,15 @@ public: */ static void SetObjectRotation(double x, double y, double z) noexcept; + /** + * \brief Set a player as the object in the temporary world object stored on the server. + * Currently only used for ConsoleCommand packets. + * + * \param pid The pid of the player. + * \return void + */ + static void SetPlayerAsObject(unsigned short pid) noexcept; + /** * \brief Set the refId of the temporary container item stored on the server. * @@ -583,6 +606,15 @@ public: */ static void SendContainer() noexcept; + /** + * \brief Send a ConsoleCommand packet. + * + * It is sent only to the player for whom the current event was initialized. + * + * \return void + */ + static void SendConsoleCommand() noexcept; + /** * \brief Set the game hour for a player and send a GameTime packet to that player. * diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index b6cd36e19..4ae470a1c 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -305,6 +305,16 @@ namespace MWBase virtual void executeInConsole (const std::string& path) = 0; + /* + Start of tes3mp addition + + Allow the execution of console commands from elsewhere in the code + */ + virtual void executeCommandInConsole(const std::string& command) = 0; + /* + End of tes3mp addition + */ + virtual void enableRest() = 0; virtual bool getRestEnabled() = 0; virtual bool getJournalAllowed() = 0; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 8d98e55d9..87476f2a3 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1450,6 +1450,19 @@ namespace MWGui mConsole->executeFile (path); } + /* + Start of tes3mp addition + + Allow the execution of console commands from elsewhere in the code + */ + void WindowManager::executeCommandInConsole(const std::string& command) + { + mConsole->execute(command); + } + /* + End of tes3mp addition + */ + MWGui::DialogueWindow* WindowManager::getDialogueWindow() { return mDialogueWindow; } MWGui::InventoryWindow* WindowManager::getInventoryWindow() { return mInventoryWindow; } MWGui::CountDialog* WindowManager::getCountDialog() { return mCountDialog; } diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 4f5ff1275..3eab95587 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -334,6 +334,16 @@ namespace MWGui virtual void executeInConsole (const std::string& path); + /* + Start of tes3mp addition + + Allow the execution of console commands from elsewhere in the code + */ + virtual void executeCommandInConsole(const std::string& command); + /* + End of tes3mp addition + */ + virtual void enableRest() { mRestAllowed = true; } virtual bool getRestEnabled(); diff --git a/apps/openmw/mwmp/LocalPlayer.hpp b/apps/openmw/mwmp/LocalPlayer.hpp index 30b3f9aab..558d45f1c 100644 --- a/apps/openmw/mwmp/LocalPlayer.hpp +++ b/apps/openmw/mwmp/LocalPlayer.hpp @@ -93,9 +93,10 @@ namespace mwmp void playAnimation(); void playSpeech(); + MWWorld::Ptr getPlayerPtr(); + private: Networking *getNetworking(); - MWWorld::Ptr getPlayerPtr(); }; } diff --git a/apps/openmw/mwmp/WorldEvent.cpp b/apps/openmw/mwmp/WorldEvent.cpp index c7f304ec1..10f57b8aa 100644 --- a/apps/openmw/mwmp/WorldEvent.cpp +++ b/apps/openmw/mwmp/WorldEvent.cpp @@ -432,6 +432,51 @@ void WorldEvent::activateDoors(MWWorld::CellStore* cellStore) } } +void WorldEvent::runConsoleCommands(MWWorld::CellStore* cellStore) +{ + MWBase::WindowManager *windowManager = MWBase::Environment::get().getWindowManager(); + + LOG_APPEND(Log::LOG_VERBOSE, "- console command: %s", consoleCommand.c_str()); + + if (worldObjects.empty()) + { + LOG_APPEND(Log::LOG_VERBOSE, "-- running with no object reference"); + windowManager->executeCommandInConsole(consoleCommand); + } + else + { + for (const auto &worldObject : worldObjects) + { + if (worldObject.isPlayer) + { + LOG_APPEND(Log::LOG_VERBOSE, "-- running on player %s"); + + if (worldObject.guid != Main::get().getLocalPlayer()->guid) + windowManager->setConsoleSelectedObject(PlayerList::getPlayer(worldObject.guid)->getPtr()); + else + windowManager->setConsoleSelectedObject(Main::get().getLocalPlayer()->getPlayerPtr()); + + windowManager->executeCommandInConsole(consoleCommand); + } + else + { + LOG_APPEND(Log::LOG_VERBOSE, "-- running on cellRef: %s, %i, %i", worldObject.refId.c_str(), worldObject.refNumIndex, worldObject.mpNum); + + MWWorld::Ptr ptrFound = cellStore->searchExact(worldObject.refNumIndex, worldObject.mpNum); + + if (ptrFound) + { + LOG_APPEND(Log::LOG_VERBOSE, "-- Found %s, %i, %i", ptrFound.getCellRef().getRefId().c_str(), + ptrFound.getCellRef().getRefNum(), ptrFound.getCellRef().getMpNum()); + + windowManager->setConsoleSelectedObject(ptrFound); + windowManager->executeCommandInConsole(consoleCommand); + } + } + } + } +} + void WorldEvent::setLocalShorts(MWWorld::CellStore* cellStore) { for (const auto &worldObject : worldObjects) diff --git a/apps/openmw/mwmp/WorldEvent.hpp b/apps/openmw/mwmp/WorldEvent.hpp index fb9650644..a9b1b4429 100644 --- a/apps/openmw/mwmp/WorldEvent.hpp +++ b/apps/openmw/mwmp/WorldEvent.hpp @@ -31,6 +31,7 @@ namespace mwmp void rotateObjects(MWWorld::CellStore* cellStore); void animateObjects(MWWorld::CellStore* cellStore); void activateDoors(MWWorld::CellStore* cellStore); + void runConsoleCommands(MWWorld::CellStore* cellStore); void setLocalShorts(MWWorld::CellStore* cellStore); void setLocalFloats(MWWorld::CellStore* cellStore); diff --git a/apps/openmw/mwmp/processors/ProcessorInitializer.cpp b/apps/openmw/mwmp/processors/ProcessorInitializer.cpp index 254655b18..f0b994486 100644 --- a/apps/openmw/mwmp/processors/ProcessorInitializer.cpp +++ b/apps/openmw/mwmp/processors/ProcessorInitializer.cpp @@ -125,6 +125,7 @@ void ProcessorInitializer() PlayerProcessor::AddProcessor(new ProcessorPlayerStatsDynamic()); PlayerProcessor::AddProcessor(new ProcessorPlayerTopic()); + WorldProcessor::AddProcessor(new ProcessorConsoleCommand()); WorldProcessor::AddProcessor(new ProcessorContainer()); WorldProcessor::AddProcessor(new ProcessorDoorState()); WorldProcessor::AddProcessor(new ProcessorMusicPlay()); diff --git a/apps/openmw/mwmp/processors/world/ProcessorConsoleCommand.hpp b/apps/openmw/mwmp/processors/world/ProcessorConsoleCommand.hpp index 9d6229a89..bf8492733 100644 --- a/apps/openmw/mwmp/processors/world/ProcessorConsoleCommand.hpp +++ b/apps/openmw/mwmp/processors/world/ProcessorConsoleCommand.hpp @@ -1,11 +1,11 @@ #ifndef OPENMW_PROCESSORCONSOLECOMMAND_HPP #define OPENMW_PROCESSORCONSOLECOMMAND_HPP -#include "../WorldProcessor.hpp" +#include "BaseObjectProcessor.hpp" namespace mwmp { - class ProcessorConsoleCommand : public WorldProcessor + class ProcessorConsoleCommand : public BaseObjectProcessor { public: ProcessorConsoleCommand() @@ -15,8 +15,9 @@ namespace mwmp virtual void Do(WorldPacket &packet, WorldEvent &event) { - LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Received %s", strPacketID.c_str()); - //event.runConsoleCommand(); + BaseObjectProcessor::Do(packet, event); + + event.runConsoleCommands(ptrCellStore); } }; } diff --git a/components/openmw-mp/Base/BaseEvent.hpp b/components/openmw-mp/Base/BaseEvent.hpp index 6adb60b7a..19f7e6ea3 100644 --- a/components/openmw-mp/Base/BaseEvent.hpp +++ b/components/openmw-mp/Base/BaseEvent.hpp @@ -55,6 +55,9 @@ namespace mwmp std::vector containerItems; unsigned int containerItemCount; + + RakNet::RakNetGUID guid; // only for events that can also affect players + bool isPlayer; }; class BaseEvent @@ -85,6 +88,7 @@ namespace mwmp unsigned int worldObjectCount; ESM::Cell cell; + std::string consoleCommand; unsigned char action; // 0 - Clear and set in entirety, 1 - Add item, 2 - Remove item, 3 - Request items diff --git a/components/openmw-mp/Packets/World/PacketConsoleCommand.cpp b/components/openmw-mp/Packets/World/PacketConsoleCommand.cpp index 796f7988e..a4f9f8517 100644 --- a/components/openmw-mp/Packets/World/PacketConsoleCommand.cpp +++ b/components/openmw-mp/Packets/World/PacketConsoleCommand.cpp @@ -8,7 +8,27 @@ PacketConsoleCommand::PacketConsoleCommand(RakNet::RakPeerInterface *peer) : Wor packetID = ID_CONSOLE_COMMAND; } -void PacketConsoleCommand::Object(WorldObject &worldObject, bool send) +void PacketConsoleCommand::Packet(RakNet::BitStream *bs, bool send) { - WorldPacket::Object(worldObject, send); + if (!PacketHeader(bs, send)) + return; + + RW(event->consoleCommand, send); + + WorldObject worldObject; + for (unsigned int i = 0; i < event->worldObjectCount; i++) + { + if (send) + worldObject = event->worldObjects.at(i); + + RW(worldObject.isPlayer, send); + + if (worldObject.isPlayer) + RW(worldObject.guid, send); + else + Object(worldObject, send); + + if (!send) + event->worldObjects.push_back(worldObject); + } } diff --git a/components/openmw-mp/Packets/World/PacketConsoleCommand.hpp b/components/openmw-mp/Packets/World/PacketConsoleCommand.hpp index f04d2c247..52f6c6943 100644 --- a/components/openmw-mp/Packets/World/PacketConsoleCommand.hpp +++ b/components/openmw-mp/Packets/World/PacketConsoleCommand.hpp @@ -10,7 +10,7 @@ namespace mwmp public: PacketConsoleCommand(RakNet::RakPeerInterface *peer); - virtual void Object(WorldObject &obj, bool send); + virtual void Packet(RakNet::BitStream *bs, bool send); }; }