mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-10-30 08:11:25 +00:00
attempt at something
This commit is contained in:
parent
b1ec446360
commit
42ec5701e3
8 changed files with 137 additions and 151 deletions
14
src/Debug.hx
14
src/Debug.hx
|
|
@ -12,7 +12,8 @@ class Debug {
|
|||
static var _triangles:Array<h3d.col.Point> = [];
|
||||
static var _spheres:Array<{
|
||||
position:Vector,
|
||||
radius:Float
|
||||
radius:Float,
|
||||
lifetime:Float
|
||||
}> = [];
|
||||
|
||||
static var debugTriangles:h3d.scene.Mesh;
|
||||
|
|
@ -20,7 +21,7 @@ class Debug {
|
|||
|
||||
public static function init() {}
|
||||
|
||||
public static function update() {
|
||||
public static function update(dt:Float) {
|
||||
if (_triangles.length != 0 && drawBounds) {
|
||||
var prim = new h3d.prim.Polygon(_triangles.copy());
|
||||
if (debugTriangles != null) {
|
||||
|
|
@ -48,12 +49,17 @@ class Debug {
|
|||
MarbleGame.instance.scene.addChild(debugSphere);
|
||||
}
|
||||
debugSphere.begin(_spheres.length);
|
||||
var toremove = [];
|
||||
for (sph in _spheres) {
|
||||
debugSphere.setPosition(sph.position.x, sph.position.y, sph.position.z);
|
||||
debugSphere.setScale(sph.radius);
|
||||
debugSphere.emitInstance();
|
||||
sph.lifetime -= dt;
|
||||
if (sph.lifetime < 0)
|
||||
toremove.push(sph);
|
||||
}
|
||||
_spheres = [];
|
||||
for (sph in toremove)
|
||||
_spheres.remove(sph);
|
||||
} else {
|
||||
if (debugSphere != null) {
|
||||
debugSphere.remove();
|
||||
|
|
@ -72,6 +78,6 @@ class Debug {
|
|||
|
||||
public static function drawSphere(centre:Vector, radius:Float) {
|
||||
if (drawBounds)
|
||||
_spheres.push({position: centre.clone(), radius: radius});
|
||||
_spheres.push({position: centre.clone(), radius: radius, lifetime: 0.032});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -243,6 +243,7 @@ class Marble extends GameObject {
|
|||
public var contacts:Array<CollisionInfo> = [];
|
||||
public var bestContact:CollisionInfo;
|
||||
public var contactEntities:Array<CollisionEntity> = [];
|
||||
public var collidingMarbles:Array<Marble> = [];
|
||||
|
||||
var queuedContacts:Array<CollisionInfo> = [];
|
||||
var appliedImpulses:Array<{impulse:Vector, contactImpulse:Bool}> = [];
|
||||
|
|
@ -295,6 +296,7 @@ class Marble extends GameObject {
|
|||
var connection:net.Net.ClientConnection;
|
||||
var moveMotionDir:Vector;
|
||||
var isNetUpdate:Bool = false;
|
||||
var collisionToken:Int = 0;
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
|
|
@ -527,6 +529,11 @@ class Marble extends GameObject {
|
|||
this.contacts = queuedContacts;
|
||||
var c = collisiomWorld.sphereIntersection(this.collider, timeState);
|
||||
this.contactEntities = c.foundEntities;
|
||||
this.collidingMarbles = [];
|
||||
for (e in this.contacts) {
|
||||
if (e.collider is SphereCollisionEntity)
|
||||
this.collidingMarbles.push(cast(e.collider, SphereCollisionEntity).marble);
|
||||
}
|
||||
contacts = contacts.concat(c.contacts);
|
||||
}
|
||||
|
||||
|
|
@ -1661,7 +1668,7 @@ class Marble extends GameObject {
|
|||
|
||||
newPos = this.collider.transform.getPosition();
|
||||
|
||||
if (this.prevPos != null) {
|
||||
if (this.prevPos != null && !this.isNetUpdate) {
|
||||
var tempTimeState = timeState.clone();
|
||||
tempTimeState.currentAttemptTime = passedTime;
|
||||
this.level.callCollisionHandlers(cast this, tempTimeState, oldPos, newPos);
|
||||
|
|
@ -1697,7 +1704,7 @@ class Marble extends GameObject {
|
|||
// }
|
||||
this.oldPos = this.newPos;
|
||||
this.newPos = p.position;
|
||||
this.collider.transform.setPosition(this.newPos);
|
||||
this.collider.transform.setPosition(p.position);
|
||||
this.velocity = p.velocity;
|
||||
this.omega = p.omega;
|
||||
return true;
|
||||
|
|
@ -1739,6 +1746,12 @@ class Marble extends GameObject {
|
|||
playedSounds = [];
|
||||
advancePhysics(timeState, move.move, collisionWorld, pathedInteriors);
|
||||
|
||||
for (marble in this.collidingMarbles) {
|
||||
marble.collisionToken = timeState.ticks;
|
||||
}
|
||||
if (this.collidingMarbles.length != 0)
|
||||
this.collisionToken = timeState.ticks;
|
||||
|
||||
physicsAccumulator = 0;
|
||||
|
||||
if (Net.isHost) {
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ class MarbleGame {
|
|||
world = null;
|
||||
return;
|
||||
}
|
||||
Debug.update();
|
||||
Debug.update(dt);
|
||||
if (Util.isTouchDevice()) {
|
||||
touchInput.update();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package src;
|
||||
|
||||
import net.MarbleUpdateQueue;
|
||||
import haxe.Exception;
|
||||
import net.NetPacket.MarbleUpdatePacket;
|
||||
import net.NetPacket.MarbleMovePacket;
|
||||
|
|
@ -202,7 +203,7 @@ class MarbleWorld extends Scheduler {
|
|||
|
||||
var clientMarbles:Map<ClientConnection, Marble> = [];
|
||||
|
||||
public var lastMoves:Map<Int, MarbleUpdatePacket> = [];
|
||||
public var lastMoves:MarbleUpdateQueue;
|
||||
|
||||
// Loading
|
||||
var resourceLoadFuncs:Array<(() -> Void)->Void> = [];
|
||||
|
|
@ -242,6 +243,7 @@ class MarbleWorld extends Scheduler {
|
|||
if (this.isMultiplayer) {
|
||||
isRecording = false;
|
||||
isWatching = false;
|
||||
lastMoves = new MarbleUpdateQueue();
|
||||
}
|
||||
|
||||
// Set the network RNG for hunt
|
||||
|
|
@ -1023,180 +1025,113 @@ class MarbleWorld extends Scheduler {
|
|||
}
|
||||
|
||||
public function applyReceivedMoves() {
|
||||
if (!lastMoves[Net.clientId].applied) {
|
||||
var allApplied = false;
|
||||
for (client => lastMove in lastMoves) {
|
||||
if (lastMove.applied) {
|
||||
allApplied = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!allApplied) {
|
||||
for (client => lastMove in lastMoves) {
|
||||
var isApplied = lastMove.clientId == Net.clientId ? marble.unpackUpdate(lastMove) : clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove);
|
||||
if (!lastMoves.ourMoveApplied) {
|
||||
var ourMove = lastMoves.myMarbleUpdate;
|
||||
if (ourMove != null) {
|
||||
marble.unpackUpdate(ourMove);
|
||||
for (client => arr in lastMoves.otherMarbleUpdates) {
|
||||
var lastMove = null;
|
||||
while (arr.length > 0) {
|
||||
var p = arr[0];
|
||||
if (p.serverTicks <= ourMove.serverTicks && p.serverTicks >= ourMove.collisionToken) {
|
||||
clientMarbles[Net.clientIdMap[client]].unpackUpdate(p);
|
||||
lastMove = arr.shift();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lastMove != null)
|
||||
arr.insert(0, lastMove);
|
||||
}
|
||||
}
|
||||
}
|
||||
// for (client => lastMove in lastMoves) {
|
||||
// if (lastMove.applied)
|
||||
// continue;
|
||||
|
||||
// var isApplied = lastMove.clientId == Net.clientId ? marble.unpackUpdate(lastMove) : clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove);
|
||||
|
||||
// if (!isApplied)
|
||||
// lastMove.applied = true;
|
||||
// }
|
||||
}
|
||||
|
||||
public function applyClientPrediction() {
|
||||
// First acknowledge the marble's last move so we can get that over with
|
||||
var ourLastMove = lastMoves[Net.clientId];
|
||||
var ourLastMove = lastMoves.myMarbleUpdate;
|
||||
if (ourLastMove == null)
|
||||
return;
|
||||
var ackLag = -1;
|
||||
if (!ourLastMove.applied)
|
||||
if (!lastMoves.ourMoveApplied)
|
||||
ackLag = Net.clientConnection.moveManager.acknowledgeMove(ourLastMove.move.id);
|
||||
else
|
||||
return;
|
||||
|
||||
var ourLastMoveTime = ourLastMove.serverTicks;
|
||||
|
||||
// Then find the minimum tick from which we need to begin our predictions from
|
||||
var tickStart = timeState.ticks;
|
||||
var ourQueuedMoves = @:privateAccess Net.clientConnection.moveManager.queuedMoves.copy();
|
||||
if (ourQueuedMoves.length > 0 && ourQueuedMoves[0].timeState.ticks < tickStart)
|
||||
tickStart = ourQueuedMoves[0].timeState.ticks;
|
||||
|
||||
var advanceTimeState = timeState.clone();
|
||||
advanceTimeState.dt = 0.032;
|
||||
/*
|
||||
for (client => lastMove in lastMoves) {
|
||||
if (lastMove.applied)
|
||||
continue;
|
||||
if (lastMove.serverTicks < tickStart)
|
||||
tickStart = lastMove.serverTicks;
|
||||
}
|
||||
|
||||
// Now actually do the sim, tick by tick
|
||||
for (tick in tickStart...timeState.ticks) {
|
||||
for (client => lastMove in lastMoves) {
|
||||
if (lastMove.applied || (tick < lastMove.serverTicks && lastMove.clientId != Net.clientId))
|
||||
continue;
|
||||
|
||||
var marbleToUpdate = lastMove.clientId == Net.clientId ? marble : clientMarbles[Net.clientIdMap[client]];
|
||||
@:privateAccess marbleToUpdate.isNetUpdate = true;
|
||||
if (marbleToUpdate == marble) {
|
||||
if (ourQueuedMoves.length > 0) {
|
||||
if (ourQueuedMoves[0].timeState.ticks <= tick) {
|
||||
var move = ourQueuedMoves.shift();
|
||||
Debug.drawSphere(@:privateAccess marbleToUpdate.newPos, marbleToUpdate._radius);
|
||||
@:privateAccess marbleToUpdate.moveMotionDir = move.motionDir;
|
||||
@:privateAccess marbleToUpdate.advancePhysics(advanceTimeState, move.move, this.collisionWorld, this.pathedInteriors);
|
||||
}
|
||||
} else {
|
||||
lastMove.applied = true;
|
||||
}
|
||||
} else {
|
||||
var m = lastMove.move.move;
|
||||
Debug.drawSphere(@:privateAccess marbleToUpdate.newPos, marbleToUpdate._radius);
|
||||
@:privateAccess marbleToUpdate.moveMotionDir = lastMove.move.motionDir;
|
||||
@:privateAccess marbleToUpdate.advancePhysics(advanceTimeState, m, this.collisionWorld, this.pathedInteriors);
|
||||
}
|
||||
@:privateAccess marbleToUpdate.isNetUpdate = false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Tick the remaining moves (ours)
|
||||
if (!ourLastMove.applied) {
|
||||
if (!lastMoves.ourMoveApplied) {
|
||||
@:privateAccess this.marble.isNetUpdate = true;
|
||||
var totalTicksToDo = ourQueuedMoves.length;
|
||||
var endTick = ourLastMoveTime + totalTicksToDo;
|
||||
var currentTick = ourLastMoveTime;
|
||||
|
||||
var marblesToTick = new Map();
|
||||
|
||||
for (client => arr in lastMoves.otherMarbleUpdates) {
|
||||
if (arr.length > 0) {
|
||||
var m = arr[0];
|
||||
if (m.serverTicks <= ourLastMoveTime && m.serverTicks >= ourLastMove.collisionToken) {
|
||||
m.calculationTicks = Std.int(/*ourLastMoveTime - m.serverTicks + */ ourQueuedMoves.length);
|
||||
marblesToTick.set(client, m);
|
||||
arr.shift();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (move in ourQueuedMoves) {
|
||||
var m = move.move;
|
||||
Debug.drawSphere(@:privateAccess this.marble.newPos, this.marble._radius);
|
||||
@:privateAccess this.marble.moveMotionDir = move.motionDir;
|
||||
@:privateAccess this.marble.advancePhysics(advanceTimeState, m, this.collisionWorld, this.pathedInteriors);
|
||||
if (this.marble.collidingMarbles.length > 0)
|
||||
this.lastMoves.addCollisionFrame(currentTick);
|
||||
|
||||
// for (client => lastMove in lastMoves) {
|
||||
// if (lastMove.clientId == Net.clientId || lastMove.calculationTicks >= endTick)
|
||||
// continue;
|
||||
for (client => m in marblesToTick) {
|
||||
if (m.calculationTicks > 0) {
|
||||
var marbleToUpdate = clientMarbles[Net.clientIdMap[client]];
|
||||
|
||||
// trace('tick diff: ${lastMove.serverTicks - ourLastMoveTime}');
|
||||
Debug.drawSphere(@:privateAccess marbleToUpdate.newPos, marbleToUpdate._radius);
|
||||
|
||||
// lastMove.calculationTicks++;
|
||||
// // lastMove.serverTicks++;
|
||||
|
||||
// var marbleToUpdate = clientMarbles[Net.clientIdMap[client]];
|
||||
// @:privateAccess marbleToUpdate.isNetUpdate = true;
|
||||
// var m = lastMove.move.move;
|
||||
// @:privateAccess marbleToUpdate.moveMotionDir = lastMove.move.motionDir;
|
||||
// @:privateAccess marbleToUpdate.advancePhysics(advanceTimeState, m, this.collisionWorld, this.pathedInteriors);
|
||||
// @:privateAccess marbleToUpdate.isNetUpdate = false;
|
||||
// }
|
||||
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;
|
||||
if (marbleToUpdate.collidingMarbles.length > 0)
|
||||
this.lastMoves.addCollisionFrame(currentTick);
|
||||
m.calculationTicks--;
|
||||
}
|
||||
}
|
||||
currentTick++;
|
||||
}
|
||||
|
||||
for (client => lastMove in lastMoves) {
|
||||
if (lastMove.clientId == Net.clientId)
|
||||
continue;
|
||||
|
||||
// lastMove.calculationTicks++;
|
||||
// lastMove.serverTicks++;
|
||||
|
||||
var tickDiff = ackLag + 1; // - (lastMove.serverTicks - ourLastMoveTime) + 1;
|
||||
while (tickDiff > 0) {
|
||||
for (client => m in marblesToTick) {
|
||||
if (m.calculationTicks >= 0) {
|
||||
var marbleToUpdate = clientMarbles[Net.clientIdMap[client]];
|
||||
@:privateAccess marbleToUpdate.isNetUpdate = true;
|
||||
var m = lastMove.move.move;
|
||||
@:privateAccess marbleToUpdate.moveMotionDir = lastMove.move.motionDir;
|
||||
@:privateAccess marbleToUpdate.advancePhysics(advanceTimeState, m, this.collisionWorld, this.pathedInteriors);
|
||||
@:privateAccess marbleToUpdate.isNetUpdate = false;
|
||||
tickDiff--;
|
||||
|
||||
while (m.calculationTicks > 0) {
|
||||
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;
|
||||
if (marbleToUpdate.collidingMarbles.length > 0)
|
||||
this.lastMoves.addCollisionFrame(currentTick);
|
||||
m.calculationTicks--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if (ourQueuedMoves.length >= 2) {
|
||||
// trace('Move queue tick diff: ${ourQueuedMoves[ourQueuedMoves.length - 1].timeState.ticks - ourQueuedMoves[0].timeState.ticks}');
|
||||
// }
|
||||
ourLastMove.applied = true;
|
||||
lastMoves.ourMoveApplied = true;
|
||||
@:privateAccess this.marble.isNetUpdate = false;
|
||||
}
|
||||
|
||||
// for (client => lastMove in lastMoves) {
|
||||
// if (lastMove.applied)
|
||||
// continue;
|
||||
// if (lastMove.serverTicks > timeState.ticks) {
|
||||
// trace('Marble ticked ahead ${lastMove.serverTicks - timeState.ticks} ticks');
|
||||
// lastMove.serverTicks = timeState.ticks;
|
||||
// }
|
||||
// if (lastMove.serverTicks < tickStart)
|
||||
// tickStart = lastMove.serverTicks;
|
||||
// }
|
||||
|
||||
// for (tick in tickStart...timeState.ticks) {
|
||||
// for (client => lastMove in lastMoves) {
|
||||
// if (lastMove.applied || tick < lastMove.serverTicks)
|
||||
// continue;
|
||||
|
||||
// // if (lastMove.calculationTicks > 0) {
|
||||
// // lastMove.calculationTicks--;
|
||||
// // continue;
|
||||
// // }
|
||||
|
||||
// var marbleToUpdate = clientMarbles[Net.clientIdMap[client]];
|
||||
// @:privateAccess marbleToUpdate.isNetUpdate = true;
|
||||
// var m = lastMove.move.move;
|
||||
// Debug.drawSphere(@:privateAccess marbleToUpdate.newPos, marbleToUpdate._radius);
|
||||
// @:privateAccess marbleToUpdate.moveMotionDir = lastMove.move.motionDir;
|
||||
// @:privateAccess marbleToUpdate.advancePhysics(advanceTimeState, m, this.collisionWorld, this.pathedInteriors);
|
||||
// @:privateAccess marbleToUpdate.isNetUpdate = false;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Now mark them all as applied
|
||||
for (client => lastMove in lastMoves) {
|
||||
lastMove.applied = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function rollback(t:Float) {
|
||||
|
|
|
|||
36
src/net/MarbleUpdateQueue.hx
Normal file
36
src/net/MarbleUpdateQueue.hx
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
package net;
|
||||
|
||||
import net.NetPacket.MarbleUpdatePacket;
|
||||
import net.Net;
|
||||
|
||||
@:publicFields
|
||||
class MarbleUpdateQueue {
|
||||
var otherMarbleUpdates:Map<Int, Array<MarbleUpdatePacket>> = [];
|
||||
var myMarbleUpdate:MarbleUpdatePacket;
|
||||
var ourMoveApplied:Bool = false;
|
||||
var collisionFrame:Int;
|
||||
|
||||
public function new() {}
|
||||
|
||||
public function enqueue(update:MarbleUpdatePacket) {
|
||||
var cc = update.clientId;
|
||||
if (update.serverTicks < collisionFrame)
|
||||
return;
|
||||
if (cc != Net.clientId) {
|
||||
if (otherMarbleUpdates.exists(cc)) {
|
||||
otherMarbleUpdates[cc].push(update);
|
||||
} else {
|
||||
otherMarbleUpdates[cc] = [update];
|
||||
}
|
||||
} else {
|
||||
if (myMarbleUpdate == null || update.serverTicks > myMarbleUpdate.serverTicks) {
|
||||
myMarbleUpdate = update;
|
||||
ourMoveApplied = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addCollisionFrame(tick:Int) {
|
||||
collisionFrame = tick + 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ class MoveManager {
|
|||
var lastMove:NetMove;
|
||||
var lastAckMoveId:Int = -1;
|
||||
|
||||
static var maxMoves = 32;
|
||||
static var maxMoves = 45;
|
||||
|
||||
public function new(connection:ClientConnection) {
|
||||
queuedMoves = [];
|
||||
|
|
|
|||
|
|
@ -248,12 +248,7 @@ class Net {
|
|||
var cc = marbleUpdatePacket.clientId;
|
||||
if (MarbleGame.instance.world != null) {
|
||||
var m = MarbleGame.instance.world.lastMoves;
|
||||
if (m.exists(cc)) {
|
||||
if (m[cc].serverTicks < marbleUpdatePacket.serverTicks)
|
||||
m.set(cc, marbleUpdatePacket);
|
||||
} else {
|
||||
m.set(cc, marbleUpdatePacket);
|
||||
}
|
||||
m.enqueue(marbleUpdatePacket);
|
||||
}
|
||||
|
||||
case MarbleMove:
|
||||
|
|
|
|||
|
|
@ -34,11 +34,11 @@ class MarbleUpdatePacket implements NetPacket {
|
|||
var clientId:Int;
|
||||
var move:NetMove;
|
||||
var serverTicks:Int;
|
||||
var calculationTicks:Int;
|
||||
var calculationTicks:Int = -1;
|
||||
var position:Vector;
|
||||
var velocity:Vector;
|
||||
var omega:Vector;
|
||||
var applied:Bool = false;
|
||||
var collisionToken:Int;
|
||||
|
||||
public function new() {}
|
||||
|
||||
|
|
@ -46,6 +46,7 @@ class MarbleUpdatePacket implements NetPacket {
|
|||
b.writeUInt16(clientId);
|
||||
MoveManager.packMove(move, b);
|
||||
b.writeUInt16(serverTicks);
|
||||
b.writeUInt16(collisionToken);
|
||||
b.writeFloat(position.x);
|
||||
b.writeFloat(position.y);
|
||||
b.writeFloat(position.z);
|
||||
|
|
@ -61,7 +62,7 @@ class MarbleUpdatePacket implements NetPacket {
|
|||
clientId = b.readUInt16();
|
||||
move = MoveManager.unpackMove(b);
|
||||
serverTicks = b.readUInt16();
|
||||
calculationTicks = serverTicks;
|
||||
collisionToken = b.readUInt16();
|
||||
position = new Vector(b.readFloat(), b.readFloat(), b.readFloat());
|
||||
velocity = new Vector(b.readFloat(), b.readFloat(), b.readFloat());
|
||||
omega = new Vector(b.readFloat(), b.readFloat(), b.readFloat());
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue