Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Feature Requests

Development::Feature Requests Post suggestions/feature requests here.

Reply
 
Thread Tools Display Modes
  #1  
Old 10-06-2008, 08:02 PM
Rocker8956
Hill Giant
 
Join Date: Sep 2007
Posts: 117
Default

I think this would only effect character's with track and people using MQ. Couple of questions to confirm that though.

Does track get the mob's position from the server everytime it ticks? or does it use the cleint's last known position of that mob?

The ghost would disappear before the player saw it because the player would have to be within the level 3 distance to see it correct? or does the update only happen if the mob is within that range?

Is the client smart enough to ask "Is this mob really there?" when the player tries to target it?
Reply With Quote
  #2  
Old 10-06-2008, 08:12 PM
Rocker8956
Hill Giant
 
Join Date: Sep 2007
Posts: 117
Default

Sorry for the back to back post, ran out of time to edit.

Does an update occur in the level 2 and level 3 intervals even though it occured during the level 1 interval?
Reply With Quote
  #3  
Old 10-06-2008, 11:39 PM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

I think the NPC ghost will still be there because it doesn't check if it is actually there, it only updates if it is there. So, since it isn't there, it would never update until the globalposition timer was up.

I do think we are doing the same work multiple times in some cases though. If so, it is a huge waste of bandwidth and resources. For example, from reading the code, it looks like the globalpositionupdate is done everytime the threshold (60 seconds by default) is met. But, it will still send it even if that same mob is within close range of the player and may have just sent an update already. Here is the code that decides when to send the position update:

npc.cpp
Code:
	global_position_update_timer(RuleI(Zone, NPCGlobalPositionUpdateInterval)),

//lines between this code and the code below here:

		//60 seconds, or whatever the rule is set to has passed, send this position to everyone to avoid ghosting
		if(global_position_update_timer.Check()){
			SendAllPosition();
		}
And then the SendAllPosition code:

mob.cpp
Code:
// this one just warps the mob to the current location
void Mob::SendAllPosition() {
	EQApplicationPacket* app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
	PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer;	
	MakeSpawnUpdateNoDelta(spu);
//?	spu->heading *= 8;
	entity_list.QueueClients(this, app, true);
	safe_delete(app);
}
After thinking about it more, maybe the zonewide update of the NPCGlobalPositionUpdateInterval should actually be part of the update manager settings. So, it all works in the same system and all works together to make it as efficient as possible and reduce any overlapping possibilities.

Maybe an all around better system would be to only update NPC locations if they actually move from their current position. So, only pathing NPCs or NPC that have been moved by a player by being pulled or whatever would ever be sending updates. Then you instantly reduce regular updates down to only pathing NPCs and the few that are maybe aggroed and chasing a player or whatever. Then, after the check to see if the NPC is moving happens, it would use a radius check to see how far away they are from the player to decide how often they will update the player. This should minimize traffic to a very bare minimum, at least the traffic related to spawn updates. From what I have seen, it does seem like a large portion of the traffic for the emulator is related to updates, so tweaks to the system could have a nice impact. If this could all be adjusted on a per zone basis, I wouldn't be too surprised if servers could be tweaked to handle double the number of players that they can now. I haven't really done any detailed testing on this yet, but from what I have seen, the changes I have made already are a very noticeable improvement.

Maybe if we could check the NPCs current position and if it differs by X amount from the last time it was checked, it sends a global position update.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #4  
Old 10-13-2008, 12:31 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Still looking into how to trim down the bandwidth from location updates, I think I know how things need to work to trim bandwidth to a minimum without effecting how players see the world.

If a player zones in, they will be sent position updates for all NPCs in the zone, but after that they only need to know if an NPC moves, depops/dies or spawns. Zoning and spawn/depop/death updates are already set, so all we need to adjust are the regular updates that occur.

First, we would only want position updates to come in if they NPC has actually moved, so maybe a check something like this could look for NPC movement:

Code:
	float cur_x = GetX();
	float cur_y = GetY();
	float cur_z = GetZ();

	if( cur_x != last_x || cur_y != last_y || cur_z != last_z ) {
		float last_x = cur_x;
		float last_y = cur_y;
		float last_z = cur_z;
		SendAllPosition();
	}
Currently, all NPCs send regular updates whether they have moved or not, which is a major waste of bandwidth. Unless a zone is full of NPCs that move non-stop, then a simple change to only update when they do move will make a considerable difference.

Next, we would just have it use the Update Manager to set the levels and timers for updates. So that close npc updates will update often and NPCs that are further away will update slower with diminishing returns the further away they are. This code is already in place in the update manager, so my only suggestion would be to allow the levels to be able to be set in the zones table and then load those levels into memory for the zone when it boots up. We could also have an adjustable setting for the level timers in the zones table, but that isn't quite as important as the levels themselves. It is probably a good idea to have a default value for all zones if these fields are left at 0. But, it would also be nice if there was a way to disable position updates completely on a per zone basis if needed.

