From b9fd38a76eccc88b7bc1ce008ac870973bd10560 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 19 Sep 2020 21:54:08 -0400 Subject: [PATCH] Various tweaks and speculative changes --- .../formations/patterns/CircleFormation.java | 8 +--- core/src/mindustry/ai/types/FormationAI.java | 36 ++++++++--------- core/src/mindustry/content/UnitTypes.java | 1 + core/src/mindustry/core/NetClient.java | 6 +-- core/src/mindustry/core/NetServer.java | 2 +- core/src/mindustry/core/World.java | 2 +- .../entities/comp/CommanderComp.java | 4 +- core/src/mindustry/game/SectorInfo.java | 3 ++ core/src/mindustry/game/Universe.java | 40 ++++++++++++------- core/src/mindustry/input/InputHandler.java | 3 +- core/src/mindustry/net/NetworkIO.java | 2 - .../world/blocks/campaign/LaunchPad.java | 13 ++++-- 12 files changed, 66 insertions(+), 54 deletions(-) diff --git a/core/src/mindustry/ai/formations/patterns/CircleFormation.java b/core/src/mindustry/ai/formations/patterns/CircleFormation.java index c658c48bf0..0988657adf 100644 --- a/core/src/mindustry/ai/formations/patterns/CircleFormation.java +++ b/core/src/mindustry/ai/formations/patterns/CircleFormation.java @@ -5,20 +5,14 @@ import arc.math.geom.*; import mindustry.ai.formations.*; public class CircleFormation extends FormationPattern{ - /** The radius of one member. This is needed to determine how close we can pack a given number of members around circle. */ - public float memberRadius; /** Angle offset. */ public float angleOffset = 0; - public CircleFormation(float memberRadius){ - this.memberRadius = memberRadius; - } - @Override public Vec3 calculateSlotLocation(Vec3 outLocation, int slotNumber){ if(slots > 1){ float angle = (360f * slotNumber) / slots; - float radius = memberRadius / (float)Math.sin(180f / slots * Mathf.degRad); + float radius = spacing / (float)Math.sin(180f / slots * Mathf.degRad); outLocation.set(Angles.trnsx(angle, radius), Angles.trnsy(angle, radius), angle); }else{ outLocation.set(0, 0, 360f * slotNumber); diff --git a/core/src/mindustry/ai/types/FormationAI.java b/core/src/mindustry/ai/types/FormationAI.java index e101291ccf..4201fb3486 100644 --- a/core/src/mindustry/ai/types/FormationAI.java +++ b/core/src/mindustry/ai/types/FormationAI.java @@ -2,10 +2,10 @@ package mindustry.ai.types; import arc.math.geom.*; import arc.util.ArcAnnotate.*; -import mindustry.*; import mindustry.ai.formations.*; import mindustry.entities.units.*; import mindustry.gen.*; +import mindustry.type.*; public class FormationAI extends AIController implements FormationMember{ public Unit leader; @@ -25,33 +25,33 @@ public class FormationAI extends AIController implements FormationMember{ @Override public void updateUnit(){ + UnitType type = unit.type(); + if(leader.dead){ unit.resetController(); return; } - unit.controlWeapons(leader.isRotate(), leader.isShooting); + unit.controlWeapons(true, leader.isShooting); // unit.moveAt(Tmp.v1.set(deltaX, deltaY).limit(unit.type().speed)); - if(leader.isShooting){ - unit.aimLook(leader.aimX(), leader.aimY()); - }else{ - if(!leader.moving() || !unit.type().rotateShooting){ - if(unit.moving()){ - unit.lookAt(unit.vel.angle()); - } - }else{ - unit.lookAt(leader.rotation); - } + + unit.aim(leader.aimX(), leader.aimY()); + + if(unit.type().rotateShooting){ + unit.lookAt(leader.aimX(), leader.aimY()); + }else if(unit.moving()){ + unit.lookAt(unit.vel.angle()); } Vec2 realtarget = vec.set(target); - if(unit.isGrounded() && Vars.world.raycast(unit.tileX(), unit.tileY(), leader.tileX(), leader.tileY(), Vars.world::solid)){ - //TODO pathfind - //realtarget.set(Vars.pathfinder.getTargetTile(unit.tileOn(), unit.team, leader)); - } + float margin = 3f; - unit.moveAt(realtarget.sub(unit).limit(unit.type().speed)); + if(unit.dst(realtarget) <= margin){ + unit.vel.approachDelta(Vec2.ZERO, type.speed * type.accel / 2f); + }else{ + unit.moveAt(realtarget.sub(unit).limit(type.speed)); + } } @Override @@ -68,7 +68,7 @@ public class FormationAI extends AIController implements FormationMember{ //TODO return formation size //eturn ((Commanderc)unit).formation(). } - return unit.hitSize * 1.7f; + return unit.hitSize * 1f; } @Override diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index d258fdfed7..4891cb5b37 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -747,6 +747,7 @@ public class UnitTypes implements ContentList{ accel = 0.08f; drag = 0.016f; flying = true; + hitsize = 9f; targetAir = false; engineOffset = 7.8f; range = 140f; diff --git a/core/src/mindustry/core/NetClient.java b/core/src/mindustry/core/NetClient.java index d42c8d7b4f..c4e519a4a5 100644 --- a/core/src/mindustry/core/NetClient.java +++ b/core/src/mindustry/core/NetClient.java @@ -338,8 +338,6 @@ public class NetClient implements ApplicationListener{ @Remote(variants = Variant.both) public static void setRules(Rules rules){ state.rules = rules; - //campaign is not valid in multiplayer - state.rules.sector = null; } @Remote(variants = Variant.both) @@ -442,7 +440,7 @@ public class NetClient implements ApplicationListener{ } @Remote(variants = Variant.one, priority = PacketPriority.low, unreliable = true) - public static void stateSnapshot(float waveTime, int wave, int enemies, boolean paused, boolean gameOver, short coreDataLen, byte[] coreData){ + public static void stateSnapshot(float waveTime, int wave, int enemies, boolean paused, boolean gameOver, int timeData, short coreDataLen, byte[] coreData){ try{ if(wave > state.wave){ state.wave = wave; @@ -455,6 +453,8 @@ public class NetClient implements ApplicationListener{ state.enemies = enemies; state.serverPaused = paused; + universe.updateNetSeconds(timeData); + netClient.byteStream.setBytes(net.decompressSnapshot(coreData, coreDataLen)); DataInputStream input = netClient.dataStream; diff --git a/core/src/mindustry/core/NetServer.java b/core/src/mindustry/core/NetServer.java index 7ca78f8c89..994b3a273e 100644 --- a/core/src/mindustry/core/NetServer.java +++ b/core/src/mindustry/core/NetServer.java @@ -846,7 +846,7 @@ public class NetServer implements ApplicationListener{ byte[] stateBytes = syncStream.toByteArray(); //write basic state data. - Call.stateSnapshot(player.con, state.wavetime, state.wave, state.enemies, state.serverPaused, state.gameOver, (short)stateBytes.length, net.compressSnapshot(stateBytes)); + Call.stateSnapshot(player.con, state.wavetime, state.wave, state.enemies, state.serverPaused, state.gameOver, universe.seconds(), (short)stateBytes.length, net.compressSnapshot(stateBytes)); viewport.setSize(player.con.viewWidth, player.con.viewHeight).setCenter(player.con.viewX, player.con.viewY); diff --git a/core/src/mindustry/core/World.java b/core/src/mindustry/core/World.java index c6a448a642..867ba38f1a 100644 --- a/core/src/mindustry/core/World.java +++ b/core/src/mindustry/core/World.java @@ -519,7 +519,7 @@ public class World{ dark = Math.max((edgeBlend - edgeDst) * (4f / edgeBlend), dark); } - if(state.hasSector()){ + if(state.hasSector() && state.getSector().preset == null){ int circleBlend = 14; //quantized angle float offset = state.getSector().rect.rotation + 90; diff --git a/core/src/mindustry/entities/comp/CommanderComp.java b/core/src/mindustry/entities/comp/CommanderComp.java index c9c93bb618..354581654b 100644 --- a/core/src/mindustry/entities/comp/CommanderComp.java +++ b/core/src/mindustry/entities/comp/CommanderComp.java @@ -27,7 +27,7 @@ abstract class CommanderComp implements Unitc{ @Override public void update(){ if(formation != null){ - formation.anchor.set(x, y, rotation); + formation.anchor.set(x, y, /*rotation*/ 0); //TODO rotation set to 0 because rotating is pointless formation.updateSlots(); } } @@ -73,7 +73,7 @@ abstract class CommanderComp implements Unitc{ void command(Formation formation, Seq units){ clearCommand(); - float spacing = hitSize() * 1.7f; + float spacing = hitSize() * 1f; minFormationSpeed = type().speed; controlling.addAll(units); diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java index 1934697aad..806d079b05 100644 --- a/core/src/mindustry/game/SectorInfo.java +++ b/core/src/mindustry/game/SectorInfo.java @@ -87,6 +87,9 @@ public class SectorInfo{ /** Update averages of various stats, updates some special sector logic. * Called every frame. */ public void update(){ + //updating in multiplayer as a client doesn't make sense + if(net.client()) return; + internalTimeSpent += Time.delta; //create last stored core items diff --git a/core/src/mindustry/game/Universe.java b/core/src/mindustry/game/Universe.java index c1416cc672..cb3cf1de19 100644 --- a/core/src/mindustry/game/Universe.java +++ b/core/src/mindustry/game/Universe.java @@ -14,7 +14,8 @@ import static mindustry.Vars.*; /** Updates and handles state of the campaign universe. Has no relevance to other gamemodes. */ public class Universe{ - private long seconds; + private int seconds; + private int netSeconds; private float secondCounter; private int turn; @@ -76,15 +77,19 @@ public class Universe{ /** Update planet rotations, global time and relevant state. */ public void update(){ - secondCounter += Time.delta / 60f; - if(secondCounter >= 1){ - seconds += (int)secondCounter; - secondCounter %= 1f; + //only update time when not in multiplayer + if(!net.client()){ + secondCounter += Time.delta / 60f; - //save every few seconds - if(seconds % 10 == 1){ - save(); + if(secondCounter >= 1){ + seconds += (int)secondCounter; + secondCounter %= 1f; + + //save every few seconds + if(seconds % 10 == 1){ + save(); + } } } @@ -191,25 +196,30 @@ public class Universe{ return count; } - public float secondsMod(float mod, float scale){ - return (seconds / scale) % mod; + public void updateNetSeconds(int value){ + netSeconds = value; } - public long seconds(){ - return seconds; + public float secondsMod(float mod, float scale){ + return (seconds() / scale) % mod; + } + + public int seconds(){ + //use networked seconds when playing as client + return net.client() ? netSeconds : seconds; } public float secondsf(){ - return seconds + secondCounter; + return seconds() + secondCounter; } private void save(){ - Core.settings.put("utime", seconds); + Core.settings.put("utimei", seconds); Core.settings.put("turn", turn); } private void load(){ - seconds = Core.settings.getLong("utime"); + seconds = Core.settings.getInt("utimei"); turn = Core.settings.getInt("turn"); } diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 1cde8aebd6..c678723fec 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -324,7 +324,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ commander.clearCommand(); }else{ - commander.commandNearby(new SquareFormation()); + //TODO try out some other formations + commander.commandNearby(new CircleFormation()); Fx.commandSend.at(player); } diff --git a/core/src/mindustry/net/NetworkIO.java b/core/src/mindustry/net/NetworkIO.java index 271ea5f9d1..05bd69fe32 100644 --- a/core/src/mindustry/net/NetworkIO.java +++ b/core/src/mindustry/net/NetworkIO.java @@ -42,8 +42,6 @@ public class NetworkIO{ try(DataInputStream stream = new DataInputStream(is)){ Time.clear(); state.rules = JsonIO.read(Rules.class, stream.readUTF()); - //campaign is not valid in multiplayer - state.rules.sector = null; state.map = new Map(SaveIO.getSaveWriter().readStringMap(stream)); state.wave = stream.readInt(); diff --git a/core/src/mindustry/world/blocks/campaign/LaunchPad.java b/core/src/mindustry/world/blocks/campaign/LaunchPad.java index 7d38a302ba..efbd2485a2 100644 --- a/core/src/mindustry/world/blocks/campaign/LaunchPad.java +++ b/core/src/mindustry/world/blocks/campaign/LaunchPad.java @@ -97,7 +97,7 @@ public class LaunchPad extends Block{ //launch when full and base conditions are met if(items.total() >= itemCapacity && efficiency() >= 1f && timer(timerLaunch, launchTime / timeScale)){ LaunchPayload entity = LaunchPayload.create(); - items.each((item, amount) -> entity.stacks().add(new ItemStack(item, amount))); + items.each((item, amount) -> entity.stacks.add(new ItemStack(item, amount))); entity.set(this); entity.lifetime(120f); entity.team(team); @@ -174,9 +174,14 @@ public class LaunchPad extends Block{ @Override public void remove(){ + if(!state.isCampaign()) return; + + //on multiplayer the destination is a the first captured sector (basically random) + Sector destsec = !net.client() ? state.secinfo.origin : state.rules.sector.planet.sectors.find(Sector::hasBase); + //actually launch the items upon removal - if(team() == state.rules.defaultTeam && state.secinfo.origin != null){ - ItemSeq dest = state.secinfo.origin.getExtraItems(); + if(team() == state.rules.defaultTeam && destsec != null){ + ItemSeq dest = destsec.getExtraItems(); for(ItemStack stack : stacks){ dest.add(stack); @@ -186,7 +191,7 @@ public class LaunchPad extends Block{ Events.fire(new LaunchItemEvent(stack)); } - state.secinfo.origin.setExtraItems(dest); + destsec.setExtraItems(dest); } } }