mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-10-30 08:11:25 +00:00
some optimization
This commit is contained in:
parent
99ae6ecf65
commit
aa85fc2faa
6 changed files with 224 additions and 106 deletions
|
|
@ -1062,7 +1062,7 @@ class Marble extends GameObject {
|
||||||
searchbox.addSpherePos(position.x + velocity.x * deltaT, position.y + velocity.y * deltaT, position.z + velocity.z * deltaT, _radius);
|
searchbox.addSpherePos(position.x + velocity.x * deltaT, position.y + velocity.y * deltaT, position.z + velocity.z * deltaT, _radius);
|
||||||
|
|
||||||
var foundObjs = this.collisionWorld.boundingSearch(searchbox);
|
var foundObjs = this.collisionWorld.boundingSearch(searchbox);
|
||||||
foundObjs.push(this.collisionWorld.staticWorld);
|
// foundObjs.push(this.collisionWorld.staticWorld);
|
||||||
|
|
||||||
var finalT = deltaT;
|
var finalT = deltaT;
|
||||||
var found = false;
|
var found = false;
|
||||||
|
|
@ -1151,7 +1151,7 @@ class Marble extends GameObject {
|
||||||
// var v = surface.points[surface.indices[i + 1]].transformed(obj.transform);
|
// var v = surface.points[surface.indices[i + 1]].transformed(obj.transform);
|
||||||
// var v2 = surface.points[surface.indices[i + 2]].transformed(obj.transform);
|
// var v2 = surface.points[surface.indices[i + 2]].transformed(obj.transform);
|
||||||
|
|
||||||
var triangleVerts = [v0, v, v2];
|
// var triangleVerts = [v0, v, v2];
|
||||||
|
|
||||||
var surfaceNormal = new Vector(verts.nx, verts.ny,
|
var surfaceNormal = new Vector(verts.nx, verts.ny,
|
||||||
verts.nz); // surface.normals[surface.indices[i]].transformed3x3(obj.transform).normalized();
|
verts.nz); // surface.normals[surface.indices[i]].transformed3x3(obj.transform).normalized();
|
||||||
|
|
@ -1166,8 +1166,8 @@ class Marble extends GameObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
testTriangles.push({
|
testTriangles.push({
|
||||||
v: [v0, v, v2],
|
v: [v0.clone(), v.clone(), v2.clone()],
|
||||||
n: surfaceNormal,
|
n: surfaceNormal.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Time until collision with the plane
|
// Time until collision with the plane
|
||||||
|
|
@ -1190,7 +1190,9 @@ class Marble extends GameObject {
|
||||||
}
|
}
|
||||||
// We *might* be colliding with an edge
|
// We *might* be colliding with an edge
|
||||||
|
|
||||||
var lastVert = v2;
|
var triangleVerts = [v0.clone(), v.clone(), v2.clone()];
|
||||||
|
|
||||||
|
var lastVert = v2.clone();
|
||||||
|
|
||||||
var radSq = radius * radius;
|
var radSq = radius * radius;
|
||||||
for (iter in 0...3) {
|
for (iter in 0...3) {
|
||||||
|
|
@ -1211,7 +1213,7 @@ class Marble extends GameObject {
|
||||||
|
|
||||||
// If it's not quadratic or has no solution, ignore this edge.
|
// If it's not quadratic or has no solution, ignore this edge.
|
||||||
if (a == 0.0 || discriminant < 0.0) {
|
if (a == 0.0 || discriminant < 0.0) {
|
||||||
lastVert = thisVert;
|
lastVert.load(thisVert);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1231,7 +1233,7 @@ class Marble extends GameObject {
|
||||||
|
|
||||||
// If the collision doesn't happen on this time step, ignore this edge.
|
// If the collision doesn't happen on this time step, ignore this edge.
|
||||||
if (edgeCollisionTime2 <= 0.0001 || finalT <= edgeCollisionTime) {
|
if (edgeCollisionTime2 <= 0.0001 || finalT <= edgeCollisionTime) {
|
||||||
lastVert = thisVert;
|
lastVert.load(thisVert);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1245,7 +1247,7 @@ class Marble extends GameObject {
|
||||||
|
|
||||||
// If the collision happens outside the boundaries of the edge, ignore this edge.
|
// If the collision happens outside the boundaries of the edge, ignore this edge.
|
||||||
if (-radius > distanceAlongEdge || edgeLen + radius < distanceAlongEdge) {
|
if (-radius > distanceAlongEdge || edgeLen + radius < distanceAlongEdge) {
|
||||||
lastVert = thisVert;
|
lastVert.load(thisVert);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1309,14 +1311,14 @@ class Marble extends GameObject {
|
||||||
|
|
||||||
// We still need to check the other corner ...
|
// We still need to check the other corner ...
|
||||||
// Build one last quadratic equation to solve for the collision time
|
// Build one last quadratic equation to solve for the collision time
|
||||||
posVertDiff = position.sub(lastVert);
|
var posVertDiff = position.sub(lastVert);
|
||||||
b = 2 * posVertDiff.dot(relVel);
|
b = 2 * posVertDiff.dot(relVel);
|
||||||
c = posVertDiff.lengthSq() - radSq;
|
c = posVertDiff.lengthSq() - radSq;
|
||||||
discriminant = b * b - (4 * a * c);
|
discriminant = b * b - (4 * a * c);
|
||||||
|
|
||||||
// If it's not quadratic or has no solution, then skip this corner
|
// If it's not quadratic or has no solution, then skip this corner
|
||||||
if (a == 0.0 || discriminant < 0.0) {
|
if (a == 0.0 || discriminant < 0.0) {
|
||||||
lastVert = thisVert;
|
lastVert.load(thisVert);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1335,7 +1337,7 @@ class Marble extends GameObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (edgeCollisionTime2 <= 0.0001 || finalT <= edgeCollisionTime) {
|
if (edgeCollisionTime2 <= 0.0001 || finalT <= edgeCollisionTime) {
|
||||||
lastVert = thisVert;
|
lastVert.load(thisVert);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1343,7 +1345,7 @@ class Marble extends GameObject {
|
||||||
edgeCollisionTime = 0;
|
edgeCollisionTime = 0;
|
||||||
|
|
||||||
if (edgeCollisionTime < 0.000001) {
|
if (edgeCollisionTime < 0.000001) {
|
||||||
lastVert = thisVert;
|
lastVert.load(thisVert);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1351,7 +1353,7 @@ class Marble extends GameObject {
|
||||||
currentFinalPos = position.add(relVel.multiply(finalT));
|
currentFinalPos = position.add(relVel.multiply(finalT));
|
||||||
// Debug.drawSphere(currentFinalPos, radius);
|
// Debug.drawSphere(currentFinalPos, radius);
|
||||||
|
|
||||||
lastVert = thisVert;
|
lastVert.load(thisVert);
|
||||||
found = true;
|
found = true;
|
||||||
// iterationFound = true;
|
// iterationFound = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1415,7 +1417,7 @@ class Marble extends GameObject {
|
||||||
// Nudge to the surface of the contact plane
|
// Nudge to the surface of the contact plane
|
||||||
Debug.drawTriangle(testTri.v[0], testTri.v[1], testTri.v[2]);
|
Debug.drawTriangle(testTri.v[0], testTri.v[1], testTri.v[2]);
|
||||||
Debug.drawSphere(position, radius);
|
Debug.drawSphere(position, radius);
|
||||||
position = position.add(separatingDistance.multiply(radius - distToContactPlane - 0.005));
|
position.load(position.add(separatingDistance.multiply(radius - distToContactPlane - 0.005)));
|
||||||
resolved++;
|
resolved++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1446,7 +1448,7 @@ class Marble extends GameObject {
|
||||||
var dist = marblePosition.distance(position);
|
var dist = marblePosition.distance(position);
|
||||||
if (dist < radius + marble.radius + 0.001) {
|
if (dist < radius + marble.radius + 0.001) {
|
||||||
var separatingDistance = position.sub(marblePosition).normalized();
|
var separatingDistance = position.sub(marblePosition).normalized();
|
||||||
position = position.add(separatingDistance.multiply(radius + marble.radius + 0.001 - dist));
|
position.load(position.add(separatingDistance.multiply(radius + marble.radius + 0.001 - dist)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return position;
|
return position;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package src;
|
package src;
|
||||||
|
|
||||||
|
import net.MarblePredictionStore;
|
||||||
|
import net.MarblePredictionStore.MarblePrediction;
|
||||||
import net.MarbleUpdateQueue;
|
import net.MarbleUpdateQueue;
|
||||||
import haxe.Exception;
|
import haxe.Exception;
|
||||||
import net.NetPacket.MarbleUpdatePacket;
|
import net.NetPacket.MarbleUpdatePacket;
|
||||||
|
|
@ -103,6 +105,7 @@ import modes.NullMode;
|
||||||
import modes.GameMode.GameModeFactory;
|
import modes.GameMode.GameModeFactory;
|
||||||
import src.Renderer;
|
import src.Renderer;
|
||||||
import src.Analytics;
|
import src.Analytics;
|
||||||
|
import src.Debug;
|
||||||
|
|
||||||
class MarbleWorld extends Scheduler {
|
class MarbleWorld extends Scheduler {
|
||||||
public var collisionWorld:CollisionWorld;
|
public var collisionWorld:CollisionWorld;
|
||||||
|
|
@ -204,6 +207,7 @@ class MarbleWorld extends Scheduler {
|
||||||
var maxPredictionTicks:Int = 16;
|
var maxPredictionTicks:Int = 16;
|
||||||
|
|
||||||
var clientMarbles:Map<GameConnection, Marble> = [];
|
var clientMarbles:Map<GameConnection, Marble> = [];
|
||||||
|
var predictions:MarblePredictionStore;
|
||||||
|
|
||||||
public var lastMoves:MarbleUpdateQueue;
|
public var lastMoves:MarbleUpdateQueue;
|
||||||
|
|
||||||
|
|
@ -246,6 +250,7 @@ class MarbleWorld extends Scheduler {
|
||||||
isRecording = false;
|
isRecording = false;
|
||||||
isWatching = false;
|
isWatching = false;
|
||||||
lastMoves = new MarbleUpdateQueue();
|
lastMoves = new MarbleUpdateQueue();
|
||||||
|
predictions = new MarblePredictionStore();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the network RNG for hunt
|
// Set the network RNG for hunt
|
||||||
|
|
@ -768,10 +773,10 @@ class MarbleWorld extends Scheduler {
|
||||||
var tmat = Matrix.T(interiorPosition.x, interiorPosition.y, interiorPosition.z);
|
var tmat = Matrix.T(interiorPosition.x, interiorPosition.y, interiorPosition.z);
|
||||||
mat.multiply(mat, tmat);
|
mat.multiply(mat, tmat);
|
||||||
|
|
||||||
if (hasCollision)
|
// if (hasCollision)
|
||||||
this.collisionWorld.addStaticInterior(interior.collider, mat);
|
// this.collisionWorld.addStaticInterior(interior.collider, mat);
|
||||||
|
|
||||||
interior.isCollideable = false;
|
interior.isCollideable = hasCollision;
|
||||||
interior.setTransform(mat);
|
interior.setTransform(mat);
|
||||||
onFinish();
|
onFinish();
|
||||||
});
|
});
|
||||||
|
|
@ -890,7 +895,7 @@ class MarbleWorld extends Scheduler {
|
||||||
public function addInterior(obj:InteriorObject, onFinish:Void->Void) {
|
public function addInterior(obj:InteriorObject, onFinish:Void->Void) {
|
||||||
this.interiors.push(obj);
|
this.interiors.push(obj);
|
||||||
obj.init(cast this, () -> {
|
obj.init(cast this, () -> {
|
||||||
// this.collisionWorld.addEntity(obj.collider);
|
this.collisionWorld.addEntity(obj.collider);
|
||||||
if (obj.useInstancing)
|
if (obj.useInstancing)
|
||||||
this.instanceManager.addObject(obj);
|
this.instanceManager.addObject(obj);
|
||||||
else
|
else
|
||||||
|
|
@ -1033,9 +1038,12 @@ class MarbleWorld extends Scheduler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyReceivedMoves() {
|
public function applyReceivedMoves() {
|
||||||
|
var needsPrediction = 0;
|
||||||
if (!lastMoves.ourMoveApplied) {
|
if (!lastMoves.ourMoveApplied) {
|
||||||
var ourMove = lastMoves.myMarbleUpdate;
|
var ourMove = lastMoves.myMarbleUpdate;
|
||||||
if (ourMove != null) {
|
if (ourMove != null) {
|
||||||
|
var ourMoveStruct = Net.clientConnection.moveManager.acknowledgeMove(ourMove.move.id, timeState);
|
||||||
|
lastMoves.ourMoveApplied = true;
|
||||||
for (client => arr in lastMoves.otherMarbleUpdates) {
|
for (client => arr in lastMoves.otherMarbleUpdates) {
|
||||||
var lastMove = null;
|
var lastMove = null;
|
||||||
while (arr.length > 0) {
|
while (arr.length > 0) {
|
||||||
|
|
@ -1047,27 +1055,61 @@ class MarbleWorld extends Scheduler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (lastMove != null) {
|
if (lastMove != null) {
|
||||||
if (ourMove.serverTicks == lastMove.serverTicks)
|
// if (ourMove.serverTicks == lastMove.serverTicks) {
|
||||||
|
if (ourMoveStruct != null) {
|
||||||
|
var otherPred = predictions.retrieveState(clientMarbles[Net.clientIdMap[client]], ourMoveStruct.timeState.ticks);
|
||||||
|
if (otherPred != null) {
|
||||||
|
if (otherPred.getError(lastMove) > 0.001) {
|
||||||
|
// trace('Prediction error: ${otherPred.getError(lastMove)}');
|
||||||
|
trace('Desync for tick ${ourMoveStruct.timeState.ticks}');
|
||||||
|
clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove);
|
||||||
|
needsPrediction |= 1 << client;
|
||||||
|
arr.insert(0, lastMove);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
trace('Desync for tick ${ourMoveStruct.timeState.ticks}');
|
||||||
|
clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove);
|
||||||
|
needsPrediction |= 1 << client;
|
||||||
|
arr.insert(0, lastMove);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
trace('Desync in General');
|
||||||
clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove);
|
clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove);
|
||||||
arr.insert(0, lastMove);
|
needsPrediction |= 1 << client;
|
||||||
|
arr.insert(0, lastMove);
|
||||||
|
}
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
marble.unpackUpdate(ourMove);
|
if (ourMoveStruct != null) {
|
||||||
|
var ourPred = predictions.retrieveState(marble, ourMoveStruct.timeState.ticks);
|
||||||
|
if (ourPred != null) {
|
||||||
|
if (ourPred.getError(ourMove) > 0.001) {
|
||||||
|
trace('Desync for tick ${ourMoveStruct.timeState.ticks}');
|
||||||
|
marble.unpackUpdate(ourMove);
|
||||||
|
needsPrediction |= 1 << Net.clientId;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
trace('Desync for tick ${ourMoveStruct.timeState.ticks}');
|
||||||
|
marble.unpackUpdate(ourMove);
|
||||||
|
needsPrediction |= 1 << Net.clientId;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
trace('Desync in General');
|
||||||
|
marble.unpackUpdate(ourMove);
|
||||||
|
needsPrediction |= 1 << Net.clientId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return needsPrediction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function applyClientPrediction() {
|
public function applyClientPrediction(marbleNeedsPrediction:Int) {
|
||||||
// First acknowledge the marble's last move so we can get that over with
|
// First acknowledge the marble's last move so we can get that over with
|
||||||
var ourLastMove = lastMoves.myMarbleUpdate;
|
var ourLastMove = lastMoves.myMarbleUpdate;
|
||||||
if (ourLastMove == null)
|
if (ourLastMove == null || marbleNeedsPrediction == 0)
|
||||||
return;
|
return -1;
|
||||||
var ackLag = @:privateAccess Net.clientConnection.moveManager.queuedMoves.length;
|
var ackLag = @:privateAccess Net.clientConnection.moveManager.queuedMoves.length;
|
||||||
var mvStored = null;
|
|
||||||
if (!lastMoves.ourMoveApplied)
|
|
||||||
mvStored = Net.clientConnection.moveManager.acknowledgeMove(ourLastMove.move.id, timeState);
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
|
|
||||||
var ourLastMoveTime = ourLastMove.serverTicks;
|
var ourLastMoveTime = ourLastMove.serverTicks;
|
||||||
|
|
||||||
|
|
@ -1076,97 +1118,87 @@ class MarbleWorld extends Scheduler {
|
||||||
var qm = ourQueuedMoves[0];
|
var qm = ourQueuedMoves[0];
|
||||||
var advanceTimeState = qm != null ? qm.timeState.clone() : timeState.clone();
|
var advanceTimeState = qm != null ? qm.timeState.clone() : timeState.clone();
|
||||||
advanceTimeState.dt = 0.032;
|
advanceTimeState.dt = 0.032;
|
||||||
|
advanceTimeState.ticks = ourLastMoveTime;
|
||||||
|
|
||||||
if (qm != null) {
|
if (marbleNeedsPrediction & (1 << Net.clientId) > 0) {
|
||||||
var mvs = qm.powerupStates.copy();
|
if (qm != null) {
|
||||||
for (pw in marble.level.powerUps) {
|
var mvs = qm.powerupStates.copy();
|
||||||
pw.lastPickUpTime = mvs.shift();
|
for (pw in marble.level.powerUps) {
|
||||||
|
pw.lastPickUpTime = mvs.shift();
|
||||||
|
}
|
||||||
|
@:privateAccess marble.helicopterEnableTime = qm.helicopterState;
|
||||||
|
@:privateAccess marble.megaMarbleEnableTime = qm.megaState;
|
||||||
|
marble.blastAmount = qm.blastAmt;
|
||||||
}
|
}
|
||||||
@:privateAccess marble.helicopterEnableTime = qm.helicopterState;
|
|
||||||
@:privateAccess marble.megaMarbleEnableTime = qm.megaState;
|
|
||||||
marble.blastAmount = qm.blastAmt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ackLag = ourQueuedMoves.length;
|
ackLag = ourQueuedMoves.length;
|
||||||
|
|
||||||
// Tick the remaining moves (ours)
|
// Tick the remaining moves (ours)
|
||||||
if (!lastMoves.ourMoveApplied) {
|
@:privateAccess this.marble.isNetUpdate = true;
|
||||||
@:privateAccess this.marble.isNetUpdate = true;
|
var totalTicksToDo = ourQueuedMoves.length;
|
||||||
var totalTicksToDo = ourQueuedMoves.length;
|
var endTick = ourLastMoveTime + totalTicksToDo;
|
||||||
var endTick = ourLastMoveTime + totalTicksToDo;
|
var currentTick = ourLastMoveTime;
|
||||||
var currentTick = ourLastMoveTime;
|
//- Std.int(ourLastMove.moveQueueSize - @:privateAccess Net.clientConnection.moveManager.ackRTT); // - Std.int((@:privateAccess Net.clientConnection.moveManager.ackRTT)) - offset;
|
||||||
//- Std.int(ourLastMove.moveQueueSize - @:privateAccess Net.clientConnection.moveManager.ackRTT); // - Std.int((@:privateAccess Net.clientConnection.moveManager.ackRTT)) - offset;
|
|
||||||
|
|
||||||
var marblesToTick = new Map();
|
var marblesToTick = new Map();
|
||||||
|
|
||||||
for (client => arr in lastMoves.otherMarbleUpdates) {
|
for (client => arr in lastMoves.otherMarbleUpdates) {
|
||||||
if (arr.length > 0) {
|
if (marbleNeedsPrediction & (1 << client) > 0 && arr.length > 0) {
|
||||||
var m = arr[0];
|
var m = arr[0];
|
||||||
if (m.serverTicks == ourLastMoveTime) {
|
// if (m.serverTicks == ourLastMoveTime) {
|
||||||
var marbleToUpdate = clientMarbles[Net.clientIdMap[client]];
|
var marbleToUpdate = clientMarbles[Net.clientIdMap[client]];
|
||||||
Debug.drawSphere(@:privateAccess marbleToUpdate.newPos, marbleToUpdate._radius);
|
Debug.drawSphere(@:privateAccess marbleToUpdate.newPos, marbleToUpdate._radius);
|
||||||
m.calculationTicks = ourQueuedMoves.length; // ourQueuedMoves.length;
|
if (marbleNeedsPrediction & (1 << Net.clientId) > 0)
|
||||||
|
m.calculationTicks = ourQueuedMoves.length; // ourQueuedMoves.length;
|
||||||
|
else
|
||||||
|
m.calculationTicks = ourQueuedMoves.length;
|
||||||
|
// - Std.int((@:privateAccess Net.clientConnection.moveManager.ackRTT - ourLastMove.moveQueueSize) / 2);
|
||||||
|
|
||||||
// - Std.int((@:privateAccess Net.clientConnection.moveManager.ackRTT - ourLastMove.moveQueueSize) / 2);
|
marblesToTick.set(client, m);
|
||||||
marblesToTick.set(client, m);
|
arr.shift();
|
||||||
arr.shift();
|
// }
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Debug.drawSphere(@:privateAccess this.marble.newPos, this.marble._radius);
|
Debug.drawSphere(@:privateAccess this.marble.newPos, this.marble._radius);
|
||||||
// var syncTickStates = new Map();
|
// var syncTickStates = new Map();
|
||||||
|
|
||||||
for (move in ourQueuedMoves) {
|
for (move in ourQueuedMoves) {
|
||||||
var m = move.move;
|
var m = move.move;
|
||||||
// Debug.drawSphere(@:privateAccess this.marble.newPos, this.marble._radius);
|
// Debug.drawSphere(@:privateAccess this.marble.newPos, this.marble._radius);
|
||||||
|
if (marbleNeedsPrediction & (1 << Net.clientId) > 0) {
|
||||||
this.marble.heldPowerup = move.powerup;
|
this.marble.heldPowerup = move.powerup;
|
||||||
@:privateAccess this.marble.moveMotionDir = move.motionDir;
|
@:privateAccess this.marble.moveMotionDir = move.motionDir;
|
||||||
@:privateAccess this.marble.advancePhysics(advanceTimeState, m, this.collisionWorld, this.pathedInteriors);
|
@:privateAccess this.marble.advancePhysics(advanceTimeState, m, this.collisionWorld, this.pathedInteriors);
|
||||||
// var collidings = @:privateAccess this.marble.contactEntities.filter(x -> x is SphereCollisionEntity);
|
this.predictions.storeState(this.marble, move.timeState.ticks);
|
||||||
advanceTimeState.currentAttemptTime += 0.032;
|
|
||||||
|
|
||||||
for (client => m in marblesToTick) {
|
|
||||||
if (m.calculationTicks > 0) {
|
|
||||||
var marbleToUpdate = clientMarbles[Net.clientIdMap[client]];
|
|
||||||
// Debug.drawSphere(@:privateAccess marbleToUpdate.newPos, marbleToUpdate._radius);
|
|
||||||
|
|
||||||
var beforePos = @:privateAccess marbleToUpdate.newPos.clone();
|
|
||||||
var mv = m.move.move;
|
|
||||||
@:privateAccess marbleToUpdate.isNetUpdate = true;
|
|
||||||
@:privateAccess marbleToUpdate.moveMotionDir = m.move.motionDir;
|
|
||||||
@:privateAccess marbleToUpdate.advancePhysics(advanceTimeState, mv, this.collisionWorld, this.pathedInteriors);
|
|
||||||
@:privateAccess marbleToUpdate.isNetUpdate = false;
|
|
||||||
m.calculationTicks--;
|
|
||||||
|
|
||||||
var afterPos = @:privateAccess marbleToUpdate.newPos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
currentTick++;
|
|
||||||
}
|
}
|
||||||
|
// var collidings = @:privateAccess this.marble.contactEntities.filter(x -> x is SphereCollisionEntity);
|
||||||
|
|
||||||
// for (marble => state in syncTickStates) {
|
for (client => m in marblesToTick) {
|
||||||
// marble.restoreState(state);
|
if (m.calculationTicks > 0) {
|
||||||
// }
|
var marbleToUpdate = clientMarbles[Net.clientIdMap[client]];
|
||||||
|
// Debug.drawSphere(@:privateAccess marbleToUpdate.newPos, marbleToUpdate._radius);
|
||||||
|
|
||||||
// for (client => m in marblesToTick) {
|
var mv = m.move.move;
|
||||||
// if (m.calculationTicks >= 0) {
|
@:privateAccess marbleToUpdate.isNetUpdate = true;
|
||||||
// var marbleToUpdate = clientMarbles[Net.clientIdMap[client]];
|
@:privateAccess marbleToUpdate.moveMotionDir = m.move.motionDir;
|
||||||
|
@:privateAccess marbleToUpdate.advancePhysics(advanceTimeState, mv, this.collisionWorld, this.pathedInteriors);
|
||||||
// while (m.calculationTicks > 0) {
|
this.predictions.storeState(marbleToUpdate, move.timeState.ticks);
|
||||||
// var mv = m.move.move;
|
@:privateAccess marbleToUpdate.isNetUpdate = false;
|
||||||
// @:privateAccess marbleToUpdate.isNetUpdate = true;
|
m.calculationTicks--;
|
||||||
// @:privateAccess marbleToUpdate.moveMotionDir = m.move.motionDir;
|
}
|
||||||
// @:privateAccess marbleToUpdate.advancePhysics(advanceTimeState, mv, this.collisionWorld, this.pathedInteriors);
|
}
|
||||||
// @:privateAccess marbleToUpdate.isNetUpdate = false;
|
advanceTimeState.currentAttemptTime += 0.032;
|
||||||
// m.calculationTicks--;
|
advanceTimeState.ticks++;
|
||||||
// }
|
currentTick++;
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
lastMoves.ourMoveApplied = true;
|
|
||||||
@:privateAccess this.marble.isNetUpdate = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastMoves.ourMoveApplied = true;
|
||||||
|
@:privateAccess this.marble.isNetUpdate = false;
|
||||||
|
return advanceTimeState.ticks;
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function rollback(t:Float) {
|
public function rollback(t:Float) {
|
||||||
|
|
@ -1355,10 +1387,11 @@ class MarbleWorld extends Scheduler {
|
||||||
tickAccumulator += timeState.dt;
|
tickAccumulator += timeState.dt;
|
||||||
while (tickAccumulator >= 0.032) {
|
while (tickAccumulator >= 0.032) {
|
||||||
// Apply the server side ticks
|
// Apply the server side ticks
|
||||||
|
var lastPredTick = -1;
|
||||||
if (Net.isClient) {
|
if (Net.isClient) {
|
||||||
applyReceivedMoves();
|
var marbleNeedsTicking = applyReceivedMoves();
|
||||||
// Catch up
|
// Catch up
|
||||||
applyClientPrediction();
|
lastPredTick = applyClientPrediction(marbleNeedsTicking);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the clientside prediction sim
|
// Do the clientside prediction sim
|
||||||
|
|
@ -1371,6 +1404,10 @@ class MarbleWorld extends Scheduler {
|
||||||
for (client => marble in clientMarbles) {
|
for (client => marble in clientMarbles) {
|
||||||
otherMoves.push(marble.updateServer(fixedDt, collisionWorld, pathedInteriors));
|
otherMoves.push(marble.updateServer(fixedDt, collisionWorld, pathedInteriors));
|
||||||
}
|
}
|
||||||
|
this.predictions.storeState(marble, myMove.timeState.ticks);
|
||||||
|
for (client => marble in clientMarbles) {
|
||||||
|
this.predictions.storeState(marble, myMove.timeState.ticks);
|
||||||
|
}
|
||||||
if (Net.isHost) {
|
if (Net.isHost) {
|
||||||
for (client => othermarble in clientMarbles) { // Oh no!
|
for (client => othermarble in clientMarbles) { // Oh no!
|
||||||
var mv = otherMoves.shift();
|
var mv = otherMoves.shift();
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ class CollisionWorld {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contacts = contacts.concat(this.staticWorld.sphereIntersection(spherecollision, timeState));
|
// contacts = contacts.concat(this.staticWorld.sphereIntersection(spherecollision, timeState));
|
||||||
|
|
||||||
var dynSearch = dynamicOctree.boundingSearch(box).map(x -> cast(x, CollisionEntity));
|
var dynSearch = dynamicOctree.boundingSearch(box).map(x -> cast(x, CollisionEntity));
|
||||||
for (obj in dynSearch) {
|
for (obj in dynSearch) {
|
||||||
|
|
|
||||||
62
src/net/MarblePredictionStore.hx
Normal file
62
src/net/MarblePredictionStore.hx
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
package net;
|
||||||
|
|
||||||
|
import net.NetPacket.MarbleUpdatePacket;
|
||||||
|
import net.NetPacket.MarbleMovePacket;
|
||||||
|
import src.TimeState;
|
||||||
|
import src.Marble;
|
||||||
|
import h3d.Vector;
|
||||||
|
|
||||||
|
@:publicFields
|
||||||
|
class MarblePrediction {
|
||||||
|
var tick:Int;
|
||||||
|
var position:Vector;
|
||||||
|
var velocity:Vector;
|
||||||
|
var omega:Vector;
|
||||||
|
|
||||||
|
public function new(marble:Marble, tick:Int) {
|
||||||
|
this.tick = tick;
|
||||||
|
position = @:privateAccess marble.newPos.clone();
|
||||||
|
velocity = @:privateAccess marble.velocity.clone();
|
||||||
|
omega = @:privateAccess marble.omega.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public inline function getError(p:MarbleUpdatePacket) {
|
||||||
|
var subs = position.sub(p.position).lengthSq() + velocity.sub(p.velocity).lengthSq() + omega.sub(p.omega).lengthSq();
|
||||||
|
return subs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MarblePredictionStore {
|
||||||
|
var predictions:Map<Marble, Array<MarblePrediction>>;
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
predictions = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function storeState(marble:Marble, tick:Int) {
|
||||||
|
var state = new MarblePrediction(marble, tick);
|
||||||
|
if (predictions.exists(marble)) {
|
||||||
|
var arr = predictions[marble];
|
||||||
|
while (arr.length != 0 && arr[0].tick >= tick)
|
||||||
|
arr.shift();
|
||||||
|
arr.push(state);
|
||||||
|
} else {
|
||||||
|
predictions.set(marble, [state]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function retrieveState(marble:Marble, tick:Int) {
|
||||||
|
if (predictions.exists(marble)) {
|
||||||
|
var arr = predictions[marble];
|
||||||
|
while (arr.length != 0 && arr[0].tick < tick)
|
||||||
|
arr.shift();
|
||||||
|
if (arr.length == 0)
|
||||||
|
return null;
|
||||||
|
var p = arr[0];
|
||||||
|
if (p.tick == tick)
|
||||||
|
return p;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package net;
|
package net;
|
||||||
|
|
||||||
|
import net.NetPacket.MarbleUpdatePacket;
|
||||||
import shapes.PowerUp;
|
import shapes.PowerUp;
|
||||||
import net.NetPacket.MarbleMovePacket;
|
import net.NetPacket.MarbleMovePacket;
|
||||||
import src.TimeState;
|
import src.TimeState;
|
||||||
|
|
@ -199,4 +200,20 @@ class MoveManager {
|
||||||
lastAckMoveId = m;
|
lastAckMoveId = m;
|
||||||
return mv;
|
return mv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getMoveForTick(m:Int) {
|
||||||
|
if (m <= lastAckMoveId)
|
||||||
|
return null;
|
||||||
|
if (m == 65535 || m == -1)
|
||||||
|
return null;
|
||||||
|
if (queuedMoves.length == 0)
|
||||||
|
return null;
|
||||||
|
for (i in 0...queuedMoves.length) {
|
||||||
|
if (queuedMoves[i].id == m)
|
||||||
|
return queuedMoves[i];
|
||||||
|
if (queuedMoves[i].id > m)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ class Net {
|
||||||
isHost = true;
|
isHost = true;
|
||||||
isClient = false;
|
isClient = false;
|
||||||
clientId = 0;
|
clientId = 0;
|
||||||
masterWs = new WebSocket("ws://localhost:8080");
|
masterWs = new WebSocket("ws://192.168.1.2:8080");
|
||||||
|
|
||||||
masterWs.onmessage = (m) -> {
|
masterWs.onmessage = (m) -> {
|
||||||
switch (m) {
|
switch (m) {
|
||||||
|
|
@ -97,7 +97,7 @@ class Net {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function joinServer(connectedCb:() -> Void) {
|
public static function joinServer(connectedCb:() -> Void) {
|
||||||
masterWs = new WebSocket("ws://localhost:8080");
|
masterWs = new WebSocket("ws://192.168.1.2:8080");
|
||||||
masterWs.onopen = () -> {
|
masterWs.onopen = () -> {
|
||||||
client = new RTCPeerConnection(["stun:stun.l.google.com:19302"], "0.0.0.0");
|
client = new RTCPeerConnection(["stun:stun.l.google.com:19302"], "0.0.0.0");
|
||||||
var candidates = [];
|
var candidates = [];
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue