CS Code convertion

From PSwiki
Jump to navigation Jump to search

Code convertion

Types

csArray<> -> TArray

csBox2 -> TArray<FVector2D>

If you need to have unique key-value pairs:

csHash<Value> -> TMap<int,Value>

csHash<Value,Key> -> TMap<Key,Value> (note the swap of Key and Value)

If you need have multiple values for the same key:

csHash<Value,Key> -> TMultiMap<Key,Value> (notice the swap of Key and Value)

csHashCompute(string) -> StrUtils::hashCompute(string)

csList -> TDoubleLinkedList

csMD5::Digest -> to be bettere analyzed, for now just temporary

csPDelArray<PhonicEntry> -> TArray<PhonicEntry*>; (note the pointer in UE)

csRandomGen -> FMath::FRandRange(low, high);

psGetRandom() -> FMath::FRandRange(0, 1); // CAREFUL: psGetRandom 0 <= num < 1 WHILE FRandRange 0 <= num <= 1

psserver->GetRandomRange(pos, range) -> (pos - range + FMath::FRandRange(0,1)*range*2)

If you want to generate Integer random then use FMath::RandRange(1,10) // Returns a random number >= Min and <= Max

psserver->rng->Get(100) -> FMath::FRandRange(0,100);

csRef<iDocumentNode> containerNode -> FXmlNode *containerNode

csRefArray<csString> -> TArray<FString*>

csRegExpMatcher -> FRegexPattern , FRegexMatcher (check msgmanager.cpp:234)

csSet -> TArray (but be careful about insertions as csSet.Add checks for uniqueness)

csString -> psString or FString

