gems and player list

This commit is contained in:
RandomityGuy 2024-02-29 00:58:21 +05:30
parent 17e77c7096
commit ff5f6e1a9b
14 changed files with 460 additions and 59 deletions

View file

@ -2163,9 +2163,9 @@ class Marble extends GameObject {
this.blastPerc = amount;
var impulse = this.currentUp.multiply(amount * 8);
this.applyImpulse(impulse);
if (this.controllable)
AudioManager.playSound(ResourceLoader.getResource('data/sound/use_blast.wav', ResourceLoader.getAudio, this.soundResources));
if (!this.isNetUpdate) {
if (this.controllable)
AudioManager.playSound(ResourceLoader.getResource('data/sound/use_blast.wav', ResourceLoader.getAudio, this.soundResources));
this.blastWave.doSequenceOnceBeginTime = this.level.timeState.timeSinceLoad;
this.blastUseTime = this.level.timeState.currentAttemptTime;
}

View file

@ -1,5 +1,7 @@
package src;
import net.GemPredictionStore;
import modes.HuntMode;
import net.NetPacket.MarbleNetFlags;
import net.PowerupPredictionStore;
import net.MarblePredictionStore;
@ -211,6 +213,7 @@ class MarbleWorld extends Scheduler {
var clientMarbles:Map<GameConnection, Marble> = [];
var predictions:MarblePredictionStore;
var powerupPredictions:PowerupPredictionStore;
var gemPredictions:GemPredictionStore;
public var lastMoves:MarbleUpdateQueue;
@ -254,6 +257,7 @@ class MarbleWorld extends Scheduler {
lastMoves = new MarbleUpdateQueue();
predictions = new MarblePredictionStore();
powerupPredictions = new PowerupPredictionStore();
gemPredictions = new GemPredictionStore();
}
// Set the network RNG for hunt
@ -333,6 +337,19 @@ class MarbleWorld extends Scheduler {
this.collisionWorld.finalizeStaticGeometry();
this.playGui.init(this.scene2d, this.mission.game.toLowerCase());
this.scene.addChild(this.sky);
if (this.isMultiplayer) {
// Add us
if (Net.isHost) {
this.playGui.addPlayer(0, 'Player 0', true);
} else {
this.playGui.addPlayer(Net.clientId, 'Player ${Net.clientId}', true);
}
for (client in Net.clientIdMap) {
this.playGui.addPlayer(client.id, 'Player ${client.id}', false);
}
}
this._ready = true;
// AudioManager.playShell();
MarbleGame.canvas.clearContent();
@ -1160,6 +1177,10 @@ class MarbleWorld extends Scheduler {
// Console.log('Revert powerup pickup: ${pw.lastPickUpTime} -> ${val}');
pw.lastPickUpTime = powerupPredictions.getState(pw.netIndex);
}
var huntMode:HuntMode = cast this.gameMode;
for (activeGem in @:privateAccess huntMode.activeGemSpawnGroup) {
huntMode.setGemHiddenStatus(activeGem, gemPredictions.getState(activeGem));
}
// }
}
@ -1182,10 +1203,10 @@ class MarbleWorld extends Scheduler {
Debug.drawSphere(@:privateAccess marbleToUpdate.newPos, marbleToUpdate._radius);
var distFromUs = @:privateAccess marbleToUpdate.newPos.distance(this.marble.newPos);
if (distFromUs < 5)
m.calculationTicks = ourQueuedMoves.length; // ourQueuedMoves.length;
else
m.calculationTicks = Std.int(Math.max(1, ourQueuedMoves.length - (distFromUs - 5) / 3));
// if (distFromUs < 5)
m.calculationTicks = ourQueuedMoves.length; // ourQueuedMoves.length;
// else
// m.calculationTicks = Std.int(Math.max(1, ourQueuedMoves.length - (distFromUs - 5) / 3));
// - Std.int((@:privateAccess Net.clientConnection.moveManager.ackRTT - ourLastMove.moveQueueSize) / 2);
marblesToTick.set(client, m);
@ -1233,6 +1254,14 @@ class MarbleWorld extends Scheduler {
return -1;
}
public function spawnHuntGemsClientSide(gemIds:Array<Int>) {
if (this.isMultiplayer && Net.isClient) {
var huntMode:HuntMode = cast this.gameMode;
huntMode.setActiveSpawnSphere(gemIds);
radar.blink();
}
}
public function rollback(t:Float) {
var newT = timeState.currentAttemptTime - t;
var rewindFrame = rewindManager.getNextRewindFrame(timeState.currentAttemptTime - t);

View file

@ -342,6 +342,13 @@ class Util {
'${(hours > 0 ? (hoursTen > 0 ? '${hoursTen}' : '') +'${hoursOne}' + ':' : '')}${minutesTen}${minutesOne}:${secondsTen}${secondsOne}.${hundredthTen}${hundredthOne}${thousandth}';
}
public static function rightPad(str:String, len:Int, cutOff:Int) {
str = str.substring(0, len - cutOff);
while (str.length < len)
str += " ";
return str;
}
public static function getKeyForButton(button:Int) {
var keyName = Key.getKeyName(button);
if (keyName == "MouseLeft")

View file

@ -1,5 +1,6 @@
package gui;
import h2d.filter.Filter;
import h2d.HtmlText;
import h2d.Flow;
import h3d.Engine;
@ -33,14 +34,17 @@ class GuiMLTextListCtrl extends GuiControl {
public var scrollable:Bool = false;
var filter:Filter = null;
var flow:Flow;
var _imageLoader:String->Tile;
public function new(font:Font, texts:Array<String>, imageLoader:String->Tile) {
public function new(font:Font, texts:Array<String>, imageLoader:String->Tile, ?filter:Filter = null) {
super();
this.font = font;
this.texts = texts;
this.textObjs = [];
this.filter = filter;
this._imageLoader = imageLoader;
for (text in texts) {
var tobj = new HtmlText(font);
@ -48,6 +52,8 @@ class GuiMLTextListCtrl extends GuiControl {
tobj.loadImage = imageLoader;
tobj.text = text;
tobj.textColor = 0;
if (filter != null)
tobj.filter = filter;
textObjs.push(tobj);
}
this.g = new Graphics();
@ -65,6 +71,8 @@ class GuiMLTextListCtrl extends GuiControl {
tobj.lineHeightMode = TextOnly;
tobj.text = text;
tobj.textColor = 0;
if (filter != null)
tobj.filter = filter;
textObjs.push(tobj);
if (this.scrollable) {

View file

@ -25,6 +25,7 @@ class GuiTextListCtrl extends GuiControl {
public var selectedColor:Int = 0x206464;
public var selectedFillColor:Int = 0xC8C8C8;
public var textColor:Int = 0;
public var textYOffset:Int = 0;
@ -34,15 +35,16 @@ class GuiTextListCtrl extends GuiControl {
var flow:Flow;
public function new(font:Font, texts:Array<String>) {
public function new(font:Font, texts:Array<String>, textColor:Int = 0) {
super();
this.font = font;
this.texts = texts;
this.textObjs = [];
this.textColor = textColor;
for (text in texts) {
var tobj = new Text(font);
tobj.text = text;
tobj.textColor = 0;
tobj.textColor = textColor;
textObjs.push(tobj);
}
this.g = new Graphics();
@ -57,7 +59,7 @@ class GuiTextListCtrl extends GuiControl {
for (text in texts) {
var tobj = new Text(font);
tobj.text = text;
tobj.textColor = 0;
tobj.textColor = textColor;
textObjs.push(tobj);
if (this.scrollable) {
@ -178,7 +180,7 @@ class GuiTextListCtrl extends GuiControl {
for (i in 0...textObjs.length) {
var selected = i == hoverIndex || i == this._prevSelected;
var text = textObjs[i];
text.textColor = selected ? selectedColor : 0;
text.textColor = selected ? selectedColor : textColor;
// fill color = 0xC8C8C8
}
// obviously in renderRect
@ -189,7 +191,7 @@ class GuiTextListCtrl extends GuiControl {
if (i == this._prevSelected)
continue;
var text = textObjs[i];
text.textColor = 0;
text.textColor = textColor;
// fill color = 0xC8C8C8
}
}

View file

@ -38,6 +38,13 @@ typedef MiddleMessage = {
yPos:Float
}
typedef PlayerInfo = {
id:Int,
name:String,
us:Bool,
score:Int
}
class PlayGui {
var scene2d:h2d.Scene;
@ -64,6 +71,12 @@ class PlayGui {
var blastFillUltra:GuiImage;
var blastFrame:GuiImage;
var playerListContainerOuter:GuiControl;
var playerListContainer:GuiControl;
var playerListCtrl:GuiMLTextListCtrl;
var playerListScoresCtrl:GuiMLTextListCtrl;
var playerList:Array<PlayerInfo> = [];
var imageResources:Array<Resource<Image>> = [];
var textureResources:Array<Resource<Texture>> = [];
var soundResources:Array<Resource<Sound>> = [];
@ -137,11 +150,14 @@ class PlayGui {
gemCountNumbers.push(new GuiAnim(numberTiles));
}
initTimer();
initGemCounter();
if (!MarbleGame.instance.world.isMultiplayer)
initGemCounter();
initPowerupBox();
if (game == 'ultra')
initBlastBar();
initTexts();
if (MarbleGame.instance.world.isMultiplayer)
initPlayerList();
if (Util.isTouchDevice()) {
MarbleGame.instance.touchInput.showControls(this.playGuiCtrlOuter, game == 'ultra');
@ -574,6 +590,106 @@ class PlayGui {
}
}
function initPlayerList() {
var arial14fontdata = ResourceLoader.getFileEntry("data/font/Arial Bold.fnt");
var arial14b = new BitmapFont(arial14fontdata.entry);
@:privateAccess arial14b.loader = ResourceLoader.loader;
var arial14 = arial14b.toSdfFont(cast 22 * Settings.uiScale, MultiChannel);
var coliseumfontdata = ResourceLoader.getFileEntry("data/font/ColiseumRR.fnt");
var coliseumb = new BitmapFont(coliseumfontdata.entry);
@:privateAccess coliseumb.loader = ResourceLoader.loader;
var coliseum = coliseumb.toSdfFont(cast 44 * Settings.uiScale, MultiChannel);
playerListContainer = new GuiControl();
playerListContainer.horizSizing = Right;
playerListContainer.vertSizing = Bottom;
playerListContainer.position = new Vector(0, 0);
playerListContainer.extent = new Vector(392, 360);
this.playGuiCtrl.addChild(playerListContainer);
var scoreBackdrop = new GuiImage(ResourceLoader.getResource("data/ui/game/scoreBackdrop.png", ResourceLoader.getImage, this.imageResources).toTile());
scoreBackdrop.position = new Vector(0, 0);
scoreBackdrop.extent = new Vector(386, 128);
playerListContainer.addChild(scoreBackdrop);
var scorePlusMinus = new GuiImage(ResourceLoader.getResource("data/ui/game/scoreBackdropMinus.png", ResourceLoader.getImage, this.imageResources)
.toTile());
scorePlusMinus.position = new Vector(20, 17);
scorePlusMinus.extent = new Vector(22, 111);
scoreBackdrop.addChild(scorePlusMinus);
function imgLoader(path:String) {
switch (path) {
case "us":
return ResourceLoader.getResource("data/ui/xbox/GreenDot.png", ResourceLoader.getImage, this.imageResources).toTile();
case "them":
return ResourceLoader.getResource("data/ui/xbox/EmptyDot.png", ResourceLoader.getImage, this.imageResources).toTile();
}
return null;
}
// var playerList = [
// '<font color="#EBEBEB"><img src="us"></img>Player 1 1</font>',
// '<font color="#EBEBEB"><img src="them"></img>Player 2 2</font>'
// ];
var ds = new h2d.filter.DropShadow(1.414, 0.785, 0x000000, 1, 0, 0.4, 1, true);
playerListCtrl = new GuiMLTextListCtrl(arial14, [], imgLoader, ds);
playerListCtrl.position = new Vector(27, 43);
playerListCtrl.extent = new Vector(392, 271);
playerListCtrl.scrollable = true;
playerListCtrl.onSelectedFunc = (sel) -> {}
playerListContainer.addChild(playerListCtrl);
playerListScoresCtrl = new GuiMLTextListCtrl(arial14, [], imgLoader, ds);
playerListScoresCtrl.position = new Vector(277, 43);
playerListScoresCtrl.extent = new Vector(392, 271);
playerListScoresCtrl.scrollable = true;
playerListScoresCtrl.onSelectedFunc = (sel) -> {}
playerListContainer.addChild(playerListScoresCtrl);
}
public function redrawPlayerList() {
var pl = [];
var plScores = [];
playerList.sort((a, b) -> a.score > b.score ? -1 : (a.score < b.score ? 1 : 0));
for (item in playerList) {
pl.push('<font color="#EBEBEB"><img src="${item.us ? "us" : "them"}"></img>${Util.rightPad(item.name, 25, 3)}</font>');
plScores.push('<font color="#EBEBEB">${item.score}</font>');
}
playerListCtrl.setTexts(pl);
playerListScoresCtrl.setTexts(plScores);
}
public function addPlayer(id:Int, name:String, us:Bool) {
playerList.push({
id: id,
name: name,
us: us,
score: 0
});
redrawPlayerList();
}
public function removePlayer(id:Int) {
var f = playerList.filter(x -> x.id == id);
if (f.length != 0)
playerList.remove(f[0]);
redrawPlayerList();
}
public function incrementPlayerScore(id:Int, score:Int) {
var f = playerList.filter(x -> x.id == id);
if (f.length != 0)
f[0].score += score;
redrawPlayerList();
}
public function setHelpTextOpacity(value:Float) {
@:privateAccess helpTextForeground.text._textColorVec.a = value;
@:privateAccess helpTextBackground.text._textColorVec.a = value;
@ -702,6 +818,8 @@ class PlayGui {
}
public function formatGemCounter(collected:Int, total:Int) {
if (MarbleGame.instance.world.isMultiplayer)
return;
if (total == 0) {
for (number in gemCountNumbers) {
number.anim.visible = false;
@ -734,6 +852,8 @@ class PlayGui {
}
public function formatGemHuntCounter(collected:Int) {
if (MarbleGame.instance.world.isMultiplayer)
return;
gemCountNumbers[0].anim.visible = true;
gemCountNumbers[1].anim.visible = true;
gemCountNumbers[2].anim.visible = true;

View file

@ -1,5 +1,11 @@
package modes;
import net.NetCommands;
import net.NetPacket.GemPickupPacket;
import haxe.Exception;
import net.BitStream.OutputBitStream;
import net.NetPacket.GemSpawnPacket;
import net.Net;
import rewind.RewindManager;
import hxd.Rand;
import rewind.RewindableState;
@ -26,6 +32,7 @@ import src.Marble;
@:publicFields
class GemSpawnSphere {
var netIndex:Int;
var position:Vector;
var rotation:Quat;
var element:MissionElementSpawnSphere;
@ -176,8 +183,14 @@ class HuntMode extends NullMode {
playerSpawnPoints.push(spawnSphere);
spawnPointTaken.push(false);
}
if (dbname == "gemspawnspheremarker")
gemSpawnPoints.push(new GemSpawnSphere(spawnSphere));
if (dbname == "gemspawnspheremarker") {
var sphere = new GemSpawnSphere(spawnSphere);
sphere.netIndex = gemSpawnPoints.length;
gemSpawnPoints.push(sphere);
if (level.isMultiplayer) {
@:privateAccess level.gemPredictions.alloc();
}
}
} else if (element._type == MissionElementType.SimGroup) {
scanMission(cast element);
}
@ -271,42 +284,75 @@ class HuntMode extends NullMode {
}
override function onRestart() {
rng.setSeed(100);
rng2.setSeed(100);
if (Settings.optionsSettings.huntRandom) {
rng.setSeed(cast Math.random() * 10000);
rng2.setSeed(cast Math.random() * 10000);
if (!this.level.isMultiplayer || Net.isHost) {
rng.setSeed(100);
rng2.setSeed(100);
if (Settings.optionsSettings.huntRandom) {
rng.setSeed(cast Math.random() * 10000);
rng2.setSeed(cast Math.random() * 10000);
}
setupGems();
}
setupGems();
points = 0;
@:privateAccess level.playGui.formatGemHuntCounter(points);
}
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));
if (@:privateAccess !marble.isNetUpdate) {
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();
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);
if (!this.level.isMultiplayer || Net.isHost) {
refillGemGroups();
}
var incr = 0;
switch (gem.gemColor) {
case "red.gem":
incr = 1;
case "yellow.gem":
incr = 2;
case "blue.gem":
incr = 5;
}
if (@:privateAccess !marble.isNetUpdate) {
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);
}
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.sendPacketToAll(os);
@:privateAccess level.playGui.incrementPlayerScore(packet.clientId, packet.scoreIncr);
}
}
@ -369,6 +415,15 @@ class HuntMode extends NullMode {
activeGemSpawnGroup = spawnGroup;
fillGemGroup(spawnGroup);
@:privateAccess level.radar.blink();
if (level.isMultiplayer && Net.isHost) {
var bs = new OutputBitStream();
bs.writeByte(GemSpawn);
var packet = new GemSpawnPacket();
packet.gemIds = spawnGroup;
packet.serialize(bs);
Net.sendPacketToAll(bs);
}
}
}
@ -384,6 +439,7 @@ class HuntMode extends NullMode {
var melem = new MissionElementItem();
melem.datablock = "GemItem" + gemSpawn.gemColor;
var gem = new Gem(melem);
gem.netIndex = gi;
gemSpawn.gem = gem;
gem.setPosition(gemSpawn.position.x, gemSpawn.position.y, gemSpawn.position.z);
gem.setRotationQuat(gemSpawn.rotation);
@ -406,6 +462,57 @@ class HuntMode extends NullMode {
}
}
public function setActiveSpawnSphere(spawnGroup:Array<Int>) {
for (sphereId in spawnGroup) {
var gemSpawn = gemSpawnPoints[sphereId];
if (gemSpawn.gem != null) {
gemSpawn.gem.pickedUp = false;
gemSpawn.gem.setHide(false);
gemSpawn.gemBeam.setHide(false);
this.activeGems.push(gemSpawn.gem);
} else {
var melem = new MissionElementItem();
melem.datablock = "GemItem" + gemSpawn.gemColor;
var gem = new Gem(melem);
gem.netIndex = sphereId;
gemSpawn.gem = gem;
gem.setPosition(gemSpawn.position.x, gemSpawn.position.y, gemSpawn.position.z);
gem.setRotationQuat(gemSpawn.rotation);
this.activeGems.push(gem);
var gemBeam = new GemBeam();
gemBeam.setPosition(gemSpawn.position.x, gemSpawn.position.y, gemSpawn.position.z);
gemBeam.setRotationQuat(gemSpawn.rotation);
this.gemBeams.push(gemBeam);
gemSpawn.gemBeam = gemBeam;
this.gemToBeamMap.set(gem, gemBeam);
level.addDtsObject(gemBeam, () -> {
level.addDtsObject(gem, () -> {
level.gems.push(gem);
}); // Please be fast lol
});
}
}
activeGemSpawnGroup = spawnGroup;
}
public inline function setGemHiddenStatus(gemId:Int, status:Bool) {
var gemSpawn = gemSpawnPoints[gemId];
if (gemSpawn.gem != null) {
gemSpawn.gem.pickedUp = status;
gemSpawn.gem.setHide(status);
gemSpawn.gemBeam.setHide(status);
if (status)
this.activeGems.push(gemSpawn.gem);
else
this.activeGems.remove(gemSpawn.gem);
} else {
throw new Exception("Setting gem status for non existent gem!");
}
}
function pickGemSpawnGroup() {
var searchRadius = gemGroupRadius * 2;
@ -477,6 +584,45 @@ class HuntMode extends NullMode {
override function onTimeExpire() {
if (level.finishTime != null)
return;
if (!this.level.isMultiplayer || Net.isHost) {
AudioManager.playSound(ResourceLoader.getResource('data/sound/finish.wav', ResourceLoader.getAudio, @:privateAccess level.soundResources));
level.finishTime = level.timeState.clone();
level.marble.setMode(Start);
level.marble.camera.finish = true;
level.finishYaw = level.marble.camera.CameraYaw;
level.finishPitch = level.marble.camera.CameraPitch;
level.displayAlert("Congratulations! You've finished!");
level.cancel(@:privateAccess level.oobSchedule);
level.cancel(@:privateAccess level.marble.oobSchedule);
if (Net.isHost) {
NetCommands.timerRanOut();
}
if (!level.isWatching) {
var myScore = {
name: "Player",
time: getFinishScore()
};
Settings.saveScore(level.mission.path, myScore, getScoreType());
var notifies = AchievementsGui.check();
var delay = 5.0;
var achDelay = 0.0;
for (i in 0...9) {
if (notifies & (1 << i) > 0)
achDelay += 3;
}
if (notifies > 0)
achDelay += 0.5;
@:privateAccess level.schedule(level.timeState.currentAttemptTime + Math.max(delay, achDelay), () -> cast level.showFinishScreen());
}
// Stop the ongoing sounds
if (@:privateAccess level.timeTravelSound != null) {
@:privateAccess level.timeTravelSound.stop();
@:privateAccess level.timeTravelSound = null;
}
}
}
public function doTimerRunOut() {
AudioManager.playSound(ResourceLoader.getResource('data/sound/finish.wav', ResourceLoader.getAudio, @:privateAccess level.soundResources));
level.finishTime = level.timeState.clone();
level.marble.setMode(Start);
@ -484,24 +630,8 @@ class HuntMode extends NullMode {
level.finishYaw = level.marble.camera.CameraYaw;
level.finishPitch = level.marble.camera.CameraPitch;
level.displayAlert("Congratulations! You've finished!");
level.cancel(@:privateAccess level.oobSchedule);
level.cancel(@:privateAccess level.marble.oobSchedule);
if (!level.isWatching) {
var myScore = {
name: "Player",
time: getFinishScore()
};
Settings.saveScore(level.mission.path, myScore, getScoreType());
var notifies = AchievementsGui.check();
var delay = 5.0;
var achDelay = 0.0;
for (i in 0...9) {
if (notifies & (1 << i) > 0)
achDelay += 3;
}
if (notifies > 0)
achDelay += 0.5;
@:privateAccess level.schedule(level.timeState.currentAttemptTime + Math.max(delay, achDelay), () -> cast level.showFinishScreen());
@:privateAccess level.schedule(level.timeState.currentAttemptTime, () -> cast level.showFinishScreen());
}
// Stop the ongoing sounds
if (@:privateAccess level.timeTravelSound != null) {

View file

@ -0,0 +1,29 @@
package net;
import net.NetPacket.GemSpawnPacket;
import net.NetPacket.GemPickupPacket;
class GemPredictionStore {
var predictions:Array<Bool>;
public function new() {
predictions = [];
}
public function alloc() {
predictions.push(true);
}
public inline function getState(netIndex:Int) {
return predictions[netIndex];
}
public function acknowledgeGemPickup(packet:GemPickupPacket) {
predictions[packet.gemId] = true;
}
public function acknowledgeGemSpawn(packet:GemSpawnPacket) {
for (gemId in packet.gemIds)
predictions[gemId] = false;
}
}

View file

@ -30,7 +30,7 @@ class MarblePrediction {
if (p.netFlags != 0)
subs += 1;
// if (p.powerUpId != powerupItemId)
// subs += 1;
subs += 1; // temp
// if (isControl)
// subs += Math.abs(blastAmount - p.blastAmount);
return subs;

View file

@ -1,6 +1,5 @@
package net;
import hl.I64;
import net.NetPacket.MarbleNetFlags;
import net.NetPacket.MarbleUpdatePacket;
import net.Net;

View file

@ -1,5 +1,7 @@
package net;
import net.NetPacket.GemPickupPacket;
import net.NetPacket.GemSpawnPacket;
import net.BitStream.InputBitStream;
import net.BitStream.OutputBitStream;
import net.NetPacket.PowerupPickupPacket;
@ -24,6 +26,8 @@ enum abstract NetPacketType(Int) from Int to Int {
var MarbleUpdate;
var MarbleMove;
var PowerupPickup;
var GemSpawn;
var GemPickup;
var PlayerInfo;
}
@ -262,6 +266,22 @@ class Net {
m.acknowledgePowerupPickup(powerupPickupPacket, MarbleGame.instance.world.timeState, clientConnection.moveManager.getQueueSize());
}
case GemSpawn:
var gemSpawnPacket = new GemSpawnPacket();
gemSpawnPacket.deserialize(input);
if (MarbleGame.instance.world != null) {
MarbleGame.instance.world.spawnHuntGemsClientSide(gemSpawnPacket.gemIds);
@:privateAccess MarbleGame.instance.world.gemPredictions.acknowledgeGemSpawn(gemSpawnPacket);
}
case GemPickup:
var gemPickupPacket = new GemPickupPacket();
gemPickupPacket.deserialize(input);
if (MarbleGame.instance.world != null) {
@:privateAccess MarbleGame.instance.world.playGui.incrementPlayerScore(gemPickupPacket.clientId, gemPickupPacket.scoreIncr);
@:privateAccess MarbleGame.instance.world.gemPredictions.acknowledgeGemPickup(gemPickupPacket);
}
case PlayerInfo:
var count = input.readByte();
for (i in 0...count) {

View file

@ -1,5 +1,6 @@
package net;
import modes.HuntMode;
import net.ClientConnection.GameplayState;
import net.Net.NetPacketType;
import gui.MultiplayerLevelSelectGui;
@ -51,4 +52,11 @@ class NetCommands {
MarbleGame.instance.world.startRealTime = MarbleGame.instance.world.timeState.timeSinceLoad + t;
}
}
@:rpc(server) public static function timerRanOut() {
if (Net.isClient && MarbleGame.instance.world != null) {
var huntMode:HuntMode = cast MarbleGame.instance.world.gameMode;
huntMode.onTimeExpire();
}
}
}

View file

@ -152,3 +152,50 @@ class PowerupPickupPacket implements NetPacket {
b.writeInt(powerupItemId, 9);
}
}
@:publicFields
class GemSpawnPacket implements NetPacket {
var gemIds:Array<Int>;
public function new() {
gemIds = [];
}
public function serialize(b:OutputBitStream) {
b.writeInt(gemIds.length, 5);
for (gemId in gemIds) {
b.writeInt(gemId, 10);
}
}
public function deserialize(b:InputBitStream) {
var count = b.readInt(5);
for (i in 0...count) {
gemIds.push(b.readInt(10));
}
}
}
@:publicFields
class GemPickupPacket implements NetPacket {
var clientId:Int;
var serverTicks:Int;
var gemId:Int;
var scoreIncr:Int;
public function new() {}
public inline function deserialize(b:InputBitStream) {
clientId = b.readByte();
serverTicks = b.readUInt16();
gemId = b.readInt(10);
scoreIncr = b.readInt(4);
}
public inline function serialize(b:OutputBitStream) {
b.writeByte(clientId);
b.writeUInt16(serverTicks);
b.writeInt(gemId, 10);
b.writeInt(scoreIncr, 4);
}
}

View file

@ -12,6 +12,8 @@ import src.Marble;
class Gem extends DtsObject {
public var pickedUp:Bool;
public var netIndex:Int;
var gemColor:String;
public var radarColor:Int;