# HG changeset patch
# User CrimsonDusk
# Date 1360538371 -7200
#      Mon Feb 11 01:19:31 2013 +0200
# Node ID 460a4505ef46193f2d5080d29a62c94b0a0cb21e
# Parent  7be09b1cfb24c42c42db433e497cf40724e14228
Added netcode for texture offsets, Line_SetTextureOffset works online now

diff -r 7be09b1cfb24 -r 460a4505ef46 docs/zandronum-history.txt
--- a/docs/zandronum-history.txt	Sun Feb 10 16:30:43 2013 +0200
+++ b/docs/zandronum-history.txt	Mon Feb 11 01:19:31 2013 +0200
@@ -38,6 +38,7 @@
 +	- Added NORANDOM support to A_CustomBulletAttack and A_FireBullets (ported from ZDoom revision 2318). [Torr Samaho] 
 +	- Added new CVAR cl_connectiontype (default 1, allowed values 0-1). The lower the number, the less network traffic the server will try to send to the client. Currently this is very limited and only has one effect: With a setting of 1, blood sprites are spawned on the client with a size depending on the damage dealt, while they are always at full size if it's 0. [Torr Samaho]
 +	- Added new compatflag "ZDoom 1.23b33 jump physics ", controlled by the new CVAR compat_123b33jumpphysics. If this is enabled, jumping behaves more like it did in ZDoom 1.23b33. In particular, the MAP26 reverse window jump is not possible anymore. [Watermelon, Torr Samaho]
++	- Added networking management for walltexture offset management. Changed offsets are reset properly and are transmitted to newly connecting clients. Line_SetTextureOffset works properly online now. [Dusk]
 -	- Hopefully fixed player class related Hexen startup crashes. [Torr Samaho]
 -	- Fixed: Newly connecting clients were not properly informed about a music change if the music name was longer than 15 characters. [Torr Samaho]
 -	- Fixed: Attached 3d midtexture heights were not reset properly during map resets. [Dusk]
diff -r 7be09b1cfb24 -r 460a4505ef46 src/cl_main.cpp
--- a/src/cl_main.cpp	Sun Feb 10 16:30:43 2013 +0200
+++ b/src/cl_main.cpp	Mon Feb 11 01:19:31 2013 +0200
@@ -2461,6 +2461,25 @@
 		client_AnnouncerSound( pByteStream );
 		break;
 