csStringSet -> StringSet ( #include "util/strset.h" )

csStringArray -> TArray<FString>

psStringArray -> TArray<FString>

csSquaredDist::PointPoint() -> FVector::Dist(v1,v2)

csTicks -> float (time_t can be used only when 100% sure we can use an integer and no convertion issues from float)

CS::Threading::AtomicOperations::Increment(&nextid); -> FThreadSafeCounter.Increment()

CS::Threading::MutexScopedLock ScopeLock(mutex); -> FCriticalSection mutex; FScopeLock ScopeLock(mutex);

csTuple2 -> TPair

csVector2 -> FIntPoint

csVector3 -> FVector

?? csSet -> TArray ??

uint -> uint32

uint32_t -> #include <stdint.h>

iResultRow -> psResultRow

StringIDValue -> int (is this a correct assumption?)

WordArray -> TArray<FString> with space separator. Verify if this assumption is enough

 //WordArray words(trigger.GetString());
 TArray<FString> words;
 trigger.ParseIntoArray(words, TEXT(" "), true);

iVFS -> not used in UE, just delete the reference.

CS::Utility::PriorityQueue<TaskEntry> -> TArray<TaskEntry> items; use items.Heapify() to order.

NPC -> psNPCBrain

Types conversion

FString to char* -> const char *myData = TCHAR_TO_ANSI(*NameString);

FString to TCHAR -> *myFString

char* to FString -> ANSI_TO_TCHAR(NameString);

int to FString -> FString::FromInt(myInt);

float to FString -> FString::SanitizeFloat(myFloat);

int32 MyShinyNewInt = FCString::Atoi(*TheString);

float MyShinyNewFloat = FCString::Atof(*TheString);

Functions on csString

csString csv.AppendFmt(",%d,%d", fs->faction->id, fs->score); -> csv.Append(FString::Printf(TEXT(",%d,%d"), fs->faction->id, fs->score));

csString.AppendFmtV(fmt, args) -> vsprintf(line, fmt, args); script.Append(line);

csString.Clear() -> Empty()

csString input.Collapse() -> output = StrUtils::Collapse(input)

csString.CompareNoCase() returns TRUE if equal -> FString.Compare("ADD", ESearchCase::IgnoreCase)==0 returns 0 if equal

csString.DeleteAt(start) -> FString.RemoveAt(start)

csString.DeleteAt(start,count) -> FString.RemoveAt(start,count)

csString str.Detach() -> TCHAR_TO_ANSI(*str) detaches the data from the csString

csString.Downcase() -> mystring = mystring.ToLower() (NOTE the assignment in UE)

csString.Find(search, pos, ignore_case) -> FString.Find(search, ESearchCase::IgnoreCase)

csString.FindLast('-') -> int pos; csString.FindLastChar('-', pos)

csString.FindLast('-', startposition) -> pos = csString.Find('-', pos)

csString end = resp.Find("]", start); -> int end = resp.Find("]",ESearchCase::IgnoreCase , ESearchDir::FromStart, start);

csString.Free() -> mystring = ""

csString.FindFirst ('a') -> int pos; FString.FindChar(' ',pos);

csString pos = script.FindFirst(';', start); -> pos = script.Find("]",ESearchCase::IgnoreCase , ESearchDir::FromStart, start);

script.FindStr("string") -> script.Find("string");

mystr.FindReplace (search, replace) -> mystr = mystr.Replace(search, replace); (NOTE the assignment in UE)

csString.FindSubString() -> FString.Find()

string.Format("hey %s", param) -> string = FString::Printf(TEXT("hey %s"), param) (NOTE the assignment in UE)

csString.GetAt(0) -> [0]

csString.GetData() -> TCHAR_TO_ANSI(*mystring)

csString.GetDataSafe() -> TCHAR_TO_ANSI(*mystring)

csString.Insert(pos, str) -> FString.InsertAt(pos, string)

csString.Length() -> Len()

csString.LTrim() -> FString.Trim()

csString.Replace(from, to) -> mystr = mystr.Replace(TEXT("fromtext"), *to); (NOTE the assignment in UE)

csString.ReplaceSubString(search, replace) -> mystr = mystr.Replace(search, replace) (NOTE the assignment in UE)

csString.ReplaceAll(search, replace) -> mystr = mystr.Replace(search, replace) (NOTE the assignment in UE)

csString.Slice(5) -> FString.RightChop(5); if there is only one parameter CS assumes the second to be -1, so the end of the string

csString.Slice(0,5) -> mystr = FString.Left(5);

csString.Slice(a,b) -> mystr = FString.Mid(a,b);

csString.Split(csStringArray& arr, char delim) -> FString.ParseIntoArray(arr,TEXT("."));

csString resp.SubString(saySegment,start,numchars); -> FString saySegment = resp.Mid(start, numchars);

csString resp.SubString(saySegment,start); -> FString saySegment = resp.RightChop(start);

csString response.StartsWith("<Examine>", true) -> response.StartsWith("<Examine>", ESearchCase::IgnoreCase) (true ignore case, false case sensitive)

csString.RTrim() -> FString.TrimTrailing()

csString xxx = mystring.Trim() -> FString.TrimStartAndEnd() (this one does NOT change the string in place)

csString : mystring.Trim() -> FString.TrimStartAndEndInline() (this one changes the string in place)

csString.Truncate(5) -> modifiedString = FString.Left(5)

csString.Upcase() -> FString.ToUpper()

const char *myData = str->GetData(); -> TArray<TCHAR> myData = str.GetCharArray();

psString.GetLine() scr.GetLine(start,line); -> line = StrUtils::GetLine(scr,start);

Functions other types

psserver->GetRandom() provides a number between 0.0 and 1.0 -> FMath::FRandRange(0.0, 1.0)

csRandomGen.Get() -> FMath::FRandRange(0.0, 1.0)

psserver->GetRandom(limit) -> provides a number between 0.0 and limit -> FMath::FRandRange(0.0, limit) If provided with float it returns a float, if int then returns int.

csPDelArray.GetSize() -> TArray.Num()

csPDelArray.Push() -> TArray.Add()

csArray.Delete(item) -> TArray.Remove(item)

csArray.DeleteAll() -> TArray.Empty()

csArray.DeleteIndex(i) -> TArray.RemoveAt(i)

csArray.DeleteIndexFast(i) -> TArray.RemoveAt(i)

csArray.Extract(index) -> item = TArray[index]; TArray.RemoveAt(index);

csArray.FindStr("str", start) -> end = StrUtils::FindStr(words, "str", start);

csArray.FormatPush("%d",i); -> TArray.Add(FString::Printf(TEXT("%d",i));

csArray.GetSize() -> TArray.Num();

csArray myarray.Merge(otherArray) -> TArray.Append(otherArray)

csArray myarray.Get(0) -> TArray myarray[0]

csArray.Insert(index, item) -> TArray.Insert(item, index); (note switch of order)

csArray.InsertSorted(item) -> TArray.Add(item); TArray.Sort();

csArray.IsEmpty() -> TArray.Num()==0

csArray.PushSmart(item) -> int found = TArray.Find(item); if (found == INDEX_NONE) TArray.Add(item);

csArray.Put(index, item) -> TArray.RemoveAt(index); TArray.Insert(item, index); (note switch of order)

csArray.ShrinkBestFit() -> TArray.Shrink();

csArray.SplitString(str, ',') -> str.ParseIntoArray(array, TEXT(","));

csArrayItemNotFound -> INDEX_NONE

csList.Delete(node) -> TDoubleLinkedList.RemoveNode(node)

csList.DeleteAll() -> TDoubleLinkedList.Empty()

csList.Front() -> TDoubleLinkedList.GetHead()

csList.IsEmpty() -> TDoubleLinkedList.Num()==0

csList.PushBack() -> TDoubleLinkedList.AddTail() adds an element at the end of the list

csList.PushFront() -> TDoubleLinkedList.AddHead() adds an element at the beginning of the list

csList attackList.PopFront() -> attackList.RemoveNode(attackList.GetHead()); deletes an element at the beginning

csList attackList.Pop() -> attackList.RemoveNode(attackList.GetTail()); deletes an element at the end of the list

csList values.PopBack() -> values.RemoveNode(values.GetTail()); Deletes the last element of the list

 for(csList<psItem*>::Iterator newitemitr(newitem); newitemitr.HasNext();) -> 
 TDoubleLinkedList<ApsItem*>::TIterator i(itemlist.GetHead());
 while (i) { ....}

csHash.Delete(id, item) -> If not using multimap then TMap.Remove(id);

csHash.DeleteAll() -> TMap.Empty()

csHash.DeleteAll(name) -> If used as TMap (meaning no duplicate keys -> TMap.Remove(name)

csHash.Get(key,fallback) -> TMap.FindRef(key)

csHash.GetAll(key) example: channelSubscribers.GetAll(key) ->

   TArray<uint32_t> subscribers;
   channelSubscribers.GetKeys(subscribers);
   for(size_t i = 0; i < subscribers.Num(); i++)
   {
       // filter subscribers by given channelID
       if (subscribers[i] == channelID) {

csHash.GetElementPointer(name) -> TMap.Find(name);

csHash.GetSize() -> TMap.Num();

csHash.In() -> TMap.Contains()

CS::IsNaN() -> isnan()

csHash.Put(value, key) -> TMap.Add(value, key) (NOTE NO swap of parameters)

csHash.PutUnique() -> TMap.Add() (we should test if this is ok)

csHash<FactionStanding*, int>::GlobalIterator iter(factionstandings.GetIterator()); -> TMap<int, FactionStanding*>::TIterator iter = factionstandings.CreateIterator();

csHash if(iter.HasNext()) -> if(iter)

csHash iter.Next() -> iter.Value(); iter++;

csGetTicks() -> time(0) Need to #include <ctime> NOTE: if you need seconds then is ok to use this one

csGetTicks() -> GetWorld()->GetRealTimeSeconds() OR GetWorld()->GetTimeSeconds() NOTE: if you need to use milliseconds use this one

csMax(a, b); -> a > b ? a : b;

csMin(a, b); -> a < b ? a : b;

csQsqrt(x) -> FMath::Sqrt(x)

csSet.Add() -> TArray.AddUnique();

csSquaredDist::PointLine() -> psPath::DistPointLine

csStringArray.FindCaseInsensitive() -> Find (but is case sensitive).... no solution atm

csTuple.first -> TPair.Key

csTuple.second -> TPair.Value

csVector.Norm() -> FVector.Size() calculates the magnitude/norm of the vector.

csVector.SquaredNorm() -> FVector.SizeSquared()

csVector v1 * v2 -> FVector::DotProduct(v1,v2)

csVector.Unit() -> FVector.GetSafeNormal()

output.Insert(0, time_buffer) -> output.InsertAt(0, time_buffer)

output.GetAt(output.Length()-1) -> output [ output.Len()-1 ]

Cross platform types are defined in Platform.h , like uint32. Those can be included with #include "EngineMinimal.h"

(!! Please note that CS_ASSERT are not enabled in PSLegacy production database, those are skipped !!)

CS_ASSERT() -> check()

CS_ASSERT_MSG() -> checkf(expr, TEXT("%s caused the error"), str);

strcasecmp and strcmp, I added those two defines, so the code can stay as it is

 #define strcasecmp(expr1,expr2) FCString::Strcmp( ANSI_TO_TCHAR(expr1), ANSI_TO_TCHAR(expr2)) == 0
 #define strcmp(expr1,expr2) FCString::Stricmp( ANSI_TO_TCHAR(expr1), ANSI_TO_TCHAR(expr2)) == 0

time(NULL) -> FString buf = FDateTime().GetDate().ToString();

toString(pos) -> StrUtils::toString(pos);

toString(pos, sector) -> StrUtils::toString(pos, sector);

csArray<csString> splitTarget = psSplit(target, ':'); -> TArray<FString> splitTarget; target.ParseIntoArray(splitTarget, TEXT(":"));

WordArray.GetInt(1) -> FCString::Atoi(*myarray[1])

WordArray.GetFloat(1) -> FCString::Atof(*myarray[1])

WordArray.GetString(2, str) -> FString str = TArray[2]

WordArray.GetTail(1) -> StrUtils::GetTail(words, 1)

WordArray.GetWords(2, 5) -> StrUtils::GetWords(words, 2, 5)

PI -> PI

TWO_PI -> TWO_PI (added to PSUnreal.h)

Result result(db->Select("")) -> psResultSet result = db->Query("")

db->Command("INSERT...%s %s %s", var1, var2, var3); -> FString cmdString = FString::Printf(TEXT("INSERT...%s %s %s"), var1, var2, var3)); db->Command(cmdString);

result[0].GetUInt32(0); -> result[0].GetInt(0);

client->GetClientNum() -> client->GetUniqueID() need to check if this is ok, documentation says the ID lives until the actor lives.

 psserver->GetConnections()->Find  -> becomes (to be tested)
 FConstPlayerControllerIterator iter = actor->GetWorld()->GetPlayerControllerIterator();
 while(iter)
 {
    APlayerController* client = *iter;
    ApsCharacter *actor = (ApsCharacter*)client->GetPawn();

gemObject.GetPosition(pos, sector) -> ApsCharacter.GetActorLocation()

gemActor.RangeTo(gemActor) -> ApsCharacter.GetDistanceTo(ApsCharacter)

EscpXML(string) -> StrUtils::EscpXML(string)

psserver->CheckAccess() -> cacheManager->GetCommandManager()->CheckAccess()

cel->FindPlayerEntity(pid) -> ((APlaneshiftBaseGameMode*)GetWorld()->GetAuthGameMode())->FindPlayerEntity(pid);

gem->FindNearbyEntities(iSec, pos, 0, range); -> ((APlaneshiftBaseGameMode*)GetWorld()->GetAuthGameMode())->FindNearbyEntities(iSec, pos, 0, range);

gemSupervisor->FindObject(containerID) -> ((APlaneshiftBaseGameMode*)GetWorld()->GetAuthGameMode())->FindObject(containerID)

GetGEM()->FindItemEntity(idNum); -> ((APlaneshiftBaseGameMode*)GetWorld()->GetAuthGameMode())->FindObject(itemID)

Logging and Error Messages

Verbosity levels:

  • Fatal: Always prints s fatal error to console (and log file) and crashes (even if logging is disabled)
  • Error: Prints an error to console (and log file)
  • Warning: Prints a warning to console (and log file)
  • Display: Prints a message to console (and log file)
  • Log: Prints a message to a log file (does not print to console)
  • Verbose: Prints a verbose message to a log file (if Verbose logging is enabled for the given category)

CPrintf(CON_CMDOUTPUT,str.GetDataSafe()); -> UE_LOG(LogTemp, Warning, TEXT("%s"), str);

CPrintf(CON_CMDOUTPUT,"name: %s",str.GetDataSafe()); -> UE_LOG(LogTemp, Warning, TEXT("name: %s"), str);

CPrintf(CON_ERROR, "psItemStats::GetProperty(%s) failed\n",ptr); -> UE_LOG(LogTemp, Error, TEXT("psItemStats::GetProperty(%s) failed\n"),ptr);

Notify3(LOG_SPAWN,"Spawning item (%u) in %d ",item->GetItemID(),triggerticks -csGetTicks()); -> UE_LOG(LogSpawn, Warning, TEXT("psItemStats::GetProperty(%s) failed\n"),ptr);

Debug3(LOG_ITEM, 0, "Set location in parent %d for %u", location, GetUID()); -> UE_LOG(LogTemp, Log, TEXT("psItemStats::GetProperty(%s) failed\n"),ptr);

Error3("Failed to insert trait '%s'.\n",t->name.GetData()); -> UE_LOG(LogTemp, Error, TEXT("Failed to insert trait '%s' into location table for race %d.\n"), t->name, t->raceID);

psserver->SendSystemError(...) ->

           FString msg = FString::Printf(TEXT("You can't pick up %s."), *GetName());
           client->ReceiveSystemMessage(msg, ESystemMessageType::MSG_ERROR);


psserver->SendSystemInfo(...) ->

           FString msg = FString::Printf(TEXT("You can't pick up %s."), *GetName());
           client->ReceiveSystemMessage(msg, ESystemMessageType::MSG_INFO);


psserver->SendSystemOK(...); ->

           FString msg = FString::Printf(TEXT("You can't pick up %s."), *GetName());
           client->ReceiveSystemMessage(msg, ESystemMessageType::MSG_OK);

psserver->SendSystemResult(...); ->


           FString msg = FString::Printf(TEXT("You can't pick up %s."), *GetName());
           client->ReceiveSystemMessage(msg, ESystemMessageType::MSG_RESULT);

FText and Localization

FText is Unreal's class for user viewable strings. It is localizable. See https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/StringHandling/FText/index.html

XML parsing

  1. include "XmlParser.h"

iDocumentNode -> FXmlNode

   csRef<iDocument> doc=xml->CreateDocument();
   const char* error =doc->Parse(buff);

becomes

   FXmlFile File(FPaths::ProjectDir() + FString(PHONICS_LIST));
   FXmlNode* root = File.GetRootNode();

if its parsing a string and not a file, script is an FString

   FXmlFile File(script, EConstructMethod::ConstructFromBuffer);
   FXmlNode* root = File.GetRootNode();

Finding a specific child node: root->GetNode("FAMILY_NAME"); -> FXmlNode *familyName = root->FindChildNode("FAMILY_NAME");

   csRef<iDocumentNodeIterator> iter = attitudeNode->GetNodes("response"); -> 
   TArray<FXmlNode *> responses = attitudeNode->GetChildrenNodes();
   for (int i = 0; i < responses.Num(); i++)
       {
       FXmlNode *responseNode = responses[i];
       if (responseNode->GetTag().Equals("response")) {

csRef<iDocumentNodeIterator> iter = topNode->GetNodes(); -> TArray<FXmlNode*> arr = topNode->GetChildrenNodes(); TArray<FXmlNode*>::TIterator iter = arr.CreateIterator();


csRef<iDocumentAttributeIterator> it = top->GetAttributes(); -> TArray<FXmlAttribute> attrs = top->GetAttributes(); for (int i=0;attrs.Num();i++)

csString skillName = tmp->GetAttributeValue("name"); -> tmp->GetAttribute("name");

float value = children[i]->GetAttributeValueAsFloat("value"); -> float value = FCString::Atof(*children[i]->GetAttribute("value"));

int cstr_id_material = node->GetAttributeValueAsInt( "mesh" ); -> int cstr_id_material = FCString::Atoi(*node->GetAttribute("mesh"));

bool includeInventory = topNode->GetAttributeValueAsBool("inventory", false); -> bool includeInventory = topNode->GetAttribute("inventory").Equals("true") ? 1 : 0;

id = node->GetContentsValueAsInt(); -> id = FCString::Atoi(*node->GetContent());

meshname = node->GetContentsValue(); -> meshname = node->GetContent();

posx = node->GetContentsValueAsFloat(); -> posx = FCString::Atof(*node->GetContent());

node->GetValue() -> node->GetTag() if applied to an element.

Platform specific includes

If you want to include some code for a specific platform you can use:


  1. ifdef PLATFORM_WINDOWS

your stuff here

  1. endif


Converting psMessages

PlaneShift code is heavily based on messages send from client to server and viceversa. The typical way to communicate is to create a message and send it. Messages are specific classes, example:

 class psCharDeleteMessage : public psMessageCracker
 {
 public:
     psCharDeleteMessage(const char* charNameToDel, uint32_t clientNum);
     psCharDeleteMessage(MsgEntry* message);
 ...


To convert the messages we use this technique

When we have a SystemMessage like this:

  psSystemMessage newmsg(GetUniqueID(), ESystemMessageType::MSG_INFO_BASE, "%s dropped %s.", *fullName, *item->GetQuantityName());
  newmsg.Multicast(GetMulticastClients(), 0, RANGE_TO_SELECT);

should be changed to :

   FString msg = FString::Printf(TEXT("%s dropped %s."), *fullName, *item->GetQuantityName());
   pawn->Multicast(msg, ESystemMessageType::MSG_INFO_BASE, false, RANGE_TO_SELECT);


Object Mapping PSLegacy PSUnreal

Unrealengine gemObjects.png