mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2026-02-19 12:41:04 +00:00
make hunt network again, and fix marble radius for MP
This commit is contained in:
parent
d20d3a1e90
commit
141a3f892b
7 changed files with 303 additions and 91 deletions
|
|
@ -163,6 +163,9 @@ class Console {
|
|||
} else {
|
||||
error("Expected one argument, got " + (cmdSplit.length - 1));
|
||||
}
|
||||
} else if (cmdType == 'rollback') {
|
||||
var t = Std.parseFloat(cmdSplit[1]);
|
||||
MarbleGame.instance.world.rollback(t);
|
||||
} else {
|
||||
error("Unknown command");
|
||||
}
|
||||
|
|
|
|||
158
src/Marble.hx
158
src/Marble.hx
|
|
@ -482,6 +482,11 @@ class Marble extends GameObject {
|
|||
} else
|
||||
this._radius = avgRadius;
|
||||
|
||||
if (Net.isMP) {
|
||||
this._radius = 0.2; // For the sake of physics
|
||||
marbleDts.scale(0.2 / avgRadius);
|
||||
}
|
||||
|
||||
this._prevRadius = this._radius;
|
||||
|
||||
if (isUltra) {
|
||||
|
|
@ -556,8 +561,8 @@ class Marble extends GameObject {
|
|||
|
||||
public function getMarbleAxis() {
|
||||
var motiondir = new Vector(0, -1, 0);
|
||||
// if (level.isReplayingMovement)
|
||||
// return level.currentInputMoves[1].marbleAxes;
|
||||
if (level.isReplayingMovement)
|
||||
return level.currentInputMoves[1].marbleAxes;
|
||||
if (this.controllable && !this.isNetUpdate) {
|
||||
motiondir.transform(Matrix.R(0, 0, camera.CameraYaw));
|
||||
motiondir.transform(level.newOrientationQuat.toMatrix());
|
||||
|
|
@ -663,6 +668,8 @@ class Marble extends GameObject {
|
|||
var R = currentGravityDir.multiply(-this._radius);
|
||||
var rollVelocity = this.omega.cross(R);
|
||||
var axes = this.getMarbleAxis();
|
||||
// if (!level.isReplayingMovement)
|
||||
// level.inputRecorder.recordAxis(axes);
|
||||
var sideDir = axes[0];
|
||||
var motionDir = axes[1];
|
||||
var upDir = axes[2];
|
||||
|
|
@ -811,37 +818,37 @@ class Marble extends GameObject {
|
|||
}
|
||||
}
|
||||
} while (!done && itersIn < 1e4); // Maximum limit pls
|
||||
// if (this.velocity.lengthSq() < 625) {
|
||||
var gotOne = false;
|
||||
var dir = new Vector(0, 0, 0);
|
||||
for (j in 0...contacts.length) {
|
||||
var dir2 = dir.add(contacts[j].normal);
|
||||
if (dir2.lengthSq() < 0.01) {
|
||||
dir2.load(dir2.add(contacts[j].normal));
|
||||
}
|
||||
dir = dir2;
|
||||
dir.normalize();
|
||||
gotOne = true;
|
||||
}
|
||||
if (gotOne) {
|
||||
dir.normalize();
|
||||
var soFar = 0.0;
|
||||
for (k in 0...contacts.length) {
|
||||
var dist = this._radius - contacts[k].contactDistance;
|
||||
var timeToSeparate = 0.1;
|
||||
var vel = this.velocity.sub(contacts[k].velocity);
|
||||
var outVel = vel.add(dir.multiply(soFar)).dot(contacts[k].normal);
|
||||
if (dist > timeToSeparate * outVel) {
|
||||
soFar += (dist - outVel * timeToSeparate) / timeToSeparate / contacts[k].normal.dot(dir);
|
||||
if (this.velocity.lengthSq() < 625) {
|
||||
var gotOne = false;
|
||||
var dir = new Vector(0, 0, 0);
|
||||
for (j in 0...contacts.length) {
|
||||
var dir2 = dir.add(contacts[j].normal);
|
||||
if (dir2.lengthSq() < 0.01) {
|
||||
dir2.load(dir2.add(contacts[j].normal));
|
||||
}
|
||||
dir = dir2;
|
||||
dir.normalize();
|
||||
gotOne = true;
|
||||
}
|
||||
if (gotOne) {
|
||||
dir.normalize();
|
||||
var soFar = 0.0;
|
||||
for (k in 0...contacts.length) {
|
||||
var dist = this._radius - contacts[k].contactDistance;
|
||||
var timeToSeparate = 0.1;
|
||||
var vel = this.velocity.sub(contacts[k].velocity);
|
||||
var outVel = vel.add(dir.multiply(soFar)).dot(contacts[k].normal);
|
||||
if (dist > timeToSeparate * outVel) {
|
||||
soFar += (dist - outVel * timeToSeparate) / timeToSeparate / contacts[k].normal.dot(dir);
|
||||
}
|
||||
}
|
||||
if (soFar < -25)
|
||||
soFar = -25;
|
||||
if (soFar > 25)
|
||||
soFar = 25;
|
||||
this.velocity.load(this.velocity.add(dir.multiply(soFar)));
|
||||
}
|
||||
if (soFar < -25)
|
||||
soFar = -25;
|
||||
if (soFar > 25)
|
||||
soFar = 25;
|
||||
this.velocity.load(this.velocity.add(dir.multiply(soFar)));
|
||||
}
|
||||
// }
|
||||
|
||||
return stoppedPaths;
|
||||
}
|
||||
|
|
@ -1228,6 +1235,7 @@ class Marble extends GameObject {
|
|||
finalT = collisionTime;
|
||||
currentFinalPos = position.add(relVel.multiply(finalT));
|
||||
found = true;
|
||||
lastContactPos = currentFinalPos.clone();
|
||||
// iterationFound = true;
|
||||
i += 3;
|
||||
// Debug.drawSphere(currentFinalPos, radius);
|
||||
|
|
@ -1427,6 +1435,8 @@ class Marble extends GameObject {
|
|||
}
|
||||
|
||||
function nudgeToContacts(position:Vector, radius:Float, foundContacts:Array<MarbleTestMoveFoundContact>, foundMarbles:Array<SphereCollisionEntity>) {
|
||||
if (Net.isMP)
|
||||
return position;
|
||||
var it = 0;
|
||||
var concernedContacts = foundContacts; // PathedInteriors have their own nudge logic
|
||||
var prevResolved = 0;
|
||||
|
|
@ -1717,36 +1727,36 @@ class Marble extends GameObject {
|
|||
|
||||
this.updateRollSound(timeState, contactTime / timeState.dt, this._slipAmount);
|
||||
|
||||
// if (this.megaMarbleUseTick > 0) {
|
||||
// if (Net.isHost) {
|
||||
// if ((timeState.ticks - this.megaMarbleUseTick) <= 312 && this.megaMarbleUseTick > 0) {
|
||||
// this._radius = 0.675;
|
||||
// this.collider.radius = 0.675;
|
||||
// } else if ((timeState.ticks - this.megaMarbleUseTick) > 312) {
|
||||
// this.collider.radius = this._radius = 0.3;
|
||||
// if (!this.isNetUpdate && this.controllable)
|
||||
// AudioManager.playSound(ResourceLoader.getResource("data/sound/MegaShrink.wav", ResourceLoader.getAudio, this.soundResources), null,
|
||||
// false);
|
||||
// this.megaMarbleUseTick = 0;
|
||||
// this.netFlags |= MarbleNetFlags.DoMega;
|
||||
// }
|
||||
// }
|
||||
// if (Net.isClient) {
|
||||
// if (this.serverTicks - this.megaMarbleUseTick <= 312 && this.megaMarbleUseTick > 0) {
|
||||
// this._radius = 0.675;
|
||||
// this.collider.radius = 0.675;
|
||||
// } else {
|
||||
// this.collider.radius = this._radius = 0.3;
|
||||
// if (!this.isNetUpdate && this.controllable)
|
||||
// AudioManager.playSound(ResourceLoader.getResource("data/sound/MegaShrink.wav", ResourceLoader.getAudio, this.soundResources), null,
|
||||
// false);
|
||||
// this.megaMarbleUseTick = 0;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (Net.isClient && this.megaMarbleUseTick == 0) {
|
||||
// this.collider.radius = this._radius = 0.3;
|
||||
// }
|
||||
if (this.megaMarbleUseTick > 0) {
|
||||
if (Net.isHost) {
|
||||
if ((timeState.ticks - this.megaMarbleUseTick) <= 312 && this.megaMarbleUseTick > 0) {
|
||||
this._radius = 0.675;
|
||||
this.collider.radius = 0.675;
|
||||
} else if ((timeState.ticks - this.megaMarbleUseTick) > 312) {
|
||||
this.collider.radius = this._radius = 0.2;
|
||||
if (!this.isNetUpdate && this.controllable)
|
||||
AudioManager.playSound(ResourceLoader.getResource("data/sound/MegaShrink.wav", ResourceLoader.getAudio, this.soundResources), null,
|
||||
false);
|
||||
this.megaMarbleUseTick = 0;
|
||||
this.netFlags |= MarbleNetFlags.DoMega;
|
||||
}
|
||||
}
|
||||
if (Net.isClient) {
|
||||
if (this.serverTicks - this.megaMarbleUseTick <= 312 && this.megaMarbleUseTick > 0) {
|
||||
this._radius = 0.675;
|
||||
this.collider.radius = 0.675;
|
||||
} else {
|
||||
this.collider.radius = this._radius = 0.2;
|
||||
if (!this.isNetUpdate && this.controllable)
|
||||
AudioManager.playSound(ResourceLoader.getResource("data/sound/MegaShrink.wav", ResourceLoader.getAudio, this.soundResources), null,
|
||||
false);
|
||||
this.megaMarbleUseTick = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Net.isClient && this.megaMarbleUseTick == 0) {
|
||||
this.collider.radius = this._radius = 0.2;
|
||||
}
|
||||
|
||||
if (Net.isMP) {
|
||||
if (m.jump && this.outOfBounds) {
|
||||
|
|
@ -2035,6 +2045,8 @@ class Marble extends GameObject {
|
|||
if (this.controllable && !this.level.isWatching) {
|
||||
move = recordMove();
|
||||
}
|
||||
if (level.isReplayingMovement)
|
||||
move = level.currentInputMoves[1].move;
|
||||
|
||||
if (this.level.isWatching) {
|
||||
if (this.level.replay.currentPlaybackFrame.marbleStateFlags.has(Jumped))
|
||||
|
|
@ -2056,6 +2068,32 @@ class Marble extends GameObject {
|
|||
playedSounds = [];
|
||||
advancePhysics(timeState, move, collisionWorld, pathedInteriors);
|
||||
|
||||
// physicsAccumulator += timeState.dt;
|
||||
|
||||
// while (physicsAccumulator > 0.032) {
|
||||
// var adt = timeState.clone();
|
||||
// adt.dt = 0.032;
|
||||
// advancePhysics(adt, move, collisionWorld, pathedInteriors);
|
||||
// physicsAccumulator -= 0.032;
|
||||
// }
|
||||
// if (oldPos != null && newPos != null) {
|
||||
// var deltaT = physicsAccumulator / 0.032;
|
||||
// var renderPos = Util.lerpThreeVectors(this.oldPos, this.newPos, deltaT);
|
||||
// this.setPosition(renderPos.x, renderPos.y, renderPos.z);
|
||||
|
||||
// var rot = this.getRotationQuat();
|
||||
// var quat = new Quat();
|
||||
// quat.initRotation(omega.x * timeState.dt, omega.y * timeState.dt, omega.z * timeState.dt);
|
||||
// quat.multiply(quat, rot);
|
||||
// this.setRotationQuat(quat);
|
||||
|
||||
// var adt = timeState.clone();
|
||||
// adt.dt = physicsAccumulator;
|
||||
// for (pi in pathedInteriors) {
|
||||
// pi.update(adt);
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!this.level.isWatching) {
|
||||
if (this.level.isRecording) {
|
||||
this.level.replay.recordMarbleState(this.getAbsPos().getPosition(), this.velocity, this.getRotationQuat(), this.omega);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package src;
|
||||
|
||||
import rewind.InputRecorder;
|
||||
import net.NetPacket.ScoreboardPacket;
|
||||
import net.NetPacket.PowerupPickupPacket;
|
||||
import net.Move;
|
||||
|
|
@ -209,6 +210,10 @@ class MarbleWorld extends Scheduler {
|
|||
public var rewindManager:RewindManager;
|
||||
public var rewinding:Bool = false;
|
||||
|
||||
public var inputRecorder:InputRecorder;
|
||||
public var isReplayingMovement:Bool = false;
|
||||
public var currentInputMoves:Array<InputRecorderFrame>;
|
||||
|
||||
// Multiplayer
|
||||
public var isMultiplayer:Bool;
|
||||
|
||||
|
|
@ -257,6 +262,7 @@ class MarbleWorld extends Scheduler {
|
|||
this.replay = new Replay(mission.path, mission.isClaMission ? mission.id : 0);
|
||||
this.isRecording = record;
|
||||
this.rewindManager = new RewindManager(cast this);
|
||||
this.inputRecorder = new InputRecorder(cast this);
|
||||
this.isMultiplayer = multiplayer;
|
||||
if (this.isMultiplayer) {
|
||||
isRecording = false;
|
||||
|
|
@ -761,7 +767,7 @@ class MarbleWorld extends Scheduler {
|
|||
if (isMultiplayer) {
|
||||
marble.megaMarbleUseTick = 0;
|
||||
marble.helicopterUseTick = 0;
|
||||
marble.collider.radius = marble._radius = 0.3;
|
||||
// marble.collider.radius = marble._radius = 0.3;
|
||||
@:privateAccess marble.netFlags |= MarbleNetFlags.DoHelicopter | MarbleNetFlags.DoMega | MarbleNetFlags.GravityChange;
|
||||
} else {
|
||||
@:privateAccess marble.helicopterEnableTime = -1e8;
|
||||
|
|
@ -1496,11 +1502,44 @@ class MarbleWorld extends Scheduler {
|
|||
}
|
||||
}
|
||||
|
||||
public function rollback(t:Float) {
|
||||
var newT = timeState.currentAttemptTime - t;
|
||||
var rewindFrame = rewindManager.getNextRewindFrame(timeState.currentAttemptTime - t);
|
||||
rewindManager.applyFrame(rewindFrame);
|
||||
this.isReplayingMovement = true;
|
||||
this.currentInputMoves = this.inputRecorder.getMovesFrom(timeState.currentAttemptTime);
|
||||
}
|
||||
|
||||
public function advanceWorld(dt:Float) {
|
||||
ProfilerUI.measure("updateTimer");
|
||||
this.updateTimer(dt);
|
||||
this.tickSchedule(timeState.currentAttemptTime);
|
||||
|
||||
this.updateGameState();
|
||||
ProfilerUI.measure("updateDTS");
|
||||
for (obj in dtsObjects) {
|
||||
obj.update(timeState);
|
||||
}
|
||||
for (obj in triggers) {
|
||||
obj.update(timeState);
|
||||
}
|
||||
|
||||
ProfilerUI.measure("updateMarbles");
|
||||
marble.update(timeState, collisionWorld, this.pathedInteriors);
|
||||
for (client => marble in clientMarbles) {
|
||||
marble.update(timeState, collisionWorld, this.pathedInteriors);
|
||||
}
|
||||
}
|
||||
|
||||
public function update(dt:Float) {
|
||||
if (!_ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Key.isPressed(Key.T)) {
|
||||
rollback(0.4);
|
||||
}
|
||||
|
||||
var realDt = dt;
|
||||
|
||||
if ((Key.isDown(Settings.controlsSettings.rewind)
|
||||
|
|
@ -1558,6 +1597,31 @@ class MarbleWorld extends Scheduler {
|
|||
if (dt < 0)
|
||||
return;
|
||||
|
||||
if (this.isReplayingMovement) {
|
||||
trace('Rollback start');
|
||||
while (this.currentInputMoves.length > 1) {
|
||||
while (this.currentInputMoves[1].time <= timeState.currentAttemptTime) {
|
||||
this.currentInputMoves = this.currentInputMoves.slice(1);
|
||||
if (this.currentInputMoves.length == 1)
|
||||
break;
|
||||
}
|
||||
if (this.currentInputMoves.length > 1) {
|
||||
dt = this.currentInputMoves[1].time - this.currentInputMoves[0].time;
|
||||
}
|
||||
|
||||
if (this.isReplayingMovement) {
|
||||
if (this.timeState.currentAttemptTime != this.currentInputMoves[0].time)
|
||||
trace("fucked");
|
||||
}
|
||||
|
||||
if (this.currentInputMoves.length > 1) {
|
||||
advanceWorld(dt);
|
||||
trace('Position: ${@:privateAccess marble.newPos.sub(currentInputMoves[1].pos).length()}. Vel: ${marble.velocity.sub(currentInputMoves[1].velocity).length()}');
|
||||
}
|
||||
}
|
||||
this.isReplayingMovement = false;
|
||||
}
|
||||
|
||||
ProfilerUI.measure("updateTimer");
|
||||
this.updateTimer(dt);
|
||||
|
||||
|
|
@ -1615,6 +1679,11 @@ class MarbleWorld extends Scheduler {
|
|||
for (obj in triggers) {
|
||||
obj.update(timeState);
|
||||
}
|
||||
|
||||
// if (!isReplayingMovement) {
|
||||
// inputRecorder.recordInput(timeState.currentAttemptTime);
|
||||
// }
|
||||
|
||||
ProfilerUI.measure("updateMarbles");
|
||||
if (this.isMultiplayer) {
|
||||
tickAccumulator += timeState.dt;
|
||||
|
|
@ -1726,6 +1795,10 @@ class MarbleWorld extends Scheduler {
|
|||
if (!this.rewinding && Settings.optionsSettings.rewindEnabled && !this.isMultiplayer)
|
||||
this.rewindManager.recordFrame();
|
||||
|
||||
// if (!this.isReplayingMovement) {
|
||||
// inputRecorder.recordMarble();
|
||||
// }
|
||||
|
||||
_instancesNeedsUpdate = true;
|
||||
|
||||
this.updateTexts();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
package modes;
|
||||
|
||||
import net.BitStream.OutputBitStream;
|
||||
import net.NetPacket.GemPickupPacket;
|
||||
import net.NetPacket.GemSpawnPacket;
|
||||
import octree.IOctreeObject;
|
||||
import octree.IOctreeObject.RayIntersectionData;
|
||||
import h3d.col.Bounds;
|
||||
|
|
@ -17,6 +20,7 @@ import src.Mission;
|
|||
import src.Marble;
|
||||
import src.AudioManager;
|
||||
import src.ResourceLoader;
|
||||
import net.Net;
|
||||
|
||||
@:structInit
|
||||
@:publicFields
|
||||
|
|
@ -142,10 +146,7 @@ class HuntMode extends NullMode {
|
|||
return null;
|
||||
}
|
||||
|
||||
function setupGems() {
|
||||
hideExisting();
|
||||
this.activeGems = [];
|
||||
this.activeGemSpawnGroup = [];
|
||||
function prepareGems() {
|
||||
if (this.gemSpawnPoints == null) {
|
||||
this.gemOctree = new Octree();
|
||||
this.gemSpawnPoints = [];
|
||||
|
|
@ -158,6 +159,13 @@ class HuntMode extends NullMode {
|
|||
gem.setHide(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setupGems() {
|
||||
hideExisting();
|
||||
this.activeGems = [];
|
||||
this.activeGemSpawnGroup = [];
|
||||
prepareGems();
|
||||
spawnHuntGems();
|
||||
}
|
||||
|
||||
|
|
@ -227,6 +235,15 @@ class HuntMode extends NullMode {
|
|||
}
|
||||
activeGemSpawnGroup = spawnSet;
|
||||
|
||||
if (level.isMultiplayer && Net.isHost) {
|
||||
var bs = new OutputBitStream();
|
||||
bs.writeByte(GemSpawn);
|
||||
var packet = new GemSpawnPacket();
|
||||
packet.gemIds = spawnSet;
|
||||
packet.serialize(bs);
|
||||
Net.sendPacketToIngame(bs);
|
||||
}
|
||||
|
||||
lastSpawn = furthest;
|
||||
}
|
||||
|
||||
|
|
@ -309,21 +326,25 @@ class HuntMode extends NullMode {
|
|||
points = 0;
|
||||
}
|
||||
|
||||
override function onClientRestart() {
|
||||
prepareGems();
|
||||
}
|
||||
|
||||
override function onGemPickup(marble:Marble, gem:Gem) {
|
||||
// if ((@:privateAccess !marble.isNetUpdate && Net.isHost) || !Net.isMP) {
|
||||
if (marble == level.marble)
|
||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/gotgem.wav', ResourceLoader.getAudio, @:privateAccess this.level.soundResources));
|
||||
else
|
||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/opponent_gem_collect.wav', ResourceLoader.getAudio,
|
||||
@:privateAccess this.level.soundResources));
|
||||
// }
|
||||
if ((@:privateAccess !marble.isNetUpdate && Net.isHost) || !Net.isMP) {
|
||||
if (marble == level.marble)
|
||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/gotgem.wav', ResourceLoader.getAudio, @:privateAccess this.level.soundResources));
|
||||
else
|
||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/opponentdiamond.wav', ResourceLoader.getAudio,
|
||||
@:privateAccess this.level.soundResources));
|
||||
}
|
||||
activeGems.remove(gem);
|
||||
var beam = gemToBeamMap.get(gem);
|
||||
beam.setHide(true);
|
||||
|
||||
// if (!this.level.isMultiplayer || Net.isHost) {
|
||||
spawnHuntGems();
|
||||
// }
|
||||
if (!this.level.isMultiplayer || Net.isHost) {
|
||||
spawnHuntGems();
|
||||
}
|
||||
|
||||
var incr = 0;
|
||||
switch (gem.gemColor) {
|
||||
|
|
@ -352,24 +373,24 @@ class HuntMode extends NullMode {
|
|||
}
|
||||
}
|
||||
|
||||
// if (this.level.isMultiplayer && Net.isHost) {
|
||||
// var packet = new GemPickupPacket();
|
||||
// packet.clientId = @:privateAccess marble.connection == null ? 0 : @:privateAccess marble.connection.id;
|
||||
// packet.gemId = gem.netIndex;
|
||||
// packet.serverTicks = level.timeState.ticks;
|
||||
// packet.scoreIncr = incr;
|
||||
// var os = new OutputBitStream();
|
||||
// os.writeByte(GemPickup);
|
||||
// packet.serialize(os);
|
||||
// Net.sendPacketToIngame(os);
|
||||
if (this.level.isMultiplayer && Net.isHost) {
|
||||
var packet = new GemPickupPacket();
|
||||
packet.clientId = @:privateAccess marble.connection == null ? 0 : @:privateAccess marble.connection.id;
|
||||
packet.gemId = gem.netIndex;
|
||||
packet.serverTicks = level.timeState.ticks;
|
||||
packet.scoreIncr = incr;
|
||||
var os = new OutputBitStream();
|
||||
os.writeByte(GemPickup);
|
||||
packet.serialize(os);
|
||||
Net.sendPacketToIngame(os);
|
||||
|
||||
// Settings.playStatistics.totalMPScore += incr;
|
||||
// Settings.playStatistics.totalMPScore += incr;
|
||||
|
||||
// @:privateAccess level.playGui.incrementPlayerScore(packet.clientId, packet.scoreIncr);
|
||||
// }
|
||||
// if (this.level.isMultiplayer && Net.isClient) {
|
||||
// gem.pickUpClient = @:privateAccess marble.connection == null ? Net.clientId : @:privateAccess marble.connection.id;
|
||||
// }
|
||||
// @:privateAccess level.playGui.incrementPlayerScore(packet.clientId, packet.scoreIncr);
|
||||
}
|
||||
if (this.level.isMultiplayer && Net.isClient) {
|
||||
gem.pickUpClient = @:privateAccess marble.connection == null ? Net.clientId : @:privateAccess marble.connection.id;
|
||||
}
|
||||
}
|
||||
|
||||
override public function timeMultiplier() {
|
||||
|
|
|
|||
|
|
@ -68,6 +68,12 @@ class InputBitStream {
|
|||
return FPHelper.i32ToFloat(readInt32());
|
||||
}
|
||||
|
||||
public function readDouble() {
|
||||
var lo = readInt32();
|
||||
var hi = readInt32();
|
||||
return FPHelper.i64ToDouble(lo, hi);
|
||||
}
|
||||
|
||||
public function readString() {
|
||||
var length = readUInt16();
|
||||
var str = "";
|
||||
|
|
@ -151,4 +157,10 @@ class OutputBitStream {
|
|||
writeByte(StringTools.fastCodeAt(value, i));
|
||||
}
|
||||
}
|
||||
|
||||
public function writeDouble(value:Float) {
|
||||
var i64 = FPHelper.doubleToI64(value);
|
||||
writeInt32(i64.low);
|
||||
writeInt32(i64.high);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ class MarblePrediction {
|
|||
var subs = position.sub(p.position).lengthSq(); // + velocity.sub(p.velocity).lengthSq() + omega.sub(p.omega).lengthSq();
|
||||
if (p.netFlags != 0)
|
||||
subs += 1;
|
||||
if (subs > 0.01) {
|
||||
trace('Desync: ${position.x} ${position.y} ${position.z} != ${p.position.x} ${p.position.y} ${p.position.z}');
|
||||
}
|
||||
// if (p.powerUpId != powerupItemId)
|
||||
// if (tick % 10 == 0)
|
||||
// subs += 1; // temp
|
||||
|
|
|
|||
62
src/rewind/InputRecorder.hx
Normal file
62
src/rewind/InputRecorder.hx
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
package rewind;
|
||||
|
||||
import src.MarbleWorld;
|
||||
import h3d.Vector;
|
||||
import net.Move;
|
||||
|
||||
@:publicFields
|
||||
class InputRecorderFrame {
|
||||
var time:Float;
|
||||
var move:Move;
|
||||
var marbleAxes:Array<Vector>;
|
||||
var pos:Vector;
|
||||
var velocity:Vector;
|
||||
|
||||
public function new() {}
|
||||
}
|
||||
|
||||
class InputRecorder {
|
||||
var frames:Array<InputRecorderFrame>;
|
||||
var level:MarbleWorld;
|
||||
|
||||
public function new(level:MarbleWorld) {
|
||||
frames = [];
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public function recordInput(t:Float) {
|
||||
var frame = new InputRecorderFrame();
|
||||
frame.time = t;
|
||||
frame.move = level.marble.recordMove();
|
||||
frames.push(frame);
|
||||
}
|
||||
|
||||
public function recordMarble() {
|
||||
frames[frames.length - 1].pos = @:privateAccess level.marble.newPos?.clone();
|
||||
frames[frames.length - 1].velocity = level.marble.velocity.clone();
|
||||
}
|
||||
|
||||
public function recordAxis(axis:Array<Vector>) {
|
||||
frames[frames.length - 1].marbleAxes = axis.copy();
|
||||
}
|
||||
|
||||
public function getMovesFrom(t:Float) {
|
||||
if (frames.length == 0)
|
||||
return [];
|
||||
var start = 0;
|
||||
var end = frames.length - 1;
|
||||
var mid = Std.int(frames.length / 2);
|
||||
while (end - start > 1) {
|
||||
mid = Std.int((start / 2) + (end / 2));
|
||||
if (frames[mid].time < t) {
|
||||
start = mid + 1;
|
||||
} else if (frames[mid].time > t) {
|
||||
end = mid - 1;
|
||||
} else {
|
||||
start = end = mid;
|
||||
}
|
||||
}
|
||||
|
||||
return frames.slice(start - 1);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue