2021-12-05 17:54:36 +00:00
/*
* Darkflame Universe
* Copyright 2018
*/
# include "SlashCommandHandler.h"
# include <sstream>
# include <iostream>
# include <fstream>
# include <exception>
# include "dZoneManager.h"
# include <stdio.h> /* defines FILENAME_MAX */
# ifdef _WIN32
# include <direct.h>
# define GetCurrentDir _getcwd
# else
# include <unistd.h>
# define GetCurrentDir getcwd
# endif
# include "Metrics.hpp"
# include "User.h"
# include "UserManager.h"
# include "BitStream.h"
# include "dCommonVars.h"
# include "GeneralUtils.h"
# include "Entity.h"
# include "EntityManager.h"
# include "dLogger.h"
# include "WorldPackets.h"
# include "GameMessages.h"
# include "CDClientDatabase.h"
# include "ZoneInstanceManager.h"
# include "ControllablePhysicsComponent.h"
# include "NiPoint3.h"
# include "NiQuaternion.h"
# include "ChatPackets.h"
# include "InventoryComponent.h"
# include "Game.h"
# include "CharacterComponent.h"
# include "Database.h"
# include "DestroyableComponent.h"
# include "dServer.h"
# include "MissionComponent.h"
# include "Mail.h"
# include "dpWorld.h"
# include "Item.h"
# include "PropertyManagementComponent.h"
# include "PacketUtils.h"
2023-01-07 05:17:05 +00:00
# include "Loot.h"
# include "EntityInfo.h"
# include "LUTriggers.h"
2021-12-05 17:54:36 +00:00
# include "Player.h"
# include "PhantomPhysicsComponent.h"
# include "ProximityMonitorComponent.h"
# include "dpShapeSphere.h"
# include "PossessableComponent.h"
# include "PossessorComponent.h"
# include "VehiclePhysicsComponent.h"
# include "BuffComponent.h"
# include "SkillComponent.h"
# include "VanityUtilities.h"
2022-01-01 10:10:12 +00:00
# include "ScriptedActivityComponent.h"
2022-07-24 18:04:02 +00:00
# include "LevelProgressionComponent.h"
2022-11-01 18:21:26 +00:00
# include "AssetManager.h"
2022-11-27 11:59:59 +00:00
# include "BinaryPathFinder.h"
2022-12-04 22:25:58 +00:00
# include "dConfig.h"
2023-01-07 06:14:51 +00:00
# include "eBubbleType.h"
2023-01-07 05:17:05 +00:00
# include "AMFFormat.h"
# include "MovingPlatformComponent.h"
2021-12-05 17:54:36 +00:00
# include "eMissionState.h"
2023-02-10 08:29:53 +00:00
# include "TriggerComponent.h"
2023-02-19 12:29:14 +00:00
# include "eServerDisconnectIdentifiers.h"
2023-04-25 18:17:40 +00:00
# include "eObjectBits.h"
2023-03-24 23:16:45 +00:00
# include "eGameMasterLevel.h"
2023-03-04 07:16:37 +00:00
# include "eReplicaComponentType.h"
2023-05-02 22:39:21 +00:00
# include "eControlScheme.h"
2023-05-03 21:38:32 +00:00
# include "eConnectionType.h"
# include "eChatInternalMessageType.h"
# include "eMasterMessageType.h"
2021-12-05 17:54:36 +00:00
2023-03-17 14:36:21 +00:00
# include "CDObjectsTable.h"
# include "CDZoneTableTable.h"
2021-12-05 17:54:36 +00:00
void SlashCommandHandler : : HandleChatCommand ( const std : : u16string & command , Entity * entity , const SystemAddress & sysAddr ) {
2023-04-08 20:45:45 +00:00
auto commandCopy = command ;
// Sanity check that a command was given
if ( command . empty ( ) | | command . front ( ) ! = u ' / ' ) return ;
commandCopy . erase ( commandCopy . begin ( ) ) ;
// Split the command by spaces
2021-12-05 17:54:36 +00:00
std : : string chatCommand ;
std : : vector < std : : string > args ;
2023-04-08 20:45:45 +00:00
auto wideCommand = GeneralUtils : : SplitString ( commandCopy , u ' ' ) ;
if ( wideCommand . empty ( ) ) return ;
2022-01-06 02:52:33 +00:00
2023-04-08 20:45:45 +00:00
// Convert the command to lowercase
chatCommand = GeneralUtils : : UTF16ToWTF8 ( wideCommand . front ( ) ) ;
std : : transform ( chatCommand . begin ( ) , chatCommand . end ( ) , chatCommand . begin ( ) , : : tolower ) ;
wideCommand . erase ( wideCommand . begin ( ) ) ;
2021-12-05 17:54:36 +00:00
2023-04-08 20:45:45 +00:00
// Convert the arguements to not u16strings
for ( auto wideArg : wideCommand ) args . push_back ( GeneralUtils : : UTF16ToWTF8 ( wideArg ) ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
User * user = UserManager : : Instance ( ) - > GetUser ( sysAddr ) ;
2023-03-24 23:16:45 +00:00
if ( ( chatCommand = = " setgmlevel " | | chatCommand = = " makegm " | | chatCommand = = " gmlevel " ) & & user - > GetMaxGMLevel ( ) > eGameMasterLevel : : CIVILIAN ) {
2021-12-05 17:54:36 +00:00
if ( args . size ( ) ! = 1 ) return ;
2022-01-06 02:52:33 +00:00
2023-03-24 23:16:45 +00:00
uint32_t level_intermed = 0 ;
2021-12-05 17:54:36 +00:00
2023-03-24 23:16:45 +00:00
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , level_intermed ) ) {
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid gm level. " ) ;
return ;
}
2023-03-24 23:16:45 +00:00
eGameMasterLevel level = static_cast < eGameMasterLevel > ( level_intermed ) ;
2021-12-05 17:54:36 +00:00
# ifndef DEVELOPER_SERVER
2023-03-24 23:16:45 +00:00
if ( user - > GetMaxGMLevel ( ) = = eGameMasterLevel : : JUNIOR_DEVELOPER ) {
level = eGameMasterLevel : : CIVILIAN ;
2021-12-05 17:54:36 +00:00
}
# endif
if ( level > user - > GetMaxGMLevel ( ) ) {
level = user - > GetMaxGMLevel ( ) ;
}
if ( level = = entity - > GetGMLevel ( ) ) return ;
bool success = user - > GetMaxGMLevel ( ) > = level ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
if ( success ) {
2022-04-12 19:06:03 +00:00
2023-03-24 23:16:45 +00:00
if ( entity - > GetGMLevel ( ) > eGameMasterLevel : : CIVILIAN & & level = = eGameMasterLevel : : CIVILIAN ) {
2021-12-05 17:54:36 +00:00
GameMessages : : SendToggleGMInvis ( entity - > GetObjectID ( ) , false , UNASSIGNED_SYSTEM_ADDRESS ) ;
2023-03-24 23:16:45 +00:00
} else if ( entity - > GetGMLevel ( ) = = eGameMasterLevel : : CIVILIAN & & level > eGameMasterLevel : : CIVILIAN ) {
2021-12-05 17:54:36 +00:00
GameMessages : : SendToggleGMInvis ( entity - > GetObjectID ( ) , true , UNASSIGNED_SYSTEM_ADDRESS ) ;
}
2022-04-12 23:30:46 +00:00
WorldPackets : : SendGMLevelChange ( sysAddr , success , user - > GetMaxGMLevel ( ) , entity - > GetGMLevel ( ) , level ) ;
GameMessages : : SendChatModeUpdate ( entity - > GetObjectID ( ) , level ) ;
entity - > SetGMLevel ( level ) ;
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " SlashCommandHandler " , " User %s (%i) has changed their GM level to %i for charID %llu " , user - > GetUsername ( ) . c_str ( ) , user - > GetAccountID ( ) , level , entity - > GetObjectID ( ) ) ;
2022-04-12 23:30:46 +00:00
}
}
2021-12-05 17:54:36 +00:00
# ifndef DEVELOPER_SERVER
2023-03-24 23:16:45 +00:00
if ( ( entity - > GetGMLevel ( ) > user - > GetMaxGMLevel ( ) ) | | ( entity - > GetGMLevel ( ) > eGameMasterLevel : : CIVILIAN & & user - > GetMaxGMLevel ( ) = = eGameMasterLevel : : JUNIOR_DEVELOPER ) ) {
WorldPackets : : SendGMLevelChange ( sysAddr , true , user - > GetMaxGMLevel ( ) , entity - > GetGMLevel ( ) , eGameMasterLevel : : CIVILIAN ) ;
GameMessages : : SendChatModeUpdate ( entity - > GetObjectID ( ) , eGameMasterLevel : : CIVILIAN ) ;
entity - > SetGMLevel ( eGameMasterLevel : : CIVILIAN ) ;
2021-12-05 17:54:36 +00:00
GameMessages : : SendToggleGMInvis ( entity - > GetObjectID ( ) , false , UNASSIGNED_SYSTEM_ADDRESS ) ;
ChatPackets : : SendSystemMessage ( sysAddr , u " Your game master level has been changed, you may not be able to use all commands. " ) ;
}
# endif
2023-04-02 01:30:08 +00:00
if ( chatCommand = = " togglenameplate " & & ( Game : : config - > GetValue ( " allow_nameplate_off " ) = = " 1 " | | entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) ) {
2023-03-23 14:49:31 +00:00
auto * character = entity - > GetCharacter ( ) ;
if ( character & & character - > GetBillboardVisible ( ) ) {
character - > SetBillboardVisible ( false ) ;
ChatPackets : : SendSystemMessage ( sysAddr , u " Your nameplate has been turned off and is not visible to players currently in this zone. " ) ;
} else {
character - > SetBillboardVisible ( true ) ;
ChatPackets : : SendSystemMessage ( sysAddr , u " Your nameplate is now on and visible to all players. " ) ;
}
return ;
}
2021-12-05 17:54:36 +00:00
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//HANDLE ALL NON GM SLASH COMMANDS RIGHT HERE!
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if ( chatCommand = = " pvp " ) {
auto * character = entity - > GetComponent < CharacterComponent > ( ) ;
if ( character = = nullptr ) {
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " SlashCommandHandler " , " Failed to find character component! " ) ;
2021-12-05 17:54:36 +00:00
return ;
}
character - > SetPvpEnabled ( ! character - > GetPvpEnabled ( ) ) ;
EntityManager : : Instance ( ) - > SerializeEntity ( entity ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
std : : stringstream message ;
message < < character - > GetName ( ) < < " changed their PVP flag to " < < std : : to_string ( character - > GetPvpEnabled ( ) ) < < " ! " ;
2022-01-06 02:52:33 +00:00
2022-08-02 13:56:20 +00:00
ChatPackets : : SendSystemMessage ( UNASSIGNED_SYSTEM_ADDRESS , GeneralUtils : : UTF8ToUTF16 ( message . str ( ) ) , true ) ;
2021-12-05 17:54:36 +00:00
return ;
}
if ( chatCommand = = " who " ) {
ChatPackets : : SendSystemMessage (
sysAddr ,
u " Players in this instance: ( " + GeneralUtils : : to_u16string ( Player : : GetAllPlayers ( ) . size ( ) ) + u " ) "
) ;
for ( auto * player : Player : : GetAllPlayers ( ) ) {
const auto & name = player - > GetCharacter ( ) - > GetName ( ) ;
ChatPackets : : SendSystemMessage (
sysAddr ,
2022-08-02 13:56:20 +00:00
GeneralUtils : : UTF8ToUTF16 ( player = = entity ? name + " (you) " : name )
2021-12-05 17:54:36 +00:00
) ;
}
}
if ( chatCommand = = " ping " ) {
if ( ! args . empty ( ) & & args [ 0 ] = = " -l " ) {
std : : stringstream message ;
message < < " Your latest ping: " < < std : : to_string ( Game : : server - > GetLatestPing ( sysAddr ) ) < < " ms " ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , GeneralUtils : : ASCIIToUTF16 ( message . str ( ) ) ) ;
} else {
std : : stringstream message ;
message < < " Your average ping: " < < std : : to_string ( Game : : server - > GetPing ( sysAddr ) ) < < " ms " ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , GeneralUtils : : ASCIIToUTF16 ( message . str ( ) ) ) ;
}
return ;
}
if ( chatCommand = = " fix-stats " ) {
// Reset skill component and buff component
auto * skillComponent = entity - > GetComponent < SkillComponent > ( ) ;
auto * buffComponent = entity - > GetComponent < BuffComponent > ( ) ;
auto * destroyableComponent = entity - > GetComponent < DestroyableComponent > ( ) ;
// If any of the components are nullptr, return
if ( skillComponent = = nullptr | | buffComponent = = nullptr | | destroyableComponent = = nullptr ) {
return ;
}
// Reset skill component
skillComponent - > Reset ( ) ;
// Reset buff component
buffComponent - > Reset ( ) ;
// Fix the destroyable component
destroyableComponent - > FixStats ( ) ;
}
if ( chatCommand = = " credits " | | chatCommand = = " info " ) {
2022-11-27 11:59:59 +00:00
const auto & customText = chatCommand = = " credits " ? VanityUtilities : : ParseMarkdown ( ( BinaryPathFinder : : GetBinaryDir ( ) / " vanity/CREDITS.md " ) . string ( ) ) : VanityUtilities : : ParseMarkdown ( ( BinaryPathFinder : : GetBinaryDir ( ) / " vanity/INFO.md " ) . string ( ) ) ;
2021-12-05 17:54:36 +00:00
{
AMFArrayValue args ;
auto * state = new AMFStringValue ( ) ;
state - > SetStringValue ( " Story " ) ;
args . InsertValue ( " state " , state ) ;
GameMessages : : SendUIMessageServerToSingleClient ( entity , entity - > GetSystemAddress ( ) , " pushGameState " , & args ) ;
}
entity - > AddCallbackTimer ( 0.5f , [ customText , entity ] ( ) {
AMFArrayValue args ;
auto * text = new AMFStringValue ( ) ;
text - > SetStringValue ( customText ) ;
2022-07-22 05:26:09 +00:00
args . InsertValue ( " visible " , new AMFTrueValue ( ) ) ;
2021-12-05 17:54:36 +00:00
args . InsertValue ( " text " , text ) ;
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " SlashCommandHandler " , " Sending %s " , customText . c_str ( ) ) ;
2021-12-05 17:54:36 +00:00
GameMessages : : SendUIMessageServerToSingleClient ( entity , entity - > GetSystemAddress ( ) , " ToggleStoryBox " , & args ) ;
} ) ;
return ;
}
2022-01-06 02:52:33 +00:00
if ( chatCommand = = " leave-zone " ) {
2021-12-05 17:54:36 +00:00
const auto currentZone = dZoneManager : : Instance ( ) - > GetZone ( ) - > GetZoneID ( ) . GetMapID ( ) ;
2022-02-04 06:32:45 +00:00
auto newZone = 0 ;
if ( currentZone % 100 = = 0 ) {
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " You are not in an instanced zone. " ) ;
return ;
2022-02-04 06:32:45 +00:00
} else {
newZone = ( currentZone / 100 ) * 100 ;
2021-12-05 17:54:36 +00:00
}
2022-02-04 06:32:45 +00:00
// If new zone would be inaccessible, then default to Avant Gardens.
if ( ! CheckIfAccessibleZone ( newZone ) ) newZone = 1100 ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Leaving zone... " ) ;
const auto objid = entity - > GetObjectID ( ) ;
ZoneInstanceManager : : Instance ( ) - > RequestZoneTransfer ( Game : : server , newZone , 0 , false , [ objid ] ( bool mythranShift , uint32_t zoneID , uint32_t zoneInstance , uint32_t zoneClone , std : : string serverIP , uint16_t serverPort ) {
auto * entity = EntityManager : : Instance ( ) - > GetEntity ( objid ) ;
if ( entity = = nullptr ) {
return ;
}
const auto sysAddr = entity - > GetSystemAddress ( ) ;
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " UserManager " , " Transferring %s to Zone %i (Instance %i | Clone %i | Mythran Shift: %s) with IP %s and Port %i " , entity - > GetCharacter ( ) - > GetName ( ) . c_str ( ) , zoneID , zoneInstance , zoneClone , mythranShift = = true ? " true " : " false " , serverIP . c_str ( ) , serverPort ) ;
2021-12-05 17:54:36 +00:00
if ( entity - > GetCharacter ( ) ) {
entity - > GetCharacter ( ) - > SetZoneID ( zoneID ) ;
entity - > GetCharacter ( ) - > SetZoneInstance ( zoneInstance ) ;
entity - > GetCharacter ( ) - > SetZoneClone ( zoneClone ) ;
}
entity - > GetCharacter ( ) - > SaveXMLToDatabase ( ) ;
WorldPackets : : SendTransferToWorld ( sysAddr , serverIP , serverPort , mythranShift ) ;
} ) ;
}
2022-01-06 02:52:33 +00:00
if ( chatCommand = = " join " & & ! args . empty ( ) ) {
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Requesting private map... " ) ;
const auto & password = args [ 0 ] ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
ZoneInstanceManager : : Instance ( ) - > RequestPrivateZone ( Game : : server , false , password , [ = ] ( bool mythranShift , uint32_t zoneID , uint32_t zoneInstance , uint32_t zoneClone , std : : string serverIP , uint16_t serverPort ) {
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " UserManager " , " Transferring %s to Zone %i (Instance %i | Clone %i | Mythran Shift: %s) with IP %s and Port %i " , sysAddr . ToString ( ) , zoneID , zoneInstance , zoneClone , mythranShift = = true ? " true " : " false " , serverIP . c_str ( ) , serverPort ) ;
2021-12-05 17:54:36 +00:00
if ( entity - > GetCharacter ( ) ) {
entity - > GetCharacter ( ) - > SetZoneID ( zoneID ) ;
entity - > GetCharacter ( ) - > SetZoneInstance ( zoneInstance ) ;
entity - > GetCharacter ( ) - > SetZoneClone ( zoneClone ) ;
}
entity - > GetCharacter ( ) - > SaveXMLToDatabase ( ) ;
WorldPackets : : SendTransferToWorld ( sysAddr , serverIP , serverPort , mythranShift ) ;
} ) ;
}
2023-03-24 23:16:45 +00:00
if ( user - > GetMaxGMLevel ( ) = = eGameMasterLevel : : CIVILIAN | | entity - > GetGMLevel ( ) > = eGameMasterLevel : : CIVILIAN ) {
2021-12-05 17:54:36 +00:00
if ( chatCommand = = " die " ) {
entity - > Smash ( entity - > GetObjectID ( ) ) ;
}
if ( chatCommand = = " resurrect " ) {
2022-01-01 10:10:12 +00:00
ScriptedActivityComponent * scriptedActivityComponent = dZoneManager : : Instance ( ) - > GetZoneControlObject ( ) - > GetComponent < ScriptedActivityComponent > ( ) ;
2022-01-06 02:52:33 +00:00
2022-01-01 10:10:12 +00:00
if ( scriptedActivityComponent ) { // check if user is in activity world and if so, they can't resurrect
ChatPackets : : SendSystemMessage ( sysAddr , u " You cannot resurrect in an activity world. " ) ;
return ;
}
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
GameMessages : : SendResurrect ( entity ) ;
}
if ( chatCommand = = " requestmailcount " ) {
Mail : : HandleNotificationRequest ( entity - > GetSystemAddress ( ) , entity - > GetObjectID ( ) ) ;
}
if ( chatCommand = = " instanceinfo " ) {
const auto zoneId = dZoneManager : : Instance ( ) - > GetZone ( ) - > GetZoneID ( ) ;
ChatPackets : : SendSystemMessage ( sysAddr , u " Map: " + ( GeneralUtils : : to_u16string ( zoneId . GetMapID ( ) ) ) + u " \n Clone: " + ( GeneralUtils : : to_u16string ( zoneId . GetCloneID ( ) ) ) + u " \n Instance: " + ( GeneralUtils : : to_u16string ( zoneId . GetInstanceID ( ) ) ) ) ;
}
2023-03-24 23:16:45 +00:00
if ( entity - > GetGMLevel ( ) = = eGameMasterLevel : : CIVILIAN ) return ;
2022-04-12 23:30:46 +00:00
}
2021-12-05 17:54:36 +00:00
// Log command to database
2022-04-12 23:30:46 +00:00
auto stmt = Database : : CreatePreppedStmt ( " INSERT INTO command_log (character_id, command) VALUES (?, ?); " ) ;
stmt - > setInt ( 1 , entity - > GetCharacter ( ) - > GetID ( ) ) ;
2021-12-05 17:54:36 +00:00
stmt - > setString ( 2 , GeneralUtils : : UTF16ToWTF8 ( command ) . c_str ( ) ) ;
stmt - > execute ( ) ;
delete stmt ;
2022-01-06 02:52:33 +00:00
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " setminifig " & & args . size ( ) = = 2 & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : FORUM_MODERATOR ) { // could break characters so only allow if GM > 0
2021-12-11 02:02:02 +00:00
int32_t minifigItemId ;
if ( ! GeneralUtils : : TryParse ( args [ 1 ] , minifigItemId ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid Minifig Item Id ID. " ) ;
return ;
}
EntityManager : : Instance ( ) - > DestructEntity ( entity , sysAddr ) ;
auto * charComp = entity - > GetComponent < CharacterComponent > ( ) ;
std : : string lowerName = args [ 0 ] ;
if ( lowerName . empty ( ) ) return ;
std : : transform ( lowerName . begin ( ) , lowerName . end ( ) , lowerName . begin ( ) , : : tolower ) ;
if ( lowerName = = " eyebrows " ) {
charComp - > m_Character - > SetEyebrows ( minifigItemId ) ;
} else if ( lowerName = = " eyes " ) {
charComp - > m_Character - > SetEyes ( minifigItemId ) ;
} else if ( lowerName = = " haircolor " ) {
charComp - > m_Character - > SetHairColor ( minifigItemId ) ;
} else if ( lowerName = = " hairstyle " ) {
charComp - > m_Character - > SetHairStyle ( minifigItemId ) ;
} else if ( lowerName = = " pants " ) {
charComp - > m_Character - > SetPantsColor ( minifigItemId ) ;
} else if ( lowerName = = " lefthand " ) {
charComp - > m_Character - > SetLeftHand ( minifigItemId ) ;
} else if ( lowerName = = " mouth " ) {
charComp - > m_Character - > SetMouth ( minifigItemId ) ;
} else if ( lowerName = = " righthand " ) {
charComp - > m_Character - > SetRightHand ( minifigItemId ) ;
2021-12-15 02:55:05 +00:00
} else if ( lowerName = = " shirtcolor " ) {
2021-12-11 02:02:02 +00:00
charComp - > m_Character - > SetShirtColor ( minifigItemId ) ;
} else if ( lowerName = = " hands " ) {
charComp - > m_Character - > SetLeftHand ( minifigItemId ) ;
charComp - > m_Character - > SetRightHand ( minifigItemId ) ;
} else {
EntityManager : : Instance ( ) - > ConstructEntity ( entity ) ;
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid Minifig item to change, try one of the following: Eyebrows, Eyes, HairColor, HairStyle, Pants, LeftHand, Mouth, RightHand, Shirt, Hands " ) ;
return ;
}
2022-01-06 02:52:33 +00:00
2021-12-11 02:02:02 +00:00
EntityManager : : Instance ( ) - > ConstructEntity ( entity ) ;
ChatPackets : : SendSystemMessage ( sysAddr , GeneralUtils : : ASCIIToUTF16 ( lowerName ) + u " set to " + ( GeneralUtils : : to_u16string ( minifigItemId ) ) ) ;
GameMessages : : SendToggleGMInvis ( entity - > GetObjectID ( ) , false , UNASSIGNED_SYSTEM_ADDRESS ) ; // need to retoggle because it gets reenabled on creation of new character
}
2023-03-24 23:16:45 +00:00
if ( ( chatCommand = = " playanimation " | | chatCommand = = " playanim " ) & & args . size ( ) = = 1 & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2022-03-29 20:06:28 +00:00
std : : u16string anim = GeneralUtils : : ASCIIToUTF16 ( args [ 0 ] , args [ 0 ] . size ( ) ) ;
GameMessages : : SendPlayAnimation ( entity , anim ) ;
2022-09-02 18:49:19 +00:00
auto * possessorComponent = entity - > GetComponent < PossessorComponent > ( ) ;
if ( possessorComponent ) {
auto * possessedComponent = EntityManager : : Instance ( ) - > GetEntity ( possessorComponent - > GetPossessable ( ) ) ;
if ( possessedComponent ) GameMessages : : SendPlayAnimation ( possessedComponent , anim ) ;
}
2022-03-29 20:06:28 +00:00
}
2021-12-11 02:02:02 +00:00
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " list-spawns " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
for ( const auto & pair : EntityManager : : Instance ( ) - > GetSpawnPointEntities ( ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , GeneralUtils : : ASCIIToUTF16 ( pair . first ) ) ;
}
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Current: " + GeneralUtils : : ASCIIToUTF16 ( entity - > GetCharacter ( ) - > GetTargetScene ( ) ) ) ;
return ;
}
2022-01-06 02:52:33 +00:00
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " unlock-emote " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
int32_t emoteID ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , emoteID ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid emote ID. " ) ;
return ;
}
entity - > GetCharacter ( ) - > UnlockEmote ( emoteID ) ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " force-save " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-11 02:02:02 +00:00
entity - > GetCharacter ( ) - > SaveXMLToDatabase ( ) ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " kill " & & args . size ( ) = = 1 & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Brutally murdering that player, if online on this server. " ) ;
auto * user = UserManager : : Instance ( ) - > GetUser ( args [ 0 ] ) ;
if ( user ) {
auto * player = EntityManager : : Instance ( ) - > GetEntity ( user - > GetLoggedInChar ( ) ) ;
player - > Smash ( entity - > GetObjectID ( ) ) ;
ChatPackets : : SendSystemMessage ( sysAddr , u " It has been done, do you feel good about yourself now? " ) ;
return ;
}
ChatPackets : : SendSystemMessage ( sysAddr , u " They were saved from your carnage. " ) ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " speedboost " & & args . size ( ) = = 1 & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
float boost ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , boost ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid boost. " ) ;
return ;
}
auto * controllablePhysicsComponent = entity - > GetComponent < ControllablePhysicsComponent > ( ) ;
2022-09-02 18:49:19 +00:00
if ( ! controllablePhysicsComponent ) return ;
2021-12-05 17:54:36 +00:00
controllablePhysicsComponent - > SetSpeedMultiplier ( boost ) ;
2022-09-02 18:49:19 +00:00
// speedboost possesables
auto possessor = entity - > GetComponent < PossessorComponent > ( ) ;
if ( possessor ) {
auto possessedID = possessor - > GetPossessable ( ) ;
if ( possessedID ! = LWOOBJID_EMPTY ) {
auto possessable = EntityManager : : Instance ( ) - > GetEntity ( possessedID ) ;
if ( possessable ) {
auto * possessControllablePhysicsComponent = possessable - > GetComponent < ControllablePhysicsComponent > ( ) ;
if ( possessControllablePhysicsComponent ) {
possessControllablePhysicsComponent - > SetSpeedMultiplier ( boost ) ;
}
}
}
}
2021-12-05 17:54:36 +00:00
EntityManager : : Instance ( ) - > SerializeEntity ( entity ) ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " freecam " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
const auto state = ! entity - > GetVar < bool > ( u " freecam " ) ;
entity - > SetVar < bool > ( u " freecam " , state ) ;
2023-05-02 22:39:21 +00:00
GameMessages : : SendSetPlayerControlScheme ( entity , static_cast < eControlScheme > ( state ? 9 : 1 ) ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Toggled freecam. " ) ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " setcontrolscheme " & & args . size ( ) = = 1 & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
uint32_t scheme ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , scheme ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid control scheme. " ) ;
return ;
}
2022-01-06 02:52:33 +00:00
2023-05-02 22:39:21 +00:00
GameMessages : : SendSetPlayerControlScheme ( entity , static_cast < eControlScheme > ( scheme ) ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Switched control scheme. " ) ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " approveproperty " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : LEAD_MODERATOR ) {
2021-12-05 17:54:36 +00:00
if ( PropertyManagementComponent : : Instance ( ) ! = nullptr ) {
PropertyManagementComponent : : Instance ( ) - > UpdateApprovedStatus ( true ) ;
}
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " setuistate " & & args . size ( ) = = 1 & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
AMFStringValue * value = new AMFStringValue ( ) ;
value - > SetStringValue ( args [ 0 ] ) ;
AMFArrayValue args ;
args . InsertValue ( " state " , value ) ;
GameMessages : : SendUIMessageServerToSingleClient ( entity , sysAddr , " pushGameState " , & args ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Switched UI state. " ) ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " toggle " & & args . size ( ) = = 1 & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
AMFTrueValue * value = new AMFTrueValue ( ) ;
AMFArrayValue amfArgs ;
amfArgs . InsertValue ( " visible " , value ) ;
GameMessages : : SendUIMessageServerToSingleClient ( entity , sysAddr , args [ 0 ] , & amfArgs ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Toggled UI state. " ) ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( ( chatCommand = = " setinventorysize " | | chatCommand = = " setinvsize " ) & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) > = 1 ) {
2021-12-05 17:54:36 +00:00
uint32_t size ;
2023-03-14 12:50:12 +00:00
if ( ! GeneralUtils : : TryParse ( args . at ( 0 ) , size ) ) {
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid size. " ) ;
return ;
}
2022-01-06 02:52:33 +00:00
2023-03-14 12:50:12 +00:00
eInventoryType selectedInventory = eInventoryType : : ITEMS ;
2022-01-06 02:52:33 +00:00
2023-03-14 12:50:12 +00:00
// a possible inventory was provided if we got more than 1 argument
if ( args . size ( ) > = 2 ) {
selectedInventory = eInventoryType : : INVALID ;
if ( ! GeneralUtils : : TryParse ( args . at ( 1 ) , selectedInventory ) ) {
// In this case, we treat the input as a string and try to find it in the reflection list
std : : transform ( args . at ( 1 ) . begin ( ) , args . at ( 1 ) . end ( ) , args . at ( 1 ) . begin ( ) , : : toupper ) ;
for ( uint32_t index = 0 ; index < NUMBER_OF_INVENTORIES ; index + + ) {
if ( std : : string_view ( args . at ( 1 ) ) = = std : : string_view ( InventoryType : : InventoryTypeToString ( static_cast < eInventoryType > ( index ) ) ) ) selectedInventory = static_cast < eInventoryType > ( index ) ;
}
}
if ( selectedInventory = = eInventoryType : : INVALID ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid inventory. " ) ;
return ;
}
ChatPackets : : SendSystemMessage ( sysAddr , u " Setting inventory " +
GeneralUtils : : ASCIIToUTF16 ( args . at ( 1 ) ) +
u " to size " +
GeneralUtils : : to_u16string ( size ) ) ;
} else ChatPackets : : SendSystemMessage ( sysAddr , u " Setting inventory ITEMS to size " + GeneralUtils : : to_u16string ( size ) ) ;
auto * inventoryComponent = entity - > GetComponent < InventoryComponent > ( ) ;
if ( inventoryComponent ) {
auto * inventory = inventoryComponent - > GetInventory ( selectedInventory ) ;
inventory - > SetSize ( size ) ;
2021-12-05 17:54:36 +00:00
}
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " runmacro " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
if ( args . size ( ) ! = 1 ) return ;
2022-01-04 05:40:07 +00:00
// Only process if input does not contain separator charaters
if ( args [ 0 ] . find ( " / " ) ! = std : : string : : npos ) return ;
if ( args [ 0 ] . find ( " \\ " ) ! = std : : string : : npos ) return ;
2022-11-01 18:21:26 +00:00
auto buf = Game : : assetManager - > GetFileAsBuffer ( ( " macros/ " + args [ 0 ] + " .scm " ) . c_str ( ) ) ;
2022-11-10 18:59:31 +00:00
2023-03-14 12:50:12 +00:00
if ( ! buf . m_Success ) {
2022-11-10 18:59:31 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Unknown macro! Is the filename right? " ) ;
return ;
2023-03-14 12:50:12 +00:00
}
2022-11-10 18:59:31 +00:00
2022-11-01 18:21:26 +00:00
std : : istream infile ( & buf ) ;
2021-12-05 17:54:36 +00:00
if ( infile . good ( ) ) {
std : : string line ;
while ( std : : getline ( infile , line ) ) {
SlashCommandHandler : : HandleChatCommand ( GeneralUtils : : ASCIIToUTF16 ( line ) , entity , sysAddr ) ;
}
} else {
ChatPackets : : SendSystemMessage ( sysAddr , u " Unknown macro! Is the filename right? " ) ;
}
2022-01-06 02:52:33 +00:00
2022-11-01 18:21:26 +00:00
buf . close ( ) ;
2021-12-05 17:54:36 +00:00
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " addmission " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
if ( args . size ( ) = = 0 ) return ;
uint32_t missionID ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , missionID ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid mission id. " ) ;
return ;
}
2022-01-06 02:52:33 +00:00
2023-03-04 07:16:37 +00:00
auto comp = static_cast < MissionComponent * > ( entity - > GetComponent ( eReplicaComponentType : : MISSION ) ) ;
2021-12-05 17:54:36 +00:00
if ( comp ) comp - > AcceptMission ( missionID , true ) ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " completemission " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
if ( args . size ( ) = = 0 ) return ;
uint32_t missionID ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , missionID ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid mission id. " ) ;
return ;
}
2022-01-06 02:52:33 +00:00
2023-03-04 07:16:37 +00:00
auto comp = static_cast < MissionComponent * > ( entity - > GetComponent ( eReplicaComponentType : : MISSION ) ) ;
2021-12-05 17:54:36 +00:00
if ( comp ) comp - > CompleteMission ( missionID , true ) ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " setflag " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) = = 1 ) {
2023-05-02 22:39:21 +00:00
int32_t flagId ;
2021-12-05 17:54:36 +00:00
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , flagId ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid flag id. " ) ;
return ;
}
2022-04-12 23:30:46 +00:00
entity - > GetCharacter ( ) - > SetPlayerFlag ( flagId , true ) ;
2021-12-05 17:54:36 +00:00
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " setflag " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) = = 2 ) {
2023-05-02 22:39:21 +00:00
int32_t flagId ;
2022-01-24 13:57:50 +00:00
std : : string onOffFlag = args [ 0 ] ;
if ( ! GeneralUtils : : TryParse ( args [ 1 ] , flagId ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid flag id. " ) ;
return ;
}
if ( onOffFlag ! = " off " & & onOffFlag ! = " on " ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid flag type. " ) ;
return ;
}
2022-04-12 23:30:46 +00:00
entity - > GetCharacter ( ) - > SetPlayerFlag ( flagId , onOffFlag = = " on " ) ;
2022-01-24 13:57:50 +00:00
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " clearflag " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) = = 1 ) {
2023-05-02 22:39:21 +00:00
int32_t flagId ;
2021-12-05 17:54:36 +00:00
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , flagId ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid flag id. " ) ;
return ;
}
2022-04-12 23:30:46 +00:00
entity - > GetCharacter ( ) - > SetPlayerFlag ( flagId , false ) ;
2021-12-05 17:54:36 +00:00
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " resetmission " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
if ( args . size ( ) = = 0 ) return ;
uint32_t missionID ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , missionID ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid mission id. " ) ;
return ;
}
2022-01-06 02:52:33 +00:00
2023-03-04 07:16:37 +00:00
auto * comp = static_cast < MissionComponent * > ( entity - > GetComponent ( eReplicaComponentType : : MISSION ) ) ;
2021-12-05 17:54:36 +00:00
if ( comp = = nullptr ) {
return ;
}
auto * mission = comp - > GetMission ( missionID ) ;
if ( mission = = nullptr ) {
return ;
}
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
mission - > SetMissionState ( eMissionState : : ACTIVE ) ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " playeffect " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) > = 3 ) {
2021-12-05 17:54:36 +00:00
int32_t effectID = 0 ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , effectID ) ) {
return ;
}
2022-08-02 13:56:20 +00:00
// FIXME: use fallible ASCIIToUTF16 conversion, because non-ascii isn't valid anyway
2021-12-05 17:54:36 +00:00
GameMessages : : SendPlayFXEffect ( entity - > GetObjectID ( ) , effectID , GeneralUtils : : ASCIIToUTF16 ( args [ 1 ] ) , args [ 2 ] ) ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " stopeffect " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) > = 1 ) {
2021-12-05 17:54:36 +00:00
GameMessages : : SendStopFXEffect ( entity , true , args [ 0 ] ) ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " setanntitle " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
if ( args . size ( ) < 0 ) return ;
std : : stringstream ss ;
for ( auto string : args )
ss < < string < < " " ;
entity - > GetCharacter ( ) - > SetAnnouncementTitle ( ss . str ( ) ) ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " setannmsg " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
if ( args . size ( ) < 0 ) return ;
std : : stringstream ss ;
for ( auto string : args )
ss < < string < < " " ;
entity - > GetCharacter ( ) - > SetAnnouncementMessage ( ss . str ( ) ) ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " announce " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
if ( entity - > GetCharacter ( ) - > GetAnnouncementTitle ( ) . size ( ) = = 0 | | entity - > GetCharacter ( ) - > GetAnnouncementMessage ( ) . size ( ) = = 0 ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Use /setanntitle <title> & /setannmsg <msg> first! " ) ;
return ;
}
SendAnnouncement ( entity - > GetCharacter ( ) - > GetAnnouncementTitle ( ) , entity - > GetCharacter ( ) - > GetAnnouncementMessage ( ) ) ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " shutdownuniverse " & & entity - > GetGMLevel ( ) = = eGameMasterLevel : : OPERATOR ) {
2021-12-05 17:54:36 +00:00
//Tell the master server that we're going to be shutting down whole "universe":
CBITSTREAM ;
2023-05-03 21:38:32 +00:00
PacketUtils : : WriteHeader ( bitStream , eConnectionType : : MASTER , eMasterMessageType : : SHUTDOWN_UNIVERSE ) ;
2021-12-05 17:54:36 +00:00
Game : : server - > SendToMaster ( & bitStream ) ;
ChatPackets : : SendSystemMessage ( sysAddr , u " Sent universe shutdown notification to master. " ) ;
//Tell chat to send an announcement to all servers
SendAnnouncement ( " Servers Closing Soon! " , " DLU servers will close for maintenance in 10 minutes from now. " ) ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " getnavmeshheight " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2023-03-04 07:16:37 +00:00
auto control = static_cast < ControllablePhysicsComponent * > ( entity - > GetComponent ( eReplicaComponentType : : CONTROLLABLE_PHYSICS ) ) ;
2021-12-05 17:54:36 +00:00
if ( ! control ) return ;
2022-08-02 05:30:19 +00:00
float y = dpWorld : : Instance ( ) . GetNavMesh ( ) - > GetHeightAtPoint ( control - > GetPosition ( ) ) ;
2021-12-05 17:54:36 +00:00
std : : u16string msg = u " Navmesh height: " + ( GeneralUtils : : to_u16string ( y ) ) ;
ChatPackets : : SendSystemMessage ( sysAddr , msg ) ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " gmadditem " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2022-04-12 23:30:46 +00:00
if ( args . size ( ) = = 1 ) {
2021-12-05 17:54:36 +00:00
uint32_t itemLOT ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , itemLOT ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid item LOT. " ) ;
return ;
}
2022-01-06 02:52:33 +00:00
2023-03-04 07:16:37 +00:00
InventoryComponent * inventory = static_cast < InventoryComponent * > ( entity - > GetComponent ( eReplicaComponentType : : INVENTORY ) ) ;
2021-12-05 17:54:36 +00:00
2023-05-02 22:39:21 +00:00
inventory - > AddItem ( itemLOT , 1 , eLootSourceType : : MODERATION ) ;
2022-04-12 23:30:46 +00:00
} else if ( args . size ( ) = = 2 ) {
2021-12-05 17:54:36 +00:00
uint32_t itemLOT ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , itemLOT ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid item LOT. " ) ;
return ;
}
uint32_t count ;
if ( ! GeneralUtils : : TryParse ( args [ 1 ] , count ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid item count. " ) ;
return ;
}
2023-03-04 07:16:37 +00:00
InventoryComponent * inventory = static_cast < InventoryComponent * > ( entity - > GetComponent ( eReplicaComponentType : : INVENTORY ) ) ;
2021-12-05 17:54:36 +00:00
2023-05-02 22:39:21 +00:00
inventory - > AddItem ( itemLOT , count , eLootSourceType : : MODERATION ) ;
2021-12-05 17:54:36 +00:00
} else {
2022-04-12 23:30:46 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Correct usage: /gmadditem <lot> " ) ;
}
}
2021-12-05 17:54:36 +00:00
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " mailitem " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : MODERATOR & & args . size ( ) > = 2 ) {
2021-12-05 17:54:36 +00:00
const auto & playerName = args [ 0 ] ;
sql : : PreparedStatement * stmt = Database : : CreatePreppedStmt ( " SELECT id from charinfo WHERE name=? LIMIT 1; " ) ;
stmt - > setString ( 1 , playerName ) ;
sql : : ResultSet * res = stmt - > executeQuery ( ) ;
uint32_t receiverID = 0 ;
if ( res - > rowsCount ( ) > 0 ) {
while ( res - > next ( ) ) receiverID = res - > getUInt ( 1 ) ;
}
delete stmt ;
delete res ;
if ( receiverID = = 0 ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Failed to find that player " ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
return ;
}
uint32_t lot ;
if ( ! GeneralUtils : : TryParse ( args [ 1 ] , lot ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid item lot. " ) ;
return ;
}
uint64_t currentTime = time ( NULL ) ;
sql : : PreparedStatement * ins = Database : : CreatePreppedStmt ( " INSERT INTO `mail`(`sender_id`, `sender_name`, `receiver_id`, `receiver_name`, `time_sent`, `subject`, `body`, `attachment_id`, `attachment_lot`, `attachment_subkey`, `attachment_count`, `was_read`) VALUES (?,?,?,?,?,?,?,?,?,?,?,0) " ) ;
ins - > setUInt ( 1 , entity - > GetObjectID ( ) ) ;
ins - > setString ( 2 , " Darkflame Universe " ) ;
ins - > setUInt ( 3 , receiverID ) ;
ins - > setString ( 4 , playerName ) ;
ins - > setUInt64 ( 5 , currentTime ) ;
ins - > setString ( 6 , " Lost item " ) ;
ins - > setString ( 7 , " This is a replacement item for one you lost. " ) ;
ins - > setUInt ( 8 , 0 ) ;
ins - > setInt ( 9 , lot ) ;
ins - > setInt ( 10 , 0 ) ;
ins - > setInt ( 11 , 1 ) ;
ins - > execute ( ) ;
delete ins ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Mail sent " ) ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " setname " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
std : : string name = " " ;
for ( const auto & arg : args ) {
name + = arg + " " ;
}
2022-08-02 13:56:20 +00:00
GameMessages : : SendSetName ( entity - > GetObjectID ( ) , GeneralUtils : : UTF8ToUTF16 ( name ) , UNASSIGNED_SYSTEM_ADDRESS ) ;
2021-12-05 17:54:36 +00:00
}
2022-01-06 02:52:33 +00:00
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " title " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
std : : string name = entity - > GetCharacter ( ) - > GetName ( ) + " - " ;
for ( const auto & arg : args ) {
name + = arg + " " ;
}
2022-08-02 13:56:20 +00:00
GameMessages : : SendSetName ( entity - > GetObjectID ( ) , GeneralUtils : : UTF8ToUTF16 ( name ) , UNASSIGNED_SYSTEM_ADDRESS ) ;
2021-12-05 17:54:36 +00:00
}
2023-03-24 23:16:45 +00:00
if ( ( chatCommand = = " teleport " | | chatCommand = = " tele " ) & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : JUNIOR_MODERATOR ) {
2022-04-12 23:30:46 +00:00
NiPoint3 pos { } ;
if ( args . size ( ) = = 3 ) {
2021-12-05 17:54:36 +00:00
float x , y , z ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , x ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid x. " ) ;
return ;
}
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
if ( ! GeneralUtils : : TryParse ( args [ 1 ] , y ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid y. " ) ;
return ;
}
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
if ( ! GeneralUtils : : TryParse ( args [ 2 ] , z ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid z. " ) ;
return ;
}
pos . SetX ( x ) ;
pos . SetY ( y ) ;
pos . SetZ ( z ) ;
2022-01-06 02:52:33 +00:00
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " SlashCommandHandler " , " Teleporting objectID: %llu to %f, %f, %f " , entity - > GetObjectID ( ) , pos . x , pos . y , pos . z ) ;
2021-12-05 17:54:36 +00:00
GameMessages : : SendTeleport ( entity - > GetObjectID ( ) , pos , NiQuaternion ( ) , sysAddr ) ;
} else if ( args . size ( ) = = 2 ) {
2022-04-12 19:06:03 +00:00
2021-12-05 17:54:36 +00:00
float x , z ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , x ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid x. " ) ;
return ;
}
if ( ! GeneralUtils : : TryParse ( args [ 1 ] , z ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid z. " ) ;
return ;
}
pos . SetX ( x ) ;
pos . SetY ( 0.0f ) ;
pos . SetZ ( z ) ;
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " SlashCommandHandler " , " Teleporting objectID: %llu to X: %f, Z: %f " , entity - > GetObjectID ( ) , pos . x , pos . z ) ;
2021-12-05 17:54:36 +00:00
GameMessages : : SendTeleport ( entity - > GetObjectID ( ) , pos , NiQuaternion ( ) , sysAddr ) ;
} else {
ChatPackets : : SendSystemMessage ( sysAddr , u " Correct usage: /teleport <x> (<y>) <z> - if no Y given, will teleport to the height of the terrain (or any physics object). " ) ;
}
2022-09-02 18:49:19 +00:00
auto * possessorComponent = entity - > GetComponent < PossessorComponent > ( ) ;
if ( possessorComponent ) {
2021-12-05 17:54:36 +00:00
auto * possassableEntity = EntityManager : : Instance ( ) - > GetEntity ( possessorComponent - > GetPossessable ( ) ) ;
if ( possassableEntity ! = nullptr ) {
auto * vehiclePhysicsComponent = possassableEntity - > GetComponent < VehiclePhysicsComponent > ( ) ;
2022-09-02 18:49:19 +00:00
if ( vehiclePhysicsComponent ) {
2021-12-05 17:54:36 +00:00
vehiclePhysicsComponent - > SetPosition ( pos ) ;
EntityManager : : Instance ( ) - > SerializeEntity ( possassableEntity ) ;
2022-09-02 18:49:19 +00:00
} else GameMessages : : SendTeleport ( possassableEntity - > GetObjectID ( ) , pos , NiQuaternion ( ) , sysAddr ) ;
2021-12-05 17:54:36 +00:00
}
}
2022-04-12 23:30:46 +00:00
}
2021-12-05 17:54:36 +00:00
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " tpall " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
const auto pos = entity - > GetPosition ( ) ;
2023-03-04 07:16:37 +00:00
const auto characters = EntityManager : : Instance ( ) - > GetEntitiesByComponent ( eReplicaComponentType : : CHARACTER ) ;
2021-12-05 17:54:36 +00:00
for ( auto * character : characters ) {
GameMessages : : SendTeleport ( character - > GetObjectID ( ) , pos , NiQuaternion ( ) , character - > GetSystemAddress ( ) ) ;
}
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " dismount " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2022-09-02 18:49:19 +00:00
auto * possessorComponent = entity - > GetComponent < PossessorComponent > ( ) ;
if ( possessorComponent ) {
auto possessableId = possessorComponent - > GetPossessable ( ) ;
if ( possessableId ! = LWOOBJID_EMPTY ) {
auto * possessableEntity = EntityManager : : Instance ( ) - > GetEntity ( possessableId ) ;
if ( possessableEntity ) possessorComponent - > Dismount ( possessableEntity , true ) ;
2021-12-05 17:54:36 +00:00
}
}
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " fly " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : JUNIOR_DEVELOPER ) {
2022-08-06 08:19:34 +00:00
auto * character = entity - > GetCharacter ( ) ;
if ( character ) {
bool isFlying = character - > GetIsFlying ( ) ;
if ( isFlying ) {
GameMessages : : SendSetJetPackMode ( entity , false ) ;
character - > SetIsFlying ( false ) ;
} else {
float speedScale = 1.0f ;
if ( args . size ( ) > = 1 ) {
float tempScaleStore ;
if ( GeneralUtils : : TryParse < float > ( args [ 0 ] , tempScaleStore ) ) {
speedScale = tempScaleStore ;
} else {
ChatPackets : : SendSystemMessage ( sysAddr , u " Failed to parse speed scale argument. " ) ;
}
}
float airSpeed = 20 * speedScale ;
float maxAirSpeed = 30 * speedScale ;
float verticalVelocity = 1.5 * speedScale ;
GameMessages : : SendSetJetPackMode ( entity , true , true , false , 167 , airSpeed , maxAirSpeed , verticalVelocity ) ;
character - > SetIsFlying ( true ) ;
}
}
}
2021-12-05 17:54:36 +00:00
//------- GM COMMANDS TO ACTUALLY MODERATE --------
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " mute " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : JUNIOR_DEVELOPER ) {
2021-12-05 17:54:36 +00:00
if ( args . size ( ) > = 1 ) {
auto * player = Player : : GetPlayer ( args [ 0 ] ) ;
uint32_t accountId = 0 ;
LWOOBJID characterId = 0 ;
if ( player = = nullptr ) {
auto * accountQuery = Database : : CreatePreppedStmt ( " SELECT account_id, id FROM charinfo WHERE name=? LIMIT 1; " ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
accountQuery - > setString ( 1 , args [ 0 ] ) ;
auto result = accountQuery - > executeQuery ( ) ;
if ( result - > rowsCount ( ) > 0 ) {
while ( result - > next ( ) ) {
accountId = result - > getUInt ( 1 ) ;
characterId = result - > getUInt64 ( 2 ) ;
2022-01-06 02:52:33 +00:00
2023-04-25 18:17:40 +00:00
GeneralUtils : : SetBit ( characterId , eObjectBits : : CHARACTER ) ;
GeneralUtils : : SetBit ( characterId , eObjectBits : : PERSISTENT ) ;
2021-12-05 17:54:36 +00:00
}
}
delete accountQuery ;
delete result ;
if ( accountId = = 0 ) {
2022-08-02 13:56:20 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Count not find player of name: " + GeneralUtils : : UTF8ToUTF16 ( args [ 0 ] ) ) ;
2021-12-05 17:54:36 +00:00
return ;
}
} else {
accountId = player - > GetParentUser ( ) - > GetAccountID ( ) ;
characterId = player - > GetCharacter ( ) - > GetID ( ) ;
}
auto * userUpdate = Database : : CreatePreppedStmt ( " UPDATE accounts SET mute_expire = ? WHERE id = ?; " ) ;
time_t expire = 1 ; // Default to indefinate mute
if ( args . size ( ) > = 2 ) {
uint32_t days = 0 ;
uint32_t hours = 0 ;
if ( ! GeneralUtils : : TryParse ( args [ 1 ] , days ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid days. " ) ;
return ;
}
if ( args . size ( ) > = 3 ) {
if ( ! GeneralUtils : : TryParse ( args [ 2 ] , hours ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid hours. " ) ;
return ;
}
}
expire = time ( NULL ) ;
expire + = 24 * 60 * 60 * days ;
expire + = 60 * 60 * hours ;
}
userUpdate - > setUInt64 ( 1 , expire ) ;
userUpdate - > setInt ( 2 , accountId ) ;
userUpdate - > executeUpdate ( ) ;
delete userUpdate ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
char buffer [ 32 ] = " brought up for review. \0 " ;
if ( expire ! = 1 ) {
std : : tm * ptm = std : : localtime ( & expire ) ;
// Format: Mo, 15.06.2009 20:20:00
std : : strftime ( buffer , 32 , " %a, %d.%m.%Y %H:%M:%S " , ptm ) ;
}
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
const auto timeStr = GeneralUtils : : ASCIIToUTF16 ( std : : string ( buffer ) ) ;
2022-08-02 13:56:20 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Muted: " + GeneralUtils : : UTF8ToUTF16 ( args [ 0 ] ) + u " until " + timeStr ) ;
2021-12-05 17:54:36 +00:00
2022-01-06 02:52:33 +00:00
//Notify chat about it
2021-12-05 17:54:36 +00:00
CBITSTREAM ;
2023-05-03 21:38:32 +00:00
PacketUtils : : WriteHeader ( bitStream , eConnectionType : : CHAT_INTERNAL , eChatInternalMessageType : : MUTE_UPDATE ) ;
2021-12-05 17:54:36 +00:00
bitStream . Write ( characterId ) ;
bitStream . Write ( expire ) ;
Game : : chatServer - > Send ( & bitStream , SYSTEM_PRIORITY , RELIABLE , 0 , Game : : chatSysAddr , false ) ;
} else {
ChatPackets : : SendSystemMessage ( sysAddr , u " Correct usage: /mute <username> <days (optional)> <hours (optional)> " ) ;
}
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " kick " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : JUNIOR_MODERATOR ) {
2021-12-05 17:54:36 +00:00
if ( args . size ( ) = = 1 ) {
auto * player = Player : : GetPlayer ( args [ 0 ] ) ;
2022-08-02 13:56:20 +00:00
std : : u16string username = GeneralUtils : : UTF8ToUTF16 ( args [ 0 ] ) ;
2021-12-05 17:54:36 +00:00
if ( player = = nullptr ) {
2022-08-02 13:56:20 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Count not find player of name: " + username ) ;
2021-12-05 17:54:36 +00:00
return ;
}
2023-02-19 12:29:14 +00:00
Game : : server - > Disconnect ( player - > GetSystemAddress ( ) , eServerDisconnectIdentifiers : : KICK ) ;
2021-12-05 17:54:36 +00:00
2022-08-02 13:56:20 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Kicked: " + username ) ;
2021-12-05 17:54:36 +00:00
} else {
ChatPackets : : SendSystemMessage ( sysAddr , u " Correct usage: /kick <username> " ) ;
}
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " ban " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : SENIOR_MODERATOR ) {
2021-12-05 17:54:36 +00:00
if ( args . size ( ) = = 1 ) {
auto * player = Player : : GetPlayer ( args [ 0 ] ) ;
uint32_t accountId = 0 ;
if ( player = = nullptr ) {
auto * accountQuery = Database : : CreatePreppedStmt ( " SELECT account_id FROM charinfo WHERE name=? LIMIT 1; " ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
accountQuery - > setString ( 1 , args [ 0 ] ) ;
auto result = accountQuery - > executeQuery ( ) ;
if ( result - > rowsCount ( ) > 0 ) {
while ( result - > next ( ) ) accountId = result - > getUInt ( 1 ) ;
}
delete accountQuery ;
delete result ;
if ( accountId = = 0 ) {
2022-08-02 13:56:20 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Count not find player of name: " + GeneralUtils : : UTF8ToUTF16 ( args [ 0 ] ) ) ;
2021-12-05 17:54:36 +00:00
return ;
}
} else {
accountId = player - > GetParentUser ( ) - > GetAccountID ( ) ;
}
auto * userUpdate = Database : : CreatePreppedStmt ( " UPDATE accounts SET banned = true WHERE id = ?; " ) ;
userUpdate - > setInt ( 1 , accountId ) ;
userUpdate - > executeUpdate ( ) ;
delete userUpdate ;
if ( player ! = nullptr ) {
2023-02-19 12:29:14 +00:00
Game : : server - > Disconnect ( player - > GetSystemAddress ( ) , eServerDisconnectIdentifiers : : FREE_TRIAL_EXPIRED ) ;
2021-12-05 17:54:36 +00:00
}
ChatPackets : : SendSystemMessage ( sysAddr , u " Banned: " + GeneralUtils : : ASCIIToUTF16 ( args [ 0 ] ) ) ;
} else {
ChatPackets : : SendSystemMessage ( sysAddr , u " Correct usage: /ban <username> " ) ;
}
}
//-------------------------------------------------
2022-01-06 02:52:33 +00:00
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " buffme " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2023-03-04 07:16:37 +00:00
auto dest = static_cast < DestroyableComponent * > ( entity - > GetComponent ( eReplicaComponentType : : DESTROYABLE ) ) ;
2021-12-05 17:54:36 +00:00
if ( dest ) {
dest - > SetHealth ( 999 ) ;
dest - > SetMaxHealth ( 999.0f ) ;
dest - > SetArmor ( 999 ) ;
dest - > SetMaxArmor ( 999.0f ) ;
dest - > SetImagination ( 999 ) ;
dest - > SetMaxImagination ( 999.0f ) ;
}
EntityManager : : Instance ( ) - > SerializeEntity ( entity ) ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " startcelebration " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) = = 1 ) {
2021-12-05 17:54:36 +00:00
int32_t celebration ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , celebration ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid celebration. " ) ;
return ;
}
GameMessages : : SendStartCelebrationEffect ( entity , entity - > GetSystemAddress ( ) , celebration ) ;
}
2022-01-06 02:52:33 +00:00
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " buffmed " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2023-03-04 07:16:37 +00:00
auto dest = static_cast < DestroyableComponent * > ( entity - > GetComponent ( eReplicaComponentType : : DESTROYABLE ) ) ;
2021-12-05 17:54:36 +00:00
if ( dest ) {
dest - > SetHealth ( 9 ) ;
dest - > SetMaxHealth ( 9.0f ) ;
dest - > SetArmor ( 9 ) ;
dest - > SetMaxArmor ( 9.0f ) ;
dest - > SetImagination ( 9 ) ;
dest - > SetMaxImagination ( 9.0f ) ;
}
EntityManager : : Instance ( ) - > SerializeEntity ( entity ) ;
}
2022-01-06 02:52:33 +00:00
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " refillstats " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2022-04-12 19:06:03 +00:00
2023-03-04 07:16:37 +00:00
auto dest = static_cast < DestroyableComponent * > ( entity - > GetComponent ( eReplicaComponentType : : DESTROYABLE ) ) ;
2021-12-05 17:54:36 +00:00
if ( dest ) {
dest - > SetHealth ( ( int ) dest - > GetMaxHealth ( ) ) ;
dest - > SetArmor ( ( int ) dest - > GetMaxArmor ( ) ) ;
dest - > SetImagination ( ( int ) dest - > GetMaxImagination ( ) ) ;
}
EntityManager : : Instance ( ) - > SerializeEntity ( entity ) ;
}
2022-01-06 02:52:33 +00:00
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " lookup " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) > = 1 ) {
2022-01-13 03:48:27 +00:00
auto query = CDClientDatabase : : CreatePreppedStmt (
2022-01-15 19:02:14 +00:00
" SELECT `id`, `name` FROM `Objects` WHERE `displayName` LIKE ?1 OR `name` LIKE ?1 OR `description` LIKE ?1 LIMIT 50 " ) ;
2023-01-07 06:17:09 +00:00
// Concatenate all of the arguments into a single query so a multi word query can be used properly.
std : : string conditional = args [ 0 ] ;
args . erase ( args . begin ( ) ) ;
for ( auto & argument : args ) {
conditional + = ' ' + argument ;
}
2022-01-13 03:48:27 +00:00
2023-01-07 06:17:09 +00:00
const std : : string query_text = " % " + conditional + " % " ;
2022-01-15 19:02:14 +00:00
query . bind ( 1 , query_text . c_str ( ) ) ;
2022-01-13 03:48:27 +00:00
auto tables = query . execQuery ( ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
while ( ! tables . eof ( ) ) {
std : : string message = std : : to_string ( tables . getIntField ( 0 ) ) + " - " + tables . getStringField ( 1 ) ;
2022-08-02 13:56:20 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , GeneralUtils : : UTF8ToUTF16 ( message , message . size ( ) ) ) ;
2021-12-05 17:54:36 +00:00
tables . nextRow ( ) ;
}
}
2022-01-06 02:52:33 +00:00
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " spawn " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) > = 1 ) {
2023-03-04 07:16:37 +00:00
ControllablePhysicsComponent * comp = static_cast < ControllablePhysicsComponent * > ( entity - > GetComponent ( eReplicaComponentType : : CONTROLLABLE_PHYSICS ) ) ;
2021-12-05 17:54:36 +00:00
if ( ! comp ) return ;
uint32_t lot ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , lot ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid lot. " ) ;
return ;
}
2022-04-12 23:30:46 +00:00
EntityInfo info ;
info . lot = lot ;
info . pos = comp - > GetPosition ( ) ;
info . rot = comp - > GetRotation ( ) ;
2021-12-05 17:54:36 +00:00
info . spawner = nullptr ;
info . spawnerID = entity - > GetObjectID ( ) ;
info . spawnerNodeID = 0 ;
2022-04-12 23:30:46 +00:00
Entity * newEntity = EntityManager : : Instance ( ) - > CreateEntity ( info , nullptr ) ;
2021-12-05 17:54:36 +00:00
2022-04-12 23:30:46 +00:00
if ( newEntity = = nullptr ) {
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Failed to spawn entity. " ) ;
return ;
2022-04-12 23:30:46 +00:00
}
2021-12-05 17:54:36 +00:00
2022-09-02 18:49:19 +00:00
auto vehiclePhysicsComponent = newEntity - > GetComponent < VehiclePhysicsComponent > ( ) ;
if ( vehiclePhysicsComponent ) {
auto newRot = newEntity - > GetRotation ( ) ;
auto angles = newRot . GetEulerAngles ( ) ;
// make it right side up
angles . x - = PI ;
// make it going in the direction of the player
angles . y - = PI ;
newRot = NiQuaternion : : FromEulerAngles ( angles ) ;
newEntity - > SetRotation ( newRot ) ;
}
2022-04-12 23:30:46 +00:00
EntityManager : : Instance ( ) - > ConstructEntity ( newEntity ) ;
}
2021-12-05 17:54:36 +00:00
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " spawngroup " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) > = 3 ) {
2022-12-02 11:47:27 +00:00
auto controllablePhysicsComponent = entity - > GetComponent < ControllablePhysicsComponent > ( ) ;
if ( ! controllablePhysicsComponent ) return ;
LOT lot { } ;
uint32_t numberToSpawn { } ;
float radiusToSpawnWithin { } ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , lot ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid lot. " ) ;
return ;
}
if ( ! GeneralUtils : : TryParse ( args [ 1 ] , numberToSpawn ) & & numberToSpawn > 0 ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid number of enemies to spawn. " ) ;
return ;
}
// Must spawn within a radius of at least 0.0f
if ( ! GeneralUtils : : TryParse ( args [ 2 ] , radiusToSpawnWithin ) & & radiusToSpawnWithin < 0.0f ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid radius to spawn within. " ) ;
return ;
}
EntityInfo info ;
info . lot = lot ;
info . spawner = nullptr ;
info . spawnerID = entity - > GetObjectID ( ) ;
info . spawnerNodeID = 0 ;
auto playerPosition = controllablePhysicsComponent - > GetPosition ( ) ;
while ( numberToSpawn > 0 ) {
auto randomAngle = GeneralUtils : : GenerateRandomNumber < float > ( 0.0f , 2 * PI ) ;
auto randomRadius = GeneralUtils : : GenerateRandomNumber < float > ( 0.0f , radiusToSpawnWithin ) ;
// Set the position to the generated random position plus the player position. This will
// spawn the entity in a circle around the player. As you get further from the player, the angle chosen will get less accurate.
info . pos = playerPosition + NiPoint3 ( cos ( randomAngle ) * randomRadius , 0.0f , sin ( randomAngle ) * randomRadius ) ;
info . rot = NiQuaternion ( ) ;
auto newEntity = EntityManager : : Instance ( ) - > CreateEntity ( info ) ;
if ( newEntity = = nullptr ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Failed to spawn entity. " ) ;
return ;
}
EntityManager : : Instance ( ) - > ConstructEntity ( newEntity ) ;
numberToSpawn - - ;
}
}
2023-03-24 23:16:45 +00:00
if ( ( chatCommand = = " giveuscore " ) & & args . size ( ) > = 1 & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
int32_t uscore ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , uscore ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid uscore. " ) ;
return ;
}
CharacterComponent * character = entity - > GetComponent < CharacterComponent > ( ) ;
if ( character ) character - > SetUScore ( character - > GetUScore ( ) + uscore ) ;
2023-05-02 22:39:21 +00:00
// MODERATION should work but it doesn't. Relog to see uscore changes
2023-01-11 20:50:21 +00:00
2023-05-02 22:39:21 +00:00
eLootSourceType lootType = eLootSourceType : : MODERATION ;
2023-01-11 20:50:21 +00:00
int32_t type ;
2023-03-14 12:50:12 +00:00
if ( args . size ( ) > = 2 & & GeneralUtils : : TryParse ( args [ 1 ] , type ) ) {
lootType = ( eLootSourceType ) type ;
2023-01-11 20:50:21 +00:00
}
GameMessages : : SendModifyLEGOScore ( entity , entity - > GetSystemAddress ( ) , uscore , lootType ) ;
2021-12-05 17:54:36 +00:00
}
2023-03-24 23:16:45 +00:00
if ( ( chatCommand = = " setlevel " ) & & args . size ( ) > = 1 & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2022-06-13 07:45:17 +00:00
// We may be trying to set a specific players level to a level. If so override the entity with the requested players.
std : : string requestedPlayerToSetLevelOf = " " ;
if ( args . size ( ) > 1 ) {
requestedPlayerToSetLevelOf = args [ 1 ] ;
auto requestedPlayer = Player : : GetPlayer ( requestedPlayerToSetLevelOf ) ;
if ( ! requestedPlayer ) {
2022-08-02 13:56:20 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " No player found with username: ( " + GeneralUtils : : UTF8ToUTF16 ( requestedPlayerToSetLevelOf ) + u " ). " ) ;
2022-06-13 07:45:17 +00:00
return ;
}
if ( ! requestedPlayer - > GetOwner ( ) ) {
2022-08-02 13:56:20 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " No entity found with username: ( " + GeneralUtils : : UTF8ToUTF16 ( requestedPlayerToSetLevelOf ) + u " ). " ) ;
2022-06-13 07:45:17 +00:00
return ;
}
entity = requestedPlayer - > GetOwner ( ) ;
}
uint32_t requestedLevel ;
uint32_t oldLevel ;
// first check the level is valid
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , requestedLevel ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid level. " ) ;
return ;
}
// query to set our uscore to the correct value for this level
auto characterComponent = entity - > GetComponent < CharacterComponent > ( ) ;
2022-07-24 18:04:02 +00:00
if ( ! characterComponent ) return ;
auto levelComponent = entity - > GetComponent < LevelProgressionComponent > ( ) ;
2022-06-13 07:45:17 +00:00
auto query = CDClientDatabase : : CreatePreppedStmt ( " SELECT requiredUScore from LevelProgressionLookup WHERE id = ?; " ) ;
query . bind ( 1 , ( int ) requestedLevel ) ;
auto result = query . execQuery ( ) ;
if ( result . eof ( ) ) return ;
// Set the UScore first
2022-07-24 18:04:02 +00:00
oldLevel = levelComponent - > GetLevel ( ) ;
2022-06-13 07:45:17 +00:00
characterComponent - > SetUScore ( result . getIntField ( 0 , characterComponent - > GetUScore ( ) ) ) ;
// handle level up for each level we have passed if we set our level to be higher than the current one.
if ( oldLevel < requestedLevel ) {
while ( oldLevel < requestedLevel ) {
oldLevel + = 1 ;
2022-07-24 18:04:02 +00:00
levelComponent - > SetLevel ( oldLevel ) ;
levelComponent - > HandleLevelUp ( ) ;
2022-06-13 07:45:17 +00:00
}
} else {
2022-07-24 18:04:02 +00:00
levelComponent - > SetLevel ( requestedLevel ) ;
2022-06-13 07:45:17 +00:00
}
if ( requestedPlayerToSetLevelOf ! = " " ) {
ChatPackets : : SendSystemMessage (
2022-08-02 13:56:20 +00:00
sysAddr , u " Set " + GeneralUtils : : UTF8ToUTF16 ( requestedPlayerToSetLevelOf ) + u " 's level to " + GeneralUtils : : to_u16string ( requestedLevel ) +
2022-07-09 03:25:44 +00:00
u " and UScore to " + GeneralUtils : : to_u16string ( characterComponent - > GetUScore ( ) ) +
2022-06-13 07:45:17 +00:00
u " . Relog to see changes. " ) ;
} else {
ChatPackets : : SendSystemMessage (
2022-07-09 03:25:44 +00:00
sysAddr , u " Set your level to " + GeneralUtils : : to_u16string ( requestedLevel ) +
u " and UScore to " + GeneralUtils : : to_u16string ( characterComponent - > GetUScore ( ) ) +
2022-06-13 07:45:17 +00:00
u " . Relog to see changes. " ) ;
}
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " pos " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
const auto position = entity - > GetPosition ( ) ;
ChatPackets : : SendSystemMessage ( sysAddr , u " < " + ( GeneralUtils : : to_u16string ( position . x ) ) + u " , " + ( GeneralUtils : : to_u16string ( position . y ) ) + u " , " + ( GeneralUtils : : to_u16string ( position . z ) ) + u " > " ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
std : : cout < < position . x < < " , " < < position . y < < " , " < < position . z < < std : : endl ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " rot " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
const auto rotation = entity - > GetRotation ( ) ;
ChatPackets : : SendSystemMessage ( sysAddr , u " < " + ( GeneralUtils : : to_u16string ( rotation . w ) ) + u " , " + ( GeneralUtils : : to_u16string ( rotation . x ) ) + u " , " + ( GeneralUtils : : to_u16string ( rotation . y ) ) + u " , " + ( GeneralUtils : : to_u16string ( rotation . z ) ) + u " > " ) ;
std : : cout < < rotation . w < < " , " < < rotation . x < < " , " < < rotation . y < < " , " < < rotation . z < < std : : endl ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " locrow " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
const auto position = entity - > GetPosition ( ) ;
const auto rotation = entity - > GetRotation ( ) ;
std : : cout < < " <location x= \" " < < position . x < < " \" y= \" " < < position . y < < " \" z= \" " < < position . z < < " \" rw= \" " < < rotation . w < < " \" rx= \" " < < rotation . x < < " \" ry= \" " < < rotation . y < < " \" rz= \" " < < rotation . z < < " \" /> " < < std : : endl ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " playlvlfx " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
GameMessages : : SendPlayFXEffect ( entity , 7074 , u " create " , " 7074 " , LWOOBJID_EMPTY , 1.0f , 1.0f , true ) ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " playrebuildfx " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2022-04-12 23:30:46 +00:00
GameMessages : : SendPlayFXEffect ( entity , 230 , u " rebuild " , " 230 " , LWOOBJID_EMPTY , 1.0f , 1.0f , true ) ;
}
2021-12-05 17:54:36 +00:00
2023-03-24 23:16:45 +00:00
if ( ( chatCommand = = " freemoney " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) & & args . size ( ) = = 1 ) {
2021-12-05 17:54:36 +00:00
int32_t money ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , money ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid money. " ) ;
return ;
}
auto * ch = entity - > GetCharacter ( ) ;
2023-05-02 22:39:21 +00:00
ch - > SetCoins ( ch - > GetCoins ( ) + money , eLootSourceType : : MODERATION ) ;
2021-12-05 17:54:36 +00:00
}
2023-03-24 23:16:45 +00:00
if ( ( chatCommand = = " setcurrency " ) & & args . size ( ) = = 1 & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
int32_t money ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , money ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid money. " ) ;
return ;
}
auto * ch = entity - > GetCharacter ( ) ;
2023-05-02 22:39:21 +00:00
ch - > SetCoins ( money , eLootSourceType : : MODERATION ) ;
2021-12-05 17:54:36 +00:00
}
// Allow for this on even while not a GM, as it sometimes toggles incorrrectly.
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " gminvis " & & entity - > GetParentUser ( ) - > GetMaxGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
GameMessages : : SendToggleGMInvis ( entity - > GetObjectID ( ) , true , UNASSIGNED_SYSTEM_ADDRESS ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " gmimmune " & & args . size ( ) > = 1 & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
auto * destroyableComponent = entity - > GetComponent < DestroyableComponent > ( ) ;
int32_t state = false ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , state ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid state. " ) ;
return ;
}
if ( destroyableComponent ! = nullptr ) {
destroyableComponent - > SetIsGMImmune ( state ) ;
}
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " buff " & & args . size ( ) > = 2 & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
auto * buffComponent = entity - > GetComponent < BuffComponent > ( ) ;
int32_t id = 0 ;
int32_t duration = 0 ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , id ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid buff id. " ) ;
return ;
}
if ( ! GeneralUtils : : TryParse ( args [ 1 ] , duration ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid buff duration. " ) ;
return ;
}
if ( buffComponent ! = nullptr ) {
buffComponent - > ApplyBuff ( id , duration , entity - > GetObjectID ( ) ) ;
}
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
return ;
}
2023-03-24 23:16:45 +00:00
if ( ( chatCommand = = " testmap " & & args . size ( ) > = 1 ) & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : FORUM_MODERATOR ) {
2022-04-12 23:30:46 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Requesting map change... " ) ;
2021-12-05 17:54:36 +00:00
uint32_t reqZone ;
LWOCLONEID cloneId = 0 ;
bool force = false ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , reqZone ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid zone. " ) ;
return ;
}
if ( args . size ( ) > 1 ) {
auto index = 1 ;
if ( args [ index ] = = " force " ) {
index + + ;
force = true ;
}
if ( args . size ( ) > index & & ! GeneralUtils : : TryParse ( args [ index ] , cloneId ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid clone id. " ) ;
return ;
}
}
const auto objid = entity - > GetObjectID ( ) ;
2022-01-06 02:52:33 +00:00
2022-07-09 03:25:44 +00:00
if ( force | | CheckIfAccessibleZone ( reqZone ) ) { // to prevent tomfoolery
2022-01-06 02:52:33 +00:00
2022-07-09 03:25:44 +00:00
ZoneInstanceManager : : Instance ( ) - > RequestZoneTransfer ( Game : : server , reqZone , cloneId , false , [ objid ] ( bool mythranShift , uint32_t zoneID , uint32_t zoneInstance , uint32_t zoneClone , std : : string serverIP , uint16_t serverPort ) {
2021-12-05 17:54:36 +00:00
auto * entity = EntityManager : : Instance ( ) - > GetEntity ( objid ) ;
2022-07-09 03:25:44 +00:00
if ( ! entity ) return ;
2021-12-05 17:54:36 +00:00
2022-07-09 03:25:44 +00:00
const auto sysAddr = entity - > GetSystemAddress ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-09 03:25:44 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Transfering map... " ) ;
2021-12-05 17:54:36 +00:00
2022-07-25 02:26:51 +00:00
Game : : logger - > Log ( " UserManager " , " Transferring %s to Zone %i (Instance %i | Clone %i | Mythran Shift: %s) with IP %s and Port %i " , sysAddr . ToString ( ) , zoneID , zoneInstance , zoneClone , mythranShift = = true ? " true " : " false " , serverIP . c_str ( ) , serverPort ) ;
2022-07-09 03:25:44 +00:00
if ( entity - > GetCharacter ( ) ) {
entity - > GetCharacter ( ) - > SetZoneID ( zoneID ) ;
entity - > GetCharacter ( ) - > SetZoneInstance ( zoneInstance ) ;
entity - > GetCharacter ( ) - > SetZoneClone ( zoneClone ) ;
entity - > GetComponent < CharacterComponent > ( ) - > SetLastRocketConfig ( u " " ) ;
}
2021-12-05 17:54:36 +00:00
2022-07-09 03:25:44 +00:00
entity - > GetCharacter ( ) - > SaveXMLToDatabase ( ) ;
2021-12-05 17:54:36 +00:00
2022-07-09 03:25:44 +00:00
WorldPackets : : SendTransferToWorld ( sysAddr , serverIP , serverPort , mythranShift ) ;
return ;
} ) ;
} else {
std : : string msg = " ZoneID not found or allowed: " ;
2022-08-02 13:56:20 +00:00
msg . append ( args [ 0 ] ) ; // FIXME: unnecessary utf16 re-encoding just for error
ChatPackets : : SendSystemMessage ( sysAddr , GeneralUtils : : UTF8ToUTF16 ( msg , msg . size ( ) ) ) ;
2022-07-09 03:25:44 +00:00
}
}
2021-12-05 17:54:36 +00:00
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " createprivate " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) > = 3 ) {
2021-12-05 17:54:36 +00:00
uint32_t zone ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , zone ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid zone. " ) ;
return ;
}
uint32_t clone ;
if ( ! GeneralUtils : : TryParse ( args [ 1 ] , clone ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid clone. " ) ;
return ;
}
const auto & password = args [ 2 ] ;
ZoneInstanceManager : : Instance ( ) - > CreatePrivateZone ( Game : : server , zone , clone , password ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , GeneralUtils : : ASCIIToUTF16 ( " Sent request for private zone with password: " + password ) ) ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( ( chatCommand = = " debugui " ) & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Opening UIDebugger... " ) ;
AMFArrayValue args ;
2022-07-22 05:26:09 +00:00
GameMessages : : SendUIMessageServerToSingleClient ( entity , sysAddr , " ToggleUIDebugger; " , nullptr ) ;
2021-12-05 17:54:36 +00:00
}
2023-03-24 23:16:45 +00:00
if ( ( chatCommand = = " boost " ) & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
auto * possessorComponent = entity - > GetComponent < PossessorComponent > ( ) ;
if ( possessorComponent = = nullptr ) {
return ;
}
auto * vehicle = EntityManager : : Instance ( ) - > GetEntity ( possessorComponent - > GetPossessable ( ) ) ;
if ( vehicle = = nullptr ) {
return ;
}
2022-09-02 18:49:19 +00:00
if ( args . size ( ) > = 1 ) {
float time ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , time ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid boost time. " ) ;
return ;
} else {
GameMessages : : SendVehicleAddPassiveBoostAction ( vehicle - > GetObjectID ( ) , UNASSIGNED_SYSTEM_ADDRESS ) ;
entity - > AddCallbackTimer ( time , [ vehicle ] ( ) {
if ( ! vehicle ) return ;
GameMessages : : SendVehicleRemovePassiveBoostAction ( vehicle - > GetObjectID ( ) , UNASSIGNED_SYSTEM_ADDRESS ) ;
} ) ;
}
} else {
GameMessages : : SendVehicleAddPassiveBoostAction ( vehicle - > GetObjectID ( ) , UNASSIGNED_SYSTEM_ADDRESS ) ;
}
}
2023-03-24 23:16:45 +00:00
if ( ( chatCommand = = " unboost " ) & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2022-09-02 18:49:19 +00:00
auto * possessorComponent = entity - > GetComponent < PossessorComponent > ( ) ;
if ( possessorComponent = = nullptr ) return ;
auto * vehicle = EntityManager : : Instance ( ) - > GetEntity ( possessorComponent - > GetPossessable ( ) ) ;
if ( vehicle = = nullptr ) return ;
GameMessages : : SendVehicleRemovePassiveBoostAction ( vehicle - > GetObjectID ( ) , UNASSIGNED_SYSTEM_ADDRESS ) ;
2021-12-05 17:54:36 +00:00
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " activatespawner " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) > = 1 ) {
2021-12-05 17:54:36 +00:00
auto spawners = dZoneManager : : Instance ( ) - > GetSpawnersByName ( args [ 0 ] ) ;
for ( auto * spawner : spawners ) {
spawner - > Activate ( ) ;
}
spawners = dZoneManager : : Instance ( ) - > GetSpawnersInGroup ( args [ 0 ] ) ;
for ( auto * spawner : spawners ) {
spawner - > Activate ( ) ;
}
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " spawnphysicsverts " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : JUNIOR_DEVELOPER ) {
2021-12-05 17:54:36 +00:00
//Go tell physics to spawn all the vertices:
2023-03-04 07:16:37 +00:00
auto entities = EntityManager : : Instance ( ) - > GetEntitiesByComponent ( eReplicaComponentType : : PHANTOM_PHYSICS ) ;
2021-12-05 17:54:36 +00:00
for ( auto en : entities ) {
2023-03-04 07:16:37 +00:00
auto phys = static_cast < PhantomPhysicsComponent * > ( en - > GetComponent ( eReplicaComponentType : : PHANTOM_PHYSICS ) ) ;
2021-12-05 17:54:36 +00:00
if ( phys )
phys - > SpawnVertices ( ) ;
}
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " reportproxphys " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : JUNIOR_DEVELOPER ) {
2023-03-04 07:16:37 +00:00
auto entities = EntityManager : : Instance ( ) - > GetEntitiesByComponent ( eReplicaComponentType : : PROXIMITY_MONITOR ) ;
2021-12-05 17:54:36 +00:00
for ( auto en : entities ) {
2023-03-04 07:16:37 +00:00
auto phys = static_cast < ProximityMonitorComponent * > ( en - > GetComponent ( eReplicaComponentType : : PROXIMITY_MONITOR ) ) ;
2021-12-05 17:54:36 +00:00
if ( phys ) {
for ( auto prox : phys - > GetProximitiesData ( ) ) {
if ( ! prox . second ) continue ;
auto sphere = static_cast < dpShapeSphere * > ( prox . second - > GetShape ( ) ) ;
auto pos = prox . second - > GetPosition ( ) ;
std : : cout < < prox . first < < " , r: " < < sphere - > GetRadius ( ) < < " , pos: " < < pos . x < < " , " < < pos . y < < " , " < < pos . z < < std : : endl ;
}
}
}
}
2022-01-06 02:52:33 +00:00
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " triggerspawner " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) > = 1 ) {
2021-12-05 17:54:36 +00:00
auto spawners = dZoneManager : : Instance ( ) - > GetSpawnersByName ( args [ 0 ] ) ;
for ( auto * spawner : spawners ) {
spawner - > Spawn ( ) ;
}
spawners = dZoneManager : : Instance ( ) - > GetSpawnersInGroup ( args [ 0 ] ) ;
for ( auto * spawner : spawners ) {
spawner - > Spawn ( ) ;
}
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " reforge " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) > = 2 ) {
2021-12-05 17:54:36 +00:00
LOT baseItem ;
LOT reforgedItem ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , baseItem ) ) return ;
if ( ! GeneralUtils : : TryParse ( args [ 1 ] , reforgedItem ) ) return ;
auto * inventoryComponent = entity - > GetComponent < InventoryComponent > ( ) ;
if ( inventoryComponent = = nullptr ) return ;
std : : vector < LDFBaseData * > data { } ;
data . push_back ( new LDFData < int32_t > ( u " reforgedLOT " , reforgedItem ) ) ;
2023-05-02 22:39:21 +00:00
inventoryComponent - > AddItem ( baseItem , 1 , eLootSourceType : : MODERATION , eInventoryType : : INVALID , data ) ;
2021-12-05 17:54:36 +00:00
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " crash " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : OPERATOR ) {
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Crashing... " ) ;
int * badPtr = nullptr ;
* badPtr = 0 ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " metrics " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2021-12-05 17:54:36 +00:00
for ( const auto variable : Metrics : : GetAllMetrics ( ) ) {
auto * metric = Metrics : : GetMetric ( variable ) ;
if ( metric = = nullptr ) {
continue ;
}
ChatPackets : : SendSystemMessage (
sysAddr ,
2022-01-06 02:52:33 +00:00
GeneralUtils : : ASCIIToUTF16 ( Metrics : : MetricVariableToString ( variable ) ) +
u " : " +
GeneralUtils : : to_u16string ( Metrics : : ToMiliseconds ( metric - > average ) ) +
2021-12-05 17:54:36 +00:00
u " ms "
) ;
}
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage (
sysAddr ,
u " Peak RSS: " + GeneralUtils : : to_u16string ( ( float ) ( ( double ) Metrics : : GetPeakRSS ( ) / 1.024e6 ) ) +
u " MB "
) ;
ChatPackets : : SendSystemMessage (
sysAddr ,
u " Current RSS: " + GeneralUtils : : to_u16string ( ( float ) ( ( double ) Metrics : : GetCurrentRSS ( ) / 1.024e6 ) ) +
u " MB "
) ;
ChatPackets : : SendSystemMessage (
sysAddr ,
u " Process ID: " + GeneralUtils : : to_u16string ( Metrics : : GetProcessID ( ) )
) ;
return ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " reloadconfig " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER ) {
2022-12-04 22:25:58 +00:00
Game : : config - > ReloadConfig ( ) ;
VanityUtilities : : SpawnVanity ( ) ;
dpWorld : : Instance ( ) . Reload ( ) ;
2023-03-04 07:16:37 +00:00
auto entities = EntityManager : : Instance ( ) - > GetEntitiesByComponent ( eReplicaComponentType : : SCRIPTED_ACTIVITY ) ;
2022-12-04 22:25:58 +00:00
for ( auto entity : entities ) {
auto * scriptedActivityComponent = entity - > GetComponent < ScriptedActivityComponent > ( ) ;
if ( ! scriptedActivityComponent ) continue ;
scriptedActivityComponent - > ReloadConfig ( ) ;
}
2022-12-21 16:51:27 +00:00
Game : : server - > UpdateMaximumMtuSize ( ) ;
2022-12-06 00:08:47 +00:00
Game : : server - > UpdateBandwidthLimit ( ) ;
2022-12-04 22:25:58 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Successfully reloaded config for world! " ) ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " rollloot " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : OPERATOR & & args . size ( ) > = 3 ) {
2021-12-20 10:25:45 +00:00
uint32_t lootMatrixIndex = 0 ;
uint32_t targetLot = 0 ;
uint32_t loops = 1 ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , lootMatrixIndex ) ) return ;
if ( ! GeneralUtils : : TryParse ( args [ 1 ] , targetLot ) ) return ;
if ( ! GeneralUtils : : TryParse ( args [ 2 ] , loops ) ) return ;
uint64_t totalRuns = 0 ;
for ( uint32_t i = 0 ; i < loops ; i + + ) {
while ( true ) {
auto lootRoll = LootGenerator : : Instance ( ) . RollLootMatrix ( lootMatrixIndex ) ;
totalRuns + = 1 ;
bool doBreak = false ;
for ( const auto & kv : lootRoll ) {
if ( ( uint32_t ) kv . first = = targetLot ) {
doBreak = true ;
}
}
if ( doBreak ) break ;
}
}
std : : u16string message = u " Ran loot drops looking for "
2022-01-06 02:52:33 +00:00
+ GeneralUtils : : to_u16string ( targetLot )
+ u " , "
+ GeneralUtils : : to_u16string ( loops )
+ u " times. It ran "
+ GeneralUtils : : to_u16string ( totalRuns )
2021-12-20 10:25:45 +00:00
+ u " times. Averaging out at "
+ GeneralUtils : : to_u16string ( ( float ) totalRuns / loops ) ;
ChatPackets : : SendSystemMessage ( sysAddr , message ) ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " deleteinven " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) > = 1 ) {
2022-12-18 15:46:04 +00:00
eInventoryType inventoryType = eInventoryType : : INVALID ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , inventoryType ) ) {
// In this case, we treat the input as a string and try to find it in the reflection list
2023-03-14 12:50:12 +00:00
std : : transform ( args [ 0 ] . begin ( ) , args [ 0 ] . end ( ) , args [ 0 ] . begin ( ) , : : toupper ) ;
2022-12-18 15:46:04 +00:00
Game : : logger - > Log ( " SlashCommandHandler " , " looking for inventory %s " , args [ 0 ] . c_str ( ) ) ;
for ( uint32_t index = 0 ; index < NUMBER_OF_INVENTORIES ; index + + ) {
if ( std : : string_view ( args [ 0 ] ) = = std : : string_view ( InventoryType : : InventoryTypeToString ( static_cast < eInventoryType > ( index ) ) ) ) inventoryType = static_cast < eInventoryType > ( index ) ;
}
}
if ( inventoryType = = eInventoryType : : INVALID | | inventoryType > = NUMBER_OF_INVENTORIES ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Invalid inventory provided. " ) ;
return ;
}
auto * inventoryComponent = entity - > GetComponent < InventoryComponent > ( ) ;
if ( ! inventoryComponent ) return ;
auto * inventoryToDelete = inventoryComponent - > GetInventory ( inventoryType ) ;
if ( ! inventoryToDelete ) return ;
inventoryToDelete - > DeleteAllItems ( ) ;
Game : : logger - > Log ( " SlashCommandHandler " , " Deleted inventory %s for user %llu " , args [ 0 ] . c_str ( ) , entity - > GetObjectID ( ) ) ;
ChatPackets : : SendSystemMessage ( sysAddr , u " Deleted inventory " + GeneralUtils : : UTF8ToUTF16 ( args [ 0 ] ) ) ;
}
2023-03-24 23:16:45 +00:00
if ( chatCommand = = " inspect " & & entity - > GetGMLevel ( ) > = eGameMasterLevel : : DEVELOPER & & args . size ( ) > = 1 ) {
2021-12-05 17:54:36 +00:00
Entity * closest = nullptr ;
2023-03-04 07:16:37 +00:00
eReplicaComponentType component ;
2021-12-05 17:54:36 +00:00
std : : u16string ldf ;
bool isLDF = false ;
if ( ! GeneralUtils : : TryParse ( args [ 0 ] , component ) ) {
2023-03-04 07:16:37 +00:00
component = eReplicaComponentType : : INVALID ;
2021-12-05 17:54:36 +00:00
2022-08-02 13:56:20 +00:00
ldf = GeneralUtils : : UTF8ToUTF16 ( args [ 0 ] ) ;
2021-12-05 17:54:36 +00:00
isLDF = true ;
}
auto reference = entity - > GetPosition ( ) ;
auto closestDistance = 0.0f ;
const auto candidates = EntityManager : : Instance ( ) - > GetEntitiesByComponent ( component ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
for ( auto * candidate : candidates ) {
if ( candidate - > GetLOT ( ) = = 1 | | candidate - > GetLOT ( ) = = 8092 ) {
continue ;
}
if ( isLDF & & ! candidate - > HasVar ( ldf ) ) {
continue ;
}
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
if ( closest = = nullptr ) {
closest = candidate ;
closestDistance = NiPoint3 : : Distance ( candidate - > GetPosition ( ) , reference ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
continue ;
}
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
const auto distance = NiPoint3 : : Distance ( candidate - > GetPosition ( ) , reference ) ;
if ( distance < closestDistance ) {
closest = candidate ;
closestDistance = distance ;
}
}
if ( closest = = nullptr ) {
return ;
}
EntityManager : : Instance ( ) - > SerializeEntity ( closest ) ;
2023-03-17 14:36:21 +00:00
auto * table = CDClientManager : : Instance ( ) . GetTable < CDObjectsTable > ( ) ;
2021-12-05 17:54:36 +00:00
const auto & info = table - > GetByID ( closest - > GetLOT ( ) ) ;
std : : stringstream header ;
header < < info . name < < " [ " < < std : : to_string ( info . id ) < < " ] " < < " " < < std : : to_string ( closestDistance ) < < " " < < std : : to_string ( closest - > IsSleeping ( ) ) ;
ChatPackets : : SendSystemMessage ( sysAddr , GeneralUtils : : ASCIIToUTF16 ( header . str ( ) ) ) ;
2022-01-06 02:52:33 +00:00
2021-12-05 17:54:36 +00:00
for ( const auto & pair : closest - > GetComponents ( ) ) {
auto id = pair . first ;
std : : stringstream stream ;
2023-03-04 07:16:37 +00:00
stream < < " Component [ " < < std : : to_string ( static_cast < uint32_t > ( id ) ) < < " ] " ;
2021-12-05 17:54:36 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , GeneralUtils : : ASCIIToUTF16 ( stream . str ( ) ) ) ;
}
if ( args . size ( ) > = 2 ) {
if ( args [ 1 ] = = " -m " & & args . size ( ) > = 3 ) {
auto * movingPlatformComponent = closest - > GetComponent < MovingPlatformComponent > ( ) ;
int32_t value = 0 ;
if ( movingPlatformComponent = = nullptr | | ! GeneralUtils : : TryParse ( args [ 2 ] , value ) ) {
return ;
}
movingPlatformComponent - > SetSerialized ( true ) ;
if ( value = = - 1 ) {
movingPlatformComponent - > StopPathing ( ) ;
} else {
movingPlatformComponent - > GotoWaypoint ( value ) ;
}
EntityManager : : Instance ( ) - > SerializeEntity ( closest ) ;
} else if ( args [ 1 ] = = " -a " & & args . size ( ) > = 3 ) {
2022-08-02 13:56:20 +00:00
GameMessages : : SendPlayAnimation ( closest , GeneralUtils : : UTF8ToUTF16 ( args [ 2 ] ) ) ;
2021-12-05 17:54:36 +00:00
} else if ( args [ 1 ] = = " -s " ) {
for ( auto * entry : closest - > GetSettings ( ) ) {
2022-08-02 13:56:20 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , GeneralUtils : : UTF8ToUTF16 ( entry - > GetString ( ) ) ) ;
2021-12-05 17:54:36 +00:00
}
ChatPackets : : SendSystemMessage ( sysAddr , u " ------ " ) ;
ChatPackets : : SendSystemMessage ( sysAddr , u " Spawner ID: " + GeneralUtils : : to_u16string ( closest - > GetSpawnerID ( ) ) ) ;
} else if ( args [ 1 ] = = " -p " ) {
const auto postion = closest - > GetPosition ( ) ;
ChatPackets : : SendSystemMessage (
2022-01-06 02:52:33 +00:00
sysAddr ,
2021-12-05 17:54:36 +00:00
GeneralUtils : : ASCIIToUTF16 ( " < " + std : : to_string ( postion . x ) + " , " + std : : to_string ( postion . y ) + " , " + std : : to_string ( postion . z ) + " > " )
) ;
} else if ( args [ 1 ] = = " -f " ) {
auto * destuctable = closest - > GetComponent < DestroyableComponent > ( ) ;
if ( destuctable = = nullptr ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " No destroyable component on this entity! " ) ;
return ;
}
ChatPackets : : SendSystemMessage ( sysAddr , u " Smashable: " + ( GeneralUtils : : to_u16string ( destuctable - > GetIsSmashable ( ) ) ) ) ;
ChatPackets : : SendSystemMessage ( sysAddr , u " Friendly factions: " ) ;
for ( const auto entry : destuctable - > GetFactionIDs ( ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , ( GeneralUtils : : to_u16string ( entry ) ) ) ;
}
ChatPackets : : SendSystemMessage ( sysAddr , u " Enemy factions: " ) ;
for ( const auto entry : destuctable - > GetEnemyFactionsIDs ( ) ) {
ChatPackets : : SendSystemMessage ( sysAddr , ( GeneralUtils : : to_u16string ( entry ) ) ) ;
}
if ( args . size ( ) > = 3 ) {
int32_t faction ;
if ( ! GeneralUtils : : TryParse ( args [ 2 ] , faction ) ) {
return ;
}
destuctable - > SetFaction ( - 1 ) ;
destuctable - > AddFaction ( faction , true ) ;
}
} else if ( args [ 1 ] = = " -t " ) {
auto * phantomPhysicsComponent = closest - > GetComponent < PhantomPhysicsComponent > ( ) ;
if ( phantomPhysicsComponent ! = nullptr ) {
2023-03-25 10:26:39 +00:00
ChatPackets : : SendSystemMessage ( sysAddr , u " Type: " + ( GeneralUtils : : to_u16string ( static_cast < uint32_t > ( phantomPhysicsComponent - > GetEffectType ( ) ) ) ) ) ;
2021-12-05 17:54:36 +00:00
const auto dir = phantomPhysicsComponent - > GetDirection ( ) ;
ChatPackets : : SendSystemMessage ( sysAddr , u " Direction: < " + ( GeneralUtils : : to_u16string ( dir . x ) ) + u " , " + ( GeneralUtils : : to_u16string ( dir . y ) ) + u " , " + ( GeneralUtils : : to_u16string ( dir . z ) ) + u " > " ) ;
ChatPackets : : SendSystemMessage ( sysAddr , u " Multiplier: " + ( GeneralUtils : : to_u16string ( phantomPhysicsComponent - > GetDirectionalMultiplier ( ) ) ) ) ;
ChatPackets : : SendSystemMessage ( sysAddr , u " Active: " + ( GeneralUtils : : to_u16string ( phantomPhysicsComponent - > GetPhysicsEffectActive ( ) ) ) ) ;
}
2023-02-10 08:29:53 +00:00
auto * triggerComponent = closest - > GetComponent < TriggerComponent > ( ) ;
2023-03-14 12:50:12 +00:00
if ( triggerComponent ) {
2023-02-10 08:29:53 +00:00
auto trigger = triggerComponent - > GetTrigger ( ) ;
if ( trigger ) {
ChatPackets : : SendSystemMessage ( sysAddr , u " Trigger: " + ( GeneralUtils : : to_u16string ( trigger - > id ) ) ) ;
}
2021-12-05 17:54:36 +00:00
}
}
}
}
}
bool SlashCommandHandler : : CheckIfAccessibleZone ( const unsigned int zoneID ) {
2022-04-12 23:05:22 +00:00
//We're gonna go ahead and presume we've got the db loaded already:
2023-03-17 14:36:21 +00:00
CDZoneTableTable * zoneTable = CDClientManager : : Instance ( ) . GetTable < CDZoneTableTable > ( ) ;
2022-04-12 19:06:03 +00:00
const CDZoneTable * zone = zoneTable - > Query ( zoneID ) ;
if ( zone ! = nullptr ) {
2022-11-01 18:21:26 +00:00
return Game : : assetManager - > HasFile ( ( " maps/ " + zone - > zoneName ) . c_str ( ) ) ;
2022-04-12 19:06:03 +00:00
} else {
return false ;
2022-01-18 19:48:56 +00:00
}
2021-12-05 17:54:36 +00:00
}
void SlashCommandHandler : : SendAnnouncement ( const std : : string & title , const std : : string & message ) {
AMFArrayValue args ;
auto * titleValue = new AMFStringValue ( ) ;
titleValue - > SetStringValue ( title ) ;
auto * messageValue = new AMFStringValue ( ) ;
messageValue - > SetStringValue ( message ) ;
args . InsertValue ( " title " , titleValue ) ;
args . InsertValue ( " message " , messageValue ) ;
GameMessages : : SendUIMessageServerToAllClients ( " ToggleAnnounce " , & args ) ;
2022-01-06 02:52:33 +00:00
//Notify chat about it
2021-12-05 17:54:36 +00:00
CBITSTREAM ;
2023-05-03 21:38:32 +00:00
PacketUtils : : WriteHeader ( bitStream , eConnectionType : : CHAT_INTERNAL , eChatInternalMessageType : : ANNOUNCEMENT ) ;
2021-12-05 17:54:36 +00:00
2022-07-17 03:40:46 +00:00
bitStream . Write < uint32_t > ( title . size ( ) ) ;
for ( auto character : title ) {
bitStream . Write < char > ( character ) ;
}
2021-12-05 17:54:36 +00:00
2022-07-17 03:40:46 +00:00
bitStream . Write < uint32_t > ( message . size ( ) ) ;
for ( auto character : message ) {
bitStream . Write < char > ( character ) ;
}
2021-12-05 17:54:36 +00:00
Game : : chatServer - > Send ( & bitStream , SYSTEM_PRIORITY , RELIABLE , 0 , Game : : chatSysAddr , false ) ;
}