From bac1648d4b01eb7ccc189c37b64ad47b89692517 Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 3 Mar 2020 17:01:09 -0500 Subject: [PATCH] Added support for changing cached floor/terrain --- core/assets/shaders/sun.fragment.glsl | 6 +- core/assets/shaders/sun.vertex.glsl | 10 +++- core/src/mindustry/core/Renderer.java | 1 + core/src/mindustry/core/World.java | 1 + core/src/mindustry/editor/EditorTile.java | 3 +- core/src/mindustry/graphics/CacheLayer.java | 14 ++++- .../src/mindustry/graphics/FloorRenderer.java | 56 ++++++++++++++----- core/src/mindustry/graphics/MenuRenderer.java | 3 + core/src/mindustry/world/Tile.java | 35 ++++++++++-- .../world/blocks/production/Drill.java | 14 +++-- gradle.properties | 2 +- tests/src/test/java/ZoneTests.java | 1 - 12 files changed, 117 insertions(+), 29 deletions(-) diff --git a/core/assets/shaders/sun.fragment.glsl b/core/assets/shaders/sun.fragment.glsl index 5ad91f3878..84a7e26625 100755 --- a/core/assets/shaders/sun.fragment.glsl +++ b/core/assets/shaders/sun.fragment.glsl @@ -1,12 +1,16 @@ #ifdef GL_ES precision mediump float; +precision lowp int; +#define INTEGER lowp int +#else +#define INTEGER int #endif #define gradients false const int MAX_COLORS = 10; -uniform int u_colornum; +uniform INTEGER u_colornum; uniform vec4 u_colors[MAX_COLORS]; varying float v_height; diff --git a/core/assets/shaders/sun.vertex.glsl b/core/assets/shaders/sun.vertex.glsl index c2880dee60..0b4d2d8783 100755 --- a/core/assets/shaders/sun.vertex.glsl +++ b/core/assets/shaders/sun.vertex.glsl @@ -1,3 +1,11 @@ +#ifdef GL_ES +precision mediump float; +precision lowp int; +#define INTEGER lowp int +#else +#define INTEGER int +#endif + attribute vec4 a_position; attribute vec3 a_normal; @@ -14,7 +22,7 @@ uniform float u_spread; uniform float u_magnitude; uniform float u_seed; -uniform int u_colornum; +uniform INTEGER u_colornum; varying float v_height; diff --git a/core/src/mindustry/core/Renderer.java b/core/src/mindustry/core/Renderer.java index bc791bf2cc..56389e077c 100644 --- a/core/src/mindustry/core/Renderer.java +++ b/core/src/mindustry/core/Renderer.java @@ -169,6 +169,7 @@ public class Renderer implements ApplicationListener{ drawBackground(); + blocks.floor.checkChanges(); blocks.floor.drawFloor(); Groups.drawFloor(); diff --git a/core/src/mindustry/core/World.java b/core/src/mindustry/core/World.java index 306b19002b..edb83303b5 100644 --- a/core/src/mindustry/core/World.java +++ b/core/src/mindustry/core/World.java @@ -99,6 +99,7 @@ public class World{ return tile.block().linked(tile); } + @NonNull public Tile rawTile(int x, int y){ return tiles.getn(x, y); } diff --git a/core/src/mindustry/editor/EditorTile.java b/core/src/mindustry/editor/EditorTile.java index aeabaed77d..96f5adcc51 100644 --- a/core/src/mindustry/editor/EditorTile.java +++ b/core/src/mindustry/editor/EditorTile.java @@ -1,5 +1,6 @@ package mindustry.editor; +import arc.util.ArcAnnotate.*; import mindustry.content.Blocks; import mindustry.core.GameState.State; import mindustry.editor.DrawOperation.OpType; @@ -20,7 +21,7 @@ public class EditorTile extends Tile{ } @Override - public void setFloor(Floor type){ + public void setFloor(@NonNull Floor type){ if(state.is(State.playing)){ super.setFloor(type); return; diff --git a/core/src/mindustry/graphics/CacheLayer.java b/core/src/mindustry/graphics/CacheLayer.java index 08ed1b8c2d..05be5fc355 100644 --- a/core/src/mindustry/graphics/CacheLayer.java +++ b/core/src/mindustry/graphics/CacheLayer.java @@ -42,9 +42,21 @@ public enum CacheLayer{ endShader(Shaders.slag); } }, - normal, + normal(5), walls; + public static final CacheLayer[] all = values(); + /** Capacity multiplier. */ + public final int capacity; + + CacheLayer(){ + this(2); + } + + CacheLayer(int capacity){ + this.capacity = capacity; + } + public void begin(){ } diff --git a/core/src/mindustry/graphics/FloorRenderer.java b/core/src/mindustry/graphics/FloorRenderer.java index fa1327e3a6..6711339cbf 100644 --- a/core/src/mindustry/graphics/FloorRenderer.java +++ b/core/src/mindustry/graphics/FloorRenderer.java @@ -16,11 +16,13 @@ import java.util.*; import static mindustry.Vars.*; public class FloorRenderer implements Disposable{ - private final static int chunksize = 64; + //TODO find out number with best performance + private final static int chunksize = mobile ? 16 : 32; private Chunk[][] cache; private MultiCacheBatch cbatch; private IntSet drawnLayerSet = new IntSet(); + private IntSet recacheSet = new IntSet(); private IntArray drawnLayers = new IntArray(); private ObjectSet used = new ObjectSet<>(); @@ -28,6 +30,11 @@ public class FloorRenderer implements Disposable{ Events.on(WorldLoadEvent.class, event -> clearTiles()); } + /**Queues up a cache change for a tile. Only runs in render loop. */ + public void recacheTile(Tile tile){ + recacheSet.add(Pos.get(tile.x / chunksize, tile.y / chunksize)); + } + public void drawFloor(){ if(cache == null){ return; @@ -41,7 +48,7 @@ public class FloorRenderer implements Disposable{ int camx = (int)(camera.position.x / (chunksize * tilesize)); int camy = (int)(camera.position.y / (chunksize * tilesize)); - int layers = CacheLayer.values().length; + int layers = CacheLayer.all.length; drawnLayers.clear(); drawnLayerSet.clear(); @@ -77,7 +84,7 @@ public class FloorRenderer implements Disposable{ beginDraw(); for(int i = 0; i < drawnLayers.size; i++){ - CacheLayer layer = CacheLayer.values()[drawnLayers.get(i)]; + CacheLayer layer = CacheLayer.all[drawnLayers.get(i)]; drawLayer(layer); } @@ -93,6 +100,19 @@ public class FloorRenderer implements Disposable{ cbatch.endDraw(); } + public void checkChanges(){ + if(recacheSet.size > 0){ + //recache one chunk at a time + IntSetIterator iterator = recacheSet.iterator(); + while(iterator.hasNext){ + int chunk = iterator.next(); + cacheChunk(Pos.x(chunk), Pos.y(chunk)); + } + + recacheSet.clear(); + } + } + public void beginDraw(){ if(cache == null){ return; @@ -146,16 +166,14 @@ public class FloorRenderer implements Disposable{ used.clear(); Chunk chunk = cache[cx][cy]; - for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize; tilex++){ - for(int tiley = cy * chunksize; tiley < (cy + 1) * chunksize; tiley++){ - Tile tile = world.tile(tilex, tiley); + for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize && tilex < world.width(); tilex++){ + for(int tiley = cy * chunksize; tiley < (cy + 1) * chunksize && tiley < world.height(); tiley++){ + Tile tile = world.rawTile(tilex, tiley); - if(tile != null){ - if(tile.block().cacheLayer != CacheLayer.normal){ - used.add(tile.block().cacheLayer); - }else{ - used.add(tile.floor().cacheLayer); - } + if(tile.block().cacheLayer != CacheLayer.normal){ + used.add(tile.block().cacheLayer); + }else{ + used.add(tile.floor().cacheLayer); } } } @@ -169,7 +187,12 @@ public class FloorRenderer implements Disposable{ SpriteBatch current = Core.batch; Core.batch = cbatch; - cbatch.beginCache(); + //begin a new cache + if(chunk.caches[layer.ordinal()] == -1){ + cbatch.beginCache(); + }else{ + cbatch.beginCache(chunk.caches[layer.ordinal()]); + } for(int tilex = cx * chunksize; tilex < (cx + 1) * chunksize; tilex++){ for(int tiley = cy * chunksize; tiley < (cy + 1) * chunksize; tiley++){ @@ -191,13 +214,16 @@ public class FloorRenderer implements Disposable{ } } } + Core.batch = current; + cbatch.reserve(layer.capacity * chunksize * chunksize); chunk.caches[layer.ordinal()] = cbatch.endCache(); } public void clearTiles(){ if(cbatch != null) cbatch.dispose(); + recacheSet.clear(); int chunksx = Mathf.ceil((float)(world.width()) / chunksize), chunksy = Mathf.ceil((float)(world.height()) / chunksize); cache = new Chunk[chunksx][chunksy]; @@ -226,6 +252,8 @@ public class FloorRenderer implements Disposable{ } private class Chunk{ - int[] caches = new int[CacheLayer.values().length]; + /** Maps cache layer ID to cache ID in the batch. + * -1 means that this cache is unoccupied. */ + int[] caches = new int[CacheLayer.all.length]; } } diff --git a/core/src/mindustry/graphics/MenuRenderer.java b/core/src/mindustry/graphics/MenuRenderer.java index 9543ed68fd..ec11615b97 100644 --- a/core/src/mindustry/graphics/MenuRenderer.java +++ b/core/src/mindustry/graphics/MenuRenderer.java @@ -40,6 +40,7 @@ public class MenuRenderer implements Disposable{ } private void generate(){ + world.beginMapLoad(); Tiles tiles = world.resize(width, height); Array ores = content.blocks().select(b -> b instanceof OreBlock); shadows = new FrameBuffer(width, height); @@ -159,6 +160,8 @@ public class MenuRenderer implements Disposable{ tile.setOverlay(ore); } } + + world.endMapLoad(); } private void cache(){ diff --git a/core/src/mindustry/world/Tile.java b/core/src/mindustry/world/Tile.java index 109ff21df3..b56d170c8b 100644 --- a/core/src/mindustry/world/Tile.java +++ b/core/src/mindustry/world/Tile.java @@ -21,9 +21,9 @@ public class Tile implements Position{ /** Tile entity, usually null. */ public Tilec entity; public short x, y; - protected Block block; - protected Floor floor; - protected Floor overlay; + protected @NonNull Block block; + protected @NonNull Floor floor; + protected @NonNull Floor overlay; /** Rotation, 0-3. Also used to store offload location, in which case it can be any number.*/ protected byte rotation; /** Team ordinal. */ @@ -175,10 +175,13 @@ public class Tile implements Position{ changed(); } - /**This resets the overlay!*/ + /** This resets the overlay! */ public void setFloor(@NonNull Floor type){ this.floor = type; this.overlay = (Floor)Blocks.air; + + recache(); + block.onProximityUpdate(this); } /** Sets the floor, preserving overlay.*/ @@ -188,6 +191,19 @@ public class Tile implements Position{ setOverlay(overlay); } + public void recache(){ + if(!headless && !world.isGenerating()){ + renderer.blocks.floor.recacheTile(this); + renderer.minimap.update(this); + for(int i = 0; i < 8; i++){ + Tile other = world.tile(x + Geometry.d8[i].x, y + Geometry.d8[i].y); + if(other != null){ + renderer.blocks.floor.recacheTile(other); + } + } + } + } + public void remove(){ link().getLinkedTiles(other -> other.setBlock(Blocks.air)); } @@ -441,10 +457,14 @@ public class Tile implements Position{ } protected void preChanged(){ - block().removed(this); + block.removed(this); if(entity != null){ entity.removeFromProximity(); } + //recache when static blocks get changed + if(block.isStatic()){ + recache(); + } team = 0; } @@ -482,6 +502,11 @@ public class Tile implements Position{ updateOcclusion(); world.notifyChanged(this); + + //recache when static block is added + if(block.isStatic()){ + recache(); + } } @Override diff --git a/core/src/mindustry/world/blocks/production/Drill.java b/core/src/mindustry/world/blocks/production/Drill.java index 0840ef4aec..123b4bd19a 100644 --- a/core/src/mindustry/world/blocks/production/Drill.java +++ b/core/src/mindustry/world/blocks/production/Drill.java @@ -234,15 +234,21 @@ public class Drill extends Block{ returnCount = oreCount.get(itemArray.peek(), 0); } + @Override + public void onProximityUpdate(Tile tile){ + DrillEntity entity = tile.ent(); + + countOre(tile); + entity.dominantItem = returnItem; + entity.dominantItems = returnCount; + } + @Override public void update(Tile tile){ DrillEntity entity = tile.ent(); if(entity.dominantItem == null){ - countOre(tile); - if(returnItem == null) return; - entity.dominantItem = returnItem; - entity.dominantItems = returnCount; + return; } if(entity.timer(timerDump, dumpTime)){ diff --git a/gradle.properties b/gradle.properties index 878d926439..bcde86fca5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ org.gradle.daemon=true org.gradle.jvmargs=-Xms256m -Xmx1024m -archash=23a7b4c41d1723835af9b79aab1093384cfcc621 +archash=80007985ae0f1cb24531272e910844d0b4b5bb18 diff --git a/tests/src/test/java/ZoneTests.java b/tests/src/test/java/ZoneTests.java index cca493ac9d..0a3ce770af 100644 --- a/tests/src/test/java/ZoneTests.java +++ b/tests/src/test/java/ZoneTests.java @@ -36,7 +36,6 @@ public class ZoneTests{ for(Zone zone : content.zones()){ out.add(dynamicTest(zone.name, () -> { - zone.generator.init(zone.loadout); logic.reset(); try{ //world.loadGenerator(zone.generator);