From 2fafb327c223d5c72c1c696d7791e73693da3e5f Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 5 Feb 2018 23:38:23 -0500 Subject: [PATCH 1/8] Now with only 28 errors! --- core/src/io/anuke/mindustry/Mindustry.java | 56 +++++++++++++++- core/src/io/anuke/mindustry/ai/Pathfind.java | 22 ++++--- core/src/io/anuke/mindustry/ai/Raycaster.java | 8 ++- core/src/io/anuke/mindustry/ai/TileGraph.java | 3 +- core/src/io/anuke/mindustry/core/Logic.java | 3 + .../src/io/anuke/mindustry/core/Renderer.java | 5 +- core/src/io/anuke/mindustry/core/World.java | 19 ------ .../anuke/mindustry/entities/BulletType.java | 9 +-- .../io/anuke/mindustry/entities/Player.java | 43 +++++++------ .../mindustry/entities/effect/DamageArea.java | 9 +-- .../anuke/mindustry/entities/effect/EMP.java | 14 ++-- .../mindustry/entities/enemies/Enemy.java | 17 +++-- .../mindustry/entities/enemies/EnemyType.java | 6 +- .../entities/enemies/types/FortressType.java | 6 +- .../entities/enemies/types/HealerType.java | 4 +- .../entities/enemies/types/TankType.java | 7 +- .../io/anuke/mindustry/resource/Weapon.java | 15 +++-- core/src/io/anuke/mindustry/world/Block.java | 1 - core/src/io/anuke/mindustry/world/Tile.java | 12 ++-- .../world/blocks/DistributionBlocks.java | 2 - .../mindustry/world/blocks/WeaponBlocks.java | 22 +++---- .../world/blocks/types/BlendBlock.java | 5 +- .../blocks/types/defense/LaserTurret.java | 8 +-- .../blocks/types/defense/RepairTurret.java | 7 +- .../world/blocks/types/defense/Turret.java | 14 ++-- .../blocks/types/distribution/Conveyor.java | 3 +- .../distribution/LiquidItemJunction.java | 64 ------------------- .../types/distribution/LiquidJunction.java | 4 +- .../types/distribution/LiquidRouter.java | 2 +- .../blocks/types/distribution/Sorter.java | 6 +- .../blocks/types/distribution/Splitter.java | 4 +- .../blocks/types/production/Generator.java | 17 +++-- 32 files changed, 206 insertions(+), 211 deletions(-) delete mode 100644 core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidItemJunction.java diff --git a/core/src/io/anuke/mindustry/Mindustry.java b/core/src/io/anuke/mindustry/Mindustry.java index 57e59ad1ef..b1f5c4aa7a 100644 --- a/core/src/io/anuke/mindustry/Mindustry.java +++ b/core/src/io/anuke/mindustry/Mindustry.java @@ -1,15 +1,21 @@ package io.anuke.mindustry; +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.utils.TimeUtils; import io.anuke.mindustry.core.*; import io.anuke.mindustry.io.BlockLoader; import io.anuke.mindustry.io.BundleLoader; import io.anuke.mindustry.io.Platform; +import io.anuke.ucore.core.Timers; import io.anuke.ucore.modules.ModuleCore; import io.anuke.ucore.util.Log; import static io.anuke.mindustry.Vars.*; public class Mindustry extends ModuleCore { + boolean multithread = true; + Thread thread; + float delta = 1f; @Override public void init(){ @@ -19,7 +25,11 @@ public class Mindustry extends ModuleCore { BundleLoader.load(); BlockLoader.load(); - module(logic = new Logic()); + + logic = new Logic(); + + if(!multithread) module(logic); + module(world = new World()); module(control = new Control()); module(renderer = new Renderer()); @@ -27,5 +37,49 @@ public class Mindustry extends ModuleCore { module(netServer = new NetServer()); module(netClient = new NetClient()); module(netCommon = new NetCommon()); + + Timers.setDeltaProvider(() -> + Math.min(Thread.currentThread() == thread ? delta : Gdx.graphics.getDeltaTime()*60f, 20f) + ); + + if(multithread) { + + logic.init(); + + thread = new Thread(() -> { + try { + while (true) { + long time = TimeUtils.millis(); + logic.update(); + long elapsed = TimeUtils.timeSinceMillis(time); + long target = (long) (1000 / 60f); + + delta = Math.max(elapsed, target) / 1000f * 60f; + + if (elapsed < target) { + Thread.sleep(target - elapsed); + } + } + } catch (Exception ex) { + Gdx.app.postRunnable(() -> { + throw new RuntimeException(ex); + }); + } + }); + thread.setDaemon(true); + thread.setName("Update Thread"); + thread.start(); + } } + + public void render(){ + super.render(); + + try { + //Thread.sleep(40); + }catch (Exception e){ + e.printStackTrace(); + } + } + } diff --git a/core/src/io/anuke/mindustry/ai/Pathfind.java b/core/src/io/anuke/mindustry/ai/Pathfind.java index cf39c79c20..35176462cb 100644 --- a/core/src/io/anuke/mindustry/ai/Pathfind.java +++ b/core/src/io/anuke/mindustry/ai/Pathfind.java @@ -11,7 +11,6 @@ import io.anuke.ucore.core.Timers; import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Log; import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Tmp; import static io.anuke.mindustry.Vars.*; @@ -26,6 +25,10 @@ public class Pathfind{ /**temporary vector2 for calculations*/ Vector2 vector = new Vector2(); + Vector2 v1 = new Vector2(); + Vector2 v2 = new Vector2(); + Vector2 v3 = new Vector2(); + /**Finds the position on the path an enemy should move to. * If the path is not yet calculated, this returns the enemy's position (i. e. "don't move") * @param enemy The enemy to find a path for @@ -76,7 +79,7 @@ public class Pathfind{ if(projectLen < 8 || !onLine(projection, prev.worldx(), prev.worldy(), target.worldx(), target.worldy())){ canProject = false; }else{ - projection.add(Angles.translation(Angles.angle(prev.worldx(), prev.worldy(), + projection.add(v1.set(Angles.angle(prev.worldx(), prev.worldy(), target.worldx(), target.worldy()), projectLen)); } @@ -122,7 +125,8 @@ public class Pathfind{ public void update(){ //go through each spawnpoint, and if it's not found a path yet, update it - for(SpawnPoint point : world.getSpawns()){ + for(int i = 0; i < world.getSpawns().size; i ++){ + SpawnPoint point = world.getSpawns().get(i); if(point.request == null || point.finder == null){ continue; } @@ -204,7 +208,7 @@ public class Pathfind{ } /**Finds the closest tile to a position, in an array of tiles.*/ - private static int findClosest(Tile[] tiles, float x, float y){ + private int findClosest(Tile[] tiles, float x, float y){ int cindex = -2; float dst = Float.MAX_VALUE; @@ -222,23 +226,23 @@ public class Pathfind{ } /**Returns whether a point is on a line.*/ - private static boolean onLine(Vector2 vector, float x1, float y1, float x2, float y2){ + private boolean onLine(Vector2 vector, float x1, float y1, float x2, float y2){ return MathUtils.isEqual(vector.dst(x1, y1) + vector.dst(x2, y2), Vector2.dst(x1, y1, x2, y2), 0.01f); } /**Returns distance from a point to a line segment.*/ - private static float pointLineDist(float x, float y, float x2, float y2, float px, float py){ + private float pointLineDist(float x, float y, float x2, float y2, float px, float py){ float l2 = Vector2.dst2(x, y, x2, y2); float t = Math.max(0, Math.min(1, Vector2.dot(px - x, py - y, x2 - x, y2 - y) / l2)); - Vector2 projection = Tmp.v1.set(x, y).add(Tmp.v2.set(x2, y2).sub(x, y).scl(t)); // Projection falls on the segment + Vector2 projection = v1.set(x, y).add(v2.set(x2, y2).sub(x, y).scl(t)); // Projection falls on the segment return projection.dst(px, py); } //TODO documentation - private static Vector2 projectPoint(float x1, float y1, float x2, float y2, float pointx, float pointy){ + private Vector2 projectPoint(float x1, float y1, float x2, float y2, float pointx, float pointy){ float px = x2-x1, py = y2-y1, dAB = px*px + py*py; float u = ((pointx - x1) * px + (pointy - y1) * py) / dAB; float x = x1 + u * px, y = y1 + u * py; - return Tmp.v3.set(x, y); //this is D + return v3.set(x, y); //this is D } } diff --git a/core/src/io/anuke/mindustry/ai/Raycaster.java b/core/src/io/anuke/mindustry/ai/Raycaster.java index 31005103a1..6ce48805e0 100644 --- a/core/src/io/anuke/mindustry/ai/Raycaster.java +++ b/core/src/io/anuke/mindustry/ai/Raycaster.java @@ -4,12 +4,13 @@ import com.badlogic.gdx.ai.utils.Collision; import com.badlogic.gdx.ai.utils.Ray; import com.badlogic.gdx.ai.utils.RaycastCollisionDetector; import com.badlogic.gdx.math.Vector2; - -import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.util.Geometry; import io.anuke.ucore.util.Mathf; +import static io.anuke.mindustry.Vars.tilesize; +import static io.anuke.mindustry.Vars.world; + public class Raycaster implements RaycastCollisionDetector{ private boolean found = false; @@ -75,7 +76,8 @@ public class Raycaster implements RaycastCollisionDetector{ if(tile == null || tile.solid()) return true; - for(Tile near : tile.getNearby()){ + for(int i = 0; i < 4; i ++){ + Tile near = tile.getNearby(i); if(near == null || near.solid()) return true; } diff --git a/core/src/io/anuke/mindustry/ai/TileGraph.java b/core/src/io/anuke/mindustry/ai/TileGraph.java index 919992078a..c4026d6ec7 100644 --- a/core/src/io/anuke/mindustry/ai/TileGraph.java +++ b/core/src/io/anuke/mindustry/ai/TileGraph.java @@ -4,11 +4,12 @@ import io.anuke.mindustry.world.Tile; /**Tilegraph that ignores player-made tiles.*/ public class TileGraph implements OptimizedGraph { + private Tile[] tiles = new Tile[4]; /**Used for the OptimizedPathFinder implementation.*/ @Override public Tile[] connectionsOf(Tile node){ - Tile[] nodes = node.getNearby(); + Tile[] nodes = node.getNearby(tiles); for(int i = 0; i < 4; i ++){ if(nodes[i] != null && !nodes[i].passable()){ nodes[i] = null; diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index c2835de052..993dd6a528 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -117,6 +117,9 @@ public class Logic extends Module { if(!state.is(State.menu)){ + if(!Net.client()) + world.pathfinder().update(); + if(world.getCore().block() != ProductionBlocks.core && !state.gameOver){ state.gameOver = true; NetEvents.handleGameOver(); diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index ef7cc58dce..355fb71f1c 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -247,8 +247,9 @@ public class Renderer extends RendererModule{ } float angle = Angles.angle(camera.position.x, camera.position.y, enemy.x, enemy.y); - Angles.translation(angle, Unit.dp.scl(20f)); - Draw.rect("enemyarrow", camera.position.x + Angles.x(), camera.position.y + Angles.y(), angle); + float tx = Angles.trnsx(angle, Unit.dp.scl(20f)); + float ty = Angles.trnsy(angle, Unit.dp.scl(20f)); + Draw.rect("enemyarrow", camera.position.x + tx, camera.position.y + ty, angle); } Draw.color(); diff --git a/core/src/io/anuke/mindustry/core/World.java b/core/src/io/anuke/mindustry/core/World.java index 5ae8c51caf..f9506a7b2a 100644 --- a/core/src/io/anuke/mindustry/core/World.java +++ b/core/src/io/anuke/mindustry/core/World.java @@ -8,7 +8,6 @@ import io.anuke.mindustry.ai.Pathfind; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.game.SpawnPoint; import io.anuke.mindustry.io.Maps; -import io.anuke.mindustry.net.Net; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Map; import io.anuke.mindustry.world.Tile; @@ -42,12 +41,6 @@ public class World extends Module{ currentMap = maps.getMap(0); } - @Override - public void update(){ - if(!Net.client()) - pathfind.update(); - } - @Override public void dispose(){ maps.dispose(); @@ -140,18 +133,6 @@ public class World extends Module{ return tiles; } - public Tile[] getNearby(int x, int y){ - return getNearby(x, y, temptiles); - } - - public Tile[] getNearby(int x, int y, Tile[] temptiles){ - temptiles[0] = tile(x+1, y); - temptiles[1] = tile(x, y+1); - temptiles[2] = tile(x-1, y); - temptiles[3] = tile(x, y-1); - return temptiles; - } - private void createTiles(){ for(int x = 0; x < tiles.length; x ++){ for(int y = 0; y < tiles[0].length; y ++){ diff --git a/core/src/io/anuke/mindustry/entities/BulletType.java b/core/src/io/anuke/mindustry/entities/BulletType.java index fb1b0fda90..3cecfe612b 100644 --- a/core/src/io/anuke/mindustry/entities/BulletType.java +++ b/core/src/io/anuke/mindustry/entities/BulletType.java @@ -252,10 +252,11 @@ public abstract class BulletType extends BaseBulletType{ Effects.effect(Fx.blastsmoke, b); Effects.effect(Fx.blastexplosion, b); - - Angles.circle(30, f->{ - Angles.translation(f, 6f); - Bullet o = new Bullet(blastshot, b.owner, b.x + Angles.x(), b.y + Angles.y(), f).add(); + + //TODO remove translation() usage + Angles.circleVectors(30, 6f, (x, y) -> { + float ang = Mathf.atan2(x, y); + Bullet o = new Bullet(blastshot, b.owner, b.x + x, b.y + y, ang).add(); o.damage = b.damage/9; }); } diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index baf12ae433..9120f9f0c5 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.entities; import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.TimeUtils; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.graphics.Shaders; @@ -17,6 +18,7 @@ import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Tmp; +import io.anuke.ucore.util.Translator; import java.nio.ByteBuffer; @@ -41,6 +43,9 @@ public class Player extends SyncEntity{ public int clientid; public boolean isLocal = false; + + private Vector2 movement = new Vector2(); + private Translator tr = new Translator(); public Player(){ hitbox.setSize(5); @@ -121,12 +126,12 @@ public class Player extends SyncEntity{ if(!isAndroid) { for (int i : Mathf.signs) { Weapon weapon = i < 0 ? weaponLeft : weaponRight; - Angles.vector.set(3 * i, 2).rotate(angle - 90); + tr.trns(angle - 90, 3*i, 2); float w = i > 0 ? -8 : 8; if(snap){ - Draw.rect(weapon.name + "-equip", (int)x + Angles.x(), (int)y + Angles.y(), w, 8, angle - 90); + Draw.rect(weapon.name + "-equip", (int)x + tr.x, (int)y + tr.y, w, 8, angle - 90); }else{ - Draw.rect(weapon.name + "-equip", x + Angles.x(), y + Angles.y(), w, 8, angle - 90); + Draw.rect(weapon.name + "-equip", x + tr.x, y + tr.y, w, 8, angle - 90); } } } @@ -172,15 +177,15 @@ public class Player extends SyncEntity{ health = Mathf.clamp(health, -1, maxhealth); - vector.set(0, 0); + movement.set(0, 0); float xa = Inputs.getAxis("move_x"); float ya = Inputs.getAxis("move_y"); if(Math.abs(xa) < 0.3) xa = 0; if(Math.abs(ya) < 0.3) ya = 0; - vector.y += ya*speed; - vector.x += xa*speed; + movement.y += ya*speed; + movement.x += xa*speed; boolean shooting = !Inputs.keyDown("dash") && Inputs.keyDown("shoot") && control.input().recipe == null && !ui.hasMouse() && !control.input().onConfigurable(); @@ -190,23 +195,22 @@ public class Player extends SyncEntity{ weaponRight.update(player, false); } - if(dashing && Timers.get(this, "dashfx", 3) && vector.len() > 0){ - Angles.translation(angle + 180, 3f); - Effects.effect(Fx.dashsmoke, x + Angles.x(), y + Angles.y()); + if(dashing && Timers.get(this, "dashfx", 3) && movement.len() > 0){ + Effects.effect(Fx.dashsmoke, x + Angles.trnsx(angle + 180f, 3f), y + Angles.trnsy(angle + 180f, 3f)); } - vector.limit(speed); + movement.limit(speed); if(!noclip){ - move(vector.x*Timers.delta(), vector.y*Timers.delta()); + move(movement.x*Timers.delta(), movement.y*Timers.delta()); }else{ - x += vector.x*Timers.delta(); - y += vector.y*Timers.delta(); + x += movement.x*Timers.delta(); + y += movement.y*Timers.delta(); } if(!shooting){ - if(!vector.isZero()) - angle = Mathf.lerpAngDelta(angle, vector.angle(), 0.13f); + if(!movement.isZero()) + angle = Mathf.lerpAngDelta(angle, movement.angle(), 0.13f); }else{ float angle = Angles.mouseAngle(x, y); this.angle = Mathf.lerpAngDelta(this.angle, angle, 0.1f); @@ -299,14 +303,15 @@ public class Player extends SyncEntity{ angle = Mathf.lerpAngDelta(angle, i.targetrot, 0.6f); + float tx = x + Angles.trnsx(angle + 180f, 3f); + float ty = y + Angles.trnsy(angle + 180f, 3f); + if(isAndroid && i.target.dst(i.last) > 2f && Timers.get(this, "dashfx", 2)){ - Angles.translation(angle + 180, 3f); - Effects.effect(Fx.dashsmoke, x + Angles.x(), y + Angles.y()); + Effects.effect(Fx.dashsmoke, tx, ty); } if(dashing && !dead && Timers.get(this, "dashfx", 3) && i.target.dst(i.last) > 1f){ - Angles.translation(angle + 180, 3f); - Effects.effect(Fx.dashsmoke, x + Angles.x(), y + Angles.y()); + Effects.effect(Fx.dashsmoke, tx, ty); } } diff --git a/core/src/io/anuke/mindustry/entities/effect/DamageArea.java b/core/src/io/anuke/mindustry/entities/effect/DamageArea.java index 2789d8fc80..c1ce0382f9 100644 --- a/core/src/io/anuke/mindustry/entities/effect/DamageArea.java +++ b/core/src/io/anuke/mindustry/entities/effect/DamageArea.java @@ -11,20 +11,21 @@ import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.function.Consumer; -import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Physics; +import io.anuke.ucore.util.Translator; import static io.anuke.mindustry.Vars.*; public class DamageArea{ private static Rectangle rect = new Rectangle(); + private static Translator tr = new Translator(); //only for entities, not tiles (yet!) public static void damageLine(Entity owner, Effect effect, float x, float y, float angle, float length, int damage){ - Angles.translation(angle, length); - rect.setPosition(x, y).setSize(Angles.x(), Angles.y()); - float x2 = Angles.x() + x, y2 = Angles.y() + y; + tr.trns(angle, length); + rect.setPosition(x, y).setSize(tr.x, tr.y); + float x2 = tr.x + x, y2 = tr.y + y; if(rect.width < 0){ rect.x += rect.width; diff --git a/core/src/io/anuke/mindustry/entities/effect/EMP.java b/core/src/io/anuke/mindustry/entities/effect/EMP.java index 62dc2c81f1..673ea3c247 100644 --- a/core/src/io/anuke/mindustry/entities/effect/EMP.java +++ b/core/src/io/anuke/mindustry/entities/effect/EMP.java @@ -3,21 +3,23 @@ package io.anuke.mindustry.entities.effect; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; - -import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.types.PowerAcceptor; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Effects; import io.anuke.ucore.entities.TimedEntity; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; -import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Mathf; +import io.anuke.ucore.util.Translator; + +import static io.anuke.mindustry.Vars.tilesize; +import static io.anuke.mindustry.Vars.world; public class EMP extends TimedEntity{ static final int maxTargets = 8; static Array array = new Array<>(); + static Translator tr = new Translator(); int radius = 4; int damage = 6; @@ -80,8 +82,8 @@ public class EMP extends TimedEntity{ } for(int i = 0; i < 14 - targets.size; i ++){ - Angles.translation(Mathf.randomSeed(i + id*77)*360f, radius * tilesize); - drawLine(x + Angles.x(), y + Angles.y()); + tr.trns(Mathf.randomSeed(i + id*77)*360f, radius * tilesize); + drawLine(x + tr.x, y + tr.y); } Lines.stroke(fract()*2f); diff --git a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java index 2fcea376bd..da2e03db53 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java +++ b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java @@ -1,5 +1,6 @@ package io.anuke.mindustry.entities.enemies; +import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.TimeUtils; import io.anuke.mindustry.entities.Bullet; @@ -10,10 +11,8 @@ import io.anuke.mindustry.net.NetEvents; import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.SolidEntity; -import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Timer; -import io.anuke.ucore.util.Tmp; +import io.anuke.ucore.graphics.Draw; +import io.anuke.ucore.util.*; import java.nio.ByteBuffer; @@ -37,6 +36,9 @@ public class Enemy extends SyncEntity { public int tier = 1; public Vector2 totalMove = new Vector2(); + public TextureRegion region; + public Translator tr = new Translator(); + public Enemy(EnemyType type){ this.type = type; } @@ -90,6 +92,7 @@ public class Enemy extends SyncEntity { hitbox.setSize(type.hitsize); hitboxTile.setSize(type.hitsizeTile); maxhealth = type.health * tier; + region = Draw.region(type.name + "-t" + Mathf.clamp(tier, 1, 3)); heal(); } @@ -166,13 +169,13 @@ public class Enemy extends SyncEntity { public void shoot(BulletType bullet, float rotation){ if(!(Net.client())) { - Angles.translation(angle + rotation, type.length); - Bullet out = new Bullet(bullet, this, x + Angles.x(), y + Angles.y(), this.angle + rotation).add(); + tr.trns(angle + rotation, type.length); + Bullet out = new Bullet(bullet, this, x + tr.x, y + tr.y, this.angle + rotation).add(); out.damage = (int) ((bullet.damage * (1 + (tier - 1) * 1f))); type.onShoot(this, bullet, rotation); if(Net.server()){ - NetEvents.handleBullet(bullet, this, x + Angles.x(), y + Angles.y(), this.angle + rotation, (short)out.damage); + NetEvents.handleBullet(bullet, this, x + tr.x, y + tr.y, this.angle + rotation, (short)out.damage); } } } diff --git a/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java b/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java index 7125f39cdf..9a48827641 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java @@ -67,15 +67,13 @@ public class EnemyType { } public void draw(Enemy enemy){ - String region = name + "-t" + Mathf.clamp(enemy.tier, 1, 3); - Shaders.outline.color.set(tierColors[enemy.tier - 1]); Shaders.outline.lighten = Mathf.clamp(enemy.hitTime/hitDuration); - Shaders.outline.region = Draw.region(region); + Shaders.outline.region = enemy.region; Shaders.outline.apply(); - Draw.rect(region, enemy.x, enemy.y, enemy.angle - 90); + Draw.rect(enemy.region, enemy.x, enemy.y, enemy.angle - 90); Draw.color(); Graphics.flush(); diff --git a/core/src/io/anuke/mindustry/entities/enemies/types/FortressType.java b/core/src/io/anuke/mindustry/entities/enemies/types/FortressType.java index 3b3f08adf4..d02c85fe7c 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/types/FortressType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/types/FortressType.java @@ -35,13 +35,13 @@ public class FortressType extends EnemyType { world.getCore().worldy()) <= 90f){ if(Timers.get(this, "spawn", spawnTime) && enemy.spawned < maxSpawn){ - Angles.translation(enemy.angle, 20f); + enemy.tr.trns(enemy.angle, 20f); Enemy s = new Enemy(EnemyTypes.fast); s.lane = enemy.lane; s.tier = enemy.tier; s.spawner = enemy; - s.set(enemy.x + Angles.x(), enemy.y + Angles.y()); + s.set(enemy.x + enemy.tr.x, enemy.y + enemy.tr.y); s.add(); Effects.effect(Fx.spawn, enemy); @@ -53,7 +53,7 @@ public class FortressType extends EnemyType { public void onShoot(Enemy enemy, BulletType type, float rotation){ - Effects.effect(Fx.largeCannonShot, enemy.x + Angles.x(), enemy.y + Angles.y(), enemy.angle); + Effects.effect(Fx.largeCannonShot, enemy.x + enemy.tr.x, enemy.y + enemy.tr.y, enemy.angle); Effects.shake(3f, 3f, enemy); } diff --git a/core/src/io/anuke/mindustry/entities/enemies/types/HealerType.java b/core/src/io/anuke/mindustry/entities/enemies/types/HealerType.java index 58628d7d58..74d2857617 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/types/HealerType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/types/HealerType.java @@ -74,7 +74,7 @@ public class HealerType extends EnemyType { if(target == null) return; - Angles.translation(enemy.angleTo(target), 5f); + enemy.tr.trns(enemy.angleTo(target), 5f); Shaders.outline.color.set(Color.CLEAR); Shaders.outline.apply(); @@ -82,7 +82,7 @@ public class HealerType extends EnemyType { if(target.health < target.maxhealth){ Draw.color(Hue.rgb(138, 244, 138, (MathUtils.sin(Timers.time()) + 1f) / 13f)); Draw.alpha(0.9f); - Shapes.laser("laser", "laserend", enemy.x + Angles.x(), enemy.y + Angles.y(), target.x - Angles.x()/1.5f, target.y - Angles.y()/1.5f); + Shapes.laser("laser", "laserend", enemy.x + enemy.tr.x, enemy.y + enemy.tr.y, target.x - enemy.tr.x/1.5f, target.y - enemy.tr.y/1.5f); Draw.color(); } diff --git a/core/src/io/anuke/mindustry/entities/enemies/types/TankType.java b/core/src/io/anuke/mindustry/entities/enemies/types/TankType.java index f812679a56..64a827c1b2 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/types/TankType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/types/TankType.java @@ -17,17 +17,14 @@ public class TankType extends EnemyType { bullet = BulletType.small; length = 3f; mass = 1.4f; + length = 8f; } @Override public void shoot(Enemy enemy){ super.shoot(enemy); - Angles.translation(enemy.angle, 8f); - - Angles.shotgun(3, 8f, enemy.angle, f -> { - enemy.shoot(bullet, f); - }); + Angles.shotgun(3, 8f, enemy.angle, f -> enemy.shoot(bullet, f)); } } diff --git a/core/src/io/anuke/mindustry/resource/Weapon.java b/core/src/io/anuke/mindustry/resource/Weapon.java index 24ba460a1f..3cedc5086a 100644 --- a/core/src/io/anuke/mindustry/resource/Weapon.java +++ b/core/src/io/anuke/mindustry/resource/Weapon.java @@ -13,6 +13,7 @@ import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.Entity; import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Mathf; +import io.anuke.ucore.util.Translator; public class Weapon extends Upgrade{ public static final Weapon @@ -87,6 +88,8 @@ public class Weapon extends Upgrade{ float length = 3f; /**whether to shoot the weapons in different arms one after another, rather an all at once*/ boolean roundrobin = false; + /**translator for vector calulations*/ + Translator tr = new Translator(); private Weapon(String name, float reload, BulletType type){ super(name); @@ -100,15 +103,15 @@ public class Weapon extends Upgrade{ Timers.reset(p, "reload" + !left, reload/2f); } float ang = Angles.mouseAngle(p.x, p.y); - Angles.vector.set(3f * Mathf.sign(left), length).rotate(ang - 90); - shoot(p, p.x + Angles.x(), p.y + Angles.y(), Angles.mouseAngle(p.x + Angles.x(), p.y + Angles.y())); + tr.trns(ang - 90, 3f * Mathf.sign(left), length); + shoot(p, p.x + tr.x, p.y + tr.y, Angles.mouseAngle(p.x + tr.x, p.y + tr.y)); } } void shootInternal(Player p, float x, float y, float rotation){ Angles.shotgun(shots, spacing, rotation, f -> bullet(p, x, y, f + Mathf.range(inaccuracy))); - Angles.translation(rotation, 3f); - if(effect != null) Effects.effect(effect, x + Angles.x(), y + Angles.y(), rotation); + tr.trns(rotation, 3f); + if(effect != null) Effects.effect(effect, x + tr.x, y + tr.y, rotation); Effects.shake(shake, shake, x, y); Effects.sound(shootsound, x, y); } @@ -122,7 +125,7 @@ public class Weapon extends Upgrade{ } void bullet(Entity owner, float x, float y, float angle){ - Angles.translation(angle, 3f); - new Bullet(type, owner, x + Angles.x(), y + Angles.y(), angle).add(); + tr.trns(angle, 3f); + new Bullet(type, owner, x + tr.x, y + tr.y, angle).add(); } } diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index 8d140696eb..2e047c9c3a 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -31,7 +31,6 @@ public class Block{ protected static TextureRegion temp = new TextureRegion(); - public Tile[] temptiles = new Tile[4]; /**internal name*/ public final String name; /**internal ID*/ diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index 67891392ec..7b63ba498b 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -237,13 +237,13 @@ public class Tile{ if(rotation == 3) return world.tile(x, y - 1); return null; } - - public Tile[] getNearby(){ - return world.getNearby(x, y); - } - public Tile[] getNearby(Tile[] copy){ - return world.getNearby(x, y, copy); + public Tile[] getNearby(Tile[] temptiles){ + temptiles[0] = world.tile(x+1, y); + temptiles[1] = world.tile(x, y+1); + temptiles[2] = world.tile(x-1, y); + temptiles[3] = world.tile(x, y-1); + return temptiles; } public void updateOcclusion(){ diff --git a/core/src/io/anuke/mindustry/world/blocks/DistributionBlocks.java b/core/src/io/anuke/mindustry/world/blocks/DistributionBlocks.java index 9ce3a90efd..c03d1445ff 100644 --- a/core/src/io/anuke/mindustry/world/blocks/DistributionBlocks.java +++ b/core/src/io/anuke/mindustry/world/blocks/DistributionBlocks.java @@ -45,8 +45,6 @@ public class DistributionBlocks{ }}, liquidjunction = new LiquidJunction("liquidjunction"){{ - }}, - liquiditemjunction = new LiquidItemJunction("liquiditemjunction"){{ }}, powerbooster = new PowerBooster("powerbooster"){{ powerRange = 4; diff --git a/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java b/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java index 681d8b45b2..e69b377800 100644 --- a/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java +++ b/core/src/io/anuke/mindustry/world/blocks/WeaponBlocks.java @@ -40,12 +40,11 @@ public class WeaponBlocks{ @Override protected void shoot(Tile tile){ TurretEntity entity = tile.entity(); - - Angles.vector.set(4, -2).rotate(entity.rotation); - bullet(tile, entity.rotation); - - Angles.vector.set(4, 2).rotate(entity.rotation); - bullet(tile, entity.rotation); + + for(int i : Mathf.signs){ + tr.trns(entity.rotation, 4, -2 * i); + bullet(tile, entity.rotation); + } } }, @@ -136,9 +135,10 @@ public class WeaponBlocks{ @Override public void shoot(Tile tile){ TurretEntity entity = tile.entity(); - Angles.translation(entity.rotation, 4); - new TeslaOrb(tile.worldx() + Angles.x(), tile.worldy() + Angles.y(), range, 9).add(); + float len = 4f; + + new TeslaOrb(tile.drawx() + Angles.trnsx(entity.rotation, len), tile.drawy() + Angles.trnsy(entity.rotation, len), range, 9).add(); } }, @@ -179,10 +179,10 @@ public class WeaponBlocks{ float space = 3.5f; for(int i = -1; i < 1; i ++){ - Angles.vector.set(len, Mathf.sign(i) * space).rotate(entity.rotation); + tr.trns(entity.rotation, len, Mathf.sign(i) * space); bullet(tile, entity.rotation); - Effects.effect(shootEffect, tile.drawx() + Angles.x(), - tile.drawy()+ Angles.y(), entity.rotation); + Effects.effect(shootEffect, tile.drawx() + tr.x, + tile.drawy() + tr.y, entity.rotation); } Effects.shake(1f, 1f, tile.worldx(), tile.worldy()); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/BlendBlock.java b/core/src/io/anuke/mindustry/world/blocks/types/BlendBlock.java index d6ccfe1305..cd27addbf2 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/BlendBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/BlendBlock.java @@ -20,10 +20,9 @@ public class BlendBlock extends Block{ Draw.rect(variants > 0 ? (name() + Mathf.randomSeed(tile.id(), 1, variants)) : name(), tile.worldx(), tile.worldy()); - Tile[] nearby = tile.getNearby(); - for(int i = 0; i < 4; i ++){ - if(nearby[i] != null && !blend.test(nearby[i].block())){ + Tile near = tile.getNearby(i); + if(near != null && !blend.test(near.block())){ Draw.rect(edge + "-" + i, tile.worldx(), tile.worldy()); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java index 67eca49211..16efe1fcd2 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/LaserTurret.java @@ -34,7 +34,7 @@ public class LaserTurret extends PowerTurret{ TurretEntity entity = tile.entity(); Enemy enemy = entity.target; - if(Angles.angleDist(entity.rotation, Angles.angle(tile.worldx(), tile.worldy(), enemy.x, enemy.y)) < cone){ + if(Angles.angleDist(entity.rotation, Angles.angle(tile.drawx(), tile.drawy(), enemy.x, enemy.y)) < cone){ enemy.damage(damage); Effects.effect(hiteffect, enemy.x + Mathf.range(3), enemy.y + Mathf.range(3)); } @@ -45,10 +45,10 @@ public class LaserTurret extends PowerTurret{ TurretEntity entity = tile.entity(); if(entity.target != null && - Angles.angleDist(entity.rotation, Angles.angle(tile.worldx(), tile.worldy(), entity.target.x, entity.target.y)) <= cone){ - Angles.translation(entity.rotation, 4f); + Angles.angleDist(entity.rotation, Angles.angle(tile.drawx(), tile.drawy(), entity.target.x, entity.target.y)) <= cone){ + float len = 4f; - float x = tile.worldx() + Angles.x(), y = tile.worldy() + Angles.y(); + float x = tile.drawx() + Angles.trnsx(entity.rotation, len), y = tile.drawy() + Angles.trnsy(entity.rotation, len); float x2 = entity.target.x, y2 = entity.target.y; float lighten = (MathUtils.sin(Timers.time()/1.2f) + 1f) / 10f; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java index 84334b3006..4e65b5dc6e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/RepairTurret.java @@ -73,7 +73,7 @@ public class RepairTurret extends PowerTurret{ @Override public void drawSelect(Tile tile){ Draw.color(Color.GREEN); - Lines.dashCircle(tile.worldx(), tile.worldy(), range); + Lines.dashCircle(tile.drawx(), tile.drawy(), range); Draw.reset(); } @@ -83,8 +83,9 @@ public class RepairTurret extends PowerTurret{ if(entity.power >= powerUsed && entity.blockTarget != null && Angles.angleDist(entity.angleTo(entity.blockTarget), entity.rotation) < 10){ Tile targetTile = entity.blockTarget.tile; - Angles.translation(entity.rotation, 4f); - float x = tile.drawx() + Angles.x(), y = tile.drawy() + Angles.y(); + float len = 4f; + + float x = tile.drawx() + Angles.trnsx(entity.rotation, len), y = tile.drawy() + Angles.trnsy(entity.rotation, len); float x2 = targetTile.drawx(), y2 = targetTile.drawy(); Draw.color(Hue.rgb(138, 244, 138, (MathUtils.sin(Timers.time()) + 1f) / 14f)); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java index 5a0abec79b..b9dafc88d5 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/Turret.java @@ -21,6 +21,7 @@ import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Strings; +import io.anuke.ucore.util.Translator; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -51,6 +52,7 @@ public class Turret extends Block{ protected Effect shootEffect = null; protected float shootShake = 0f; protected int soundReload = 0; + protected Translator tr = new Translator(); public Turret(String name) { super(name); @@ -210,14 +212,14 @@ public class Turret extends Block{ protected void shoot(Tile tile){ TurretEntity entity = tile.entity(); - Angles.translation(entity.rotation, width * tilesize / 2f); + tr.trns(entity.rotation, width * tilesize/2); for(int i = 0; i < shots; i ++){ if(Mathf.zero(shotDelayScale)){ bullet(tile, entity.rotation + Mathf.range(inaccuracy)); }else{ - Timers.run(i * shotDelayScale, ()->{ - Angles.translation(entity.rotation, width * tilesize / 2f); + Timers.run(i * shotDelayScale, () -> { + tr.trns(entity.rotation, width * tilesize/2f); bullet(tile, entity.rotation + Mathf.range(inaccuracy)); }); } @@ -225,8 +227,8 @@ public class Turret extends Block{ } if(shootEffect != null){ - Effects.effect(shootEffect, tile.drawx() + Angles.x(), - tile.drawy()+ Angles.y(), entity.rotation); + Effects.effect(shootEffect, tile.drawx() + tr.x, + tile.drawy() + tr.y, entity.rotation); } if(shootShake > 0){ @@ -235,7 +237,7 @@ public class Turret extends Block{ } protected void bullet(Tile tile, float angle){ - Bullet out = new Bullet(bullet, tile.entity, tile.drawx() + Angles.x(), tile.drawy() + Angles.y(), angle).add(); + new Bullet(bullet, tile.entity, tile.drawx() + tr.x, tile.drawy() + tr.y, angle).add(); } public static class TurretEntity extends TileEntity{ diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java index e4ca1413d5..b0769886ba 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java @@ -24,6 +24,7 @@ import java.util.List; import static io.anuke.mindustry.Vars.tilesize; public class Conveyor extends Block{ + private static ItemPos drawpos = new ItemPos(); private static ItemPos pos1 = new ItemPos(); private static ItemPos pos2 = new ItemPos(); private static LongArray removals = new LongArray(); @@ -72,7 +73,7 @@ public class Conveyor extends Block{ byte rotation = tile.getRotation(); for(int i = 0; i < entity.convey.size; i ++){ - ItemPos pos = pos1.set(entity.convey.get(i)); + ItemPos pos = drawpos.set(entity.convey.get(i)); if(pos.item == null) continue; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidItemJunction.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidItemJunction.java deleted file mode 100644 index 59dd009759..0000000000 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidItemJunction.java +++ /dev/null @@ -1,64 +0,0 @@ -package io.anuke.mindustry.world.blocks.types.distribution; - -import io.anuke.mindustry.resource.Item; -import io.anuke.mindustry.resource.Liquid; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.types.LiquidBlock; -import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.core.Timers; - -public class LiquidItemJunction extends LiquidBlock{ - - public LiquidItemJunction(String name) { - super(name); - rotate = true; - } - - @Override - public void draw(Tile tile){ - Draw.rect(name(), tile.worldx(), tile.worldy(), tile.getRotation() * 90); - } - - @Override - public void handleLiquid(Tile tile, Tile source, Liquid liquid, float amount){ - int dir = source.relativeTo(tile.x, tile.y); - dir = (dir+4)%4; - Tile to = tile.getNearby()[dir]; - - ((LiquidBlock)to.block()).handleLiquid(to, tile, liquid, amount); - } - - @Override - public boolean acceptLiquid(Tile dest, Tile source, Liquid liquid, float amount){ - int dir = source.relativeTo(dest.x, dest.y); - dir = (dir+4)%4; - - if(dir+dest.getRotation() % 2 == 1) return false; - - Tile to = dest.getNearby()[dir]; - return to != null && to.block() != this && to.block() instanceof LiquidBlock && - ((LiquidBlock)to.block()).acceptLiquid(to, dest, liquid, amount); - } - - @Override - public void handleItem(Item item, Tile tile, Tile source){ - int dir = source.relativeTo(tile.x, tile.y); - Tile to = tile.getNearby()[dir]; - - Timers.run(15, ()->{ - if(to == null || to.entity == null) return; - to.block().handleItem(item, to, tile); - }); - - } - - @Override - public boolean acceptItem(Item item, Tile tile, Tile source){ - int dir = source.relativeTo(tile.x, tile.y); - - if((dir+ tile.getRotation()) % 2 == 0) return false; - - Tile to = tile.getNearby()[dir]; - return to != null && to.block().acceptItem(item, to, tile); - } -} diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidJunction.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidJunction.java index f34146c0b8..7cc8e9da1e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidJunction.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidJunction.java @@ -23,7 +23,7 @@ public class LiquidJunction extends Conduit{ public void handleLiquid(Tile tile, Tile source, Liquid liquid, float amount){ int dir = source.relativeTo(tile.x, tile.y); dir = (dir+4)%4; - Tile to = tile.getNearby()[dir]; + Tile to = tile.getNearby(dir); ((LiquidBlock)to.block()).handleLiquid(to, tile, liquid, amount); @@ -33,7 +33,7 @@ public class LiquidJunction extends Conduit{ public boolean acceptLiquid(Tile dest, Tile source, Liquid liquid, float amount){ int dir = source.relativeTo(dest.x, dest.y); dir = (dir+4)%4; - Tile to = dest.getNearby()[dir]; + Tile to = dest.getNearby(dir); return to != null && to.block() != this && to.block() instanceof LiquidBlock && ((LiquidBlock)to.block()).acceptLiquid(to, dest, liquid, amount); } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidRouter.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidRouter.java index 2c3b617b93..a8816589b3 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidRouter.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/LiquidRouter.java @@ -19,7 +19,7 @@ public class LiquidRouter extends Conduit{ if(entity.liquidAmount > 0){ if(tile.getExtra() != tile.getRotation()){ - tryMoveLiquid(tile, tile.getNearby()[tile.getRotation()]); + tryMoveLiquid(tile, tile.getNearby(tile.getRotation())); } tile.setRotation((byte)((tile.getRotation() + 1) % 4)); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Sorter.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Sorter.java index 1ba308d2a1..dee337c83d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Sorter.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Sorter.java @@ -66,10 +66,10 @@ public class Sorter extends Block{ Tile to; if(item == entity.sortItem){ - to = dest.getNearby()[dir]; + to = dest.getNearby(dir); }else{ - Tile a = dest.getNearby()[Mathf.mod(dir - 1, 4)]; - Tile b = dest.getNearby()[Mathf.mod(dir + 1, 4)]; + Tile a = dest.getNearby(Mathf.mod(dir - 1, 4)); + Tile b = dest.getNearby(Mathf.mod(dir + 1, 4)); boolean ac = a.block().acceptItem(item, a, dest); boolean bc = b.block().acceptItem(item, b, dest); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Splitter.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Splitter.java index bebac23555..a049be2cbb 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Splitter.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Splitter.java @@ -31,8 +31,8 @@ public class Splitter extends Block{ if(dir == -1) return null; Tile to; - Tile a = dest.getNearby()[Mathf.mod(dir - 1, 4)]; - Tile b = dest.getNearby()[Mathf.mod(dir + 1, 4)]; + Tile a = dest.getNearby(Mathf.mod(dir - 1, 4)); + Tile b = dest.getNearby(Mathf.mod(dir + 1, 4)); boolean ac = a.block().acceptItem(item, a, dest); boolean bc = b.block().acceptItem(item, b, dest); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java b/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java index 680a4ec1dd..3c3950f728 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java @@ -25,6 +25,9 @@ public class Generator extends PowerBlock{ public static final int powerTime = 2; public static boolean drawRangeOverlay = false; + protected Translator t1 = new Translator(); + protected Translator t2 = new Translator(); + public int laserRange = 6; public int laserDirections = 4; public float powerSpeed = 0.5f; @@ -177,10 +180,10 @@ public class Generator extends PowerBlock{ if(target != null){ boolean interfering = isInterfering(target, rotation); - Tmp.v1.set(Angles.translation(rotation * 90, target.block().width * tilesize / 2 + 2f + - (interfering ? Vector2.dst(tile.worldx(), tile.worldy(), target.worldx(), target.worldy()) / 2f - tilesize / 2f * target.block().width + 1 : 0))); + t1.trns(rotation * 90, target.block().width * tilesize / 2 + 2f + + (interfering ? Vector2.dst(tile.worldx(), tile.worldy(), target.worldx(), target.worldy()) / 2f - tilesize / 2f * target.block().width + 1 : 0)); - Angles.translation(rotation * 90, width * tilesize / 2 + 2f); + t2.trns(rotation * 90, width * tilesize / 2 + 2f); if(!interfering){ Draw.tint(Hue.mix(Color.GRAY, Color.WHITE, 0.904f + Mathf.sin(Timers.time(), 1.7f, 0.06f))); @@ -188,7 +191,7 @@ public class Generator extends PowerBlock{ Draw.tint(Hue.mix(Color.SCARLET, Color.WHITE, 0.902f + Mathf.sin(Timers.time(), 1.7f, 0.08f))); if(state.is(State.playing) && Mathf.chance(Timers.delta() * 0.033)){ - Effects.effect(Fx.laserspark, target.worldx() - Tmp.v1.x, target.worldy() - Tmp.v1.y); + Effects.effect(Fx.laserspark, target.worldx() - t1.x, target.worldy() - t1.y); } } @@ -197,9 +200,9 @@ public class Generator extends PowerBlock{ int relative = tile.relativeTo(target.x, target.y); if(relative == -1){ - Shapes.laser("laser", "laserend", tile.worldx() + Angles.x(), tile.worldy() + Angles.y(), - target.worldx() - Tmp.v1.x + Mathf.range(r), - target.worldy() - Tmp.v1.y + Mathf.range(r), 0.7f); + Shapes.laser("laser", "laserend", tile.worldx() + t2.x, tile.worldy() + t2.y, + target.worldx() - t1.x + Mathf.range(r), + target.worldy() - t1.y + Mathf.range(r), 0.7f); }else{ Draw.rect("laserfull", tile.worldx() + Geometry.d4[relative].x * width * tilesize / 2f, From 59285f76c473a1e1b4c41c208fe15bad35b27a22 Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 6 Feb 2018 18:48:10 -0500 Subject: [PATCH 2/8] Removed all tmps, multithreading now functional --- core/src/io/anuke/mindustry/Mindustry.java | 1 - core/src/io/anuke/mindustry/ai/Pathfind.java | 4 ++-- .../io/anuke/mindustry/ai/SmoothGraphPath.java | 5 ++--- core/src/io/anuke/mindustry/core/Renderer.java | 8 +++++--- .../io/anuke/mindustry/entities/Player.java | 7 +++---- .../anuke/mindustry/entities/SyncEntity.java | 1 + .../mindustry/entities/effect/TeslaOrb.java | 10 +++++----- .../mindustry/entities/enemies/Enemy.java | 6 +++--- .../mindustry/entities/enemies/EnemyType.java | 17 ++++++++++------- .../entities/enemies/types/BlastType.java | 9 ++++----- .../io/anuke/mindustry/graphics/Shaders.java | 11 ++++++----- .../io/anuke/mindustry/input/InputHandler.java | 11 ++++++----- .../io/anuke/mindustry/input/PlaceMode.java | 12 +++++++----- .../io/anuke/mindustry/mapeditor/MapView.java | 7 +++++-- .../mindustry/ui/dialogs/LevelDialog.java | 10 ++++++---- .../mindustry/ui/fragments/DebugFragment.java | 7 ++----- .../mindustry/ui/fragments/HudFragment.java | 2 +- core/src/io/anuke/mindustry/world/Block.java | 4 ++-- .../world/blocks/types/defense/Door.java | 11 ++++++----- .../blocks/types/distribution/Conveyor.java | 18 +++++++++--------- .../types/production/NuclearReactor.java | 12 +++++++----- 21 files changed, 92 insertions(+), 81 deletions(-) diff --git a/core/src/io/anuke/mindustry/Mindustry.java b/core/src/io/anuke/mindustry/Mindustry.java index b1f5c4aa7a..7ea13b75b2 100644 --- a/core/src/io/anuke/mindustry/Mindustry.java +++ b/core/src/io/anuke/mindustry/Mindustry.java @@ -25,7 +25,6 @@ public class Mindustry extends ModuleCore { BundleLoader.load(); BlockLoader.load(); - logic = new Logic(); if(!multithread) module(logic); diff --git a/core/src/io/anuke/mindustry/ai/Pathfind.java b/core/src/io/anuke/mindustry/ai/Pathfind.java index 35176462cb..5099bd2df1 100644 --- a/core/src/io/anuke/mindustry/ai/Pathfind.java +++ b/core/src/io/anuke/mindustry/ai/Pathfind.java @@ -79,8 +79,8 @@ public class Pathfind{ if(projectLen < 8 || !onLine(projection, prev.worldx(), prev.worldy(), target.worldx(), target.worldy())){ canProject = false; }else{ - projection.add(v1.set(Angles.angle(prev.worldx(), prev.worldy(), - target.worldx(), target.worldy()), projectLen)); + projection.add(v1.set(projectLen, 0).rotate(Angles.angle(prev.worldx(), prev.worldy(), + target.worldx(), target.worldy()))); } float dst = Vector2.dst(enemy.x, enemy.y, target.worldx(), target.worldy()); diff --git a/core/src/io/anuke/mindustry/ai/SmoothGraphPath.java b/core/src/io/anuke/mindustry/ai/SmoothGraphPath.java index 2196fb97b7..39b1b75ec2 100644 --- a/core/src/io/anuke/mindustry/ai/SmoothGraphPath.java +++ b/core/src/io/anuke/mindustry/ai/SmoothGraphPath.java @@ -3,16 +3,15 @@ package io.anuke.mindustry.ai; import com.badlogic.gdx.ai.pfa.DefaultGraphPath; import com.badlogic.gdx.ai.pfa.SmoothableGraphPath; import com.badlogic.gdx.math.Vector2; - import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.util.Tmp; public class SmoothGraphPath extends DefaultGraphPath implements SmoothableGraphPath{ + private Vector2 vector = new Vector2(); @Override public Vector2 getNodePosition(int index){ Tile tile = nodes.get(index); - return Tmp.v3.set(tile.worldx(), tile.worldy()); + return vector.set(tile.worldx(), tile.worldy()); } @Override diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index 355fb71f1c..546c28d1fd 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -50,6 +50,7 @@ public class Renderer extends RendererModule{ private int targetscale = baseCameraScale; private FloatArray shieldHits = new FloatArray(); private Array shieldDraws = new Array<>(); + private Rectangle rect = new Rectangle(), rect2 = new Rectangle(); private BlockRenderer blocks = new BlockRenderer(); public Renderer() { @@ -58,9 +59,9 @@ public class Renderer extends RendererModule{ Core.cameraScale = baseCameraScale; Effects.setEffectProvider((name, color, x, y, rotation) -> { if(Settings.getBool("effects")){ - Rectangle view = Tmp.r1.setSize(camera.viewportWidth, camera.viewportHeight) + Rectangle view = rect.setSize(camera.viewportWidth, camera.viewportHeight) .setCenter(camera.position.x, camera.position.y); - Rectangle pos = Tmp.r2.setSize(name.size).setCenter(x, y); + Rectangle pos = rect2.setSize(name.size).setCenter(x, y); if(view.overlaps(pos)){ new EffectEntity(name, color, rotation).set(x, y).add(); } @@ -242,7 +243,8 @@ public class Renderer extends RendererModule{ Draw.color(Color.RED); for(Enemy enemy : enemyGroup.all()) { - if (Tmp.r1.setSize(camera.viewportWidth, camera.viewportHeight).setCenter(camera.position.x, camera.position.y).overlaps(enemy.hitbox.getRect(enemy.x, enemy.y))) { + if (rect.setSize(camera.viewportWidth, camera.viewportHeight).setCenter(camera.position.x, camera.position.y) + .overlaps(enemy.hitbox.getRect(enemy.x, enemy.y))) { continue; } diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index 9120f9f0c5..c746111a9d 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -17,7 +17,6 @@ import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Tmp; import io.anuke.ucore.util.Translator; import java.nio.ByteBuffer; @@ -290,10 +289,10 @@ public class Player extends SyncEntity{ i.time += 1f / i.spacing * Timers.delta(); - Mathf.lerp2(Tmp.v2.set(i.last), i.target, i.time); + Mathf.lerp2(movement.set(i.last), i.target, i.time); - x = Tmp.v2.x; - y = Tmp.v2.y; + x = movement.x; + y = movement.y; if(i.target.dst(x, y) > 128){ set(i.target.x, i.target.y); diff --git a/core/src/io/anuke/mindustry/entities/SyncEntity.java b/core/src/io/anuke/mindustry/entities/SyncEntity.java index cc04e55647..ada5cb5ed0 100644 --- a/core/src/io/anuke/mindustry/entities/SyncEntity.java +++ b/core/src/io/anuke/mindustry/entities/SyncEntity.java @@ -50,6 +50,7 @@ public abstract class SyncEntity extends DestructibleEntity{ public class Interpolator { public Vector2 target = new Vector2(); public Vector2 last = new Vector2(); + public Vector2 vec = new Vector2(); public float targetrot; public float spacing = 1f; public float time; diff --git a/core/src/io/anuke/mindustry/entities/effect/TeslaOrb.java b/core/src/io/anuke/mindustry/entities/effect/TeslaOrb.java index 1bd5848d31..3d5d29faf3 100644 --- a/core/src/io/anuke/mindustry/entities/effect/TeslaOrb.java +++ b/core/src/io/anuke/mindustry/entities/effect/TeslaOrb.java @@ -4,19 +4,18 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ObjectSet; - -import static io.anuke.mindustry.Vars.*; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.graphics.Fx; -import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.SolidEntity; +import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Tmp; + +import static io.anuke.mindustry.Vars.enemyGroup; public class TeslaOrb extends Entity{ private Array points = new Array<>(); @@ -25,6 +24,7 @@ public class TeslaOrb extends Entity{ private float range = 0; private float lifetime = 30f; private float life = 0f; + private Vector2 vector = new Vector2(); public TeslaOrb(float x, float y, float range, int damage){ set(x, y); @@ -83,7 +83,7 @@ public class TeslaOrb extends Entity{ float range = 1f; - Vector2 previous = Tmp.v1.set(x, y); + Vector2 previous = vector.set(x, y); for(Vector2 enemy : points){ diff --git a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java index da2e03db53..08c4edf1c5 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java +++ b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java @@ -154,10 +154,10 @@ public class Enemy extends SyncEntity { i.time += 1f / i.spacing * Timers.delta(); - Mathf.lerp2(Tmp.v2.set(i.last), i.target, i.time); + Mathf.lerp2(i.vec.set(i.last), i.target, i.time); - x = Tmp.v2.x; - y = Tmp.v2.y; + x = i.vec.x; + y = i.vec.y; angle = Mathf.lerpAngDelta(angle, i.targetrot, 0.6f); } diff --git a/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java b/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java index 9a48827641..9cc5725220 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/EnemyType.java @@ -19,7 +19,6 @@ import io.anuke.ucore.entities.Entities; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Strings; -import io.anuke.ucore.util.Tmp; import static io.anuke.mindustry.Vars.*; @@ -60,6 +59,10 @@ public class EnemyType { protected final int timerReload = timeid ++; protected final int timerReset = timeid ++; + protected final Vector2 shift = new Vector2(); + protected final Vector2 move = new Vector2(); + protected final Vector2 calc = new Vector2(); + public EnemyType(String name){ this.id = lastid++; this.name = name; @@ -158,14 +161,14 @@ public class EnemyType { Vector2 vec; if(nearCore){ - vec = Tmp.v1.setZero(); + vec = move.setZero(); if(targetCore) enemy.target = core.entity; }else{ vec = world.pathfinder().find(enemy); vec.sub(enemy.x, enemy.y).limit(speed); } - Vector2 shift = Tmp.v3.setZero(); + shift.setZero(); float shiftRange = enemy.hitbox.width + 2f; float avoidRange = shiftRange + 4f; float attractRange = avoidRange + 7f; @@ -180,11 +183,11 @@ public class EnemyType { float scl = Mathf.clamp(1.4f - dst / shiftRange) * mass * 1f/mass; shift.add((enemy.x - other.x) * scl, (enemy.y - other.y) * scl); }else if(dst < avoidRange){ - Tmp.v2.set((enemy.x - other.x), (enemy.y - other.y)).setLength(avoidSpeed); - shift.add(Tmp.v2.scl(1.1f)); + calc.set((enemy.x - other.x), (enemy.y - other.y)).setLength(avoidSpeed); + shift.add(calc.scl(1.1f)); }else if(dst < attractRange && !nearCore){ - Tmp.v2.set((enemy.x - other.x), (enemy.y - other.y)).setLength(avoidSpeed); - shift.add(Tmp.v2.scl(-1)); + calc.set((enemy.x - other.x), (enemy.y - other.y)).setLength(avoidSpeed); + shift.add(calc.scl(-1)); } }); diff --git a/core/src/io/anuke/mindustry/entities/enemies/types/BlastType.java b/core/src/io/anuke/mindustry/entities/enemies/types/BlastType.java index 00d580808f..5ce1e804ed 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/types/BlastType.java +++ b/core/src/io/anuke/mindustry/entities/enemies/types/BlastType.java @@ -1,12 +1,10 @@ package io.anuke.mindustry.entities.enemies.types; -import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.entities.enemies.EnemyType; -import io.anuke.ucore.util.Tmp; import static io.anuke.mindustry.Vars.tilesize; @@ -26,15 +24,16 @@ public class BlastType extends EnemyType { public void behavior(Enemy enemy){ float range = 10f; - Vector2 offset = Tmp.v3.setZero(); + float ox = 0, oy = 0; if(enemy.target instanceof TileEntity){ TileEntity e = (TileEntity)enemy.target; range = (e.tile.block().width * tilesize) /2f + 8f; - offset.set(e.tile.block().getPlaceOffset()); + ox = e.tile.block().getPlaceOffset().x; + oy = e.tile.block().getPlaceOffset().y; } - if(enemy.target != null && enemy.target.distanceTo(enemy.x - offset.x, enemy.y - offset.y) < range){ + if(enemy.target != null && enemy.target.distanceTo(enemy.x - ox, enemy.y - oy) < range){ explode(enemy); } } diff --git a/core/src/io/anuke/mindustry/graphics/Shaders.java b/core/src/io/anuke/mindustry/graphics/Shaders.java index eb26c012c4..61e04d8861 100644 --- a/core/src/io/anuke/mindustry/graphics/Shaders.java +++ b/core/src/io/anuke/mindustry/graphics/Shaders.java @@ -1,18 +1,19 @@ package io.anuke.mindustry.graphics; import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.FloatArray; - import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Settings; import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Shader; import io.anuke.ucore.scene.ui.layout.Unit; -import io.anuke.ucore.util.Tmp; public class Shaders{ public static final Outline outline = new Outline(); public static final Shield shield = new Shield(); + + private static final Vector2 vec = new Vector2(); public static class Outline extends Shader{ public Color color = new Color(); @@ -26,7 +27,7 @@ public class Shaders{ public void apply(){ shader.setUniformf("u_color", color); shader.setUniformf("u_lighten", lighten); - shader.setUniformf("u_texsize", Tmp.v1.set(region.getTexture().getWidth(), region.getTexture().getHeight())); + shader.setUniformf("u_texsize", vec.set(region.getTexture().getWidth(), region.getTexture().getHeight())); } } @@ -52,8 +53,8 @@ public class Shaders{ shader.setUniformf("u_color", color); shader.setUniformf("u_time", Timers.time() / Unit.dp.scl(1f)); shader.setUniformf("u_scaling", scaling); - shader.setUniformf("u_offset", Tmp.v1.set(Core.camera.position.x, Core.camera.position.y)); - shader.setUniformf("u_texsize", Tmp.v1.set(region.getTexture().getWidth() / scale, + shader.setUniformf("u_offset", vec.set(Core.camera.position.x, Core.camera.position.y)); + shader.setUniformf("u_texsize", vec.set(region.getTexture().getWidth() / scale, region.getTexture().getHeight() / scale)); } diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index 128346a7fd..948c790811 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -23,7 +23,6 @@ import io.anuke.ucore.core.Sounds; import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Tmp; import static io.anuke.mindustry.Vars.*; @@ -36,6 +35,8 @@ public abstract class InputHandler extends InputAdapter{ public PlaceMode lastPlaceMode = placeMode; public PlaceMode lastBreakMode = breakMode; + private Rectangle rect = new Rectangle(); + public abstract void update(); public abstract float getCursorX(); public abstract float getCursorY(); @@ -93,21 +94,21 @@ public abstract class InputHandler extends InputAdapter{ } } - Tmp.r2.setSize(type.width * tilesize, type.height * tilesize); + rect.setSize(type.width * tilesize, type.height * tilesize); Vector2 offset = type.getPlaceOffset(); - Tmp.r2.setCenter(offset.x + x * tilesize, offset.y + y * tilesize); + rect.setCenter(offset.x + x * tilesize, offset.y + y * tilesize); for(SolidEntity e : Entities.getNearby(enemyGroup, x * tilesize, y * tilesize, tilesize * 2f)){ Rectangle rect = e.hitbox.getRect(e.x, e.y); - if(Tmp.r2.overlaps(rect)){ + if(this.rect.overlaps(rect)){ return false; } } if(type.solid || type.solidifes) { for (Player player : playerGroup.all()) { - if (!player.isAndroid && Tmp.r2.overlaps(player.hitbox.getRect(player.x, player.y))) { + if (!player.isAndroid && rect.overlaps(player.hitbox.getRect(player.x, player.y))) { return false; } } diff --git a/core/src/io/anuke/mindustry/input/PlaceMode.java b/core/src/io/anuke/mindustry/input/PlaceMode.java index 39035ae2c2..a6e69adad7 100644 --- a/core/src/io/anuke/mindustry/input/PlaceMode.java +++ b/core/src/io/anuke/mindustry/input/PlaceMode.java @@ -12,7 +12,7 @@ import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Tmp; +import io.anuke.ucore.util.Translator; import static io.anuke.mindustry.Vars.*; @@ -44,8 +44,8 @@ public enum PlaceMode{ if(control.input().recipe.result.rotate){ Draw.color(Colors.get("placeRotate")); - Tmp.v1.set(7, 0).rotate(control.input().rotation * 90); - Lines.line(x, y, x + Tmp.v1.x, y + Tmp.v1.y); + tr.trns(control.input().rotation * 90, 7, 0); + Lines.line(x, y, x + tr.x, y + tr.y); } } @@ -293,8 +293,8 @@ public enum PlaceMode{ if(control.input().recipe.result.rotate){ float cx = tx * t, cy = ty * t; Draw.color(Colors.get("placeRotate")); - Tmp.v1.set(7, 0).rotate(rotation * 90); - Lines.line(cx, cy, cx + Tmp.v1.x, cy + Tmp.v1.y); + tr.trns(rotation * 90, 7, 0); + Lines.line(cx, cy, cx + tr.x, cy + tr.y); } Draw.reset(); } @@ -368,6 +368,8 @@ public enum PlaceMode{ public boolean showCancel; public boolean delete = false; public boolean both = false; + + private static final Translator tr = new Translator(); public void draw(int tilex, int tiley, int endx, int endy){ diff --git a/core/src/io/anuke/mindustry/mapeditor/MapView.java b/core/src/io/anuke/mindustry/mapeditor/MapView.java index a4acd5970a..29c62a7e08 100644 --- a/core/src/io/anuke/mindustry/mapeditor/MapView.java +++ b/core/src/io/anuke/mindustry/mapeditor/MapView.java @@ -9,6 +9,7 @@ import com.badlogic.gdx.input.GestureDetector; import com.badlogic.gdx.input.GestureDetector.GestureListener; import com.badlogic.gdx.math.Bresenham2; import com.badlogic.gdx.math.GridPoint2; +import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack; import com.badlogic.gdx.utils.Array; @@ -43,6 +44,8 @@ public class MapView extends Element implements GestureListener{ private float zoom = 1f; private boolean grid = false; private GridImage image = new GridImage(0, 0); + private Vector2 vec = new Vector2(); + private Rectangle rect = new Rectangle(); private boolean drawing; private int lastx, lasty; @@ -214,7 +217,7 @@ public class MapView extends Element implements GestureListener{ float px = ((float)x / editor.texture().getWidth()) * sclwidth + offsetx*zoom - sclwidth/2 + getWidth()/2; float py = (float)((float)(editor.texture().getHeight() - 1 - y) / editor.texture().getHeight()) * sclheight + offsety*zoom - sclheight/2 + getHeight()/2; - return Tmp.v1.set(px, py); + return vec.set(px, py); } @Override @@ -229,7 +232,7 @@ public class MapView extends Element implements GestureListener{ image.setImageSize(editor.pixmap().getWidth(), editor.pixmap().getHeight()); batch.flush(); - boolean pop = ScissorStack.pushScissors(Tmp.r1.set(x + width/2 - size/2, y + height/2 - size/2, size, size)); + boolean pop = ScissorStack.pushScissors(rect.set(x + width/2 - size/2, y + height/2 - size/2, size, size)); batch.draw(editor.texture(), centerx - sclwidth/2, centery - sclheight/2, sclwidth, sclheight); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java index 63dff4f4b0..19f8f95ab9 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.ui.dialogs; import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.game.Difficulty; import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.world.Map; @@ -16,7 +17,6 @@ import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.utils.Elements; import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Tmp; import static io.anuke.mindustry.Vars.*; @@ -133,13 +133,15 @@ public class LevelDialog extends FloatingDialog{ }); }).width(images+16).padBottom(-10f).grow().get(); } + + Vector2 hit = new Vector2(); image.addListener(new ClickListener(){ public void clicked(InputEvent event, float x, float y){ - image.localToStageCoordinates(Tmp.v1.set(x, y)); + image.localToStageCoordinates(hit.set(x, y)); if(delete[0] != null && (delete[0].getClickListener().isOver() || delete[0].getClickListener().isPressed() - || (Core.scene.hit(Tmp.v1.x, Tmp.v1.y, true) != null && - Core.scene.hit(Tmp.v1.x, Tmp.v1.y, true).isDescendantOf(delete[0])))){ + || (Core.scene.hit(hit.x, hit.y, true) != null && + Core.scene.hit(hit.x, hit.y, true).isDescendantOf(delete[0])))){ return; } diff --git a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java index ddb8aec8b7..ce5cb721f7 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/DebugFragment.java @@ -2,7 +2,6 @@ package io.anuke.mindustry.ui.fragments; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.net.Net; import io.anuke.ucore.scene.builders.button; @@ -50,7 +49,7 @@ public class DebugFragment implements Fragment { row(); new button("infammo", "toggle", () -> infiniteAmmo = !infiniteAmmo); row(); - new button("wave", () -> logic.runWave()); + new button("wave", () -> state.wavetime = 0f); row(); new button("clear", () -> { enemyGroup.clear(); @@ -58,9 +57,7 @@ public class DebugFragment implements Fragment { netClient.clearRecieved(); }); row(); - new button("spawn", () -> {try{ Net.connect("localhost", Vars.port); }catch (Exception e){e.printStackTrace();}}); - row(); - new button("stuff", () -> netClient.test()); + new button("spawn", () -> {}); row(); }}.end(); diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java index ffc46f7cb7..1b72bf365a 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java @@ -194,7 +194,7 @@ public class HudFragment implements Fragment{ private void playButton(float uheight){ new imagebutton("icon-play", 30f, () -> { - logic.runWave(); + state.wavetime = 0f; }).height(uheight).fillX().right().padTop(-8f).padBottom(-12f).padRight(-36).width(40f).update(l->{ boolean vis = state.enemies <= 0 && (Net.server() || !Net.active()); boolean paused = state.is(State.paused) || !vis; diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index 2e047c9c3a..311490b56d 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -19,7 +19,6 @@ import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Tmp; import static io.anuke.mindustry.Vars.state; import static io.anuke.mindustry.Vars.tilesize; @@ -30,6 +29,7 @@ public class Block{ private static ObjectMap map = new ObjectMap<>(); protected static TextureRegion temp = new TextureRegion(); + protected Vector2 offset = new Vector2(); /**internal name*/ public final String name; @@ -272,7 +272,7 @@ public class Block{ /**Offset for placing and drawing multiblocks.*/ public Vector2 getPlaceOffset(){ - return Tmp.v3.set(((width + 1) % 2) * tilesize/2, ((height + 1) % 2) * tilesize/2); + return offset.set(((width + 1) % 2) * tilesize/2, ((height + 1) % 2) * tilesize/2); } public boolean isMultiblock(){ diff --git a/core/src/io/anuke/mindustry/world/blocks/types/defense/Door.java b/core/src/io/anuke/mindustry/world/blocks/types/defense/Door.java index 95ffcc8930..265ecccddb 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/defense/Door.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/defense/Door.java @@ -11,7 +11,6 @@ import io.anuke.ucore.core.Effects.Effect; import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.Tmp; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -20,6 +19,8 @@ import java.io.IOException; import static io.anuke.mindustry.Vars.*; public class Door extends Wall{ + protected final Rectangle rect = new Rectangle(); + protected Effect openfx = Fx.dooropen; protected Effect closefx = Fx.doorclose; @@ -65,13 +66,13 @@ public class Door extends Wall{ boolean anyEntities(Tile tile){ int x = tile.x, y = tile.y; Block type = tile.block(); - Tmp.r2.setSize(type.width * tilesize, type.height * tilesize); - Tmp.r2.setCenter(tile.drawx(), tile.drawy()); + rect.setSize(type.width * tilesize, type.height * tilesize); + rect.setCenter(tile.drawx(), tile.drawy()); for(SolidEntity e : Entities.getNearby(enemyGroup, x * tilesize, y * tilesize, tilesize * 2f)){ Rectangle rect = e.hitbox.getRect(e.x, e.y); - if(Tmp.r2.overlaps(rect)){ + if(rect.overlaps(rect)){ return true; } } @@ -79,7 +80,7 @@ public class Door extends Wall{ for(SolidEntity e : Entities.getNearby(playerGroup, x * tilesize, y * tilesize, tilesize * 2f)){ Rectangle rect = e.hitbox.getRect(e.x, e.y); - if(Tmp.r2.overlaps(rect)){ + if(rect.overlaps(rect)){ return true; } } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java index b0769886ba..cc46d45bad 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java @@ -9,10 +9,7 @@ import io.anuke.mindustry.world.Layer; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.Bits; -import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Strings; -import io.anuke.ucore.util.Tmp; +import io.anuke.ucore.util.*; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -31,6 +28,9 @@ public class Conveyor extends Block{ private static final float itemSpace = 0.135f; private static final float offsetScl = 128f*3f; private static final float itemSize = 4f; + + private final Translator tr1 = new Translator(); + private final Translator tr2 = new Translator(); public float speed = 0.02f; @@ -76,13 +76,13 @@ public class Conveyor extends Block{ ItemPos pos = drawpos.set(entity.convey.get(i)); if(pos.item == null) continue; - - Tmp.v1.set(tilesize, 0).rotate(rotation * 90); - Tmp.v2.set(-tilesize / 2, pos.x*tilesize/2).rotate(rotation * 90); + + tr1.trns(rotation * 90, tilesize, 0); + tr2.trns(rotation * 90, -tilesize / 2, pos.x*tilesize/2); Draw.rect(pos.item.region, - tile.x * tilesize + Tmp.v1.x * pos.y + Tmp.v2.x, - tile.y * tilesize + Tmp.v1.y * pos.y + Tmp.v2.y, itemSize, itemSize); + tile.x * tilesize + tr1.x * pos.y + tr2.x, + tile.y * tilesize + tr1.y * pos.y + tr2.y, itemSize, itemSize); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java b/core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java index be72ccfb45..5a597eb7a6 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java @@ -14,7 +14,7 @@ import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Strings; -import io.anuke.ucore.util.Tmp; +import io.anuke.ucore.util.Translator; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -25,6 +25,8 @@ import static io.anuke.mindustry.Vars.tilesize; public class NuclearReactor extends LiquidPowerGenerator{ protected final int timerFuel = timers++; + protected final Translator tr = new Translator(); + protected Item generateItem; protected int itemCapacity = 30; protected Color coolColor = new Color(1, 1, 1, 0f); @@ -137,15 +139,15 @@ public class NuclearReactor extends LiquidPowerGenerator{ for(int i = 0; i < 20; i ++){ Timers.run(Mathf.random(50), ()->{ - Tmp.v1.setToRandomDirection().setLength(Mathf.random(40f)); - Effects.effect(Fx.explosion, Tmp.v1.x + tile.worldx(), Tmp.v1.y + tile.worldy()); + tr.rnd(Mathf.random(40f)); + Effects.effect(Fx.explosion, tr.x + tile.worldx(), tr.y + tile.worldy()); }); } for(int i = 0; i < 70; i ++){ Timers.run(Mathf.random(80), ()->{ - Tmp.v1.setToRandomDirection().setLength(Mathf.random(120f)); - Effects.effect(Fx.nuclearsmoke, Tmp.v1.x + tile.worldx(), Tmp.v1.y + tile.worldy()); + tr.rnd(Mathf.random(120f)); + Effects.effect(Fx.nuclearsmoke, tr.x + tile.worldx(), tr.y + tile.worldy()); }); } } From 1a6f773ddb5a228b8174f1892c140d0a6e6eb0d9 Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 6 Feb 2018 18:52:36 -0500 Subject: [PATCH 3/8] Fixed tunnel conveyors outputting only stone --- .../world/blocks/types/distribution/TunnelConveyor.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java index a68b7ed7ab..6fd170fda9 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/TunnelConveyor.java @@ -35,7 +35,7 @@ public class TunnelConveyor extends Block{ Tile to = tunnel.getNearby(tunnel.getRotation()); if(to == null) return; - entity.buffer[entity.index ++] = item.id; + entity.buffer[entity.index ++] = Bits.packLong(NumberUtils.floatToIntBits(Timers.time()), item.id); } @Override @@ -48,9 +48,7 @@ public class TunnelConveyor extends Block{ if(Timers.time() >= time + speed){ - int val = Bits.getRightInt(l); - - Item item = Item.getByID(Bits.getLeftShort(val)); + Item item = Item.getByID(Bits.getRightInt(l)); Tile tunnel = getDestTunnel(tile, item); if(tunnel == null) return; From 460558bc87c197002961fdf1ac923730052d5c7c Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 7 Feb 2018 14:47:39 -0500 Subject: [PATCH 4/8] Implemented toggling of multithreading --- .../io/anuke/mindustry/AndroidLauncher.java | 7 + core/assets/bundles/bundle.properties | 1 + core/src/io/anuke/mindustry/Mindustry.java | 52 +------ core/src/io/anuke/mindustry/Vars.java | 2 + core/src/io/anuke/mindustry/core/Control.java | 7 + core/src/io/anuke/mindustry/core/Logic.java | 6 +- .../anuke/mindustry/core/ThreadHandler.java | 82 +++++++++++ .../anuke/mindustry/entities/TileEntity.java | 4 +- core/src/io/anuke/mindustry/io/Platform.java | 24 ++++ .../ui/dialogs/SettingsMenuDialog.java | 9 ++ .../blocks/types/distribution/Conveyor.java | 127 +++++++++--------- .../mindustry/desktop/DesktopPlatform.java | 7 + .../io/anuke/kryonet/DefaultThreadImpl.java | 40 ++++++ 13 files changed, 248 insertions(+), 120 deletions(-) create mode 100644 core/src/io/anuke/mindustry/core/ThreadHandler.java create mode 100644 kryonet/src/io/anuke/kryonet/DefaultThreadImpl.java diff --git a/android/src/io/anuke/mindustry/AndroidLauncher.java b/android/src/io/anuke/mindustry/AndroidLauncher.java index 77b79e5c31..0dbcb13cac 100644 --- a/android/src/io/anuke/mindustry/AndroidLauncher.java +++ b/android/src/io/anuke/mindustry/AndroidLauncher.java @@ -9,8 +9,10 @@ import android.os.Bundle; import android.telephony.TelephonyManager; import com.badlogic.gdx.backends.android.AndroidApplication; import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; +import io.anuke.kryonet.DefaultThreadImpl; import io.anuke.kryonet.KryoClient; import io.anuke.kryonet.KryoServer; +import io.anuke.mindustry.core.ThreadHandler.ThreadProvider; import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.net.Net; import io.anuke.ucore.scene.ui.TextField; @@ -85,6 +87,11 @@ public class AndroidLauncher extends AndroidApplication{ } } } + + @Override + public ThreadProvider getThreadProvider() { + return new DefaultThreadImpl(); + } }; if(doubleScaleTablets && isTablet(this.getContext())){ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index ffb08eff5c..e41cf25858 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -217,6 +217,7 @@ setting.sensitivity.name=Controller Sensitivity setting.saveinterval.name=Autosave Interval setting.seconds={0} Seconds setting.fullscreen.name=Fullscreen +setting.multithread.name=Multithreading [scarlet](unstable!) setting.fps.name=Show FPS setting.vsync.name=VSync setting.lasers.name=Show Power Lasers diff --git a/core/src/io/anuke/mindustry/Mindustry.java b/core/src/io/anuke/mindustry/Mindustry.java index 7ea13b75b2..1bc490e7d4 100644 --- a/core/src/io/anuke/mindustry/Mindustry.java +++ b/core/src/io/anuke/mindustry/Mindustry.java @@ -1,21 +1,15 @@ package io.anuke.mindustry; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.utils.TimeUtils; import io.anuke.mindustry.core.*; import io.anuke.mindustry.io.BlockLoader; import io.anuke.mindustry.io.BundleLoader; import io.anuke.mindustry.io.Platform; -import io.anuke.ucore.core.Timers; import io.anuke.ucore.modules.ModuleCore; import io.anuke.ucore.util.Log; import static io.anuke.mindustry.Vars.*; public class Mindustry extends ModuleCore { - boolean multithread = true; - Thread thread; - float delta = 1f; @Override public void init(){ @@ -25,10 +19,7 @@ public class Mindustry extends ModuleCore { BundleLoader.load(); BlockLoader.load(); - logic = new Logic(); - - if(!multithread) module(logic); - + module(logic = new Logic()); module(world = new World()); module(control = new Control()); module(renderer = new Renderer()); @@ -36,49 +27,12 @@ public class Mindustry extends ModuleCore { module(netServer = new NetServer()); module(netClient = new NetClient()); module(netCommon = new NetCommon()); - - Timers.setDeltaProvider(() -> - Math.min(Thread.currentThread() == thread ? delta : Gdx.graphics.getDeltaTime()*60f, 20f) - ); - - if(multithread) { - - logic.init(); - - thread = new Thread(() -> { - try { - while (true) { - long time = TimeUtils.millis(); - logic.update(); - long elapsed = TimeUtils.timeSinceMillis(time); - long target = (long) (1000 / 60f); - - delta = Math.max(elapsed, target) / 1000f * 60f; - - if (elapsed < target) { - Thread.sleep(target - elapsed); - } - } - } catch (Exception ex) { - Gdx.app.postRunnable(() -> { - throw new RuntimeException(ex); - }); - } - }); - thread.setDaemon(true); - thread.setName("Update Thread"); - thread.start(); - } } + @Override public void render(){ super.render(); - - try { - //Thread.sleep(40); - }catch (Exception e){ - e.printStackTrace(); - } + threads.handleRender(); } } diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index 509b4550a1..d2032630c4 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -10,6 +10,7 @@ import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.effect.Shield; import io.anuke.mindustry.entities.enemies.Enemy; +import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.net.ClientDebug; import io.anuke.mindustry.net.ServerDebug; import io.anuke.ucore.UCore; @@ -112,6 +113,7 @@ public class Vars{ public static final int webPort = 6568; public static final GameState state = new GameState(); + public static final ThreadHandler threads = new ThreadHandler(Platform.instance.getThreadProvider()); public static final ServerDebug serverDebug = new ServerDebug(); public static final ClientDebug clientDebug = new ClientDebug(); diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index ba1980090c..89cb4cbe08 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -268,6 +268,13 @@ public class Control extends Module{ Entities.collisions().setCollider(tilesize, world::solid); Platform.instance.updateRPC(); + + //TODO remove + /* + Timers.runTask(2, () -> { + state.set(State.playing); + SaveIO.loadFromSlot(0); + });*/ } @Override diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index 993dd6a528..3491b81a3a 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -1,6 +1,5 @@ package io.anuke.mindustry.core; -import com.badlogic.gdx.Gdx; import com.badlogic.gdx.utils.Array; import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.GameState.State; @@ -35,10 +34,6 @@ import static io.anuke.mindustry.Vars.*; public class Logic extends Module { private final Array spawns = WaveCreator.getSpawns(); - public Logic(){ - Timers.setDeltaProvider(() -> Math.min(Gdx.graphics.getDeltaTime()*60f, 60)); - } - @Override public void init(){ Entities.initPhysics(); @@ -111,6 +106,7 @@ public class Logic extends Module { @Override public void update(){ + if(!state.is(State.paused) || Net.active()){ Timers.update(); } diff --git a/core/src/io/anuke/mindustry/core/ThreadHandler.java b/core/src/io/anuke/mindustry/core/ThreadHandler.java new file mode 100644 index 0000000000..0b46272c55 --- /dev/null +++ b/core/src/io/anuke/mindustry/core/ThreadHandler.java @@ -0,0 +1,82 @@ +package io.anuke.mindustry.core; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.utils.TimeUtils; +import io.anuke.ucore.core.Timers; +import io.anuke.ucore.util.Log; + +import static io.anuke.mindustry.Vars.logic; + +public class ThreadHandler { + private final ThreadProvider impl; + private final Object lock = new Object(); + private float delta = 1f; + private boolean finished; + private boolean enabled; + + public ThreadHandler(ThreadProvider impl){ + this.impl = impl; + + Timers.setDeltaProvider(() -> impl.isOnThread() ? delta : Gdx.graphics.getDeltaTime()*60f); + } + + public void handleRender(){ + synchronized(lock) { + finished = true; + lock.notify(); + } + } + + public void setEnabled(boolean enabled){ + if(enabled){ + logic.doUpdate = false; + Timers.runTask(2f, () -> impl.start(this::runLogic)); + }else{ + impl.stop(); + Timers.runTask(2f, () -> logic.doUpdate = true); + } + this.enabled = enabled; + } + + public boolean isEnabled(){ + return enabled; + } + + private void runLogic(){ + try { + while (true) { + long time = TimeUtils.millis(); + logic.update(); + + long elapsed = TimeUtils.timeSinceMillis(time); + long target = (long) (1000 / 60f); + + delta = Math.max(elapsed, target) / 1000f * 60f; + + if (elapsed < target) { + impl.sleep(target - elapsed); + } + + synchronized(lock) { + while(!finished) { + lock.wait(); + } + finished = false; + } + } + } catch (InterruptedException ex) { + Log.info("Stopping logic thread."); + } catch (Exception ex) { + Gdx.app.postRunnable(() -> { + throw new RuntimeException(ex); + }); + } + } + + public interface ThreadProvider { + boolean isOnThread(); + void sleep(long ms) throws InterruptedException; + void start(Runnable run); + void stop(); + } +} diff --git a/core/src/io/anuke/mindustry/entities/TileEntity.java b/core/src/io/anuke/mindustry/entities/TileEntity.java index 816ddb428b..38631d9893 100644 --- a/core/src/io/anuke/mindustry/entities/TileEntity.java +++ b/core/src/io/anuke/mindustry/entities/TileEntity.java @@ -108,10 +108,10 @@ public class TileEntity extends Entity{ public void update(){ if(health != 0 && health < tile.block().health && !(tile.block() instanceof Wall) && Mathf.chance(0.009f*Timers.delta()*(1f-health/tile.block().health))){ - + Effects.effect(Fx.smoke, x+Mathf.range(4), y+Mathf.range(4)); } - + if(health <= 0){ onDeath(); } diff --git a/core/src/io/anuke/mindustry/io/Platform.java b/core/src/io/anuke/mindustry/io/Platform.java index ca2ae7c48e..9c0aab5fdd 100644 --- a/core/src/io/anuke/mindustry/io/Platform.java +++ b/core/src/io/anuke/mindustry/io/Platform.java @@ -1,5 +1,6 @@ package io.anuke.mindustry.io; +import io.anuke.mindustry.core.ThreadHandler.ThreadProvider; import io.anuke.ucore.scene.ui.TextField; import java.util.Date; @@ -27,4 +28,27 @@ public abstract class Platform { return true; } public boolean isDebug(){return false;} + public ThreadProvider getThreadProvider(){ + return new ThreadProvider() { + @Override + public boolean isOnThread() { + return true; + } + + @Override + public void sleep(long ms) { + + } + + @Override + public void start(Runnable run) { + + } + + @Override + public void stop() { + + } + }; + } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java index 780701f399..ca0c126cf6 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -113,6 +113,14 @@ public class SettingsMenuDialog extends SettingsDialog{ game.sliderPref("sensitivity", 100, 10, 300, i -> i + "%"); game.sliderPref("saveinterval", 90, 10, 5*120, i -> Bundles.format("setting.seconds", i)); + if(!gwt){ + graphics.checkPref("multithread", false, threads::setEnabled); + + if(Settings.getBool("multithread")){ + threads.setEnabled(true); + } + } + if(!android && !gwt) { graphics.checkPref("vsync", true, b -> Gdx.graphics.setVSync(b)); graphics.checkPref("fullscreen", false, b -> { @@ -128,6 +136,7 @@ public class SettingsMenuDialog extends SettingsDialog{ Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode()); } } + graphics.checkPref("fps", false); graphics.checkPref("lasers", true); graphics.checkPref("indicators", true); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java index cc46d45bad..dac7eeff7f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java @@ -28,36 +28,37 @@ public class Conveyor extends Block{ private static final float itemSpace = 0.135f; private static final float offsetScl = 128f*3f; private static final float itemSize = 4f; + private static final float minmove = 1f / (Short.MAX_VALUE - 2); private final Translator tr1 = new Translator(); private final Translator tr2 = new Translator(); - + public float speed = 0.02f; - + protected Conveyor(String name) { super(name); rotate = true; update = true; layer = Layer.overlay; } - + @Override public void getStats(Array list){ super.getStats(list); list.add("[iteminfo]Item Speed/second: " + Strings.toFixed(speed * 60, 1)); } - + @Override public boolean canReplace(Block other){ return other instanceof Conveyor || other instanceof Router || other instanceof Junction; } - + @Override public void draw(Tile tile){ byte rotation = tile.getRotation(); - - Draw.rect(name() + - (Timers.time() % ((20 / 100f) / speed) < (10 / 100f) / speed && acceptItem(Item.stone, tile, null) ? "" : "move"), + + Draw.rect(name() + + (Timers.time() % ((20 / 100f) / speed) < (10 / 100f) / speed && acceptItem(Item.stone, tile, null) ? "" : "move"), tile.worldx(), tile.worldy(), rotation * 90); } @@ -65,13 +66,13 @@ public class Conveyor extends Block{ public boolean isLayer(Tile tile){ return tile.entity().convey.size > 0; } - + @Override - public void drawLayer(Tile tile){ + public synchronized void drawLayer(Tile tile){ ConveyorEntity entity = tile.entity(); - + byte rotation = tile.getRotation(); - + for(int i = 0; i < entity.convey.size; i ++){ ItemPos pos = drawpos.set(entity.convey.get(i)); @@ -79,19 +80,19 @@ public class Conveyor extends Block{ tr1.trns(rotation * 90, tilesize, 0); tr2.trns(rotation * 90, -tilesize / 2, pos.x*tilesize/2); - + Draw.rect(pos.item.region, tile.x * tilesize + tr1.x * pos.y + tr2.x, tile.y * tilesize + tr1.y * pos.y + tr2.y, itemSize, itemSize); } } - + @Override - public void update(Tile tile){ - + public synchronized void update(Tile tile){ + ConveyorEntity entity = tile.entity(); entity.minitem = 1f; - + removals.clear(); float shift = entity.elapsed * speed; @@ -106,37 +107,35 @@ public class Conveyor extends Block{ removals.add(value); continue; } - - boolean canmove = i == entity.convey.size - 1 || - !(pos2.set(entity.convey.get(i + 1)).y - pos.y < itemSpace * Math.max(Timers.delta(), 1f)); - float minmove = 1f / (Short.MAX_VALUE - 2); + float nextpos = (i == entity.convey.size - 1 ? 100f : pos2.set(entity.convey.get(i + 1)).y) - itemSpace; + float maxmove = Math.min(nextpos - pos.y, speed * Timers.delta()); - if(canmove){ - pos.y += Math.max(speed * Timers.delta(), minmove); //TODO fix precision issues when at high FPS? + if(maxmove > minmove){ + pos.y += maxmove; pos.x = Mathf.lerpDelta(pos.x, 0, 0.06f); }else{ pos.x = Mathf.lerpDelta(pos.x, pos.seed/offsetScl, 0.1f); } - + pos.y = Mathf.clamp(pos.y); - + if(pos.y >= 0.9999f && offloadDir(tile, pos.item)){ removals.add(value); }else{ value = pos.pack(); - + if(pos.y < entity.minitem) entity.minitem = pos.y; entity.convey.set(i, value); } - + } entity.elapsed = 0f; entity.convey.removeAll(removals); } - + @Override public TileEntity getEntity(){ return new ConveyorEntity(); @@ -146,25 +145,25 @@ public class Conveyor extends Block{ public boolean acceptItem(Item item, Tile tile, Tile source){ int direction = source == null ? 0 : Math.abs(source.relativeTo(tile.x, tile.y) - tile.getRotation()); float minitem = tile.entity().minitem; - return (((direction == 0) && minitem > 0.05f) || + return (((direction == 0) && minitem > 0.05f) || ((direction %2 == 1) && minitem > 0.52f)) && (source == null || !(source.block().rotate && (source.getRotation() + 2) % 4 == tile.getRotation())); } @Override public void handleItem(Item item, Tile tile, Tile source){ byte rotation = tile.getRotation(); - + int ch = Math.abs(source.relativeTo(tile.x, tile.y) - rotation); int ang = ((source.relativeTo(tile.x, tile.y) - rotation)); - + float pos = ch == 0 ? 0 : ch % 2 == 1 ? 0.5f : 1f; float y = (ang == -1 || ang == 3) ? 1 : (ang == 1 || ang == -3) ? -1 : 0; - + ConveyorEntity entity = tile.entity(); long result = ItemPos.packItem(item, y*0.9f, pos, (byte)Mathf.random(255)); boolean inserted = false; - + for(int i = 0; i < entity.convey.size; i ++){ if(compareItems(result, entity.convey.get(i)) < 0){ entity.convey.insert(i, result); @@ -172,13 +171,13 @@ public class Conveyor extends Block{ break; } } - + //this item must be greater than anything there... if(!inserted){ entity.convey.add(result); } } - + /** * Conveyor data format: * [0] item ordinal @@ -191,26 +190,26 @@ public class Conveyor extends Block{ LongArray convey = new LongArray(); float minitem = 1, elapsed; - + @Override public void write(DataOutputStream stream) throws IOException{ stream.writeInt(convey.size); - + for(int i = 0; i < convey.size; i ++){ stream.writeInt(ItemPos.toInt(convey.get(i))); } } - + @Override public void read(DataInputStream stream) throws IOException{ convey.clear(); int amount = stream.readInt(); convey.ensureCapacity(amount); - + for(int i = 0; i < amount; i ++){ convey.add(ItemPos.toLong(stream.readInt())); } - + sort(convey.items, convey.size); } @@ -220,37 +219,37 @@ public class Conveyor extends Block{ this.elapsed = elapsed; } } - + private static void sort(long[] elements, int length){ List wrapper = new AbstractList() { - @Override - public Long get(int index) { - return elements[index]; - } + @Override + public Long get(int index) { + return elements[index]; + } - @Override - public int size() { - return length; - } + @Override + public int size() { + return length; + } - @Override - public Long set(int index, Long element) { - long v = elements[index]; - elements[index] = element; - return v; - } - }; - - Collections.sort(wrapper, Conveyor::compareItems); + @Override + public Long set(int index, Long element) { + long v = elements[index]; + elements[index] = element; + return v; + } + }; + + Collections.sort(wrapper, Conveyor::compareItems); } - + private static int compareItems(Long a, Long b){ pos1.set(a); pos2.set(b); return Float.compare(pos1.y, pos2.y); } - + //Container class. Do not instantiate. static class ItemPos{ private static short[] writeShort = new short[4]; @@ -259,7 +258,7 @@ public class Conveyor extends Block{ Item item; float x, y; byte seed; - + private ItemPos(){} ItemPos set(long lvalue){ @@ -275,11 +274,11 @@ public class Conveyor extends Block{ seed = (byte)values[3]; return this; } - + long pack(){ return packItem(item, x, y, seed); } - + static long packItem(Item item, float x, float y, byte seed){ short[] shorts = Bits.getShorts(); shorts[0] = (short)item.id; @@ -322,4 +321,4 @@ public class Conveyor extends Block{ return Bits.packLong(shorts); } } -} +} \ No newline at end of file diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java index 7962856ec3..f925c59602 100644 --- a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java @@ -3,7 +3,9 @@ package io.anuke.mindustry.desktop; import club.minnced.discord.rpc.DiscordEventHandlers; import club.minnced.discord.rpc.DiscordRPC; import club.minnced.discord.rpc.DiscordRichPresence; +import io.anuke.kryonet.DefaultThreadImpl; import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.core.ThreadHandler.ThreadProvider; import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.net.Net; import io.anuke.ucore.util.Strings; @@ -85,4 +87,9 @@ public class DesktopPlatform extends Platform { public boolean isDebug() { return args.length > 0 && args[0].equalsIgnoreCase("-debug"); } + + @Override + public ThreadProvider getThreadProvider() { + return new DefaultThreadImpl(); + } } diff --git a/kryonet/src/io/anuke/kryonet/DefaultThreadImpl.java b/kryonet/src/io/anuke/kryonet/DefaultThreadImpl.java new file mode 100644 index 0000000000..64e8b62240 --- /dev/null +++ b/kryonet/src/io/anuke/kryonet/DefaultThreadImpl.java @@ -0,0 +1,40 @@ +package io.anuke.kryonet; + +import io.anuke.mindustry.core.ThreadHandler.ThreadProvider; +import io.anuke.ucore.util.Log; + +public class DefaultThreadImpl implements ThreadProvider { + private Thread thread; + + @Override + public boolean isOnThread() { + return Thread.currentThread() == thread; + } + + @Override + public void sleep(long ms) throws InterruptedException{ + Thread.sleep(ms); + } + + @Override + public void start(Runnable run) { + if(thread != null){ + thread.interrupt(); + thread = null; + } + + thread = new Thread(run); + thread.setDaemon(true); + thread.setName("Update Thread"); + thread.start(); + Log.info("Starting logic thread."); + } + + @Override + public void stop() { + if(thread != null){ + thread.interrupt(); + thread = null; + } + } +} From 153905cf474407501d074ff9937dd2abdad43197 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 7 Feb 2018 16:47:15 -0500 Subject: [PATCH 5/8] Fixed multiple bugs, made multithreading work more properly --- core/src/io/anuke/mindustry/core/Control.java | 2 +- core/src/io/anuke/mindustry/core/Logic.java | 7 ++-- .../anuke/mindustry/core/ThreadHandler.java | 32 ++++++++++++------- .../src/io/anuke/mindustry/game/GameMode.java | 6 ++-- .../anuke/mindustry/input/InputHandler.java | 4 +-- .../mindustry/ui/fragments/HudFragment.java | 2 +- core/src/io/anuke/mindustry/world/Block.java | 2 ++ .../mindustry/world/blocks/types/Rock.java | 1 + .../blocks/types/distribution/Conveyor.java | 14 ++++---- 9 files changed, 41 insertions(+), 29 deletions(-) diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index 89cb4cbe08..5b7125c163 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -172,7 +172,7 @@ public class Control extends Module{ int last = Settings.getInt("hiscore" + world.getMap().name); - if(state.wave > last && !state.mode.infiniteResources && !state.mode.toggleWaves){ + if(state.wave > last && !state.mode.infiniteResources && !state.mode.disableWaveTimer){ Settings.putInt("hiscore" + world.getMap().name, state.wave); Settings.save(); hiscore = true; diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index 3491b81a3a..32f54535c1 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -8,6 +8,7 @@ import io.anuke.mindustry.game.EnemySpawn; import io.anuke.mindustry.game.EventType.GameOverEvent; import io.anuke.mindustry.game.EventType.PlayEvent; import io.anuke.mindustry.game.EventType.ResetEvent; +import io.anuke.mindustry.game.EventType.WaveEvent; import io.anuke.mindustry.game.SpawnPoint; import io.anuke.mindustry.game.WaveCreator; import io.anuke.mindustry.graphics.Fx; @@ -102,6 +103,8 @@ public class Logic extends Module { state.wave ++; state.wavetime = wavespace * state.difficulty.timeScaling; state.extrawavetime = maxwavespace * state.difficulty.maxTimeScaling; + + Events.fire(WaveEvent.class); } @Override @@ -116,7 +119,7 @@ public class Logic extends Module { if(!Net.client()) world.pathfinder().update(); - if(world.getCore().block() != ProductionBlocks.core && !state.gameOver){ + if(world.getCore() != null && world.getCore().block() != ProductionBlocks.core && !state.gameOver){ state.gameOver = true; NetEvents.handleGameOver(); Events.fire(GameOverEvent.class); @@ -124,7 +127,7 @@ public class Logic extends Module { if(!state.is(State.paused) || Net.active()){ - if(!state.mode.toggleWaves){ + if(!state.mode.disableWaveTimer){ if(state.enemies <= 0){ state.wavetime -= delta(); diff --git a/core/src/io/anuke/mindustry/core/ThreadHandler.java b/core/src/io/anuke/mindustry/core/ThreadHandler.java index 0b46272c55..d27ca75ddc 100644 --- a/core/src/io/anuke/mindustry/core/ThreadHandler.java +++ b/core/src/io/anuke/mindustry/core/ThreadHandler.java @@ -9,11 +9,12 @@ import static io.anuke.mindustry.Vars.logic; public class ThreadHandler { private final ThreadProvider impl; - private final Object lock = new Object(); private float delta = 1f; - private boolean finished; private boolean enabled; + private final Object updateLock = new Object(); + private boolean rendered = true; + public ThreadHandler(ThreadProvider impl){ this.impl = impl; @@ -21,21 +22,28 @@ public class ThreadHandler { } public void handleRender(){ - synchronized(lock) { - finished = true; - lock.notify(); + if(!enabled) return; + + synchronized (updateLock) { + rendered = true; + updateLock.notify(); } } public void setEnabled(boolean enabled){ if(enabled){ logic.doUpdate = false; - Timers.runTask(2f, () -> impl.start(this::runLogic)); + Timers.runTask(2f, () -> { + impl.start(this::runLogic); + this.enabled = true; + }); }else{ + this.enabled = false; impl.stop(); - Timers.runTask(2f, () -> logic.doUpdate = true); + Timers.runTask(2f, () -> { + logic.doUpdate = true; + }); } - this.enabled = enabled; } public boolean isEnabled(){ @@ -57,11 +65,11 @@ public class ThreadHandler { impl.sleep(target - elapsed); } - synchronized(lock) { - while(!finished) { - lock.wait(); + synchronized(updateLock) { + while(!rendered) { + updateLock.wait(); } - finished = false; + rendered = false; } } } catch (InterruptedException ex) { diff --git a/core/src/io/anuke/mindustry/game/GameMode.java b/core/src/io/anuke/mindustry/game/GameMode.java index 0df08f07f5..4d102a0ac9 100644 --- a/core/src/io/anuke/mindustry/game/GameMode.java +++ b/core/src/io/anuke/mindustry/game/GameMode.java @@ -7,16 +7,16 @@ public enum GameMode{ sandbox{ { infiniteResources = true; - toggleWaves = true; + disableWaveTimer = true; } }, freebuild{ { - toggleWaves = true; + disableWaveTimer = true; } }; public boolean infiniteResources; - public boolean toggleWaves; + public boolean disableWaveTimer; @Override public String toString(){ diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index 948c790811..f6bbc5dd44 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -139,14 +139,14 @@ public abstract class InputHandler extends InputAdapter{ for(int dx = 0; dx < type.width; dx ++){ for(int dy = 0; dy < type.height; dy ++){ Tile other = world.tile(x + dx + offsetx, y + dy + offsety); - if(other == null || other.block() != Blocks.air || isSpawnPoint(other)){ + if(other == null || (other.block() != Blocks.air && !other.block().alwaysReplace) || isSpawnPoint(other)){ return false; } } } return true; }else{ - if(tile.block() != type && type.canReplace(tile.block()) && tile.block().isMultiblock() == type.isMultiblock()){ + if(tile.block() != type && (type.canReplace(tile.block()) || tile.block().alwaysReplace) && tile.block().isMultiblock() == type.isMultiblock()){ return true; } return tile.block() == Blocks.air; diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java index 1b72bf365a..a29870a79b 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java @@ -179,7 +179,7 @@ public class HudFragment implements Fragment{ new label(()-> state.enemies > 0 ? getEnemiesRemaining() : - (control.tutorial().active() || state.mode.toggleWaves) ? "$text.waiting" + (control.tutorial().active() || state.mode.disableWaveTimer) ? "$text.waiting" : Bundles.format("text.wave.waiting", (int) (state.wavetime / 60f))) .minWidth(126).padLeft(-6).padRight(-12).left(); diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index 311490b56d..1d7518c8da 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -87,6 +87,8 @@ public class Block{ public Layer layer2 = null; /**list of displayed block status bars. Defaults to health bar.*/ public Array bars = Array.with(new BlockBar(Color.RED, false, tile -> tile.entity.health / (float)tile.block().health)); + /**whether this block can be replaced in all cases*/ + public boolean alwaysReplace = false; public Block(String name) { this.name = name; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/Rock.java b/core/src/io/anuke/mindustry/world/blocks/types/Rock.java index 14a8681c3a..bc5e82dae6 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/Rock.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/Rock.java @@ -9,5 +9,6 @@ public class Rock extends Block { shadow = name+"shadow"; breakable = true; breaktime = 10; + alwaysReplace = true; } } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java index dac7eeff7f..8ae8bd0061 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java @@ -24,7 +24,6 @@ public class Conveyor extends Block{ private static ItemPos drawpos = new ItemPos(); private static ItemPos pos1 = new ItemPos(); private static ItemPos pos2 = new ItemPos(); - private static LongArray removals = new LongArray(); private static final float itemSpace = 0.135f; private static final float offsetScl = 128f*3f; private static final float itemSize = 4f; @@ -93,9 +92,8 @@ public class Conveyor extends Block{ ConveyorEntity entity = tile.entity(); entity.minitem = 1f; - removals.clear(); - float shift = entity.elapsed * speed; + int minremove = Integer.MAX_VALUE; for(int i = 0; i < entity.convey.size; i ++){ long value = entity.convey.get(i); @@ -103,9 +101,10 @@ public class Conveyor extends Block{ pos.y += shift; + //..this should never happen, but in case it does, remove it and stop here if(pos.item == null){ - removals.add(value); - continue; + entity.convey.removeValue(value); + break; } float nextpos = (i == entity.convey.size - 1 ? 100f : pos2.set(entity.convey.get(i + 1)).y) - itemSpace; @@ -121,7 +120,7 @@ public class Conveyor extends Block{ pos.y = Mathf.clamp(pos.y); if(pos.y >= 0.9999f && offloadDir(tile, pos.item)){ - removals.add(value); + minremove = Math.min(i, minremove); }else{ value = pos.pack(); @@ -133,7 +132,7 @@ public class Conveyor extends Block{ } entity.elapsed = 0f; - entity.convey.removeAll(removals); + if(minremove != Integer.MAX_VALUE) entity.convey.truncate(minremove); } @Override @@ -156,7 +155,6 @@ public class Conveyor extends Block{ int ch = Math.abs(source.relativeTo(tile.x, tile.y) - rotation); int ang = ((source.relativeTo(tile.x, tile.y) - rotation)); - float pos = ch == 0 ? 0 : ch % 2 == 1 ? 0.5f : 1f; float y = (ang == -1 || ang == 3) ? 1 : (ang == 1 || ang == -3) ? -1 : 0; From f4227b99ff78b8798fefb5696adb40f1bea885de Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 7 Feb 2018 17:56:39 -0500 Subject: [PATCH 6/8] Added visual interpolation for slow tickrates --- core/src/io/anuke/mindustry/Vars.java | 2 + core/src/io/anuke/mindustry/core/Control.java | 1 + .../src/io/anuke/mindustry/core/Renderer.java | 13 +++--- .../anuke/mindustry/core/ThreadHandler.java | 12 +++++ .../io/anuke/mindustry/entities/Player.java | 3 +- .../anuke/mindustry/entities/SyncEntity.java | 44 +++++++++++++++++++ .../mindustry/entities/enemies/Enemy.java | 6 +-- .../mindustry/ui/fragments/HudFragment.java | 2 +- 8 files changed, 72 insertions(+), 11 deletions(-) diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index d2032630c4..235722b106 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -14,6 +14,7 @@ import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.net.ClientDebug; import io.anuke.mindustry.net.ServerDebug; import io.anuke.ucore.UCore; +import io.anuke.ucore.entities.EffectEntity; import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.scene.ui.layout.Unit; @@ -134,4 +135,5 @@ public class Vars{ public static final EntityGroup tileGroup = Entities.addGroup(TileEntity.class, false); public static final EntityGroup bulletGroup = Entities.addGroup(Bullet.class); public static final EntityGroup shieldGroup = Entities.addGroup(Shield.class); + public static final EntityGroup effectGroup = Entities.addGroup(EffectEntity.class); } diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index 5b7125c163..851d1bc4b9 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -352,6 +352,7 @@ public class Control extends Module{ } if(!state.is(State.paused) || Net.active()){ + Entities.update(effectGroup); if(respawntime > 0){ diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index 546c28d1fd..31b7f583bc 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -12,6 +12,7 @@ import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.Pools; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.entities.SyncEntity; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.game.SpawnPoint; import io.anuke.mindustry.graphics.BlockRenderer; @@ -24,7 +25,6 @@ import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Blocks; import io.anuke.mindustry.world.blocks.ProductionBlocks; import io.anuke.ucore.core.*; -import io.anuke.ucore.entities.DestructibleEntity; import io.anuke.ucore.entities.EffectEntity; import io.anuke.ucore.entities.Entities; import io.anuke.ucore.function.Callable; @@ -63,7 +63,7 @@ public class Renderer extends RendererModule{ .setCenter(camera.position.x, camera.position.y); Rectangle pos = rect2.setSize(name.size).setCenter(x, y); if(view.overlaps(pos)){ - new EffectEntity(name, color, rotation).set(x, y).add(); + new EffectEntity(name, color, rotation).set(x, y).add(effectGroup); } } }); @@ -191,6 +191,7 @@ public class Renderer extends RendererModule{ Graphics.shader(); Entities.draw(bulletGroup); + Entities.draw(effectGroup); drawShield(); @@ -448,11 +449,13 @@ public class Renderer extends RendererModule{ } } - void drawHealth(DestructibleEntity dest){ + void drawHealth(SyncEntity dest){ + float x = dest.getDrawPosition().x; + float y = dest.getDrawPosition().y; if(dest instanceof Player && snapCamera && Settings.getBool("smoothcam") && Settings.getBool("pixelate")){ - drawHealth((int) dest.x, (int) dest.y - 7f, dest.health, dest.maxhealth); + drawHealth((int) x, (int) y - 7f, dest.health, dest.maxhealth); }else{ - drawHealth(dest.x, dest.y - 7f, dest.health, dest.maxhealth); + drawHealth(x, y - 7f, dest.health, dest.maxhealth); } } diff --git a/core/src/io/anuke/mindustry/core/ThreadHandler.java b/core/src/io/anuke/mindustry/core/ThreadHandler.java index d27ca75ddc..7b1a5a0a52 100644 --- a/core/src/io/anuke/mindustry/core/ThreadHandler.java +++ b/core/src/io/anuke/mindustry/core/ThreadHandler.java @@ -10,6 +10,7 @@ import static io.anuke.mindustry.Vars.logic; public class ThreadHandler { private final ThreadProvider impl; private float delta = 1f; + private long frame = 0; private boolean enabled; private final Object updateLock = new Object(); @@ -21,6 +22,14 @@ public class ThreadHandler { Timers.setDeltaProvider(() -> impl.isOnThread() ? delta : Gdx.graphics.getDeltaTime()*60f); } + public int getFPS(){ + return (int)(60/delta); + } + + public long getFrameID(){ + return frame; + } + public void handleRender(){ if(!enabled) return; @@ -55,6 +64,7 @@ public class ThreadHandler { while (true) { long time = TimeUtils.millis(); logic.update(); + //impl.sleep(130); long elapsed = TimeUtils.timeSinceMillis(time); long target = (long) (1000 / 60f); @@ -71,6 +81,8 @@ public class ThreadHandler { } rendered = false; } + + frame ++; } } catch (InterruptedException ex) { Log.info("Stopping logic thread."); diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index c746111a9d..a54e1a6f74 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -35,7 +35,6 @@ public class Player extends SyncEntity{ public Weapon weaponRight = Weapon.blaster; public Mech mech = Mech.standard; - public float angle; public float targetAngle = 0f; public float stucktime = 0f; public boolean dashing = false; @@ -106,7 +105,7 @@ public class Player extends SyncEntity{ } @Override - public void draw(){ + public void drawSmooth(){ if(isAndroid && isLocal){ angle = Mathf.lerpAngDelta(angle, targetAngle, 0.2f); } diff --git a/core/src/io/anuke/mindustry/entities/SyncEntity.java b/core/src/io/anuke/mindustry/entities/SyncEntity.java index ada5cb5ed0..968bdf285d 100644 --- a/core/src/io/anuke/mindustry/entities/SyncEntity.java +++ b/core/src/io/anuke/mindustry/entities/SyncEntity.java @@ -1,17 +1,27 @@ package io.anuke.mindustry.entities; +import com.badlogic.gdx.Gdx; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.ObjectIntMap; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.ucore.entities.DestructibleEntity; +import io.anuke.ucore.util.Mathf; import java.nio.ByteBuffer; +import static io.anuke.mindustry.Vars.threads; + public abstract class SyncEntity extends DestructibleEntity{ private static ObjectIntMap> writeSizes = new ObjectIntMap<>(); protected transient Interpolator interpolator = new Interpolator(); + //for interpolating at low tick speeds. + private transient Vector2 tpos = new Vector2(-999, -999); + private transient float tang = 0f; + + public float angle; + static{ setWriteSize(Enemy.class, 4 + 4 + 2 + 2); setWriteSize(Player.class, 4 + 4 + 4 + 2 + 1); @@ -24,6 +34,40 @@ public abstract class SyncEntity extends DestructibleEntity{ public abstract void read(ByteBuffer data, long time); public abstract void interpolate(); + @Override + public final void draw(){ + float x = this.x, y = this.y, angle = this.angle; + + //interpolates data at low tick speeds. + if(isSmoothing()){ + if(tpos.dst(x, y) > 100){ + tpos.set(x, y); + } + tpos.x = Mathf.lerpDelta(tpos.x, x, 0.3f); + tpos.y = Mathf.lerpDelta(tpos.y, y, 0.3f); + tang = Mathf.lerpAngDelta(tang, angle, 0.3f); + this.x = tpos.x; + this.y = tpos.y; + this.angle = tang; + } + + drawSmooth(); + + this.x = x; + this.y = y; + this.angle = angle; + } + + private boolean isSmoothing(){ + return threads.isEnabled() && threads.getFPS() <= Gdx.graphics.getFramesPerSecond() / 2f; + } + + public Vector2 getDrawPosition(){ + return isSmoothing() ? tpos : tpos.set(x, y); + } + + public void drawSmooth(){} + public int getWriteSize(){ return getWriteSize(getClass()); } diff --git a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java index 08c4edf1c5..2ab55ea398 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java +++ b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java @@ -29,12 +29,12 @@ public class Enemy extends SyncEntity { public Enemy spawner; public int spawned; - public float angle; public Vector2 velocity = new Vector2(); + public Vector2 totalMove = new Vector2(); + public Vector2 tpos = new Vector2(-999, -999); public Entity target; public float hitTime; public int tier = 1; - public Vector2 totalMove = new Vector2(); public TextureRegion region; public Translator tr = new Translator(); @@ -52,7 +52,7 @@ public class Enemy extends SyncEntity { } @Override - public void draw(){ + public void drawSmooth(){ type.draw(this); } diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java index a29870a79b..e69aa70c6c 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java @@ -93,7 +93,7 @@ public class HudFragment implements Fragment{ visible(() -> !state.is(State.menu)); Label fps = new Label(() -> (Settings.getBool("fps") ? (Gdx.graphics.getFramesPerSecond() + " FPS") + - (Net.client() && !gwt ? " / Ping: " + Net.getPing() : "") : "")); + (threads.isEnabled() ? " / " + threads.getFPS() + " TPS" : "") + (Net.client() && !gwt ? " / Ping: " + Net.getPing() : "") : "")); row(); add(fps).size(-1); From 757f4f5a53234308478f592ab7f62db7eceb2895 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 7 Feb 2018 21:06:26 -0500 Subject: [PATCH 7/8] Reduced multithreaded conveyor corruption, improved interpolation --- core/assets/bundles/bundle.properties | 2 +- core/src/io/anuke/mindustry/core/Control.java | 7 -- .../anuke/mindustry/core/ThreadHandler.java | 9 ++- .../io/anuke/mindustry/entities/Bullet.java | 19 +++-- .../io/anuke/mindustry/entities/Player.java | 24 +----- .../anuke/mindustry/entities/SyncEntity.java | 75 ++++++++++++++----- .../mindustry/entities/enemies/Enemy.java | 26 +------ core/src/io/anuke/mindustry/net/Net.java | 2 +- core/src/io/anuke/mindustry/net/Packets.java | 8 +- .../world/blocks/types/LiquidBlock.java | 3 +- .../blocks/types/distribution/Conveyor.java | 37 ++++----- .../blocks/types/distribution/Junction.java | 25 ++++--- 12 files changed, 118 insertions(+), 119 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index e41cf25858..03bdb62bc8 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -217,7 +217,7 @@ setting.sensitivity.name=Controller Sensitivity setting.saveinterval.name=Autosave Interval setting.seconds={0} Seconds setting.fullscreen.name=Fullscreen -setting.multithread.name=Multithreading [scarlet](unstable!) +setting.multithread.name=Multithreading [scarlet](extremely unstable!) setting.fps.name=Show FPS setting.vsync.name=VSync setting.lasers.name=Show Power Lasers diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index 851d1bc4b9..86795a8641 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -268,13 +268,6 @@ public class Control extends Module{ Entities.collisions().setCollider(tilesize, world::solid); Platform.instance.updateRPC(); - - //TODO remove - /* - Timers.runTask(2, () -> { - state.set(State.playing); - SaveIO.loadFromSlot(0); - });*/ } @Override diff --git a/core/src/io/anuke/mindustry/core/ThreadHandler.java b/core/src/io/anuke/mindustry/core/ThreadHandler.java index 7b1a5a0a52..885c48f99d 100644 --- a/core/src/io/anuke/mindustry/core/ThreadHandler.java +++ b/core/src/io/anuke/mindustry/core/ThreadHandler.java @@ -11,6 +11,7 @@ public class ThreadHandler { private final ThreadProvider impl; private float delta = 1f; private long frame = 0; + private float framesSinceUpdate; private boolean enabled; private final Object updateLock = new Object(); @@ -30,9 +31,15 @@ public class ThreadHandler { return frame; } + public float getFramesSinceUpdate(){ + return framesSinceUpdate; + } + public void handleRender(){ if(!enabled) return; + framesSinceUpdate += Timers.delta(); + synchronized (updateLock) { rendered = true; updateLock.notify(); @@ -64,7 +71,6 @@ public class ThreadHandler { while (true) { long time = TimeUtils.millis(); logic.update(); - //impl.sleep(130); long elapsed = TimeUtils.timeSinceMillis(time); long target = (long) (1000 / 60f); @@ -83,6 +89,7 @@ public class ThreadHandler { } frame ++; + framesSinceUpdate = 0; } } catch (InterruptedException ex) { Log.info("Stopping logic thread."); diff --git a/core/src/io/anuke/mindustry/entities/Bullet.java b/core/src/io/anuke/mindustry/entities/Bullet.java index 40d77f07f2..b1b0d4c9ec 100644 --- a/core/src/io/anuke/mindustry/entities/Bullet.java +++ b/core/src/io/anuke/mindustry/entities/Bullet.java @@ -9,21 +9,26 @@ import io.anuke.ucore.util.Mathf; import static io.anuke.mindustry.Vars.*; public class Bullet extends BulletEntity{ - public boolean absorbed = false; public Bullet(BulletType type, Entity owner, float x, float y, float angle){ super(type, owner, angle); set(x, y); this.type = type; } - - public void absorb(){ - absorbed = true; - remove(); - } public void draw(){ - type.draw(this); + //interpolate position linearly at low tick speeds + if(SyncEntity.isSmoothing()){ + x += threads.getFramesSinceUpdate() * velocity.x; + y += threads.getFramesSinceUpdate() * velocity.y; + + type.draw(this); + + x -= threads.getFramesSinceUpdate() * velocity.x; + y -= threads.getFramesSinceUpdate() * velocity.y; + }else{ + type.draw(this); + } } public float drawSize(){ diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index a54e1a6f74..305c70c297 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -2,7 +2,6 @@ package io.anuke.mindustry.entities; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.TimeUtils; import io.anuke.mindustry.graphics.Fx; import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.net.Net; @@ -275,32 +274,15 @@ public class Player extends SyncEntity{ this.health = health; this.dashing = dashing == 1; - interpolator.targetrot = angle; - interpolator.time = 0f; - interpolator.last.set(this.x, this.y); - interpolator.target.set(x, y); - interpolator.spacing = Math.min(Math.max(((TimeUtils.timeSinceMillis(time) / 1000f) * 60f), 4f), 10); + interpolator.read(this.x, this.y, x, y, angle, time); } @Override public void interpolate() { + super.interpolate(); + Interpolator i = interpolator; - i.time += 1f / i.spacing * Timers.delta(); - - Mathf.lerp2(movement.set(i.last), i.target, i.time); - - x = movement.x; - y = movement.y; - - if(i.target.dst(x, y) > 128){ - set(i.target.x, i.target.y); - i.time = 0f; - i.last.set(i.target); - } - - angle = Mathf.lerpAngDelta(angle, i.targetrot, 0.6f); - float tx = x + Angles.trnsx(angle + 180f, 3f); float ty = y + Angles.trnsy(angle + 180f, 3f); diff --git a/core/src/io/anuke/mindustry/entities/SyncEntity.java b/core/src/io/anuke/mindustry/entities/SyncEntity.java index 968bdf285d..7d29b4e9f0 100644 --- a/core/src/io/anuke/mindustry/entities/SyncEntity.java +++ b/core/src/io/anuke/mindustry/entities/SyncEntity.java @@ -2,8 +2,11 @@ package io.anuke.mindustry.entities; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.utils.ObjectIntMap; +import com.badlogic.gdx.utils.TimeUtils; import io.anuke.mindustry.entities.enemies.Enemy; +import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.DestructibleEntity; import io.anuke.ucore.util.Mathf; @@ -16,9 +19,8 @@ public abstract class SyncEntity extends DestructibleEntity{ protected transient Interpolator interpolator = new Interpolator(); - //for interpolating at low tick speeds. - private transient Vector2 tpos = new Vector2(-999, -999); - private transient float tang = 0f; + //smoothed position/angle + private Vector3 spos = new Vector3(); public float angle; @@ -27,12 +29,23 @@ public abstract class SyncEntity extends DestructibleEntity{ setWriteSize(Player.class, 4 + 4 + 4 + 2 + 1); } + public static boolean isSmoothing(){ + return threads.isEnabled() && threads.getFPS() <= Gdx.graphics.getFramesPerSecond() / 2f; + } + public abstract void writeSpawn(ByteBuffer data); public abstract void readSpawn(ByteBuffer data); public abstract void write(ByteBuffer data); public abstract void read(ByteBuffer data, long time); - public abstract void interpolate(); + + public void interpolate(){ + interpolator.update(); + + x = interpolator.pos.x; + y = interpolator.pos.y; + angle = interpolator.angle; + } @Override public final void draw(){ @@ -40,15 +53,13 @@ public abstract class SyncEntity extends DestructibleEntity{ //interpolates data at low tick speeds. if(isSmoothing()){ - if(tpos.dst(x, y) > 100){ - tpos.set(x, y); + if(Vector2.dst(spos.x, spos.y, x, y) > 128){ + spos.set(x, y, angle); } - tpos.x = Mathf.lerpDelta(tpos.x, x, 0.3f); - tpos.y = Mathf.lerpDelta(tpos.y, y, 0.3f); - tang = Mathf.lerpAngDelta(tang, angle, 0.3f); - this.x = tpos.x; - this.y = tpos.y; - this.angle = tang; + + this.x = spos.x = Mathf.lerpDelta(spos.x, x, 0.2f); + this.y = spos.y = Mathf.lerpDelta(spos.y, y, 0.2f); + this.angle = spos.z = Mathf.lerpAngDelta(spos.z, angle, 0.3f); } drawSmooth(); @@ -58,12 +69,8 @@ public abstract class SyncEntity extends DestructibleEntity{ this.angle = angle; } - private boolean isSmoothing(){ - return threads.isEnabled() && threads.getFPS() <= Gdx.graphics.getFramesPerSecond() / 2f; - } - - public Vector2 getDrawPosition(){ - return isSmoothing() ? tpos : tpos.set(x, y); + public Vector3 getDrawPosition(){ + return isSmoothing() ? spos : spos.set(x, y, angle); } public void drawSmooth(){} @@ -91,12 +98,40 @@ public abstract class SyncEntity extends DestructibleEntity{ return (T)this; } - public class Interpolator { + public static class Interpolator { + //used for movement public Vector2 target = new Vector2(); public Vector2 last = new Vector2(); - public Vector2 vec = new Vector2(); public float targetrot; public float spacing = 1f; public float time; + + //current state + public Vector2 pos = new Vector2(); + public float angle; + + public void read(float cx, float cy, float x, float y, float angle, long sent){ + targetrot = angle; + time = 0f; + last.set(cx, cy); + target.set(x, y); + spacing = Math.min(Math.max(((TimeUtils.timeSinceMillis(sent) / 1000f) * 60f), 4f), 10); + } + + public void update(){ + + time += 1f / spacing * Timers.delta(); + + Mathf.lerp2(pos.set(last), target, time); + + angle = Mathf.lerpAngDelta(angle, targetrot, 0.6f); + + if(target.dst(pos) > 128){ + pos.set(target); + last.set(target); + time = 0f; + } + + } } } diff --git a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java index 2ab55ea398..1c0a92d95e 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java +++ b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java @@ -2,17 +2,17 @@ package io.anuke.mindustry.entities.enemies; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.TimeUtils; import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.SyncEntity; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.NetEvents; -import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.graphics.Draw; -import io.anuke.ucore.util.*; +import io.anuke.ucore.util.Mathf; +import io.anuke.ucore.util.Timer; +import io.anuke.ucore.util.Translator; import java.nio.ByteBuffer; @@ -141,25 +141,7 @@ public class Enemy extends SyncEntity { this.health = health; - interpolator.targetrot = angle / 2f; - interpolator.time = 0f; - interpolator.last.set(this.x, this.y); - interpolator.target.set(x, y); - interpolator.spacing = Math.min(Math.max(((TimeUtils.timeSinceMillis(time) / 1000f) * 60f), 4f), 10f); - } - - @Override - public void interpolate() { - Interpolator i = interpolator; - - i.time += 1f / i.spacing * Timers.delta(); - - Mathf.lerp2(i.vec.set(i.last), i.target, i.time); - - x = i.vec.x; - y = i.vec.y; - - angle = Mathf.lerpAngDelta(angle, i.targetrot, 0.6f); + interpolator.read(this.x, this.y, x, y, angle, time); } public void shoot(BulletType bullet){ diff --git a/core/src/io/anuke/mindustry/net/Net.java b/core/src/io/anuke/mindustry/net/Net.java index ba77d1a2bc..e0957fa0f6 100644 --- a/core/src/io/anuke/mindustry/net/Net.java +++ b/core/src/io/anuke/mindustry/net/Net.java @@ -25,7 +25,7 @@ import java.io.IOException; import static io.anuke.mindustry.Vars.*; public class Net{ - public static final int version = 19; + public static final int version = 20; private static boolean server; private static boolean active; diff --git a/core/src/io/anuke/mindustry/net/Packets.java b/core/src/io/anuke/mindustry/net/Packets.java index 08646fea96..646478c94f 100644 --- a/core/src/io/anuke/mindustry/net/Packets.java +++ b/core/src/io/anuke/mindustry/net/Packets.java @@ -508,15 +508,15 @@ public class Packets { @Override public void write(ByteBuffer buffer) { - buffer.putInt(position); - buffer.put(rotation); + buffer.putInt((rotation) | (position << 2)); buffer.put(itemid); } @Override public void read(ByteBuffer buffer) { - position = buffer.getInt(); - rotation = buffer.get(); + int i = buffer.getInt(); + rotation = (byte)(i & 0x3); + position = i >> 2; itemid = buffer.get(); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/LiquidBlock.java b/core/src/io/anuke/mindustry/world/blocks/types/LiquidBlock.java index a775431132..cca55a313a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/LiquidBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/LiquidBlock.java @@ -5,6 +5,7 @@ import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.resource.Liquid; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; @@ -80,7 +81,7 @@ public class LiquidBlock extends Block implements LiquidAcceptor{ LiquidAcceptor other = (LiquidAcceptor)next.block(); float flow = Math.min(other.getLiquidCapacity(next) - other.getLiquid(next) - 0.001f, - Math.min(entity.liquidAmount/flowfactor, entity.liquidAmount)); + Math.min(entity.liquidAmount/flowfactor * Timers.delta(), entity.liquidAmount)); if(flow <= 0f || entity.liquidAmount < flow) return; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java index 8ae8bd0061..ff286cea59 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java @@ -67,13 +67,13 @@ public class Conveyor extends Block{ } @Override - public synchronized void drawLayer(Tile tile){ + public void drawLayer(Tile tile){ ConveyorEntity entity = tile.entity(); byte rotation = tile.getRotation(); for(int i = 0; i < entity.convey.size; i ++){ - ItemPos pos = drawpos.set(entity.convey.get(i)); + ItemPos pos = drawpos.set(entity.convey.get(i), ItemPos.drawShorts); if(pos.item == null) continue; @@ -87,19 +87,16 @@ public class Conveyor extends Block{ } @Override - public synchronized void update(Tile tile){ + public void update(Tile tile){ ConveyorEntity entity = tile.entity(); entity.minitem = 1f; - float shift = entity.elapsed * speed; int minremove = Integer.MAX_VALUE; for(int i = 0; i < entity.convey.size; i ++){ long value = entity.convey.get(i); - ItemPos pos = pos1.set(value); - - pos.y += shift; + ItemPos pos = pos1.set(value, ItemPos.updateShorts); //..this should never happen, but in case it does, remove it and stop here if(pos.item == null){ @@ -107,7 +104,7 @@ public class Conveyor extends Block{ break; } - float nextpos = (i == entity.convey.size - 1 ? 100f : pos2.set(entity.convey.get(i + 1)).y) - itemSpace; + float nextpos = (i == entity.convey.size - 1 ? 100f : pos2.set(entity.convey.get(i + 1), ItemPos.updateShorts).y) - itemSpace; float maxmove = Math.min(nextpos - pos.y, speed * Timers.delta()); if(maxmove > minmove){ @@ -128,10 +125,8 @@ public class Conveyor extends Block{ entity.minitem = pos.y; entity.convey.set(i, value); } - } - entity.elapsed = 0f; if(minremove != Integer.MAX_VALUE) entity.convey.truncate(minremove); } @@ -187,7 +182,7 @@ public class Conveyor extends Block{ public static class ConveyorEntity extends TileEntity{ LongArray convey = new LongArray(); - float minitem = 1, elapsed; + float minitem = 1; @Override public void write(DataOutputStream stream) throws IOException{ @@ -210,12 +205,6 @@ public class Conveyor extends Block{ sort(convey.items, convey.size); } - - @Override - public void readNetwork(DataInputStream stream, float elapsed) throws IOException{ - read(stream); - this.elapsed = elapsed; - } } private static void sort(long[] elements, int length){ @@ -243,8 +232,8 @@ public class Conveyor extends Block{ } private static int compareItems(Long a, Long b){ - pos1.set(a); - pos2.set(b); + pos1.set(a, ItemPos.packShorts); + pos2.set(b, ItemPos.packShorts); return Float.compare(pos1.y, pos2.y); } @@ -253,14 +242,18 @@ public class Conveyor extends Block{ private static short[] writeShort = new short[4]; private static byte[] writeByte = new byte[4]; + private static short[] packShorts = new short[4]; + private static short[] drawShorts = new short[4]; + private static short[] updateShorts = new short[4]; + Item item; float x, y; byte seed; private ItemPos(){} - ItemPos set(long lvalue){ - short[] values = Bits.getShorts(lvalue); + ItemPos set(long lvalue, short[] values){ + Bits.getShorts(lvalue, values); if(values[0] >= Item.getAllItems().size || values[0] < 0) item = null; @@ -278,7 +271,7 @@ public class Conveyor extends Block{ } static long packItem(Item item, float x, float y, byte seed){ - short[] shorts = Bits.getShorts(); + short[] shorts = packShorts; shorts[0] = (short)item.id; shorts[1] = (short)(x*Short.MAX_VALUE); shorts[2] = (short)((y - 1f)*Short.MAX_VALUE); diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Junction.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Junction.java index 8242c3bd7b..9d2f2abfac 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Junction.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Junction.java @@ -22,18 +22,6 @@ public class Junction extends Block{ public boolean canReplace(Block other){ return other instanceof Conveyor || other instanceof Router; } - - @Override - public void handleItem(Item item, Tile tile, Tile source){ - JunctionEntity entity = tile.entity(); - boolean x = tile.x == source.x; - long value = Bits.packLong(NumberUtils.floatToIntBits(Timers.time()), Bits.packInt((short)item.id, source.relativeTo(tile.x, tile.y))); - if(x){ - entity.bx.add(value); - }else { - entity.by.add(value); - } - } @Override public void update(Tile tile){ @@ -64,6 +52,18 @@ public class Junction extends Block{ } } + @Override + public void handleItem(Item item, Tile tile, Tile source){ + JunctionEntity entity = tile.entity(); + boolean x = tile.x == source.x; + long value = Bits.packLong(NumberUtils.floatToIntBits(Timers.time()), Bits.packInt((short)item.id, source.relativeTo(tile.x, tile.y))); + if(x){ + entity.bx.add(value); + }else { + entity.by.add(value); + } + } + @Override public boolean acceptItem(Item item, Tile tile, Tile source){ JunctionEntity entity = tile.entity(); @@ -91,6 +91,7 @@ public class Junction extends Block{ int index; void add(long id){ + if(full()) return; items[index++] = id; } From 435161f59d896b68ca53bd4af5b4f40790b0f179 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 7 Feb 2018 21:08:27 -0500 Subject: [PATCH 8/8] Updated uCore, ready to merge --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c76796921b..eba5f5987f 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ allprojects { appName = "Mindustry" gdxVersion = '1.9.8' aiVersion = '1.8.1' - uCoreVersion = 'f40fdf3' + uCoreVersion = 'a480029' } repositories {