mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-07-09 15:27:45 +07:00
Fixed jittery snapshots / Fixed misaligned unit bullets
This commit is contained in:
@ -47,7 +47,7 @@ public class Mechs implements ContentList{
|
||||
boostSpeed = 0.85f;
|
||||
weapon = Weapons.blaster;
|
||||
maxSpeed = 4f;
|
||||
altChargeAlpha = 0.04f;
|
||||
altChargeAlpha = 0.02f;
|
||||
trailColorTo = Color.valueOf("ffd37f");
|
||||
armor = 20f;
|
||||
}
|
||||
@ -64,8 +64,8 @@ public class Mechs implements ContentList{
|
||||
drone.leader = player;
|
||||
drone.set(player.x, player.y);
|
||||
drone.add();
|
||||
Effects.effect(UnitFx.unitLand, player);
|
||||
}
|
||||
Effects.effect(UnitFx.unitLand, player);
|
||||
player.altHeat = 0f;
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class UnitTypes implements ContentList{
|
||||
speed = 0.5f;
|
||||
maxVelocity = 1.6f;
|
||||
range = 40f;
|
||||
health = 20;
|
||||
health = 30;
|
||||
weapon = Weapons.droneBlaster;
|
||||
trailColor = Color.valueOf("ffd37f");
|
||||
}
|
||||
|
@ -3,12 +3,16 @@ package io.anuke.mindustry.core;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.utils.Base64Coder;
|
||||
import com.badlogic.gdx.utils.IntArray;
|
||||
import com.badlogic.gdx.utils.IntMap;
|
||||
import com.badlogic.gdx.utils.IntMap.Entry;
|
||||
import com.badlogic.gdx.utils.IntSet;
|
||||
import io.anuke.annotations.Annotations.PacketPriority;
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.annotations.Annotations.Variant;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.traits.SyncTrait;
|
||||
import io.anuke.mindustry.entities.traits.TypeTrait;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
@ -18,6 +22,7 @@ import io.anuke.mindustry.net.Net.SendMode;
|
||||
import io.anuke.mindustry.net.NetworkIO;
|
||||
import io.anuke.mindustry.net.Packets.*;
|
||||
import io.anuke.mindustry.net.TraceInfo;
|
||||
import io.anuke.mindustry.world.modules.InventoryModule;
|
||||
import io.anuke.ucore.core.Settings;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.entities.Entities;
|
||||
@ -41,6 +46,7 @@ import static io.anuke.mindustry.Vars.*;
|
||||
public class NetClient extends Module{
|
||||
private final static float dataTimeout = 60 * 18;
|
||||
private final static float playerSyncTime = 2;
|
||||
private final static IntArray removals = new IntArray();
|
||||
|
||||
private Timer timer = new Timer(5);
|
||||
/**Whether the client is currently connecting.*/
|
||||
@ -54,8 +60,8 @@ public class NetClient extends Module{
|
||||
|
||||
/**Last snapshot ID recieved.*/
|
||||
private int lastSnapshotBaseID = -1;
|
||||
/**Last snapshot recieved.*/
|
||||
private byte[] lastSnapshotBase;
|
||||
|
||||
private IntMap<byte[]> recievedSnapshots = new IntMap<>();
|
||||
/**Current snapshot that is being built from chinks.*/
|
||||
private byte[] currentSnapshot;
|
||||
/**Array of recieved chunk statuses.*/
|
||||
@ -191,12 +197,12 @@ public class NetClient extends Module{
|
||||
|
||||
@Remote(variants = Variant.one, priority = PacketPriority.low, unreliable = true)
|
||||
public static void onSnapshot(byte[] chunk, int snapshotID, short chunkID, int totalLength, int base){
|
||||
if(NetServer.showSnapshotSize)
|
||||
if(NetServer.debugSnapshots)
|
||||
Log.info("Recieved snapshot: len {0} ID {1} chunkID {2} totalLength {3} base {4} client-base {5}", chunk.length, snapshotID, chunkID, totalLength, base, netClient.lastSnapshotBaseID);
|
||||
|
||||
//skip snapshot IDs that have already been recieved OR snapshots that are too far in front
|
||||
if(snapshotID < netClient.lastSnapshotBaseID || base != netClient.lastSnapshotBaseID){
|
||||
if(NetServer.showSnapshotSize) Log.info("//SKIP SNAPSHOT");
|
||||
if(base != -1 && (snapshotID < netClient.lastSnapshotBaseID || !netClient.recievedSnapshots.containsKey(base))){
|
||||
if(NetServer.debugSnapshots) Log.info("//SKIP SNAPSHOT");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -235,7 +241,7 @@ public class NetClient extends Module{
|
||||
snapshot = chunk;
|
||||
}
|
||||
|
||||
if(NetServer.showSnapshotSize)
|
||||
if(NetServer.debugSnapshots)
|
||||
Log.info("Finished recieving snapshot ID {0} length {1}", snapshotID, chunk.length);
|
||||
|
||||
byte[] result;
|
||||
@ -243,20 +249,21 @@ public class NetClient extends Module{
|
||||
if(base == -1){ //fresh snapshot
|
||||
result = snapshot;
|
||||
length = snapshot.length;
|
||||
netClient.lastSnapshotBase = Arrays.copyOf(snapshot, snapshot.length);
|
||||
netClient.recievedSnapshots.put(snapshotID, Arrays.copyOf(snapshot, snapshot.length));
|
||||
}else{ //otherwise, last snapshot must not be null, decode it
|
||||
if(NetServer.showSnapshotSize)
|
||||
Log.info("Base size: {0} Patch size: {1}", netClient.lastSnapshotBase.length, snapshot.length);
|
||||
netClient.decoder.init(netClient.lastSnapshotBase, snapshot);
|
||||
byte[] baseBytes = netClient.recievedSnapshots.get(base);
|
||||
if(NetServer.debugSnapshots)
|
||||
Log.info("Base size: {0} Patch size: {1}", baseBytes.length, snapshot.length);
|
||||
netClient.decoder.init(baseBytes, snapshot);
|
||||
result = netClient.decoder.decode();
|
||||
length = netClient.decoder.getDecodedLength();
|
||||
//set last snapshot to a copy to prevent issues
|
||||
netClient.lastSnapshotBase = Arrays.copyOf(result, length);
|
||||
netClient.recievedSnapshots.put(snapshotID, Arrays.copyOf(result, length));
|
||||
}
|
||||
|
||||
netClient.lastSnapshotBaseID = snapshotID;
|
||||
|
||||
//set stream bytes to begin snapshot reaeding
|
||||
//set stream bytes to begin snapshot reading
|
||||
netClient.byteStream.setBytes(result, 0, length);
|
||||
|
||||
//get data input for reading from the stream
|
||||
@ -266,6 +273,16 @@ public class NetClient extends Module{
|
||||
|
||||
//confirm that snapshot has been recieved
|
||||
netClient.lastSnapshotBaseID = snapshotID;
|
||||
|
||||
removals.clear();
|
||||
for(Entry<byte[]> entry : netClient.recievedSnapshots.entries()){
|
||||
if(entry.key < base){
|
||||
removals.add(entry.key);
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < removals.size; i++){
|
||||
netClient.recievedSnapshots.remove(removals.get(i));
|
||||
}
|
||||
}catch(Exception e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -280,7 +297,12 @@ public class NetClient extends Module{
|
||||
byte cores = input.readByte();
|
||||
for(int i = 0; i < cores; i++){
|
||||
int pos = input.readInt();
|
||||
world.tile(pos).entity.items.read(input);
|
||||
TileEntity entity = world.tile(pos).entity;
|
||||
if(entity != null){
|
||||
entity.items.read(input);
|
||||
}else{
|
||||
new InventoryModule().read(input);
|
||||
}
|
||||
}
|
||||
|
||||
long timestamp = input.readLong();
|
||||
@ -364,7 +386,7 @@ public class NetClient extends Module{
|
||||
connecting = true;
|
||||
quiet = false;
|
||||
lastSent = 0;
|
||||
lastSnapshotBase = null;
|
||||
recievedSnapshots.clear();
|
||||
currentSnapshot = null;
|
||||
currentSnapshotID = -1;
|
||||
lastSnapshotBaseID = -1;
|
||||
|
@ -4,6 +4,7 @@ import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.Colors;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.IntArray;
|
||||
import com.badlogic.gdx.utils.IntMap;
|
||||
import com.badlogic.gdx.utils.TimeUtils;
|
||||
import io.anuke.annotations.Annotations.Loc;
|
||||
@ -45,11 +46,15 @@ import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class NetServer extends Module{
|
||||
public final static int maxSnapshotSize = 2047;
|
||||
public final static boolean showSnapshotSize = false;
|
||||
|
||||
public final static boolean debugSnapshots = true;
|
||||
public final static float maxSnapshotDelay = 200;
|
||||
public final static float snapshotDropchance = 0.01f;
|
||||
|
||||
private final static byte[] reusableSnapArray = new byte[maxSnapshotSize];
|
||||
private final static float serverSyncTime = 4, kickDuration = 30 * 1000;
|
||||
private final static Vector2 vector = new Vector2();
|
||||
private final static IntArray removals = new IntArray();
|
||||
/**If a play goes away of their server-side coordinates by this distance, they get teleported back.*/
|
||||
private final static float correctDist = 16f;
|
||||
|
||||
@ -215,6 +220,7 @@ public class NetServer extends Module{
|
||||
player.setMineTile(packet.mining);
|
||||
player.isBoosting = packet.boosting;
|
||||
player.isShooting = packet.shooting;
|
||||
player.isAlt = packet.alting;
|
||||
player.getPlaceQueue().clear();
|
||||
for(BuildRequest req : packet.requests){
|
||||
//auto-skip done requests
|
||||
@ -231,7 +237,7 @@ public class NetServer extends Module{
|
||||
|
||||
float prevx = player.x, prevy = player.y;
|
||||
player.set(player.getInterpolator().target.x, player.getInterpolator().target.y);
|
||||
if(!player.mech.flying){
|
||||
if(!player.mech.flying && player.boostHeat < 0.01f){
|
||||
player.move(vector.x, vector.y);
|
||||
}else{
|
||||
player.x += vector.x;
|
||||
@ -257,9 +263,18 @@ public class NetServer extends Module{
|
||||
player.getVelocity().set(packet.xv, packet.yv); //only for visual calculation purposes, doesn't actually update the player
|
||||
|
||||
//when the client confirms recieveing a snapshot, update base and clear map
|
||||
if(packet.lastSnapshot > connection.currentBaseID){
|
||||
connection.currentBaseID = packet.lastSnapshot;
|
||||
connection.currentBaseSnapshot = connection.lastSentRawSnapshot;
|
||||
if(packet.lastSnapshot > connection.lastRecievedSnapshotID){
|
||||
connection.lastRecievedSnapshotID = packet.lastSnapshot;
|
||||
removals.clear();
|
||||
for(IntMap.Entry entry : connection.sent){
|
||||
if(entry.key < packet.lastSnapshot){
|
||||
removals.add(entry.key);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < removals.size; i++){
|
||||
connection.sent.remove(removals.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
connection.lastRecievedClientSnapshot = packet.snapid;
|
||||
@ -285,7 +300,7 @@ public class NetServer extends Module{
|
||||
/** Sends a raw byte[] snapshot to a client, splitting up into chunks when needed.*/
|
||||
private static void sendSplitSnapshot(int userid, byte[] bytes, int snapshotID, int base){
|
||||
if(bytes.length < maxSnapshotSize){
|
||||
Call.onSnapshot(userid, bytes, snapshotID, (short) 0, bytes.length, base);
|
||||
scheduleSnapshot(() -> Call.onSnapshot(userid, bytes, snapshotID, (short) 0, bytes.length, base));
|
||||
}else{
|
||||
int remaining = bytes.length;
|
||||
int offset = 0;
|
||||
@ -294,13 +309,15 @@ public class NetServer extends Module{
|
||||
int used = Math.min(remaining, maxSnapshotSize);
|
||||
byte[] toSend;
|
||||
//re-use sent byte arrays when possible
|
||||
if(used == maxSnapshotSize){
|
||||
if(used == maxSnapshotSize && !debugSnapshots){
|
||||
toSend = reusableSnapArray;
|
||||
System.arraycopy(bytes, offset, toSend, 0, Math.min(offset + maxSnapshotSize, bytes.length) - offset);
|
||||
}else{
|
||||
toSend = Arrays.copyOfRange(bytes, offset, Math.min(offset + maxSnapshotSize, bytes.length));
|
||||
}
|
||||
Call.onSnapshot(userid, toSend, snapshotID, (short) chunkid, bytes.length, base);
|
||||
|
||||
short fchunk = (short)chunkid;
|
||||
scheduleSnapshot(() -> Call.onSnapshot(userid, toSend, snapshotID, fchunk, bytes.length, base));
|
||||
|
||||
remaining -= used;
|
||||
offset += used;
|
||||
@ -309,6 +326,16 @@ public class NetServer extends Module{
|
||||
}
|
||||
}
|
||||
|
||||
private static void scheduleSnapshot(Runnable r){
|
||||
if(debugSnapshots){
|
||||
if(!Mathf.chance(snapshotDropchance)){
|
||||
Timers.run(maxSnapshotDelay / 1000f * 60f, r);
|
||||
}
|
||||
}else{
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
|
||||
public void sendWorldData(Player player, int clientID){
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
DeflaterOutputStream def = new DeflaterOutputStream(stream);
|
||||
@ -490,10 +517,6 @@ public class NetServer extends Module{
|
||||
}
|
||||
}
|
||||
|
||||
String getUUID(int connectionID){
|
||||
return connections.get(connectionID).uuid;
|
||||
}
|
||||
|
||||
String fixName(String name){
|
||||
if(name.equals("[") || name.equals("]")){
|
||||
return "";
|
||||
@ -559,12 +582,12 @@ public class NetServer extends Module{
|
||||
if(!player.timer.get(Player.timerSync, serverSyncTime) || !connection.hasConnected) continue;
|
||||
|
||||
//if the player hasn't acknowledged that it has recieved the packet, send the same thing again
|
||||
if(connection.currentBaseID < connection.lastSentSnapshotID){
|
||||
if(showSnapshotSize)
|
||||
/*if(connection.currentBaseID < connection.lastSentSnapshotID){
|
||||
if(debugSnapshots)
|
||||
Log.info("Re-sending snapshot: {0} bytes, ID {1} base {2} baselength {3}", connection.lastSentSnapshot.length, connection.lastSentSnapshotID, connection.lastSentBase, connection.currentBaseSnapshot.length);
|
||||
sendSplitSnapshot(connection.id, connection.lastSentSnapshot, connection.lastSentSnapshotID, connection.lastSentBase);
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
//reset stream to begin writing
|
||||
syncStream.reset();
|
||||
@ -573,29 +596,28 @@ public class NetServer extends Module{
|
||||
|
||||
byte[] bytes = syncStream.toByteArray();
|
||||
|
||||
if(connection.currentBaseID == -1){
|
||||
//assign to last sent snapshot so that there is only ever one unique snapshot with ID 0
|
||||
if(connection.lastSentSnapshot != null){
|
||||
int snapid = connection.lastSentSnapshotID ++;
|
||||
|
||||
if(connection.lastRecievedSnapshotID == -1){
|
||||
/*if(connection.lastSentSnapshot != null){
|
||||
bytes = connection.lastSentSnapshot;
|
||||
}else{
|
||||
connection.lastSentRawSnapshot = bytes;
|
||||
connection.lastSentSnapshot = bytes;
|
||||
}
|
||||
}*/
|
||||
|
||||
if(showSnapshotSize) Log.info("Sent raw snapshot: {0} bytes.", bytes.length);
|
||||
if(debugSnapshots) Log.info("Sent raw snapshot: {0} bytes.", bytes.length);
|
||||
///Nothing to diff off of in this case, send the whole thing
|
||||
sendSplitSnapshot(connection.id, bytes, 0, -1);
|
||||
sendSplitSnapshot(connection.id, bytes, snapid, -1);
|
||||
connection.sent.put(snapid, bytes);
|
||||
}else{
|
||||
connection.lastSentRawSnapshot = bytes;
|
||||
|
||||
//send diff, otherwise
|
||||
byte[] diff = ByteDeltaEncoder.toDiff(new ByteMatcherHash(connection.currentBaseSnapshot, bytes), encoder);
|
||||
if(showSnapshotSize)
|
||||
Log.info("Shrank snapshot: {0} -> {1}, Base {2} ID {3} base length = {4}", bytes.length, diff.length, connection.currentBaseID, connection.currentBaseID + 1, connection.currentBaseSnapshot.length);
|
||||
sendSplitSnapshot(connection.id, diff, connection.currentBaseID + 1, connection.currentBaseID);
|
||||
connection.lastSentSnapshot = diff;
|
||||
connection.lastSentSnapshotID = connection.currentBaseID + 1;
|
||||
connection.lastSentBase = connection.currentBaseID;
|
||||
byte[] diff = ByteDeltaEncoder.toDiff(new ByteMatcherHash(connection.sent.get(connection.lastRecievedSnapshotID), bytes), encoder);
|
||||
if(debugSnapshots)
|
||||
Log.info("Shrank snapshot: {0} -> {1}, Base {2}", bytes.length, diff.length, connection.lastRecievedSnapshotID);
|
||||
|
||||
sendSplitSnapshot(connection.id, diff, snapid, connection.lastRecievedSnapshotID);
|
||||
connection.sent.put(snapid, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,6 +460,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
|
||||
altHeat = Mathf.lerpDelta(altHeat, isAlt ? 1f : 0f, mech.altChargeAlpha);
|
||||
boostHeat = Mathf.lerpDelta(boostHeat, (tile != null && tile.solid()) || (isBoosting && ((!movement.isZero() && moved) || !isLocal)) ? 1f : 0f, 0.08f);
|
||||
mech.updateAlt(this); //updated regardless
|
||||
|
||||
if(!isLocal){
|
||||
interpolate();
|
||||
@ -480,8 +481,6 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
control.database().unlockContent(mech);
|
||||
}
|
||||
|
||||
mech.updateAlt(this);
|
||||
|
||||
if(mobile){
|
||||
updateFlying();
|
||||
}else{
|
||||
|
@ -23,7 +23,7 @@ public class AlphaDrone extends FlyingUnit {
|
||||
public final UnitState attack = new UnitState() {
|
||||
@Override
|
||||
public void update() {
|
||||
if(leader == null || leader.isDead()){
|
||||
if(leader == null || leader.isDead() || !leader.isAdded()){
|
||||
damage(99999f);
|
||||
return;
|
||||
}
|
||||
@ -67,12 +67,19 @@ public class AlphaDrone extends FlyingUnit {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSave(DataOutput stream) throws IOException {
|
||||
super.writeSave(stream);
|
||||
public void write(DataOutput stream) throws IOException {
|
||||
super.write(stream);
|
||||
stream.writeInt(leader == null ? -1 : leader.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readSave(DataInput stream) throws IOException {
|
||||
public void read(DataInput stream, long time) throws IOException {
|
||||
super.read(stream, time);
|
||||
leader = Vars.playerGroup.getByID(stream.readInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readSave(DataInput stream) throws IOException{
|
||||
super.readSave(stream);
|
||||
|
||||
if(!Net.active()){
|
||||
|
@ -19,7 +19,7 @@ public class Interpolator{
|
||||
public void read(float cx, float cy, float x, float y, long sent, float... target1ds){
|
||||
if(lastUpdated != 0) updateSpacing = TimeUtils.timeSinceMillis(lastUpdated);
|
||||
|
||||
lastUpdated = sent;
|
||||
lastUpdated = TimeUtils.millis();
|
||||
|
||||
targets = target1ds;
|
||||
last.set(cx, cy);
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.anuke.mindustry.net;
|
||||
|
||||
import com.badlogic.gdx.utils.IntMap;
|
||||
import io.anuke.mindustry.net.Net.SendMode;
|
||||
|
||||
public abstract class NetConnection{
|
||||
@ -10,24 +11,22 @@ public abstract class NetConnection{
|
||||
* The current base snapshot that the client is absolutely confirmed to have recieved.
|
||||
* All sent snapshots should be taking the diff from this base snapshot, if it isn't null.
|
||||
*/
|
||||
public byte[] currentBaseSnapshot;
|
||||
//public byte[] currentBaseSnapshot;
|
||||
/**
|
||||
* ID of the current base snapshot.
|
||||
*/
|
||||
public int currentBaseID = -1;
|
||||
// public int currentBaseID = -1;
|
||||
|
||||
public int lastSentBase = -1;
|
||||
public byte[] lastSentSnapshot;
|
||||
public byte[] lastSentRawSnapshot;
|
||||
//public int lastSentBase = -1;
|
||||
// public byte[] lastSentSnapshot;
|
||||
//public byte[] lastSentRawSnapshot;
|
||||
public int lastRecievedSnapshotID = -1;
|
||||
public int lastSentSnapshotID = -1;
|
||||
public IntMap<byte[]> sent = new IntMap<>();
|
||||
|
||||
/**
|
||||
* ID of last recieved client snapshot.
|
||||
*/
|
||||
/**ID of last recieved client snapshot.*/
|
||||
public int lastRecievedClientSnapshot = -1;
|
||||
/**
|
||||
* Timestamp of last recieved snapshot.
|
||||
*/
|
||||
/**Timestamp of last recieved snapshot.*/
|
||||
public long lastRecievedClientTime;
|
||||
|
||||
public boolean hasConnected = false;
|
||||
|
@ -155,7 +155,7 @@ public class Packets{
|
||||
//player snapshot data
|
||||
public float x, y, pointerX, pointerY, rotation, baseRotation, xv, yv;
|
||||
public Tile mining;
|
||||
public boolean boosting, shooting;
|
||||
public boolean boosting, shooting, alting;
|
||||
public Array<BuildRequest> requests = new Array<>();
|
||||
|
||||
@Override
|
||||
@ -172,6 +172,7 @@ public class Packets{
|
||||
buffer.putFloat(player.pointerY);
|
||||
buffer.put(player.isBoosting ? (byte) 1 : 0);
|
||||
buffer.put(player.isShooting ? (byte) 1 : 0);
|
||||
buffer.put(player.isAlt ? (byte) 1 : 0);
|
||||
|
||||
buffer.put((byte) (Mathf.clamp(player.getVelocity().x, -Unit.maxAbsVelocity, Unit.maxAbsVelocity) * Unit.velocityPercision));
|
||||
buffer.put((byte) (Mathf.clamp(player.getVelocity().y, -Unit.maxAbsVelocity, Unit.maxAbsVelocity) * Unit.velocityPercision));
|
||||
@ -204,6 +205,7 @@ public class Packets{
|
||||
pointerY = buffer.getFloat();
|
||||
boosting = buffer.get() == 1;
|
||||
shooting = buffer.get() == 1;
|
||||
alting = buffer.get() == 1;
|
||||
xv = buffer.get() / Unit.velocityPercision;
|
||||
yv = buffer.get() / Unit.velocityPercision;
|
||||
rotation = buffer.getShort() / 2f;
|
||||
|
@ -81,7 +81,10 @@ public class Weapon implements Content{
|
||||
shootDirect(shooter, x, y, rotation, left);
|
||||
}
|
||||
|
||||
public static void shootDirect(ShooterTrait shooter, float x, float y, float rotation, boolean left){
|
||||
public static void shootDirect(ShooterTrait shooter, float offsetX, float offsetY, float rotation, boolean left){
|
||||
float x = shooter.getX() + offsetX;
|
||||
float y = shooter.getY() + offsetY;
|
||||
|
||||
Weapon weapon = shooter.getWeapon();
|
||||
|
||||
Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> weapon.bullet(shooter, x, y, f + Mathf.range(weapon.inaccuracy)));
|
||||
@ -149,7 +152,7 @@ public class Weapon implements Content{
|
||||
float ang = tr.angle();
|
||||
tr.trns(ang - 90, width * Mathf.sign(left), length);
|
||||
|
||||
shoot(shooter, shooter.getX() + tr.x, shooter.getY() + tr.y, Angles.angle(shooter.getX() + tr.x, shooter.getY() + tr.y, cx, cy), left);
|
||||
shoot(shooter, tr.x, tr.y, Angles.angle(shooter.getX() + tr.x, shooter.getY() + tr.y, cx, cy), left);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -352,7 +352,9 @@ public class JoinDialog extends FloatingDialog{
|
||||
this.ip = ip;
|
||||
this.port = Vars.port;
|
||||
}
|
||||
|
||||
}else{
|
||||
this.ip = ip;
|
||||
this.port = Vars.port;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,6 +179,10 @@ public class CoreBlock extends StorageBlock{
|
||||
}
|
||||
|
||||
if(entity.currentUnit != null){
|
||||
if(!entity.currentUnit.isDead()){
|
||||
entity.currentUnit = null;
|
||||
return;
|
||||
}
|
||||
entity.heat = Mathf.lerpDelta(entity.heat, 1f, 0.1f);
|
||||
entity.time += Timers.delta();
|
||||
entity.progress += 1f / (entity.currentUnit instanceof Player ? state.mode.respawnTime : droneRespawnDuration) * Timers.delta();
|
||||
|
@ -163,6 +163,7 @@ public class ServerControl extends Module{
|
||||
|
||||
handler.register("stop", "Stop hosting the server.", arg -> {
|
||||
Net.closeServer();
|
||||
Timers.clear();
|
||||
state.set(State.menu);
|
||||
netServer.reset();
|
||||
Log.info("Stopped server.");
|
||||
@ -889,6 +890,7 @@ public class ServerControl extends Module{
|
||||
private void play(boolean wait, Runnable run){
|
||||
inExtraRound = true;
|
||||
Runnable r = () -> {
|
||||
|
||||
Array<Player> players = new Array<>();
|
||||
for(Player p : playerGroup.all()){
|
||||
players.add(p);
|
||||
@ -906,7 +908,7 @@ public class ServerControl extends Module{
|
||||
};
|
||||
|
||||
if(wait){
|
||||
Timers.runTask(60f * roundExtraTime, r);
|
||||
Timers.run(60f * roundExtraTime, r);
|
||||
}else{
|
||||
r.run();
|
||||
}
|
||||
|
Reference in New Issue
Block a user