I'll try to explain you, how this works. Hoping that after explaining to you I'll be able to understand it myself too
- ClientPerkRepLink is spawned in ServerStStats.PreBeginPlay().ServerPerksMut.CheckReplacement() catches ClientPerkRepLink and fills it with data: weapons, custom chars, smiles.
- ServerPerksMut.CheckReplacement() catches ServerStStats and fills it with perk data.
- ClientPerkRepLink sends all weapons, then categories to the client, taking 0.1s pauses between subsequent sends. For example, it takes 10 seconds to send 100 weapons.
- ClientPerkRepLink.ClientSendAcknowledge() is called, waiting 1s for client to acknowledge server how many weapons and categories are received.
- If client didn't received all weapons and categories (or didn't sent ack in time), the entire weapon sending process will be repeated (steps 4-6).
- When client confirms that all weapons and categories are successfully received, server starts sending custom characters, taking 0.15s pauses in between.
- After that smiles are being sent. There are no ACK requests on smile tags, and that's is absolutely right, because player can normally play even without seeing any dumb pictures in the chat
- After all weapons, categories, characters and smile are being sent, servers calls ClientAllReceived(), which sets bRepCompleted=true on client side. Starting from this point trader menu items can be displayed.
The problems I see:[/U]
Code:
Auto state RepSetup
{
Begin:
if( Level.NetMode==NM_Client )
Stop;
Sleep(1.f);
[COLOR="Orange"]NetUpdateFrequency = 0.5f;[/COLOR]
if( NetConnection(StatObject.PlayerOwner.Player)!=None ) // Network client.
{
ClientReceiveURL(ServerWebSite,StatObject.PlayerOwner.GetPlayerIDHash());
// Now MAKE SURE client receives the full inventory list.
[COLOR="Yellow"]while( ClientAccknowledged[0]<ShopInventory.Length || ClientAccknowledged[1]<ShopCategories.Length )[/COLOR]
{
for( SendIndex=0; SendIndex<ShopInventory.Length; ++SendIndex )
{
ClientReceiveWeapon(SendIndex,ShopInventory[SendIndex].PC,ShopInventory[SendIndex].CatNum);
Sleep(0.1f);
}
for( SendIndex=0; SendIndex<ShopCategories.Length; ++SendIndex )
{
ClientReceiveCategory(SendIndex,ShopCategories[SendIndex]);
Sleep(0.1f);
}
ClientSendAcknowledge();
[COLOR="orange"]Sleep(1.f);[/COLOR]
}
// Send client all the custom characters.
while( ClientAckSkinNum<CustomChars.Length )
{
ClientReceiveChar(CustomChars[ClientAckSkinNum],ClientAckSkinNum);
Sleep(0.15f);
}
// Send all chat icons.
for( SendIndex=0; SendIndex<SmileyTags.Length; ++SendIndex )
{
ClientReceiveTag(SmileyTags[SendIndex].SmileyTex,SmileyTags[SendIndex].SmileyTag,SmileyTags[SendIndex].bInCAPS);
Sleep(0.1f);
}
SmileyTags.Length = 0;
}
else
{
bReceivedURL = true;
InitDLCCheck();
}
ClientAllReceived();
GoToState('UpdatePerkProgress');
}
First one, why weapon categories and weapons are put together in the same loop? For example, if client hasn't received one category only (or most likely haven't managed to send ACK to server in time), then server re-sends all weapons again, which takes another 10+ seconds.
Second, server-to-client replication happens once per 2 seconds (
NetUpdateFrequency=0.5f;), client-to-server replication happens once per second (default LinkedReplicationInfo.NetUpdateFrequency=1). So in worst scenario it may take up to 3 seconds to receive ACK back from client. Server waits only 1 second (
Sleep(1.f);) after calling
ClientSendAcknowledge(). Most likely it will start re-sending weapons again before ACK received.
Third,
SmileyTags should be sent after calling
ClientAllReceived(), because this data is unimportant. Unless you can't do shopping before seeing a portrait of
Chuck Norris first
But even after fixing all issues above I don't like the way, how weapons are replicated, or, to be precise, how ACKs are being sent. Imo it would be much better to do checks on client side. Server should send total amount of weapons, categories and custom characters to the client during the initial replication. Then client checks, if all this data is received, and if not, it requests server to send missing data.