rewind fixes

This commit is contained in:
RandomityGuy 2023-10-02 23:10:28 +05:30
parent f571bd6836
commit 792f1b480a
7 changed files with 208 additions and 77 deletions

View file

@ -616,11 +616,11 @@ class DtsObject extends GameObject {
for (index in [i1, i2, i3]) { for (index in [i1, i2, i3]) {
var vertex = vertices[index]; var vertex = vertices[index];
hs.points.push(new Vector(vertex.x, vertex.y, vertex.z)); hs.addPoint(vertex.x, vertex.y, vertex.z);
hs.transformKeys.push(0); hs.transformKeys.push(0);
var normal = vertexNormals[index]; var normal = vertexNormals[index];
hs.normals.push(new Vector(normal.x, normal.y, normal.z)); hs.addNormal(normal.x, normal.y, normal.z);
} }
hs.indices.push(hs.indices.length); hs.indices.push(hs.indices.length);
@ -667,11 +667,11 @@ class DtsObject extends GameObject {
for (index in [i1, i2, i3]) { for (index in [i1, i2, i3]) {
var vertex = vertices[index]; var vertex = vertices[index];
hs.points.push(new Vector(vertex.x, vertex.y, vertex.z)); hs.addPoint(vertex.x, vertex.y, vertex.z);
hs.transformKeys.push(0); hs.transformKeys.push(0);
var normal = vertexNormals[index]; var normal = vertexNormals[index];
hs.normals.push(new Vector(normal.x, normal.y, normal.z)); hs.addNormal(normal.x, normal.y, normal.z);
} }
hs.indices.push(hs.indices.length); hs.indices.push(hs.indices.length);

View file

@ -28,6 +28,7 @@ interface GameMode {
public function onGemPickup(gem:Gem):Void; public function onGemPickup(gem:Gem):Void;
public function getPreloadFiles():Array<String>; public function getPreloadFiles():Array<String>;
public function constructRewindState():RewindableState;
} }
class GameModeFactory { class GameModeFactory {

View file

@ -1,5 +1,6 @@
package modes; package modes;
import rewind.RewindManager;
import hxd.Rand; import hxd.Rand;
import rewind.RewindableState; import rewind.RewindableState;
import gui.AchievementsGui; import gui.AchievementsGui;
@ -55,14 +56,16 @@ class GemSpawnSphere {
class GemOctreeElem implements IOctreeObject { class GemOctreeElem implements IOctreeObject {
public var boundingBox:Bounds; public var boundingBox:Bounds;
public var spawn:GemSpawnSphere; public var spawn:GemSpawnSphere;
public var spawnIndex:Int;
var priority:Int; var priority:Int;
public function new(vec:Vector, spawn:GemSpawnSphere) { public function new(vec:Vector, spawn:GemSpawnSphere, spawnIndex:Int) {
boundingBox = new Bounds(); boundingBox = new Bounds();
boundingBox.addPoint(vec.add(new Vector(-0.5, -0.5, -0.5)).toPoint()); boundingBox.addPoint(vec.add(new Vector(-0.5, -0.5, -0.5)).toPoint());
boundingBox.addPoint(vec.add(new Vector(0.5, 0.5, 0.5)).toPoint()); boundingBox.addPoint(vec.add(new Vector(0.5, 0.5, 0.5)).toPoint());
this.spawn = spawn; this.spawn = spawn;
this.spawnIndex = spawnIndex;
} }
public function getElementType() { public function getElementType() {
@ -80,7 +83,7 @@ class GemOctreeElem implements IOctreeObject {
@:publicFields @:publicFields
class HuntState implements RewindableState { class HuntState implements RewindableState {
var activeGemSpawnGroup:Array<GemSpawnSphere>; var activeGemSpawnGroup:Array<Int>;
var activeGems:Array<Gem>; var activeGems:Array<Gem>;
var points:Int; var points:Int;
var rngState:Int; var rngState:Int;
@ -102,6 +105,47 @@ class HuntState implements RewindableState {
c.rngState2 = rngState2; c.rngState2 = rngState2;
return c; return c;
} }
public function getSize():Int {
var size = 2;
size += 2 + activeGemSpawnGroup.length * 2;
size += 2 + activeGems.length * 2;
size += 4;
size += 4;
size += 4;
return size;
}
public function serialize(rm:RewindManager, bw:haxe.io.BytesOutput) {
bw.writeUInt16(points);
bw.writeUInt16(activeGemSpawnGroup.length);
for (elem in activeGemSpawnGroup) {
bw.writeUInt16(elem);
}
bw.writeUInt16(activeGems.length);
for (elem in activeGems) {
bw.writeUInt16(rm.allocGO(elem));
}
bw.writeInt32(rngState);
bw.writeInt32(rngState2);
}
public function deserialize(rm:RewindManager, br:haxe.io.BytesInput) {
points = br.readUInt16();
activeGemSpawnGroup = [];
var len = br.readUInt16();
for (i in 0...len) {
activeGemSpawnGroup.push(br.readUInt16());
}
activeGems = [];
var len = br.readUInt16();
for (i in 0...len) {
var uid = br.readUInt16();
activeGems.push(cast rm.getGO(uid));
}
rngState = br.readInt32();
rngState2 = br.readInt32();
}
} }
class HuntMode extends NullMode { class HuntMode extends NullMode {
@ -111,7 +155,7 @@ class HuntMode extends NullMode {
var gemOctree:Octree; var gemOctree:Octree;
var gemGroupRadius:Float; var gemGroupRadius:Float;
var maxGemsPerGroup:Int; var maxGemsPerGroup:Int;
var activeGemSpawnGroup:Array<GemSpawnSphere>; var activeGemSpawnGroup:Array<Int>;
var activeGems:Array<Gem> = []; var activeGems:Array<Gem> = [];
var gemBeams:Array<GemBeam> = []; var gemBeams:Array<GemBeam> = [];
var gemToBeamMap:Map<Gem, GemBeam> = []; var gemToBeamMap:Map<Gem, GemBeam> = [];
@ -191,7 +235,8 @@ class HuntMode extends NullMode {
override function onRespawn() { override function onRespawn() {
if (activeGemSpawnGroup.length != 0) { if (activeGemSpawnGroup.length != 0) {
var gemAvg = new Vector(); var gemAvg = new Vector();
for (g in activeGemSpawnGroup) { for (gi in activeGemSpawnGroup) {
var g = gemSpawnPoints[gi];
gemAvg = gemAvg.add(g.position); gemAvg = gemAvg.add(g.position);
} }
gemAvg.scale(1 / activeGemSpawnGroup.length); gemAvg.scale(1 / activeGemSpawnGroup.length);
@ -258,9 +303,10 @@ class HuntMode extends NullMode {
maxGemsPerGroup = Std.parseInt(level.mission.missionInfo.maxgemspergroup); maxGemsPerGroup = Std.parseInt(level.mission.missionInfo.maxgemspergroup);
gemOctree = new Octree(); gemOctree = new Octree();
for (gemSpawn in gemSpawnPoints) { for (gi in 0...gemSpawnPoints.length) {
var gemSpawn = gemSpawnPoints[gi];
var vec = gemSpawn.position; var vec = gemSpawn.position;
gemOctree.insert(new GemOctreeElem(vec, gemSpawn)); gemOctree.insert(new GemOctreeElem(vec, gemSpawn, gi));
if (gemSpawn.gem != null) { if (gemSpawn.gem != null) {
gemSpawn.gem.setHide(true); gemSpawn.gem.setHide(true);
gemSpawn.gem.pickedUp = true; gemSpawn.gem.pickedUp = true;
@ -269,7 +315,8 @@ class HuntMode extends NullMode {
} }
if (activeGemSpawnGroup != null) { if (activeGemSpawnGroup != null) {
for (gemSpawn in activeGemSpawnGroup) { for (gemSpawnIndex in activeGemSpawnGroup) {
var gemSpawn = gemSpawnPoints[gemSpawnIndex];
if (gemSpawn.gem != null) { if (gemSpawn.gem != null) {
gemSpawn.gem.pickedUp = true; gemSpawn.gem.pickedUp = true;
gemSpawn.gem.setHide(true); gemSpawn.gem.setHide(true);
@ -283,7 +330,8 @@ class HuntMode extends NullMode {
refillGemGroups(); refillGemGroups();
var gemAvg = new Vector(); var gemAvg = new Vector();
for (g in activeGemSpawnGroup) { for (gi in activeGemSpawnGroup) {
var g = gemSpawnPoints[gi];
gemAvg = gemAvg.add(g.position); gemAvg = gemAvg.add(g.position);
} }
gemAvg.scale(1 / activeGemSpawnGroup.length); gemAvg.scale(1 / activeGemSpawnGroup.length);
@ -308,8 +356,9 @@ class HuntMode extends NullMode {
} }
} }
function fillGemGroup(group:Array<GemSpawnSphere>) { function fillGemGroup(group:Array<Int>) {
for (gemSpawn in group) { for (gi in group) {
var gemSpawn = gemSpawnPoints[gi];
if (gemSpawn.gem != null) { if (gemSpawn.gem != null) {
gemSpawn.gem.pickedUp = false; gemSpawn.gem.pickedUp = false;
gemSpawn.gem.setHide(false); gemSpawn.gem.setHide(false);
@ -354,7 +403,8 @@ class HuntMode extends NullMode {
var ok = true; var ok = true;
if (activeGemSpawnGroup != null) { if (activeGemSpawnGroup != null) {
for (gemSpawn in activeGemSpawnGroup) { for (gi in activeGemSpawnGroup) {
var gemSpawn = gemSpawnPoints[gi];
if (gemSpawn.position.distance(groupMainPt) < searchRadius) { if (gemSpawn.position.distance(groupMainPt) < searchRadius) {
ok = false; ok = false;
break; break;
@ -384,7 +434,7 @@ class HuntMode extends NullMode {
var search = gemOctree.radiusSearch(pos, gemGroupRadius); var search = gemOctree.radiusSearch(pos, gemGroupRadius);
for (elem in search) { for (elem in search) {
var gemElem:GemOctreeElem = cast elem; var gemElem:GemOctreeElem = cast elem;
results.push(gemElem.spawn); results.push(gemElem.spawnIndex);
if (results.length >= maxGemsPerGroup) if (results.length >= maxGemsPerGroup)
break; break;
} }
@ -481,4 +531,8 @@ class HuntMode extends NullMode {
rng2.setSeed(s.rngState2); rng2.setSeed(s.rngState2);
} }
} }
override function constructRewindState():RewindableState {
return new HuntState();
};
} }

View file

@ -103,4 +103,8 @@ class NullMode implements GameMode {
} }
public function applyRewindState(state:RewindableState) {} public function applyRewindState(state:RewindableState) {}
public function constructRewindState() {
return null;
}
} }

View file

@ -128,8 +128,13 @@ class RewindFrame {
var bb = new BytesOutput(); var bb = new BytesOutput();
var framesize = 0; var framesize = 0;
framesize += 32; // timeState framesize += 32; // timeState
framesize += 24; // marblePosition framesize += 8; // rewindAcculumulator
framesize += 128; // marbleColliderTransform
framesize += 24; // marblePrevPosition
framesize += 24; // marbleNextPosition
framesize += 8; // marblePhysicsAccumulator
framesize += 32; // marbleOrientation framesize += 32; // marbleOrientation
framesize += 32; // marblePrevOrientation
framesize += 24; // marbleVelocity framesize += 24; // marbleVelocity
framesize += 24; // marbleAngularVelocity framesize += 24; // marbleAngularVelocity
framesize += 2; // marblePowerup framesize += 2; // marblePowerup
@ -138,16 +143,19 @@ class RewindFrame {
framesize += 2 + gemStates.length * 1; // gemStates framesize += 2 + gemStates.length * 1; // gemStates
framesize += 2 + powerupStates.length * 8; // powerupStates framesize += 2 + powerupStates.length * 8; // powerupStates
framesize += 2 + landMineStates.length * 8; // landMineStates framesize += 2 + landMineStates.length * 8; // landMineStates
framesize += 32; // activePowerupStates framesize += 16; // activePowerupStates
framesize += 24; // currentUp framesize += 24; // currentUp
framesize += 24; // lastContactNormal framesize += 24; // lastContactNormal
framesize += 2; // mpStates.length framesize += 2; // mpStates.length
for (s in mpStates) { for (s in mpStates) {
framesize += 8; // s.curState.currentTime framesize += 8; // s.currentTime
framesize += 8; // s.curState.targetTime framesize += 8; // s.targetTime
framesize += 24; // s.curState.velocity framesize += 1; // Null<s.stoppedPosition>
framesize += 1; // s.stopped if (s.stoppedPosition != null)
framesize += 24; // s.stoppedPosition
framesize += 24; // s.prevPosition
framesize += 24; // s.position framesize += 24; // s.position
framesize += 24; // s.velocity
} }
framesize += 2; // trapdoorStates.length framesize += 2; // trapdoorStates.length
for (s in trapdoorStates) { for (s in trapdoorStates) {
@ -161,7 +169,7 @@ class RewindFrame {
framesize += 32; // oobState.timeState framesize += 32; // oobState.timeState
framesize += 1; // Null<checkpointState> framesize += 1; // Null<checkpointState>
if (checkpointState != null) { if (checkpointState != null) {
framesize += 4; // checkpointState.currentCheckpoint framesize += 2; // checkpointState.currentCheckpoint
} }
framesize += 2; // checkpointState.currentCheckpointTrigger framesize += 2; // checkpointState.currentCheckpointTrigger
framesize += 2; // checkpointState.checkpointCollectedGems.length framesize += 2; // checkpointState.checkpointCollectedGems.length
@ -170,23 +178,48 @@ class RewindFrame {
framesize += 1; // checkpointState.checkpointCollectedGems[gem] framesize += 1; // checkpointState.checkpointCollectedGems[gem]
} }
framesize += 2; // checkpointState.checkpointHeldPowerup framesize += 2; // checkpointState.checkpointHeldPowerup
framesize += 1; // Null<checkpointState.checkpointUp>
if (checkpointState.checkpointUp != null)
framesize += 24; // checkpointState.checkpointUp
framesize += 8; // checkpointState.checkpointBlast framesize += 8; // checkpointState.checkpointBlast
framesize += 1; // Null<modeState>
if (modeState != null)
framesize += modeState.getSize();
bb.prepare(framesize); bb.prepare(framesize);
// Now actually write // Now actually write
bb.writeDouble(timeState.currentAttemptTime); bb.writeDouble(timeState.currentAttemptTime);
bb.writeDouble(timeState.timeSinceLoad); bb.writeDouble(timeState.timeSinceLoad);
bb.writeDouble(timeState.gameplayClock); bb.writeDouble(timeState.gameplayClock);
bb.writeDouble(timeState.dt); bb.writeDouble(timeState.dt);
bb.writeDouble(marblePosition.x); bb.writeDouble(rewindAccumulator);
bb.writeDouble(marblePosition.y); bb.writeDouble(marbleColliderTransform._11);
bb.writeDouble(marblePosition.z); bb.writeDouble(marbleColliderTransform._12);
bb.writeDouble(marbleColliderTransform._13);
bb.writeDouble(marbleColliderTransform._14);
bb.writeDouble(marbleColliderTransform._21);
bb.writeDouble(marbleColliderTransform._22);
bb.writeDouble(marbleColliderTransform._23);
bb.writeDouble(marbleColliderTransform._24);
bb.writeDouble(marbleColliderTransform._31);
bb.writeDouble(marbleColliderTransform._32);
bb.writeDouble(marbleColliderTransform._33);
bb.writeDouble(marbleColliderTransform._34);
bb.writeDouble(marbleColliderTransform._41);
bb.writeDouble(marbleColliderTransform._42);
bb.writeDouble(marbleColliderTransform._43);
bb.writeDouble(marbleColliderTransform._44);
bb.writeDouble(marblePrevPosition.x);
bb.writeDouble(marblePrevPosition.y);
bb.writeDouble(marblePrevPosition.z);
bb.writeDouble(marbleNextPosition.x);
bb.writeDouble(marbleNextPosition.y);
bb.writeDouble(marbleNextPosition.z);
bb.writeDouble(marblePhysicsAccmulator);
bb.writeDouble(marbleOrientation.x); bb.writeDouble(marbleOrientation.x);
bb.writeDouble(marbleOrientation.y); bb.writeDouble(marbleOrientation.y);
bb.writeDouble(marbleOrientation.z); bb.writeDouble(marbleOrientation.z);
bb.writeDouble(marbleOrientation.w); bb.writeDouble(marbleOrientation.w);
bb.writeDouble(marblePrevOrientation.x);
bb.writeDouble(marblePrevOrientation.y);
bb.writeDouble(marblePrevOrientation.z);
bb.writeDouble(marblePrevOrientation.w);
bb.writeDouble(marbleVelocity.x); bb.writeDouble(marbleVelocity.x);
bb.writeDouble(marbleVelocity.y); bb.writeDouble(marbleVelocity.y);
bb.writeDouble(marbleVelocity.z); bb.writeDouble(marbleVelocity.z);
@ -210,8 +243,6 @@ class RewindFrame {
} }
bb.writeDouble(activePowerupStates[0]); bb.writeDouble(activePowerupStates[0]);
bb.writeDouble(activePowerupStates[1]); bb.writeDouble(activePowerupStates[1]);
bb.writeDouble(activePowerupStates[2]);
bb.writeDouble(activePowerupStates[3]);
bb.writeDouble(currentUp.x); bb.writeDouble(currentUp.x);
bb.writeDouble(currentUp.y); bb.writeDouble(currentUp.y);
bb.writeDouble(currentUp.z); bb.writeDouble(currentUp.z);
@ -220,15 +251,23 @@ class RewindFrame {
bb.writeDouble(lastContactNormal.z); bb.writeDouble(lastContactNormal.z);
bb.writeInt16(mpStates.length); bb.writeInt16(mpStates.length);
for (s in mpStates) { for (s in mpStates) {
bb.writeDouble(s.curState.currentTime); bb.writeDouble(s.currentTime);
bb.writeDouble(s.curState.targetTime); bb.writeDouble(s.targetTime);
bb.writeDouble(s.curState.velocity.x); bb.writeByte(s.stoppedPosition == null ? 0 : 1);
bb.writeDouble(s.curState.velocity.y); if (s.stoppedPosition != null) {
bb.writeDouble(s.curState.velocity.z); bb.writeDouble(s.stoppedPosition.x);
bb.writeByte(s.stopped ? 1 : 0); bb.writeDouble(s.stoppedPosition.y);
bb.writeDouble(s.stoppedPosition.z);
}
bb.writeDouble(s.prevPosition.x);
bb.writeDouble(s.prevPosition.y);
bb.writeDouble(s.prevPosition.z);
bb.writeDouble(s.position.x); bb.writeDouble(s.position.x);
bb.writeDouble(s.position.y); bb.writeDouble(s.position.y);
bb.writeDouble(s.position.z); bb.writeDouble(s.position.z);
bb.writeDouble(s.velocity.x);
bb.writeDouble(s.velocity.y);
bb.writeDouble(s.velocity.z);
} }
bb.writeInt16(trapdoorStates.length); bb.writeInt16(trapdoorStates.length);
for (s in trapdoorStates) { for (s in trapdoorStates) {
@ -246,8 +285,7 @@ class RewindFrame {
} }
bb.writeByte(checkpointState.currentCheckpoint == null ? 0 : 1); bb.writeByte(checkpointState.currentCheckpoint == null ? 0 : 1);
if (checkpointState.currentCheckpoint != null) { if (checkpointState.currentCheckpoint != null) {
bb.writeInt16(rm.allocGO(checkpointState.currentCheckpoint.obj)); bb.writeInt16(rm.allocGO(checkpointState.currentCheckpoint));
bb.writeInt16(rm.allocME(checkpointState.currentCheckpoint.elem));
} }
bb.writeInt16(rm.allocGO(checkpointState.currentCheckpointTrigger)); bb.writeInt16(rm.allocGO(checkpointState.currentCheckpointTrigger));
var chkgemcount = 0; var chkgemcount = 0;
@ -260,18 +298,18 @@ class RewindFrame {
bb.writeByte(checkpointState.checkpointCollectedGems[gem] ? 1 : 0); bb.writeByte(checkpointState.checkpointCollectedGems[gem] ? 1 : 0);
} }
bb.writeInt16(rm.allocGO(checkpointState.checkpointHeldPowerup)); bb.writeInt16(rm.allocGO(checkpointState.checkpointHeldPowerup));
bb.writeByte(checkpointState.checkpointUp == null ? 0 : 1);
if (checkpointState.checkpointUp != null) {
bb.writeDouble(checkpointState.checkpointUp.x);
bb.writeDouble(checkpointState.checkpointUp.y);
bb.writeDouble(checkpointState.checkpointUp.z);
}
bb.writeDouble(checkpointState.checkpointBlast); bb.writeDouble(checkpointState.checkpointBlast);
bb.writeByte(modeState == null ? 0 : 1);
if (modeState != null)
modeState.serialize(rm, bb);
return bb.getBytes(); return bb.getBytes();
} }
public inline function deserialize(rm:RewindManager, br:haxe.io.BytesInput) { public inline function deserialize(rm:RewindManager, br:haxe.io.BytesInput) {
marblePosition = new Vector(); marbleColliderTransform = new Matrix();
marblePrevPosition = new Vector();
marbleNextPosition = new Vector();
marblePrevOrientation = new Quat();
marbleOrientation = new Quat(); marbleOrientation = new Quat();
marbleVelocity = new Vector(); marbleVelocity = new Vector();
marbleAngularVelocity = new Vector(); marbleAngularVelocity = new Vector();
@ -282,13 +320,38 @@ class RewindFrame {
timeState.timeSinceLoad = br.readDouble(); timeState.timeSinceLoad = br.readDouble();
timeState.gameplayClock = br.readDouble(); timeState.gameplayClock = br.readDouble();
timeState.dt = br.readDouble(); timeState.dt = br.readDouble();
marblePosition.x = br.readDouble(); rewindAccumulator = br.readDouble();
marblePosition.y = br.readDouble(); marbleColliderTransform._11 = br.readDouble();
marblePosition.z = br.readDouble(); marbleColliderTransform._12 = br.readDouble();
marbleColliderTransform._13 = br.readDouble();
marbleColliderTransform._14 = br.readDouble();
marbleColliderTransform._21 = br.readDouble();
marbleColliderTransform._22 = br.readDouble();
marbleColliderTransform._23 = br.readDouble();
marbleColliderTransform._24 = br.readDouble();
marbleColliderTransform._31 = br.readDouble();
marbleColliderTransform._32 = br.readDouble();
marbleColliderTransform._33 = br.readDouble();
marbleColliderTransform._34 = br.readDouble();
marbleColliderTransform._41 = br.readDouble();
marbleColliderTransform._42 = br.readDouble();
marbleColliderTransform._43 = br.readDouble();
marbleColliderTransform._44 = br.readDouble();
marblePrevPosition.x = br.readDouble();
marblePrevPosition.y = br.readDouble();
marblePrevPosition.z = br.readDouble();
marbleNextPosition.x = br.readDouble();
marbleNextPosition.y = br.readDouble();
marbleNextPosition.z = br.readDouble();
marblePhysicsAccmulator = br.readDouble();
marbleOrientation.x = br.readDouble(); marbleOrientation.x = br.readDouble();
marbleOrientation.y = br.readDouble(); marbleOrientation.y = br.readDouble();
marbleOrientation.z = br.readDouble(); marbleOrientation.z = br.readDouble();
marbleOrientation.w = br.readDouble(); marbleOrientation.w = br.readDouble();
marblePrevOrientation.x = br.readDouble();
marblePrevOrientation.y = br.readDouble();
marblePrevOrientation.z = br.readDouble();
marblePrevOrientation.w = br.readDouble();
marbleVelocity.x = br.readDouble(); marbleVelocity.x = br.readDouble();
marbleVelocity.y = br.readDouble(); marbleVelocity.y = br.readDouble();
marbleVelocity.z = br.readDouble(); marbleVelocity.z = br.readDouble();
@ -316,8 +379,6 @@ class RewindFrame {
activePowerupStates = []; activePowerupStates = [];
activePowerupStates.push(br.readDouble()); activePowerupStates.push(br.readDouble());
activePowerupStates.push(br.readDouble()); activePowerupStates.push(br.readDouble());
activePowerupStates.push(br.readDouble());
activePowerupStates.push(br.readDouble());
currentUp.x = br.readDouble(); currentUp.x = br.readDouble();
currentUp.y = br.readDouble(); currentUp.y = br.readDouble();
currentUp.z = br.readDouble(); currentUp.z = br.readDouble();
@ -327,24 +388,29 @@ class RewindFrame {
mpStates = []; mpStates = [];
var mpStates_len = br.readInt16(); var mpStates_len = br.readInt16();
for (i in 0...mpStates_len) { for (i in 0...mpStates_len) {
var mpStates_item = { var mpStates_item = new RewindMPState();
curState: { mpStates_item.currentTime = br.readDouble();
currentTime: 0.0, mpStates_item.targetTime = br.readDouble();
targetTime: 0.0, mpStates_item.stoppedPosition = new Vector();
velocity: new Vector(), mpStates_item.prevPosition = new Vector();
}, mpStates_item.position = new Vector();
stopped: false, mpStates_item.velocity = new Vector();
position: new Vector() if (br.readByte() != 0) {
}; mpStates_item.stoppedPosition.x = br.readDouble();
mpStates_item.curState.currentTime = br.readDouble(); mpStates_item.stoppedPosition.y = br.readDouble();
mpStates_item.curState.targetTime = br.readDouble(); mpStates_item.stoppedPosition.z = br.readDouble();
mpStates_item.curState.velocity.x = br.readDouble(); } else {
mpStates_item.curState.velocity.y = br.readDouble(); mpStates_item.stoppedPosition = null;
mpStates_item.curState.velocity.z = br.readDouble(); }
mpStates_item.stopped = br.readByte() != 0; mpStates_item.prevPosition.x = br.readDouble();
mpStates_item.prevPosition.y = br.readDouble();
mpStates_item.prevPosition.z = br.readDouble();
mpStates_item.position.x = br.readDouble(); mpStates_item.position.x = br.readDouble();
mpStates_item.position.y = br.readDouble(); mpStates_item.position.y = br.readDouble();
mpStates_item.position.z = br.readDouble(); mpStates_item.position.z = br.readDouble();
mpStates_item.velocity.x = br.readDouble();
mpStates_item.velocity.y = br.readDouble();
mpStates_item.velocity.z = br.readDouble();
mpStates.push(mpStates_item); mpStates.push(mpStates_item);
} }
trapdoorStates = []; trapdoorStates = [];
@ -378,13 +444,11 @@ class RewindFrame {
currentCheckpointTrigger: null, currentCheckpointTrigger: null,
checkpointCollectedGems: new Map<Gem, Bool>(), checkpointCollectedGems: new Map<Gem, Bool>(),
checkpointHeldPowerup: null, checkpointHeldPowerup: null,
checkpointUp: null,
checkpointBlast: 0.0, checkpointBlast: 0.0,
}; };
if (hasCheckpoint) { if (hasCheckpoint) {
var co = rm.getGO(br.readInt16()); var co = rm.getGO(br.readInt16());
var ce = rm.getME(br.readInt16()); checkpointState.currentCheckpoint = cast co;
checkpointState.currentCheckpoint = {obj: cast co, elem: ce};
} }
checkpointState.currentCheckpointTrigger = cast rm.getGO(br.readInt16()); checkpointState.currentCheckpointTrigger = cast rm.getGO(br.readInt16());
var checkpointState_checkpointCollectedGems_len = br.readInt16(); var checkpointState_checkpointCollectedGems_len = br.readInt16();
@ -394,13 +458,11 @@ class RewindFrame {
checkpointState.checkpointCollectedGems.set(cast gem, c); checkpointState.checkpointCollectedGems.set(cast gem, c);
} }
checkpointState.checkpointHeldPowerup = cast rm.getGO(br.readInt16()); checkpointState.checkpointHeldPowerup = cast rm.getGO(br.readInt16());
var checkpointState_checkpointUp_has = br.readByte() != 0;
if (checkpointState_checkpointUp_has) {
checkpointState.checkpointUp = new Vector();
checkpointState.checkpointUp.x = br.readDouble();
checkpointState.checkpointUp.y = br.readDouble();
checkpointState.checkpointUp.z = br.readDouble();
}
checkpointState.checkpointBlast = br.readDouble(); checkpointState.checkpointBlast = br.readDouble();
var hasModeState = br.readByte() != 0;
if (hasModeState) {
modeState = rm.level.gameMode.constructRewindState();
modeState.deserialize(rm, br);
}
} }
} }

View file

@ -20,7 +20,9 @@ class RewindManager {
var allocObjs:Array<GameObject> = []; var allocObjs:Array<GameObject> = [];
var allocMeMap:Map<MissionElementBase, Int> = []; var allocMeMap:Map<MissionElementBase, Int> = [];
var allocMes:Array<MissionElementBase> = []; var allocMes:Array<MissionElementBase> = [];
var level:MarbleWorld;
public var level:MarbleWorld;
var allocId = 0; var allocId = 0;
var allocMeId = 0; var allocMeId = 0;
@ -39,6 +41,7 @@ class RewindManager {
while (timeAccumulator >= saveResolution) { while (timeAccumulator >= saveResolution) {
timeAccumulator -= saveResolution; timeAccumulator -= saveResolution;
var rf = new RewindFrame(); var rf = new RewindFrame();
rf.rewindAccumulator = timeAccumulator;
rf.timeState = level.timeState.clone(); rf.timeState = level.timeState.clone();
rf.marbleColliderTransform = level.marble.collider.transform.clone(); rf.marbleColliderTransform = level.marble.collider.transform.clone();
rf.marblePrevPosition = @:privateAccess level.marble.oldPos.clone(); rf.marblePrevPosition = @:privateAccess level.marble.oldPos.clone();
@ -275,6 +278,8 @@ class RewindManager {
} }
public function getGO(id:Int):GameObject { public function getGO(id:Int):GameObject {
if (id == -1)
return null;
return allocObjs[id]; return allocObjs[id];
} }
@ -290,6 +295,8 @@ class RewindManager {
} }
public function getME(id:Int):MissionElementBase { public function getME(id:Int):MissionElementBase {
if (id == -1)
return null;
return allocMes[id]; return allocMes[id];
} }

View file

@ -5,4 +5,7 @@ import src.MarbleWorld;
interface RewindableState { interface RewindableState {
function apply(level:MarbleWorld):Void; function apply(level:MarbleWorld):Void;
function clone():RewindableState; function clone():RewindableState;
function getSize():Int;
function serialize(rm:RewindManager, bw:haxe.io.BytesOutput):Void;
function deserialize(rm:RewindManager, br:haxe.io.BytesInput):Void;
} }