attempt at something

This commit is contained in:
RandomityGuy 2024-01-29 00:15:09 +05:30
parent b1ec446360
commit 42ec5701e3
8 changed files with 137 additions and 151 deletions

View file

@ -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});
}
}

View file

@ -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) {

View file

@ -189,7 +189,7 @@ class MarbleGame {
world = null;
return;
}
Debug.update();
Debug.update(dt);
if (Util.isTouchDevice()) {
touchInput.update();
}

View file

@ -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) {

View 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;
}
}

View file

@ -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 = [];

View file

@ -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:

View file

@ -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());