Page 1 of 1

Operating arrays discussion

Posted: Tue Feb 18, 2020 11:58 pm
by Nelsona
Here I must open a discussion for anyone interested to participate.
Subject target is how to handle bigger arrays. By example we want to move element 200 to first place, and the rest moved down resulting 199 moved at 200, 198 at 199 and so on. What method it's fast ? First thing would be a limited array to a few thousands of elements or else I think it takes ages for processing...
With regard to something like UTES records probably the most seen players will get into firsts places and new comers. The rest can go lower and lower. The number of new comers will push all records down and... last one can be wiped probably being a long time since he did not play, do we need records for 3 years ? Me one I don't think this is necessary.
What do you think ?

Re: Operating arrays discussion

Posted: Wed Feb 19, 2020 12:58 am
by SC]-[WARTZ_{HoF}
I think that we should have the array be around 3000-5000. Have it auto prune clients that have not played for so many X amount of days. Having clients logged by player name is a bit to simple and at this moment that is how UTES manages the lists. Maybe we need a system that also checks IP's and Nexgen ID's which unfortunately can be changed client side. I think AutoTeamBalancer has this way of tracking data but I'm not educated enough on how to integrate this script into UTES.

Re: Operating arrays discussion

Posted: Wed Feb 19, 2020 6:59 am
by Nelsona
Yup, here comes again discussion about identification of player which would be hard if player it's unstable. It's why we need to be simple, regulars playing daily and keeping their main data Name+IP stable are moved to the top permanently while others which are only full filling slots have to be discarded. In serious terms I don't think we have 400 UT players now days and then 5000 it's only a server charge with less purpose.
Handling data through 2000-3000 records based on IP vs Name probably works somehow depending on strategy used - here will result a number of iterations to be taken in account.
As for Nexgen, you might check that ...LookUp.INI and see duplicated names in at least 30-50+ locations, mentioning that even IP can be changed and Net-Adapter depending on networking, 3G, 4G even 5G , LAN, Fiber, if player has options and will use more hardware... Excepting IP and Name I think we can forget other "tech" in recognizing players. If are unstable they are one by one discarded after each match by simply moving data to the tail until they are gone. If this is not based on an account with password like in forum, player using another machine from a friend can be seen as another person and then... doesn't worth loading mod with multiple arrays and parsing a lot of data because it won't help at all.
Even if happens stealing of name, if "new" player won't score that much will gain a refresh in database, moved to the top and false player is helping the "original player" instead of damaging - IP here might have a word - dodgy connections don't have to be in TOP, and then I think won't be any damaging thing, but those attempting to create records are automatically discarded in time. PlayerLookUP grows daily until will cause problems filling all array at a moment and I'm not sure if number of UT players grows like that, this addiction in recognizing people and stamping them was never good.
With regard to that link - those downloads are no longer available. Okay, let's the way of moving data quickly.

A different said purpose
Take a look at file UTES.ini randomly at records. Compare record PName[704]= with record IPToName[704]=. Or, compare other entry. One array has 20000 elements, and another one has 5000. Now go figure what soup was done over there. I DID NOT TOUCH these codes and I don't have many plans here until things are getting clarified.
I believe we need some other pro-stats attached to forum somehow instead of spoofing these using GameEngine.

Re: Operating arrays discussion

Posted: Wed Feb 19, 2020 2:40 pm
by Kelly
Nels I remember having a long discussion with Barbie over this very issue. He had scripted a way to do this that was very fast and quite smart and they were using it on their MH server to order the player records. You should ask him about it, he's open to sharing code.

Re: Operating arrays discussion

Posted: Wed Feb 19, 2020 5:46 pm
by Nelsona
Hmm... these array things are not my best point in coding, the only thing which I did was "RandomWeapon" loading using XCGE from a DYNAMIC array and wrapping paths lists in Navigationpoints. I'm not sure if this last solution it's fast - that array has 16 elements - of course, my first attempt was buggy but I could solve problem later with price of losing some performance.

Here when that array returned out of bounds and corrupting "UCC" application so bad, definitely something was not written where it had to and then... this was not a single time. Like I said I would go for a time deal but dictated by presence in server. Players permanently moved on top and tail will get cut at new comers as long as olders are not coming back or are changing identity not being interested about scoring and stats. Perhaps I'm on the same side as long as all these years I wasn't interested about such stats because... players are many... but people are just a few.

More easy for me is a counter as an array, spread whatever actors and record something until it fills up and then do other action, cleaning, etc. If you ask me for some items/ammo in certain map I think I can write that in maximum two hours but working at long arrays takes time. Must have conditions: empty, full, updating, discarding certain element, etc. But.. I would like to know quick solutions and smart code optimization.

Re: Operating arrays discussion

Posted: Thu Feb 20, 2020 5:16 pm
by Nelsona
I'm gonna introduce my notes about these UTES things.
We have a class called UTES_PList.uc
Technically this has
  • var config string IPToName[5000];
    var config string LastPlayed[5000];
I'm looking at
  • if ( i >= 5000 )
    i = 4999;
I don't know if this is wrong or unused Cannot be 5000 but definitely 4999. Is this even getting this value big or equal to 5000 ? Cycle for has this:
  • for ( i = 0; (( i < 5000 ) &&....
Of course, it doesn't hurt.

Re: Operating arrays discussion

Posted: Thu Feb 20, 2020 5:20 pm
by SC]-[WARTZ_{HoF}
I do believe that the UTESPList.uc is handling this array well. Eventually if client is no longer active in server then eventually drops client from list.

Re: Operating arrays discussion

Posted: Thu Feb 20, 2020 6:06 pm
by Nelsona
After looking at stats class I think we do not have too many headaches. But if I recall that 5000 array problem, definitely I need to look well at that. I'm afraid that a malformed name used might do funky stuff. I'll spend more time over there. Stats are not in very relations with that Scoreboard arrays that's why previous records did not match, and exactly There (for that 5000) is the obscure problem which I have to figure out. In this case, I'm hoping that we do not have some memory problem allocation which is out of UScript domain and then... I'm hunting a Ghost which is nowhere :? . If I take in account that Name changed of a map actor I can expect "entertaining" reactions.

Edit: As for various proposals
#1 If player is joined during votes - during an ended match, perhaps nothing is updated, that data saving happens exactly in ending moment - ModifyPlayer should not check anything after End and... Timer should be disabled in that stage being entirely useless. We don't have to do processing for no reason if game is no longer valid. I doubt to see players scoring after ending game.
#2 In PrebeginPlay we are doing a call to next mutator. This will trigger a duplicated execution of NextMutator's PreBeginPlay as long as Engine takes care about ALL PreBeginPlay calls natively, sometimes this is not welcomed and it's pointless.
Resource

Code: Select all

ULevel* UGameEngine::LoadMap( const FURL& URL, UPendingLevel* Pending, const TMap<FString,FString>* TravelInfo, FString& Error )
...
...
		debugf( NAME_Log, TEXT("Bringing %s up for play (%i)..."), GLevel->GetFullName(), appRound(GetMaxTickRate()) );
		GLevel->TimeSeconds = 0;
		GLevel->GetLevelInfo()->TimeSeconds = 0;

		// Init touching actors.
		for( INT i=0; i<GLevel->Actors.Num(); i++ )
			if( GLevel->Actors(i) )
				for( INT j=0; j<ARRAY_COUNT(GLevel->Actors(i)->Touching); j++ )
					GLevel->Actors(i)->Touching[j] = NULL;

		// Kill off actors that aren't interesting to the client.
		if( !GLevel->IsServer() )
		{
			for( INT i=0; i<GLevel->Actors.Num(); i++ )
			{
				AActor* Actor = GLevel->Actors(i);
				if( Actor )
				{
					if( Actor->bStatic || Actor->bNoDelete )
						Exchange( Actor->Role, Actor->RemoteRole );
					else
						GLevel->DestroyActor( Actor );
				}
			}
		}

		// Init scripting.
		for( i=0; i<GLevel->Actors.Num(); i++ )
			if( GLevel->Actors(i) )
				GLevel->Actors(i)->InitExecution();

		// Enable actor script calls.
		Info->bBegunPlay = 1;
		Info->bStartup = 1;

		// Init the game.
		if( Info->Game )
			Info->Game->eventInitGame( Options, Error );

		// Send PreBeginPlay.
		for( i=0; i<GLevel->Actors.Num(); i++ )
			if( GLevel->Actors(i) )
				GLevel->Actors(i)->eventPreBeginPlay();

		// Set BeginPlay.
		for( i=0; i<GLevel->Actors.Num(); i++ )
			if( GLevel->Actors(i) )
				GLevel->Actors(i)->eventBeginPlay();

		// Set zones.
		for( i=0; i<GLevel->Actors.Num(); i++ )
			if( GLevel->Actors(i) )
				GLevel->SetActorZone( GLevel->Actors(i), 1, 1 );

		// Post begin play.
		for( i=0; i<GLevel->Actors.Num(); i++ )
			if( GLevel->Actors(i) )
				GLevel->Actors(i)->eventPostBeginPlay();

		// Begin scripting.
		for( i=0; i<GLevel->Actors.Num(); i++ )
			if( GLevel->Actors(i) )
				GLevel->Actors(i)->eventSetInitialState();

		// Find bases
		for( i=0; i<GLevel->Actors.Num(); i++ )
		{
			if( GLevel->Actors(i) ) 
			{
				if ( GLevel->Actors(i)->AttachTag != NAME_None )
				{
					//find actor to attach self onto
					for( INT j=0; j<GLevel->Actors.Num(); j++ )
					{
						if( GLevel->Actors(j) && (GLevel->Actors(j)->Tag == GLevel->Actors(i)->AttachTag) )
						{
							GLevel->Actors(i)->SetBase(GLevel->Actors(j), 0);
							break;
						}
					}
				}
				else if( !GLevel->Actors(i)->Base && GLevel->Actors(i)->bCollideWorld 
				 && (GLevel->Actors(i)->IsA(ADecoration::StaticClass()) || GLevel->Actors(i)->IsA(AInventory::StaticClass()) || GLevel->Actors(i)->IsA(APawn::StaticClass())) 
				 &&	((GLevel->Actors(i)->Physics == PHYS_None) || (GLevel->Actors(i)->Physics == PHYS_Rotating)) )
				{
					 GLevel->Actors(i)->FindBase();
					 if ( GLevel->Actors(i)->Base == Info )
						 GLevel->Actors(i)->SetBase(NULL, 0);
				}
			}
		}