mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-10-30 08:11:25 +00:00
kind of do powerups and use our own bitstream
This commit is contained in:
parent
3bf672df9a
commit
16dc9dc718
14 changed files with 180 additions and 69 deletions
|
|
@ -1,5 +1,6 @@
|
|||
package src;
|
||||
|
||||
import net.BitStream.OutputBitStream;
|
||||
import net.ClientConnection;
|
||||
import net.ClientConnection.GameConnection;
|
||||
import net.NetPacket.MarbleUpdatePacket;
|
||||
|
|
@ -577,7 +578,7 @@ class Marble extends GameObject {
|
|||
A = A.add(force.multiply(1 / mass));
|
||||
}
|
||||
for (marble in level.marbles) {
|
||||
if (marble != this) {
|
||||
if (marble != cast this) {
|
||||
var force = marble.getForce(this.collider.transform.getPosition(), tick);
|
||||
A = A.add(force.multiply(1 / mass));
|
||||
}
|
||||
|
|
@ -1608,7 +1609,7 @@ class Marble extends GameObject {
|
|||
var pTime = timeState.clone();
|
||||
pTime.dt = timeStep;
|
||||
pTime.currentAttemptTime = passedTime;
|
||||
this.heldPowerup.use(this, pTime);
|
||||
this.heldPowerup.use(cast this, pTime);
|
||||
this.heldPowerup = null;
|
||||
if (this.level.isRecording) {
|
||||
this.level.replay.recordPowerupPickup(null);
|
||||
|
|
@ -1655,7 +1656,7 @@ class Marble extends GameObject {
|
|||
// MP Only Functions
|
||||
|
||||
public function packUpdate(move:NetMove, timeState:TimeState) {
|
||||
var b = new haxe.io.BytesOutput();
|
||||
var b = new OutputBitStream();
|
||||
b.writeByte(NetPacketType.MarbleUpdate);
|
||||
var marbleUpdate = new MarbleUpdatePacket();
|
||||
marbleUpdate.clientId = connection != null ? connection.id : 0;
|
||||
|
|
@ -1670,6 +1671,7 @@ class Marble extends GameObject {
|
|||
marbleUpdate.heliTick = this.helicopterUseTick;
|
||||
marbleUpdate.megaTick = this.megaMarbleUseTick;
|
||||
marbleUpdate.oob = this.outOfBounds;
|
||||
marbleUpdate.powerUpId = this.heldPowerup != null ? this.heldPowerup.netIndex : 0xFFFF;
|
||||
marbleUpdate.serialize(b);
|
||||
return b.getBytes();
|
||||
}
|
||||
|
|
@ -1694,6 +1696,11 @@ class Marble extends GameObject {
|
|||
this.megaMarbleUseTick = p.megaTick;
|
||||
this.outOfBounds = p.oob;
|
||||
this.camera.oob = p.oob;
|
||||
if (p.powerUpId == 0xFFFF) {
|
||||
this.level.deselectPowerUp(cast this);
|
||||
} else {
|
||||
this.level.pickUpPowerUp(cast this, this.level.powerUps[p.powerUpId]);
|
||||
}
|
||||
if (this.controllable && Net.isClient) {
|
||||
// We are client, need to do something about the queue
|
||||
var mm = Net.clientConnection.moveManager;
|
||||
|
|
@ -1712,7 +1719,7 @@ class Marble extends GameObject {
|
|||
if (this.controllable && this.mode != Finish && !MarbleGame.instance.paused && !this.level.isWatching && !this.level.isReplayingMovement) {
|
||||
if (Net.isClient) {
|
||||
var axis = getMarbleAxis()[1];
|
||||
move = Net.clientConnection.moveManager.recordMove(this, axis, timeState);
|
||||
move = Net.clientConnection.moveManager.recordMove(cast this, axis, timeState);
|
||||
} else if (Net.isHost) {
|
||||
var axis = getMarbleAxis()[1];
|
||||
var innerMove = recordMove();
|
||||
|
|
@ -1763,6 +1770,11 @@ class Marble extends GameObject {
|
|||
}
|
||||
}
|
||||
|
||||
if (move.move.jump && this.outOfBounds) {
|
||||
this.level.cancel(this.oobSchedule);
|
||||
this.level.restart(cast this);
|
||||
}
|
||||
|
||||
return move;
|
||||
// if (Net.isHost) {
|
||||
// packets.push({b: packUpdate(move, timeState), c: this.connection != null ? this.connection.id : 0});
|
||||
|
|
@ -1770,7 +1782,7 @@ class Marble extends GameObject {
|
|||
}
|
||||
|
||||
public function updateClient(timeState:TimeState, pathedInteriors:Array<PathedInterior>) {
|
||||
this.level.updateBlast(this, timeState);
|
||||
this.level.updateBlast(cast this, timeState);
|
||||
if (oldPos != null && newPos != null) {
|
||||
var deltaT = physicsAccumulator / 0.032;
|
||||
var renderPos = Util.lerpThreeVectors(this.oldPos, this.newPos, deltaT);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package src;
|
||||
|
||||
import net.PowerupPredictionStore;
|
||||
import net.MarblePredictionStore;
|
||||
import net.MarblePredictionStore.MarblePrediction;
|
||||
import net.MarbleUpdateQueue;
|
||||
|
|
@ -208,6 +209,7 @@ class MarbleWorld extends Scheduler {
|
|||
|
||||
var clientMarbles:Map<GameConnection, Marble> = [];
|
||||
var predictions:MarblePredictionStore;
|
||||
var powerupPredictions:PowerupPredictionStore;
|
||||
|
||||
public var lastMoves:MarbleUpdateQueue;
|
||||
|
||||
|
|
@ -239,17 +241,18 @@ class MarbleWorld extends Scheduler {
|
|||
this.scene2d = scene2d;
|
||||
this.mission = mission;
|
||||
this.game = mission.game.toLowerCase();
|
||||
this.gameMode = GameModeFactory.getGameMode(this, mission.missionInfo.gamemode);
|
||||
this.gameMode = GameModeFactory.getGameMode(cast this, mission.missionInfo.gamemode);
|
||||
this.replay = new Replay(mission.path, mission.isClaMission ? mission.id : 0);
|
||||
this.isRecording = record;
|
||||
this.rewindManager = new RewindManager(this);
|
||||
this.inputRecorder = new InputRecorder(this);
|
||||
this.rewindManager = new RewindManager(cast this);
|
||||
this.inputRecorder = new InputRecorder(cast this);
|
||||
this.isMultiplayer = multiplayer;
|
||||
if (this.isMultiplayer) {
|
||||
isRecording = false;
|
||||
isWatching = false;
|
||||
lastMoves = new MarbleUpdateQueue();
|
||||
predictions = new MarblePredictionStore();
|
||||
powerupPredictions = new PowerupPredictionStore();
|
||||
}
|
||||
|
||||
// Set the network RNG for hunt
|
||||
|
|
@ -345,7 +348,7 @@ class MarbleWorld extends Scheduler {
|
|||
this.playGui = new PlayGui();
|
||||
this.instanceManager = new InstanceManager(scene);
|
||||
this.particleManager = new ParticleManager(cast this);
|
||||
this.radar = new Radar(this, this.scene2d);
|
||||
this.radar = new Radar(cast this, this.scene2d);
|
||||
radar.init();
|
||||
|
||||
var worker = new ResourceLoaderWorker(() -> {
|
||||
|
|
@ -955,8 +958,13 @@ class MarbleWorld extends Scheduler {
|
|||
var worker = new ResourceLoaderWorker(() -> {
|
||||
obj.idInLevel = this.dtsObjects.length; // Set the id of the thing
|
||||
this.dtsObjects.push(obj);
|
||||
if (obj is PowerUp)
|
||||
if (obj is PowerUp) {
|
||||
var pw:PowerUp = cast obj;
|
||||
pw.netIndex = this.powerUps.length;
|
||||
this.powerUps.push(cast obj);
|
||||
if (Net.isClient)
|
||||
powerupPredictions.alloc();
|
||||
}
|
||||
if (obj is ForceObject) {
|
||||
this.forceObjects.push(cast obj);
|
||||
}
|
||||
|
|
@ -1142,13 +1150,16 @@ class MarbleWorld extends Scheduler {
|
|||
advanceTimeState.dt = 0.032;
|
||||
advanceTimeState.ticks = ourLastMoveTime;
|
||||
|
||||
if (marbleNeedsPrediction & (1 << Net.clientId) > 0) {
|
||||
if (qm != null) {
|
||||
var mvs = qm.powerupStates.copy();
|
||||
for (pw in marble.level.powerUps) {
|
||||
pw.lastPickUpTime = mvs.shift();
|
||||
}
|
||||
if (marbleNeedsPrediction > 0) {
|
||||
// if (qm != null) {
|
||||
// var mvs = qm.powerupStates.copy();
|
||||
for (pw in marble.level.powerUps) {
|
||||
// var val = mvs.shift();
|
||||
// if (pw.lastPickUpTime != val)
|
||||
// Console.log('Revert powerup pickup: ${pw.lastPickUpTime} -> ${val}');
|
||||
pw.lastPickUpTime = powerupPredictions.getState(pw.netIndex);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
ackLag = ourQueuedMoves.length;
|
||||
|
|
@ -1189,7 +1200,6 @@ class MarbleWorld extends Scheduler {
|
|||
var m = move.move;
|
||||
// Debug.drawSphere(@:privateAccess this.marble.newPos, this.marble._radius);
|
||||
if (marbleNeedsPrediction & (1 << Net.clientId) > 0) {
|
||||
this.marble.heldPowerup = move.powerup;
|
||||
@:privateAccess this.marble.moveMotionDir = move.motionDir;
|
||||
@:privateAccess this.marble.advancePhysics(advanceTimeState, m, this.collisionWorld, this.pathedInteriors);
|
||||
this.predictions.storeState(this.marble, move.timeState.ticks);
|
||||
|
|
@ -1476,12 +1486,14 @@ class MarbleWorld extends Scheduler {
|
|||
ProfilerUI.measure("updateAudio");
|
||||
AudioManager.update(this.scene);
|
||||
|
||||
if (this.marble.outOfBounds
|
||||
&& this.finishTime == null
|
||||
&& (Key.isDown(Settings.controlsSettings.jump) || Gamepad.isDown(Settings.gamepadSettings.jump))
|
||||
&& !this.isWatching) {
|
||||
this.restart(this.marble);
|
||||
return;
|
||||
if (!this.isMultiplayer) {
|
||||
if (this.marble.outOfBounds
|
||||
&& this.finishTime == null
|
||||
&& (Key.isDown(Settings.controlsSettings.jump) || Gamepad.isDown(Settings.gamepadSettings.jump))
|
||||
&& !this.isWatching) {
|
||||
this.restart(this.marble);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.isWatching) {
|
||||
|
|
@ -1690,8 +1702,8 @@ class MarbleWorld extends Scheduler {
|
|||
this.helpTextTimeState = this.timeState.timeSinceLoad;
|
||||
}
|
||||
|
||||
public function pickUpGem(gem:Gem) {
|
||||
this.gameMode.onGemPickup(gem);
|
||||
public function pickUpGem(marble:Marble, gem:Gem) {
|
||||
this.gameMode.onGemPickup(marble, gem);
|
||||
}
|
||||
|
||||
public function callCollisionHandlers(marble:Marble, timeState:TimeState, start:Vector, end:Vector) {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ interface GameMode {
|
|||
public function onTimeExpire():Void;
|
||||
public function onRestart():Void;
|
||||
public function onRespawn(marble:Marble):Void;
|
||||
public function onGemPickup(gem:Gem):Void;
|
||||
public function onGemPickup(marble:Marble, gem:Gem):Void;
|
||||
|
||||
public function getPreloadFiles():Array<String>;
|
||||
public function constructRewindState():RewindableState;
|
||||
|
|
|
|||
|
|
@ -282,25 +282,32 @@ class HuntMode extends NullMode {
|
|||
@:privateAccess level.playGui.formatGemHuntCounter(points);
|
||||
}
|
||||
|
||||
override function onGemPickup(gem:Gem) {
|
||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/gem_collect.wav', ResourceLoader.getAudio, @:privateAccess this.level.soundResources));
|
||||
override function onGemPickup(marble:Marble, gem:Gem) {
|
||||
if (marble == level.marble)
|
||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/gem_collect.wav', ResourceLoader.getAudio,
|
||||
@:privateAccess this.level.soundResources));
|
||||
else
|
||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/opponent_gem_collect.wav', ResourceLoader.getAudio,
|
||||
@:privateAccess this.level.soundResources));
|
||||
activeGems.remove(gem);
|
||||
var beam = gemToBeamMap.get(gem);
|
||||
beam.setHide(true);
|
||||
refillGemGroups();
|
||||
|
||||
switch (gem.gemColor) {
|
||||
case "red.gem":
|
||||
points += 1;
|
||||
@:privateAccess level.playGui.addMiddleMessage('+1', 0xFF6666);
|
||||
case "yellow.gem":
|
||||
points += 2;
|
||||
@:privateAccess level.playGui.addMiddleMessage('+2', 0xFFFF66);
|
||||
case "blue.gem":
|
||||
points += 5;
|
||||
@:privateAccess level.playGui.addMiddleMessage('+5', 0x6666FF);
|
||||
if (marble == level.marble) {
|
||||
switch (gem.gemColor) {
|
||||
case "red.gem":
|
||||
points += 1;
|
||||
@:privateAccess level.playGui.addMiddleMessage('+1', 0xFF6666);
|
||||
case "yellow.gem":
|
||||
points += 2;
|
||||
@:privateAccess level.playGui.addMiddleMessage('+2', 0xFFFF66);
|
||||
case "blue.gem":
|
||||
points += 5;
|
||||
@:privateAccess level.playGui.addMiddleMessage('+5', 0x6666FF);
|
||||
}
|
||||
@:privateAccess level.playGui.formatGemHuntCounter(points);
|
||||
}
|
||||
@:privateAccess level.playGui.formatGemHuntCounter(points);
|
||||
}
|
||||
|
||||
function setupGems() {
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class NullMode implements GameMode {
|
|||
|
||||
public function onRespawn(marble:Marble) {}
|
||||
|
||||
public function onGemPickup(gem:Gem) {
|
||||
public function onGemPickup(marble:Marble, gem:Gem) {
|
||||
this.level.gemCount++;
|
||||
var string:String;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package net;
|
||||
|
||||
import haxe.io.FPHelper;
|
||||
import haxe.io.BytesOutput;
|
||||
import haxe.io.BytesInput;
|
||||
import haxe.io.Bytes;
|
||||
|
|
@ -64,7 +65,7 @@ class InputBitStream {
|
|||
}
|
||||
|
||||
public function readFloat() {
|
||||
return readInt32();
|
||||
return FPHelper.i32ToFloat(readInt32());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -129,4 +130,8 @@ class OutputBitStream {
|
|||
this.data.writeByte(this.lastByte);
|
||||
return this.data.getBytes();
|
||||
}
|
||||
|
||||
public function writeFloat(value:Float) {
|
||||
writeInt(FPHelper.floatToI32(value), 32);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ class MarblePrediction {
|
|||
var omega:Vector;
|
||||
var isControl:Bool;
|
||||
var blastAmount:Int;
|
||||
var powerupItemId:Int;
|
||||
|
||||
public function new(marble:Marble, tick:Int) {
|
||||
this.tick = tick;
|
||||
|
|
@ -22,11 +23,14 @@ class MarblePrediction {
|
|||
omega = @:privateAccess marble.omega.clone();
|
||||
blastAmount = @:privateAccess marble.blastTicks;
|
||||
isControl = @:privateAccess marble.controllable;
|
||||
powerupItemId = marble.heldPowerup != null ? marble.heldPowerup.netIndex : 0xFFFF;
|
||||
}
|
||||
|
||||
public inline function getError(p:MarbleUpdatePacket) {
|
||||
// Just doing position errors is enough to make it work
|
||||
var subs = position.sub(p.position).lengthSq(); // + velocity.sub(p.velocity).lengthSq() + omega.sub(p.omega).lengthSq();
|
||||
if (p.powerUpId != powerupItemId)
|
||||
subs += 1;
|
||||
// if (isControl)
|
||||
// subs += Math.abs(blastAmount - p.blastAmount);
|
||||
return subs;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package net;
|
||||
|
||||
import net.BitStream.OutputBitStream;
|
||||
import net.BitStream.InputBitStream;
|
||||
import net.NetPacket.MarbleUpdatePacket;
|
||||
import shapes.PowerUp;
|
||||
import net.NetPacket.MarbleMovePacket;
|
||||
|
|
@ -23,9 +25,6 @@ class NetMove {
|
|||
var move:Move;
|
||||
var id:Int;
|
||||
var timeState:TimeState;
|
||||
// For rewind purposes
|
||||
var powerup:PowerUp;
|
||||
var powerupStates:Array<Float>;
|
||||
|
||||
public function new(move:Move, motionDir:Vector, timeState:TimeState, id:Int) {
|
||||
this.move = move;
|
||||
|
|
@ -96,17 +95,12 @@ class MoveManager {
|
|||
}
|
||||
|
||||
var netMove = new NetMove(move, motionDir, timeState.clone(), nextMoveId++);
|
||||
netMove.powerup = marble.heldPowerup;
|
||||
netMove.powerupStates = [];
|
||||
for (pw in marble.level.powerUps) {
|
||||
netMove.powerupStates.push(pw.lastPickUpTime);
|
||||
}
|
||||
queuedMoves.push(netMove);
|
||||
|
||||
if (nextMoveId >= 65535) // 65535 is reserved for null move
|
||||
nextMoveId = 0;
|
||||
|
||||
var b = new haxe.io.BytesOutput();
|
||||
var b = new OutputBitStream();
|
||||
var movePacket = new MarbleMovePacket();
|
||||
movePacket.clientId = Net.clientId;
|
||||
movePacket.move = netMove;
|
||||
|
|
@ -119,7 +113,7 @@ class MoveManager {
|
|||
return netMove;
|
||||
}
|
||||
|
||||
public static inline function packMove(m:NetMove, b:haxe.io.BytesOutput) {
|
||||
public static inline function packMove(m:NetMove, b:OutputBitStream) {
|
||||
b.writeUInt16(m.id);
|
||||
b.writeByte(Std.int((m.move.d.x * 16) + 16));
|
||||
b.writeByte(Std.int((m.move.d.y * 16) + 16));
|
||||
|
|
@ -137,7 +131,7 @@ class MoveManager {
|
|||
return b;
|
||||
}
|
||||
|
||||
public static inline function unpackMove(b:haxe.io.BytesInput) {
|
||||
public static inline function unpackMove(b:InputBitStream) {
|
||||
var moveId = b.readUInt16();
|
||||
var move = new Move();
|
||||
move.d = new Vector();
|
||||
|
|
@ -155,7 +149,7 @@ class MoveManager {
|
|||
return netMove;
|
||||
}
|
||||
|
||||
public function queueMove(m:NetMove) {
|
||||
public inline function queueMove(m:NetMove) {
|
||||
queuedMoves.push(m);
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +163,7 @@ class MoveManager {
|
|||
}
|
||||
}
|
||||
|
||||
public function getQueueSize() {
|
||||
public inline function getQueueSize() {
|
||||
return queuedMoves.length;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
package net;
|
||||
|
||||
import net.BitStream.InputBitStream;
|
||||
import net.BitStream.OutputBitStream;
|
||||
import net.NetPacket.PowerupPickupPacket;
|
||||
import net.ClientConnection;
|
||||
import net.NetPacket.MarbleUpdatePacket;
|
||||
import net.NetPacket.MarbleMovePacket;
|
||||
|
|
@ -20,6 +23,7 @@ enum abstract NetPacketType(Int) from Int to Int {
|
|||
var PingBack;
|
||||
var MarbleUpdate;
|
||||
var MarbleMove;
|
||||
var PowerupPickup;
|
||||
var PlayerInfo;
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +145,7 @@ class Net {
|
|||
haxe.Timer.delay(() -> connectedCb(), 1500); // 1.5 second delay to do the RTT calculation
|
||||
}
|
||||
clientDatachannel.onMessage = (b) -> {
|
||||
onPacketReceived(client, clientDatachannel, new haxe.io.BytesInput(b));
|
||||
onPacketReceived(client, clientDatachannel, new InputBitStream(b));
|
||||
}
|
||||
|
||||
isMP = true;
|
||||
|
|
@ -155,7 +159,7 @@ class Net {
|
|||
clients.set(c, new ClientConnection(clientId, c, dc));
|
||||
clientIdMap[clientId] = clients[c];
|
||||
dc.onMessage = (msgBytes) -> {
|
||||
onPacketReceived(c, dc, new haxe.io.BytesInput(msgBytes));
|
||||
onPacketReceived(c, dc, new InputBitStream(msgBytes));
|
||||
}
|
||||
var b = haxe.io.Bytes.alloc(3);
|
||||
b.set(0, ClientIdAssign);
|
||||
|
|
@ -194,7 +198,7 @@ class Net {
|
|||
return b.getBytes();
|
||||
}
|
||||
|
||||
static function onPacketReceived(c:RTCPeerConnection, dc:RTCDataChannel, input:haxe.io.BytesInput) {
|
||||
static function onPacketReceived(c:RTCPeerConnection, dc:RTCDataChannel, input:InputBitStream) {
|
||||
var packetType = input.readByte();
|
||||
switch (packetType) {
|
||||
case NetCommand:
|
||||
|
|
@ -250,6 +254,14 @@ class Net {
|
|||
var cc = clientIdMap[movePacket.clientId];
|
||||
cc.moveManager.queueMove(movePacket.move);
|
||||
|
||||
case PowerupPickup:
|
||||
var powerupPickupPacket = new PowerupPickupPacket();
|
||||
powerupPickupPacket.deserialize(input);
|
||||
if (MarbleGame.instance.world != null) {
|
||||
var m = @:privateAccess MarbleGame.instance.world.powerupPredictions;
|
||||
m.acknowledgePowerupPickup(powerupPickupPacket, MarbleGame.instance.world.timeState, clientConnection.moveManager.getQueueSize());
|
||||
}
|
||||
|
||||
case PlayerInfo:
|
||||
var count = input.readByte();
|
||||
for (i in 0...count) {
|
||||
|
|
@ -265,14 +277,14 @@ class Net {
|
|||
}
|
||||
}
|
||||
|
||||
public static function sendPacketToAll(packetData:haxe.io.BytesOutput) {
|
||||
public static function sendPacketToAll(packetData:OutputBitStream) {
|
||||
var bytes = packetData.getBytes();
|
||||
for (c => v in clients) {
|
||||
v.sendBytes(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
public static function sendPacketToHost(packetData:haxe.io.BytesOutput) {
|
||||
public static function sendPacketToHost(packetData:OutputBitStream) {
|
||||
var bytes = packetData.getBytes();
|
||||
clientDatachannel.sendBytes(bytes);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
package net;
|
||||
|
||||
import net.BitStream.InputBitStream;
|
||||
import net.BitStream.OutputBitStream;
|
||||
import h3d.Vector;
|
||||
import net.MoveManager.NetMove;
|
||||
|
||||
interface NetPacket {
|
||||
public function serialize(b:haxe.io.BytesOutput):Void;
|
||||
public function deserialize(b:haxe.io.BytesInput):Void;
|
||||
public function serialize(b:OutputBitStream):Void;
|
||||
public function deserialize(b:InputBitStream):Void;
|
||||
}
|
||||
|
||||
@:publicFields
|
||||
|
|
@ -16,13 +18,13 @@ class MarbleMovePacket implements NetPacket {
|
|||
|
||||
public function new() {}
|
||||
|
||||
public inline function deserialize(b:haxe.io.BytesInput) {
|
||||
public inline function deserialize(b:InputBitStream) {
|
||||
clientId = b.readUInt16();
|
||||
clientTicks = b.readUInt16();
|
||||
move = MoveManager.unpackMove(b);
|
||||
}
|
||||
|
||||
public inline function serialize(b:haxe.io.BytesOutput) {
|
||||
public inline function serialize(b:OutputBitStream) {
|
||||
b.writeUInt16(clientId);
|
||||
b.writeUInt16(clientTicks);
|
||||
MoveManager.packMove(move, b);
|
||||
|
|
@ -43,11 +45,12 @@ class MarbleUpdatePacket implements NetPacket {
|
|||
var megaTick:Int;
|
||||
var heliTick:Int;
|
||||
var oob:Bool;
|
||||
var powerUpId:Int;
|
||||
var moveQueueSize:Int;
|
||||
|
||||
public function new() {}
|
||||
|
||||
public inline function serialize(b:haxe.io.BytesOutput) {
|
||||
public inline function serialize(b:OutputBitStream) {
|
||||
b.writeUInt16(clientId);
|
||||
MoveManager.packMove(move, b);
|
||||
b.writeUInt16(serverTicks);
|
||||
|
|
@ -66,9 +69,10 @@ class MarbleUpdatePacket implements NetPacket {
|
|||
b.writeUInt16(heliTick);
|
||||
b.writeUInt16(megaTick);
|
||||
b.writeByte(oob ? 1 : 0);
|
||||
b.writeUInt16(powerUpId);
|
||||
}
|
||||
|
||||
public inline function deserialize(b:haxe.io.BytesInput) {
|
||||
public inline function deserialize(b:InputBitStream) {
|
||||
clientId = b.readUInt16();
|
||||
move = MoveManager.unpackMove(b);
|
||||
serverTicks = b.readUInt16();
|
||||
|
|
@ -81,5 +85,27 @@ class MarbleUpdatePacket implements NetPacket {
|
|||
heliTick = b.readUInt16();
|
||||
megaTick = b.readUInt16();
|
||||
oob = b.readByte() != 0;
|
||||
powerUpId = b.readUInt16();
|
||||
}
|
||||
}
|
||||
|
||||
@:publicFields
|
||||
class PowerupPickupPacket implements NetPacket {
|
||||
var clientId:Int;
|
||||
var serverTicks:Int;
|
||||
var powerupItemId:Int;
|
||||
|
||||
public function new() {}
|
||||
|
||||
public inline function deserialize(b:InputBitStream) {
|
||||
clientId = b.readUInt16();
|
||||
serverTicks = b.readUInt16();
|
||||
powerupItemId = b.readUInt16();
|
||||
}
|
||||
|
||||
public inline function serialize(b:OutputBitStream) {
|
||||
b.writeUInt16(clientId);
|
||||
b.writeUInt16(serverTicks);
|
||||
b.writeUInt16(powerupItemId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
24
src/net/PowerupPredictionStore.hx
Normal file
24
src/net/PowerupPredictionStore.hx
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package net;
|
||||
|
||||
import src.TimeState;
|
||||
import net.NetPacket.PowerupPickupPacket;
|
||||
|
||||
class PowerupPredictionStore {
|
||||
var predictions:Array<Float>;
|
||||
|
||||
public function new() {
|
||||
predictions = [];
|
||||
}
|
||||
|
||||
public function alloc() {
|
||||
predictions.push(Math.NEGATIVE_INFINITY);
|
||||
}
|
||||
|
||||
public inline function getState(netIndex:Int) {
|
||||
return predictions[netIndex];
|
||||
}
|
||||
|
||||
public function acknowledgePowerupPickup(packet:PowerupPickupPacket, timeState:TimeState, futureTicks:Int) {
|
||||
predictions[packet.powerupItemId] = timeState.currentAttemptTime - futureTicks * 0.032; // Approximate
|
||||
}
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ class RPCMacro {
|
|||
case EConst(CIdent("server")):
|
||||
var lastExpr = macro {
|
||||
if (Net.isHost) {
|
||||
var stream = new haxe.io.BytesOutput();
|
||||
var stream = new net.BitStream.OutputBitStream();
|
||||
stream.writeByte(NetPacketType.NetCommand);
|
||||
stream.writeByte($v{rpcFnId});
|
||||
$b{serializeFns};
|
||||
|
|
@ -72,7 +72,7 @@ class RPCMacro {
|
|||
case EConst(CIdent("client")):
|
||||
var lastExpr = macro {
|
||||
if (!Net.isHost) {
|
||||
var stream = new haxe.io.BytesOutput();
|
||||
var stream = new net.BitStream.OutputBitStream();
|
||||
stream.writeByte(NetPacketType.NetCommand);
|
||||
stream.writeByte($v{rpcFnId});
|
||||
$b{serializeFns};
|
||||
|
|
@ -113,7 +113,7 @@ class RPCMacro {
|
|||
args: [
|
||||
{
|
||||
name: "stream",
|
||||
type: haxe.macro.TypeTools.toComplexType(Context.getType('haxe.io.Input'))
|
||||
type: haxe.macro.TypeTools.toComplexType(Context.getType('net.BitStream.InputBitStream'))
|
||||
}
|
||||
],
|
||||
expr: macro {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class Gem extends DtsObject {
|
|||
return;
|
||||
this.pickedUp = true;
|
||||
this.setOpacity(0); // Hide the gem
|
||||
this.level.pickUpGem(this);
|
||||
this.level.pickUpGem(marble, this);
|
||||
// this.level.replay.recordMarbleInside(this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
package shapes;
|
||||
|
||||
import net.BitStream.OutputBitStream;
|
||||
import net.NetPacket.PowerupPickupPacket;
|
||||
import net.Net;
|
||||
import src.Marble;
|
||||
import src.AudioManager;
|
||||
import hxd.res.Sound;
|
||||
|
|
@ -16,6 +19,7 @@ abstract class PowerUp extends DtsObject {
|
|||
public var pickUpName:String;
|
||||
public var element:MissionElementItem;
|
||||
public var pickupSound:Sound;
|
||||
public var netIndex:Int;
|
||||
|
||||
var customPickupMessage:String = null;
|
||||
|
||||
|
|
@ -35,6 +39,17 @@ abstract class PowerUp extends DtsObject {
|
|||
if (this.pickUp(marble)) {
|
||||
// this.level.replay.recordMarbleInside(this);
|
||||
|
||||
if (level.isMultiplayer && Net.isHost) {
|
||||
var b = new OutputBitStream();
|
||||
b.writeByte(NetPacketType.PowerupPickup);
|
||||
var pickupPacket = new PowerupPickupPacket();
|
||||
pickupPacket.clientId = @:privateAccess marble.connection != null ? @:privateAccess marble.connection.id : 0;
|
||||
pickupPacket.serverTicks = timeState.ticks;
|
||||
pickupPacket.powerupItemId = this.netIndex;
|
||||
pickupPacket.serialize(b);
|
||||
Net.sendPacketToAll(b);
|
||||
}
|
||||
|
||||
this.lastPickUpTime = timeState.currentAttemptTime;
|
||||
if (this.autoUse)
|
||||
this.use(marble, timeState);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue