diff --git a/game/server/CMakeLists.txt b/game/server/CMakeLists.txt index 23452272..5440fbac 100644 --- a/game/server/CMakeLists.txt +++ b/game/server/CMakeLists.txt @@ -1,3 +1,3 @@ -#add_subdirectory(application) +add_subdirectory(application) add_subdirectory(library) diff --git a/game/server/application/CMakeLists.txt b/game/server/application/CMakeLists.txt new file mode 100644 index 00000000..014c8492 --- /dev/null +++ b/game/server/application/CMakeLists.txt @@ -0,0 +1,2 @@ + +add_subdirectory(SwgGameServer) diff --git a/game/server/application/SwgGameServer/CMakeLists.txt b/game/server/application/SwgGameServer/CMakeLists.txt new file mode 100644 index 00000000..f3a4416f --- /dev/null +++ b/game/server/application/SwgGameServer/CMakeLists.txt @@ -0,0 +1,12 @@ + +cmake_minimum_required(VERSION 2.8) + +project(SwgGameServer) + +if(WIN32) + add_definitions(/D_CRT_SECURE_NO_WARNINGS) +endif() + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/public) + +add_subdirectory(src) diff --git a/game/server/application/SwgGameServer/codegen/README b/game/server/application/SwgGameServer/codegen/README new file mode 100644 index 00000000..89c0f796 --- /dev/null +++ b/game/server/application/SwgGameServer/codegen/README @@ -0,0 +1,32 @@ +Using maketable.pl + +This PERL script can generate some of the more boring sections of the database code. To run it, +feed in the header files for the object declarations like so: + +./maketable.pl ../src/shared/object/*.h + +It outputs several files. The text of these files should be pasted into sections of the server +code. These sections are set off with comments like this: + +//----------------------------------------------------------------------------- +// From savepackage.auto +// BEGIN AUTO_GENERATED CODE ############################# + + .... + +// END AUTO_GENERATED CODE ############################# + +The utility putauto.pl will paste in any autogenerated files. Run it like this: + +./putauto.pl + +The script putall will run putauto.pl on all the necessary files, except for create.ddl + +These are the output files: +sql.auto (sql for creating tables, goes into create.ddl) +Schema.h.auto (goes into Schema.h) +ObjectQueries.cpp.auto (etc.) +ObjectQueries.h.auto +MakeDBPackage.cpp.auto +DatabasePackage.h.auto +DatabasePackage.cpp.auto diff --git a/game/server/application/SwgGameServer/codegen/bindmap.def b/game/server/application/SwgGameServer/codegen/bindmap.def new file mode 100644 index 00000000..28fc2211 --- /dev/null +++ b/game/server/application/SwgGameServer/codegen/bindmap.def @@ -0,0 +1,3 @@ +integer BindableLong +float BindableDouble +char(1) BindableBool diff --git a/game/server/application/SwgGameServer/codegen/maketable.pl b/game/server/application/SwgGameServer/codegen/maketable.pl new file mode 100644 index 00000000..a4021b14 --- /dev/null +++ b/game/server/application/SwgGameServer/codegen/maketable.pl @@ -0,0 +1,372 @@ +#!/usr/bin/perl + +# This auto-gens some of the more boring code for dealing with +# database objects. The generated code needs to be cut-and +# pasted into the appropriate files. The idea is to save +# typing and reduce errors, not to fully automate the system. + +open (TYPEMAP,"typemap.def"); +while ($_=) +{ + chop; + ($c,$db,$cast) = split /\t/; + $typemap{$c}=$db; + if ($cast ne "") + { + $cast{$c}=1; + } +} +close (TYPEMAP); + +open (BINDMAP,"bindmap.def"); +while ($_=) +{ + chop; + ($db,$bindable) = split /\t/; + $bindablemap{$db}=$bindable; +} +close (BINDMAP); + +while (<>) +{ + if(/\/\/.*BPM/) + { + &parseBPM(); + } +} + +open (SQL,">sql.auto"); +open (SCHEMA,">Schema.h.auto"); +open (QUERY,">ObjectQueries.cpp.auto"); +open (QUERYH,">ObjectQueries.h.auto"); +open (MAKEPACKAGE,">MakeDBPackage.cpp.auto"); +open (PACKAGEH,">DatabasePackage.h.auto"); +open (SAVEPACKAGE,">DatabasePackage.cpp.auto"); + +# Print out the tables +foreach $tablename (sort keys %columns) +{ + # build a list of columns, including those from inherited classes + $col=""; + for ($dep=$depend{$tablename}; $dep ne ""; $dep=$depend{$dep}) + { + $col=$col.$columns{$dep}; + } + + $col=$col.$columns{$tablename}; + + ######################################################## + # print out the table creation script + ######################################################## + + print SQL "create table ".&dbIzeName($tablename)."s\n(\n"; + @tabledef = (); + push (@tabledef, "\tobject_id integer"); + foreach $colrec (split /\|/,$col) + { + ($name,$type) = split / /,$colrec; + if ($typemap{$type} eq "") + { +# push (@tabledef, "--\t".$name." ".$type) + } + else + { + push (@tabledef, "\t".&dbIzeName($name)." ".$typemap{$type}); + } + } + + print SQL join (",\n",@tabledef); + print SQL "\n);\n\n"; + + ######################################################## + # print out the row object + ######################################################## + + print SCHEMA "struct ".$tablename."Row : public DB::Row\n{\n"; + print SCHEMA "\tDB::BindableLong object_id;\n"; + foreach $colrec (split /\|/,$col) + { + ($name,$type) = split / /,$colrec; + if ($typemap{$type} ne "") + { + print SCHEMA "\tDB::".$bindablemap{$typemap{$type}}." ".&dbIzeName($name).";\n"; + } + } + print SCHEMA "};\n\n"; + + ######################################################## + #print out the query class declaration + ######################################################## + + print QUERYH "class ".$tablename."Query : public DB::ModeQuery\n{\n"; + print QUERYH "\t".$tablename."Query(const ".$tablename."Query&); // disable\n"; + print QUERYH "\t".$tablename."Query& operator=(const ".$tablename."Query&); // disable\n"; + print QUERYH "public:\n"; + print QUERYH "\t".$tablename."Query() {}\n\n"; + print QUERYH "\tbool bind();\n"; + print QUERYH "\tchar *getSQL();\n"; + print QUERYH "};\n\n"; + + ######################################################## + #print out the bind function + ######################################################## + + $count=1; + $bind="bool ".$tablename."Query::bind()\n{\n"; + $bind=$bind."\t".$tablename."Row *myData=dynamic_cast<".$tablename."Row*>(data);\n"; + $bind=$bind."\tswitch (mode)\n\t{\n"; + + $bindObjId="\t\t\tif (!myData->object_id.bindParameter(1,this)) return false;\n"; + + $updSection="\t\tcase mode_UPDATE:\n\t\tcase mode_INSERT:\n"; + $selSection="\t\tcase mode_SELECT:\n".$bindObjId."\n"; + foreach $colrec (split /\|/,$col) + { + ($name,$type) = split / /,$colrec; + if ($typemap{$type} ne "") + { + $updSection=$updSection."\t\t\tif (!myData->".&dbIzeName($name).".bindParameter(".$count.",this)) return false;\n"; + $selSection=$selSection."\t\t\tif (!myData->".&dbIzeName($name).".bindCol(".$count.",this)) return false;\n"; + $count++; + } + } + $updSection=$updSection."\n\t\t\tif (!myData->object_id.bindParameter($count,this)) return false;\n"; + + + $bind=$bind.$updSection."\t\t\tbreak;\n\n".$selSection."\t\t\tbreak;\n\n"; + $bind=$bind."\t\tcase mode_DELETE:\n".$bindObjId."\t\t\tbreak;\n\n"; + $bind=$bind."\t\tdefault:\n\t\t\tDEBUG_FATAL(true,(\"Bad query mode.\"));\n"; + $bind=$bind."\t}\n\treturn true;\n}\n\n"; + print QUERY $bind; #fix object_id -- should be last for update,insert + + + ######################################################## + # Print out the SQL + ######################################################## + + @columnNames=(); + foreach $colrec (split /\|/,$col) + { + ($name,$type) = split / /,$colrec; + if ($typemap{$type} ne "") + { + push @columnNames,&dbIzeName($name); + } + } + + print QUERY "char *".$tablename."Query::getSQL()\n{\n\tswitch(mode)\n\t{\n"; + print QUERY "\t\tcase mode_UPDATE:\n"; + print QUERY "\t\t\treturn (\"update ".&dbIzeName($tablename)."s set "; + print QUERY join("=?, ",@columnNames)."=? where object_id=?\");\n"; + + print QUERY "\t\tcase mode_INSERT:\n"; + print QUERY "\t\t\treturn (\"insert into ".&dbIzeName($tablename)."s ("; + print QUERY join(", ",@columnNames).", object_id) values ("; + foreach $temp (@columnNames) { print QUERY "?, ";} + print QUERY "?)\");\n"; + + print QUERY "\t\tcase mode_DELETE:\n"; + print QUERY "\t\t\treturn (\"delete from ".&dbIzeName($tablename)."s where object_id=?\");\n"; + + print QUERY "\t\tcase mode_SELECT:\n"; + print QUERY "\t\t\treturn (\"select "; + print QUERY join(", ",@columnNames); + print QUERY " from ".&dbIzeName($tablename)."s where object_id=?\");\n"; + + print QUERY "\t\tdefault:\n"; + print QUERY "\t\t\tDEBUG_FATAL(true,(\"Bad query mode.\"));\n"; + + print QUERY "\t}\n\treturn 0; // this is unreachable but here to avoid compiler warning\n}\n\n"; + + ######################################################## + # Print out the Package declaration + ######################################################## + + print PACKAGEH "class ".$tablename."Package : public ServerObjectPackage\n{\n"; + print PACKAGEH "public:\n"; + print PACKAGEH "\t".$tablename."Package() {}\n\n"; + + print PACKAGEH "\tvirtual void finishLoad(Snapshot *snap, DB::Session *ses);\n"; + print PACKAGEH "\tvirtual void save(Snapshot *snap, DB::Session *ses);\n"; + + print PACKAGEH "private:\n"; + print PACKAGEH "\t".$tablename."Package(const ".$tablename."Package&); //disable\n"; + print PACKAGEH "\t".$tablename."Package& operator=(const ".$tablename."Package&); // disable\n\n"; + print PACKAGEH "\tDBSchema::".$tablename."Row data;\n\n"; + + print PACKAGEH "\tfriend class ::".$tablename.";\n};\n\n"; + + ######################################################## + # Print out the CreatePacakge functions + ######################################################## + + print MAKEPACKAGE "DBPackage::ServerObjectPackage* ".$tablename."::MakeDBPackage(void) const\n{\n"; + print MAKEPACKAGE "\tDBPackage::".$tablename."Package *buffer=new DBPackage::".$tablename."Package;\n"; + print MAKEPACKAGE "\tbuffer->status=databaseStatus;\n"; + print MAKEPACKAGE "\tMakeDBPackage(buffer);\n"; + print MAKEPACKAGE "\treturn buffer;\n}\n\n"; + + print MAKEPACKAGE "void ".$tablename."::MakeDBPackage(DBPackage::ServerObjectPackage *buffer) const\n{\n"; + print MAKEPACKAGE "\tDBPackage::".$tablename."Package *myBuffer=dynamic_cast(buffer);\n"; + print MAKEPACKAGE "\tNOT_NULL(myBuffer);\n\n"; + print MAKEPACKAGE "\tmyBuffer->data.object_id=getNetworkId();\n"; + foreach $colrec (split /\|/,$col) + { + ($name,$type) = split / /,$colrec; + if ($typemap{$type} ne "") + { + print MAKEPACKAGE "\tmyBuffer->data.".&dbIzeName($name)."=".&getterName($name)."();\n"; + } + } + print MAKEPACKAGE "\n\tNetworkObject::MakeDBPackage(buffer);\n}\n\n"; + + ######################################################## + # Print out the LoadFromPackage functions + ######################################################## + + #constructor -- going away +# if ($depend{$tablename} eq "") +# { +# print MAKEPACKAGE $tablename."::".$tablename."(DBPackage::ServerObjectPackage *buffer) : NetworkObject(buffer)\n"; +# } +# else +# { +# print MAKEPACKAGE $tablename."::".$tablename."(DBPackage::ServerObjectPackage *buffer) : ".$depend{$tablename}."(buffer)\n"; +# } + +# print MAKEPACKAGE "{\n"; +# print MAKEPACKAGE "\tDBPackage::".$tablename."Package *myPackage=dynamic_cast(buffer);\n"; +# print MAKEPACKAGE "\tDEBUG_FATAL(myPackage==0,(\"Attempt to create a ".$tablename." from something that isn't a ".$tablename."Package\"));\n\n"; + +# foreach $colrec (split /\|/,$col) +# { +# ($name,$type) = split / /,$colrec; +# if ($typemap{$type} ne "") +# { +# if ($cast{$type} ne "") +# { +# print MAKEPACKAGE "\t".&setterName($name)."(static_cast<".$type.">(myPackage->data.".&dbIzeName($name).".getValue()));\n"; +# } +# else +# { +# print MAKEPACKAGE "\t".&setterName($name)."(myPackage->data.".&dbIzeName($name).".getValue());\n"; +# } +# } +# } +# print MAKEPACKAGE "}\n\n"; + + #loadFromDBPackage -- keep + print MAKEPACKAGE "void ".$tablename."::loadFromDBPackage(DBPackage::ServerObjectPackage *buffer)\n"; + print MAKEPACKAGE "{\n"; + print MAKEPACKAGE "\tDBPackage::".$tablename."Package *myPackage=dynamic_cast(buffer);\n"; + print MAKEPACKAGE "\tDEBUG_FATAL(myPackage==0,(\"Attempt to create object %i, a ".$tablename." from something that isn't a ".$tablename."Package. May indicate that the object's type_id doesn't match its template.\",buffer->getObjectId()));\n\n"; + print MAKEPACKAGE "\tNetworkObject::loadFromDBPackage(buffer);\n\n"; + foreach $colrec (split /\|/,$col) + { + ($name,$type) = split / /,$colrec; + if ($typemap{$type} ne "") + { + if ($cast{$type} ne "") + { + print MAKEPACKAGE "\t".&setterName($name)."(static_cast<".$type.">(myPackage->data.".&dbIzeName($name).".getValue()));\n"; + } + else + { + print MAKEPACKAGE "\t".&setterName($name)."(myPackage->data.".&dbIzeName($name).".getValue());\n"; + } + } + } + print MAKEPACKAGE "}\n\n"; + + ######################################################## + # Print out the save & load package functions + ######################################################## + + print SAVEPACKAGE "void DBPackage::".$tablename."Package::finishLoad(Snapshot *snap, DB::Session *ses)\n"; + print SAVEPACKAGE "{\n"; + print SAVEPACKAGE "\tUNREF(ses);\n"; + print SAVEPACKAGE "\tUNREF(snap);\n\n"; + + print SAVEPACKAGE "\tDBQuery::".$tablename."Query q;\n"; + print SAVEPACKAGE "\tq.selectMode();\n"; + print SAVEPACKAGE "\tdata.object_id=baseData.object_id;\n"; + print SAVEPACKAGE "\tq.setData(&data);\n\n"; + + print SAVEPACKAGE "\tses->exec(&q);\n"; + print SAVEPACKAGE "\tif (!q.fetch())\n"; + print SAVEPACKAGE "\t{\n"; + print SAVEPACKAGE "\t\tFATAL (true,(\"Unable to retrive additional data needed by object %i\",baseData.object_id.getValue()));\n"; + print SAVEPACKAGE "\t}\n\n"; + + print SAVEPACKAGE "\tq.done();\n"; + print SAVEPACKAGE "}\n\n"; + + print SAVEPACKAGE "void DBPackage::".$tablename."Package::save(Snapshot *snap, DB::Session *ses)\n"; + print SAVEPACKAGE "{\n"; + print SAVEPACKAGE "\tDBQuery::".$tablename."Query q;\n\n"; + + print SAVEPACKAGE "\tswitch(status)\n"; + print SAVEPACKAGE "\t{\n"; + print SAVEPACKAGE "\t\tcase ::NetworkObject::NEW_OBJECT:\n"; + print SAVEPACKAGE "\t\t\tq.insertMode();\n"; + print SAVEPACKAGE "\t\t\tbreak;\n\n"; + + print SAVEPACKAGE "\t\tcase ::NetworkObject::CHANGED:\n"; + print SAVEPACKAGE "\t\t\tq.updateMode();\n"; + print SAVEPACKAGE "\t\t\tbreak;\n\n"; + + print SAVEPACKAGE "\t\tdefault:\n"; + print SAVEPACKAGE "\t\t\tFATAL(true,(\"Unsupported database status.\"));\n"; + print SAVEPACKAGE "\t}\n\n"; + + print SAVEPACKAGE "\tq.setData(&data);\n"; + print SAVEPACKAGE "\tses->exec(&q);\n"; + print SAVEPACKAGE "\tq.done();\n"; + + print SAVEPACKAGE "\tServerObjectPackage::save(snap,ses);\n"; + print SAVEPACKAGE "}\n\n"; + +} + + +sub parseBPM +{ + $_ =~ /BPM\s*(\w*)/; + $tablename=$1; + if ($_ =~ /BPM\s*\w+\s*\:\s*(\w+)/) + { + $depend{$tablename} = $1; + } + $_=<>; + while (!($_ =~ /\/\/.*EPM/)) + { + if ($_ =~ /([^\s]+)\s+([^\s]+)\;/) + { + ($type,$name)=($1,$2); + $columns{$tablename}=$columns{$tablename}.$name." ".$type."|"; + } + $_=<>; + } +} + +sub dbIzeName +{ + my($name)=@_; + $name =~ s/([a-z])([A-Z])/$1_$2/g; + $name =~ tr/[A-Z]/[a-z]/; + return $name; +} + +sub getterName +{ + my($name)=@_; + $name = "get".ucfirst ($name); + return $name; +} + +sub setterName +{ + my($name)=@_; + $name = "set".ucfirst ($name); + return $name; +} diff --git a/game/server/application/SwgGameServer/codegen/putall b/game/server/application/SwgGameServer/codegen/putall new file mode 100644 index 00000000..9363f9cb --- /dev/null +++ b/game/server/application/SwgGameServer/codegen/putall @@ -0,0 +1,9 @@ +#!/bin/bash + +./maketable.pl ../src/shared/object/*.h + +p4 open ../src/shared/database/Schema.h ../src/shared/database/ObjectQueries.cpp ../src/shared/database/ObjectQueries.h ../src/shared/database/MakeDBPackage.cpp ../src/shared/database/DatabasePackage.h ../src/shared/database/DatabasePackage.cpp ../../database/schema/create.ddl + +./putauto.pl ../src/shared/database/Schema.h ../src/shared/database/ObjectQueries.cpp ../src/shared/database/ObjectQueries.h ../src/shared/database/MakeDBPackage.cpp ../src/shared/database/DatabasePackage.h ../src/shared/database/DatabasePackage.cpp ../../database/schema/create.ddl + +p4 revert -a ../src/shared/database/Schema.h ../src/shared/database/ObjectQueries.cpp ../src/shared/database/ObjectQueries.h ../src/shared/database/MakeDBPackage.cpp ../src/shared/database/DatabasePackage.h ../src/shared/database/DatabasePackage.cpp ../../database/schema/create.ddl diff --git a/game/server/application/SwgGameServer/codegen/putauto.pl b/game/server/application/SwgGameServer/codegen/putauto.pl new file mode 100644 index 00000000..bde1f12d --- /dev/null +++ b/game/server/application/SwgGameServer/codegen/putauto.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl + +@files=@ARGV; + +foreach $file (@files) +{ + print "Working on $file\n"; + + open (INFILE,$file); + open (OUTFILE,">".$file.".tmp"); + while () + { + print OUTFILE $_; + if ((/\/\/\s*From\s+([^\s]+)/) || + (/--\s*From\s+([^\s]+)/)) + { + $from=$1; + } + if ((/\/\/ BEGIN AUTO_GENERATED CODE\s*\#/) || + (/-- BEGIN AUTO_GENERATED CODE/)) + { + &insertFile($from); + while (!(/\/\/ END AUTO_GENERATED CODE\s*\#/) && + !(/-- END AUTO_GENERATED CODE/)) + { + $_=; + } + print OUTFILE $_; + } + } + close (OUTFILE); + close(INFILE); + + $rc=system("diff --brief $file.tmp $file"); + if ($rc!=0) + { + system ("cp $file.tmp $file"); + } + system("rm $file.tmp"); +} + +sub insertFile +{ + print OUTFILE "\n"; + + my($filename)=@_; + open (INSFILE,$filename); + while () + { + print OUTFILE $_; + } + close INSFILE; +} + diff --git a/game/server/application/SwgGameServer/codegen/typemap.def b/game/server/application/SwgGameServer/codegen/typemap.def new file mode 100644 index 00000000..9f11c299 --- /dev/null +++ b/game/server/application/SwgGameServer/codegen/typemap.def @@ -0,0 +1,8 @@ +int integer +bool char(1) +NetworkId integer +Gender integer cast +ArmorEffectiveness integer +real float cast +StringId integer +InstallationType integer cast diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/CSHandler.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/CSHandler.h new file mode 100644 index 00000000..6bf81604 --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/CSHandler.h @@ -0,0 +1 @@ +#include "../../src/shared/core/CSHandler.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/CombatEngine.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/CombatEngine.h new file mode 100644 index 00000000..5b002800 --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/CombatEngine.h @@ -0,0 +1 @@ +#include "../../src/shared/combat/CombatEngine.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/ConfigCombatEngine.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/ConfigCombatEngine.h new file mode 100644 index 00000000..76a8e8d6 --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/ConfigCombatEngine.h @@ -0,0 +1 @@ +#include "../../src/shared/combat/ConfigCombatEngine.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/ConsoleCommandParserCombatEngine.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/ConsoleCommandParserCombatEngine.h new file mode 100644 index 00000000..c960efd4 --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/ConsoleCommandParserCombatEngine.h @@ -0,0 +1 @@ +#include "../../src/shared/console/ConsoleCommandParserCombatEngine.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/ConsoleCommandParserCombatEngineQueue.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/ConsoleCommandParserCombatEngineQueue.h new file mode 100644 index 00000000..3a9f078b --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/ConsoleCommandParserCombatEngineQueue.h @@ -0,0 +1 @@ +#include "../../src/shared/console/ConsoleCommandParserCombatEngineQueue.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/FirstSwgGameServer.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/FirstSwgGameServer.h new file mode 100644 index 00000000..a74eb34f --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/FirstSwgGameServer.h @@ -0,0 +1 @@ +#include "../../src/shared/core/FirstSwgGameServer.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/JediManagerController.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/JediManagerController.h new file mode 100644 index 00000000..484732f7 --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/JediManagerController.h @@ -0,0 +1 @@ +#include "../../src/shared/controller/JediManagerController.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/JediManagerObject.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/JediManagerObject.h new file mode 100644 index 00000000..6df75c47 --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/JediManagerObject.h @@ -0,0 +1 @@ +#include "../../src/shared/object/JediManagerObject.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/ServerJediManagerObjectTemplate.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/ServerJediManagerObjectTemplate.h new file mode 100644 index 00000000..11a37d7d --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/ServerJediManagerObjectTemplate.h @@ -0,0 +1 @@ +#include "../../src/shared/objectTemplate/ServerJediManagerObjectTemplate.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgCreatureObject.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgCreatureObject.h new file mode 100644 index 00000000..01ffb8e3 --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgCreatureObject.h @@ -0,0 +1 @@ +#include "../../src/shared/object/SwgCreatureObject.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgGameServer.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgGameServer.h new file mode 100644 index 00000000..117487ff --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgGameServer.h @@ -0,0 +1 @@ +#include "../../src/shared/core/SwgGameServer.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgPlayerCreatureController.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgPlayerCreatureController.h new file mode 100644 index 00000000..eadbbe2c --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgPlayerCreatureController.h @@ -0,0 +1 @@ +#include "../../src/shared/controller/SwgPlayerCreatureController.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgPlayerObject.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgPlayerObject.h new file mode 100644 index 00000000..b829af65 --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgPlayerObject.h @@ -0,0 +1 @@ +#include "../../src/shared/object/SwgPlayerObject.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgServerCreatureObjectTemplate.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgServerCreatureObjectTemplate.h new file mode 100644 index 00000000..f65a6485 --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgServerCreatureObjectTemplate.h @@ -0,0 +1 @@ +#include "../../src/shared/objectTemplate/SwgServerCreatureObjectTemplate.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgServerPlayerObjectTemplate.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgServerPlayerObjectTemplate.h new file mode 100644 index 00000000..f5e6eb27 --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgServerPlayerObjectTemplate.h @@ -0,0 +1 @@ +#include "../../src/shared/objectTemplate/SwgServerPlayerObjectTemplate.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgServerUniverse.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgServerUniverse.h new file mode 100644 index 00000000..f62506fd --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/SwgServerUniverse.h @@ -0,0 +1 @@ +#include "../../src/shared/core/SwgServerUniverse.h" diff --git a/game/server/application/SwgGameServer/include/public/SwgGameServer/WorldSnapshotParser.h b/game/server/application/SwgGameServer/include/public/SwgGameServer/WorldSnapshotParser.h new file mode 100644 index 00000000..1e973f47 --- /dev/null +++ b/game/server/application/SwgGameServer/include/public/SwgGameServer/WorldSnapshotParser.h @@ -0,0 +1 @@ +#include "../../src/shared/snapshot/WorldSnapshotParser.h" diff --git a/game/server/application/SwgGameServer/src/CMakeLists.txt b/game/server/application/SwgGameServer/src/CMakeLists.txt new file mode 100644 index 00000000..91923137 --- /dev/null +++ b/game/server/application/SwgGameServer/src/CMakeLists.txt @@ -0,0 +1,110 @@ + +set(SHARED_SOURCES + shared/combat/combat.def + shared/combat/CombatEngine.cpp + shared/combat/CombatEngine.h + shared/combat/ConfigCombatEngine.cpp + shared/combat/ConfigCombatEngine.h + + shared/console/ConsoleCommandParserCombatEngine.cpp + shared/console/ConsoleCommandParserCombatEngine.h + shared/console/ConsoleCommandParserCombatEngineQueue.cpp + shared/console/ConsoleCommandParserCombatEngineQueue.h + + shared/controller/JediManagerController.cpp + shared/controller/JediManagerController.h + shared/controller/SwgPlayerCreatureController.cpp + shared/controller/SwgPlayerCreatureController.h + + shared/core/CSHandler.cpp + shared/core/CSHandler.h + shared/core/SwgGameServer.cpp + shared/core/SwgGameServer.h + shared/core/SwgServerUniverse.cpp + shared/core/SwgServerUniverse.h + + shared/lint/ServerObjectLint.cpp + shared/lint/ServerObjectLint.h + + shared/object/JediManagerObject.cpp + shared/object/JediManagerObject.h + shared/object/SwgCreatureObject.cpp + shared/object/SwgCreatureObject.h + shared/object/SwgPlayerObject.cpp + shared/object/SwgPlayerObject.h + + shared/objectTemplate/ServerJediManagerObjectTemplate.cpp + shared/objectTemplate/ServerJediManagerObjectTemplate.h + shared/objectTemplate/SwgServerCreatureObjectTemplate.cpp + shared/objectTemplate/SwgServerCreatureObjectTemplate.h + shared/objectTemplate/SwgServerPlayerObjectTemplate.cpp + shared/objectTemplate/SwgServerPlayerObjectTemplate.h + + shared/snapshot/WorldSnapshotParser.cpp + shared/snapshot/WorldSnapshotParser.h +) + +if(WIN32) + set(PLATFORM_SOURCES + win32/FirstSwgGameServer.cpp + win32/WinMain.cpp + ) + + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/win32) +else() + set(PLATFORM_SOURCES + linux/main.cpp + ) + + include_directories(${CMAKE_CURRENT_SOURCE_DIR}/linux) +endif() + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/shared/combat + ${CMAKE_CURRENT_SOURCE_DIR}/shared/core + ${CMAKE_CURRENT_SOURCE_DIR}/shared/lint + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedCollision/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedCommandParser/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFile/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundation/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundationTypes/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedGame/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedImage/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedLog/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMath/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMathArchive/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMessageDispatch/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetwork/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetworkMessages/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedObject/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedPathfinding/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedRandom/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedRegex/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedSkillSystem/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedTerrain/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public + ${SWG_ENGINE_SOURCE_DIR}/server/library/serverGame/include/public + ${SWG_ENGINE_SOURCE_DIR}/server/library/serverNetworkMessages/include/public + ${SWG_ENGINE_SOURCE_DIR}/server/library/serverPathfinding/include/public + ${SWG_ENGINE_SOURCE_DIR}/server/library/serverScript/include/public + ${SWG_ENGINE_SOURCE_DIR}/server/library/serverUtility/include/public + ${SWG_GAME_SOURCE_DIR}/shared/library/swgSharedNetworkMessages/include/public + ${SWG_GAME_SOURCE_DIR}/shared/library/swgSharedUtility/include/public + ${SWG_GAME_SOURCE_DIR}/server/library/swgServerNetworkMessages/include/public + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/fileInterface/include/public + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localization/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localizationArchive/include/public + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/singleton/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicodeArchive/include/public + ${Boost_INCLUDE_DIR} + ${JNI_INCLUDE_DIRS} +) + +add_executable(SwgGameServer + ${SHARED_SOURCES} + ${PLATFORM_SOURCES} +) diff --git a/game/server/application/SwgGameServer/src/linux/main.cpp b/game/server/application/SwgGameServer/src/linux/main.cpp new file mode 100644 index 00000000..8c52d111 --- /dev/null +++ b/game/server/application/SwgGameServer/src/linux/main.cpp @@ -0,0 +1,141 @@ +#include "FirstSwgGameServer.h" +#include "serverGame/GameServer.h" + +#include "LocalizationManager.h" +#include "serverGame/SetupServerGame.h" +#include "serverPathfinding/SetupServerPathfinding.h" +#include "serverScript/SetupScript.h" +#include "serverUtility/SetupServerUtility.h" +#include "sharedDebug/SetupSharedDebug.h" +#include "sharedFile/SetupSharedFile.h" +#include "sharedFile/TreeFile.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedFoundation/ExitChain.h" +#include "sharedFoundation/Os.h" +#include "sharedFoundation/SetupSharedFoundation.h" +#include "sharedGame/SetupSharedGame.h" +#include "sharedImage/SetupSharedImage.h" +#include "sharedLog/LogManager.h" +#include "sharedLog/SetupSharedLog.h" +#include "sharedMath/SetupSharedMath.h" +#include "sharedNetwork/NetworkHandler.h" +#include "sharedNetwork/SetupSharedNetwork.h" +#include "sharedObject/SetupSharedObject.h" +#include "sharedRandom/SetupSharedRandom.h" +#include "sharedRegex/SetupSharedRegex.h" +#include "sharedTerrain/SetupSharedTerrain.h" +#include "sharedThread/SetupSharedThread.h" +#include "sharedUtility/SetupSharedUtility.h" +#include "sharedNetworkMessages/SetupSharedNetworkMessages.h" +#include "SwgGameServer/SwgGameServer.h" +#include "SwgGameServer/WorldSnapshotParser.h" +#include "swgSharedNetworkMessages/SetupSwgSharedNetworkMessages.h" +#include "swgServerNetworkMessages/SetupSwgServerNetworkMessages.h" + + +// ====================================================================== + +int main(int argc, char ** argv) +{ + SetupSharedThread::install(); + SetupSharedDebug::install(1024); + + //-- setup foundation + SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game); + setupFoundationData.lpCmdLine = ConvertCommandLine(argc,argv); + setupFoundationData.runInBackground = true; + SetupSharedFoundation::install (setupFoundationData); + + SetupServerUtility::install(); + + SetupSharedRegex::install(); + + SetupSharedFile::install(false); + SetupSharedMath::install(); + + SetupSharedNetwork::SetupData networkSetupData; + SetupSharedNetwork::getDefaultServerSetupData(networkSetupData); + SetupSharedNetwork::install(networkSetupData); + + SetupSharedUtility::Data setupUtilityData; + SetupSharedUtility::setupGameData (setupUtilityData); + SetupSharedUtility::install (setupUtilityData); + + SetupSharedNetworkMessages::install(); + SetupSwgSharedNetworkMessages::install(); + SetupSwgServerNetworkMessages::install(); + + SetupSharedRandom::install(time(0));//lint !e732 + { + SetupSharedObject::Data data; + SetupSharedObject::setupDefaultGameData(data); + // we want the SlotIdManager initialized, but we don't need the associated hardpoint names on the server. + SetupSharedObject::addSlotIdManagerData(data, false); + // we want movement table information on this server + SetupSharedObject::addMovementTableData(data); + // we want CustomizationData support on this server. + SetupSharedObject::addCustomizationSupportData(data); + // we want POB ejection point override support. + SetupSharedObject::addPobEjectionTransformData(data); + // objects should not automatically alter their children and contents + data.objectsAlterChildrenAndContents = false; + SetupSharedObject::install(data); + } + + char tmp[92]; + sprintf(tmp, "SwgGameServer:%d", Os::getProcessId()); + SetupSharedLog::install(tmp); + + TreeFile::addSearchAbsolute(0); + TreeFile::addSearchPath(".",0); + + SetupSharedImage::Data setupImageData; + SetupSharedImage::setupDefaultData (setupImageData); + SetupSharedImage::install (setupImageData); + + SetupSharedGame::Data setupSharedGameData; + setupSharedGameData.setUseMountValidScaleRangeTable(true); + setupSharedGameData.setUseClientCombatManagerSupport(true); + SetupSharedGame::install (setupSharedGameData); + + SetupSharedTerrain::Data setupSharedTerrainData; + SetupSharedTerrain::setupGameData (setupSharedTerrainData); + SetupSharedTerrain::install (setupSharedTerrainData); + + SetupScript::Data setupScriptData; + SetupScript::setupDefaultGameData(setupScriptData); + SetupScript::install(); + + SetupServerPathfinding::install(); + + //-- setup game server + SetupServerGame::install(); + + NetworkHandler::install(); + Os::setProgramName("SwgGameServer"); + SwgGameServer::install(); + +#ifdef _DEBUG + //-- see if the game server is being run in a mode to parse the database dump to create planetary snapshot files + const char* const createWorldSnapshots = ConfigFile::getKeyString("WorldSnapshot", "createWorldSnapshots", 0); + if (createWorldSnapshots) + { + WorldSnapshotParser::createWorldSnapshots (createWorldSnapshots); + } + else +#endif + { + //-- run game + SetupSharedFoundation::callbackWithExceptionHandling(GameServer::run); + } + + NetworkHandler::remove(); + SetupServerGame::remove(); + + SetupSharedLog::remove(); + SetupSharedFoundation::remove(); + SetupSharedThread::remove (); + + return 0; +} + diff --git a/game/server/application/SwgGameServer/src/shared/combat/CombatEngine.cpp b/game/server/application/SwgGameServer/src/shared/combat/CombatEngine.cpp new file mode 100644 index 00000000..15fc34f7 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/combat/CombatEngine.cpp @@ -0,0 +1,740 @@ +//======================================================================== +// +// CombatEngine.cpp +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + + +#include "FirstSwgGameServer.h" +#include "CombatEngine.h" + +#include "ConfigCombatEngine.h" +#include "serverGame/Client.h" +#include "serverGame/ConfigServerGame.h" //@todo code reorg, need another cfg file +#include "serverGame/ConsoleManager.h" +#include "serverGame/ContainerInterface.h" +#include "serverGame/CreatureController.h" +#include "serverGame/CreatureObject.h" +#include "serverGame/ServerObject.h" +#include "serverGame/ServerWorld.h" +#include "serverGame/TangibleObject.h" +#include "serverGame/WeaponObject.h" +#include "serverScript/GameScriptObject.h" +#include "serverScript/ScriptFunctionTable.h" +#include "serverScript/ScriptParameters.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedFoundation/ConstCharCrcLowerString.h" +#include "sharedFoundation/GameControllerMessage.h" +#include "sharedFoundation/GameControllerMessage.h" +#include "sharedFoundation/Misc.h" +#include "sharedGame/CommandTable.h" +#include "sharedGame/GameObjectTypes.h" +#include "sharedGame/SharedObjectTemplate.h" +#include "sharedNetworkMessages/MessageQueueGenericValueType.h" +#include "sharedNetworkMessages/MessageQueueNetworkId.h" +#include "sharedTerrain/TerrainObject.h" +#include "swgServerNetworkMessages/MessageQueueCombatDamageList.h" +#include "swgServerNetworkMessages/MessageQueueDirectDamage.h" +#include "swgSharedNetworkMessages/CombatActionCompleteMessage.h" +#include "swgSharedNetworkMessages/MessageQueueCombatAction.h" +#include "swgSharedNetworkMessages/MessageQueueCombatDamage.h" + +#include + +static const std::string UNSKILLED_COMMAND("unskilled"); +static const ConstCharCrcLowerString COMBAT_TARGET_COMMAND("combattarget"); +static const ConstCharCrcLowerString AIM_COMMAND("aim"); +static const ConstCharCrcLowerString DEFAULT_ATTACK_COMMAND("defaultattack"); + + +//------------------------------------------------------------------------ +// static class variables + +uint16 CombatEngine::ms_nextActionId = 0; + + +//------------------------------------------------------------------------ +// class functions + +/** + * Initializes the combat engine. + */ +void CombatEngine::install(void) +{ + ConfigCombatEngine::install(); + + // set up command queue combat functions + CommandTable::addCppFunction("aim", aim); + + ExitChain::add(CombatEngine::remove, "CombatEngine::remove"); +} // CombatEngine::install + +/** + * Cleans up the combat engine. + */ +void CombatEngine::remove(void) +{ + ConfigCombatEngine::remove(); +} // CombatEngine::remove + +/** + * Reloads the combat data values from the combat config file. + * + * @return true on success, false on fail + */ +bool CombatEngine::reloadCombatData(void) +{ + // @todo: can we synchronize this between servers? + ConfigCombatEngine::remove(); + ConfigCombatEngine::install(); + return true; +} // CombatEngine::reloadCombatData + +/** + * Adds an aim to an attacker's next attack. + * + * @param actor the attacker + */ +void CombatEngine::aim(const Command &, const NetworkId & actor, const NetworkId &, const Unicode::String &) +{ + CachedNetworkId attackerId(actor); + TangibleObject * attacker = dynamic_cast(attackerId.getObject()); + + if (attacker != NULL) + { + attacker->addAim(); + } +} // CombatEngine::aim + +/** + * Adds a target action to the end of an object's action queue. + * + * @param attacker the object attacking + * @param targets who is being targeted + * + * @return true on success, false on fail + */ +bool CombatEngine::addTargetAction(TangibleObject & attacker, + const CombatEngineData::TargetIdList & targets) +{ + // @todo: support tangible attacks + CreatureObject * const creatureAttacker = attacker.asCreatureObject (); + if (creatureAttacker == NULL) + { + WARNING_STRICT_FATAL(true, ("Tangible attackers not supported yet")); + return false; + } + + creatureAttacker->commandQueueEnqueue(CommandTable::getCommand( + COMBAT_TARGET_COMMAND.getCrc()), targets[0], Unicode::String()); + return true; +} // CombatEngine::addTargetAction + +/** + * Adds an attack action to the end of an object's action queue. + * + * @param attacker the object attacking + * @param weapon the weapon being used (0 = attacker's primary weapon) + * @param weaponMode the mode of the weapon being used (0 = primary, -1 = current mode) + * + * @return true on success, false on fail + */ +bool CombatEngine::addAttackAction(TangibleObject & attacker, + const NetworkId & weapon, int weaponMode) +{ + // @todo: support tangible attacks + CreatureObject * const creatureAttacker = attacker.asCreatureObject (); + if (creatureAttacker == NULL) + { + WARNING_STRICT_FATAL(true, ("Tangible attackers not supported yet")); + return false; + } + + // set up the weapon id and mode into a params string + char buffer[64]; + sprintf(buffer, "%s %d", weapon.getValueString().c_str(), weaponMode); + Unicode::String params(Unicode::narrowToWide(buffer)); + + creatureAttacker->commandQueueEnqueue(CommandTable::getCommand( + DEFAULT_ATTACK_COMMAND.getCrc()), NetworkId::cms_invalid, params); + return true; +} // CombatEngine::addAttackAction + +/** + * Adds an aim action to the end of an object's action queue. + * + * @param attacker the object attacking + * + * @return true on success, false on fail + */ +bool CombatEngine::addAimAction(TangibleObject & attacker) +{ + if (!attacker.isInCombat()) + return false; + + // @todo: support tangible attacks + CreatureObject * const creatureAttacker = attacker.asCreatureObject (); + if (creatureAttacker == NULL) + { + WARNING_STRICT_FATAL(true, ("Tangible attackers not supported yet")); + return false; + } + + creatureAttacker->commandQueueEnqueue(CommandTable::getCommand( + AIM_COMMAND.getCrc()), NetworkId::cms_invalid, Unicode::String()); + return true; +} // CombatEngine::addAimAction + +/** + * Determines the specific damage to apply to the defender after a successful + * attack. + * + * @param attacker the attacker + * @param defender the defender + * @param weapon the attacker's weapon + * @param damageAmount base damage done + * @param hitLocation where the defender was hit + * + * @return true on success, false if there was an error + */ +bool CombatEngine::onSuccessfulAttack(const TangibleObject & attacker, + TangibleObject & defender, const WeaponObject & weapon, int damageAmount, + int hitLocation) +{ + const bool creatureDefender = defender.asCreatureObject() != NULL; + const bool isVehicle = GameObjectTypes::isTypeOf (defender.getGameObjectType (), SharedObjectTemplate::GOT_vehicle); + + // if attacking an object, always hit location 0 + if (!creatureDefender || isVehicle) + hitLocation = 0; + + // get the damage profile for the hit location + const ConfigCombatEngine::SkeletonAttackMod & skeletonAttackMod = + ConfigCombatEngine::getSkeletonAttackMod(static_cast(defender.getCombatSkeleton())); + if (hitLocation < 0 || hitLocation >= static_cast(skeletonAttackMod.attackMods.size())) + return false; + const ConfigCombatEngineData::BodyAttackMod & hitLocationData = + skeletonAttackMod.attackMods[static_cast(hitLocation)]; + + // put a attribMod structure on the defender's damage list for each type of + // damage received + DamageList damageList; + if (creatureDefender && !isVehicle) + { + computeCreatureDamage(&hitLocationData, damageAmount, damageList); + } + else + { + computeObjectDamage(&hitLocationData, damageAmount, damageList); + } + if (damageList.empty()) + return false; + + // determine if the defender was wounded + bool isWounded = false; + + if (creatureDefender && !isVehicle) + { + float woundChance = weapon.getWoundChance() + ConfigCombatEngine::getWoundChance(); + if (hitLocation) + woundChance += hitLocationData.toWoundBonus; + if (Random::randomReal(0.0f, 100.0f) <= woundChance) + isWounded = true; + } + + // apply the damage + if (defender.isAuthoritative()) + { + // Ensure the combat data has been initialized + defender.createCombatData(); + + CombatEngineData::DefenseData & defenseData = defender.getCombatData()->defenseData; + defenseData.damage.push_back(CombatEngineData::DamageData()); + CombatEngineData::DamageData &damageData = defenseData.damage.back(); + damageData.attackerId = attacker.getNetworkId(); + damageData.weaponId = weapon.getNetworkId(); + damageData.damageType = static_cast(static_cast(weapon.getDamageType())); + damageData.hitLocationIndex = static_cast(hitLocation); + damageData.damage.insert(damageData.damage.end(), damageList.begin(), damageList.end()); + damageData.wounded = isWounded; + } + else + { + TangibleController * const tangibleController = (defender.getController() != NULL) ? defender.getController()->asTangibleController() : NULL; + + if (tangibleController == NULL) + { + WARNING_STRICT_FATAL(true, ("CombatEngine::onSuccessfulAttack non-auth " + "defender %s doesn't have a TangibleController!", + defender.getNetworkId().getValueString().c_str())); + return false; + } + + // send the damage info to the authoritative object + MessageQueueCombatDamageList * message = new MessageQueueCombatDamageList(); + NOT_NULL(message); + CombatEngineData::DamageData & damageData = message->addDamage(); + + damageData.attackerId = attacker.getNetworkId(); + damageData.weaponId = weapon.getNetworkId(); + damageData.damageType = static_cast(static_cast(weapon.getDamageType())); + damageData.hitLocationIndex = static_cast(hitLocation); + damageData.damage.insert(damageData.damage.end(), damageList.begin(), damageList.end()); + damageData.wounded = isWounded; + + tangibleController->appendMessage( + CM_combatDamageList, + 0.0f, + message, + GameControllerMessageFlags::SEND | + GameControllerMessageFlags::RELIABLE | + GameControllerMessageFlags::DEST_AUTH_SERVER + ); + }//lint !e429 // Custodial pointer 'message' has not been freed or returned // the controller queue will manage freeing the memory + + return true; +} // CombatEngine::onSuccessfulAttack + +/** + * Determines the specific damage to apply to the defender after a successful + * attack. + * + * @param attacker the attacker + * @param defender the defender + * @param damageAmount base damage done + * @param hitLocation where the defender was hit + * + * @return true on success, false if there was an error + */ +bool CombatEngine::onSuccessfulAttack(const TangibleObject & attacker, + TangibleObject & defender, int damageAmount, + int hitLocation) +{ + const bool creatureDefender = defender.asCreatureObject() != NULL; + const bool isVehicle = GameObjectTypes::isTypeOf (defender.getGameObjectType (), SharedObjectTemplate::GOT_vehicle); + + // if attacking an object, always hit location 0 + if (!creatureDefender || isVehicle) + hitLocation = 0; + + // get the damage profile for the hit location + const ConfigCombatEngine::SkeletonAttackMod & skeletonAttackMod = + ConfigCombatEngine::getSkeletonAttackMod(static_cast(defender.getCombatSkeleton())); + if (hitLocation < 0 || hitLocation >= static_cast(skeletonAttackMod.attackMods.size())) + return false; + const ConfigCombatEngineData::BodyAttackMod & hitLocationData = + skeletonAttackMod.attackMods[static_cast(hitLocation)]; + + // put a attribMod structure on the defender's damage list for each type of + // damage received + DamageList damageList; + if (creatureDefender && !isVehicle) + { + computeCreatureDamage(&hitLocationData, damageAmount, damageList); + } + else + { + computeObjectDamage(&hitLocationData, damageAmount, damageList); + } + if (damageList.empty()) + return false; + + // determine if the defender was wounded + bool isWounded = false; + + // apply the damage + if (defender.isAuthoritative()) + { + // Ensure the combat data has been initialized + defender.createCombatData(); + + CombatEngineData::DefenseData & defenseData = defender.getCombatData()->defenseData; + defenseData.damage.push_back(CombatEngineData::DamageData()); + CombatEngineData::DamageData &damageData = defenseData.damage.back(); + damageData.attackerId = attacker.getNetworkId(); + damageData.hitLocationIndex = static_cast(hitLocation); + damageData.damage.insert(damageData.damage.end(), damageList.begin(), damageList.end()); + damageData.wounded = isWounded; + } + else + { + TangibleController * const tangibleController = (defender.getController() != NULL) ? defender.getController()->asTangibleController() : NULL; + + if (tangibleController == NULL) + { + WARNING_STRICT_FATAL(true, ("CombatEngine::onSuccessfulAttack non-auth " + "defender %s doesn't have a TangibleController!", + defender.getNetworkId().getValueString().c_str())); + return false; + } + + // send the damage info to the authoritative object + MessageQueueCombatDamageList * message = new MessageQueueCombatDamageList(); + NOT_NULL(message); + CombatEngineData::DamageData & damageData = message->addDamage(); + + damageData.attackerId = attacker.getNetworkId(); + damageData.hitLocationIndex = static_cast(hitLocation); + damageData.damage.insert(damageData.damage.end(), damageList.begin(), damageList.end()); + damageData.wounded = isWounded; + + tangibleController->appendMessage( + CM_combatDamageList, + 0.0f, + message, + GameControllerMessageFlags::SEND | + GameControllerMessageFlags::RELIABLE | + GameControllerMessageFlags::DEST_AUTH_SERVER + ); + }//lint !e429 // Custodial pointer 'message' has not been freed or returned // the controller queue will manage freeing the memory + + return true; +} // CombatEngine::onSuccessfulAttack + +/** + * Damages an object. This damage is immediately applied to the object, outside + * the combat loop. + * + * @param defender the defender + * @param weapon the weapon the defender is hit by + * @param damageAmount base damage done + * @param hitLocation where the defender was hit + * + * @return true on success, false if there was an error + */ +bool CombatEngine::damage(TangibleObject & defender, const WeaponObject & weapon, + int damageAmount, int hitLocation) +{ + if (defender.isAuthoritative()) + { + CreatureObject * const critter = defender.asCreatureObject(); + const bool isVehicle = GameObjectTypes::isTypeOf (defender.getGameObjectType (), SharedObjectTemplate::GOT_vehicle); + + // if attacking an object, always hit location 0 + if (critter == NULL || isVehicle) + hitLocation = 0; + + // get the damage profile for the hit location + const ConfigCombatEngine::SkeletonAttackMod & skeletonAttackMod = + ConfigCombatEngine::getSkeletonAttackMod(static_cast(defender.getCombatSkeleton())); + if (hitLocation < 0 || hitLocation >= static_cast(skeletonAttackMod.attackMods.size())) + return false; + const ConfigCombatEngineData::BodyAttackMod & hitLocationData = + skeletonAttackMod.attackMods[static_cast(hitLocation)]; + + // put a attribMod structure on the defender's damage list for each type of + // damage received + DamageList damageList; + if (critter != NULL && !isVehicle) + { + computeCreatureDamage(&hitLocationData, damageAmount, damageList); + } + else + { + computeObjectDamage(&hitLocationData, damageAmount, damageList); + } + if (damageList.empty()) + return false; + + // determine if the defender was wounded + bool isWounded = false; + if (critter && !isVehicle) + { + float woundChance = weapon.getWoundChance() + ConfigCombatEngine::getWoundChance(); + if (hitLocation) + woundChance += hitLocationData.toWoundBonus; + if (Random::randomReal(0.0f, 100.0f) <= woundChance) + isWounded = true; + } + + // apply the damage + CombatEngineData::DamageData damageData; + damageData.attackerId = NetworkId::cms_invalid; + damageData.weaponId = weapon.getNetworkId(); + damageData.damageType = static_cast(static_cast(weapon.getDamageType())); + damageData.hitLocationIndex = static_cast(hitLocation); + damageData.damage.insert(damageData.damage.end(), damageList.begin(), damageList.end()); + damageData.wounded = isWounded; + + if (critter != NULL || !defender.isDisabled()) + { + // update the object's hit points or attributes for the damage + defender.applyDamage(damageData); + } + } + + return true; +} // CombatEngine::damage + +/** + * Damages an object. This damage is immediately applied to the object, outside + * the combat loop. + * + * @param defender the object to be damaged + * @param damageType the type of damage being done + * @param hitLocation the hit location of the damage + * @param damage the amount of damage to do + */ +void CombatEngine::damage(TangibleObject & defender, + ServerWeaponObjectTemplate::DamageType damageType, uint16 hitLocation, + int damageDone) +{ + if (defender.isAuthoritative()) + { + CreatureObject *critter = defender.asCreatureObject(); + const bool isVehicle = GameObjectTypes::isTypeOf (defender.getGameObjectType (), SharedObjectTemplate::GOT_vehicle); + + // if attacking an object, always hit location 0 + if (critter == NULL || isVehicle) + hitLocation = 0; + + // get the damage profile for the hit location + const ConfigCombatEngine::SkeletonAttackMod & skeletonAttackMod = + ConfigCombatEngine::getSkeletonAttackMod(static_cast(defender.getCombatSkeleton())); + if (hitLocation >= static_cast(skeletonAttackMod.attackMods.size())) + return; + const ConfigCombatEngineData::BodyAttackMod & hitLocationData = + skeletonAttackMod.attackMods[static_cast(hitLocation)]; + + // get the damage + DamageList damageList; + if (critter && !isVehicle) + CombatEngine::computeCreatureDamage(&hitLocationData, damageDone, damageList); + else + CombatEngine::computeObjectDamage(&hitLocationData, damageDone, damageList); + + if (damageList.empty()) + return; + + // apply the damage + CombatEngineData::DamageData damageData; + damageData.attackerId = NetworkId::cms_invalid; + damageData.weaponId = NetworkId::cms_invalid; + damageData.damageType = static_cast(static_cast(damageType)); + damageData.hitLocationIndex = hitLocation; + damageData.damage.insert(damageData.damage.end(), damageList.begin(), damageList.end()); + + if (critter != NULL || !defender.isDisabled()) + { + // update the object's hit points or attributes for the damage + defender.applyDamage(damageData); + } + } + else + { + defender.sendControllerMessageToAuthServer(CM_directDamage, + new MessageQueueDirectDamage(damageType, hitLocation, damageDone)); + } +} // CombatEngine::damage + +/** + * Damages all objects within a given area. + * + * @param center the center of the area to damage + * @param radius the radius of the area to damage + * @param damageType the type of damage being done + * @param damage the amount of damage to do + */ +void CombatEngine::damage(const Vector ¢er, float radius, + ServerWeaponObjectTemplate::DamageType damageType, int damageDone) +{ + // determine the damage that will occur to creatures and non-creatures + DamageList creatureDamageList, objectDamageList; + computeCreatureDamage(0, damageDone, creatureDamageList); + computeObjectDamage(0, damageDone, objectDamageList); + if (creatureDamageList.empty() && objectDamageList.empty()) + return; + + // get everything in the damage area + std::vector targetList; + ServerWorld::findObjectsInRange(center, radius, targetList); + if (targetList.empty()) + return; + + std::vector::iterator iter; + for (iter = targetList.begin(); iter != targetList.end(); ++iter) + { + ServerObject * const obj = *iter; + if (!obj) + continue; + + TangibleObject * const defender = obj->asTangibleObject (); + if (!defender) + continue; + + const bool isVehicle = GameObjectTypes::isTypeOf (defender->getGameObjectType (), SharedObjectTemplate::GOT_vehicle); + + // apply the damage + { + // Ensure the combat data has been initialized + defender->createCombatData(); + + CombatEngineData::DefenseData & defenseData = defender->getCombatData()->defenseData; + defenseData.damage.push_back(CombatEngineData::DamageData()); + CombatEngineData::DamageData &damageData = defenseData.damage.back(); + damageData.attackerId = NetworkId::cms_invalid; + damageData.weaponId = NetworkId::cms_invalid; + damageData.damageType = static_cast(static_cast(damageType)); + damageData.hitLocationIndex = 0; + + if (defender->asCreatureObject () && !isVehicle) + { + damageData.damage.insert(damageData.damage.end(), + creatureDamageList.begin(), creatureDamageList.end()); + } + else + { + damageData.damage.insert(damageData.damage.end(), + objectDamageList.begin(), objectDamageList.end()); + } + } + } +} // CombatEngine::damage + +/** + * Determines how a creature will be damaged. + * + * @param hitLocation where on the defender the damage occurred + * @param damageType the type of damage being done + * @param damage the amount of damage to do + * @param damageList list to be filled in with attribMods caused by the damage + */ +void CombatEngine::computeCreatureDamage( + const ConfigCombatEngineData::BodyAttackMod *hitLocation, + int damageDone, + DamageList & damageList) +{ + // put all damage into health + damageList.push_back(AttribMod::AttribMod()); + AttribMod::AttribMod & attribMod = damageList.back(); + attribMod.tag = 0; + attribMod.attrib = Attributes::Health; + attribMod.value = -damageDone; + attribMod.attack = 0.0f; + attribMod.sustain = 0.0f; + attribMod.decay = ServerWeaponObjectTemplate::AMDS_pool; + attribMod.flags = AttribMod::AMF_directDamage; +} // CombatEngine::computeCreatureDamage + +/** + * Determines how a non-creature will be damaged. + * + * @param hitLocation where on the defender the damage occurred + * @param damageType the type of damage being done + * @param damage the amount of damage to do + * @param damageList list to be filled in with attribMods caused by the damage + */ +void CombatEngine::computeObjectDamage( + const ConfigCombatEngineData::BodyAttackMod *hitLocation, + int damageDone, + DamageList & damageList) +{ + int actualDamage = static_cast(floor(damageDone * 1.0f + 0.5f)); //lint !e747 Significant prototype coercion (arg. no. 1) float to double + if (actualDamage == 0) + return; + + // create an attribMod structure for damage received + if (hitLocation && hitLocation->damageBonus[0] != 0) + { + if (hitLocation->damageBonus[0] > 0) + { + actualDamage += static_cast(floor(actualDamage * hitLocation-> + damageBonus[0] + 0.5f)); //lint !e747 Significant prototype coercion (arg. no. 1) float to double + } + else + { + actualDamage += static_cast(ceil(actualDamage * hitLocation-> + damageBonus[0] - 0.5f)); //lint !e747 Significant prototype coercion (arg. no. 1) float to double + } + } + damageList.push_back(AttribMod::AttribMod()); + AttribMod::AttribMod & attribMod = damageList.back(); + attribMod.tag = 0; + attribMod.attrib = ServerObjectTemplate::AT_health; + attribMod.value = -actualDamage; + attribMod.attack = 0.0f; + attribMod.sustain = 0.0f; + attribMod.decay = ServerWeaponObjectTemplate::AMDS_pool; //lint !e641 Converting enum 'AttribModDecaySpecial' to int + attribMod.flags = AttribMod::AMF_directDamage; +} // CombatEngine::computeObjectDamage + +/** + * Applies combat damage done during execute() to an object. Should be called as + * part of the object's alter function. + * + * @param object the object to damage + */ +void CombatEngine::alter(TangibleObject & object) +{ + NOT_NULL(object.getController()); + + if ( (object.getCombatData() == NULL) + || object.getCombatData()->defenseData.damage.empty()) + { + return; + } + + std::vector &damageData = object.getCombatData()->defenseData.damage; + std::vector::iterator iter; + + if (object.isAuthoritative()) + { + // if the object is a creature, get it's attributes + Attributes::Value currentAttribs[Attributes::NumberOfAttributes]; + CreatureObject * const critter = object.asCreatureObject (); + if (critter != NULL) + { + for (int i = 0; i < Attributes::NumberOfAttributes; ++i) + currentAttribs[i] = critter->getAttribute(i); + } + else + { + // @todo: handle damage to objects + } + // update the object + // to guard against the list changing while we are iterating over it, + // we will iterate using index rather than iterator + for (std::vector::size_type i = 0; object.isInCombat() && i < damageData.size(); ++i) + { + // since armor == hp now, we need to double check that the object + // is in combat, since a non-creature could be removed by just + // damaging their armor + if (object.isInCombat()) + { + // update the object's hit points or attributes for the damage + object.applyDamage(damageData[i]); + } + } + }//lint !e550 Symbol 'currentAttribs' (line 2653) not accessed // yes it is + else + { + TangibleController * const tangibleController = object.getController()->asTangibleController(); + + if (tangibleController == NULL) + { + WARNING_STRICT_FATAL(true, ("CombatEngine::alter non-auth " + "object %s doesn't have a TangibleController!", + object.getNetworkId().getValueString().c_str())); + return; + } + + // send the damage info to the authoritative object + MessageQueueCombatDamageList * message = new MessageQueueCombatDamageList(); + NOT_NULL(message); + for (iter = damageData.begin(); iter != damageData.end(); ++iter) + message->addDamage(*iter); + tangibleController->appendMessage( + CM_combatDamageList, + 0.0f, + message, + GameControllerMessageFlags::SEND | + GameControllerMessageFlags::RELIABLE | + GameControllerMessageFlags::DEST_AUTH_SERVER + ); + }//lint !e429 Custodial pointer 'message' has not been freed or returned // Controller handles message destruction + + object.clearDamageList(); +} // CombatEngine::alter + diff --git a/game/server/application/SwgGameServer/src/shared/combat/CombatEngine.h b/game/server/application/SwgGameServer/src/shared/combat/CombatEngine.h new file mode 100644 index 00000000..5748254a --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/combat/CombatEngine.h @@ -0,0 +1,74 @@ +//======================================================================== +// +// CombatEngine.h +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + + +#ifndef _INCLUDED_CombatEngine_H +#define _INCLUDED_CombatEngine_H + +#include "sharedGame/AttribMod.h" +#include "sharedObject/CachedNetworkId.h" +#include "serverGame/ServerWeaponObjectTemplate.h" +#include "swgSharedUtility/CombatEngineData.h" +#include + +class Command; +class CreatureObject; + + +//------------------------------------------------------------------- +// class CombatEngine + +class CombatEngine +{ +public: + typedef std::vector DamageList; + +public: + + static void install(void); + static void remove(void); + + static bool reloadCombatData(void); + + // command queue hooks + static void aim(const Command & command, const NetworkId & actor, + const NetworkId & target, const Unicode::String & params); + + // queue actions + static bool addTargetAction(TangibleObject & attacker, const CombatEngineData::TargetIdList & targets); + static bool addAttackAction(TangibleObject & attacker, const NetworkId & weapon, int weaponMode); + static bool addAimAction(TangibleObject & attacker); + + static bool onSuccessfulAttack(const TangibleObject & attacker, TangibleObject & defender, const WeaponObject & weapon, int damage, int hitLocation); + static bool onSuccessfulAttack(const TangibleObject & attacker, TangibleObject & defender, int damage, int hitLocation); + static bool damage(TangibleObject & defender, const WeaponObject & weapon, int damageAmount, int hitLocation); + static void damage(TangibleObject & defender, ServerWeaponObjectTemplate::DamageType damageType, uint16 hitLocation, int damage); + static void damage(const Vector ¢er, float radius, ServerWeaponObjectTemplate::DamageType damageType, int damage); + static void alter(TangibleObject & object); + +private: + + static uint16 ms_nextActionId; // id to link attack messages with damage messages + static uint16 getNextActionId(void); + + static void computeCreatureDamage( + const ConfigCombatEngineData::BodyAttackMod *hitLocation, + int damage, DamageList & damageList); + static void computeObjectDamage( + const ConfigCombatEngineData::BodyAttackMod *hitLocation, + int damage, DamageList & damageList); +}; + + +inline uint16 CombatEngine::getNextActionId(void) +{ + return ++ms_nextActionId; +} + + +#endif // _INCLUDED_CombatEngine_H diff --git a/game/server/application/SwgGameServer/src/shared/combat/ConfigCombatEngine.cpp b/game/server/application/SwgGameServer/src/shared/combat/ConfigCombatEngine.cpp new file mode 100644 index 00000000..8b42da06 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/combat/ConfigCombatEngine.cpp @@ -0,0 +1,279 @@ +//======================================================================== +// +// ConfigCombatEngine.h +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#include "FirstSwgGameServer.h" +#include "ConfigCombatEngine.h" +#include "sharedFile/TreeFile.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedFoundation/CrcLowerString.h" +#include "swgSharedUtility/CombatEngineData.h" + +#include +#include "combat.def" + + +#define KEY_INT(a,b) (m_data.a = ConfigFile::getKeyInt("CombatEngine", #a, b)) + + +//------------------------------------------------------------------- +// local statics + +namespace ConfigCombatEngineNameSpace +{ + typedef std::map BoneMap; + BoneMap ms_boneMap; +} + +//------------------------------------------------------------------- + +using namespace ConfigCombatEngineNameSpace; + + +//------------------------------------------------------------------- +// static member variables + +ConfigCombatEngine::Data ConfigCombatEngine::m_data; +float ConfigCombatEngine::m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorHeavy+1][ServerArmorTemplate::AR_armorHeavy+1]; + +void ConfigCombatEngine::install(void) +{ + static const std::string CONFIG_FILE("abstract/combat/combat_consts.iff"); + Iff file; + + ms_boneMap.insert(BoneMap::value_type(CrcLowerString("CSB_body"), static_cast(CSB_body))); + ms_boneMap.insert(BoneMap::value_type(CrcLowerString("CSB_head"), static_cast(CSB_head))); + ms_boneMap.insert(BoneMap::value_type(CrcLowerString("CSB_rightArm"), static_cast(CSB_rightArm))); + ms_boneMap.insert(BoneMap::value_type(CrcLowerString("CSB_leftArm"), static_cast(CSB_leftArm))); + ms_boneMap.insert(BoneMap::value_type(CrcLowerString("CSB_rightLeg"), static_cast(CSB_rightLeg))); + ms_boneMap.insert(BoneMap::value_type(CrcLowerString("CSB_leftLeg"), static_cast(CSB_leftLeg))); + + installFromConfigFile(); + + if (!TreeFile::exists(CONFIG_FILE.c_str())) + return; + if (!file.open(CONFIG_FILE.c_str(), true)) + return; + + Tag type = file.getCurrentName(); + if (type != TAG(C,O,M,C)) + return; + file.enterForm(); + Tag version = file.getCurrentName(); + + switch (version) + { + case TAG(0,0,0,0): + parseVersion0(file); + break; + default: + break; + } + + file.exitForm(); + file.close(); +} // ConfigCombatEngine::install + +/** + * Loads config info from the [CombatEngine] config file section. + */ +void ConfigCombatEngine::installFromConfigFile(void) +{ + KEY_INT(debugQueues, 0); + KEY_INT(debugTargeting, 0); + KEY_INT(debugAttack, 0); + KEY_INT(debugDefense, 0); + KEY_INT(debugDamage, 0); + KEY_INT(debugExplosion, 0); +} // ConfigCombatEngine::installFromConfigFile + +void ConfigCombatEngine::parseVersion0(Iff & file) +{ +std::string paramName, tempString; +ConfigCombatEngineData::BodyAttackMod bodyAttackMod; +ConfigCombatEngine::SkeletonAttackMod skeletonAttackMod; + + //-- Initialize data structures. + memset(&bodyAttackMod, 0, sizeof(bodyAttackMod)); + memset(&skeletonAttackMod, 0, sizeof(skeletonAttackMod)); + + file.enterForm(); + + for (;;) + { + if (file.atEndOfForm()) + break; + + file.enterChunk(); + + file.read_string(paramName); + if (paramName == "maxAims") + { + m_data.maxAims = file.read_uint8(); + } + else if (paramName == "kineticObjectDamage") + { + m_data.kineticObjectDamage = static_cast(file.read_uint8()) / 100.0f; + } + else if (paramName == "energyObjectDamage") + { + m_data.energyObjectDamage = static_cast(file.read_uint8()) / 100.0f; + } + else if (paramName == "blastObjectDamage") + { + m_data.blastObjectDamage = static_cast(file.read_uint8()) / 100.0f; + } + else if (paramName == "stunObjectDamage") + { + m_data.stunObjectDamage = static_cast(file.read_uint8()) / 100.0f; + } + else if (paramName == "restraintObjectDamage") + { + m_data.restraintObjectDamage = static_cast(file.read_uint8()) / 100.0f; + } + else if (paramName == "elementalObjectDamage") + { + m_data.elementalObjectDamage = static_cast(file.read_uint8()) / 100.0f; + } + else if (paramName == "weaponLowerThanArmorRating") + { + m_data.weaponLowerThanArmorRating = static_cast(file.read_uint8()) / 100.0f; + } + else if (paramName == "weaponHigherThanArmorRating") + { + m_data.weaponHigherThanArmorRating = static_cast(file.read_uint8()) / 100.0f; + } + else if (paramName == "woundChance") + { + m_data.woundChance = static_cast(file.read_uint8()) / 100.0f; + } + else if (paramName == "woundPercent") + { + m_data.woundPercent = static_cast(file.read_uint8()) / 100.0f; + } + else if (paramName == "shockWoundPercent") + { + m_data.shockWoundPercent = static_cast(file.read_uint8()) / 100.0f; + } + else if (paramName == "numberSkeletons") + { + m_data.numberSkeletons = file.read_uint8() + 1; + // set up all-body skeleton + bodyAttackMod.name = ""; + bodyAttackMod.modelBoneName = ""; + bodyAttackMod.toHitChance = 100; + bodyAttackMod.toWoundBonus = 0; + bodyAttackMod.combatSkeletonBone = 0; + bodyAttackMod.damageBonus[Attributes::Health] = 0; + bodyAttackMod.damageBonus[Attributes::Action] = 0; + bodyAttackMod.damageBonus[Attributes::Mind] = 0; + skeletonAttackMod.name = ""; + skeletonAttackMod.numHitLocations = 1; + skeletonAttackMod.script = ""; + skeletonAttackMod.attackMods.clear(); + skeletonAttackMod.attackMods.push_back(bodyAttackMod); + m_data.skeletonAttackMods.push_back(skeletonAttackMod); + } + else if (paramName == "skeletonAttackMod") + { + skeletonAttackMod.attackMods.clear(); + size_t skeletonIndex = file.read_uint8() + 1; + while (m_data.skeletonAttackMods.size() <= skeletonIndex) + m_data.skeletonAttackMods.push_back(skeletonAttackMod); + ConfigCombatEngine::SkeletonAttackMod & skeleton = m_data.skeletonAttackMods[skeletonIndex]; + file.read_string(tempString); + skeleton.name = tempString; + skeleton.numHitLocations = file.read_uint8(); + file.read_string(tempString); + skeleton.script = tempString; + } + else if (paramName == "skeletonAttackLoc") + { + size_t skeletonIndex = file.read_uint8() + 1; + size_t locIndex = file.read_uint8(); + while (m_data.skeletonAttackMods.size() <= skeletonIndex) + m_data.skeletonAttackMods.push_back(skeletonAttackMod); + ConfigCombatEngine::SkeletonAttackMod & skeleton = m_data.skeletonAttackMods[skeletonIndex]; + while (skeleton.attackMods.size() <= locIndex) + skeleton.attackMods.push_back(bodyAttackMod); + ConfigCombatEngineData::BodyAttackMod & bodyLoc = skeleton.attackMods[locIndex]; + file.read_string(tempString); + bodyLoc.name = tempString; + file.read_string(tempString); + bodyLoc.modelBoneName = tempString; + bodyLoc.toHitChance = file.read_uint8(); + bodyLoc.toWoundBonus = static_cast(file.read_uint8()) / 100.0f; + bodyLoc.damageBonus[Attributes::Health] = static_cast(file.read_uint8()) / 100.0f; + bodyLoc.damageBonus[Attributes::Action] = static_cast(file.read_uint8()) / 100.0f; + bodyLoc.damageBonus[Attributes::Mind] = static_cast(file.read_uint8()) / 100.0f; + } + file.exitChunk(); + } + + file.exitForm(); + + setupRatingDifferenceDamageReduction(); +} // ConfigCombatEngine::parseVersion0 + +//------------------------------------------------------------------- + +void ConfigCombatEngine::remove(void) +{ + m_data.skeletonAttackMods.clear(); + ms_boneMap.clear(); +} // ConfigCombatEngine::remove + +//------------------------------------------------------------------- + +float ConfigCombatEngine::getObjectDamageSpread( + ServerWeaponObjectTemplate::DamageType damageType) +{ + switch (damageType) + { + case ServerWeaponObjectTemplate::DT_kinetic: + return m_data.kineticObjectDamage; + case ServerWeaponObjectTemplate::DT_energy: + return m_data.energyObjectDamage; + case ServerWeaponObjectTemplate::DT_blast: + return m_data.blastObjectDamage; + case ServerWeaponObjectTemplate::DT_stun: + return m_data.stunObjectDamage; + case ServerWeaponObjectTemplate::DT_restraint: + return m_data.restraintObjectDamage; + default: + break; + }//lint !e788 enum constant not used + return 1.0f; +} // ConfigCombatEngine::getObjectDamageSpread + +//------------------------------------------------------------------- + +/** + * Sets up the RatingDifferenceDamageReduction table. + */ +void ConfigCombatEngine::setupRatingDifferenceDamageReduction(void) +{ + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorNone][ServerArmorTemplate::AR_armorNone] = 1.0f; + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorNone][ServerArmorTemplate::AR_armorLight] = m_data.weaponLowerThanArmorRating; + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorNone][ServerArmorTemplate::AR_armorMedium] = m_data.weaponLowerThanArmorRating * m_data.weaponLowerThanArmorRating; + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorNone][ServerArmorTemplate::AR_armorHeavy] = m_data.weaponLowerThanArmorRating * m_data.weaponLowerThanArmorRating * m_data.weaponLowerThanArmorRating; + + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorLight][ServerArmorTemplate::AR_armorNone] = m_data.weaponHigherThanArmorRating; + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorLight][ServerArmorTemplate::AR_armorLight] = 1.0f; + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorLight][ServerArmorTemplate::AR_armorMedium] = m_data.weaponLowerThanArmorRating; + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorLight][ServerArmorTemplate::AR_armorHeavy] = m_data.weaponLowerThanArmorRating * m_data.weaponLowerThanArmorRating; + + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorMedium][ServerArmorTemplate::AR_armorNone] = m_data.weaponHigherThanArmorRating * m_data.weaponHigherThanArmorRating; + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorMedium][ServerArmorTemplate::AR_armorLight] = m_data.weaponHigherThanArmorRating; + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorMedium][ServerArmorTemplate::AR_armorMedium] = 1.0f; + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorMedium][ServerArmorTemplate::AR_armorHeavy] = m_data.weaponLowerThanArmorRating; + + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorHeavy][ServerArmorTemplate::AR_armorNone] = m_data.weaponHigherThanArmorRating * m_data.weaponHigherThanArmorRating * m_data.weaponHigherThanArmorRating; + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorHeavy][ServerArmorTemplate::AR_armorLight] = m_data.weaponHigherThanArmorRating * m_data.weaponHigherThanArmorRating; + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorHeavy][ServerArmorTemplate::AR_armorMedium] = m_data.weaponHigherThanArmorRating; + m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::AR_armorHeavy][ServerArmorTemplate::AR_armorHeavy] = 1.0f; +} // ConfigCombatEngine::setupRatingDifferenceDamageReduction diff --git a/game/server/application/SwgGameServer/src/shared/combat/ConfigCombatEngine.h b/game/server/application/SwgGameServer/src/shared/combat/ConfigCombatEngine.h new file mode 100644 index 00000000..65b63d80 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/combat/ConfigCombatEngine.h @@ -0,0 +1,229 @@ +//======================================================================== +// +// ConfigCombatEngine.h +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + + +#ifndef _INCLUDED_ConfigCombatEngine_H +#define _INCLUDED_ConfigCombatEngine_H + +#include "serverGame/ServerArmorTemplate.h" +#include "serverGame/ServerTangibleObjectTemplate.h" +#include "serverGame/ServerWeaponObjectTemplate.h" +#include "swgSharedUtility/CombatEngineData.h" +#include "swgSharedUtility/Attributes.def" + + +//------------------------------------------------------------------- +// namespace ConfigCombatEngineData + +namespace ConfigCombatEngineData +{ + struct BodyAttackMod + { + std::string name; + std::string modelBoneName; // name of a 3d-model bone to associate with + uint32 combatSkeletonBone; + int toHitChance; + float toWoundBonus; + float damageBonus[Attributes::NumberOfAttributes]; + }; +};//lint !e19 Useless declaration + + +//------------------------------------------------------------------- +// class ConfigCombatEngine + +class ConfigCombatEngine +{ +public: + + struct AggressionMod + { + float time; + int toHit; + }; + + struct SkeletonAttackMod + { + std::string name; + int numHitLocations; + std::string script; + std::vector attackMods; + }; + + struct Data + { + int maxAims; + int numberSkeletons; + std::vector skeletonAttackMods; + float kineticObjectDamage; + float energyObjectDamage; + float blastObjectDamage; + float stunObjectDamage; + float restraintObjectDamage; + float elementalObjectDamage; + float weaponLowerThanArmorRating; + float weaponHigherThanArmorRating; + float woundChance; + float woundPercent; + float shockWoundPercent; + int numCombatStates; + + int debugQueues; + int debugTargeting; + int debugAttack; + int debugDefense; + int debugDamage; + int debugExplosion; + }; + +public: + + static void install (void); + static void remove (void); + + static int getMaxAims(void); + static int getNumberSkeletons(void); + static const SkeletonAttackMod & getSkeletonAttackMod(ServerTangibleObjectTemplate::CombatSkeleton skeleton); + static float getKineticObjectDamage(void); + static float getEnergyObjectDamage(void); + static float getBlastObjectDamage(void); + static float getStunObjectDamage(void); + static float getRestraintObjectDamage(void); + static float getElementalObjectDamage(void); + static float getObjectDamageSpread(ServerWeaponObjectTemplate::DamageType damageType); + static float getWoundChance(void); + static float getWoundPercent(void); + static float getShockWoundPercent(void); + + static int getDebugQueues(void); + static int getDebugTargeting(void); + static int getDebugAttack(void); + static int getDebugDefense(void); + static int getDebugDamage(void); + static int getDebugExplosion(void); + +private: + + static Data m_data; +// static ConfigCombatEngineData::BodyAttackMod m_bodyAttackMod; +// static SkeletonAttackMod m_skeletonAttackMod; + static float m_RatingDifferenceDamageReduction[ServerWeaponObjectTemplate::ArmorRating_Last+1][ServerArmorTemplate::ArmorRating_Last+1]; //lint !e641 converting enum to int + + static void installFromConfigFile(void); + static void parseVersion0(Iff & file); + static void setupRatingDifferenceDamageReduction(void); +}; + + +//----------------------------------------------------------------------- + +inline int ConfigCombatEngine::getMaxAims(void) +{ + return m_data.maxAims; +} // ConfigCombatEngine::getMaxAims + +inline int ConfigCombatEngine::getNumberSkeletons(void) +{ + return m_data.numberSkeletons; +} // ConfigCombatEngine::getNumberSkeletons + +inline const ConfigCombatEngine::SkeletonAttackMod & + ConfigCombatEngine::getSkeletonAttackMod( + ServerTangibleObjectTemplate::CombatSkeleton skeleton) +{ + int sk = static_cast(skeleton); + if (sk < 0 || static_cast(skeleton) >= + m_data.skeletonAttackMods.size()) + { + WARNING_STRICT_FATAL(true, ("ConfigCombatEngine::SkeletonAttackMod " + "requested invalid skeleton %d", skeleton)); + // if we're not strict, use the default skeleton values + skeleton = ServerTangibleObjectTemplate::CS_none; + } + return m_data.skeletonAttackMods[skeleton]; //lint !e641 Converting enum CombatSkeleton to int +} // ConfigCombatEngine::getSkeletonAttackMods + +inline float ConfigCombatEngine::getKineticObjectDamage(void) +{ + return m_data.kineticObjectDamage; +} // ConfigCombatEngine::getKineticObjectDamage + +inline float ConfigCombatEngine::getEnergyObjectDamage(void) +{ + return m_data.energyObjectDamage; +} // ConfigCombatEngine::getEnergyObjectDamage + +inline float ConfigCombatEngine::getBlastObjectDamage(void) +{ + return m_data.blastObjectDamage; +} // ConfigCombatEngine::getBlastObjectDamage + +inline float ConfigCombatEngine::getStunObjectDamage(void) +{ + return m_data.stunObjectDamage; +} // ConfigCombatEngine::getStunObjectDamage + +inline float ConfigCombatEngine::getRestraintObjectDamage(void) +{ + return m_data.restraintObjectDamage; +} // ConfigCombatEngine::getRestraintObjectDamage + +inline float ConfigCombatEngine::getElementalObjectDamage(void) +{ + return m_data.elementalObjectDamage; +} // ConfigCombatEngine::getElementalObjectDamage + +inline float ConfigCombatEngine::getWoundChance(void) +{ + return m_data.woundChance; +} // ConfigCombatEngine::getWoundChance + +inline float ConfigCombatEngine::getWoundPercent(void) +{ + return m_data.woundPercent; +} // ConfigCombatEngine::getWoundPercent + +inline float ConfigCombatEngine::getShockWoundPercent(void) +{ + return m_data.shockWoundPercent; +} // ConfigCombatEngine::getShockWoundPercent + +inline int ConfigCombatEngine::getDebugQueues(void) +{ + return m_data.debugQueues; +} // ConfigCombatEngine::getDebugQueues + +inline int ConfigCombatEngine::getDebugTargeting(void) +{ + return m_data.debugTargeting; +} // ConfigCombatEngine::getDebugTargeting + +inline int ConfigCombatEngine::getDebugAttack(void) +{ + return m_data.debugAttack; +} // ConfigCombatEngine::getDebugAttack + +inline int ConfigCombatEngine::getDebugDefense(void) +{ + return m_data.debugDefense; +} // ConfigCombatEngine::getDebugDefense + +inline int ConfigCombatEngine::getDebugDamage(void) +{ + return m_data.debugDamage; +} // ConfigCombatEngine::getDebugDamage + +inline int ConfigCombatEngine::getDebugExplosion(void) +{ + return m_data.debugExplosion; +} // ConfigCombatEngine::getDebugExplosion + +//----------------------------------------------------------------------- + + +#endif // _INCLUDED_ConfigCombatEngine_H diff --git a/game/server/application/SwgGameServer/src/shared/combat/combat.def b/game/server/application/SwgGameServer/src/shared/combat/combat.def new file mode 100644 index 00000000..a8d3d8d2 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/combat/combat.def @@ -0,0 +1,32 @@ +// ====================================================================== +// +// combat.def +// copyright (c) 2001 Sony Online Entertainment +// +// ***IMPORTTANT: This file is mirrored in dsrc/include +// +// ====================================================================== + +#ifndef INCLUDED_combat_DEF +#define INCLUDED_combat_DEF + +// id's for combat skeleton "bones" so when we know where a creature got hit we know what +// item was protecting that area +// +// IMPORTANT: the skeleton location names in the combat.cfg file should map to these +// +enum CombatSkeletonBone +{ + CSB_body = 0x0001, + CSB_head = 0x0002, + CSB_rightArm = 0x0004, + CSB_leftArm = 0x0008, + CSB_rightLeg = 0x0010, + CSB_leftLeg = 0x0020 +}; + + +#endif + + + diff --git a/game/server/application/SwgGameServer/src/shared/console/ConsoleCommandParserCombatEngine.cpp b/game/server/application/SwgGameServer/src/shared/console/ConsoleCommandParserCombatEngine.cpp new file mode 100644 index 00000000..021b77b6 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/console/ConsoleCommandParserCombatEngine.cpp @@ -0,0 +1,73 @@ +// ====================================================================== +// +// ConsoleCommandParserCombatEngine.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstSwgGameServer.h" +#include "CombatEngine.h" + +#include "UnicodeUtils.h" +#include "ConsoleCommandParserCombatEngine.h" +#include "ConsoleCommandParserCombatEngineQueue.h" +#include "serverGame/ServerWorld.h" +#include "serverGame/CreatureController.h" +#include "serverGame/CreatureObject.h" +#include "serverGame/WeaponObject.h" + +#include + + +// ====================================================================== + +static const CommandParser::CmdInfo cmds[] = +{ + {"reload", 0, "", "Reloads the combat data from the config file."}, + {"", 0, "", ""} // this must be last +}; + + +//----------------------------------------------------------------- + +ConsoleCommandParserCombatEngine::ConsoleCommandParserCombatEngine (void) : +CommandParser ("combat", 0, "...", "Combat related commands.", 0) +{ + createDelegateCommands (cmds); + IGNORE_RETURN(addSubCommand(new ConsoleCommandParserCombatEngineQueue()));//lint !e1524 (owned by the base class command parser) +} + +//----------------------------------------------------------------- + +bool ConsoleCommandParserCombatEngine::performParsing (const NetworkId & userId, const StringVector_t & argv, const String_t & originalCommand, String_t & result, const CommandParser * node) +{ + NOT_NULL (node); + UNREF (userId); + + UNREF(originalCommand); + + //----------------------------------------------------------------- + if (isAbbrev( argv [0], "reload")) + { + if (CombatEngine::reloadCombatData()) + result += getErrorMessage(argv[0], ERR_SUCCESS); + else + result += getErrorMessage(argv[0], ERR_NO_ERROR_MSG); + } + + //----------------------------------------------------------------- + + else + { + result += getErrorMessage(argv[0], ERR_NO_HANDLER); + } + + return true; +} + +// --------------------------------------------------------------------- + + + + +// ====================================================================== diff --git a/game/server/application/SwgGameServer/src/shared/console/ConsoleCommandParserCombatEngine.h b/game/server/application/SwgGameServer/src/shared/console/ConsoleCommandParserCombatEngine.h new file mode 100644 index 00000000..45095b16 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/console/ConsoleCommandParserCombatEngine.h @@ -0,0 +1,48 @@ +// ====================================================================== +// +// ConsoleCommandParserCombatEngine.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_ConsoleCommandParserCombatEngine_H +#define INCLUDED_ConsoleCommandParserCombatEngine_H + +#include "sharedCommandParser/CommandParser.h" + +// ====================================================================== + +/** +* Commands that are related to the combat engine +*/ + +class ConsoleCommandParserCombatEngine : public CommandParser +{ +public: + ConsoleCommandParserCombatEngine (); + virtual bool performParsing (const NetworkId & userId, + const StringVector_t & argv, + const String_t & originalCommand, + String_t & result, + const CommandParser * node); + +private: + ConsoleCommandParserCombatEngine (const ConsoleCommandParserCombatEngine & rhs); + ConsoleCommandParserCombatEngine & operator= (const ConsoleCommandParserCombatEngine & rhs); +}; + +// ====================================================================== + +#endif // INCLUDED_ConsoleCommandParserCombatEngine_H + + + + + + + + + + + + diff --git a/game/server/application/SwgGameServer/src/shared/console/ConsoleCommandParserCombatEngineQueue.cpp b/game/server/application/SwgGameServer/src/shared/console/ConsoleCommandParserCombatEngineQueue.cpp new file mode 100644 index 00000000..a38c78c2 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/console/ConsoleCommandParserCombatEngineQueue.cpp @@ -0,0 +1,198 @@ +// ====================================================================== +// +// ConsoleCommandParserCombatEngineQueue.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstSwgGameServer.h" +#include "ConsoleCommandParserCombatEngineQueue.h" + +#include "CombatEngine.h" +#include "UnicodeUtils.h" +#include "serverGame/ServerWorld.h" +#include "serverGame/CreatureObject.h" +#include "serverGame/TangibleObject.h" +#include "sharedFoundation/NetworkIdArchive.h" + +// ====================================================================== + +static const CommandParser::CmdInfo cmds[] = +{ + {"target", 1, "", "Target an object (oid 0 = no target)."}, + {"attack", 0, " ", "Attack current target with weapon."}, + {"aim", 0, "", "Add aim."}, + {"attitude", 1, "", "Change combat attitude (queued)."}, + {"posture", 1, "", "Change combat posture (queued)."}, + {"", 0, "", ""} // this must be last +}; + + +//----------------------------------------------------------------- + +ConsoleCommandParserCombatEngineQueue::ConsoleCommandParserCombatEngineQueue (void) : +CommandParser ("queue", 0, "...", "Action queue commands.", 0) +{ + createDelegateCommands (cmds); +} + +//----------------------------------------------------------------- + + +bool ConsoleCommandParserCombatEngineQueue::performParsing (const NetworkId & userId, + const StringVector_t & argv, const String_t & originalCommand, String_t & result, + const CommandParser * node) +{ + NOT_NULL (node); + UNREF (userId); + + UNREF(originalCommand); + + //----------------------------------------------------------------- + if (isAbbrev( argv [0], "target")) + { + Object *object = ServerWorld::findObjectByNetworkId(userId); + if (! object) + { + result += getErrorMessage(argv[0], ERR_INVALID_USER); + return true; + } + TangibleObject *attacker = dynamic_cast(object); + if (! attacker) + { + result += getErrorMessage(argv[0], ERR_BAD_ATTACKER); + return true; + } + + CombatEngineData::TargetIdList targets; + CachedNetworkId oid((Unicode::wideToNarrow(argv[1]))); //lint !e747 Info: 747 - Significant prototype coercion (arg. no. 1) int to long long + if (oid.getValue() != 0) + { + targets.push_back(oid); + } + + if (CombatEngine::addTargetAction(*attacker, targets)) + result += getErrorMessage(argv[0], ERR_SUCCESS); + else + result += getErrorMessage(argv[0], ERR_QUEUE_COMMAND_FAIL); + } + + //----------------------------------------------------------------- + + else if (isAbbrev( argv [0], "attack")) + { + Object *object = ServerWorld::findObjectByNetworkId(userId); + if (! object) + { + result += getErrorMessage(argv[0], ERR_INVALID_USER); + return true; + } + TangibleObject *attacker = dynamic_cast(object); + if (! attacker) + { + result += getErrorMessage(argv[0], ERR_BAD_ATTACKER); + return true; + } + + NetworkId weapon; + unsigned int mode = 0; + if (argv.size() >= 2) + weapon = NetworkId(Unicode::wideToNarrow(argv[1])); + if (argv.size() >= 3) + mode = strtoul(Unicode::wideToNarrow(argv[2]).c_str (), 0, 10); + if (CombatEngine::addAttackAction(*attacker, weapon, static_cast(mode))) + result += getErrorMessage(argv[0], ERR_SUCCESS); + else + result += getErrorMessage(argv[0], ERR_QUEUE_COMMAND_FAIL); + } + + //----------------------------------------------------------------- + + else if (isAbbrev( argv [0], "aim")) + { + Object *object = ServerWorld::findObjectByNetworkId(userId); + if (! object) + { + result += getErrorMessage(argv[0], ERR_INVALID_USER); + return true; + } + TangibleObject *attacker = dynamic_cast(object); + if (! attacker) + { + result += getErrorMessage(argv[0], ERR_BAD_ATTACKER); + return true; + } + + if (CombatEngine::addAimAction(*attacker)) + result += getErrorMessage(argv[0], ERR_SUCCESS); + else + result += getErrorMessage(argv[0], ERR_QUEUE_COMMAND_FAIL); + } + + //----------------------------------------------------------------- + + else if (isAbbrev( argv [0], "attitude")) + { + Object *object = ServerWorld::findObjectByNetworkId(userId); + if (! object) + { + result += getErrorMessage(argv[0], ERR_INVALID_USER); + return true; + } + TangibleObject *attacker = dynamic_cast(object); + if (! attacker) + { + result += getErrorMessage(argv[0], ERR_BAD_ATTACKER); + return true; + } + +// int attitude = strtoul(Unicode::wideToNarrow(argv[1]).c_str (), 0, 10); + +// if (CombatEngine::addAttitudeAction(*attacker, attitude)) +// result += getErrorMessage(argv[0], ERR_SUCCESS); +// else + result += getErrorMessage(argv[0], ERR_QUEUE_COMMAND_FAIL); + } + + //----------------------------------------------------------------- + + else if (isAbbrev( argv [0], "posture")) + { + Object *object = ServerWorld::findObjectByNetworkId(userId); + if (! object) + { + result += getErrorMessage(argv[0], ERR_INVALID_USER); + return true; + } + CreatureObject *attacker = dynamic_cast(object); + if (! attacker) + { + result += getErrorMessage(argv[0], ERR_BAD_ATTACKER); + return true; + } + +// Postures::Enumerator posture = static_cast(strtoul( +// Unicode::wideToNarrow(argv[1]).c_str (), 0, 10)); + +// if (CombatEngine::addPostureAction(*attacker, posture)) +// result += getErrorMessage(argv[0], ERR_SUCCESS); +// else + result += getErrorMessage(argv[0], ERR_QUEUE_COMMAND_FAIL); + } + + //----------------------------------------------------------------- + + else + { + result += getErrorMessage(argv[0], ERR_NO_HANDLER); + } + + return true; +} + +// --------------------------------------------------------------------- + + + + +// ====================================================================== diff --git a/game/server/application/SwgGameServer/src/shared/console/ConsoleCommandParserCombatEngineQueue.h b/game/server/application/SwgGameServer/src/shared/console/ConsoleCommandParserCombatEngineQueue.h new file mode 100644 index 00000000..e3c33f39 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/console/ConsoleCommandParserCombatEngineQueue.h @@ -0,0 +1,48 @@ +// ====================================================================== +// +// ConsoleCommandParserCombatEngineQueue.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_ConsoleCommandParserCombatEngineQueue_H +#define INCLUDED_ConsoleCommandParserCombatEngineQueue_H + +#include "sharedCommandParser/CommandParser.h" + +// ====================================================================== + +/** +* Commands that are related to the combat engine +*/ + +class ConsoleCommandParserCombatEngineQueue : public CommandParser +{ +public: + ConsoleCommandParserCombatEngineQueue (); + virtual bool performParsing (const NetworkId & userId, + const StringVector_t & argv, + const String_t & originalCommand, + String_t & result, + const CommandParser * node); + +private: + ConsoleCommandParserCombatEngineQueue (const ConsoleCommandParserCombatEngineQueue & rhs); + ConsoleCommandParserCombatEngineQueue & operator= (const ConsoleCommandParserCombatEngineQueue & rhs); +}; + +// ====================================================================== + +#endif // INCLUDED_ConsoleCommandParserCombatEngineQueue_H + + + + + + + + + + + + diff --git a/game/server/application/SwgGameServer/src/shared/controller/JediManagerController.cpp b/game/server/application/SwgGameServer/src/shared/controller/JediManagerController.cpp new file mode 100644 index 00000000..80099996 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/controller/JediManagerController.cpp @@ -0,0 +1,205 @@ +//======================================================================== +// +// JediManagerController.cpp +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#include "FirstSwgGameServer.h" +#include "SwgGameServer/JediManagerController.h" +#include "sharedNetworkMessages/MessageQueueGenericValueType.h" +#include "SwgGameServer/JediManagerObject.h" +#include "swgServerNetworkMessages/MessageQueueJediData.h" +#include "swgServerNetworkMessages/MessageQueueJediLocation.h" +#include "swgServerNetworkMessages/MessageQueueRequestJediBounty.h" + + +//----------------------------------------------------------------------- + +JediManagerController::JediManagerController(JediManagerObject * newOwner) : + UniverseController(newOwner) +{ +} + +//----------------------------------------------------------------------- + +JediManagerController::~JediManagerController() +{ +} + +//----------------------------------------------------------------------- + +void JediManagerController::handleMessage (const int message, const float value, const MessageQueue::Data* const data, const uint32 flags) +{ + JediManagerObject * owner = dynamic_cast(getOwner()); + NOT_NULL(owner); + + switch (message) + { + case CM_removeJedi: + { + const MessageQueueGenericValueType * const msg = safe_cast *>(data); + if (msg != NULL) + { + owner->removeJedi(msg->getValue()); + } + } + break; + case CM_addJedi: + { + const MessageQueueJediData * const msg = safe_cast(data); + if (msg != NULL) + { + owner->addJedi(msg->getId(), + msg->getName(), + msg->getLocation(), + msg->getScene(), + msg->getVisibility(), + msg->getBountyValue(), + msg->getLevel(), + msg->getHoursAlive(), + msg->getState(), + msg->getSpentJediSkillPoints(), + msg->getFaction() + ); + } + } + break; + case CM_updateJedi: + { + const MessageQueueJediData * const msg = safe_cast(data); + if (msg != NULL) + { + owner->updateJedi(msg->getId(), + msg->getVisibility(), + msg->getBountyValue(), + msg->getLevel(), + msg->getHoursAlive() + ); + } + } + break; + case CM_updateJediState: + { + const MessageQueueGenericValueType > * const msg = safe_cast > *>(data); + if (msg != NULL) + { + owner->updateJedi(msg->getValue().first, + static_cast(msg->getValue().second) + ); + } + } + break; + case CM_updateJediBounties: + { +/* + const MessageQueueGenericValueType > > * const msg = safe_cast > > *>(data); + if (msg != NULL) + { + owner->updateJedi(msg->getValue().first, + msg->getValue().second + ); + } +*/ + } + break; + case CM_updateJediLocation: + { + const MessageQueueJediLocation * const msg = safe_cast(data); + if (msg != NULL) + { + owner->updateJediLocation(msg->getId(), + msg->getLocation(), + msg->getScene() + ); + } + } + break; + case CM_setJediOffline: + { + const MessageQueueJediLocation * const msg = safe_cast(data); + if (msg != NULL) + { + owner->setJediOffline(msg->getId(), + msg->getLocation(), + msg->getScene() + ); + } + } + break; + case CM_requestJediBounty: + { + const MessageQueueRequestJediBounty * const msg = safe_cast(data); + if (msg != NULL) + { + owner->requestJediBounty(msg->getTargetId(), + msg->getHunterId(), + msg->getSuccessCallback(), + msg->getFailCallback(), + msg->getCallbackObjectId() + ); + } + } + break; + case CM_removeJediBounty: + { + const MessageQueueGenericValueType > * const msg = safe_cast > *>(data); + if (msg != NULL) + { + owner->removeJediBounty(msg->getValue().first, msg->getValue().second); + } + } + break; + case CM_removeAllJediBounties: + { + const MessageQueueGenericValueType * const msg = safe_cast *>(data); + if (msg != NULL) + { + owner->removeAllJediBounties(msg->getValue()); + } + } + break; + case CM_updateJediSpentJediSkillPoints: + { + const MessageQueueGenericValueType > * const msg = safe_cast > *>(data); + if (msg != NULL) + { + owner->updateJediSpentJediSkillPoints(msg->getValue().first, msg->getValue().second); + } + } + break; + case CM_updateJediFaction: + { + const MessageQueueGenericValueType > * const msg = safe_cast > *>(data); + if (msg != NULL) + { + owner->updateJediFaction(msg->getValue().first, msg->getValue().second); + } + } + break; + case CM_updateJediScriptData: + { + const MessageQueueGenericValueType > > * const msg = safe_cast > > *>(data); + if (msg != NULL) + { + owner->updateJediScriptData(msg->getValue().first, msg->getValue().second.first, msg->getValue().second.second); + } + } + break; + case CM_removeJediScriptData: + { + const MessageQueueGenericValueType > * const msg = safe_cast > *>(data); + if (msg != NULL) + { + owner->removeJediScriptData(msg->getValue().first, msg->getValue().second); + } + } + break; + default: + UniverseController::handleMessage(message, value, data, flags); + break; + } +} + +//----------------------------------------------------------------------- diff --git a/game/server/application/SwgGameServer/src/shared/controller/JediManagerController.h b/game/server/application/SwgGameServer/src/shared/controller/JediManagerController.h new file mode 100644 index 00000000..5804367e --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/controller/JediManagerController.h @@ -0,0 +1,42 @@ +//======================================================================== +// +// JediManagerController.h +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#ifndef INCLUDED_JediManagerController_H +#define INCLUDED_JediManagerController_H + +#include "serverGame/UniverseController.h" + +class JediManagerObject; + + +//---------------------------------------------------------------------- + + +/** + * A generic controller for all JediManager Objects. + */ +class JediManagerController : public UniverseController +{ +public: + explicit JediManagerController (JediManagerObject * newOwner); + virtual ~JediManagerController (void); + +protected: + virtual void handleMessage (int message, float value, const MessageQueue::Data* data, uint32 flags); + +private: + JediManagerController (void); + JediManagerController (const JediManagerController & other); + JediManagerController& operator= (const JediManagerController & other); +}; + + +//----------------------------------------------------------------------- + + +#endif // INCLUDED_JediManagerController_H diff --git a/game/server/application/SwgGameServer/src/shared/controller/SwgPlayerCreatureController.cpp b/game/server/application/SwgGameServer/src/shared/controller/SwgPlayerCreatureController.cpp new file mode 100644 index 00000000..dea874be --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/controller/SwgPlayerCreatureController.cpp @@ -0,0 +1,55 @@ +// ====================================================================== +// +// SwgPlayerCreatureController.cpp +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstSwgGameServer.h" +#include "SwgGameServer/SwgPlayerCreatureController.h" + +#include "sharedNetworkMessages/MessageQueueGenericValueType.h" +#include "SwgGameServer/SwgCreatureObject.h" +#include "SwgGameServer/SwgPlayerObject.h" + + +// ====================================================================== + +SwgPlayerCreatureController::SwgPlayerCreatureController(SwgCreatureObject *newOwner) : + PlayerCreatureController(newOwner) +{ +} + +// ---------------------------------------------------------------------- + +SwgPlayerCreatureController::~SwgPlayerCreatureController() +{ +} + +// ---------------------------------------------------------------------- + +void SwgPlayerCreatureController::handleMessage (const int message, const float value, const MessageQueue::Data* const data, const uint32 flags) +{ + SwgCreatureObject * const owner = safe_cast(getOwner()); + SwgPlayerObject * playerOwner = safe_cast(getPlayerObject(owner)); + NOT_NULL(playerOwner); + + switch (message) + { + case CM_setJediState: + { + const MessageQueueGenericValueType * const msg = dynamic_cast *>(data); + if (msg != NULL) + playerOwner->setJediState(static_cast(msg->getValue())); + } + break; + + default: + PlayerCreatureController::handleMessage(message, value, data, flags); + break; + } +} + +// ---------------------------------------------------------------------- + diff --git a/game/server/application/SwgGameServer/src/shared/controller/SwgPlayerCreatureController.h b/game/server/application/SwgGameServer/src/shared/controller/SwgPlayerCreatureController.h new file mode 100644 index 00000000..e7b668cf --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/controller/SwgPlayerCreatureController.h @@ -0,0 +1,43 @@ +//======================================================================== +// +// SwgPlayerCreatureController.h +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#ifndef INCLUDED_SwgPlayerCreatureController_H +#define INCLUDED_SwgPlayerCreatureController_H + +//----------------------------------------------------------------------- + +#include "serverGame/PlayerCreatureController.h" + + +//----------------------------------------------------------------------- + +class SwgCreatureObject; + + +//----------------------------------------------------------------------- + +class SwgPlayerCreatureController : public PlayerCreatureController +{ +public: + explicit SwgPlayerCreatureController (SwgCreatureObject * newOwner); + ~SwgPlayerCreatureController (); + +protected: + virtual void handleMessage (int message, float value, const MessageQueue::Data* data, uint32 flags); + +private: + // Disabled. + SwgPlayerCreatureController (void); + SwgPlayerCreatureController (const SwgPlayerCreatureController & other); + SwgPlayerCreatureController& operator= (const SwgPlayerCreatureController & other); +}; + +//-------------------------------------------------------------------- + +#endif // INCLUDED_SwgPlayerCreatureController_H + diff --git a/game/server/application/SwgGameServer/src/shared/core/CSHandler.cpp b/game/server/application/SwgGameServer/src/shared/core/CSHandler.cpp new file mode 100644 index 00000000..d51dbfb2 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/core/CSHandler.cpp @@ -0,0 +1,1517 @@ +// CSHandler.cpp +//-------------------------- +// Copyright 2005 Sony Online Entertainment + +#include "FirstSwgGameServer.h" +#include "CSHandler.h" + +#include "serverGame/ConfigServerGame.h" +#include "serverGame/ConsoleManager.h" +#include "serverGame/ContainerInterface.h" +#include "serverGame/CreatureObject.h" +#include "serverGame/NameManager.h" +#include "serverGame/PlayerCreationManagerServer.h" +#include "serverGame/PlayerCreatureController.h" +#include "serverGame/PlayerObject.h" +#include "serverGame/ServerObject.h" +#include "serverGame/ServerWorld.h" +#include "serverGame/ShipObject.h" +#include "serverNetworkMessages/GameServerCSRequestMessage.h" +#include "serverNetworkMessages/GameServerCSResponseMessage.h" +#include "serverNetworkMessages/RenameCharacterMessage.h" +#include "serverScript/GameScriptObject.h" +#include "serverScript/JavaLibrary.h" +#include "serverScript/ScriptParameters.h" +#include "sharedFoundation/DynamicVariableList.h" +#include "sharedFoundation/DynamicVariableListNestedList.h" +#include "sharedFoundation/DynamicVariableLocationData.h" +#include "sharedLog/Log.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "sharedObject/SlottedContainer.h" +#include "sharedObject/VolumeContainer.h" +#include "SwgGameServer.h" +#include "Unicode.h" +#include "UnicodeUtils.h" + +#define REGISTER_CS_CMD(_name_,_access_) \ + CSHandlerNamespace::cmdMap[ #_name_ ] = CSHandlerEntry( #_name_, _access_, &CSHandler::handle_##_name_ ); + +#define CS_CMD(_name_) void CSHandler::handle_##_name_( CSHandlerRequest & request, GameServerCSResponseMessage & msg ) + +namespace CSHandlerNamespace +{ + const int smallBufferSize = 64; + const int largeBufferSize = 256; + + typedef std::map< std::string, std::string > CSLogData; + typedef std::vector< std::string > CSArgs; + std::map< std::string, CSHandlerEntry > cmdMap; + + // from CommandCppFuncs.cpp + ShipObject const *getFirstPackedShipForCreature(CreatureObject const &creature) + { + ServerObject const * const datapad = creature.getDatapad(); + if (datapad) + { + Container const * const container = ContainerInterface::getContainer(*datapad); + if (container) + { + for (ContainerConstIterator i = container->begin(); i != container->end(); ++i) + { + ServerObject const * const content = safe_cast((*i).getObject()); + if ( content + && content->getGameObjectType() == SharedObjectTemplate::GOT_data_ship_control_device + && !content->isBeingDestroyed()) + { + Container const * const scdContainer = ContainerInterface::getContainer(*content); + if (scdContainer) + { + for (ContainerConstIterator j = scdContainer->begin(); j != scdContainer->end(); ++j) + { + ServerObject const * const scdContent = safe_cast((*j).getObject()); + if (scdContent && !scdContent->isBeingDestroyed() && scdContent->asShipObject()) + return scdContent->asShipObject(); + } + } + } + } + } + } + return 0; + } + + std::string getOneArg( std::string input, unsigned &position ) + { + unsigned pos; // where we stop looking + unsigned lastpos; // the last character in our argument. + // bounds checking. + if( position < 0 || position >= input.length() ) + { + return ""; + } + // skip whitespace + while( input[ position ] == ' ' && position < input.length() ) + { + ++position; + } + + if( position == input.length() ) + return ""; + // see if the first character is a quote. + if( input[ position ] == '"' ) + { + // if it is... + // skip over the quote. + pos = ++position; + // look for the next quote. + while( 1 ) + { + pos = input.find( '"', pos ); + // if we don't find one, assume the end of the line. + if( pos == std::string::npos ) + { + pos = input.length(); + lastpos = pos - 1; + break; + } + else + { + // and verify that it's not preceded by a backslash. + if( input[ pos - 1 ] != '\\' ) + { + lastpos = pos; + break; + } + else + { + pos++; + } + } + } + } + else + { + // otherwise, just look for a space. + pos = input.find( ' ', position ); + // if we don't find a space, assume the end of the line. + if( pos == std::string::npos ) + { + pos = input.length(); + } + lastpos = pos; + } + + + // build the string. + std::string output = input.substr( position, lastpos - position ); + + // modify the position. Assume that the caller will do bounds checking. + position = pos + 1; + return output; + + } + + void getArgs( std::string input, std::vector< std::string > & output ) + { + unsigned pos = 0; + while ( pos < input.length() ) + { + std::string temp = getOneArg( input, pos ); + output.push_back( temp ); + } + } + void log( CSLogData & data ) + { + std::string logline = ""; + bool b_first = true; + for( CSLogData::iterator it = data.begin(); it != data.end(); ++it ) + { + if( b_first ) + { + b_first = false; + } + else + { + logline += ";"; + } + logline = logline + it->first + "=" + it->second; + } + LOG( "CustomerService", ( "CSTool: %s", logline.c_str() ) ); + } + + void log( CSHandlerRequest &req, CSLogData &data ) + { + // add the additional fields and pass to log. + data[ "user" ] = req.m_name; + log( data ); + } + + void addObjVarToString( std::string & response, + const std::string & prefix, + DynamicVariableList::NestedList::const_iterator &objVar ) + { + char buffer[ smallBufferSize ]; + + // print the data + switch (objVar.getType()) + { + case DynamicVariable::INT: + { + int value=0; + objVar.getValue(value); + IGNORE_RETURN(_itoa(value, buffer, 10)); + // print the name + response += prefix + objVar.getName(); + response += ":"; + response += buffer; + response += "\r\n"; + } + break; + case DynamicVariable::INT_ARRAY: + { + std::vector value; + objVar.getValue(value); + std::string text = "["; + size_t count = value.size(); + for (size_t j = 0; j < count; ++j) + { + IGNORE_RETURN(_itoa(value[j], buffer, 10)); + text += buffer; + if (j + 1 < count) + text += ", "; + } + text += "]\r\n"; + // print the name + response += prefix + objVar.getName(); + response += ":"; + response += text; + } + break; + case DynamicVariable::REAL: + { + real value = 0; + objVar.getValue(value); + snprintf(buffer, sizeof( buffer ) -1 , "%f\r\n", value); + buffer[ sizeof( buffer ) -1 ] = 0; + // print the name + response += prefix + objVar.getName(); + response += ":"; + + response += buffer; + } + break; + case DynamicVariable::REAL_ARRAY: + { + std::vector value; + objVar.getValue(value); + std::string text = "["; + size_t count = value.size(); + for (size_t j = 0; j < count; ++j) + { + snprintf(buffer, sizeof( buffer ) - 1, "%f", value[j]); + buffer[ sizeof( buffer ) - 1 ] = 0; + text += buffer; + if (j + 1 < count) + text += ", "; + } + text += "]\n"; + // print the name + response += prefix + objVar.getName(); + response += ":"; + + response += text; + } + break; + case DynamicVariable::STRING: + { + Unicode::String value; + objVar.getValue(value); + // print the name + response += prefix + objVar.getName(); + response += ":"; + + response += Unicode::wideToNarrow( value ); + response += "\r\n"; + } + break; + case DynamicVariable::STRING_ARRAY: + { + // print the name + response += prefix + objVar.getName(); + response += ":"; + + std::vector value; + objVar.getValue(value); + response += "[[\r\n"; + size_t count = value.size(); + for (size_t j = 0; j < count; ++j) + { + response += Unicode::wideToNarrow( value[j] ); + response += "\r\n"; + } + response += "]]\r\n"; + } + break; + case DynamicVariable::NETWORK_ID: + { + // print the name + response += prefix + objVar.getName(); + response += ":"; + + NetworkId value; + objVar.getValue(value); + response += "(NetworkId)"; + response += value.getValueString(); + response += "\r\n"; + } + break; + case DynamicVariable::NETWORK_ID_ARRAY: + { + // print the name + response += prefix + objVar.getName(); + response += ":"; + + std::vector value; + objVar.getValue(value); + std::string text = "(NetworkId)["; + size_t count = value.size(); + for (size_t j = 0; j < count; ++j) + { + text += value[j].getValueString(); + if (j + 1 < count) + text += ", "; + } + text += "]\r\n"; + response += text; + } + break; + case DynamicVariable::LOCATION: + { + // print the name + response += prefix + objVar.getName(); + response += ":"; + + DynamicVariableLocationData value; + objVar.getValue(value); + response += "(x="; + snprintf(buffer, sizeof( buffer ) -1 , "%f", value.pos.x); + buffer[ sizeof( buffer ) - 1 ] = 0; + response += buffer; + response += ", y="; + snprintf(buffer, sizeof( buffer ) - 1, "%f", value.pos.y); + buffer[ sizeof( buffer ) - 1 ] = 0; + response += buffer; + response += ", z="; + snprintf(buffer, sizeof( buffer ) - 1, "%f", value.pos.z); + buffer[ sizeof( buffer ) - 1 ] = 0; + response += buffer; + response += ", scene="; + response += value.scene; + response += ", cell="; + response += value.cell.getValueString(); + response += ")\r\n"; + } + break; + case DynamicVariable::LOCATION_ARRAY: + { + // print the name + response += prefix + objVar.getName(); + response += ":"; + + std::vector value; + objVar.getValue(value); + int k; + int nameLength = objVar.getName().size(); + response += "[\r\n"; + size_t count = value.size(); + for (size_t j = 0; j < count; ++j) + { + for (k = 0; k < nameLength; ++k) + response += " "; + response += "(x="; + snprintf(buffer, sizeof( buffer ) - 1, "%f", value[ j ].pos.x); + buffer[ sizeof( buffer ) - 1 ] = 0; + response += buffer; + response += ", y="; + snprintf(buffer, sizeof( buffer ) - 1, "%f", value[ j ].pos.y); + buffer[ sizeof( buffer ) - 1 ] = 0; + response += buffer; + response += ", z="; + snprintf(buffer, sizeof( buffer ) - 1, "%f", value[ j ].pos.z); + buffer[ sizeof( buffer ) - 1 ] = 0; + response += buffer; + response += ", scene="; + response += value[ j ].scene; + response += ", cell="; + response += value[ j ].cell.getValueString(); + // response += ")\r\n"; } + for (k = 0; k < nameLength; ++k) + response += " "; + response += "]\r\n"; + } + } + break; + case DynamicVariable::LIST: + { + // call recursively + std::string newPrefix = prefix + objVar.getName() + "."; + const DynamicVariableList::NestedList &list = objVar.getNestedList(); + for(DynamicVariableList::NestedList::const_iterator newObjvar = list.begin(); + newObjvar != list.end(); + ++newObjvar) + { + addObjVarToString( response, newPrefix, newObjvar ); + } + } + break; + case DynamicVariable::STRING_ID: + { + StringId value; + objVar.getValue(value); + response += "(StringId)"; + response += value.getDebugString(); + response += "\r\n"; + } + break; + case DynamicVariable::STRING_ID_ARRAY: + { + std::vector value; + objVar.getValue(value); + std::string text = "(StringId)["; + size_t count = value.size(); + for (size_t j = 0; j < count; ++j) + { + text += value[j].getDebugString(); + if (j + 1 < count) + text += ", "; + } + text += "]\r\n"; + response += text; + } + break; + case DynamicVariable::TRANSFORM: + { + Transform value; + objVar.getValue(value); + response += "(Transform)"; + //response += getDebugString(value); + response += "\r\n"; + } + break; + case DynamicVariable::TRANSFORM_ARRAY: + { + std::vector value; + objVar.getValue(value); + std::string text = "(Transform)["; + size_t count = value.size(); + for (size_t j = 0; j < count; ++j) + { + // text += getDebugString(value[j]); + if (j + 1 < count) + text += ", "; + } + text += "]\r\n"; + response += text; + } + break; + case DynamicVariable::VECTOR: + { + Vector value; + objVar.getValue(value); + response += "(Vector)"; + // response += getDebugString(value); + response += "\r\n"; + } + break; + case DynamicVariable::VECTOR_ARRAY: + { + std::vector value; + objVar.getValue(value); + std::string text = "(Vector)["; + size_t count = value.size(); + for (size_t j = 0; j < count; ++j) + { + // text += getDebugString(value[j]); + if (j + 1 < count) + text += ", "; + } + text += "]\n"; + response += text; + } + break; + } + + } + + void addItemInfo(const VolumeContainer * container, int & num, std::map & stats) + { + if(!container) + return; + char stringbuffer[CSHandlerNamespace::largeBufferSize]; + std::vector objList; + for (ContainerConstIterator iter(container->begin()); + iter != container->end(); ++iter) + { + char catbuffer[ CSHandlerNamespace::smallBufferSize ]; + const CachedNetworkId & objId = (*iter); + const TangibleObject * obj = safe_cast(objId.getObject()); + std::string category = "Item-"; + snprintf( catbuffer, sizeof( catbuffer ) - 1, "%s%d", category.c_str(), num++ ); + catbuffer[ sizeof( catbuffer ) -1 ] = 0; + snprintf( stringbuffer, sizeof( stringbuffer ) - 1, "%s(%s)", Unicode::wideToNarrow( obj->getObjectName() ).c_str(), + obj->getNetworkId().getValueString().c_str() ); + stringbuffer[ sizeof( stringbuffer ) - 1 ] = 0; + stats[ catbuffer ] = stringbuffer; + + // recurse if necessary. + const VolumeContainer * obj_as_container = ContainerInterface::getVolumeContainer(*obj); + if( obj_as_container ) + { + addItemInfo( obj_as_container, num, stats ); + } + } + } +} + +CSHandler* CSHandler::sm_instance = 0; + +CSHandler::CSHandler() +{ + registerCommands(); +} + +CSHandler::~ CSHandler() +{ +} + +void CSHandler::install() +{ + if( !sm_instance ) + sm_instance = new CSHandler(); + +} + +void CSHandler::remove() +{ + if( sm_instance ) + delete sm_instance; +} + +CSHandler & CSHandler::getInstance() +{ + NOT_NULL( sm_instance ); + return *sm_instance; +} + +void CSHandler::handle( GameServerCSRequestMessage & request ) +{ + DEBUG_REPORT_LOG( true, ( "Handling command" ) ); + const std::string &original = request.getCommandString(); + std::string command; + std::string args; + + unsigned pos = original.find( " " ); + if( pos == std::string::npos ) + { + command = original; + } + else + { + command = original.substr( 0, pos ); + args = original.substr( pos + 1, original.length() - ( pos + 1 ) ); + } + + DEBUG_REPORT_LOG( true, ( "Command is %s", command.c_str() ) ); + + // find the command + std::map< std::string, CSHandlerEntry >::iterator it = CSHandlerNamespace::cmdMap.find( command ); + if( it != CSHandlerNamespace::cmdMap.end() ) + { + // build the proto-response + GameServerCSResponseMessage msg( request ); + + std::string username = request.getUserName(); + + // build the cs request + CSHandlerRequest req( command, args, request.getAccessLevel(), username ); + + // check the access + if( req.m_access >= it->second.access ) + { + // and fire it off. + CSHandlerFunc func = it->second.handlerFunc; + ( this->*func )( req, msg ); + } + + } + else + { + // try passing it off to the console parser. + //ConsoleMgr::processStringForCSHandler( original ); + // JavaLibrary::instance()->runScripts(m_owner->getNetworkId(), funcName, "Ouf", params); + } +} + +void CSHandler::registerCommands() +{ + REGISTER_CS_CMD( get_pc_info, 4 ); + REGISTER_CS_CMD( set_bank_credits, 4 ); + REGISTER_CS_CMD( undelete_item, 4 ); + REGISTER_CS_CMD( list_objvars, 4 ); + REGISTER_CS_CMD( set_objvar, 4 ); + REGISTER_CS_CMD( remove_objvar, 4 ); + REGISTER_CS_CMD( dump_info, 4 ); + REGISTER_CS_CMD( rename_player, 4 ); + + REGISTER_CS_CMD( freeze, 4 ); + REGISTER_CS_CMD( unfreeze, 4 ); + + REGISTER_CS_CMD( get_player_id, 4 ); + REGISTER_CS_CMD( get_player_items, 4 ); + + REGISTER_CS_CMD( move_object, 4 ); + + REGISTER_CS_CMD( create_crafted_object, 4 ); + + REGISTER_CS_CMD( delete_object, 4 ); + + REGISTER_CS_CMD( adjust_lots, 4 ); + + REGISTER_CS_CMD( warp_player, 4 ); +} + +void addIntData( std::map< std::string, std::string > & data, const std::string & stat, int amount ) +{ + char buffer[ CSHandlerNamespace::smallBufferSize ]; + snprintf( buffer, sizeof( buffer ) - 1, "%d", amount ); + buffer[ sizeof( buffer ) - 1 ] = 0; + data[ stat ] = buffer; +} + + + +enum ArgType +{ + STRING_ARGUMENT = 0, + REAL_ARGUMENT, + INT_ARGUMENT +}; + +int getArgumentType(const std::string &arg) +{ + bool foundDecimal = false; + + size_t count = arg.length(); + for (size_t i = 0; i < count; ++i) + { + if (!isdigit(arg[i])) + { + if (arg[i] != '.' || foundDecimal) + return STRING_ARGUMENT; + foundDecimal = true; + } + } + if (foundDecimal) + return REAL_ARGUMENT; + return INT_ARGUMENT; +} + +CS_CMD( warp_player ) +{ + CSHandlerNamespace::CSArgs args; + CSHandlerNamespace::getArgs( request.m_args, args ); + + if( args.size() < 5 ) + return; + + // format: target planet x y z + NetworkId target_id( args[ 0 ] ); + CreatureObject *target = CreatureObject::getCreatureObject( target_id ); + if( !( target && target->isAuthoritative() ) ) + return; + + std::string planet = args[ 1 ]; + float x=0.0f, y=0.0f, z=0.0f; + sscanf( args[2].c_str(), "%f", &x ); + sscanf( args[3].c_str(), "%f", &y ); + sscanf( args[4].c_str(), "%f", &z ); + + Vector newPosition_w(x, y, z); + Vector newPosition_p(0.0f, 0.0f, 0.0f); + NetworkId newContainer; + TangibleObject *targetTangible = target; + + if (targetTangible) + { + if (!ServerWorld::isSpaceScene() && !strncmp(planet.c_str(), "space_", 5) && targetTangible->asCreatureObject()) + { + // don't allow CS Tool to warp to space from ground. + return; + + // NOTE RHanz: This code is commented out due to lack of an obvious unified interface + // for setting up launches (ie, having to manually set objvars) + // to space in this usage case. The code is exactly the same (except var names) + // as the code for planetwarp (in CommandCppFuncs.cpp). If CS actually does need to + // move people from ground to space for admin purposes, you should be able to simply uncomment + // the below section of code. + + //// going to space from the ground, so require a ship and set launch information + //ShipObject const * const ship = CSHandlerNamespace::getFirstPackedShipForCreature(*targetTangible->asCreatureObject()); + //if (!ship) + //{ + // return; + //} + + //DynamicVariableLocationData const loc(targetTangible->getPosition_w(), ServerWorld::getSceneId(), NetworkId::cms_invalid); + //targetTangible->setObjVarItem("space.launch.worldLoc", loc); + //targetTangible->setObjVarItem("space.launch.ship", ship->getNetworkId()); + //targetTangible->setObjVarItem("space.launch.startIndex", static_cast(0)); + } + if(!target->getClient()) + { + // character is in the save queue. This is currently not supported. Planetwarping + // appears to break the PseudoClientConnection system. + msg.setResponse( "Unable to warp player:\r\n" ); + SwgGameServer::getInstance().sendToCentralServer(msg); + return; + } + CSHandlerNamespace::CSLogData data; + data[ "command" ] = "warp_player"; + data[ "target_id" ] = args[ 0 ]; + data[ "planet" ] = args[ 1 ]; + char buf[ CSHandlerNamespace::largeBufferSize ]; + snprintf( buf, CSHandlerNamespace::largeBufferSize,"%.02f %.02f %.02f", x, y, z ); + data[ "location" ] = buf; + GameServer::getInstance().requestSceneWarp(CachedNetworkId(*targetTangible), planet, newPosition_w, newContainer, newPosition_p); + } +} + +CS_CMD( adjust_lots ) +{ + CSHandlerNamespace::CSArgs args; + CSHandlerNamespace::getArgs( request.m_args, args ); + + if( args.size() < 2 ) + return; // not enough arguments. + + NetworkId target_id( args[ 0 ] ); + CreatureObject *target = CreatureObject::getCreatureObject( target_id ); + if( !( target && target->isAuthoritative() ) ) + return; + PlayerObject * player = PlayerCreatureController::getPlayerObject( target ); + if( !player ) + return; // not a player, can't adjust lots. + + int count = atoi( args[ 1 ].c_str() ); + + CSHandlerNamespace::CSLogData data; + data[ "command" ] = "adjust_lots"; + data[ "target_id" ] = args[ 0 ]; + data[ "amount" ] = args[ 1 ]; + CSHandlerNamespace::log( request, data ); + + player->adjustLotCount( count ); + +} + +CS_CMD( create_crafted_object ) +{ + CSHandlerNamespace::CSArgs args; + CSHandlerNamespace::getArgs( request.m_args, args ); + // args should be: + // destination schematic quality + + if( args.size() < 2 ) + return; + + NetworkId target_id( args[ 0 ] ); + CreatureObject *target = CreatureObject::getCreatureObject( target_id ); + if( !( target && target->isAuthoritative() ) ) + return; + ServerObject *inventory = target->getInventory(); + if( inventory == NULL ) + return; + DEBUG_REPORT_LOG( true, ( "Trying to make %s\n", args[ 1 ].c_str())); + GameScriptObject * script = target->getScriptObject(); + if( script ) + { + ScriptParams params; + params.addParam(target_id); + params.addParam(args[ 1 ].c_str()); + script->trigAllScripts(Scripting::TRIG_CS_CREATE_STATIC_ITEM, params); + + } + CSHandlerNamespace::CSLogData data; + data[ "command" ] = "create_crafted_object"; + data[ "target_id" ] = args[ 0 ]; + data[ "schematic" ] = args[ 1 ]; + CSHandlerNamespace::log( request, data ); +} + +// informational command. no logs needed. +CS_CMD( get_player_items ) +{ + std::transform( request.m_args.begin(), request.m_args.end(), request.m_args.begin(), tolower ); + + CSHandlerNamespace::CSArgs args; + CSHandlerNamespace::getArgs( request.m_args, args ); + if( args.size() < 1 ) + return; // no player + + // get the player ID + + + if( args.size() > 0 ) + { + NetworkId player_id = NameManager::getInstance().getPlayerId( args[ 0 ] ); + + // get the object + const CreatureObject* const creatureActor = CreatureObject::getCreatureObject(player_id); + + if( !creatureActor ) + return; + + + // are we authoritative? + if( creatureActor->isAuthoritative() ) + { + // if so, built a list of items + std::string response; + const ServerObject * inventory = creatureActor->getInventory(); + if( inventory ) + { + + std::map< std::string, std::string > stats; + const VolumeContainer * inventoryContainer = ContainerInterface::getVolumeContainer(*inventory); + if (inventoryContainer ) + { + + int item_num = 0; + std::vector objList; + for (ContainerConstIterator iter(inventoryContainer->begin()); + iter != inventoryContainer->end(); ++iter) + { + char catbuffer[ CSHandlerNamespace::smallBufferSize ]; + char stringbuffer[ CSHandlerNamespace::largeBufferSize ]; + const CachedNetworkId & objId = (*iter); + const TangibleObject * obj = safe_cast(objId.getObject()); + std::string category = "Item-"; + snprintf( catbuffer, sizeof( catbuffer ) - 1, "%s%d", category.c_str(), item_num++ ); + snprintf( stringbuffer, sizeof( stringbuffer ) - 1,"%s(%s)", Unicode::wideToNarrow( obj->getObjectName() ).c_str(), + obj->getNetworkId().getValueString().c_str() ); + catbuffer[ sizeof( catbuffer ) - 1 ] = 0; + stringbuffer[ sizeof( stringbuffer ) -1 ] = 0; + stats[ catbuffer ] = stringbuffer; + } + } + // and send it back. + std::map< std::string, std::string >::iterator it = stats.begin(); + response = "item list\r\n"; + while( it != stats.end() ) + { + response = response + it->first + ":" + it->second + "\r\n"; + it++; + } + msg.setResponse( response ); + SwgGameServer::getInstance().sendToCentralServer( msg ); + } + } + } +} + +CS_CMD( move_object ) +{ + CSHandlerNamespace::CSArgs args; + CSHandlerNamespace::getArgs( request.m_args, args ); + if( args.size() < 2 ) + return; + + NetworkId oid( args[ 1 ] ); + NetworkId player( args[ 0 ] ); + + if( !( oid.isValid() && player.isValid() ) ) + return; // bad args or this wasn't confirmed as an offline char. + if (oid < ConfigServerGame::getMaxGoldNetworkId()) + return; + else + { + ServerObject *object = ServerObject::getServerObject( oid ); + if (!( object && object->isAuthoritative() ) ) + return; + else + { + if (!NameManager::getInstance().isPlayer(player)) + return; + else + { + msg.setResponse( "Moving object:\r\n" ); + SwgGameServer::getInstance().sendToCentralServer( msg ); + CSHandlerNamespace::CSLogData data; + data[ "command" ] = "move_object"; + object->moveToPlayerAndUnload(player); + data[ "object" ] = args[ 1 ]; + data[ "target_char" ] = args[ 0 ]; + CSHandlerNamespace::log( request, data ); + + } + } + + } +} + +CS_CMD( freeze ) +{ + DEBUG_REPORT_LOG( true, ( "Trying to freeze\n" ) ); + CSHandlerNamespace::CSArgs args; + CSHandlerNamespace::getArgs( request.m_args, args ); + + if( args.size() < 1 ) + return; + + NetworkId id( args[ 0 ].c_str() ); + if( id.isValid() ) + { + ServerObject * const object = ServerWorld::findObjectByNetworkId(id); + + if( !object ) + return; + if( object->isAuthoritative() ) + { + JavaLibrary::freezePlayer( id ); + CSHandlerNamespace::CSLogData data; + data[ "target" ] = args[ 0 ]; + data[ "command" ] = "freeze"; + CSHandlerNamespace::log( request, data ); + DEBUG_REPORT_LOG( true, ( "really doing freeze %s\n", id.getValueString().c_str() ) ); + } + } + +} + +CS_CMD( unfreeze ) +{ + CSHandlerNamespace::CSArgs args; + CSHandlerNamespace::getArgs( request.m_args, args ); + + if( args.size() < 1 ) + return; + + NetworkId id( args[ 0 ].c_str() ); + if( id.isValid() ) + { + ServerObject * const object = ServerWorld::findObjectByNetworkId(id); + + if( !object ) + return; + if( object->isAuthoritative() ) + { + CSHandlerNamespace::CSLogData data; + data[ "target" ] = args[ 0 ]; + data[ "command" ] = "unfreeze"; + CSHandlerNamespace::log( request, data ); + JavaLibrary::unFreezePlayer( id ); + } + } + +} + +CS_CMD( dump_info ) +{ + // LocalRefPtr local_ref; + DEBUG_REPORT_LOG( true, ( "dump_info" ) ); + NetworkId id( request.m_args ); + if( id.isValid() ) + { + ServerObject * const object = ServerWorld::findObjectByNetworkId(id); + if (object && object->isAuthoritative()) + { + DEBUG_REPORT_LOG( true, ( "Valid ID\n" ) ); + std::string returned_value; + + returned_value = GameScriptObject::callDumpTargetInfo( id ); + std::string response; + response = "Character info dump:\r\n"; + response = response + returned_value; + msg.setResponse( response ); + SwgGameServer::getInstance().sendToCentralServer( msg ); + } + + + } + // JavaStringPtr javaResult= callStaticStringMethod(, getVarNameMid); + // JavaLibrary::convert(*javaCustomVarName, nativeCustomVarName); +} + + +CS_CMD( remove_objvar ) +{ + std::string objid; + std::string objvar; + + CSHandlerNamespace::CSArgs args; + CSHandlerNamespace::getArgs( request.m_args, args ); + if( args.size() < 2 ) + return; + + objid = args[ 0 ]; + objvar = args[ 1 ]; + + NetworkId specifiedNetworkId( objid ); + ServerObject * const object = ServerWorld::findObjectByNetworkId(specifiedNetworkId); + + if( !( object && object->isAuthoritative() ) ) + return; + + object->removeObjVarItem(objvar); + CSHandlerNamespace::CSLogData data; + data[ "target" ] = args[ 0 ]; + data[ "command" ] = "remove_objvar"; + data[ "objvar" ] = args[ 1 ]; + CSHandlerNamespace::log( request, data ); +} + +CS_CMD( set_objvar ) +{ + // set_objvar [itemid] [objvar] [value] + std::string objid; + std::string objvar; + std::string objvarvalue; + + CSHandlerNamespace::CSArgs args; + CSHandlerNamespace::getArgs( request.m_args, args ); + + if( args.size() < 3 ) + { + return; + } + + objid = args[ 0 ]; + objvar = args[ 1 ]; + objvarvalue = args[ 2 ]; + NetworkId specifiedNetworkId( objid ); + ServerObject * const object = ServerWorld::findObjectByNetworkId(specifiedNetworkId); + if( !( object && object->isAuthoritative() ) ) + { + return; + } + + + switch (getArgumentType(objvarvalue)) + { + case INT_ARGUMENT: + object->setObjVarItem(objvar, atoi(objvarvalue.c_str())); + break; + case REAL_ARGUMENT: + object->setObjVarItem(objvar, static_cast(atof(objvarvalue.c_str()))); + break; + case STRING_ARGUMENT: + object->setObjVarItem(objvar, objvarvalue); + break; + default: + break; + } + CSHandlerNamespace::CSLogData data; + data[ "target" ] = args[ 0 ]; + data[ "command" ] = "set_objvar"; + data[ "objvar" ] = args[ 1 ]; + data[ "value" ] = args[ 2 ]; + CSHandlerNamespace::log( request, data ); +} + +// this is kind of sloppy. Code is copied from consolecommandparserobjvar.cpp, and modified to work. +// realistically, it seems like objvars should internally be able to print their own value as a string without +// having to rely on code to do it each time. +CS_CMD( list_objvars ) +{ + DEBUG_REPORT_LOG( true, ( "Got list_objvars command\n" ) ); + CSHandlerNamespace::CSArgs args; + CSHandlerNamespace::getArgs( request.m_args, args ); + + if( args.size() < 1 ) + { + DEBUG_REPORT_LOG( true, ( "not enough args\n" ) ); + return; + } + + + std::string response; + + response = "Objvar list for "; + response = response + args[ 0 ] + "\r\n"; + // get the obj + + + NetworkId specifiedNetworkId = NetworkId(args[ 0 ]); + + ServerObject * const specifiedServerObject = ServerWorld::findObjectByNetworkId(specifiedNetworkId); + // iterate objvars + + if( !( specifiedServerObject && specifiedServerObject->isAuthoritative() ) ) + { + DEBUG_REPORT_LOG( true, ( "Item not found\n" ) ); + return; + } + + DynamicVariableList::NestedList objvarList = specifiedServerObject->getObjVars(); + + // char buffer[ CSHandlerNamespace::smallBufferSize ]; + // add to response string + for (DynamicVariableList::NestedList::const_iterator objVar(objvarList.begin()); objVar!=objvarList.end(); ++objVar) + { + CSHandlerNamespace::addObjVarToString( response, "", objVar ); + } + // send response. + msg.setResponse( response ); + SwgGameServer::getInstance().sendToCentralServer( msg ); + +} + + +CS_CMD( delete_object ) +{ + CSHandlerNamespace::CSArgs args; + CSHandlerNamespace::getArgs( request.m_args, args ); + + if( args.size() < 1 ) + return; + + + const NetworkId oid (args[0]); + ServerObject *object = ServerObject::getServerObject( oid ); + + if (object == NULL) + { + return; + } + else if (object->getClient()) + { + return; + } + else if (!object->isAuthoritative()) + { + return; + } + else + { + CSHandlerNamespace::CSLogData data; + data[ "target" ] = args[ 0 ]; + data[ "command" ] = "delete_object"; + CSHandlerNamespace::log( request, data ); + object->permanentlyDestroy(DeleteReasons::God); + } + return; +} + +CS_CMD( rename_player ) +{ + CSHandlerNamespace::CSArgs args; + DEBUG_REPORT_LOG( true, ( "rename_player" ) ); + CSHandlerNamespace::getArgs( request.m_args, args ); + if( args.size() < 3 ) + { + return; + } + std::transform( args[ 0 ].begin(), args[ 0 ].end(), args[ 0 ].begin(), tolower ); + + + NetworkId player_id = NameManager::getInstance().getPlayerId( args[ 0 ] ); + + // only execute on the authoritative object. exit early for all others + // to avoid spam. + ServerObject *object = ServerObject::getServerObject( player_id ); + if( !( object && object->isAuthoritative() ) ) + { + return; + } + + std::string lowertarget = args[1]; + std::transform( lowertarget.begin(), lowertarget.end(), lowertarget.begin(), tolower ); + + NetworkId target_check = NameManager::getInstance().getPlayerId( lowertarget ); + if( target_check.isValid() ) + { + // invalid name, already used by someone. + msg.setResponse( "Could not rename player, name in use:\r\n" ); + SwgGameServer::getInstance().sendToCentralServer( msg ); + return; + } + if( player_id.isValid() ) + { + // null id to pass to the playercreationmanager. + NetworkId source( "0" ); + + DEBUG_REPORT_LOG( true, ( "Attempting to rename %s.", args[ 0 ].c_str() ) ); + PlayerCreationManagerServer::renamePlayer( static_cast(RenameCharacterMessageEx::RCMS_cs_tool), NameManager::getInstance().getPlayerStationId(player_id), player_id, Unicode::narrowToWide( args[ 1 ] ), object->getAssignedObjectName(), source ); + CSHandlerNamespace::CSLogData data; + msg.setResponse( "Rename player complete:\r\n" ); + SwgGameServer::getInstance().sendToCentralServer( msg ); + data[ "target" ] = args[ 0 ]; + data[ "command" ] = "rename_player"; + data[ "new_name" ] = args[ 1 ]; + CSHandlerNamespace::log( request, data ); + } + else + { + DEBUG_REPORT_LOG( true, ( "Could not rename player. %s not found", args[ 0 ].c_str() ) ); + } + +} + +CS_CMD( set_bank_credits ) +{ + CSHandlerNamespace::CSArgs args; + CSHandlerNamespace::getArgs( request.m_args, args ); + if( args.size() < 2 ) + { + return; + } + + std::transform( args[ 0 ].begin(), args[ 0 ].end(), args[ 0 ].begin(), tolower ); + int amount = atoi( args[ 1 ].c_str() ); + + DEBUG_REPORT_LOG( true, ( "set_bank_credits: %d\n", amount ) ); + NetworkId player_id = NameManager::getInstance().getPlayerId( args[ 0 ] ); + if( player_id.isValid() ) + { + CreatureObject* creatureActor = CreatureObject::getCreatureObject(player_id); + PlayerObject const * const player = PlayerCreatureController::getPlayerObject(creatureActor); + + if( ( player != NULL ) && ( player->isAuthoritative() ) ) + { + amount -= creatureActor->getBankBalance(); + DEBUG_REPORT_LOG( true, ( "Amount to modify by: %d (%d current balance)\n", amount, creatureActor->getBankBalance() ) ); + if( amount < 0 ) + { + DEBUG_REPORT_LOG( true, ( "Transferring to\n" ) ); + creatureActor->transferBankCreditsTo( "cs_" "stub", amount * -1 ); + } + else + { + DEBUG_REPORT_LOG( true, ( "Transferring from\n" ) ); + creatureActor->transferBankCreditsFrom( "cs_" "stub", amount ); + + } + msg.setResponse( "Successfully modified bank amount" ); + CSHandlerNamespace::CSLogData data; + data[ "target" ] = args[ 0 ]; + data[ "command" ] = "set_bank_credits"; + data[ "amount" ] = args[ 1 ]; + CSHandlerNamespace::log( request, data ); + SwgGameServer::getInstance().sendToCentralServer( msg ); + } + } + +} + +CS_CMD( get_pc_info ) +{ + // see if we have the character. + std::transform( request.m_args.begin(), request.m_args.end(), request.m_args.begin(), tolower ); + DEBUG_REPORT_LOG( true, ( "Got get_pc_info for %s\n", request.m_args.c_str() ) ); + NetworkId player_id = NameManager::getInstance().getPlayerId( request.m_args ); + if( player_id.isValid() ) + { + DEBUG_REPORT_LOG( true, ( "Found player.\n" ) ); + // get the info on the player. + const CreatureObject* const creatureActor = CreatureObject::getCreatureObject(player_id); + if (!( creatureActor && creatureActor->isAuthoritative() ) ) + { + return; + } + + char stringbuffer[ CSHandlerNamespace::smallBufferSize ]; // for formatted output. + std::map< std::string, std::string > stats; + + //get the bind location + Vector bindLoc; + std::string bindPlanet; + NetworkId bindId; + if (creatureActor->getObjVars().hasItem("bind.facility")) + { + creatureActor->getObjVars().getItem("bind.facility", bindId); + } + if(bindId != NetworkId::cms_invalid) + { + const ServerObject* const bindObject = ServerObject::getServerObject(bindId); + if (bindObject != NULL) + { + bindLoc = bindObject->getPosition_w(); + snprintf( stringbuffer, sizeof( stringbuffer ) -1, "%02f %02f %02f", bindLoc.x, bindLoc.y, bindLoc.z ); + stringbuffer[ sizeof( stringbuffer ) - 1 ] = 0; + stats[ "Bind Location" ] = stringbuffer; + bindPlanet = bindObject->getSceneId(); + stats[ "Bind Planet" ] = bindPlanet; + } + } + + //get the bankId + // Vector bankLoc(0, 0, 0); + std::string bankPlanet; + if (creatureActor->getObjVars().hasItem("banking_bankid")) + { + creatureActor->getObjVars().getItem("banking_bankid", bankPlanet); + stats[ "Bank Planet" ] = bankPlanet; + } + + + const ServerObject * inventory = creatureActor->getInventory(); + if( inventory ) + { + + const VolumeContainer * inventoryContainer = ContainerInterface::getVolumeContainer(*inventory); + if (inventoryContainer ) + { + int item_num = 0; + CSHandlerNamespace::addItemInfo(inventoryContainer,item_num,stats); + } + } + + + int item_num = 0; + const SlottedContainer * p_equipment = creatureActor->getSlottedContainerProperty(); + for( ContainerConstIterator it = p_equipment->begin(); + it != p_equipment->end(); + it++ ) + { + Object * const object = (*it).getObject(); + char catbuffer[ CSHandlerNamespace::smallBufferSize ]; + + if( object && object->asServerObject() ) + { + snprintf( catbuffer, sizeof( catbuffer ) - 1, "Equipment-%d", item_num++ ); + catbuffer[ sizeof( catbuffer ) - 1 ] = 0; + snprintf( stringbuffer, sizeof( stringbuffer ) -1, "%s(%s)", Unicode::wideToNarrow( object->asServerObject()->getObjectName() ).c_str(), object->asServerObject()->getNetworkId().getValueString().c_str() ); + stringbuffer[ sizeof( stringbuffer ) - 1 ] = 0; + stats[ catbuffer ] = stringbuffer; + } + + } + + //get the residence location + Vector resLoc; + std::string resPlanet; + + /* creatureActor->getAllBuffs(); + creatureActor->getAllShipsInDatapad();*/ + + // attributes + addIntData( stats, "Action", creatureActor->getAttribute( Attributes::Action ) ); + addIntData( stats, "Constitution", creatureActor->getAttribute( Attributes::Constitution ) ); + addIntData( stats, "Health", creatureActor->getAttribute( Attributes::Health ) ); + addIntData( stats, "Mind", creatureActor->getAttribute( Attributes::Mind ) ); + addIntData( stats, "Stamina", creatureActor->getAttribute( Attributes::Stamina ) ); + addIntData( stats, "Willpower", creatureActor->getAttribute( Attributes::Willpower ) ); + + stats[ "Character ID" ] = player_id.getValueString(); + + // skills + + const CreatureObject::SkillList & skills = creatureActor->getSkillList(); + int temp_int = 0; + for( CreatureObject::SkillList::iterator slit = skills.begin(); + slit != skills.end(); + ++slit ) + { + snprintf( stringbuffer, sizeof( stringbuffer ) - 1, "%d", temp_int ); + stringbuffer[ sizeof( stringbuffer ) -1 ] = 0; + std::string category = "Skill-"; + category = category + stringbuffer; + stats[ category ] = ( *slit )->getSkillName(); + temp_int++; + } + + // add experience into the data + const std::map< std::string, int > & exp = creatureActor->getExperiencePoints(); + + for( std::map< std::string, int >::const_iterator expit = exp.begin(); + expit != exp.end(); + ++expit ) + { + std::string category = "Experience-"; + category += expit->first; + addIntData( stats, category, expit->second ); + } + + // money + snprintf( stringbuffer, sizeof( stringbuffer ) - 1, "%d", creatureActor->getCashBalance() ); + stringbuffer[ sizeof( stringbuffer ) - 1 ] = 0; + stats[ "Credits" ] = stringbuffer; + + snprintf( stringbuffer, sizeof( stringbuffer ) - 1, "%d", creatureActor->getBankBalance() ); + stringbuffer[ sizeof( stringbuffer ) - 1 ] = 0; + stats[ "Bank Credits" ] = stringbuffer; + + // residence info + PlayerObject const * const player = PlayerCreatureController::getPlayerObject(creatureActor); + if (player != NULL) + { + NetworkId houseNetworkId = creatureActor->getHouse(); + const ServerObject* const resObject = ServerObject::getServerObject(houseNetworkId); + if (resObject != NULL) + { + resLoc = resObject->getPosition_w(); + snprintf( stringbuffer, sizeof( stringbuffer ) - 1 , "%02f %02f %02f", resLoc.x, resLoc.y, resLoc.z ); + stringbuffer[ sizeof( stringbuffer ) - 1 ] = 0; + stats[ "Residence Location" ] = stringbuffer; + resPlanet = resObject->getSceneId(); + stats[ "Residence Planet" ] = resPlanet; + } + addIntData( stats, "Account ID", player->getStationId() ); + + } + + //get the spouse's name + Unicode::String spouseName = Unicode::emptyString; + if (creatureActor->getObjVars().hasItem("marriage.spouseName")) + { + creatureActor->getObjVars().getItem("marriage.spouseName", spouseName); + stats[ "Spouse Name" ] = Unicode::wideToNarrow( spouseName ); + } + + //get the number of used lots + int lots = creatureActor->getMaxNumberOfLots(); + + if(player) + { + int lotsUsed = player->getAccountNumLots(); + lots -= lotsUsed; + snprintf( stringbuffer, sizeof( stringbuffer ) - 1, "%d", lots ); + stringbuffer[ sizeof( stringbuffer ) - 1 ] = 0; + stats[ "Lots Available" ] = stringbuffer; + } + + //get the faction standing + int factionAlignment = creatureActor->getPvpFaction(); + snprintf( stringbuffer, sizeof( stringbuffer ) - 1, "%d", factionAlignment ); + stringbuffer[ sizeof( stringbuffer ) - 1 ] = 0; + stats[ "Faction" ] = stringbuffer; + int factionDeclareType = creatureActor->getPvpType(); + snprintf( stringbuffer, sizeof( stringbuffer ) - 1, "%d", factionDeclareType ); + stringbuffer[ sizeof( stringbuffer ) - 1 ] = 0; + stats[ "PvP Type" ] = stringbuffer; + + addIntData( stats, "Guild ID", creatureActor->getGuildId() ); + + // TODO: Move this into its own function. + + // build the response based on our map. + std:: string response = "Stats for player "; + response += request.m_args + "\r\n"; + std::map< std::string, std::string >::iterator statit = stats.begin(); + while( statit != stats.end() ) + { + response += statit->first + ": " + statit->second + "\r\n"; + ++statit; + } + msg.setResponse( response ); + SwgGameServer::getInstance().sendToCentralServer( msg ); + } +} + +CS_CMD( undelete_item ) +{ + CSHandlerNamespace::CSArgs args; + CSHandlerNamespace::getArgs( request.m_args, args ); + if(args.size() < 3) + return; + NetworkId characterId(args[0]); + NetworkId itemId(args[ 1 ]); + bool bMove = false; + if (args[2] == "move") + { + bMove = true; + } + GenericValueTypeMessage, std::string>, bool > > dbmsg("UndeleteItemForCsMessage", std::make_pair(std::make_pair(std::make_pair(characterId, itemId), request.m_args), bMove)); + GameServer::getInstance().sendToDatabaseServer(dbmsg); + CSHandlerNamespace::CSLogData data; + data["character_id"]=args[0]; + data[ "item_id"] = args[ 1 ]; + data[ "command" ] = "undelete_item"; + CSHandlerNamespace::log( request, data ); + msg.setResponse( "Undelete command sent.\r\n" ); + +} + +CS_CMD( get_player_id ) +{ + std::transform( request.m_args.begin(), request.m_args.end(), request.m_args.begin(), tolower ); + + CSHandlerNamespace::CSArgs args; + CSHandlerNamespace::getArgs( request.m_args, args ); + if( args.size() > 0 ) + { + NetworkId player_id = NameManager::getInstance().getPlayerId( args[ 0 ] ); + // build the response + std::string response; + response = "Player Id found\r\ncharactername:" + args[ 0 ] + "\r\ncharacter id:" + player_id.getValueString() + "\r\n"; + + msg.setResponse( response ); + SwgGameServer::getInstance().sendToCentralServer( msg ); + } +} + + +CSHandlerEntry::CSHandlerEntry() : +access( 0 ), +handlerFunc( 0 ) +{ + +} + +CSHandlerEntry::CSHandlerEntry( const std::string & name, uint32 accessLevel, CSHandlerFunc handler ) : +sCommand( name ), +access( accessLevel ), +handlerFunc( handler ) +{ +} + +CSHandlerRequest::CSHandlerRequest( const std::string & command, + const std::string & args, + const uint32 access, + const std::string & username ) : +m_command( command ), +m_args( args ), +m_access( access ), +m_name( username ) +{ +} diff --git a/game/server/application/SwgGameServer/src/shared/core/CSHandler.h b/game/server/application/SwgGameServer/src/shared/core/CSHandler.h new file mode 100644 index 00000000..d41eac66 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/core/CSHandler.h @@ -0,0 +1,91 @@ +//CSHandler.h +// copyright 2005 Sony Online Entertainment +//----------------------------------------------- +// handler class for CS requests. + +#ifndef _CSHANDLER_H +#define _CSHANDLER_H + + + + +#define DECLARE_CS_HANDLER( _name_ ) void handle_##_name_( CSHandlerRequest & request, GameServerCSResponseMessage & msg ); + +class GameServerCSRequestMessage; +class GameServerCSResponseMessage; + +class CSHandlerRequest +{ +public: + CSHandlerRequest( const std::string & command, + const std::string & args, + const uint32 access, + const std::string & username ); + + std::string m_command; + std::string m_args; + uint32 m_access; + std::string m_name; +}; + +class CSHandler +{ + public: + + static void remove(); + + void handle( GameServerCSRequestMessage & request ); + static void install(); + static CSHandler& getInstance(); + + // handlers + DECLARE_CS_HANDLER( get_pc_info ); + DECLARE_CS_HANDLER( set_bank_credits ); + DECLARE_CS_HANDLER( undelete_item ); + DECLARE_CS_HANDLER( list_objvars ); + DECLARE_CS_HANDLER( set_objvar ); + DECLARE_CS_HANDLER( remove_objvar ); + DECLARE_CS_HANDLER( dump_info ); + DECLARE_CS_HANDLER( rename_player ); + + DECLARE_CS_HANDLER( freeze ); + DECLARE_CS_HANDLER( unfreeze ); + + DECLARE_CS_HANDLER( get_player_id ); + DECLARE_CS_HANDLER( get_player_items ); + + DECLARE_CS_HANDLER( move_object ); + DECLARE_CS_HANDLER( delete_object ); + + DECLARE_CS_HANDLER( create_crafted_object ); + + DECLARE_CS_HANDLER( adjust_lots ); + + DECLARE_CS_HANDLER( warp_player ); + + private: + void registerCommands(); + + static CSHandler * sm_instance; + CSHandler(); + virtual ~CSHandler(); + +}; + + +typedef void( CSHandler::*CSHandlerFunc )( CSHandlerRequest &, GameServerCSResponseMessage & ); + +class CSHandlerEntry +{ +public: + CSHandlerEntry(); + CSHandlerEntry( const std::string & name, uint32 access, CSHandlerFunc handler ); + std::string sCommand; + uint32 access; + CSHandlerFunc handlerFunc; + +private: + +}; +#endif // _CSHANDLER_H + diff --git a/game/server/application/SwgGameServer/src/shared/core/FirstSwgGameServer.h b/game/server/application/SwgGameServer/src/shared/core/FirstSwgGameServer.h new file mode 100644 index 00000000..967cf170 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/core/FirstSwgGameServer.h @@ -0,0 +1,25 @@ +// ====================================================================== +// +// FirstSwgGameServer.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_FirstSwgGameServer_H +#define INCLUDED_FirstSwgGameServer_H + +// ====================================================================== + +#pragma warning ( disable : 4503 ) // name truncated (STL) +#include "sharedFoundation/FirstSharedFoundation.h" +#include "sharedDebug/FirstSharedDebug.h" +#include "sharedMemoryManager/FirstSharedMemoryManager.h" + +#include "StringId.h" + + +// ====================================================================== + +#endif + + diff --git a/game/server/application/SwgGameServer/src/shared/core/SwgGameServer.cpp b/game/server/application/SwgGameServer/src/shared/core/SwgGameServer.cpp new file mode 100644 index 00000000..1b310ffd --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/core/SwgGameServer.cpp @@ -0,0 +1,141 @@ +// ====================================================================== +// +// SwgGameServer.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstSwgGameServer.h" +#include "SwgGameServer/SwgGameServer.h" +#include "serverGame/CommoditiesMarket.h" +#include "serverGame/PreloadManager.h" +#include "serverNetworkMessages/BountyHunterTargetListMessage.h" +#include "serverNetworkMessages/GameServerCSRequestMessage.h" +#include "serverNetworkMessages/GameServerCSResponseMessage.h" +#include "sharedDebug/Profiler.h" +#include "sharedGame/AppearanceManager.h" +#include "sharedLog/Log.h" +#include "sharedMessageDispatch/MessageManager.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "SwgGameServer/CombatEngine.h" +#include "SwgGameServer/JediManagerObject.h" +#include "SwgGameServer/ServerJediManagerObjectTemplate.h" +#include "SwgGameServer/SwgServerCreatureObjectTemplate.h" +#include "SwgGameServer/SwgServerPlayerObjectTemplate.h" +#include "SwgGameServer/SwgServerUniverse.h" +#include "SwgGameServer/CSHandler.h" + + +//#undef PROFILE_INDIVIDUAL_MESSAGES +#define PROFILE_INDIVIDUAL_MESSAGES 1 + +#ifdef PROFILE_INDIVIDUAL_MESSAGES + #define MESSAGE_PROFILER_BLOCK(a) PROFILER_AUTO_BLOCK_DEFINE(a) +#else + #define MESSAGE_PROFILER_BLOCK(a) NOP +#endif + + +//----------------------------------------------------------------------- + +SwgGameServer::SwgGameServer() : + GameServer() +{ + connectToMessage("BountyHunterTargetListMessage"); + connectToMessage("DeleteCharacterNotificationMessage"); +} + +//----------------------------------------------------------------------- + +SwgGameServer::~SwgGameServer() +{ +} + +//----------------------------------------------------------------------- + +void SwgGameServer::install() +{ + DEBUG_FATAL (ms_instance != NULL, ("already installed")); + ms_instance = new SwgGameServer; + + SwgServerUniverse::install(); + CombatEngine::install(); + ServerJediManagerObjectTemplate::install(); + SwgServerCreatureObjectTemplate::install(); + SwgServerPlayerObjectTemplate::install(); + // the preload manager MUST be installed after the SwgServer... templates + PreloadManager::install(); + CommoditiesMarket::install(); + + CSHandler::install(); +} + +//----------------------------------------------------------------------- + +void SwgGameServer::initialize() +{ + GameServer::initialize(); +} + +//----------------------------------------------------------------------- + +void SwgGameServer::shutdown() +{ + GameServer::shutdown(); + CommoditiesMarket::remove(); + CSHandler::remove(); +} + +void SwgGameServer::handleCSRequest( GameServerCSRequestMessage & request ) +{ + CSHandler::getInstance().handle( request ); +} + +//----------------------------------------------------------------------- + +void SwgGameServer::receiveMessage(const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message) +{ + static Archive::ReadIterator ri; + static Archive::ByteStream bs; + + PROFILER_AUTO_BLOCK_DEFINE("SwgGameServer::receiveMessage"); + + if (message.isType("BountyHunterTargetListMessage")) + { + DEBUG_REPORT_LOG(true, ("SwgGameServer: got BountyHunterTargetListMessage\n")); + MESSAGE_PROFILER_BLOCK("BountyHunterTargetListMessage"); + ri = static_cast(message).getByteStream().begin(); + const BountyHunterTargetListMessage * msg = new BountyHunterTargetListMessage(ri); + + JediManagerObject * jediManager = static_cast( + ServerUniverse::getInstance()).getJediManager(); + + if (jediManager != NULL && jediManager->isAuthoritative()) + { + jediManager->addJediBounties(*msg); + delete msg; + } + else + { + LOG("BountyHunterTargetList", ("Queuing BountyHunterTargetList from DB because JediManagerObject is not yet ready")); + JediManagerObject::queueBountyHunterTargetListFromDB(msg); + } + } + else if (message.isType("DeleteCharacterNotificationMessage")) + { + ri = static_cast(message).getByteStream().begin(); + const GenericValueTypeMessage msg(ri); + + JediManagerObject * jediManager = static_cast( + ServerUniverse::getInstance()).getJediManager(); + + if (jediManager != NULL) + { + jediManager->characterBeingDeleted(msg.getValue()); + } + } + + // GameServer::receiveMessage does some bookkeeping stuff, so always call it + GameServer::receiveMessage(source, message); +} + diff --git a/game/server/application/SwgGameServer/src/shared/core/SwgGameServer.h b/game/server/application/SwgGameServer/src/shared/core/SwgGameServer.h new file mode 100644 index 00000000..1e5c27a4 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/core/SwgGameServer.h @@ -0,0 +1,36 @@ +// ====================================================================== +// +// SwgGameServer.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_SwgGameServer_H +#define INCLUDED_SwgGameServer_H + +#include "serverGame/GameServer.h" + +class SwgGameServer : public GameServer +{ +public: + + virtual ~SwgGameServer(); + + static void install(); + + virtual void receiveMessage(const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message); + + virtual void handleCSRequest( GameServerCSRequestMessage & request ); + +protected: + SwgGameServer(); + virtual void initialize (); + virtual void shutdown (); + +private: + SwgGameServer (const SwgGameServer & source); + SwgGameServer & operator = (const SwgGameServer & rhs); +}; + + +#endif diff --git a/game/server/application/SwgGameServer/src/shared/core/SwgServerUniverse.cpp b/game/server/application/SwgGameServer/src/shared/core/SwgServerUniverse.cpp new file mode 100644 index 00000000..3d743c93 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/core/SwgServerUniverse.cpp @@ -0,0 +1,68 @@ +// ====================================================================== +// +// SwgServerUniverse.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstSwgGameServer.h" +#include "SwgGameServer/SwgServerUniverse.h" +#include "serverGame/ConfigServerGame.h" +#include "serverGame/ServerObjectTemplate.h" +#include "serverGame/ServerWorld.h" +#include "sharedObject/ObjectTemplateList.h" +#include "SwgGameServer/JediManagerObject.h" + + +// ====================================================================== + +void SwgServerUniverse::install() +{ + Universe::installDerived(new SwgServerUniverse); + ServerUniverse::install(); +} + +// ---------------------------------------------------------------------- + +SwgServerUniverse::SwgServerUniverse() : + ServerUniverse (), + m_jediManager (NULL) +{ +} + +// ---------------------------------------------------------------------- + +SwgServerUniverse::~SwgServerUniverse() +{ +} + +// ---------------------------------------------------------------------- + +/** + * Check the Universe Objects. Spawn new objects as + * needed, update the amount remaining on all the resource pools, etc. + * + * May be time consuming, so this should not be called every frame. + */ + +void SwgServerUniverse::updateAndValidateData() +{ + WARNING_STRICT_FATAL(!isAuthoritative(), ("UpdateAndValidateData() should " + "only be called on the process that is authoritative for UniverseObjects.\n")); + + // create Jedi manager + if (m_jediManager == NULL) + { + const ServerObjectTemplate * objTemplate = safe_cast(ObjectTemplateList::fetch(ConfigServerGame::getJediManagerTemplate())); + m_jediManager = safe_cast(ServerWorld::createNewObject(*objTemplate, Transform::identity, 0, false)); + NOT_NULL(m_jediManager); + registerJediManager(*m_jediManager); + m_jediManager->addToWorld(); + objTemplate->releaseReference(); + } + + ServerUniverse::updateAndValidateData(); +} + + +// ====================================================================== diff --git a/game/server/application/SwgGameServer/src/shared/core/SwgServerUniverse.h b/game/server/application/SwgGameServer/src/shared/core/SwgServerUniverse.h new file mode 100644 index 00000000..624f2d07 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/core/SwgServerUniverse.h @@ -0,0 +1,62 @@ +// ====================================================================== +// +// SwgServerUniverse.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_SwgServerUniverse_H +#define INCLUDED_SwgServerUniverse_H + +#include "serverGame/ServerUniverse.h" + +class JediManagerObject; + + +// ====================================================================== + +/** +* Singleton that manages Universe objects and functions that are global +* to the entire game universe. +*/ +class SwgServerUniverse : public ServerUniverse +{ +public: + static void install(); + +public: + JediManagerObject * getJediManager () const; + void registerJediManager(JediManagerObject & jediManager); + +protected: + virtual void updateAndValidateData(); + +private: + JediManagerObject * m_jediManager; + +private: + SwgServerUniverse(); + virtual ~SwgServerUniverse(); + + SwgServerUniverse(SwgServerUniverse const &); + SwgServerUniverse & operator=(SwgServerUniverse const &); +}; + +// ====================================================================== + +inline JediManagerObject * SwgServerUniverse::getJediManager() const +{ + return m_jediManager; +} + +// ---------------------------------------------------------------------- + +inline void SwgServerUniverse::registerJediManager(JediManagerObject & jediManager) +{ + m_jediManager = &jediManager; +} + +// ====================================================================== + + +#endif diff --git a/game/server/application/SwgGameServer/src/shared/lint/ServerObjectLint.cpp b/game/server/application/SwgGameServer/src/shared/lint/ServerObjectLint.cpp new file mode 100644 index 00000000..a8dd455b --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/lint/ServerObjectLint.cpp @@ -0,0 +1,122 @@ + + +#include "FirstSwgGameServer.h" +#include "ServerObjectLint.h" + +#include "serverGame/ObjectIdManager.h" +#include "serverGame/ServerWorld.h" +#include "sharedFoundation/NetworkId.h" + +#include "serverGame/ServerArmorTemplate.h" +#include "serverGame/ServerBuildingObjectTemplate.h" +#include "serverGame/ServerCellObjectTemplate.h" +#include "serverGame/ServerCreatureObjectTemplate.h" +#include "serverGame/ServerDraftSchematicObjectTemplate.h" +#include "serverGame/ServerInstallationObjectTemplate.h" +#include "serverGame/ServerMissionObjectTemplate.h" +#include "serverGame/ServerManufactureSchematicObjectTemplate.h" +#include "serverGame/ServerMissionObjectTemplate.h" +#include "serverGame/ServerObject.h" +#include "serverGame/ServerObjectTemplate.h" +#include "serverGame/ServerPlanetObjectTemplate.h" +#include "serverGame/ServerResourceContainerObjectTemplate.h" +#include "serverGame/ServerStaticObjectTemplate.h" +#include "serverGame/ServerUniverse.h" +#include "serverGame/ServerVehicleObjectTemplate.h" +#include "serverGame/ServerWeaponObjectTemplate.h" + +#include "sharedGame/SharedBuildingObjectTemplate.h" +#include "sharedGame/SharedCellObjectTemplate.h" +#include "sharedGame/SharedCreatureObjectTemplate.h" +#include "sharedGame/SharedDraftSchematicObjectTemplate.h" +#include "sharedGame/SharedInstallationObjectTemplate.h" +#include "sharedGame/SharedResourceContainerObjectTemplate.h" +#include "sharedGame/SharedStaticObjectTemplate.h" +#include "sharedGame/SharedTerrainSurfaceObjectTemplate.h" +#include "sharedGame/SharedVehicleObjectTemplate.h" +#include "sharedGame/SharedWeaponObjectTemplate.h" + +#include + +void ServerObjectLint::install() +{ + ObjectIdManager::getInstance().addBlock(100,10000000); //lint !e747 Significant prototype coercion (arg. no. 1) int to long long +} + +void ServerObjectLint::run(const std::vector & templateList) +{ + install(); + + /* + ServerArmorTemplate::install(true); + ServerBuildingObjectTemplate::install(true); + ServerCellObjectTemplate::install(); + ServerCreatureObjectTemplate::install(true); + ServerDraftSchematicObjectTemplate::install(true); + ServerInstallationObjectTemplate::install(true); + ServerIntangibleObjectTemplate::install(true); + ServerManufactureSchematicObjectTemplate::install(true); + ServerMissionBoardObjectTemplate::install(true); + ServerMissionObjectTemplate::install(true); + ServerObjectTemplate::install(true); + ServerPlanetObjectTemplate::install(true); + ServerResourceClassObjectTemplate::install(true); + ServerResourceContainerObjectTemplate::install(true); + ServerResourcePoolObjectTemplate::install(true); + ServerResourceTypeObjectTemplate::install(true); + ServerStaticObjectTemplate::install(true); + ServerTangibleObjectTemplate::install(true); + ServerVehicleObjectTemplate::install(true); + ServerWeaponObjectTemplate::install(true); + + SharedBuildingObjectTemplate::install(true); + SharedCellObjectTemplate::install(true); + SharedCreatureObjectTemplate::install(true); + SharedDraftSchematicObjectTemplate::install(true); + SharedInstallationObjectTemplate::install(true); + SharedIntangibleObjectTemplate::install(true); + SharedObjectTemplate::install(true); + SharedResourceContainerObjectTemplate::install(true); + SharedStaticObjectTemplate::install(true); + SharedTangibleObjectTemplate::install(true); + SharedTerrainSurfaceObjectTemplate::install(true); + SharedVehicleObjectTemplate::install(true); + SharedWeaponObjectTemplate::install(true); +*/ + ServerWorld::install(); + + + std::vector::const_iterator i = templateList.begin(); + FILE * output = fopen("server_object_lint.sln", "w"); //lint !e64 Type mismatch (initialization) (struct _IO_FILE * = int) + FATAL(!output, ("Could not create output file")); + for (; i != templateList.end(); ++i) + { + if (i->find("base") != std::string::npos) + { + //Don't try to instantiate base templtates + IGNORE_RETURN(fprintf(output, "Skipping %s because it is a base class.\n", i->c_str())); //lint !e64 !e119 + continue; + } + DEBUG_REPORT_LOG(true, ("Now processing %s...\n", i->c_str())); + IGNORE_RETURN(fprintf(output, "Now processing %s...\n", i->c_str()));//lint !e64 !e119 + IGNORE_RETURN(fflush(output)); + + ServerObject* obj = ServerWorld::createObjectFromTemplate((*i), NetworkId(static_cast(1))); + DEBUG_REPORT_LOG(!obj, ("***ERROR: Could not create %s\n", i->c_str())); + DEBUG_REPORT_LOG(obj,("Successfully created %s\n", i->c_str())); + if (!obj) + IGNORE_RETURN(fprintf(output, "***ERROR: Could not create %s\n", i->c_str())); //lint !e64 !e119 + else + { + IGNORE_RETURN(fprintf(output, "Successfully created %s\n", i->c_str())); //lint !e64 !e119 + obj->serverObjectInitializeFirstTimeObject(0, Transform::identity); + delete obj; + obj = 0; + } + } + DEBUG_REPORT_LOG(true, ("-----Done with Server Objects ----\n")); + IGNORE_RETURN(fprintf(output, ("-----Done with Server Objects ----\n"))); //lint !e64 !e119 + IGNORE_RETURN(fclose(output)); + +} + diff --git a/game/server/application/SwgGameServer/src/shared/lint/ServerObjectLint.h b/game/server/application/SwgGameServer/src/shared/lint/ServerObjectLint.h new file mode 100644 index 00000000..dee4865a --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/lint/ServerObjectLint.h @@ -0,0 +1,16 @@ + +#include +#include + + +class ServerObjectLint +{ + public: + static void run(const std::vector & templateList); + static void install(); + + private: + ServerObjectLint(); + ServerObjectLint(const ServerObjectLint&); + ServerObjectLint& operator= (const ServerObjectLint&); +}; diff --git a/game/server/application/SwgGameServer/src/shared/object/JediManagerObject.cpp b/game/server/application/SwgGameServer/src/shared/object/JediManagerObject.cpp new file mode 100644 index 00000000..a2b4f882 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/object/JediManagerObject.cpp @@ -0,0 +1,1489 @@ +// ====================================================================== +// +// JediManagerObject.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstSwgGameServer.h" +#include "SwgGameServer/JediManagerObject.h" + +#include "UnicodeUtils.h" +#include "boost/smart_ptr.hpp" +#include "serverGame/ConfigServerGame.h" +#include "serverGame/GameServer.h" +#include "serverGame/MessageToQueue.h" +#include "serverGame/PlayerObject.h" +#include "serverNetworkMessages/BountyHunterTargetListMessage.h" +#include "serverNetworkMessages/BountyHunterTargetMessage.h" +#include "serverScript/GameScriptObject.h" +#include "serverScript/ScriptDictionary.h" +#include "serverScript/ScriptParameters.h" +#include "sharedFoundation/GameControllerMessage.h" +#include "sharedLog/Log.h" +#include "sharedNetworkMessages/MessageQueueGenericValueType.h" +#include "sharedObject/NetworkIdManager.h" +#include "SwgGameServer/JediManagerController.h" +#include "SwgGameServer/ServerJediManagerObjectTemplate.h" +#include "SwgGameServer/SwgCreatureObject.h" +#include "SwgGameServer/SwgServerUniverse.h" +#include "swgServerNetworkMessages/MessageQueueJediData.h" +#include "swgServerNetworkMessages/MessageQueueJediLocation.h" +#include "swgServerNetworkMessages/MessageQueueRequestJediBounty.h" + + +static const int IGNORE_JEDI_STAT = INT_MAX; + + +// ====================================================================== + +namespace JediManagerObjectNamespace +{ + // the bounty hunter target list loaded from the DB; we store it here + // and wait until the JediManagerObject object is created, and then + // read it into the JediManagerObject object + const BountyHunterTargetListMessage * s_queuedBountyHunterTargetListFromDB = NULL; +} + +using namespace JediManagerObjectNamespace; + +// ---------------------------------------------------------------------- + +/** + * Class constructor. + */ +JediManagerObject::JediManagerObject(const ServerJediManagerObjectTemplate *newTemplate) : + UniverseObject(newTemplate), + m_jediId(), + m_holes(), + m_jediName(), + m_jediLocation(), + m_jediScene(), + m_jediVisibility(), + m_jediBountyValue(), + m_jediLevel(), + m_jediBounties(), + m_jediHoursAlive(), + m_jediState(), + m_jediOnline(), + m_jediSpentJediSkillPoints(), + m_jediFaction(), + m_jediScriptData(), + m_jediScriptDataNames(), + m_bountyHunterTargetsReceivedFromDB(false) +{ + addMembersToPackages(); +} // JediManagerObject::JediManagerObject + +// ---------------------------------------------------------------------- + +/** + * Class destructor. + */ +JediManagerObject::~JediManagerObject() +{ +} // JediManagerObject::~JediManagerObject + +// ---------------------------------------------------------------------- + +/** + * Sets up auto-sync data. + */ +void JediManagerObject::addMembersToPackages() +{ + addServerVariable_np (m_jediId); + addServerVariable_np (m_holes); + addServerVariable_np (m_jediName); + addServerVariable_np (m_jediLocation); + addServerVariable_np (m_jediScene); + addServerVariable_np (m_jediVisibility); + addServerVariable_np (m_jediBountyValue); + addServerVariable_np (m_jediLevel); + addServerVariable_np (m_jediBounties); + addServerVariable_np (m_bountyHunters); + addServerVariable_np (m_jediHoursAlive); + addServerVariable_np (m_jediState); + addServerVariable_np (m_jediOnline); + addServerVariable_np (m_jediSpentJediSkillPoints); + addServerVariable_np (m_jediFaction); + addServerVariable_np (m_jediScriptData); + addServerVariable_np (m_jediScriptDataNames); + addServerVariable_np (m_bountyHunterTargetsReceivedFromDB); +} // JediManagerObject::addMembersToPackages + +// ---------------------------------------------------------------------- + +/** + * Initializes data for a newly created object. + */ +void JediManagerObject::initializeFirstTimeObject() +{ + UniverseObject::initializeFirstTimeObject(); +} // JediManagerObject::initializeFirstTimeObject + +// ---------------------------------------------------------------------- + +/** + * Initializes an object just proxied. + */ +void JediManagerObject::endBaselines() +{ + UniverseObject::endBaselines(); +} // JediManagerObject::endBaselines + +// ---------------------------------------------------------------------- + +/** + * Final setup for universe objects. Registers this object with the universe. + */ +void JediManagerObject::setupUniverse() +{ + static_cast(SwgServerUniverse::getInstance()).registerJediManager(*this); +} // JediManagerObject::setupUniverse + +// ---------------------------------------------------------------------- + +void JediManagerObject::onServerUniverseGainedAuthority() +{ + if (s_queuedBountyHunterTargetListFromDB) + { + addJediBounties(*s_queuedBountyHunterTargetListFromDB); + + delete s_queuedBountyHunterTargetListFromDB; + s_queuedBountyHunterTargetListFromDB = NULL; + } +} + +// ---------------------------------------------------------------------- + +/** + * Creates the controller for this object. + */ +Controller * JediManagerObject::createDefaultController() +{ + Controller * controller = new JediManagerController(this); + NOT_NULL(controller); + + setController(controller); + return controller; +} // JediManagerObject::createDefaultController + +// ---------------------------------------------------------------------- + +void JediManagerObject::conclude() +{ + if (ConfigServerGame::getLogJediConcludes()) + REPORT_LOG(true, ("Jedi manager concluding\n")); + UniverseObject::conclude(); +} + +// ---------------------------------------------------------------------- + +/** + * Adds a Jedi to the list of Jedi online. + * + * @param id id of the Jedi + * @param name name of the Jedi + * @param location the world location of the Jedi + * @param scene the scene the Jedi is in + * @param visibility how visible the Jedi is + * @param bountyValue the bountyValue on the Jedi + * @param level the level of the Jedi + * @param hoursAlive how long the Jedi has been alive + * @param state the Jedi state + * @param spentJediSkillPoints number of skills points the Jedi has spent on Jedi skills + * @param faction the Jedi's pvp faction + */ +void JediManagerObject::addJedi(const NetworkId & id, const Unicode::String & name, + const Vector & location, const std::string & scene, int visibility, int bountyValue, + int level, int hoursAlive, int state, int spentJediSkillPoints, int faction) +{ + WARNING_DEBUG_FATAL(!isInitialized(), ("JediManagerObject::addJedi when not " + "initialized")); + + if (isAuthoritative()) + { + // make sure we aren't adding a duplicate Jedi + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(id); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index == -1) + { + if (bountyValue > 0) + { + LOG("CustomerService", ("Jedi: Adding %s to the Jedi manager with a bounty value of %d", + PlayerObject::getAccountDescription(id).c_str(), bountyValue)); + + // add the Jedi + if (m_holes.empty()) + { + m_jediName.push_back(name); + m_jediLocation.push_back(location); + m_jediScene.push_back(scene); + m_jediVisibility.push_back(visibility); + m_jediBountyValue.push_back(bountyValue); + m_jediLevel.push_back(level); + m_jediBounties.push_back(std::vector()); + m_jediHoursAlive.push_back(hoursAlive); + m_jediState.push_back(state); + m_jediOnline.push_back(1); + m_jediSpentJediSkillPoints.push_back(spentJediSkillPoints); + m_jediFaction.push_back(faction); + + m_jediId.set(id, m_jediName.size() - 1); + } + else + { + const int hole = m_holes.back(); + m_holes.pop_back(); + + m_jediName.set(hole, name); + m_jediLocation.set(hole, location); + m_jediScene.set(hole, scene); + m_jediVisibility.set(hole, visibility); + m_jediBountyValue.set(hole, bountyValue); + m_jediLevel.set(hole, level); + m_jediBounties.set(hole, std::vector()); + m_jediHoursAlive.set(hole, hoursAlive); + m_jediState.set(hole, state); + m_jediOnline.set(hole, 1); + m_jediSpentJediSkillPoints.set(hole, spentJediSkillPoints); + m_jediFaction.set(hole, faction); + + m_jediId.set(id, hole); + } + + if (location.x == 0 && location.y == 0 && location.z == 0) + { + LOG("CustomerService", ("Jedi: %s has a location of 0 0 0", + PlayerObject::getAccountDescription(id).c_str())); + } + } + } + else + { + // if bountyValue is 0 and Jedi doesn't have any + // more bounty hunters hunting him, remove him + if ((bountyValue <= 0) && (m_jediBounties[index].empty())) + { + removeJedi(id); + } + else + { + if (bountyValue != m_jediBountyValue[index]) + { + LOG("CustomerService", ("Jedi: Updating Jedi %s bounty value from %d to %d", + PlayerObject::getAccountDescription(id).c_str(), m_jediBountyValue[index], bountyValue)); + } + + m_jediName.set(index, name); + m_jediLocation.set(index, location); + m_jediScene.set(index, scene); + m_jediVisibility.set(index, visibility); + m_jediBountyValue.set(index, bountyValue); + m_jediLevel.set(index,level); + m_jediState.set(index, state); + m_jediOnline.set(index, 1); + m_jediSpentJediSkillPoints.set(index, spentJediSkillPoints); + m_jediFaction.set(index, faction); + + if (location.x == 0 && location.y == 0 && location.z == 0) + { + LOG("CustomerService", ("Jedi: %s has a location of 0 0 0", + PlayerObject::getAccountDescription(id).c_str())); + } + } + } + } + else + { + sendControllerMessageToAuthServer(CM_addJedi, + new MessageQueueJediData(id, name, location, scene, visibility, bountyValue, + level, hoursAlive, state, spentJediSkillPoints, faction)); + } + + // in theory this should happen automatically via the auto delta code or when + // we send the controller message, but on live this appears not to be happening + if (ConfigServerGame::getForceJediConcludes()) + addObjectToConcludeList(); +} // JediManagerObject::addJedi + +// ---------------------------------------------------------------------- + +/** + * Tags a Jedi as being offline. + * + * @param id id of the Jedi + * @param location final world location of the Jedi + * @param scene final scene of the Jedi + */ +void JediManagerObject::setJediOffline(const NetworkId & id, const Vector & location, + const std::string & scene) +{ + WARNING_DEBUG_FATAL(!isInitialized(), ("JediManagerObject::setJediOffline " + "when not initialized")); + + if (isAuthoritative()) + { + // make sure we aren't adding a duplicate Jedi + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(id); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + LOG("CustomerService", ("Jedi: Flagging Jedi %s as offline", + PlayerObject::getAccountDescription(id).c_str())); + m_jediLocation.set(index, location); + m_jediScene.set(index, scene); + m_jediOnline.set(index, 0); + + if (location.x == 0 && location.y == 0 && location.z == 0) + { + LOG("CustomerService", ("Jedi: %s has a location of 0 0 0", + PlayerObject::getAccountDescription(id).c_str())); + } + } + else + { + LOG("CustomerService", ("Jedi: setJediOffline called " + " for unknown Jedi %s", PlayerObject::getAccountDescription(id).c_str())); + } + } + else + { + sendControllerMessageToAuthServer(CM_setJediOffline, + new MessageQueueJediLocation(id, location, scene)); + } + + // in theory this should happen automatically via the auto delta code or when + // we send the controller message, but on live this appears not to be happening + if (ConfigServerGame::getForceJediConcludes()) + addObjectToConcludeList(); +} // JediManagerObject::setJediOffline + +// ---------------------------------------------------------------------- + +/** + * Removes a Jedi from the list of Jedi online. + * + * @param id id of the Jedi + */ +void JediManagerObject::removeJedi(const NetworkId & id) +{ + WARNING_DEBUG_FATAL(!isInitialized(), ("JediManagerObject::removeJedi " + "when not initialized")); + + if (isAuthoritative()) + { + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(id); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + LOG("CustomerService", ("Jedi: Removing %s from the Jedi manager", + PlayerObject::getAccountDescription(id).c_str())); + + { + const std::vector & bounties = m_jediBounties[index]; + for (std::vector::const_iterator i = bounties.begin(); i != bounties.end(); ++i) + { + adjustBountyCount(*i, -1); + + // tell the db about the change + GameServer::getInstance().sendToDatabaseServer(BountyHunterTargetMessage(*i, NetworkId::cms_invalid)); + + // tell the hunter to update their pvp status + MessageToQueue::getInstance().sendMessageToC(*i, "C++UpdatePvp", "", 0, false); + } + } + + // mark the location in the vectors as removed + IGNORE_RETURN(m_jediId.erase(id)); + m_holes.push_back(index); + + // find and remove all the Jedi script data + { + char buffer[1024]; + for (Archive::AutoDeltaSet::const_iterator i = m_jediScriptDataNames.begin(); + i != m_jediScriptDataNames.end(); ++i) + { + snprintf(buffer, sizeof(buffer), "%d|%s", index, (*i).c_str()); + m_jediScriptData.erase(buffer); + } + } + } + else + { + LOG("CustomerService", ("Jedi: removeJedi asked to " + "remove unknown Jedi %s", PlayerObject::getAccountDescription(id).c_str())); + } + } + else + { + sendControllerMessageToAuthServer(CM_removeJedi, + new MessageQueueGenericValueType(id)); + } + + // in theory this should happen automatically via the auto delta code or when + // we send the controller message, but on live this appears not to be happening + if (ConfigServerGame::getForceJediConcludes()) + addObjectToConcludeList(); +} // JediManagerObject::removeJedi + +// ---------------------------------------------------------------------- + +/** + * A character is being deleted + * + * @param id id of the character + */ +void JediManagerObject::characterBeingDeleted(const NetworkId & id) +{ + WARNING_DEBUG_FATAL(!isInitialized(), ("JediManagerObject::jediBeingDeleted " + "when not initialized")); + + // stop tracking the character + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(id); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + // tell all bounty hunters currently hunting the jedi to cancel their bounty mission + ScriptParams params; + params.addParam(id, "target"); + + ScriptDictionaryPtr dictionary; + GameScriptObject::makeScriptDictionary(params, dictionary); + if (dictionary.get() != NULL) + { + dictionary->serialize(); + + const std::vector & bounties = m_jediBounties[index]; + for (std::vector::const_iterator i = bounties.begin(); i != bounties.end(); ++i) + { + MessageToQueue::getInstance().sendMessageToJava(*i, + "handleBountyMissionIncomplete", dictionary->getSerializedData(), 0, true); + } + } + else + { + WARNING(true, ("JediManagerObject::characterBeingDeleted error converting " + "params")); + } + + // remove the jedi + removeJedi(id); + } + + // remove all bounties that the deleted character is hunting + std::vector jedis; + getBountyHunterBounties(id, jedis); + + for (std::vector::const_iterator iter = jedis.begin(); iter != jedis.end(); ++iter) + { + removeJediBounty(*iter, id); + } +} // JediManagerObject::characterBeingDeleted + +// ---------------------------------------------------------------------- + +/** + * Updates the data for a Jedi in the list of Jedi online. If a data param + * is < 0, it will be ignored. + * + * @param id id of the Jedi + * @param visibility how visible the Jedi is + * @param bountyValue the bounty value of the Jedi + * @param level the level of the Jedi + * @param hoursAlive how long the Jedi has been alive + */ +void JediManagerObject::updateJedi(const NetworkId & id, int visibility, + int bountyValue, int level, int hoursAlive) +{ + WARNING_DEBUG_FATAL(!isInitialized(), ("JediManagerObject::updateJedi(1) " + "when not initialized")); + + if (isAuthoritative()) + { + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(id); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + if (visibility >= 0 && visibility != m_jediVisibility.get(index)) + { + LOG("CustomerService", ("Jedi: Setting Jedi %s visibility to %d", + PlayerObject::getAccountDescription(id).c_str(), visibility)); + m_jediVisibility.set(index, visibility); + } + if (bountyValue >= 0 && bountyValue != m_jediBountyValue.get(index)) + { + LOG("CustomerService", ("Jedi: Setting Jedi %s bounty value to %d", + PlayerObject::getAccountDescription(id).c_str(), bountyValue)); + m_jediBountyValue.set(index, bountyValue); + } + if (level >= 0 && level != m_jediLevel.get(index)) + { + LOG("CustomerService", ("Jedi: Setting Jedi %s level to %d", + PlayerObject::getAccountDescription(id).c_str(), level)); + m_jediLevel.set(index, level); + } + if (hoursAlive >= 0 && hoursAlive != m_jediHoursAlive.get(index)) + { + LOG("CustomerService", ("Jedi: Setting Jedi %s hoursAlive to %d", + PlayerObject::getAccountDescription(id).c_str(), hoursAlive)); + m_jediHoursAlive.set(index, hoursAlive); + } + } + else + { + LOG("CustomerService", ("Jedi: updateJedi(1) called for " + "unknown Jedi %s", PlayerObject::getAccountDescription(id).c_str())); + } + } + else + { + sendControllerMessageToAuthServer(CM_updateJedi, new MessageQueueJediData( + id, Unicode::emptyString, Vector(), "", visibility, bountyValue, level, hoursAlive, + 0, 0, 0)); + } + + // in theory this should happen automatically via the auto delta code or when + // we send the controller message, but on live this appears not to be happening + if (ConfigServerGame::getForceJediConcludes()) + addObjectToConcludeList(); +} // JediManagerObject::updateJedi(int, int) + +// ---------------------------------------------------------------------- + +/** + * Updates the data for a Jedi in the list of Jedi online. + * + * @param id id of the Jedi + * @param state the new state for the Jedi + */ +void JediManagerObject::updateJedi(const NetworkId & id, JediState state) +{ + WARNING_DEBUG_FATAL(!isInitialized(), ("JediManagerObject::updateJedi(2) " + "when not initialized")); + + if (isAuthoritative()) + { + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(id); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + if (state != m_jediState.get(index)) + { + LOG("CustomerService", ("Jedi: Setting Jedi %s state to %d", + PlayerObject::getAccountDescription(id).c_str(), static_cast(state))); + m_jediState.set(index, state); + } + } + else + { + LOG("CustomerService", ("Jedi: updateJedi(2) called for " + "unknown Jedi %s", PlayerObject::getAccountDescription(id).c_str())); + } + } + else + { + sendControllerMessageToAuthServer(CM_updateJediState, + new MessageQueueGenericValueType >( + std::make_pair(id, static_cast(state)))); + } + + // in theory this should happen automatically via the auto delta code or when + // we send the controller message, but on live this appears not to be happening + if (ConfigServerGame::getForceJediConcludes()) + addObjectToConcludeList(); +} // JediManagerObject::updateJedi(JediState) + +// ---------------------------------------------------------------------- + +/** + * Updates the bounty data for a Jedi in the list of Jedi online. + * + * @param id id of the Jedi + * @param bounties list of the bounty hunters tracking the Jedi + * +void JediManagerObject::updateJedi(const NetworkId & id, + const std::vector & bounties) const +{ + WARNING_DEBUG_FATAL(!isInitialized(), ("JediManagerObject::updateJedi(3) " + "when not initialized")); + + if (isAuthoritative()) + { + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(id); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + LOG("CustomerService", ("Jedi: Updating bounties on Jedi %s", + PlayerObject::getAccountDescription(id).c_str())); + m_jediBounties.set(index, bounties); + } + else + { + LOG("CustomerService", ("Jedi: updateJedi(3) called for " + "unknown Jedi %s", PlayerObject::getAccountDescription(id).c_str())); + } + } + else + { + sendControllerMessageToAuthServer(CM_updateJediBounties, + new MessageQueueGenericValueType > >( + std::make_pair(id, bounties))); + } + + // in theory this should happen automatically via the auto delta code or when + // we send the controller message, but on live this appears not to be happening + if (ConfigServerGame::getForceJediConcludes()) + addObjectToConcludeList(); +} // JediManagerObject::updateJedi(const std::vector &) +*/ +// ---------------------------------------------------------------------- + +/** + * Updates the location for a Jedi. + * + * @param id id of the Jedi + * @param location the Jedi location + * @param scene the Jedi scene + */ +void JediManagerObject::updateJediLocation(const NetworkId & id, const Vector & location, + const std::string & scene) +{ + WARNING_DEBUG_FATAL(!isInitialized(), ("JediManagerObject::updateJediLocation " + "when not initialized")); + + if (isAuthoritative()) + { + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(id); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + if (scene != m_jediScene.get(index)) + { + LOG("CustomerService", ("Jedi: Updating scene for Jedi %s to %s", + PlayerObject::getAccountDescription(id).c_str(), scene.c_str())); + m_jediScene.set(index, scene); + } + m_jediLocation.set(index, location); + if (location.x == 0 && location.y == 0 && location.z == 0) + { + LOG("CustomerService", ("Jedi: %s has a location of 0 0 0", + PlayerObject::getAccountDescription(id).c_str())); + } + if (!m_jediOnline.get(index)) + { + LOG("CustomerService", ("Jedi: Jedi %s was offline but we received a position update, so we are marking them online.",PlayerObject::getAccountDescription(id).c_str(), scene.c_str())); + m_jediOnline.set(index, 1); + } + } + else + { + LOG("CustomerService", ("Jedi: updateJediLocation called " + "for unknown Jedi %s", PlayerObject::getAccountDescription(id).c_str())); + } + } + else + { + sendControllerMessageToAuthServer(CM_updateJediLocation, + new MessageQueueJediLocation(id, location, scene)); + } + + // in theory this should happen automatically via the auto delta code or when + // we send the controller message, but on live this appears not to be happening + if (ConfigServerGame::getForceJediConcludes()) + addObjectToConcludeList(); +} // JediManagerObject::updateJediLocation + +// ---------------------------------------------------------------------- + +/** + * Updates the number of skill points spent on Jedi skills for a Jedi. + * + * @param id id of the Jedi + * @param spentJediSkillPoints the number of skill points the Jedi has spent on Jedi skills + */ +void JediManagerObject::updateJediSpentJediSkillPoints(const NetworkId & id, int spentJediSkillPoints) +{ + WARNING_DEBUG_FATAL(!isInitialized(), ("JediManagerObject::updateJediSpentJediSkillPoints " + "when not initialized")); + + if (isAuthoritative()) + { + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(id); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + if (spentJediSkillPoints != m_jediSpentJediSkillPoints.get(index)) + { + LOG("CustomerService", ("Jedi: Updating spent Jedi skill points for Jedi %s from %d to %d", + PlayerObject::getAccountDescription(id).c_str(), m_jediSpentJediSkillPoints.get(index), spentJediSkillPoints)); + m_jediSpentJediSkillPoints.set(index, spentJediSkillPoints); + } + } + else + { + LOG("CustomerService", ("Jedi: updateJediSpentJediSkillPoints called " + "for unknown Jedi %s", PlayerObject::getAccountDescription(id).c_str())); + } + } + else + { + sendControllerMessageToAuthServer(CM_updateJediSpentJediSkillPoints, + new MessageQueueGenericValueType >( + std::make_pair(id, spentJediSkillPoints))); + } + + // in theory this should happen automatically via the auto delta code or when + // we send the controller message, but on live this appears not to be happening + if (ConfigServerGame::getForceJediConcludes()) + addObjectToConcludeList(); +} // JediManagerObject::updateJediSpentJediSkillPoints + +// ---------------------------------------------------------------------- + +/** + * Updates the faction of a Jedi. + * + * @param id id of the Jedi + * @param faction the Jedi's faction + */ +void JediManagerObject::updateJediFaction(const NetworkId & id, int faction) +{ + WARNING_DEBUG_FATAL(!isInitialized(), ("JediManagerObject::updateJediFaction " + "when not initialized")); + + if (isAuthoritative()) + { + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(id); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + if (faction != m_jediFaction.get(index)) + { + LOG("CustomerService", ("Jedi: Updating Jedi faction for Jedi %s from %d to %d", + PlayerObject::getAccountDescription(id).c_str(), m_jediFaction.get(index), faction)); + m_jediFaction.set(index, faction); + } + } + else + { + LOG("CustomerService", ("Jedi: updateJediFaction called for unknown " + "Jedi %s", PlayerObject::getAccountDescription(id).c_str())); + } + } + else + { + sendControllerMessageToAuthServer(CM_updateJediFaction, + new MessageQueueGenericValueType >( + std::make_pair(id, faction))); + } + + // in theory this should happen automatically via the auto delta code or when + // we send the controller message, but on live this appears not to be happening + if (ConfigServerGame::getForceJediConcludes()) + addObjectToConcludeList(); +} // JediManagerObject::updateJediFaction + +// ---------------------------------------------------------------------- + +/** + * Adds an arbitrary name->int pair to the info for a Jedi. + * + * @param id the Jedi's id + * @param name the data name + * @param value the data value + */ +void JediManagerObject::updateJediScriptData(const NetworkId & id, const std::string & name, int value) +{ + WARNING_DEBUG_FATAL(!isInitialized(), ("JediManagerObject::updateJediScriptData " + "when not initialized")); + + if (isAuthoritative()) + { + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(id); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + LOG("CustomerService", ("Jedi: Updating script data on Jedi %s. Data " + "name = %s, value = %d", PlayerObject::getAccountDescription(id).c_str(), + name.c_str(), value)); + char buffer[1024]; + if (snprintf(buffer, sizeof(buffer), "%d|%s", index, name.c_str()) > 0) + { + m_jediScriptData.set(buffer, value); + m_jediScriptDataNames.insert(name); + } + } + else + { + LOG("CustomerService", ("Jedi: updateJediScriptData called for " + "unknown Jedi %s", PlayerObject::getAccountDescription(id).c_str())); + } + } + else + { + sendControllerMessageToAuthServer(CM_updateJediScriptData, + new MessageQueueGenericValueType > >( + std::make_pair(id, std::make_pair(name, value)))); + } + + // in theory this should happen automatically via the auto delta code or when + // we send the controller message, but on live this appears not to be happening + if (ConfigServerGame::getForceJediConcludes()) + addObjectToConcludeList(); +} // JediManagerObject::updateJediScriptData + +// ---------------------------------------------------------------------- + +/** + * Removes an arbitrary name->int pair to the info for a Jedi. + * + * @param id the Jedi's id + * @param name the data name + */ +void JediManagerObject::removeJediScriptData(const NetworkId & id, const std::string & name) +{ + WARNING_DEBUG_FATAL(!isInitialized(), ("JediManagerObject::removeJediScriptData " + "when not initialized")); + + if (isAuthoritative()) + { + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(id); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + LOG("CustomerService", ("Jedi: Removing script data on Jedi %s. Data " + "name = %s", PlayerObject::getAccountDescription(id).c_str(), + name.c_str())); + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "%d|%s", index, name.c_str()); + m_jediScriptData.erase(buffer); + } + else + { + LOG("CustomerService", ("Jedi: removeJediScriptData called for " + "unknown Jedi %s", PlayerObject::getAccountDescription(id).c_str())); + } + } + else + { + sendControllerMessageToAuthServer(CM_removeJediScriptData, + new MessageQueueGenericValueType >( + std::make_pair(id, name))); + } + + // in theory this should happen automatically via the auto delta code or when + // we send the controller message, but on live this appears not to be happening + if (ConfigServerGame::getForceJediConcludes()) + addObjectToConcludeList(); +} // JediManagerObject::removeJediScriptData + +// ---------------------------------------------------------------------- + +/** + * Called by a script requesting Jedi with certain parameters. Limits are passed + * in for statistics that the caller is interested in; the Jedi returned will + * have the requested value or greater for the statistic if the value given is + * >= 0, or less than the statistic if the value given is < 0. If the statistic + * should be ignored, IGNORE_JEDI_STAT should be passed in as the limit value. + * The exception to this is the minLevel and maxLevel parameters, which always + * specify the (inclusive) minLevel and maxLevel filter + * + * @param visibility how visible the Jedi is + * @param bountyValue bounty value of the Jedi + * @param minLevel minimum Jedi level (inclusive) + * @param maxLevel maximum Jedi level (inclusive) + * @param bounties how many bounties the Jedi has on him + * @param hoursAlive how long the Jedi has been alive + * @param state which Jedi states we're interested in + * @param returnParams params that will be filled in with the Jedi data + */ +void JediManagerObject::getJedi(int visibility, int bountyValue, int minLevel, int maxLevel, + int hoursAlive, int bounties, int state, ScriptParams & returnParams) const +{ + // unfortunately we have to create new data to store the Jedi info, + // since the ScriptParams class wasn't set up to be passed as a return + // value like we're using it. + + // the returnParams will be responsible for destructing these + std::vector * jediId = new std::vector; + std::vector * jediName = new std::vector; + std::vector * jediLocation = new std::vector; + std::vector * jediScene = new std::vector; + std::vector * jediVisibility = new std::vector; + std::vector * jediBountyValue = new std::vector; + std::vector * jediLevel = new std::vector; + std::vector *> * jediBounties = new std::vector *>; + std::vector * jediHoursAlive = new std::vector; + std::vector * jediState = new std::vector; + std::deque * jediOnline = new std::deque; + std::vector * jediSpentJediSkillPoints = new std::vector; + std::vector * jediFaction = new std::vector; + std::map *> jediScriptData; + + // initialize the jedi script data map + { + for (Archive::AutoDeltaSet::const_iterator iter = m_jediScriptDataNames.begin(); + iter != m_jediScriptDataNames.end(); ++iter) + { + jediScriptData.insert(std::make_pair(*iter, new std::vector)); + } + } + + // check each Jedi to see if they meet the requirements + for (Archive::AutoDeltaMap::const_iterator i = m_jediId.begin(); i != m_jediId.end(); ++i) + { + if (m_jediName[i->second].empty()) + continue; + + // filter out Jedi who don't meet the requirements + if (visibility != IGNORE_JEDI_STAT) + { + if (visibility >= 0 && m_jediVisibility[i->second] < visibility) + continue; + else if (visibility < 0 && m_jediVisibility[i->second] >= -visibility) + continue; + } + if (bountyValue != IGNORE_JEDI_STAT) + { + if (bountyValue >= 0 && m_jediBountyValue[i->second] < bountyValue) + continue; + else if (bountyValue < 0 && m_jediBountyValue[i->second] >= -bountyValue) + continue; + } + if ((m_jediLevel[i->second] <= 0) || (m_jediLevel[i->second] < minLevel) || (m_jediLevel[i->second] > maxLevel)) + continue; + if (hoursAlive != IGNORE_JEDI_STAT) + { + if (hoursAlive >= 0 && m_jediHoursAlive[i->second] < hoursAlive) + continue; + else if (hoursAlive < 0 && m_jediHoursAlive[i->second] >= -hoursAlive) + continue; + } + if (bounties != IGNORE_JEDI_STAT) + { + if (bounties >= 0 && m_jediBounties[i->second].size() < static_cast(bounties)) + continue; + else if (bounties < 0 && m_jediBounties[i->second].size() >= static_cast(-bounties)) + continue; + } + if (state != IGNORE_JEDI_STAT) + { + if ((state & m_jediState[i->second]) == 0) + continue; + } + // this Jedi is ok + jediId->push_back(i->first); + jediName->push_back(new Unicode::String(m_jediName[i->second])); + jediLocation->push_back(new Vector(m_jediLocation[i->second])); + char * scene = new char[m_jediScene[i->second].size() + 1]; + strcpy(scene, m_jediScene[i->second].c_str()); + jediScene->push_back(scene); + jediVisibility->push_back(m_jediVisibility[i->second]); + jediBountyValue->push_back(m_jediBountyValue[i->second]); + jediLevel->push_back(m_jediLevel[i->second]); + jediBounties->push_back(new std::vector(m_jediBounties[i->second])); + jediHoursAlive->push_back(m_jediHoursAlive[i->second]); + jediState->push_back(m_jediState[i->second]); + jediOnline->push_back(static_cast(m_jediOnline[i->second])); + jediSpentJediSkillPoints->push_back(m_jediSpentJediSkillPoints[i->second]); + jediFaction->push_back(m_jediFaction[i->second]); + + // find the script data for the Jedi + char buffer[1024]; + for (Archive::AutoDeltaSet::const_iterator j = m_jediScriptDataNames.begin(); + j != m_jediScriptDataNames.end(); ++j) + { + std::vector * dataList = (*jediScriptData.find(*j)).second; + NOT_NULL(dataList); + snprintf(buffer, sizeof(buffer), "%d|%s", i->second, (*j).c_str()); + Archive::AutoDeltaMap::const_iterator result = + m_jediScriptData.find(buffer); + if (result != m_jediScriptData.end()) + { + dataList->push_back((*result).second); + } + else + { + dataList->push_back(0); + } + } + } + + returnParams.addParam(*jediId, "id", true); + returnParams.addParam(*jediName, "name", true); + returnParams.addParam(*jediLocation, "location", true); + returnParams.addParam(*jediScene, "scene", true); + returnParams.addParam(*jediVisibility, "visibility", true); + returnParams.addParam(*jediBountyValue, "bountyValue", true); + returnParams.addParam(*jediLevel, "level", true); + returnParams.addParam(*jediBounties, "bounties", true); + returnParams.addParam(*jediHoursAlive, "hoursAlive", true); + returnParams.addParam(*jediState, "state", true); + returnParams.addParam(*jediOnline, "online", true); + returnParams.addParam(*jediSpentJediSkillPoints, "spentJediSkillPoints", true); + returnParams.addParam(*jediFaction, "faction", true); + + { + for (std::map *>::const_iterator iter = jediScriptData.begin(); + iter != jediScriptData.end(); ++iter) + { + returnParams.addParam(*((*iter).second), (*iter).first, true); + } + } +} // JediManagerObject::getJedi + +// ---------------------------------------------------------------------- + +/** + * Called by a script requesting a specific Jedi. + * + * @param id the id of the Jedi + * @param returnParams params that will be filled in with the Jedi data + */ +void JediManagerObject::getJedi(const NetworkId & id, ScriptParams & returnParams) const +{ + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(id); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index < 0) + return; + + returnParams.addParam(id, "id"); + returnParams.addParam(m_jediName[index], "name"); + returnParams.addParam(m_jediLocation[index], "location"); + returnParams.addParam(m_jediScene[index].c_str(), "scene"); + returnParams.addParam(m_jediVisibility[index], "visibility"); + returnParams.addParam(m_jediBountyValue[index], "bountyValue"); + returnParams.addParam(m_jediLevel[index], "level"); + returnParams.addParam(m_jediBounties[index], "bounties"); + returnParams.addParam(m_jediHoursAlive[index], "hoursAlive"); + returnParams.addParam(m_jediState[index], "state"); + returnParams.addParam(static_cast(m_jediOnline[index]), "online"); + returnParams.addParam(m_jediSpentJediSkillPoints[index], "spentJediSkillPoints"); + returnParams.addParam(m_jediFaction[index], "faction"); + + + // add the script data + char buffer[1024]; + for (Archive::AutoDeltaSet::const_iterator i = m_jediScriptDataNames.begin(); + i != m_jediScriptDataNames.end(); ++i) + { + snprintf(buffer, sizeof(buffer), "%d|%s", index, (*i).c_str()); + Archive::AutoDeltaMap::const_iterator result = + m_jediScriptData.find(buffer); + if (result != m_jediScriptData.end()) + { + returnParams.addParam((*result).second, *i); + } + else + { + returnParams.addParam(0, *i); + } + } +} // JediManagerObject::getJedi + +// ---------------------------------------------------------------------- + +/** + * Returns the location of a Jedi. + * + * @param id id of the Jedi + * @param location filled with the Jedi location + * @param scene filled with the Jedi scene + * + * @return true if the location/scene data is valid, false if we couldn't find + * the Jedi + */ +bool JediManagerObject::getJediLocation(const NetworkId & id, Vector & location, + std::string & scene) const +{ + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(id); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index < 0) + return false; + + location = m_jediLocation[index]; + scene = m_jediScene[index]; + return true; +} // JediManagerObject::getJediLocation + +// ---------------------------------------------------------------------- + +/** + * Sets up the Jedi bounties from the database. + * + * @param msg the message from the database listing all the Jedi and who + * is hunting them + */ +void JediManagerObject::addJediBounties(const BountyHunterTargetListMessage & msg) +{ + if (!isAuthoritative()) + return; + + if (m_bountyHunterTargetsReceivedFromDB.get()) + { + WARNING(true, ("JediManagerObject::addJediBounties() - attempting to apply BountyHunterTargetList from DB a second time")); + return; + } + + typedef std::vector< std::pair< NetworkId, NetworkId > > BountyList; + const BountyList & bountyList = msg.getTargetList(); + for (BountyList::const_iterator i = bountyList.begin(); i != bountyList.end(); ++i) + { + const NetworkId & jediId = (*i).second; + const NetworkId & hunterId = (*i).first; + + LOG("BountyHunterTargetList",("adding bounty from DB bh=%s jedi=%s", hunterId.getValueString().c_str(), jediId.getValueString().c_str())); + + if (jediId == NetworkId::cms_invalid || hunterId == NetworkId::cms_invalid) + continue; + + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(jediId); + int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index < 0) + { + // we need to add the Jedi + if (m_holes.empty()) + { + m_jediName.push_back(Unicode::String()); + m_jediLocation.push_back(Vector()); + m_jediScene.push_back(""); + m_jediVisibility.push_back(0); + m_jediBountyValue.push_back(0); + m_jediLevel.push_back(0); + m_jediBounties.push_back(std::vector()); + m_jediHoursAlive.push_back(0); + m_jediState.push_back(0); + m_jediOnline.push_back(0); + m_jediSpentJediSkillPoints.push_back(0); + m_jediFaction.push_back(0); + + index = m_jediName.size() - 1; + } + else + { + index = m_holes.back(); + m_holes.pop_back(); + + m_jediName.set(index, Unicode::String()); + m_jediLocation.set(index, Vector()); + m_jediScene.set(index, ""); + m_jediVisibility.set(index, 0); + m_jediBountyValue.set(index, 0); + m_jediLevel.set(index, 0); + m_jediBounties.set(index, std::vector()); + m_jediHoursAlive.set(index, 0); + m_jediState.set(index, 0); + m_jediOnline.set(index, 0); + m_jediSpentJediSkillPoints.set(index, 0); + m_jediFaction.set(index, 0); + } + + m_jediId.set(jediId, index); + } + + if (std::find(m_jediBounties[index].begin(), m_jediBounties[index].end(), hunterId) == m_jediBounties[index].end()) + { + std::vector hunters = m_jediBounties[index]; + hunters.push_back(hunterId); + m_jediBounties.set(index, hunters); + + adjustBountyCount(hunterId, 1); + } + } + + m_bountyHunterTargetsReceivedFromDB = true; +} // JediManagerObject::addJediBounties + +// ---------------------------------------------------------------------- + +/** + * Requests to assign a bounty hunter to track down a Jedi. + * + * @param target the Jedi to hunt + * @param hunter the bounty hunter + * @param successCallback name of a messageHandler than will be called if the + * bounty was assigned + * @param failCallback name of a messageHandler than will be called if the + * bounty was not assigned + * @param callbackObj the object that will receive the callback + */ +void JediManagerObject::requestJediBounty(const NetworkId & targetId, + const NetworkId & hunterId, const std::string & successCallback, + const std::string & failCallback, const NetworkId & callbackObjectId) +{ + if (isAuthoritative()) + { + bool success = false; + int bounties = 0; + + // find the target and see how many bounties they have on them + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(targetId); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + bounties = m_jediBounties[index].size(); + if (bounties < ConfigServerGame::getMaxJediBounties()) + { + success = true; + // only add the hunter to the list if he isn't on there already + if (std::find(m_jediBounties[index].begin(), m_jediBounties[index].end(), hunterId) == m_jediBounties[index].end()) + { + std::vector hunters = m_jediBounties[index]; + hunters.push_back(hunterId); + m_jediBounties.set(index, hunters); + ++bounties; + + adjustBountyCount(hunterId, 1); + + // tell the db about the change + GameServer::getInstance().sendToDatabaseServer(BountyHunterTargetMessage(hunterId, targetId)); + } + } + } + + if (callbackObjectId != NetworkId::cms_invalid) + { + // send the success or fail message + ScriptParams params; + params.addParam(targetId, "jedi"); + params.addParam(hunterId, "hunter"); + params.addParam(bounties, "bounties"); + + ScriptDictionaryPtr dictionary; + GameScriptObject::makeScriptDictionary(params, dictionary); + if (dictionary.get() != NULL) + { + dictionary->serialize(); + if (success) + { + MessageToQueue::getInstance().sendMessageToJava(callbackObjectId, + successCallback, dictionary->getSerializedData(), 0, true); + } + else + { + MessageToQueue::getInstance().sendMessageToJava(callbackObjectId, + failCallback, dictionary->getSerializedData(), 0, true); + } + } + else + { + WARNING(true, ("JediManagerObject::requestJediBounty error converting " + "params")); + } + } + + // tell the hunter to update their pvp status; this must be done after the + // callback notification message above to give script a chance to finish + // initializing the bounty mission so that we have all the information + // required to calculate pvp status + if (success) + MessageToQueue::getInstance().sendMessageToC(hunterId, "C++UpdatePvp", "", 10, false); + } + else + { + sendControllerMessageToAuthServer(CM_requestJediBounty, + new MessageQueueRequestJediBounty(targetId, hunterId, successCallback, + failCallback, callbackObjectId)); + } +} // JediManagerObject::requestJediBounty + +// ---------------------------------------------------------------------- + +/** + * Removes a bounty from a Jedi. + * + * @param targetId the Jedi + * @param hunterId the id of the bounty hunter to remove + */ +void JediManagerObject::removeJediBounty(const NetworkId & targetId, + const NetworkId & hunterId) +{ + if (isAuthoritative()) + { + // find the target and see how many bounties they have on them + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(targetId); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + std::vector hunters = m_jediBounties[index]; + std::vector::iterator i = std::find(hunters.begin(), hunters.end(), hunterId); + if (i != hunters.end()) + { + hunters.erase(i); + + // must always do this even if we end up calling removeJedi() below, + // because removeJedi() also processes the hunters list, so we need + // to remove the hunter from the hunters list or else removeJedi() + // will remove the hunter again + m_jediBounties.set(index, hunters); + adjustBountyCount(hunterId, -1); + + // if bountyValue is 0 and Jedi doesn't have any + // more bounty hunters hunting him, remove him + if ((m_jediBountyValue[index] <= 0) && (hunters.empty())) + { + removeJedi(targetId); + } + + // tell the db about the change + GameServer::getInstance().sendToDatabaseServer(BountyHunterTargetMessage(hunterId, NetworkId::cms_invalid)); + + // tell the hunter to update their pvp status + MessageToQueue::getInstance().sendMessageToC(hunterId, "C++UpdatePvp", "", 0, false); + } + } + } + else + { + sendControllerMessageToAuthServer(CM_removeJediBounty, + new MessageQueueGenericValueType >( + std::make_pair(targetId, hunterId))); + } +} // JediManagerObject::removeJediBounty + +// ---------------------------------------------------------------------- + +/** + * Removes all the bounties on a Jedi. + * + * @param targetId the Jedi + */ +void JediManagerObject::removeAllJediBounties(const NetworkId & targetId) +{ + if (isAuthoritative()) + { + // find the target and see how many bounties they have on them + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(targetId); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + std::vector hunters = m_jediBounties[index]; + for (std::vector::const_iterator i = hunters.begin(); i != hunters.end(); ++i) + { + adjustBountyCount(*i,-1); + + // tell the db about the change + GameServer::getInstance().sendToDatabaseServer(BountyHunterTargetMessage(*i, NetworkId::cms_invalid)); + + // tell the hunter to update their pvp status + MessageToQueue::getInstance().sendMessageToC(*i, "C++UpdatePvp", "", 0, false); + } + + // must always do this even if we end up calling removeJedi() below, + // because removeJedi() also processes the hunters list, so we need + // to remove all the hunter from the hunters list or else removeJedi() + // will remove the hunters again + hunters.clear(); + m_jediBounties.set(index, hunters); + + // if bountyValue is 0 and Jedi doesn't have any + // more bounty hunters hunting him, remove him + if (m_jediBountyValue[index] <= 0) + { + removeJedi(targetId); + } + } + } + else + { + sendControllerMessageToAuthServer(CM_removeAllJediBounties, + new MessageQueueGenericValueType(targetId)); + } +} // JediManagerObject::removeJediBounty + +// ---------------------------------------------------------------------- + +/** + * Tests if a Jedi is being hunted by a given bounty hunter. + * + * @param targetId the id of the Jedi + * @param hunterId the id of the bounty hunter + * + * @return true if the Jedi is being hunted, false if not + */ +bool JediManagerObject::hasBountyOnJedi(const NetworkId & targetId, + const NetworkId & hunterId) const +{ + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(targetId); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + const std::vector & hunters = m_jediBounties[index]; + return std::find(hunters.begin(), hunters.end(), hunterId) != hunters.end(); + } + return false; +} // JediManagerObject::hasBountyOnJedi + +// ---------------------------------------------------------------------- + +/** + * Tests if a given bounty hunter is hunting any Jedis + * + * @param hunterId the id of the bounty hunter + * + * @return true if the bounty hunter is hunting someone, false if not + */ +bool JediManagerObject::hasBountyOnJedi(NetworkId const & hunterId) const +{ + Archive::AutoDeltaMap::const_iterator i=m_bountyHunters.find(hunterId); + if (i==m_bountyHunters.end() || i->second<=0) + return false; + else + return true; +} + +// ---------------------------------------------------------------------- + +void JediManagerObject::queueBountyHunterTargetListFromDB(const BountyHunterTargetListMessage * bhtlm) +{ + WARNING(s_queuedBountyHunterTargetListFromDB && bhtlm, ("JediManagerObject::queueBountyHunterTargetListFromDB() - attempting to queue another BountyHunterTargetList from DB")); + + delete s_queuedBountyHunterTargetListFromDB; + s_queuedBountyHunterTargetListFromDB = bhtlm; +} + +// ---------------------------------------------------------------------- + +const std::vector & JediManagerObject::getJediBounties(const NetworkId & targetId) const +{ + const static std::vector EMPTY_ARRAY; + + Archive::AutoDeltaMap::const_iterator const indexIter = m_jediId.find(targetId); + const int index = (indexIter == m_jediId.end() ? -1 : indexIter->second); + if (index >= 0) + { + return m_jediBounties[index]; + } + return EMPTY_ARRAY; +} // JediManagerObject::getJediBounties + +// ---------------------------------------------------------------------- + +void JediManagerObject::getBountyHunterBounties(const NetworkId & hunterId, std::vector & jedis) const +{ + jedis.clear(); + + for (Archive::AutoDeltaMap::const_iterator iter = m_jediId.begin(); iter != m_jediId.end(); ++iter) + { + if (std::find(m_jediBounties[iter->second].begin(), m_jediBounties[iter->second].end(), hunterId) != m_jediBounties[iter->second].end()) + jedis.push_back(iter->first); + } +} + +// ---------------------------------------------------------------------- + +void JediManagerObject::adjustBountyCount(NetworkId const & hunterId, int const adjustment) +{ + Archive::AutoDeltaMap::const_iterator i = m_bountyHunters.find(hunterId); + int const oldBountyCount = (i!=m_bountyHunters.end()) ? i->second : 0; + int const newBountyCount = oldBountyCount + adjustment; + WARNING_DEBUG_FATAL(newBountyCount < 0,("Programmer bug: the bounty count for bounty hunter %s when below 0.", hunterId.getValueString().c_str())); + + if (newBountyCount <= 0) + m_bountyHunters.erase(hunterId); + else + m_bountyHunters.set(hunterId, newBountyCount); +} + +// ====================================================================== diff --git a/game/server/application/SwgGameServer/src/shared/object/JediManagerObject.h b/game/server/application/SwgGameServer/src/shared/object/JediManagerObject.h new file mode 100644 index 00000000..4caf3469 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/object/JediManagerObject.h @@ -0,0 +1,111 @@ +// ====================================================================== +// +// JediManagerObject.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_JediManagerObject_H +#define INCLUDED_JediManagerObject_H + +#include "serverGame/UniverseObject.h" +#include "swgSharedUtility/JediConstants.h" + +class BountyHunterTargetListMessage; +class ScriptParams; +class ServerJediManagerObjectTemplate; +class Vector; + + +// ====================================================================== + +/** + * Keeps track of what Jedi are online and grants bounty missions for them. + */ +class JediManagerObject : public UniverseObject +{ +public: + JediManagerObject(const ServerJediManagerObjectTemplate* newTemplate); + virtual ~JediManagerObject(); + + void addMembersToPackages(); + + virtual void setupUniverse(); + virtual void onServerUniverseGainedAuthority(); + virtual Controller* createDefaultController(); + virtual void conclude(); + + void addJedi(const NetworkId & id, const Unicode::String & name, const Vector & location, const std::string & scene, int visibility, int bountyValue, int level, int hoursAlive, int state, int spentJediSkillPoints, int faction); + void setJediOffline(const NetworkId & id, const Vector & location, const std::string & scene); + void removeJedi(const NetworkId & id); + void characterBeingDeleted(const NetworkId & id); + void updateJedi(const NetworkId & id, int visibility, int bountyValue, int level, int hoursAlive); + void updateJedi(const NetworkId & id, JediState state); +// void updateJedi(const NetworkId & id, const std::vector & bounties) const; + void updateJediLocation(const NetworkId & id, const Vector & location, const std::string & scene); + void updateJediSpentJediSkillPoints(const NetworkId & id, int spentJediSkillPoints); + void updateJediFaction(const NetworkId & id, int faction); + void updateJediScriptData(const NetworkId & id, const std::string & name, int value); + void removeJediScriptData(const NetworkId & id, const std::string & name); + + void getJedi(int visibility, int bountyValue, int minLevel, int maxLevel, int hoursAlive, int bounties, int state, ScriptParams & returnParams) const; + void getJedi(const NetworkId & id, ScriptParams & returnParams) const; + bool getJediLocation(const NetworkId & id, Vector & location, std::string & scene) const; + void addJediBounties(const BountyHunterTargetListMessage & msg); + void requestJediBounty(const NetworkId & targetId, const NetworkId & hunterId, const std::string & successCallback, const std::string & failCallback, const NetworkId & callbackObjectId); + void removeJediBounty(const NetworkId & targetId, const NetworkId & hunterId); + void removeAllJediBounties(const NetworkId & targetId); + const std::vector & getJediBounties(const NetworkId & targetId) const; + void getBountyHunterBounties(const NetworkId & hunterId, std::vector & jedis) const; + + bool hasBountyOnJedi(const NetworkId & targetId, const NetworkId & hunterId) const; + bool hasBountyOnJedi(NetworkId const & hunterId) const; + + static void queueBountyHunterTargetListFromDB(const BountyHunterTargetListMessage * bhtlm); + +protected: + virtual void initializeFirstTimeObject(); + virtual void endBaselines(); + +private: + JediManagerObject(const JediManagerObject&); + JediManagerObject & operator=(const JediManagerObject&); + + void adjustBountyCount(NetworkId const & hunterId, int adjustment); + +private: + // most of the jedi information are kept in vectors, which makes it very expensive + // to search, so we're going to keep a map to store the index in the vector where + // the jedi information is kept; to prevent updating the indices whenever an item is + // deleted from the vector, we will never delete items from the vector, but we + // will keep track of places in the vector that has been deleted (i.e. the "holes") + // so that when a new item is added, we add it to one of the "hole" in the vector + Archive::AutoDeltaMap m_jediId; + Archive::AutoDeltaVector m_holes; + + Archive::AutoDeltaVector m_jediName; + Archive::AutoDeltaVector m_jediLocation; + Archive::AutoDeltaVector m_jediScene; + Archive::AutoDeltaVector m_jediVisibility; + Archive::AutoDeltaVector m_jediBountyValue; + Archive::AutoDeltaVector m_jediLevel; + Archive::AutoDeltaVector > m_jediBounties; // each element of this vector is a vector of bounty hunters that are chasing the jedi + Archive::AutoDeltaMap m_bountyHunters; // map of bounty hunter id --> number of jedis being chased + Archive::AutoDeltaVector m_jediHoursAlive; + Archive::AutoDeltaVector m_jediState; + // this should actuall be a vector of bool, but it won't compile in VC + Archive::AutoDeltaVector m_jediOnline; + Archive::AutoDeltaVector m_jediSpentJediSkillPoints; + Archive::AutoDeltaVector m_jediFaction; + Archive::AutoDeltaMap m_jediScriptData; + + // this contains all the names that are used to make up the key value in m_jediScriptData + Archive::AutoDeltaSet m_jediScriptDataNames; + + // indicates whether the bounty hunter target list has been received from the DB + Archive::AutoDeltaVariable m_bountyHunterTargetsReceivedFromDB; +}; + +// ====================================================================== + +#endif diff --git a/game/server/application/SwgGameServer/src/shared/object/SwgCreatureObject.cpp b/game/server/application/SwgGameServer/src/shared/object/SwgCreatureObject.cpp new file mode 100644 index 00000000..e1ab4b18 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/object/SwgCreatureObject.cpp @@ -0,0 +1,338 @@ +//======================================================================== +// +// SwgCreatureObject.cpp +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#include "FirstSwgGameServer.h" +#include "SwgGameServer/SwgCreatureObject.h" +#include "serverGame/PlayerCreatureController.h" +#include "serverGame/PlayerObject.h" +#include "serverGame/ServerCreatureObjectTemplate.h" +#include "serverNetworkMessages/MessageToPayload.h" +#include "SwgGameServer/JediManagerObject.h" +#include "SwgGameServer/SwgPlayerCreatureController.h" +#include "SwgGameServer/SwgPlayerObject.h" +#include "SwgGameServer/SwgServerUniverse.h" + + +//---------------------------------------------------------------------- + +/** + * Class constructor. + */ +SwgCreatureObject::SwgCreatureObject(const ServerCreatureObjectTemplate* newTemplate) : + CreatureObject(newTemplate) +{ +} // SwgCreatureObject::SwgCreatureObject + +//---------------------------------------------------------------------- + +/** + * Class destructor. + */ +SwgCreatureObject::~SwgCreatureObject() +{ + //-- This must be the first line in the destructor to invalidate any watchers watching this object + nullWatchers(); + +} // SwgCreatureObject::~SwgCreatureObject + +//---------------------------------------------------------------------- + +/** + * Creates a default controller for this object. + * + * @return the object's controller + */ +Controller* SwgCreatureObject::createDefaultController () +{ + const ServerCreatureObjectTemplate * myTemplate = safe_cast< + const ServerCreatureObjectTemplate *>(getObjectTemplate()); + + Controller * controller = 0; + if (myTemplate->getCanCreateAvatar()) + { + controller = new SwgPlayerCreatureController(this); + } + else + { + controller = CreatureObject::createDefaultController(); + } + + setController(controller); + return controller; +} // CreatureObject::createDefaultController + +//---------------------------------------------------------------------- + +/** + * Called to alter the creature. + */ +float SwgCreatureObject::alter(float time) +{ + if (isAuthoritative() && isPlayerControlled() && (getBountyValue() > 0)) + { + PlayerObject * const player = PlayerCreatureController::getPlayerObject(this); + if (player) + { + SwgPlayerObject * swgPlayer = safe_cast(player); + swgPlayer->updateJediLocationTime(time); + } + } + return CreatureObject::alter(time); +} // SwgCreatureObject::alter + +//---------------------------------------------------------------------- + +/** + * Called when the creature is being removed from the world. + */ +void SwgCreatureObject::onRemovingFromWorld() +{ + // if we are a Jedi, flag ourself as offline + if (isAuthoritative() && isPlayerControlled() && (getBountyValue() > 0)) + { + JediManagerObject * const jediManager = static_cast(ServerUniverse::getInstance()).getJediManager(); + if (jediManager != NULL) + { + jediManager->setJediOffline(getNetworkId(), getPosition_w(), getSceneId()); + } + } + + CreatureObject::onRemovingFromWorld(); +} // SwgCreatureObject::onRemovingFromWorld + +//---------------------------------------------------------------------- + +/** + * Called when the creature is being deleted from the game. + */ +void SwgCreatureObject::onPermanentlyDestroyed() +{ + // if we are a Jedi, remove ourself from the Jedi manager + if (isAuthoritative() && isPlayerControlled() && (getBountyValue() > 0)) + { + JediManagerObject * const jediManager = static_cast(ServerUniverse::getInstance()).getJediManager(); + if (jediManager != NULL) + { + jediManager->removeJedi(getNetworkId()); + } + } + + CreatureObject::onPermanentlyDestroyed(); +} // SwgCreatureObject::onPermanentlyDestroyed + +//---------------------------------------------------------------------- + +/** + * Handles messages to this object. + * + * @param message the message + */ +void SwgCreatureObject::handleCMessageTo (const MessageToPayload &message) +{ + CreatureObject::handleCMessageTo (message); +} // SwgCreatureObject::handleCMessageTo + +//---------------------------------------------------------------------- + +/** +* Checks if a player is a Jedi or not. +*/ +bool SwgCreatureObject::isJedi(void) const +{ + if (!isPlayerControlled()) + return false; + + PlayerObject const * const player = PlayerCreatureController::getPlayerObject(this); + if (player) + { + SwgPlayerObject const * const swgPlayer = safe_cast(player); + return swgPlayer->isJedi(); + } + + return false; +} // SwgCreatureObject::isJedi + +//----------------------------------------------------------------------- + +/** +* Returns the number of skill points that have been spent on Jedi skills. +*/ +const int SwgCreatureObject::getSpentJediSkillPoints() const +{ + int result = 0; + + /* skill points no longer exist + const SkillList & skills = getSkillList(); + for (SkillList::const_iterator i = skills.begin(); i != skills.end(); ++i) + { + if (*i) + { + // per Dave White, we only care about skills starting with "force_discipline" + if ((*i)->getSkillName().find("force_discipline") == 0) + result += (*i)->getSkillPointCost(); + } + else + { + WARNING(true, ("Creature %s had a null in their skill list", getNetworkId().getValueString().c_str())); + } + } + */ + return result; +} // SwgCreatureObject::getSpentJediSkillPoints + +//---------------------------------------------------------------------- + +/** + * Tests if this creature has a bounty on another creature. + * + * @param target the creature to test if we have a bounty on + * + * @return true if we have a bounty on the target, false if not + */ +bool SwgCreatureObject::hasBounty(const CreatureObject & target) const +{ + const SwgCreatureObject * swgTarget = dynamic_cast( + &target); + if (swgTarget == NULL) + return false; + + JediManagerObject * jediManager = static_cast( + ServerUniverse::getInstance()).getJediManager(); + NOT_NULL(jediManager); + + return jediManager->hasBountyOnJedi(target.getNetworkId(), getNetworkId()); +} // SwgCreatureObject::hasBounty + +// ---------------------------------------------------------------------- + +/** + * Tests if this creature has a bounty on any other creature. + * + * @return true if we have a bounty, false if not + */ +bool SwgCreatureObject::hasBounty() const +{ + JediManagerObject * jediManager = static_cast( + ServerUniverse::getInstance()).getJediManager(); + NOT_NULL(jediManager); + + return jediManager->hasBountyOnJedi(getNetworkId()); +} + +// ---------------------------------------------------------------------- + +std::vector const & SwgCreatureObject::getJediBountiesOnMe() const +{ + JediManagerObject * jediManager = static_cast( + ServerUniverse::getInstance()).getJediManager(); + NOT_NULL(jediManager); + + return jediManager->getJediBounties(getNetworkId()); +} + +// ---------------------------------------------------------------------- + +int SwgCreatureObject::getBountyValue() const +{ + int bountyValue; + if (getObjVars().getItem("bounty.amount", bountyValue)) + return bountyValue; + + return 0; +} + +//------------------------------------------------------------------------------------------ + +const bool SwgCreatureObject::grantSkill(const SkillObject & newSkill) +{ + return CreatureObject::grantSkill(newSkill); +} // SwgCreatureObject::grantSkill + +//----------------------------------------------------------------------- + +void SwgCreatureObject::revokeSkill(const SkillObject & oldSkill) +{ + CreatureObject::revokeSkill(oldSkill); +} // SwgCreatureObject::revokeSkill + +//------------------------------------------------------------------------------------------ + +void SwgCreatureObject::endBaselines() +{ + CreatureObject::endBaselines(); + + // if the player has a bounty value, register him with the bounty manager + if (isAuthoritative() && isPlayerControlled()) + { + int bountyValue = getBountyValue(); + if (bountyValue > 0) + { + SwgPlayerObject const * player = safe_cast(PlayerCreatureController::getPlayerObject(this)); + if (player) + { + JediManagerObject * jediManager = static_cast(ServerUniverse::getInstance()).getJediManager(); + if (jediManager) + { + jediManager->addJedi(getNetworkId(), getObjectName(), + getPosition_w(), getSceneId(), player->getJediVisibility(), + bountyValue, getLevel(), + 0, player->getJediState(), getSpentJediSkillPoints(), getPvpFaction()); + } + } + } + } +} + +//------------------------------------------------------------------------------------------ + +void SwgCreatureObject::onAddedToWorld() +{ + CreatureObject::onAddedToWorld(); + if (isAuthoritative() && isPlayerControlled() && (getBountyValue() > 0)) + { + JediManagerObject * jediManager = static_cast(ServerUniverse::getInstance()).getJediManager(); + if (jediManager != NULL) + { + jediManager->updateJediLocation(getNetworkId(), getPosition_w(), getSceneId()); + } + } +} + +//------------------------------------------------------------------------------------------ + +void SwgCreatureObject::levelChanged() const +{ + CreatureObject::levelChanged(); + + // If the player has a bounty value, update the level with the bounty manager + if (isAuthoritative() && isPlayerControlled() && (getBountyValue() > 0)) + { + JediManagerObject * jediManager = static_cast(ServerUniverse::getInstance()).getJediManager(); + if (jediManager) + { + jediManager->updateJedi(getNetworkId(), -1, -1, getLevel(), -1); + } + } +} + +//------------------------------------------------------------------------------------------ + +void SwgCreatureObject::setPvpFaction(Pvp::FactionId factionId) +{ + Pvp::FactionId oldId = getPvpFaction(); + CreatureObject::setPvpFaction(factionId); + Pvp::FactionId newId = getPvpFaction(); + if ((oldId != newId) && isAuthoritative() && isPlayerControlled() && (getBountyValue() > 0)) + { + JediManagerObject * jediManager = static_cast(ServerUniverse::getInstance()).getJediManager(); + if (jediManager != NULL) + { + jediManager->updateJediFaction(getNetworkId(), newId); + } + } +} diff --git a/game/server/application/SwgGameServer/src/shared/object/SwgCreatureObject.h b/game/server/application/SwgGameServer/src/shared/object/SwgCreatureObject.h new file mode 100644 index 00000000..8473a4e8 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/object/SwgCreatureObject.h @@ -0,0 +1,61 @@ +//======================================================================== +// +// SwgCreatureObject.h +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#ifndef INCLUDED_SwgCreatureObject_H +#define INCLUDED_SwgCreatureObject_H + +#include "serverGame/CreatureObject.h" + + +class ServerCreatureObjectTemplate; + + +//---------------------------------------------------------------------- + +class SwgCreatureObject : public CreatureObject +{ +public: + explicit SwgCreatureObject(const ServerCreatureObjectTemplate * newTemplate); + virtual ~SwgCreatureObject(); + + virtual void handleCMessageTo (const MessageToPayload &message); + + bool isJedi(void) const; + const int getSpentJediSkillPoints() const; + + virtual Controller* createDefaultController(); + virtual float alter(float time); + virtual void onRemovingFromWorld(); + virtual void onPermanentlyDestroyed(); + + virtual bool hasBounty(const CreatureObject & target) const; + virtual bool hasBounty() const; + virtual std::vector const & getJediBountiesOnMe() const; + int getBountyValue() const; + + virtual const bool grantSkill(const SkillObject & newSkill); + virtual void revokeSkill(const SkillObject & oldSkill); + + virtual void setPvpFaction(Pvp::FactionId factionId); + +protected: + virtual void endBaselines(); + virtual void onAddedToWorld(); + virtual void levelChanged() const; + +private: + SwgCreatureObject(); + SwgCreatureObject(const SwgCreatureObject& rhs); + SwgCreatureObject& operator=(const SwgCreatureObject& rhs); +}; + + +//---------------------------------------------------------------------- + + +#endif // INCLUDED_SwgCreatureObject_H diff --git a/game/server/application/SwgGameServer/src/shared/object/SwgPlayerObject.cpp b/game/server/application/SwgGameServer/src/shared/object/SwgPlayerObject.cpp new file mode 100644 index 00000000..ef587054 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/object/SwgPlayerObject.cpp @@ -0,0 +1,374 @@ +//======================================================================== +// +// SwgCreatureObject.cpp +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#include "FirstSwgGameServer.h" +#include "SwgGameServer/SwgCreatureObject.h" +#include "SwgGameServer/SwgPlayerObject.h" +#include "serverGame/ConfigServerGame.h" +#include "serverGame/CreatureObject.h" +#include "serverGame/PlayerObject.h" +#include "serverNetworkMessages/MessageToPayload.h" +#include "sharedFoundation/DynamicVariableList.h" +#include "sharedNetworkMessages/MessageQueueGenericValueType.h" +#include "SwgGameServer/JediManagerObject.h" +#include "SwgGameServer/SwgServerUniverse.h" +#include "serverGame/PlayerCreatureController.h" + + +//---------------------------------------------------------------------- + +// jedi/force power objvars +const static std::string OBJVAR_JEDI("jedi"); +const static std::string OBJVAR_JEDI_STATE("jedi.state"); +const static std::string OBJVAR_FORCE_REGEN_RATE("jedi.regenrate"); +const static std::string OBJVAR_FORCE_REGEN_VALUE("jedi.regenvalue"); +const static std::string OBJVAR_JEDI_VISIBILITY("jedi.visibility"); +const static std::string OBJVAR_JEDI_BOUNTIES("jedi.objKillers"); + + +//---------------------------------------------------------------------- + +/** + * Class constructor. + */ +SwgPlayerObject::SwgPlayerObject(const ServerPlayerObjectTemplate* newTemplate) : + PlayerObject(newTemplate), + m_updateJediLocationTime(0), + m_jediState(0) +{ + addMembersToPackages(); +} // SwgCreatureObject::SwgCreatureObject + +//---------------------------------------------------------------------- + +/** + * Class destructor. + */ +SwgPlayerObject::~SwgPlayerObject() +{ +} // SwgPlayerObject::~SwgPlayerObject + +//---------------------------------------------------------------------- + +/** + * Sets up auto-sync data. + */ +void SwgPlayerObject::addMembersToPackages() +{ + //@todo: do we want to make a game equivalent of package.txt and Packager.cpp? + addFirstParentAuthClientServerVariable_np (m_jediState); +} // SwgPlayerObject::addMembersToPackages + +//---------------------------------------------------------------------- + +/** + * Initializes data for a proxy object. + */ +void SwgPlayerObject::endBaselines() +{ + PlayerObject::endBaselines(); + + if (isAuthoritative()) + { + // get the jediState from the objvar + int jediState = 0; + if (getObjVars().getItem(OBJVAR_JEDI_STATE, jediState)) + m_jediState = static_cast(jediState); + } +} // SwgPlayerObject::endBaselines + +//---------------------------------------------------------------------- + +/** + * Called when we are made authoritative. + */ +void SwgPlayerObject::virtualOnSetAuthority() +{ + PlayerObject::virtualOnSetAuthority(); + + const SwgCreatureObject * owner = safe_cast(getCreatureObject()); + if ((owner != NULL) && owner->isPlayerControlled() && (owner->getBountyValue() > 0)) + { + // tell the Jedi manager our position + JediManagerObject * jediManager = static_cast( + ServerUniverse::getInstance()).getJediManager(); + if (jediManager != NULL) + { + jediManager->updateJediLocation(owner->getNetworkId(), + owner->getPosition_w(), owner->getSceneId()); + } + m_updateJediLocationTime = 0; + } +} // SwgPlayerObject::virtualOnSetAuthority + +//---------------------------------------------------------------------- + +/** + * Sets the Jedi state for the player. + * + * @param state the new state + */ +void SwgPlayerObject::setJediState(JediState state) +{ + if (state == JS_none || + state == JS_forceSensitive || + state == JS_jedi || + state == JS_forceRankedLight || + state == JS_forceRankedDark + ) + { + if (isAuthoritative()) + { + // get our current state for comparison + JediState oldState = getJediState(); + bool oldIsJedi = isJedi(); + + m_jediState = state; + if (state == JS_none) + { + if (oldState != JS_none) + { + // we are no longer force sensitive + removeObjVarItem(OBJVAR_JEDI); + setMaxForcePower(0); + } + } + else + { + setObjVarItem(OBJVAR_JEDI_STATE, state); + if (oldState == JS_none) + { + // we are newly force sensitive + // note that our max force power needs to be set separately + WARNING(getForcePowerRegenRate() > 0, ("SwgPlayerObject::setJediState, " + "resetting force power regen for player %s that has a non-zero " + "regen value %f", getAccountDescription(getCreatureObject()).c_str(), + getForcePowerRegenRate())); + setForcePowerRegenRate(ConfigServerGame::getMinForcePowerRegenRate()); + } + } + + // check if our Jedi status has turned on or off + if (!oldIsJedi && isJedi()) + { + setJediVisibility(0); + } + } + else + { + sendControllerMessageToAuthServer(CM_setJediState, + new MessageQueueGenericValueType(static_cast(state))); + } + } + else + { + WARNING(true, ("setJediState for player %s invalid state %d", + getAccountDescription(getCreatureObject()).c_str(), state)); + } +} + +//---------------------------------------------------------------------- + +/** + * Updates the time from when we sent the Jedi manager our position. + * + * @param time time since the last call + */ +void SwgPlayerObject::updateJediLocationTime(float time) +{ + if (isAuthoritative()) + { + m_updateJediLocationTime += time; + if (m_updateJediLocationTime > static_cast( + ConfigServerGame::getJediUpdateLocationTimeSeconds())) + { + m_updateJediLocationTime = 0; + + // tell the Jedi manager our position + JediManagerObject * jediManager = static_cast( + ServerUniverse::getInstance()).getJediManager(); + if (jediManager != NULL) + { + const CreatureObject * owner = getCreatureObject(); + if (owner->isInWorld()) + { + jediManager->updateJediLocation(owner->getNetworkId(), + owner->getPosition_w(), owner->getSceneId()); + } + } + } + } +} // SwgPlayerObject::updateJediLocationTime + +//---------------------------------------------------------------------- + +/** + * Sets the visibility of a Jedi. + * + * @param visibility the visibility value + */ +void SwgPlayerObject::setJediVisibility(int visibility) +{ + if (!isJedi()) + return; + + if (visibility < 0) + visibility = 0; + + setObjVarItem(OBJVAR_JEDI_VISIBILITY, visibility); +} // SwgPlayerObject::setJediVisibility + +//---------------------------------------------------------------------- + +/** + * Returns the visibility of a Jedi. + * + * @return the visibility of the Jedi + */ +int SwgPlayerObject::getJediVisibility(void) const +{ + if (!isJedi()) + return 0; + + int visibility; + if (!getObjVars().getItem(OBJVAR_JEDI_VISIBILITY,visibility)) + { + WARNING(true, ("Jedi %s doesn't have a visibility objvar, adding one", + getNetworkId().getValueString().c_str())); + const_cast(this)->setJediVisibility(0); + return 0; + } + return visibility; +} // SwgPlayerObject::getJediVisibility + +//---------------------------------------------------------------------- + +/** + * Adds a bounty hunter to the list of players hunting this Jedi. + * + * @param hunter the bounty hunter's id + */ +/* +void SwgPlayerObject::addJediBounty(const NetworkId & hunter) +{ + if (!isJedi()) + return; + + std::vector bounties; + if (getObjVars().getItem(OBJVAR_JEDI_BOUNTIES, bounties)) + { + // make sure we don't have the hunter already on our list + if (std::find(bounties.begin(), bounties.end(), hunter) == bounties.end()) + { + bounties.push_back(hunter); + setObjVarItem(OBJVAR_JEDI_BOUNTIES, bounties); + } + } + + // note that since this function should only be called due to the Jedi + // manager being updated, so we don't forward this to the manager like + // we do with setJediBounties +} // SwgPlayerObject::addJediBounty +*/ + +//---------------------------------------------------------------------- + +/** + * Removes a bounty hunter from the list of players hunting this Jedi. + * + * @param hunter the bounty hunter's id + */ +/* +void SwgPlayerObject::removeJediBounty(const NetworkId & hunter) +{ + if (!isJedi()) + return; + + std::vector bounties; + if (getObjVars().getItem(OBJVAR_JEDI_BOUNTIES, bounties)) + { + std::vector::iterator i = std::find(bounties.begin(), + bounties.end(), hunter); + if (i != bounties.end()) + { + bounties.erase(i); + setObjVarItem(OBJVAR_JEDI_BOUNTIES, bounties); + } + } + + // note that since this function should only be called due to the Jedi + // manager being updated, so we don't forward this to the manager like + // we do with setJediBounties +} // SwgPlayerObject::removeJediBounty +*/ + +//---------------------------------------------------------------------- + +/** + * Sets the bounties on a Jedi. + * + * @param bounties the number of bounties + * +void SwgPlayerObject::setJediBounties(const std::vector & bounties) +{ + if (!isJedi()) + return; + + setObjVarItem(OBJVAR_JEDI_BOUNTIES, bounties); + + // update the Jedi manager + JediManagerObject * jediManager = static_cast( + ServerUniverse::getInstance()).getJediManager(); + if (jediManager != NULL) + { + const CreatureObject * owner = getCreatureObject(); + jediManager->updateJedi(owner->getNetworkId(), bounties); + } +} // SwgPlayerObject::setJediBounties +*/ +//---------------------------------------------------------------------- + +/** + * Returns the bounties on a Jedi once for old characters. Once this function is + * called for a player, assume the Jedi manager is authoritative for who + * has bounties on this Jedi. + * + * @param bounties vector to be filled in with the ids of the players + * hunting the Jedi + * + * @return true if bounties has good data, false if not + */ +/* +bool SwgPlayerObject::getJediBounties(std::vector & bounties) +{ + if (!isJedi()) + return false; + + bounties.clear(); + SwgCreatureObject * owner = safe_cast(getCreatureObject()); + if (owner != NULL) + { + if (owner->getObjVars().getItem(OBJVAR_JEDI_BOUNTIES, bounties)) + { + // remove the objvar, the Jedi manager is authoritative for this data + owner->removeObjVarItem(OBJVAR_JEDI_BOUNTIES); + } + } + return true; +} // SwgPlayerObject::getJediBounties +*/ +/** + * Calculates whether a player is a jedi + * + * @return true if the player is a jedi + */ +bool SwgPlayerObject::isJedi() const +{ + return (getJediState() & (JS_jedi | JS_forceRankedLight | JS_forceRankedDark)) != 0; +} + diff --git a/game/server/application/SwgGameServer/src/shared/object/SwgPlayerObject.h b/game/server/application/SwgGameServer/src/shared/object/SwgPlayerObject.h new file mode 100644 index 00000000..2e5f6150 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/object/SwgPlayerObject.h @@ -0,0 +1,66 @@ +//======================================================================== +// +// SwgPlayerObject.h +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#ifndef INCLUDED_SwgPlayerObject_H +#define INCLUDED_SwgPlayerObject_H + +#include "serverGame/PlayerObject.h" +#include "swgSharedUtility/JediConstants.h" + +class ServerPlayerObjectTemplate; + + +//---------------------------------------------------------------------- + +class SwgPlayerObject : public PlayerObject +{ +public: + explicit SwgPlayerObject(const ServerPlayerObjectTemplate * newTemplate); + virtual ~SwgPlayerObject(); + + // Jedi functions + virtual bool isJedi(void) const; + JediState getJediState() const; + void setJediState(JediState state); + void updateJediLocationTime(float time); + void setJediVisibility(int visibility); + int getJediVisibility(void) const; +// void addJediBounty(const NetworkId & hunter); +// void removeJediBounty(const NetworkId & hunter); +// void setJediBounties(const std::vector & bounties); +// bool getJediBounties(std::vector & bounties); + +protected: + virtual void endBaselines(); + virtual void virtualOnSetAuthority(); + +private: + void addMembersToPackages(); + +// bool getJediBounties(std::vector & bounties); + +private: + SwgPlayerObject(); + SwgPlayerObject(const SwgPlayerObject & rhs); + SwgPlayerObject & operator=(const SwgPlayerObject & rhs); + +private: + float m_updateJediLocationTime; + Archive::AutoDeltaVariable m_jediState; +}; + + +//---------------------------------------------------------------------- + +inline JediState SwgPlayerObject::getJediState() const +{ + return static_cast(m_jediState.get()); +} + + +#endif // INCLUDED_SwgPlayerObject_H diff --git a/game/server/application/SwgGameServer/src/shared/objectTemplate/ServerJediManagerObjectTemplate.cpp b/game/server/application/SwgGameServer/src/shared/objectTemplate/ServerJediManagerObjectTemplate.cpp new file mode 100644 index 00000000..90edb0a3 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/objectTemplate/ServerJediManagerObjectTemplate.cpp @@ -0,0 +1,186 @@ +//======================================================================== +// +// ServerJediManagerObjectTemplate.cpp +// +//IMPORTANT: Any code between //@BEGIN TFD... and //@END TFD... will be +//overwritten the next time the template definition is compiled. Do not +//make changes to code inside these blocks. +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#include "FirstSwgGameServer.h" +#include "ServerJediManagerObjectTemplate.h" +#include "sharedDebug/DataLint.h" +#include "sharedFile/Iff.h" +#include "sharedObject/ObjectTemplate.h" +#include "sharedObject/ObjectTemplateList.h" +#include "SwgGameServer/JediManagerObject.h" +//@BEGIN TFD TEMPLATE REFS +//@END TFD TEMPLATE REFS +#include + +const std::string DefaultString(""); +const StringId DefaultStringId("", 0); +const Vector DefaultVector(0,0,0); +const TriggerVolumeData DefaultTriggerVolumeData; + +bool ServerJediManagerObjectTemplate::ms_allowDefaultTemplateParams = true; + + +/** + * Class constructor. + */ +ServerJediManagerObjectTemplate::ServerJediManagerObjectTemplate(const std::string & filename) +//@BEGIN TFD INIT + : ServerUniverseObjectTemplate(filename) + ,m_versionOk(true) +//@END TFD INIT +{ +} // ServerJediManagerObjectTemplate::ServerJediManagerObjectTemplate + +/** + * Class destructor. + */ +ServerJediManagerObjectTemplate::~ServerJediManagerObjectTemplate() +{ +//@BEGIN TFD CLEANUP +//@END TFD CLEANUP +} // ServerJediManagerObjectTemplate::~ServerJediManagerObjectTemplate + +/** + * Static function used to register this template. + */ +void ServerJediManagerObjectTemplate::registerMe(void) +{ + ObjectTemplateList::registerTemplate(ServerJediManagerObjectTemplate_tag, create); +} // ServerJediManagerObjectTemplate::registerMe + +/** + * Creates a ServerJediManagerObjectTemplate template. + * + * @return a new instance of the template + */ +ObjectTemplate * ServerJediManagerObjectTemplate::create(const std::string & filename) +{ + return new ServerJediManagerObjectTemplate(filename); +} // ServerJediManagerObjectTemplate::create + +/** + * Returns the template id. + * + * @return the template id + */ +Tag ServerJediManagerObjectTemplate::getId(void) const +{ + return ServerJediManagerObjectTemplate_tag; +} // ServerJediManagerObjectTemplate::getId + +/** + * Returns this template's version. + * + * @return the version + */ +Tag ServerJediManagerObjectTemplate::getTemplateVersion(void) const +{ + return m_templateVersion; +} // ServerJediManagerObjectTemplate::getTemplateVersion + +/** + * Returns the highest version of this template or it's base templates. + * + * @return the highest version + */ +Tag ServerJediManagerObjectTemplate::getHighestTemplateVersion(void) const +{ + if (m_baseData == NULL) + return m_templateVersion; + const ServerJediManagerObjectTemplate * base = dynamic_cast(m_baseData); + if (base == NULL) + return m_templateVersion; + return std::max(m_templateVersion, base->getHighestTemplateVersion()); +} // ServerJediManagerObjectTemplate::getHighestTemplateVersion + +/** + * Creates a new object from this template. + * + * @return the object + */ +Object * ServerJediManagerObjectTemplate::createObject(void) const +{ + return new JediManagerObject(this); +} // ServerJediManagerObjectTemplate::createObject + +//@BEGIN TFD +#ifdef _DEBUG +/** + * Special function used by datalint. Checks for duplicate values in base and derived templates. + */ +void ServerJediManagerObjectTemplate::testValues(void) const +{ + ServerUniverseObjectTemplate::testValues(); +} // ServerJediManagerObjectTemplate::testValues +#endif + +/** + * Loads the template data from an iff file. We should already be in the form + * for this template. + * + * @param file file to load from + */ +void ServerJediManagerObjectTemplate::load(Iff &file) +{ +static const int MAX_NAME_SIZE = 256; +char paramName[MAX_NAME_SIZE]; + + if (file.getCurrentName() != ServerJediManagerObjectTemplate_tag) + { + ServerUniverseObjectTemplate::load(file); + return; + } + + file.enterForm(); + m_templateVersion = file.getCurrentName(); + if (m_templateVersion == TAG(D,E,R,V)) + { + file.enterForm(); + file.enterChunk(); + std::string baseFilename; + file.read_string(baseFilename); + file.exitChunk(); + const ObjectTemplate *base = ObjectTemplateList::fetch(baseFilename); + DEBUG_WARNING(base == NULL, ("was unable to load base template %s", baseFilename.c_str())); + if (m_baseData == base && base != NULL) + base->releaseReference(); + else + { + if (m_baseData != NULL) + m_baseData->releaseReference(); + m_baseData = base; + } + file.exitForm(); + m_templateVersion = file.getCurrentName(); + } + if (getHighestTemplateVersion() != TAG(0,0,0,0)) + { + if (DataLint::isEnabled()) + DEBUG_WARNING(true, ("template %s version out of date", file.getFileName())); + m_versionOk = false; + } + + file.enterForm(); + + file.enterChunk(); + int paramCount = file.read_int32(); + file.exitChunk(); + UNREF(paramName); + UNREF(paramCount); + + file.exitForm(); + ServerUniverseObjectTemplate::load(file); + file.exitForm(); + return; +} // ServerJediManagerObjectTemplate::load + +//@END TFD diff --git a/game/server/application/SwgGameServer/src/shared/objectTemplate/ServerJediManagerObjectTemplate.h b/game/server/application/SwgGameServer/src/shared/objectTemplate/ServerJediManagerObjectTemplate.h new file mode 100644 index 00000000..4244461a --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/objectTemplate/ServerJediManagerObjectTemplate.h @@ -0,0 +1,87 @@ +//======================================================================== +// +// ServerJediManagerObjectTemplate.h +// +//IMPORTANT: Any code between //@BEGIN TFD... and //@END TFD... will be +//overwritten the next time the template definition is compiled. Do not +//make changes to code inside these blocks. +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#ifndef _INCLUDED_ServerJediManagerObjectTemplate_H +#define _INCLUDED_ServerJediManagerObjectTemplate_H + +#include "serverGame/ServerUniverseObjectTemplate.h" +#include "sharedFoundation/DynamicVariable.h" +#include "sharedUtility/TemplateParameter.h" + + +class Vector; +typedef StructParam StructParamOT; +//@BEGIN TFD TEMPLATE REFS +//@END TFD TEMPLATE REFS + + +class ServerJediManagerObjectTemplate : public ServerUniverseObjectTemplate +{ +public: +//@BEGIN TFD ID + enum + { + ServerJediManagerObjectTemplate_tag = TAG(J,E,D,I) + }; +//@END TFD ID +public: + ServerJediManagerObjectTemplate(const std::string & filename); + virtual ~ServerJediManagerObjectTemplate(); + + virtual Tag getId(void) const; + virtual Tag getTemplateVersion(void) const; + virtual Tag getHighestTemplateVersion(void) const; + static void install(bool allowDefaultTemplateParams = true); + +//@BEGIN TFD +public: + +#ifdef _DEBUG +public: + // special code used by datalint + virtual void testValues(void) const; +#endif + +protected: + virtual void load(Iff &file); + +private: +//@END TFD + +public: + // user functions + virtual Object * createObject(void) const; + +private: + Tag m_templateVersion; // the template version + bool m_versionOk; // flag that the template version loaded is the one we expect + static bool ms_allowDefaultTemplateParams; // flag to allow defaut params instead of fataling + + static void registerMe(void); + static ObjectTemplate * create(const std::string & filename); + + // no copying + ServerJediManagerObjectTemplate(const ServerJediManagerObjectTemplate &); + ServerJediManagerObjectTemplate & operator =(const ServerJediManagerObjectTemplate &); +}; + + +inline void ServerJediManagerObjectTemplate::install(bool allowDefaultTemplateParams) +{ + ms_allowDefaultTemplateParams = allowDefaultTemplateParams; +//@BEGIN TFD INSTALL + ServerJediManagerObjectTemplate::registerMe(); +//@END TFD INSTALL +} + + +#endif // _INCLUDED_ServerJediManagerObjectTemplate_H diff --git a/game/server/application/SwgGameServer/src/shared/objectTemplate/SwgServerCreatureObjectTemplate.cpp b/game/server/application/SwgGameServer/src/shared/objectTemplate/SwgServerCreatureObjectTemplate.cpp new file mode 100644 index 00000000..81fd99fd --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/objectTemplate/SwgServerCreatureObjectTemplate.cpp @@ -0,0 +1,57 @@ +//======================================================================== +// +// SwgServerCreatureObjectTemplate.cpp +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#include "FirstSwgGameServer.h" +#include "SwgGameServer/SwgServerCreatureObjectTemplate.h" +#include "sharedObject/ObjectTemplateList.h" +#include "SwgGameServer/SwgCreatureObject.h" + + +/** + * Class constructor. + */ +SwgServerCreatureObjectTemplate::SwgServerCreatureObjectTemplate(const std::string & filename) : + ServerCreatureObjectTemplate(filename) +{ +} // SwgServerCreatureObjectTemplate::SwgServerCreatureObjectTemplate + +/** + * Class destructor. + */ +SwgServerCreatureObjectTemplate::~SwgServerCreatureObjectTemplate() +{ +} // SwgServerCreatureObjectTemplate::~SwgServerCreatureObjectTemplate + +/** + * Replaces the ServerCreatureObjectTemplate tag->create mapping with our own. + */ +void SwgServerCreatureObjectTemplate::install(void) +{ + ObjectTemplateList::assignBinding(ServerCreatureObjectTemplate_tag, create); +} // SwgServerCreatureObjectTemplate::install + +/** + * Creates a SwgServerCreatureObjectTemplate template. + * + * @return a new instance of the template + */ +ObjectTemplate * SwgServerCreatureObjectTemplate::create(const std::string & filename) +{ + return new SwgServerCreatureObjectTemplate(filename); +} // SwgServerCreatureObjectTemplate::create + +/** + * Creates a new object from this template. + * + * @return the object + */ +Object * SwgServerCreatureObjectTemplate::createObject(void) const +{ + return new SwgCreatureObject(this); +} // SwgServerCreatureObjectTemplate::createObject + diff --git a/game/server/application/SwgGameServer/src/shared/objectTemplate/SwgServerCreatureObjectTemplate.h b/game/server/application/SwgGameServer/src/shared/objectTemplate/SwgServerCreatureObjectTemplate.h new file mode 100644 index 00000000..cd2ed394 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/objectTemplate/SwgServerCreatureObjectTemplate.h @@ -0,0 +1,33 @@ +//======================================================================== +// +// SwgServerCreatureObjectTemplate.h +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#ifndef _INCLUDED_SwgServerCreatureObjectTemplate_H +#define _INCLUDED_SwgServerCreatureObjectTemplate_H + +#include "serverGame/ServerCreatureObjectTemplate.h" + + +class SwgServerCreatureObjectTemplate : public ServerCreatureObjectTemplate +{ +public: + SwgServerCreatureObjectTemplate(const std::string & filename); + virtual ~SwgServerCreatureObjectTemplate(); + + static void install(void); + virtual Object * createObject(void) const; + +private: + static ObjectTemplate * create(const std::string & filename); + + // no copying + SwgServerCreatureObjectTemplate(const SwgServerCreatureObjectTemplate &); + SwgServerCreatureObjectTemplate & operator =(const SwgServerCreatureObjectTemplate &); +}; + + +#endif // _INCLUDED_SwgServerCreatureObjectTemplate_H diff --git a/game/server/application/SwgGameServer/src/shared/objectTemplate/SwgServerPlayerObjectTemplate.cpp b/game/server/application/SwgGameServer/src/shared/objectTemplate/SwgServerPlayerObjectTemplate.cpp new file mode 100644 index 00000000..2669b8aa --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/objectTemplate/SwgServerPlayerObjectTemplate.cpp @@ -0,0 +1,57 @@ +//======================================================================== +// +// SwgServerPlayerObjectTemplate.cpp +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#include "FirstSwgGameServer.h" +#include "SwgGameServer/SwgServerPlayerObjectTemplate.h" +#include "sharedObject/ObjectTemplateList.h" +#include "SwgGameServer/SwgPlayerObject.h" + + +/** + * Class constructor. + */ +SwgServerPlayerObjectTemplate::SwgServerPlayerObjectTemplate(const std::string & filename) : + ServerPlayerObjectTemplate(filename) +{ +} // SwgServerPlayerObjectTemplate::SwgServerPlayerObjectTemplate + +/** + * Class destructor. + */ +SwgServerPlayerObjectTemplate::~SwgServerPlayerObjectTemplate() +{ +} // SwgServerPlayerObjectTemplate::~SwgServerPlayerObjectTemplate + +/** + * Replaces the ServerCreatureObjectTemplate tag->create mapping with our own. + */ +void SwgServerPlayerObjectTemplate::install(void) +{ + ObjectTemplateList::assignBinding(ServerPlayerObjectTemplate_tag, create); +} // SwgServerPlayerObjectTemplate::install + +/** + * Creates a SwgServerPlayerObjectTemplate template. + * + * @return a new instance of the template + */ +ObjectTemplate * SwgServerPlayerObjectTemplate::create(const std::string & filename) +{ + return new SwgServerPlayerObjectTemplate(filename); +} // SwgServerPlayerObjectTemplate::create + +/** + * Creates a new object from this template. + * + * @return the object + */ +Object * SwgServerPlayerObjectTemplate::createObject(void) const +{ + return new SwgPlayerObject(this); +} // SwgServerPlayerObjectTemplate::createObject + diff --git a/game/server/application/SwgGameServer/src/shared/objectTemplate/SwgServerPlayerObjectTemplate.h b/game/server/application/SwgGameServer/src/shared/objectTemplate/SwgServerPlayerObjectTemplate.h new file mode 100644 index 00000000..b62d7773 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/objectTemplate/SwgServerPlayerObjectTemplate.h @@ -0,0 +1,33 @@ +//======================================================================== +// +// SwgServerPlayerObjectTemplate.h +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#ifndef _INCLUDED_SwgServerPlayerObjectTemplate_H +#define _INCLUDED_SwgServerPlayerObjectTemplate_H + +#include "serverGame/ServerPlayerObjectTemplate.h" + + +class SwgServerPlayerObjectTemplate : public ServerPlayerObjectTemplate +{ +public: + SwgServerPlayerObjectTemplate(const std::string & filename); + virtual ~SwgServerPlayerObjectTemplate(); + + static void install(void); + virtual Object * createObject(void) const; + +private: + static ObjectTemplate * create(const std::string & filename); + + // no copying + SwgServerPlayerObjectTemplate(const SwgServerPlayerObjectTemplate &); + SwgServerPlayerObjectTemplate & operator =(const SwgServerPlayerObjectTemplate &); +}; + + +#endif // _INCLUDED_SwgServerPlayerObjectTemplate_H diff --git a/game/server/application/SwgGameServer/src/shared/snapshot/WorldSnapshotParser.cpp b/game/server/application/SwgGameServer/src/shared/snapshot/WorldSnapshotParser.cpp new file mode 100644 index 00000000..998a835d --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/snapshot/WorldSnapshotParser.cpp @@ -0,0 +1,366 @@ +//=================================================================== +// +// WorldSnapshotParser.cpp +// asommers +// +// copyright 2002, sony online entertainment +// +//=================================================================== + +#include "FirstSwgGameServer.h" +#include "SwgGameServer/WorldSnapshotParser.h" + +#include "serverGame/ServerBuildingObjectTemplate.h" +#include "serverGame/ServerCellObjectTemplate.h" +#include "serverGame/ServerObjectTemplate.h" +#include "serverGame/ServerStaticObjectTemplate.h" +#include "serverGame/ServerTangibleObjectTemplate.h" +#include "serverGame/ServerWorld.h" +#include "sharedFile/TreeFile.h" +#include "sharedFoundation/ConstCharCrcString.h" +#include "sharedFoundation/PointerDeleter.h" +#include "sharedGame/SharedObjectTemplate.h" +#include "sharedObject/ObjectTemplateList.h" +#include "sharedObject/PortalPropertyTemplate.h" +#include "sharedUtility/WorldSnapshotReaderWriter.h" +#include "sharedMath/Quaternion.h" +#include "sharedMath/Transform.h" +#include "sharedMath/Vector.h" + +#include +#include +#include +#include + +//=================================================================== + +namespace +{ + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + const char* const ms_serverCellObjectTemplateName = "object/cell/cell.iff"; + + typedef std::map PlanetMap; + PlanetMap ms_planetMap; + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + static void install () + { + IGNORE_RETURN (ms_planetMap.insert (std::make_pair (std::string ("corellia"), new WorldSnapshotReaderWriter))); + IGNORE_RETURN (ms_planetMap.insert (std::make_pair (std::string ("dantooine"), new WorldSnapshotReaderWriter))); + IGNORE_RETURN (ms_planetMap.insert (std::make_pair (std::string ("dathomir"), new WorldSnapshotReaderWriter))); + IGNORE_RETURN (ms_planetMap.insert (std::make_pair (std::string ("dungeon1"), new WorldSnapshotReaderWriter))); + IGNORE_RETURN (ms_planetMap.insert (std::make_pair (std::string ("endor"), new WorldSnapshotReaderWriter))); + IGNORE_RETURN (ms_planetMap.insert (std::make_pair (std::string ("lok"), new WorldSnapshotReaderWriter))); + IGNORE_RETURN (ms_planetMap.insert (std::make_pair (std::string ("naboo"), new WorldSnapshotReaderWriter))); + IGNORE_RETURN (ms_planetMap.insert (std::make_pair (std::string ("rori"), new WorldSnapshotReaderWriter))); + IGNORE_RETURN (ms_planetMap.insert (std::make_pair (std::string ("talus"), new WorldSnapshotReaderWriter))); + IGNORE_RETURN (ms_planetMap.insert (std::make_pair (std::string ("tatooine"), new WorldSnapshotReaderWriter))); + IGNORE_RETURN (ms_planetMap.insert (std::make_pair (std::string ("yavin4"), new WorldSnapshotReaderWriter))); + } + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + static void remove () + { + std::for_each (ms_planetMap.begin (), ms_planetMap.end (), PointerDeleterPairSecond ()); + ms_planetMap.clear (); + } + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + void advancePastWhitespace (const char*& buffer) + { + NOT_NULL (buffer); + while (*buffer && (*buffer == ' ' || *buffer == '\t' || *buffer == '\r' || *buffer == '\n')) + ++buffer; + } + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + void advancePastToken (const char*& buffer) + { + NOT_NULL (buffer); + while (*buffer && !(*buffer == ' ' || *buffer == '\t' || *buffer == '\r' || *buffer == '\n')) + ++buffer; + + advancePastWhitespace (buffer); + } + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +} + +//=================================================================== + +void WorldSnapshotParser::createWorldSnapshots (const char* const filename) +{ + //-- make sure the file exists + FILE* infile = fopen (filename, "rt"); + FATAL (!infile, ("%s does not exist", filename)); + + //-- install + install (); + + DEBUG_REPORT_LOG_PRINT (true, ("----- START: WorldSnapshotParser::createWorldSnapshots -----\n")); + + //-- setup parsing + char buffer [1024]; + char planetName [32]; + int networkIdInt; + Vector position; + Quaternion orientation; + int containedByNetworkIdInt; + char serverObjectTemplateName [256]; + int cellIndex; + uint32 portalLayoutCrc; + std::vector objectTemplateList; + std::vector validNetworkIdList; + +/* + select scene_id||chr(9)|| + object_id||chr(9)|| + x||chr(9)|| + y||chr(9)|| + z||chr(9)|| + quaternion_w||chr(9)|| + quaternion_x||chr(9)|| + quaternion_y||chr(9)|| + quaternion_z||chr(9)|| + contained_by||chr(9)|| + object_template_crc||chr(10) + cell_index where object_template == ms_serverCellObjectTemplateName + +*/ + + //-- scan each line of the file + bool quit = false; + while (!quit && fgets (buffer, 1024, infile) != 0) + { + const char* current = buffer; + + //-- skip past blank lines + advancePastWhitespace (current); + if (*current == 0) + continue; + + //-- start parsing parameters + sscanf (current, "%s", planetName); + advancePastToken (current); + + sscanf (current, "%i", &networkIdInt); + advancePastToken (current); + + sscanf (current, "%f", &position.x); + advancePastToken (current); + + sscanf (current, "%f", &position.y); + advancePastToken (current); + + sscanf (current, "%f", &position.z); + advancePastToken (current); + + sscanf (current, "%f", &orientation.w); + advancePastToken (current); + + sscanf (current, "%f", &orientation.x); + advancePastToken (current); + + sscanf (current, "%f", &orientation.y); + advancePastToken (current); + + sscanf (current, "%f", &orientation.z); + advancePastToken (current); + + sscanf (current, "%i", &containedByNetworkIdInt); + advancePastToken (current); + + char possibleServerObjectTemplateName [256]; + sscanf (current, "%s", possibleServerObjectTemplateName); + advancePastToken (current); + + if (possibleServerObjectTemplateName [0] == 'o') + strcpy (serverObjectTemplateName, possibleServerObjectTemplateName); + else + strcpy (serverObjectTemplateName, ObjectTemplateList::lookUp (static_cast (atoi (possibleServerObjectTemplateName))).getString ()); + + //-- check to see of the object is a cell, and if so, read a cell index (all cells have a cell index) + cellIndex = 0; + if (strcmp (serverObjectTemplateName, ms_serverCellObjectTemplateName) == 0) + { + sscanf (current, "%i", &cellIndex); + advancePastToken (current); + } + + //-- check to see if the object is at the origin + if (containedByNetworkIdInt == 0 && position == Vector::zero) + { + DEBUG_REPORT_LOG_PRINT (true, ("skipping %i - object %s is at the origin of the world on planet %s\n", networkIdInt, serverObjectTemplateName, planetName)); + continue; + } + + //-- check to see if the object is too close to the origin + if (containedByNetworkIdInt == 0 && position.magnitude () < 10.f) + { + DEBUG_REPORT_LOG_PRINT (true, ("skipping %i - object %s is suspiciously close to the origin of the world on planet %s\n", networkIdInt, serverObjectTemplateName, planetName)); + continue; + } + + //-- check to see of the line has a portal crc (may be there, may not) + portalLayoutCrc = 0; + sscanf (current, "%lu", &portalLayoutCrc); + + //-- find the planet + const std::string planetNameString (planetName); + PlanetMap::iterator iter = ms_planetMap.find (planetNameString); + if (iter != ms_planetMap.end ()) + { + WorldSnapshotReaderWriter* const worldSnapshotWriter = iter->second; + NOT_NULL (worldSnapshotWriter); + + //-- verify that the object has a valid contained by object + if (containedByNetworkIdInt != 0) + { + std::sort (validNetworkIdList.begin (), validNetworkIdList.end ()); + if (!std::binary_search (validNetworkIdList.begin (), validNetworkIdList.end (), containedByNetworkIdInt)) + { + DEBUG_REPORT_LOG_PRINT (true, ("skipping %i - containedByNetworkId %i not found for %s\n", networkIdInt, containedByNetworkIdInt, serverObjectTemplateName)); + continue; + } + } + + //-- check to see that the server object template exists + if (!TreeFile::exists (serverObjectTemplateName)) + { + DEBUG_REPORT_LOG_PRINT (true, ("skipping %i - server object template %s does not exist\n", networkIdInt, serverObjectTemplateName)); + continue; + } + + //-- check to see that the object template is of the correct type + const ServerObjectTemplate* const serverObjectTemplate = dynamic_cast (ObjectTemplateList::fetch (serverObjectTemplateName)); + if (!serverObjectTemplate) + { + DEBUG_REPORT_LOG_PRINT (true, ("skipping %i - object template %s is not a valid ServerObjectTemplate\n", networkIdInt, serverObjectTemplateName)); + continue; + } + + objectTemplateList.push_back (serverObjectTemplate); + + if (!(serverObjectTemplate->getId () == ServerBuildingObjectTemplate::ServerBuildingObjectTemplate_tag || + serverObjectTemplate->getId () == ServerCellObjectTemplate::ServerCellObjectTemplate_tag || + serverObjectTemplate->getId () == ServerTangibleObjectTemplate::ServerTangibleObjectTemplate_tag || + serverObjectTemplate->getId () == ServerStaticObjectTemplate::ServerStaticObjectTemplate_tag)) + { + char tagString [5]; + ConvertTagToString (serverObjectTemplate->getId (), tagString); + DEBUG_REPORT_LOG_PRINT (true, ("skipping %i - object template %s not building, cell, or static [%s]\n", networkIdInt, serverObjectTemplateName, tagString)); + continue; + } + + //-- compute the transform + Transform transform_p; + orientation.getTransform (&transform_p); + transform_p.setPosition_p (position); + + //-- extract any necessary variables from the object template + const std::string& sharedObjectTemplateName = serverObjectTemplate->getSharedTemplate (); + + //-- check to see that the shared object template exists + if (!TreeFile::exists (sharedObjectTemplateName.c_str ())) + { + DEBUG_REPORT_LOG_PRINT (true, ("skipping %i - server object template %s specifies shared object template %s which does not exist\n", networkIdInt, serverObjectTemplateName, sharedObjectTemplateName.c_str ())); + continue; + } + + const float radius = serverObjectTemplate->getUpdateRanges (ServerObjectTemplate::UR_far); + + //-- verify portalLayoutCrc + { + //-- make sure the shared template could be loaded + const SharedObjectTemplate* const sharedObjectTemplate = safe_cast (ObjectTemplateList::fetch (sharedObjectTemplateName.c_str ())); + if (!sharedObjectTemplate) + { + DEBUG_REPORT_LOG_PRINT (true, ("skipping %i - server object template %s specifies shared object template %s which could not be loaded\n", networkIdInt, serverObjectTemplateName, sharedObjectTemplateName.c_str ())); + continue; + } + + objectTemplateList.push_back (sharedObjectTemplate); + + //-- + const std::string& portalLayoutFilename = sharedObjectTemplate->getPortalLayoutFilename (); + if (!portalLayoutFilename.empty ()) + { + uint32 extractedPortalLayoutCrc; + if (!PortalPropertyTemplate::extractPortalLayoutCrc (portalLayoutFilename.c_str (), extractedPortalLayoutCrc)) + { + DEBUG_REPORT_LOG_PRINT (true, ("skipping %i - server object template %s specifies shared object template %s with portal layout file %s which could not extract portal layout crc\n", networkIdInt, serverObjectTemplateName, sharedObjectTemplateName.c_str (), portalLayoutFilename.c_str ())); + continue; + } + + if (portalLayoutCrc != extractedPortalLayoutCrc) + { + DEBUG_REPORT_LOG_PRINT (true, ("skipping %i - server object template %s specifies shared object template %s with portal layout file %s with mismatched crcs [%lu != %lu] <%s %1.2f, %1.2f>\n", networkIdInt, serverObjectTemplateName, sharedObjectTemplateName.c_str (), portalLayoutFilename.c_str (), portalLayoutCrc, extractedPortalLayoutCrc, planetName, position.x, position.z)); + continue; + } + } + } + + //-- add the object to the list of valid objects + validNetworkIdList.push_back (networkIdInt); + + //-- add to writer + worldSnapshotWriter->addObject ( + networkIdInt, + containedByNetworkIdInt, + ConstCharCrcString(sharedObjectTemplateName.c_str()), + cellIndex, + transform_p, + radius, + portalLayoutCrc); + +// DEBUG_REPORT_LOG_PRINT (true, ("added %s - %s, %s\n", networkIdString, planetName, sharedObjectTemplateName.c_str ())); + } + else + { + DEBUG_REPORT_LOG_PRINT (true, ("skipping %i - unknown planet %s\n", networkIdInt, planetName)); + } + } + + //-- release all object templates + { + uint i; + for (i = 0; i < objectTemplateList.size (); ++i) + objectTemplateList [i]->releaseReference (); + + objectTemplateList.clear (); + } + + DEBUG_REPORT_LOG_PRINT (true, ("----- SUMMARY: WorldSnapshotParser::createWorldSnapshots -----\n")); + + //-- write the planet maps + { + PlanetMap::iterator iter = ms_planetMap.begin (); + for (; iter != ms_planetMap.end (); ++iter) + { + const WorldSnapshotReaderWriter* const writer = iter->second; + + const std::string fileName = iter->first + ".ws"; + if (!writer->save (fileName.c_str ())) + DEBUG_WARNING (true, ("could not save world snapshot file %s", fileName.c_str ())); + +#ifdef _DEBUG + const int numberOfNodes = writer->getNumberOfNodes (); + const int totalNumberOfNodes = writer->getTotalNumberOfNodes (); + DEBUG_REPORT_LOG_PRINT (true, ("%s has %i root objects and %i total objects\n", iter->first.c_str (), numberOfNodes, totalNumberOfNodes)); +#endif + } + } + + //-- remove + remove (); + + DEBUG_REPORT_LOG_PRINT (true, ("----- END: WorldSnapshotParser::createWorldSnapshots -----\n")); +} + +//=================================================================== + diff --git a/game/server/application/SwgGameServer/src/shared/snapshot/WorldSnapshotParser.h b/game/server/application/SwgGameServer/src/shared/snapshot/WorldSnapshotParser.h new file mode 100644 index 00000000..981e4457 --- /dev/null +++ b/game/server/application/SwgGameServer/src/shared/snapshot/WorldSnapshotParser.h @@ -0,0 +1,25 @@ +//=================================================================== +// +// WorldSnapshotParser.h +// asommers +// +// copyright 2002, sony online entertainment +// +//=================================================================== + +#ifndef INCLUDED_WorldSnapshotParser_H +#define INCLUDED_WorldSnapshotParser_H + +//=================================================================== + +class WorldSnapshotParser +{ +public: + + static void createWorldSnapshots (const char* const filename); +}; + +//=================================================================== + +#endif + diff --git a/game/server/application/SwgGameServer/src/win32/FirstSwgGameServer.cpp b/game/server/application/SwgGameServer/src/win32/FirstSwgGameServer.cpp new file mode 100644 index 00000000..9716e6e8 --- /dev/null +++ b/game/server/application/SwgGameServer/src/win32/FirstSwgGameServer.cpp @@ -0,0 +1 @@ +#include "FirstSwgGameServer.h" diff --git a/game/server/application/SwgGameServer/src/win32/WinMain.cpp b/game/server/application/SwgGameServer/src/win32/WinMain.cpp new file mode 100644 index 00000000..7d49e9ab --- /dev/null +++ b/game/server/application/SwgGameServer/src/win32/WinMain.cpp @@ -0,0 +1,553 @@ +#include "FirstSwgGameServer.h" +#include "serverGame/GameServer.h" + +#include "LocalizationManager.h" +#include "serverGame/SetupServerGame.h" +#include "serverGame/ServerWorld.h" +#include "serverGame/ServerObjectTemplate.h" +#include "ServerObjectLint.h" +#include "serverPathfinding/SetupServerPathfinding.h" +#include "serverScript/SetupScript.h" +#include "serverUtility/SetupServerUtility.h" +#include "sharedDebug/SetupSharedDebug.h" +#include "sharedFile/SetupSharedFile.h" +#include "sharedFile/TreeFile.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedFoundation/ExitChain.h" +#include "sharedFoundation/FormattedString.h" +#include "sharedFoundation/Os.h" +#include "sharedFoundation/SetupSharedFoundation.h" +#include "sharedGame/SetupSharedGame.h" +#include "sharedGame/SharedObjectTemplate.h" +#include "sharedImage/SetupSharedImage.h" +#include "sharedLog/LogManager.h" +#include "sharedLog/SetupSharedLog.h" +#include "sharedMath/SetupSharedMath.h" +#include "sharedNetwork/NetworkHandler.h" +#include "sharedNetwork/SetupSharedNetwork.h" +#include "sharedObject/SetupSharedObject.h" +#include "sharedObject/ObjectTemplateList.h" +#include "sharedRandom/SetupSharedRandom.h" +#include "sharedRegex/SetupSharedRegex.h" +#include "sharedRemoteDebugServer/SharedRemoteDebugServer.h" +#include "sharedTerrain/SetupSharedTerrain.h" +#include "sharedThread/SetupSharedThread.h" +#include "sharedUtility/SetupSharedUtility.h" +#include "sharedNetworkMessages/SetupSharedNetworkMessages.h" +#include "SwgGameServer/SwgGameServer.h" +#include "SwgGameServer/WorldSnapshotParser.h" +#include "swgSharedNetworkMessages/SetupSwgSharedNetworkMessages.h" +#include "swgServerNetworkMessages/SetupSwgServerNetworkMessages.h" + +#include +#include +#include + +#include + +#ifdef _DEBUG +#include "sharedDebug/DataLint.h" +#include "sharedDebug/PerformanceTimer.h" +#include "sharedFoundation/Os.h" +#include "sharedObject/Object.h" +#include "sharedObject/ObjectTemplate.h" + +void runDataLint(char const *responsePath); +void verifyUpdateRanges (const char* filename); +#endif // _DEBUG + +//_____________________________________________________________________ +/* +int WINAPI WinMain( + HINSTANCE hInstance, // handle to current instance + HINSTANCE hPrevInstance, // handle to previous instance + LPSTR lpCmdLine, // pointer to command line + int nCmdShow // show state of window + ) +*/ +int main(int argc, char ** argv) +{ + int i = 0; + +// UNREF(hPrevInstance); +// UNREF(nCmdShow); +//-- setup foundation + SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game); + + // command line hack + std::string cmdLine; + for(i = 1; i < argc; ++i) + { + cmdLine += argv[i]; + if(i + 1 < argc) + { + cmdLine += " "; + } + } +// setupFoundationData.hInstance = hInstance; + setupFoundationData.commandLine = cmdLine.c_str(); + setupFoundationData.createWindow = false; + setupFoundationData.clockUsesSleep = true; + + SetupSharedThread::install(); + SetupSharedDebug::install(1024); + + SetupSharedFoundation::install (setupFoundationData); + + SetupServerUtility::install(); + + SetupSharedRegex::install(); + + SetupSharedFile::install(false); + + SetupSharedNetwork::SetupData networkSetupData; + SetupSharedNetwork::getDefaultServerSetupData(networkSetupData); + SetupSharedNetwork::install(networkSetupData); + + SetupSharedMath::install(); + + SetupSharedUtility::Data setupUtilityData; + SetupSharedUtility::setupGameData (setupUtilityData); + SetupSharedUtility::install (setupUtilityData); + + SetupSharedRandom::install(int(time(NULL))); + { + SetupSharedObject::Data data; + SetupSharedObject::setupDefaultGameData(data); + // we want the SlotIdManager initialized, but we don't need the associated hardpoint names on the server. + SetupSharedObject::addSlotIdManagerData(data, false); + // we want movement table information on this server + SetupSharedObject::addMovementTableData(data); + // we want CustomizationData support on this server. + SetupSharedObject::addCustomizationSupportData(data); + // we want POB ejection point override support. + SetupSharedObject::addPobEjectionTransformData(data); + // objects should not automatically alter their children and contents + data.objectsAlterChildrenAndContents = false; + SetupSharedObject::install(data); + } + + SetupSharedLog::install(FormattedString<92>().sprintf("SwgGameServer:%d", Os::getProcessId())); + + TreeFile::addSearchAbsolute(0); + TreeFile::addSearchPath(".",0); + + SetupSharedNetworkMessages::install(); + SetupSwgServerNetworkMessages::install(); + SetupSwgSharedNetworkMessages::install(); + + SetupSharedImage::Data setupImageData; + SetupSharedImage::setupDefaultData (setupImageData); + SetupSharedImage::install (setupImageData); + + SetupSharedGame::Data setupSharedGameData; + setupSharedGameData.setUseMountValidScaleRangeTable(true); + setupSharedGameData.setUseClientCombatManagerSupport(true); + SetupSharedGame::install (setupSharedGameData); + + SetupSharedTerrain::Data setupSharedTerrainData; + SetupSharedTerrain::setupGameData (setupSharedTerrainData); + SetupSharedTerrain::install (setupSharedTerrainData); + + SetupScript::Data setupScriptData; + SetupScript::setupDefaultGameData(setupScriptData); + SetupScript::install(); + + SetupServerPathfinding::install(); + + //-- setup game server + SetupServerGame::install(); + + SharedRemoteDebugServer::install(); + + //-- setup game server + cmdLine = ""; + // now, the real command line + for(i = 0; i < argc; ++i) + { + cmdLine += argv[i]; + if(i + 1 < argc) + { + cmdLine += " "; + } + } + + + Archive::ByteStream bs; + UNREF(bs); + + NetworkHandler::install(); + SwgGameServer::install(); + GameServer::getInstance().setCommandLine(cmdLine); + +#ifdef _DEBUG + //-- see if the game server is being run in a mode to parse the database dump to create planetary snapshot files + const char* const createWorldSnapshots = ConfigFile::getKeyString("WorldSnapshot", "createWorldSnapshots", 0); + if (createWorldSnapshots) + { + WorldSnapshotParser::createWorldSnapshots (createWorldSnapshots); + } + else + //-- see if the gameserver is to be run in a mode to scan update ranges + if (ConfigFile::getKeyBool ("SwgGameServer", "verifyUpdateRanges", false)) + { + ServerWorld::install (); + verifyUpdateRanges ("../../exe/win32/serverobjecttemplates.txt"); + ServerWorld::remove (); + } + else + if (!ConfigFile::getKeyBool("SwgGameServer/DataLint", "disable", true)) + { + runDataLint("../../exe/win32/DataLintServer.rsp"); + } + else +#endif // _DEBUG + { + //-- run game + SetupSharedFoundation::callbackWithExceptionHandling(GameServer::run); + } + + NetworkHandler::remove(); + SetupServerGame::remove(); + + SharedRemoteDebugServer::remove(); + SetupSharedLog::remove(); + SetupSharedFoundation::remove(); + SetupSharedThread::remove (); + + return 0; +} + +#ifdef _DEBUG + +void verifyUpdateRanges (const char* const filename) +{ + FILE* const infile = fopen (filename, "rt"); + if (!infile) + { + DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: response file %s could not be opened\n", filename)); + return; + } + + char serverObjectTemplateName [1024]; + while (fscanf (infile, "%s", serverObjectTemplateName) != EOF) + { + //-- does the name contain test? + if (strstr (serverObjectTemplateName, "test") != 0) + { + DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: skipping test object template %s\n", serverObjectTemplateName)); + continue; + } + + if (strstr (serverObjectTemplateName, "e3_") != 0) + { + DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: skipping test object template %s\n", serverObjectTemplateName)); + continue; + } + + //-- get the object template + const ObjectTemplate* const objectTemplate = ObjectTemplateList::fetch (serverObjectTemplateName); + if (!objectTemplate) + { + DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: %s is not a valid object template\n", serverObjectTemplateName)); + continue; + } + + //-- make sure its a server object template + const ServerObjectTemplate* const serverObjectTemplate = dynamic_cast (objectTemplate); + if (!serverObjectTemplate) + { + objectTemplate->releaseReference (); + DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: %s is not a valid server object template\n", serverObjectTemplateName)); + continue; + } + + //-- make sure it has a shared object template + const std::string& sharedObjectTemplateName = serverObjectTemplate->getSharedTemplate (); + if (sharedObjectTemplateName.empty ()) + { + objectTemplate->releaseReference (); + continue; + } + + //-- make sure the shared template exists + const SharedObjectTemplate* const sharedObjectTemplate = safe_cast (ObjectTemplateList::fetch (sharedObjectTemplateName.c_str ())); + if (!sharedObjectTemplate) + { + DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: %s is not a valid shared object template for server object template %s\n", sharedObjectTemplateName.c_str (), serverObjectTemplateName)); + objectTemplate->releaseReference (); + continue; + } + + const float farUpdateRange = serverObjectTemplate->getUpdateRanges (ServerObjectTemplate::UR_far); + DEBUG_REPORT_LOG (true, ("OK:\t%s\t%s\t%1.1f\n", serverObjectTemplateName, sharedObjectTemplateName.c_str (), farUpdateRange)); + objectTemplate->releaseReference (); + } +} + +static std::string currentLintedAsset; +static int m_startIndex = 0; +static int m_numberOfFilesToLint = -1; + +//----------------------------------------------------------------------------- +static int ExceptionHandler(LPEXCEPTION_POINTERS exceptionPointers) +{ + UNREF(exceptionPointers); + + static bool entered = false; + + // make the routine safe from re-entrance + + if (entered) + { + return EXCEPTION_CONTINUE_SEARCH; + } + + entered = true; + + // tell the Os not to abort so we can rethrow the exception + + Os::returnFromAbort(); + + // Let the ExitChain do its job + + DataLint::pushAsset(currentLintedAsset.c_str()); + FATAL(true, ("ExceptionHandler invoked - A crash just occured. The asset is bad or it is constructed improperly with DataLint.")); + DataLint::popAsset(); + + // rethrow the exception so that the debugger can catch it + + return EXCEPTION_CONTINUE_SEARCH; //lint !e527 // Unreachable +} + +//----------------------------------------------------------------------------- +static void lintType(char const *filePath, DataLint::AssetType const assetType, bool const skip) +{ + DataLint::setCurrentAssetType(assetType); + + static int assetNumber = 0; + + if (!skip) + { + DEBUG_REPORT_LOG (true, ("%5i Linting file %s... ", assetNumber, filePath)); + + bool failed = false; + + try + { + switch (assetType) + { + case DataLint::AT_objectTemplate: + { + const ObjectTemplate *objectTemplate = ObjectTemplateList::fetch(filePath); + if (objectTemplate) + { + objectTemplate->testValues(); + + // if file has the directory "base" in it's path, don't + // create an object + if (strstr(filePath, "/base/") == NULL) + { + Object* const object = objectTemplate->createObject (); + if (object != NULL) + delete object; + } + + objectTemplate->releaseReference(); + } + else + { + failed = true; + } + } + break; + case DataLint::AT_unSupported: + { + } + break; + + } + + if (failed) + { + DEBUG_REPORT_LOG (true, ("failed\n")); + } + else + { + DEBUG_REPORT_LOG (true, ("ok\n")); + } + } + catch (FatalException const &e) + { + DEBUG_REPORT_LOG (true, ("failed\n")); + + DataLint::logWarning(e.getMessage()); + } + } + + ++assetNumber; +} + +//----------------------------------------------------------------------------- +static void makeMicrosoftHappyAboutObjectUnWinding(char const *filePath, DataLint::AssetType const assetType, bool const skip) +{ + __try + { + lintType(filePath, assetType, skip); + } + __except (ExceptionHandler(GetExceptionInformation())) + { + } +} + +//----------------------------------------------------------------------------- +static void lint(char const *dataTypeString, DataLint::AssetType const assetType) +{ + DataLint::StringPairList stringPairList(DataLint::getList(assetType)); + DataLint::StringPairList::const_iterator dataLintStringListIter = stringPairList.begin(); + + DEBUG_REPORT_LOG_PRINT(1, ("Linting %d %s assets\n", stringPairList.size(), dataTypeString)); + + int currentIndex = 0; + for (; dataLintStringListIter != stringPairList.end(); ++dataLintStringListIter) + { + { + if ((currentIndex % 10) == 0) + { + //-- see if a file exists to abort + + FILE *file = fopen("stoplint.dat", "rt"); + + if (file) + { + fclose(file); + DEBUG_REPORT_LOG_PRINT(1, ("Stopping all DataLint processing for %s.\n", dataTypeString)); + DataLint::logWarning("Forced DataLint stop. Delete \"stoplint.dat\" to DataLint all the assets."); + break; + } + } + } + + char const *filePath = dataLintStringListIter->first.c_str(); + currentLintedAsset = dataLintStringListIter->second.c_str(); + + //DataLint::pushAsset(filePath); + makeMicrosoftHappyAboutObjectUnWinding(filePath, assetType, (currentIndex < m_startIndex)); + //DataLint::popAsset(); + + DataLint::clearAssetStack(); + ++currentIndex; + + if ((m_numberOfFilesToLint != -1) && (currentIndex >= (m_startIndex + m_numberOfFilesToLint))) + { + break; + } + } +} + +//----------------------------------------------------------------------------- +void runDataLint(char const *responsePath) +{ + ServerObjectLint::install(); + ServerWorld::install(); + DataLint::setServerMode(); + + PerformanceTimer performanceTimer; + performanceTimer.start(); + + FILE *fp = fopen(responsePath, "r"); + + if (fp) + { + // Default to start with the first asset + + m_startIndex = ConfigFile::getKeyInt("SwgGameServer/DataLint", "startIndex", 0); + + // Default to lint all assets + + m_numberOfFilesToLint = ConfigFile::getKeyInt("SwgGameServer/DataLint", "numberOfFilesToLint", -1); + + // Verify this is a valid resonse file + + char text[4096]; + fgets(text, sizeof(text), fp); + + if (strstr(text, "Valid DataLint Rsp") == NULL) + { + DEBUG_REPORT_LOG_PRINT(1, ("DataLint: Invalid Rsp file: %s\n", responsePath)); + +#ifdef WIN32 + char text[4096]; + sprintf(text, "Invalid Rsp file specified: %s. Make sure to run DataLintRspBuilder before running DataLint.", responsePath); + MessageBox(NULL, text, "DataLint Error!", MB_OK | MB_ICONERROR); +#endif // WIN32 + } + else + { + DataLint::install(); + + typedef std::vector StringList; + StringList stringList; + stringList.reserve(32768); + + DEBUG_REPORT_LOG_PRINT(1, ("Loading assets to lint from: %s\n", responsePath)); + + while (fgets(text, sizeof(text), fp)) + { + // Remove the newline character + + char *newLineTest = strchr(text, '\n'); + + if (newLineTest) + { + *newLineTest = '\0'; + } + + // Add the files to the master file list + + stringList.push_back(text); + } + + fclose(fp); + + // Add files to data lint + + DEBUG_REPORT_LOG_PRINT(1, ("Adding %d assets to DataLint to be categorized\n", stringList.size())); + + StringList::iterator stringListIter = stringList.begin(); + + for (; stringListIter != stringList.end(); ++stringListIter) + { + DataLint::addFilePath((*stringListIter).c_str()); + } + + if (ConfigFile::getKeyBool("SwgGameServer/DataLint", "objectTemplate", true)) + { + lint("Objects Template", DataLint::AT_objectTemplate); + } + + DataLint::report(); + } + } + else + { + DEBUG_REPORT_LOG_PRINT(1, ("Bad response path specified: %s", responsePath)); + +#ifdef WIN32 + char text[4096]; + sprintf(text, "Bad response file specified: %s. Make sure to run DataLintRspBuilder before running DataLint.", responsePath); + MessageBox(NULL, text, "DataLint Error!", MB_OK | MB_ICONERROR); +#endif // WIN32 + } + + // Dump the time required to data lint + + performanceTimer.stop(); + float const dataLintTime = performanceTimer.getElapsedTime(); + int const seconds = static_cast(dataLintTime) % 60; + int const minutes = (static_cast(dataLintTime) - seconds) / 60; + DEBUG_REPORT_LOG_PRINT(1, ("DateLint took: %dm %ds\n", minutes, seconds)); +} +#endif // _DEBUG + +//_____________________________________________________________________ diff --git a/game/server/library/swgServerNetworkMessages/CMakeLists.txt b/game/server/library/swgServerNetworkMessages/CMakeLists.txt index 3243bdfe..1defcd16 100644 --- a/game/server/library/swgServerNetworkMessages/CMakeLists.txt +++ b/game/server/library/swgServerNetworkMessages/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 2.8) -project(swgSharedNetworkMessages) +project(swgServerNetworkMessages) if(WIN32) add_definitions(/D_CRT_SECURE_NO_WARNINGS)