Last, I think we could make a big difference if we have a check to see if a player was actually moving before checking the Update Manager Levels. If a player is not moving, we could have it divide the levels by 2 so that you only get updates on nearby NPCs. Most of the time, players are not moving, so they don't need to have updates from very far away. But, if they are moving, you don't want things to warp right on top of them due to having low level settings on the update manager. This would further reduce the required bandwidth for position updates to help make it as efficient as possible.

Maybe using the client movement checks created for the MQ Detection that were added to #showstats could be used to check if a player is moving so it can decide to divide the update manager levels or not:

Code:
if (GetMovementSpeed() = 0)
Then have it divide the update manager levels by 2. If they are moving, then it just uses whatever the levels are set to for that particular zone.

With some help from other coders, I think we can get this working and make a huge impact on reducing bandwidth utilization. Since that is a big limiting factor for most emulator servers, I think this change of process would be good for the whole project. Any input from experienced coders would be much appreciated!
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!

Last edited by trevius; 10-14-2008 at 02:40 AM..
Reply With Quote
  #5  
Old 10-13-2008, 04:20 PM
KLS
Administrator
 
Join Date: Sep 2006
Posts: 1,348
Default

Quote:
we would only want position updates to come in if they NPC has actually moved
I agree, it's a good thing it already does that. =p

Ima add your suggestion of a variable distance for the update manager based on zone settings. Also the global position update will no longer fire if you have the update manager enabled, and I think I'll make it being on default.

Edit: And actually after trying it, it seems like a lot of it may need to be rewritten before we can make it usable =/

Last edited by KLS; 10-14-2008 at 12:54 AM..
Reply With Quote
  #6  
Old 10-13-2008, 07:53 PM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Thanks for looking into this, KLS! I do know for sure that even just by changing the globalpositionupdate rule from 60 seconds to 10 minutes makes a huge difference on raid lag. With enough tweaking to the system to make it as efficient as possible, I think we could remove a large chunk of unneeded bandwidth usage. I wouldn't even be surprised if we could double the amount of players that a server could handle.

So, if we disabled the globalpositionupdate, do you think we would need to essentially add it to the update manager levels? Currently, there are 4 levels that can be set in the update manager. Could there be a 5th level that is just equal to anything greater than the 4th level to encompass the rest of the zone? Then maybe have an update timer for that level similar to how the global position updates work now, but adjustable per zone. I think that would take care of possible mob ghosting issues.

You mention that position updates are currently only sent if an NPC moves. That may be true for the update manager, but I think the globalpositionupdate is currently just sending the entire zone's NPC positions whether they moved or not. I think that is why non-moving NPCs seem to jump every minute, but I may be wrong about that. If it was only sending updates for NPCs that had moved, I don't think adjusting the timer setting rule would have made nearly as much impact as what I have seen from it.

I have been looking through the code for this alot lately. I know my code understanding is still noob at best, but from what I can tell, the globalpositionupdate is sending every npc's position whether they moved or not.

Code:
		//60 seconds, or whatever the rule is set to has passed, send this position to everyone to avoid ghosting
		if(global_position_update_timer.Check()){
			SendAllPosition();
		}
Code:
void Mob::SendAllPosition() {
	EQApplicationPacket* app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
	PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer;	
	MakeSpawnUpdateNoDelta(spu);
//?	spu->heading *= 8;
	entity_list.QueueClients(this, app, true);
	safe_delete(app);
}
Code:
void EntityList::QueueClients(Mob* sender, const EQApplicationPacket* app, bool ignore_sender, bool ackreq) {
	LinkedListIterator<Client*> iterator(client_list);
	
	iterator.Reset();
	while(iterator.MoreElements())
	{
		Client* ent = iterator.GetData();

		if ((!ignore_sender || ent != sender))
		{
			ent->QueuePacket(app, ackreq, Client::CLIENT_CONNECTED);
		}
		iterator.Advance();
	}
}
Code:
void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu){
	memset(spu,0xff,sizeof(PlayerPositionUpdateServer_Struct));
	spu->spawn_id	= GetID();
	spu->x_pos		= FloatToEQ19(x_pos);
	spu->y_pos		= FloatToEQ19(y_pos);
	spu->z_pos		= FloatToEQ19(z_pos);
	spu->delta_x	= NewFloatToEQ13(0);
	spu->delta_y	= NewFloatToEQ13(0);
	spu->delta_z	= NewFloatToEQ13(0);
	spu->heading	= FloatToEQ19(heading);
	spu->animation	= 0;
	spu->delta_heading = NewFloatToEQ13(0);
	spu->padding0002	=0;
	spu->padding0006	=7;
	spu->padding0014	=0x7f;
	spu->padding0018	=0x5df27;
}
I am not trying to second guess you, btw. I just want to understand what is happening to see how/where it can possibly be tweaked to work better.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 01:22 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3