TheLieka
04-20-2008, 02:54 PM
I've seen several people asking about this, so I figured I'd take a look into it.
Player Movement only stores coordinates to /rewind if they were significant, yet not a very large movement update. This prevents someone from intra-zone gating, then /rewind to get back to a spawn, etc.
One thing, when doing the diff, be sure that you update patch_Titanium.conf and move it into your server's folder, since this patch updates it (if you don't, then OP_Rewind won't get identified, and the rest of the patch won't do anything).
Here ya go, let me know what you think:
This was diffed against 0.7.0-1106:
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/zone/zoning.cpp C:/eqemu-source-diff/daxum/zone/zoning.cpp
236c236
< if(Admin() < minStatusToIgnoreZoneFlags && !HasZoneFlag(target_zone_id)) {
---
> if(Admin() < minStatusToIgnoreZoneFlags && !HasZoneFlag(target_zone_id)) {
420a421,424
> case Rewind:
> Message(15, "Rewinding to previous location.");
> ZonePC(zoneID, x, y, z, heading, ignorerestrictions, zm);
> break;
437,478c441,482
< switch(zm) {
< case EvacToSafeCoords:
< case ZoneToSafeCoords:
< x = zone->safe_x();
< y = zone->safe_y();
< z = zone->safe_z();
< heading = heading;
< break;
< case GMSummon:
< zonesummon_x = x_pos = x;
< zonesummon_y = y_pos = y;
< zonesummon_z = z_pos = z;
< heading = heading;
<
< zonesummon_id = zoneID;
< zonesummon_ignorerestrictions = 1;
< break;
< case ZoneSolicited:
< zonesummon_x = x;
< zonesummon_y = y;
< zonesummon_z = z;
< heading = heading;
<
< zonesummon_id = zoneID;
< zonesummon_ignorerestrictions = ignorerestrictions;
< break;
< case GateToBindPoint:
< x = x_pos = m_pp.binds[0].x;
< y = y_pos = m_pp.binds[0].y;
< z = z_pos = m_pp.binds[0].z;
< heading = m_pp.binds[0].heading;
< break;
< case ZoneToBindPoint:
< x = x_pos = m_pp.binds[0].x;
< y = y_pos = m_pp.binds[0].y;
< z = z_pos = m_pp.binds[0].z;
< heading = m_pp.binds[0].heading;
<
< zonesummon_ignorerestrictions = 1;
< LogFile->write(EQEMuLog::Debug, "Player %s has died and will be zoned to bind point in zone: %s at LOC x=%f, y=%f, z=%f, heading=%f", GetName(), pZoneName, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, m_pp.binds[0].heading);
< break;
< case SummonPC:
---
> switch(zm) {
> case EvacToSafeCoords:
> case ZoneToSafeCoords:
> x = zone->safe_x();
> y = zone->safe_y();
> z = zone->safe_z();
> heading = heading;
> break;
> case GMSummon:
> zonesummon_x = x_pos = x;
> zonesummon_y = y_pos = y;
> zonesummon_z = z_pos = z;
> heading = heading;
>
> zonesummon_id = zoneID;
> zonesummon_ignorerestrictions = 1;
> break;
> case ZoneSolicited:
> zonesummon_x = x;
> zonesummon_y = y;
> zonesummon_z = z;
> heading = heading;
>
> zonesummon_id = zoneID;
> zonesummon_ignorerestrictions = ignorerestrictions;
> break;
> case GateToBindPoint:
> x = x_pos = m_pp.binds[0].x;
> y = y_pos = m_pp.binds[0].y;
> z = z_pos = m_pp.binds[0].z;
> heading = m_pp.binds[0].heading;
> break;
> case ZoneToBindPoint:
> x = x_pos = m_pp.binds[0].x;
> y = y_pos = m_pp.binds[0].y;
> z = z_pos = m_pp.binds[0].z;
> heading = m_pp.binds[0].heading;
>
> zonesummon_ignorerestrictions = 1;
> LogFile->write(EQEMuLog::Debug, "Player %s has died and will be zoned to bind point in zone: %s at LOC x=%f, y=%f, z=%f, heading=%f", GetName(), pZoneName, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, m_pp.binds[0].heading);
> break;
> case SummonPC:
483,487c487,498
< break;
< default:
< LogFile->write(EQEMuLog::Error, "Client::ZonePC() received a reguest to perform an unsupported client zone operation.");
< ReadyToZone = false;
< break;
---
> break;
> case Rewind:
> LogFile->write(EQEMuLog::Debug, "%s has requested a /rewind from %f, %f, %f, to %f, %f, %f in %s", GetName(), x_pos, y_pos, z_pos, rewind_x, rewind_y, rewind_z, zone->GetShortName());
> zonesummon_x = x_pos = x;
> zonesummon_y = y_pos = y;
> zonesummon_z = z_pos = z;
> heading = heading;
> break;
> default:
> LogFile->write(EQEMuLog::Error, "Client::ZonePC() received a reguest to perform an unsupported client zone operation.");
> ReadyToZone = false;
> break;
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/zone/mob.cpp C:/eqemu-source-diff/daxum/zone/mob.cpp
102a103
> rewind_timer(30000), //Lieka: Timer used for determining amount of time between actual player position updates for /rewind.
104c105
< bardsong_timer(6000),
---
> bardsong_timer(6000),
124c125,127
<
---
> rewind_x = 0; //Lieka: Stored x_pos for /rewind
> rewind_y = 0; //Lieka: Stored y_pos for /rewind
> rewind_z = 0; //Lieka: Stored z_pos for /rewind
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/zone/client_packet.cpp C:/eqemu-source-diff/daxum/zone/client_packet.cpp
316a317,318
> ConnectedOpcodes[OP_Rewind] = &Client::Handle_OP_Rewind;
>
808c810,838
<
---
>
> //Lieka: Check to see if PPU should trigger an update to the rewind position.
> float rewind_x_diff = 0;
> float rewind_y_diff = 0;
> float rewind_z_diff = 0;
>
> rewind_x_diff = ppu->x_pos - rewind_x;
> rewind_x_diff *= rewind_x_diff;
> rewind_y_diff = ppu->y_pos - rewind_y;
> rewind_y_diff *= rewind_y_diff;
>
> //Lieka: We only need to store updated values if the player has moved.
> //If the player has moved more than units for x or y, then we'll store
> //his pre-PPU x and y for /rewind, in case he gets stuck.
> if ((rewind_x_diff > 750) || (rewind_y_diff > 750)) {
> rewind_x = x_pos;
> rewind_y = y_pos;
> rewind_z = z_pos;
> }
>
> //Lieka: If the PPU was a large jump, such as a cross zone gate or Call of Hero,
> //just update rewind coords to the new ppu coords. This will prevent exploitation.
>
> if ((rewind_x_diff > 5000) || (rewind_y_diff > 5000)) {
> rewind_x = ppu->x_pos;
> rewind_y = ppu->y_pos;
> rewind_z = ppu->z_pos;
> }
>
816,822c846,852
< if(
< ( (heading != ppu->heading) && !((int)heading % 3) ) || // turning
< ( (x_pos != ppu->x_pos) && !((int)x_pos % 6) ) // moving
< )
< {
< CheckIncreaseSkill(SENSE_HEADING, -20);
< }
---
> if(
> ( (heading != ppu->heading) && !((int)heading % 3) ) || // turning
> ( (x_pos != ppu->x_pos) && !((int)x_pos % 6) ) // moving
> )
> {
> CheckIncreaseSkill(SENSE_HEADING, -20);
> }
876a907
> rewind_timer.Start(30000, true);
3156c3187
< }
---
> }
6827a6859,6868
> }
>
> void Client::Handle_OP_Rewind(const EQApplicationPacket *app)
> {
> if ((rewind_timer.GetRemainingTime() > 1 && rewind_timer.Enabled())) {
> Message_StringID(MT_System, 4059); //You must wait a bit longer before using the rewind command again.
> } else {
> CastToClient()->MovePC(zone->GetZoneID(), rewind_x, rewind_y, rewind_z, 0, 2, Rewind);
> rewind_timer.Start(30000, true);
> }
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/zone/client.h C:/eqemu-source-diff/daxum/zone/client.h
151a152
> Rewind, // Lieka: Summon to /rewind location.
153a155
>
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/zone/client_packet.h C:/eqemu-source-diff/daxum/zone/client_packet.h
214a215
> void Handle_OP_Rewind(const EQApplicationPacket *app);
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/zone/mob.h C:/eqemu-source-diff/daxum/zone/mob.h
788a789,792
> float rewind_x; //Lieka: Used for storing /rewind values
> float rewind_y; //Lieka: Used for storing /rewind values
> float rewind_z; //Lieka: Used for storing /rewind values
> Timer rewind_timer; //Lieka: Used for measuring how long a player stays in one spot
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/utils/patch_Titanium.conf C:/eqemu-source-diff/daxum/utils/patch_Titanium.conf
267a268
> OP_Rewind=0x4cfa # Lieka 4/20/08: /rewind command
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/common/emu_oplist.h C:/eqemu-source-diff/daxum/common/emu_oplist.h
401a402
> N(OP_Rewind),
<3,
Dax
Player Movement only stores coordinates to /rewind if they were significant, yet not a very large movement update. This prevents someone from intra-zone gating, then /rewind to get back to a spawn, etc.
One thing, when doing the diff, be sure that you update patch_Titanium.conf and move it into your server's folder, since this patch updates it (if you don't, then OP_Rewind won't get identified, and the rest of the patch won't do anything).
Here ya go, let me know what you think:
This was diffed against 0.7.0-1106:
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/zone/zoning.cpp C:/eqemu-source-diff/daxum/zone/zoning.cpp
236c236
< if(Admin() < minStatusToIgnoreZoneFlags && !HasZoneFlag(target_zone_id)) {
---
> if(Admin() < minStatusToIgnoreZoneFlags && !HasZoneFlag(target_zone_id)) {
420a421,424
> case Rewind:
> Message(15, "Rewinding to previous location.");
> ZonePC(zoneID, x, y, z, heading, ignorerestrictions, zm);
> break;
437,478c441,482
< switch(zm) {
< case EvacToSafeCoords:
< case ZoneToSafeCoords:
< x = zone->safe_x();
< y = zone->safe_y();
< z = zone->safe_z();
< heading = heading;
< break;
< case GMSummon:
< zonesummon_x = x_pos = x;
< zonesummon_y = y_pos = y;
< zonesummon_z = z_pos = z;
< heading = heading;
<
< zonesummon_id = zoneID;
< zonesummon_ignorerestrictions = 1;
< break;
< case ZoneSolicited:
< zonesummon_x = x;
< zonesummon_y = y;
< zonesummon_z = z;
< heading = heading;
<
< zonesummon_id = zoneID;
< zonesummon_ignorerestrictions = ignorerestrictions;
< break;
< case GateToBindPoint:
< x = x_pos = m_pp.binds[0].x;
< y = y_pos = m_pp.binds[0].y;
< z = z_pos = m_pp.binds[0].z;
< heading = m_pp.binds[0].heading;
< break;
< case ZoneToBindPoint:
< x = x_pos = m_pp.binds[0].x;
< y = y_pos = m_pp.binds[0].y;
< z = z_pos = m_pp.binds[0].z;
< heading = m_pp.binds[0].heading;
<
< zonesummon_ignorerestrictions = 1;
< LogFile->write(EQEMuLog::Debug, "Player %s has died and will be zoned to bind point in zone: %s at LOC x=%f, y=%f, z=%f, heading=%f", GetName(), pZoneName, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, m_pp.binds[0].heading);
< break;
< case SummonPC:
---
> switch(zm) {
> case EvacToSafeCoords:
> case ZoneToSafeCoords:
> x = zone->safe_x();
> y = zone->safe_y();
> z = zone->safe_z();
> heading = heading;
> break;
> case GMSummon:
> zonesummon_x = x_pos = x;
> zonesummon_y = y_pos = y;
> zonesummon_z = z_pos = z;
> heading = heading;
>
> zonesummon_id = zoneID;
> zonesummon_ignorerestrictions = 1;
> break;
> case ZoneSolicited:
> zonesummon_x = x;
> zonesummon_y = y;
> zonesummon_z = z;
> heading = heading;
>
> zonesummon_id = zoneID;
> zonesummon_ignorerestrictions = ignorerestrictions;
> break;
> case GateToBindPoint:
> x = x_pos = m_pp.binds[0].x;
> y = y_pos = m_pp.binds[0].y;
> z = z_pos = m_pp.binds[0].z;
> heading = m_pp.binds[0].heading;
> break;
> case ZoneToBindPoint:
> x = x_pos = m_pp.binds[0].x;
> y = y_pos = m_pp.binds[0].y;
> z = z_pos = m_pp.binds[0].z;
> heading = m_pp.binds[0].heading;
>
> zonesummon_ignorerestrictions = 1;
> LogFile->write(EQEMuLog::Debug, "Player %s has died and will be zoned to bind point in zone: %s at LOC x=%f, y=%f, z=%f, heading=%f", GetName(), pZoneName, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, m_pp.binds[0].heading);
> break;
> case SummonPC:
483,487c487,498
< break;
< default:
< LogFile->write(EQEMuLog::Error, "Client::ZonePC() received a reguest to perform an unsupported client zone operation.");
< ReadyToZone = false;
< break;
---
> break;
> case Rewind:
> LogFile->write(EQEMuLog::Debug, "%s has requested a /rewind from %f, %f, %f, to %f, %f, %f in %s", GetName(), x_pos, y_pos, z_pos, rewind_x, rewind_y, rewind_z, zone->GetShortName());
> zonesummon_x = x_pos = x;
> zonesummon_y = y_pos = y;
> zonesummon_z = z_pos = z;
> heading = heading;
> break;
> default:
> LogFile->write(EQEMuLog::Error, "Client::ZonePC() received a reguest to perform an unsupported client zone operation.");
> ReadyToZone = false;
> break;
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/zone/mob.cpp C:/eqemu-source-diff/daxum/zone/mob.cpp
102a103
> rewind_timer(30000), //Lieka: Timer used for determining amount of time between actual player position updates for /rewind.
104c105
< bardsong_timer(6000),
---
> bardsong_timer(6000),
124c125,127
<
---
> rewind_x = 0; //Lieka: Stored x_pos for /rewind
> rewind_y = 0; //Lieka: Stored y_pos for /rewind
> rewind_z = 0; //Lieka: Stored z_pos for /rewind
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/zone/client_packet.cpp C:/eqemu-source-diff/daxum/zone/client_packet.cpp
316a317,318
> ConnectedOpcodes[OP_Rewind] = &Client::Handle_OP_Rewind;
>
808c810,838
<
---
>
> //Lieka: Check to see if PPU should trigger an update to the rewind position.
> float rewind_x_diff = 0;
> float rewind_y_diff = 0;
> float rewind_z_diff = 0;
>
> rewind_x_diff = ppu->x_pos - rewind_x;
> rewind_x_diff *= rewind_x_diff;
> rewind_y_diff = ppu->y_pos - rewind_y;
> rewind_y_diff *= rewind_y_diff;
>
> //Lieka: We only need to store updated values if the player has moved.
> //If the player has moved more than units for x or y, then we'll store
> //his pre-PPU x and y for /rewind, in case he gets stuck.
> if ((rewind_x_diff > 750) || (rewind_y_diff > 750)) {
> rewind_x = x_pos;
> rewind_y = y_pos;
> rewind_z = z_pos;
> }
>
> //Lieka: If the PPU was a large jump, such as a cross zone gate or Call of Hero,
> //just update rewind coords to the new ppu coords. This will prevent exploitation.
>
> if ((rewind_x_diff > 5000) || (rewind_y_diff > 5000)) {
> rewind_x = ppu->x_pos;
> rewind_y = ppu->y_pos;
> rewind_z = ppu->z_pos;
> }
>
816,822c846,852
< if(
< ( (heading != ppu->heading) && !((int)heading % 3) ) || // turning
< ( (x_pos != ppu->x_pos) && !((int)x_pos % 6) ) // moving
< )
< {
< CheckIncreaseSkill(SENSE_HEADING, -20);
< }
---
> if(
> ( (heading != ppu->heading) && !((int)heading % 3) ) || // turning
> ( (x_pos != ppu->x_pos) && !((int)x_pos % 6) ) // moving
> )
> {
> CheckIncreaseSkill(SENSE_HEADING, -20);
> }
876a907
> rewind_timer.Start(30000, true);
3156c3187
< }
---
> }
6827a6859,6868
> }
>
> void Client::Handle_OP_Rewind(const EQApplicationPacket *app)
> {
> if ((rewind_timer.GetRemainingTime() > 1 && rewind_timer.Enabled())) {
> Message_StringID(MT_System, 4059); //You must wait a bit longer before using the rewind command again.
> } else {
> CastToClient()->MovePC(zone->GetZoneID(), rewind_x, rewind_y, rewind_z, 0, 2, Rewind);
> rewind_timer.Start(30000, true);
> }
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/zone/client.h C:/eqemu-source-diff/daxum/zone/client.h
151a152
> Rewind, // Lieka: Summon to /rewind location.
153a155
>
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/zone/client_packet.h C:/eqemu-source-diff/daxum/zone/client_packet.h
214a215
> void Handle_OP_Rewind(const EQApplicationPacket *app);
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/zone/mob.h C:/eqemu-source-diff/daxum/zone/mob.h
788a789,792
> float rewind_x; //Lieka: Used for storing /rewind values
> float rewind_y; //Lieka: Used for storing /rewind values
> float rewind_z; //Lieka: Used for storing /rewind values
> Timer rewind_timer; //Lieka: Used for measuring how long a player stays in one spot
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/utils/patch_Titanium.conf C:/eqemu-source-diff/daxum/utils/patch_Titanium.conf
267a268
> OP_Rewind=0x4cfa # Lieka 4/20/08: /rewind command
diff C:/eqemu-source-diff/EQEmu-0.7.0-1106/common/emu_oplist.h C:/eqemu-source-diff/daxum/common/emu_oplist.h
401a402
> N(OP_Rewind),
<3,
Dax