+	// [Dusk]
+	case SVC_SETTEXTUREOFFSET:
+		{
+			const ULONG ulSide = NETWORK_ReadShort( pByteStream );
+			const ULONG ulWhich = NETWORK_ReadByte( pByteStream );
+			const fixed_t ofs = NETWORK_ReadLong( pByteStream );
+
+			// [Dusk] ulWhich also contains bY as a flag
+			bool bY = ulWhich & 128;
+			int which = ulWhich & ~128;
+
+			if ( ulSide >= (ULONG)numsides || which >= 3 )
+				break;
+
+			side_t::part* tex = &sides[ulSide].textures[which];
+			( bY ? tex->yoffset : tex->xoffset ) = ofs;
+		}
+		break;
+
 	case SVC_EXTENDEDCOMMAND:
 		{
 			const LONG lExtCommand = NETWORK_ReadByte( pByteStream );
diff -r 7be09b1cfb24 -r 460a4505ef46 src/g_game.cpp
--- a/src/g_game.cpp	Sun Feb 10 16:30:43 2013 +0200
+++ b/src/g_game.cpp	Mon Feb 11 01:19:31 2013 +0200
@@ -3285,30 +3285,52 @@
 		lines[ulIdx].args[4] = lines[ulIdx].SavedArgs[4];
 
 		// Also, restore any changed textures.
-		if ( lines[ulIdx].ulTexChangeFlags != 0 )
+		// [Dusk] Also reset texture offsets
+		bool bSendTextureUpdate, bSendOffsetUpdate = false;
+		for ( ULONG i = 0; i < 2; i++ )
 		{
-			if ( lines[ulIdx].sidenum[0] != 0xffff )
-			{
-				sides[lines[ulIdx].sidenum[0]].SetTexture(side_t::top, sides[lines[ulIdx].sidenum[0]].SavedTopTexture);
-				sides[lines[ulIdx].sidenum[0]].SetTexture(side_t::mid, sides[lines[ulIdx].sidenum[0]].SavedMidTexture);
-				sides[lines[ulIdx].sidenum[0]].SetTexture(side_t::bottom, sides[lines[ulIdx].sidenum[0]].SavedBottomTexture);
-			}
-
-			if ( lines[ulIdx].sidenum[1] != NO_SIDE )
+			if ( lines[ulIdx].sidenum[i] == ( i ? NO_SIDE : 0xffff ))
+				continue;
+
+			side_t* side = &sides[lines[ulIdx].sidenum[i]];
+
+			if ( lines[ulIdx].ulTexChangeFlags != 0 )
 			{
-				sides[lines[ulIdx].sidenum[1]].SetTexture(side_t::top, sides[lines[ulIdx].sidenum[1]].SavedTopTexture);
-				sides[lines[ulIdx].sidenum[1]].SetTexture(side_t::mid, sides[lines[ulIdx].sidenum[1]].SavedMidTexture);
-				sides[lines[ulIdx].sidenum[1]].SetTexture(side_t::bottom, sides[lines[ulIdx].sidenum[1]].SavedBottomTexture);
+				side->SetTexture(side_t::top, side->SavedTopTexture);
+				side->SetTexture(side_t::mid, side->SavedMidTexture);
+				side->SetTexture(side_t::bottom, side->SavedBottomTexture);
+
+				// Mark the texture as no being changed.
+				lines[ulIdx].ulTexChangeFlags = 0;
+
+				bSendTextureUpdate = true;
 			}
 
-			// If we're the server, tell clients about this texture change.
-			if ( NETWORK_GetState( ) == NETSTATE_SERVER )
-				SERVERCOMMANDS_SetLineTexture( ulIdx );
-
-			// Mark the texture as no being changed.
-			lines[ulIdx].ulTexChangeFlags = 0;
+			// [Dusk] Reset the X/Y offsets
+			for ( ULONG j = 0; j < 3; j++ )
+			{
+				const struct {fixed_t* ofs, *savedofs;} offsetInfo[2] = 
+				{
+					{&side->textures[j].xoffset, &side->textures[j].SavedXOffset},
+					{&side->textures[j].yoffset, &side->textures[j].SavedYOffset},
+				};
+
+				for ( ULONG k = 0; k < 2; k++ )
+				{
+					if ( *( offsetInfo[k].ofs ) != *( offsetInfo[k].savedofs ))
+					{
+						Printf ("Reset %lu.%lu.%lu\n", i, j, k);
+						*( offsetInfo[k].ofs ) = *( offsetInfo[k].savedofs );
+						SERVERCOMMANDS_SetTextureOffset( side - sides, j, k );
+					}
+				}
+			}
 		}
 
+		// If we're the server, tell clients about this texture change.
+		if (( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( bSendTextureUpdate == true ))
+			SERVERCOMMANDS_SetLineTexture( ulIdx );
+
 		// Restore the line's alpha if it changed.
 		if ( lines[ulIdx].Alpha != lines[ulIdx].SavedAlpha )
 		{
diff -r 7be09b1cfb24 -r 460a4505ef46 src/network_enums.h
--- a/src/network_enums.h	Sun Feb 10 16:30:43 2013 +0200
+++ b/src/network_enums.h	Mon Feb 11 01:19:31 2013 +0200
@@ -301,6 +301,7 @@
 	ENUM_ELEMENT ( SVC_ADJUSTPUSHER ),
 	ENUM_ELEMENT ( SVC_ANNOUNCERSOUND ),
 	ENUM_ELEMENT ( SVC_SETACSVARIABLE ),
+	ENUM_ELEMENT ( SVC_SETTEXTUREOFFSET ),
 	ENUM_ELEMENT ( SVC_EXTENDEDCOMMAND ),
 
 	ENUM_ELEMENT ( NUM_SERVER_COMMANDS ),
diff -r 7be09b1cfb24 -r 460a4505ef46 src/p_map.cpp
--- a/src/p_map.cpp	Sun Feb 10 16:30:43 2013 +0200
+++ b/src/p_map.cpp	Mon Feb 11 01:19:31 2013 +0200
@@ -6545,6 +6545,27 @@
 	}
 }
 
+//=============================================================================
+//
+// P_NetworkTexOffsetChange
+//
+// [Dusk] Network + map reset savvy texture offset changing callback.
+// NOTE: This is declared in r_defs.h, since side_t calls this function.
+//
+//=============================================================================
+void P_NetworkTexOffsetChange( side_t* side, ULONG ulWhich, bool bY ) {
+	if ( NETWORK_InClientMode( ) || !side )
+		return;
+
+	side_t::part* tex = &side->textures[ulWhich];
+	fixed_t ofs = ( bY ? tex->yoffset : tex->xoffset );
+
+	// If the offset was changed mid-game, we'll have to tell clients that it was.
+	// If it was set by the map, we may not call this or we'll needlessly waste bandwidth.
+	if (( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( g_bLoadingMap == false ))
+		SERVERCOMMANDS_SetTextureOffset( side - sides, ulWhich, bY );
+}
+
 void SpawnShootDecal (AActor *t1, const FTraceResults &trace)
 {
 	FDecalBase *decalbase = NULL;
diff -r 7be09b1cfb24 -r 460a4505ef46 src/p_saveg.cpp
--- a/src/p_saveg.cpp	Sun Feb 10 16:30:43 2013 +0200
+++ b/src/p_saveg.cpp	Mon Feb 11 01:19:31 2013 +0200
@@ -487,6 +487,10 @@
 FArchive &operator<< (FArchive &arc, side_t::part &p)
 {
 	arc << p.xoffset << p.yoffset << p.interpolation << p.texture;// << p.Light;
+
+	// [Dusk]
+	arc << p.SavedXOffset << p.SavedYOffset;
+
 	return arc;
 }
 
diff -r 7be09b1cfb24 -r 460a4505ef46 src/p_setup.cpp
--- a/src/p_setup.cpp	Sun Feb 10 16:30:43 2013 +0200
+++ b/src/p_setup.cpp	Mon Feb 11 01:19:31 2013 +0200
@@ -228,6 +228,9 @@
 static void P_AllocateSideDefs (int count);
 static void P_SetSideNum (DWORD *sidenum_p, WORD sidenum);
 
+// [Dusk] Is a map being currently loaded?
+bool g_bLoadingMap = false;
+
 
 
 
@@ -2503,6 +2506,14 @@
 	sd->SavedTopTexture = sd->GetTexture(side_t::top);
 	sd->SavedMidTexture = sd->GetTexture(side_t::mid);
 	sd->SavedBottomTexture = sd->GetTexture(side_t::bottom);
+
+	// [Dusk] I don't know where else to stuff this...
+	// Store the X/Y offsets here
+	for ( ULONG i = 0; i < 3; i++ )
+	{
+		sd->textures[i].SavedXOffset = sd->GetTextureXOffset( i );
+		sd->textures[i].SavedYOffset = sd->GetTextureYOffset( i );
+	}
 }
 
 // killough 4/4/98: delay using texture names until
@@ -3758,6 +3769,9 @@
 	int i;
 	bool buildmap;
 
+	// [Dusk] We are now loading a map
+	g_bLoadingMap = true;
+
 	for (i = 0; i < (int)countof(times); ++i)
 	{
 		times[i].Reset();
@@ -4366,6 +4380,9 @@
 
 	// Call Init function to set sector colors if in Domination
 	DOMINATION_Init();
+
+	// [Dusk] Done loading the map
+	g_bLoadingMap = false;
 }
 
 
diff -r 7be09b1cfb24 -r 460a4505ef46 src/p_setup.h
--- a/src/p_setup.h	Sun Feb 10 16:30:43 2013 +0200
+++ b/src/p_setup.h	Mon Feb 11 01:19:31 2013 +0200
@@ -112,4 +112,7 @@
 int GetUDMFInt(int type, int index, const char *key);
 fixed_t GetUDMFFixed(int type, int index, const char *key);
 
+// [Dusk]
+extern bool g_bLoadingMap;
+
 #endif
diff -r 7be09b1cfb24 -r 460a4505ef46 src/r_defs.h
--- a/src/r_defs.h	Sun Feb 10 16:30:43 2013 +0200
+++ b/src/r_defs.h	Mon Feb 11 01:19:31 2013 +0200
@@ -48,6 +48,10 @@
 // [BC] This is the maximum length a skin name can be.
 #define	MAX_SKIN_NAME					24
 
+// [Dusk] This just cannot be anywhere else. Defined in p_map.cpp
+struct side_t;
+void P_NetworkTexOffsetChange( side_t* side, ULONG ulWhich, bool bY );
+
 // Silhouette, needed for clipping Segs (mainly)
 // and sprites representing things.
 enum
@@ -805,6 +809,8 @@
 		FTextureID texture;
 		TObjPtr<DInterpolation> interpolation;
 		//int Light;
+		// [Dusk] We need to save offsets too for resets
+		fixed_t SavedXOffset, SavedYOffset;
 	};
 
 	sector_t*	sector;			// Sector the SideDef is facing.
@@ -843,12 +849,19 @@
 	void SetTextureXOffset(int which, fixed_t offset)
 	{
 		textures[which].xoffset = offset;
+
+		P_NetworkTexOffsetChange( this, which, false ); // [Dusk]
 	}
 	void SetTextureXOffset(fixed_t offset)
 	{
 		textures[top].xoffset =
 		textures[mid].xoffset =
 		textures[bottom].xoffset = offset;
+
+		// [Dusk]
+		P_NetworkTexOffsetChange( this, top, false );
+		P_NetworkTexOffsetChange( this, mid, false );
+		P_NetworkTexOffsetChange( this, bottom, false );
 	}
 	fixed_t GetTextureXOffset(int which) const
 	{
@@ -857,17 +870,26 @@
 	void AddTextureXOffset(int which, fixed_t delta)
 	{
 		textures[which].xoffset += delta;
+
+		P_NetworkTexOffsetChange( this, which, false ); // [Dusk]
 	}
 
 	void SetTextureYOffset(int which, fixed_t offset)
 	{
 		textures[which].yoffset = offset;
+
+		P_NetworkTexOffsetChange( this, which, true ); // [Dusk]
 	}
 	void SetTextureYOffset(fixed_t offset)
 	{
 		textures[top].yoffset =
 		textures[mid].yoffset =
 		textures[bottom].yoffset = offset;
+
+		// [Dusk]
+		P_NetworkTexOffsetChange( this, top, true );
+		P_NetworkTexOffsetChange( this, mid, true );
+		P_NetworkTexOffsetChange( this, bottom, true );
 	}
 	fixed_t GetTextureYOffset(int which) const
 	{
@@ -876,6 +898,8 @@
 	void AddTextureYOffset(int which, fixed_t delta)
 	{
 		textures[which].yoffset += delta;
+
+		P_NetworkTexOffsetChange( this, which, true ); // [Dusk]
 	}
 
 	DInterpolation *SetInterpolation(int position);
diff -r 7be09b1cfb24 -r 460a4505ef46 src/sv_commands.cpp
--- a/src/sv_commands.cpp	Sun Feb 10 16:30:43 2013 +0200
+++ b/src/sv_commands.cpp	Mon Feb 11 01:19:31 2013 +0200
@@ -5204,6 +5204,26 @@
 }
 
 //*****************************************************************************
+// [Dusk]
+void SERVERCOMMANDS_SetTextureOffset( ULONG ulSide, ULONG ulWhich, bool bY, ULONG ulPlayerExtra, ULONG ulFlags )
+{
+	if ( ulSide >= (ULONG)numsides || ulWhich > 3 )
+		return;
+
+	fixed_t ofs;
+	if ( bY == true )
+		ofs = sides[ulSide].GetTextureYOffset ( ulWhich );
+	else
+		ofs = sides[ulSide].GetTextureXOffset ( ulWhich );
+
+	NetCommand command( SVC_SETTEXTUREOFFSET );
+	command.addShort( ulSide );
+	command.addByte( ulWhich | ( bY ? 128 : 0 )); // Transmit a bit for bY
+	command.addLong( ofs );
+	command.sendCommandToClients( ulPlayerExtra, ulFlags );
+}
+
+//*****************************************************************************
 //*****************************************************************************
 //
 void SERVERCOMMANDS_Sound( LONG lChannel, const char *pszSound, float fVolume, float fAttenuation, ULONG ulPlayerExtra, ULONG ulFlags )
diff -r 7be09b1cfb24 -r 460a4505ef46 src/sv_commands.h
--- a/src/sv_commands.h	Sun Feb 10 16:30:43 2013 +0200
+++ b/src/sv_commands.h	Mon Feb 11 01:19:31 2013 +0200
@@ -257,6 +257,7 @@
 
 // Side commands. These have something to do with lines.
 void	SERVERCOMMANDS_SetSideFlags( ULONG ulSide, ULONG ulPlayerExtra = MAXPLAYERS, ULONG ulFlags = 0 );
+void	SERVERCOMMANDS_SetTextureOffset( ULONG ulSide, ULONG ulWhich, bool bY, ULONG ulPlayerExtra = MAXPLAYERS, ULONG ulFlags = 0 );
 
 // ACS commands. These have something to do with ACS scripts.
 void	SERVERCOMMANDS_ACSScriptExecute( ULONG ulScript, AActor *pActivator, LONG lLineIdx, char *pszMap, bool bBackSide, int iArg0, int iArg1, int iArg2, bool bAlways, ULONG ulPlayerExtra = MAXPLAYERS, ULONG ulFlags = 0 );
diff -r 7be09b1cfb24 -r 460a4505ef46 src/sv_main.cpp
--- a/src/sv_main.cpp	Sun Feb 10 16:30:43 2013 +0200
+++ b/src/sv_main.cpp	Mon Feb 11 01:19:31 2013 +0200
@@ -3172,6 +3172,17 @@
 		// Have the side's flags changed?
 		if ( sides[ulSide].Flags != sides[ulSide].SavedFlags )
 			SERVERCOMMANDS_SetSideFlags( ulSide, ulClient, SVCF_ONLYTHISCLIENT );
+
+		// [Dusk] Also handle offsets
+		for ( ULONG i = 0; i < 3; i++ )
+		{
+			side_t::part* tex = &sides[ulSide].textures[i];
+			if ( tex->SavedXOffset != tex->xoffset )
+				SERVERCOMMANDS_SetTextureOffset( ulSide, i, false, ulClient, SVCF_ONLYTHISCLIENT );
+
+			if ( tex->SavedYOffset != tex->yoffset )
+				SERVERCOMMANDS_SetTextureOffset( ulSide, i, true, ulClient, SVCF_ONLYTHISCLIENT );
+		}
 	}
 }
 
