diff --git a/src/main/java/de/ellpeck/rockbottom/assets/shader/ShaderProgram.java b/src/main/java/de/ellpeck/rockbottom/assets/shader/ShaderProgram.java index 2d235426..069c280e 100644 --- a/src/main/java/de/ellpeck/rockbottom/assets/shader/ShaderProgram.java +++ b/src/main/java/de/ellpeck/rockbottom/assets/shader/ShaderProgram.java @@ -80,7 +80,7 @@ public void link() { } @Override - public void bind() { + public IShaderProgram bind() { if (boundProgram != this.id) { boundProgram = this.id; boundProgramRef = this; @@ -92,6 +92,7 @@ public void bind() { GL20.glEnableVertexAttribArray(i); } } + return this; } @Override @@ -116,35 +117,40 @@ public void pointVertexAttribute(String name, int size) { } @Override - public void setUniform(String name, Matrix4f matrix) { + public IShaderProgram setUniform(String name, Matrix4f matrix) { int location = this.getUniformLocation(name); MemoryStack stack = MemoryStack.stackPush(); GL20.glUniformMatrix4fv(location, false, matrix.get(stack.mallocFloat(4 * 4))); stack.pop(); + return this; } @Override - public void setUniform(String name, int value) { + public IShaderProgram setUniform(String name, int value) { GL20.glUniform1i(this.getUniformLocation(name), value); + return this; } @Override - public void setUniform(String name, float f) { + public IShaderProgram setUniform(String name, float f) { GL20.glUniform1f(this.getUniformLocation(name), f); + return this; } @Override - public void setUniform(String name, float x, float y) { + public IShaderProgram setUniform(String name, float x, float y) { GL20.glUniform2f(this.getUniformLocation(name), x, y); + return this; } @Override - public void setUniform(String name, float x, float y, float z) { + public IShaderProgram setUniform(String name, float x, float y, float z) { GL20.glUniform3f(this.getUniformLocation(name), x, y, z); + return this; } @Override - public void unbind() { + public IShaderProgram unbind() { if (boundProgram == this.id) { for (int i : this.attributeLocations.values()) { GL20.glDisableVertexAttribArray(i); @@ -156,6 +162,7 @@ public void unbind() { boundProgram = -1; boundProgramRef = null; } + return this; } @Override diff --git a/src/main/java/de/ellpeck/rockbottom/assets/tex/Texture.java b/src/main/java/de/ellpeck/rockbottom/assets/tex/Texture.java index 5f39bb92..0e39c4ac 100644 --- a/src/main/java/de/ellpeck/rockbottom/assets/tex/Texture.java +++ b/src/main/java/de/ellpeck/rockbottom/assets/tex/Texture.java @@ -147,7 +147,7 @@ public void draw(float x, float y) { @Override public void draw(float x, float y, float scale) { - this.draw(x, y, this.renderWidth * scale, this.renderHeight * scale); + this.draw(x, y, this.renderWidth, this.renderHeight); } @Override diff --git a/src/main/java/de/ellpeck/rockbottom/init/RockBottom.java b/src/main/java/de/ellpeck/rockbottom/init/RockBottom.java index bf143ad6..6e03c2f1 100644 --- a/src/main/java/de/ellpeck/rockbottom/init/RockBottom.java +++ b/src/main/java/de/ellpeck/rockbottom/init/RockBottom.java @@ -534,7 +534,6 @@ protected void updateTickless() { this.renderer.cameraY = 0D; } SoundHandler.setListenerPos(this.renderer.cameraX, this.renderer.cameraY); - this.worldRenderer.calcCameraValues(this.renderer); this.render(); @@ -554,15 +553,11 @@ protected void render() { } this.renderer.setDefaultProgram(this.assetManager.getShaderProgram(IShaderProgram.GUI_SHADER)); - - float scale = this.renderer.getGuiScale(); - this.renderer.setScale(scale, scale); + this.assetManager.getShaderProgram(IShaderProgram.GUI_SHADER).bind().setUniform("scale", this.renderer.getGuiScale()); this.guiManager.render(this, this.assetManager, this.renderer, this.player); this.toaster.render(this, this.assetManager, this.renderer); - this.renderer.setScale(1F, 1F); - if (this.renderer.isDebug()) { DebugRenderer.render(this, this.assetManager, this.getPlayerWorld(), this.player, this.renderer); } diff --git a/src/main/java/de/ellpeck/rockbottom/particle/ParticleManager.java b/src/main/java/de/ellpeck/rockbottom/particle/ParticleManager.java index 18d401f1..252013c1 100644 --- a/src/main/java/de/ellpeck/rockbottom/particle/ParticleManager.java +++ b/src/main/java/de/ellpeck/rockbottom/particle/ParticleManager.java @@ -31,7 +31,7 @@ public void update(IGameInstance game) { } } - public void render(IGameInstance game, IAssetManager manager, IRenderer g, IWorld world, float transX, float transY) { + public void render(IGameInstance game, IAssetManager manager, IRenderer g, IWorld world) { this.particles.forEach(particle -> { ResourceName program = particle.getRenderShader(game, manager, g); g.setProgram(program == null ? null : manager.getShaderProgram(program)); @@ -40,7 +40,7 @@ public void render(IGameInstance game, IAssetManager manager, IRenderer g, IWorl double y = particle.getY(); int light = world.getCombinedVisualLight(Util.floor(x), Util.floor(y)); - particle.render(game, manager, g, (float) x - transX, (float) -y - transY + 1F, RockBottomAPI.getApiHandler().getColorByLight(light, TileLayer.MAIN)); + particle.render(game, manager, g, (float) x, (float) -y + 1F, RockBottomAPI.getApiHandler().getColorByLight(light, TileLayer.MAIN)); }); } diff --git a/src/main/java/de/ellpeck/rockbottom/render/WorldRenderer.java b/src/main/java/de/ellpeck/rockbottom/render/WorldRenderer.java index f75dfd95..7cc96657 100644 --- a/src/main/java/de/ellpeck/rockbottom/render/WorldRenderer.java +++ b/src/main/java/de/ellpeck/rockbottom/render/WorldRenderer.java @@ -77,7 +77,7 @@ public WorldRenderer() { this.addClouds(Util.RANDOM.nextInt(5) + 3, true); } - public void calcCameraValues(IRenderer g) { + public void calcCameraValues(IAssetManager m, IRenderer g) { double width = g.getWidthInWorld(); double height = g.getHeightInWorld(); @@ -101,11 +101,24 @@ public void calcCameraValues(IRenderer g) { this.maxY = Util.ceil(-this.transY + 1) - offset; } + private IShaderProgram setCameraValues(IAssetManager manager, ResourceName shader, float transX, float transY, float scale) { + IShaderProgram program = manager.getShaderProgram(shader); + program.bind(); + program.setUniform("camera", transX, transY, scale); + return program; + } + public void render(IGameInstance game, IAssetManager manager, ParticleManager particles, IRenderer g, AbstractWorld world, EntityPlayer player, InteractionManager input) { - float scale = g.getWorldScale(); + calcCameraValues(manager, g); + + this.setCameraValues(manager, IShaderProgram.BREAK_SHADER, this.transX, this.transY, g.getWorldScale()).unbind(); + this.setCameraValues(manager, IShaderProgram.WORLD_SHADER, 0, 0, g.getWorldScale()); this.renderSky(game, manager, g, world, player, g.getWidthInWorld(), g.getHeightInWorld()); + g.flush(); + this.setCameraValues(manager, IShaderProgram.WORLD_SHADER, this.transX, this.transY, g.getWorldScale()); + List entities = new ArrayList<>(); List players = new ArrayList<>(); @@ -113,7 +126,7 @@ public void render(IGameInstance game, IAssetManager manager, ParticleManager pa for (int gridX = this.minChunkX; gridX <= this.maxChunkX; gridX++) { if (world.isChunkLoaded(gridX, gridY)) { IChunk chunk = world.getChunkFromGridCoords(gridX, gridY); - this.renderChunk(game, manager, g, input, world, chunk, scale, chunk.getLoadedLayers(), false); + this.renderChunk(game, manager, g, input, world, chunk, chunk.getLoadedLayers(), false); for (Entity entity : chunk.getAllEntities()) { entities.add(entity); @@ -127,8 +140,6 @@ public void render(IGameInstance game, IAssetManager manager, ParticleManager pa } g.setProgram(null); - g.setScale(scale, scale); - entities.stream().sorted(Comparator.comparingInt(Entity::getRenderPriority)).forEach(entity -> { if (entity.shouldRender()) { IEntityRenderer renderer = entity.getRenderer(); @@ -165,16 +176,16 @@ public void render(IGameInstance game, IAssetManager manager, ParticleManager pa } } - renderer.render(game, manager, g, world, entity, (float) x - this.transX, (float) -y - this.transY + 1F, color); + renderer.render(game, manager, g, world, entity, (float) x, (float) -y + 1F, color); if (g.isBoundBoxDebug()) { - g.addFilledRect((float) x - this.transX - 0.1F, (float) -y - this.transY + 0.9F, 0.2F, 0.2F, Colors.GREEN); + g.addFilledRect((float) x - 0.1F, (float) -y + 0.9F, 0.2F, 0.2F, Colors.GREEN); BoundBox box = entity.currentBounds; - g.addEmptyRect((float) box.getMinX() - this.transX, (float) -box.getMaxY() - this.transY + 1F, (float) box.getWidth(), (float) box.getHeight(), 0.1F, Colors.RED); + g.addEmptyRect((float) box.getMinX(), (float) -box.getMaxY() + 1F, (float) box.getWidth(), (float) box.getHeight(), 0.1F, Colors.RED); BoundBox boxMotion = box.copy().add(entity.motionX, entity.motionY); - g.addEmptyRect((float) boxMotion.getMinX() - this.transX, (float) -boxMotion.getMaxY() - this.transY + 1F, (float) boxMotion.getWidth(), (float) boxMotion.getHeight(), 0.05F, Colors.YELLOW); + g.addEmptyRect((float) boxMotion.getMinX(), (float) -boxMotion.getMaxY() + 1F, (float) boxMotion.getWidth(), (float) boxMotion.getHeight(), 0.05F, Colors.YELLOW); } } } @@ -182,24 +193,22 @@ public void render(IGameInstance game, IAssetManager manager, ParticleManager pa }); g.setProgram(null); - particles.render(game, manager, g, world, this.transX, this.transY); + particles.render(game, manager, g, world); g.setProgram(null); - RockBottomAPI.getEventHandler().fireEvent(new WorldRenderEvent(game, manager, g, world, player, this.transX, this.transY)); + RockBottomAPI.getEventHandler().fireEvent(new WorldRenderEvent(game, manager, g, world, player)); players.forEach(entity -> { if (entity.shouldRender() && !entity.isLocalPlayer()) { - manager.getFont().drawCenteredString((float) entity.getLerpedX() - this.transX, (float) -entity.getLerpedY() - this.transY - 0.75F, entity.getChatColorFormat() + entity.getName(), 0.015F, false); + manager.getFont().drawCenteredString((float) entity.getLerpedX(), (float) -entity.getLerpedY() - 0.75F, entity.getChatColorFormat() + entity.getName(), 0.015F, false); } }); - g.setScale(1F, 1F); - for (int gridY = this.minChunkY; gridY <= this.maxChunkY; gridY++) { for (int gridX = this.minChunkX; gridX <= this.maxChunkX; gridX++) { if (world.isChunkLoaded(gridX, gridY)) { IChunk chunk = world.getChunkFromGridCoords(gridX, gridY); - this.renderChunk(game, manager, g, input, world, chunk, scale, chunk.getLoadedLayers(), true); + this.renderChunk(game, manager, g, input, world, chunk, chunk.getLoadedLayers(), true); } } } @@ -210,7 +219,6 @@ public void render(IGameInstance game, IAssetManager manager, ParticleManager pa boolean biomeDebug = g.isBiomeDebug(); if (chunkDebug || heightDebug || biomeDebug) { - g.setScale(scale, scale); for (int gridX = this.minChunkX; gridX <= this.maxChunkX; gridX++) { for (int gridY = this.minChunkY; gridY <= this.maxChunkY; gridY++) { @@ -219,7 +227,7 @@ public void render(IGameInstance game, IAssetManager manager, ParticleManager pa int worldY = Util.toWorldPos(gridY); if (chunkDebug) { - g.addEmptyRect(worldX - this.transX, -worldY - this.transY + 1F - Constants.CHUNK_SIZE, Constants.CHUNK_SIZE, Constants.CHUNK_SIZE, 0.1F, Colors.GREEN); + g.addEmptyRect(worldX, -worldY + 1F - Constants.CHUNK_SIZE, Constants.CHUNK_SIZE, Constants.CHUNK_SIZE, 0.1F, Colors.GREEN); } if (heightDebug || biomeDebug) { @@ -228,7 +236,11 @@ public void render(IGameInstance game, IAssetManager manager, ParticleManager pa if (heightDebug) { for (TileLayer layer : TileLayer.getLayersByRenderPrio()) { this.random.setSeed(layer.getName().hashCode()); - g.addFilledRect(worldX - this.transX + x, -worldY - this.transY + 1F - chunk.getHeightInner(layer, x), 1F, 0.1F, Colors.random(this.random)); + g.addFilledRect(worldX + x, -worldY + 1F - chunk.getHeightInner(layer, x), 1F, 0.1F, Colors.random(this.random)); + } + int highest = world.getHighestTile(worldX + x, world.getChunkHeight(TileLayer.MAIN, worldX, worldY), false); + if (highest >= chunk.getY() && highest <= chunk.getY() + Constants.CHUNK_SIZE) { + g.addFilledRect(worldX + x, -highest + 1.1F, 1F, 0.1F, Colors.YELLOW); } } @@ -236,10 +248,10 @@ public void render(IGameInstance game, IAssetManager manager, ParticleManager pa for (int y = 0; y < Constants.CHUNK_SIZE; y++) { if (!world.isClient()) { this.random.setSeed(chunk.getExpectedBiomeLevel(worldX + x, worldY + y).getName().hashCode()); - g.addFilledRect(worldX - this.transX + x + 0.35F, -worldY - this.transY - y + 0.35F, 0.3F, 0.3F, Colors.random(this.random)); + g.addFilledRect(worldX + x + 0.35F, -worldY - y + 0.35F, 0.3F, 0.3F, Colors.random(this.random)); } this.random.setSeed(chunk.getBiomeInner(x, y).getName().hashCode()); - g.addEmptyRect(worldX - this.transX + x + 0.25F, -worldY - this.transY - y + 0.25F, 0.5F, 0.5F, 0.1F, Colors.random(this.random)); + g.addEmptyRect(worldX + x + 0.25F, -worldY - y + 0.25F, 0.5F, 0.5F, 0.1F, Colors.random(this.random)); } } } @@ -247,12 +259,10 @@ public void render(IGameInstance game, IAssetManager manager, ParticleManager pa } } } - - g.setScale(1F, 1F); } } - private void renderChunk(IGameInstance game, IAssetManager manager, IRenderer g, InteractionManager input, IWorld world, IChunk chunk, float scale, List layers, boolean foreground) { + private void renderChunk(IGameInstance game, IAssetManager manager, IRenderer g, InteractionManager input, IWorld world, IChunk chunk, List layers, boolean foreground) { int chunkX = chunk.getX(); int chunkY = chunk.getY(); @@ -286,13 +296,13 @@ private void renderChunk(IGameInstance game, IAssetManager manager, IRenderer g, } } - this.renderLayer(game, manager, g, input, world, chunk, layer, x, y, scale, color, foreground); + this.renderLayer(game, manager, g, input, world, chunk, layer, x, y, color, foreground); } } } } - private void renderLayer(IGameInstance game, IAssetManager manager, IRenderer g, InteractionManager input, IWorld world, IChunk chunk, TileLayer layer, int x, int y, float scale, int[] color, boolean foreground) { + private void renderLayer(IGameInstance game, IAssetManager manager, IRenderer g, InteractionManager input, IWorld world, IChunk chunk, TileLayer layer, int x, int y, int[] color, boolean foreground) { if (layer.isVisible(game, game.getPlayer(), chunk, x, y, foreground)) { TileState state = chunk.getState(layer, x, y); Tile tile = state.getTile(); @@ -301,15 +311,15 @@ private void renderLayer(IGameInstance game, IAssetManager manager, IRenderer g, if (renderer != null) { if (foreground) { - this.renderTile(game, manager, g, input, world, layer, state, tile, renderer, x, y, scale, color, forcesForeground, true); + this.renderTile(game, manager, g, input, world, layer, state, tile, renderer, x, y, color, forcesForeground, true); } else if (!forcesForeground) { - this.renderTile(game, manager, g, input, world, layer, state, tile, renderer, x, y, scale, color, true, false); + this.renderTile(game, manager, g, input, world, layer, state, tile, renderer, x, y, color, true, false); } } } } - private void renderTile(IGameInstance game, IAssetManager manager, IRenderer g, InteractionManager input, IWorld world, TileLayer layer, TileState state, Tile tile, ITileRenderer renderer, int x, int y, float scale, int[] color, boolean renderNormal, boolean renderForeground) { + private void renderTile(IGameInstance game, IAssetManager manager, IRenderer g, InteractionManager input, IWorld world, TileLayer layer, TileState state, Tile tile, ITileRenderer renderer, int x, int y, int[] color, boolean renderNormal, boolean renderForeground) { boolean isBreakTile = input.breakingLayer == layer && input.breakProgress > 0 && x == input.breakTileX && y == input.breakTileY; if (isBreakTile) { @@ -321,11 +331,11 @@ private void renderTile(IGameInstance game, IAssetManager manager, IRenderer g, } if (renderNormal) { - renderer.render(game, manager, g, world, tile, state, x, y, layer, (x - this.transX) * scale, (-y - this.transY) * scale, scale, color); + renderer.render(game, manager, g, world, tile, state, x, y, layer, x, -y, 1, color); } if (renderForeground) { - renderer.renderInForeground(game, manager, g, world, tile, state, x, y, layer, (x - this.transX) * scale, (-y - this.transY) * scale, scale, color); + renderer.renderInForeground(game, manager, g, world, tile, state, x, y, layer, x, -y, 1, color); } if (isBreakTile) { @@ -345,11 +355,7 @@ private void renderSky(IGameInstance game, IAssetManager manager, IRenderer g, A int skyColor = SKY_COLORS[skyLight]; g.backgroundColor(skyColor); - float scale = g.getWorldScale(); - g.setScale(scale, scale); - int time = world.getCurrentTime(); - float worldScale = game.getSettings().renderScale; float starAlpha = 1F - Math.min(1F, skylightMod + 0.5F); if (starAlpha <= 0F) { @@ -372,8 +378,8 @@ private void renderSky(IGameInstance game, IAssetManager manager, IRenderer g, A } } - double radiusX = 10D / worldScale; - double radiusY = 7D / worldScale; + double radiusX = 10D; + double radiusY = 7D; double sunAngle = (time / (double) Constants.TIME_PER_DAY) * 360D + 180D; double sunRads = Math.toRadians(sunAngle); @@ -391,8 +397,6 @@ private void renderSky(IGameInstance game, IAssetManager manager, IRenderer g, A for (Cloud cloud : this.clouds) { cloud.render(manager, width, height, skylightMod, yOff); } - - g.setScale(1F, 1F); } public void update(IWorld world, IParticleManager manager) { diff --git a/src/main/java/de/ellpeck/rockbottom/render/tile/TileCaveMushroomRenderer.java b/src/main/java/de/ellpeck/rockbottom/render/tile/TileCaveMushroomRenderer.java index 86fc31b6..0f6e42a7 100644 --- a/src/main/java/de/ellpeck/rockbottom/render/tile/TileCaveMushroomRenderer.java +++ b/src/main/java/de/ellpeck/rockbottom/render/tile/TileCaveMushroomRenderer.java @@ -16,7 +16,7 @@ public class TileCaveMushroomRenderer extends TileMetaRenderer @Override public void render(IGameInstance game, IAssetManager manager, IRenderer g, IWorld world, TileCaveMushroom tile, TileState state, int x, int y, TileLayer layer, float renderX, float renderY, float scale, int[] light) { for (int i = 0; i < light.length; i++) { - light[i] = Math.max(light[i], Colors.multiply(Colors.WHITE, 0.2F)); + //light[i] = Math.max(light[i], Colors.multiply(Colors.WHITE, 0.2F)); } this.getTexture(manager, tile, state.get(tile.metaProp)).getPositionalVariation(x, y).draw(renderX, renderY, scale, scale, light); } diff --git a/src/main/java/de/ellpeck/rockbottom/world/AbstractWorld.java b/src/main/java/de/ellpeck/rockbottom/world/AbstractWorld.java index 76db914b..b4917907 100644 --- a/src/main/java/de/ellpeck/rockbottom/world/AbstractWorld.java +++ b/src/main/java/de/ellpeck/rockbottom/world/AbstractWorld.java @@ -6,6 +6,8 @@ import de.ellpeck.rockbottom.api.assets.IAssetManager; import de.ellpeck.rockbottom.api.data.set.DataSet; import de.ellpeck.rockbottom.api.data.set.ModBasedDataSet; +import de.ellpeck.rockbottom.api.data.set.part.DataPart; +import de.ellpeck.rockbottom.api.data.set.part.num.PartInt; import de.ellpeck.rockbottom.api.entity.Entity; import de.ellpeck.rockbottom.api.entity.player.AbstractEntityPlayer; import de.ellpeck.rockbottom.api.event.EventResult; @@ -61,6 +63,9 @@ public abstract class AbstractWorld implements IWorld { private BiomeGen biomeGen; private HeightGen heightGen; + // Maps every x position to the y position of the highest tile in the chunk + private Map highestTileLookup = new HashMap<>(); + public AbstractWorld(File worldDirectory, long seed) { this.seed = seed; @@ -169,12 +174,22 @@ public void loadWorldData(DataSet set) { this.time = set.getInt("time"); this.totalTime = set.getInt("total_time"); this.timeFrozen = set.getBoolean("time_frozen"); + DataSet highestTileSet = set.getDataSet("highest_tiles"); + this.highestTileLookup = new HashMap<>(); + for (Map.Entry entry : highestTileSet.getData().entrySet()) { + this.highestTileLookup.put(Integer.parseInt(entry.getKey()), ((PartInt)entry.getValue()).get()); + } } public void saveWorldData(DataSet set) { set.addInt("time", this.time); set.addInt("total_time", this.totalTime); set.addBoolean("time_frozen", this.timeFrozen); + DataSet highestTileSet = new DataSet(); + for (Map.Entry entry : this.highestTileLookup.entrySet()) { + highestTileSet.addInt(entry.getKey().toString(), entry.getValue()); + } + set.addDataSet("highest_tiles", highestTileSet); } protected void updateChunksAndTime(IGameInstance game) { @@ -585,6 +600,26 @@ public void destroyTile(int x, int y, TileLayer layer, Entity destroyer, boolean this.setState(layer, x, y, GameContent.TILE_AIR.getDefState()); } + @Override + public boolean hasHighestTile(int x) { + return highestTileLookup.containsKey(x); + } + + @Override + public int getHighestTile(int x, int fallback, boolean setFallback) { + if (this.highestTileLookup.containsKey(x)) { + int highest = this.highestTileLookup.get(x); + return highest; + } + if (setFallback) this.highestTileLookup.put(x, fallback); + return fallback; + } + + @Override + public void setHighestTile(int x, int y) { + this.highestTileLookup.put(x, y); + } + @Override public int getSpawnX() { return 0; @@ -664,6 +699,11 @@ private byte calcLight(int x, int y, boolean isSky, boolean checkGenerating) { } private byte getTileLight(int x, int y, boolean isSky) { + if (isSky && this.hasHighestTile(x)) { + int highestTile = this.getHighestTile(x, y - Constants.CHUNK_SIZE * 4, false); + //if (y > highestTile) return Constants.MAX_LIGHT; + } + int highestLight = 0; boolean nonAir = false; @@ -916,6 +956,12 @@ protected Chunk loadChunk(int gridX, int gridY, boolean isPersistent, boolean en return chunk; } + // TODO: this + protected void findHighestTile(int x, int startY) { + loadChunk(Util.toGridPos(x), Util.toGridPos(startY), false, true); + + } + @Override public void unloadChunk(IChunk chunk) { this.saveChunk(chunk, true); diff --git a/src/main/java/de/ellpeck/rockbottom/world/Chunk.java b/src/main/java/de/ellpeck/rockbottom/world/Chunk.java index cad56de8..f99fe5bb 100644 --- a/src/main/java/de/ellpeck/rockbottom/world/Chunk.java +++ b/src/main/java/de/ellpeck/rockbottom/world/Chunk.java @@ -2,6 +2,7 @@ import com.google.common.base.Preconditions; import de.ellpeck.rockbottom.api.*; +import de.ellpeck.rockbottom.api.construction.compendium.construction.ConstructionRecipe; import de.ellpeck.rockbottom.api.data.set.DataSet; import de.ellpeck.rockbottom.api.data.set.ModBasedDataSet; import de.ellpeck.rockbottom.api.data.set.part.PartDataSet; @@ -316,67 +317,73 @@ public void setStateInner(int x, int y, TileState tile) { } @Override - public void setStateInner(TileLayer layer, int x, int y, TileState state) { - SetStateEvent event = new SetStateEvent(this, state, layer, x, y); + public void setStateInner(TileLayer layer, int setStateX, int setStateY, TileState setState) { + SetStateEvent event = new SetStateEvent(this, setState, layer, setStateX, setStateY); if (RockBottomAPI.getEventHandler().fireEvent(event) != EventResult.CANCELLED) { - state = event.state; + setState = event.state; layer = event.layer; - x = event.x; - y = event.y; + setStateX = event.x; + setStateY = event.y; - Preconditions.checkNotNull(state, "Tried setting null tile in chunk at " + this.gridX + ", " + this.gridY + '!'); + Preconditions.checkNotNull(setState, "Tried setting null tile in chunk at " + this.gridX + ", " + this.gridY + '!'); Preconditions.checkNotNull(layer, "Tried setting tile to null layer in chunk at " + this.gridX + ", " + this.gridY + '!'); - TileState lastState = this.getStateInner(layer, x, y); - if (state != lastState) { - Tile tile = state.getTile(); - Preconditions.checkArgument(layer.canTileBeInLayer(this.world, this.x + x, this.y + y, tile), "Tried setting tile " + state + " at " + (this.x + x) + ", " + (this.y + y) + " on layer " + layer + " that doesn't allow it!"); + TileState lastState = this.getStateInner(layer, setStateX, setStateY); + if (setState != lastState) { + Tile setTile = setState.getTile(); + Preconditions.checkArgument(layer.canTileBeInLayer(this.world, this.x + setStateX, this.y + setStateY, setTile), "Tried setting tile " + setState + " at " + (this.x + setStateX) + ", " + (this.y + setStateY) + " on layer " + layer + " that doesn't allow it!"); Tile lastTile = lastState.getTile(); - boolean oldHeightMap = lastTile.factorsIntoHeightMap(this.world, this.x + x, this.y + y, layer); + boolean oldTileHadHeightmap = lastTile.factorsIntoHeightMap(this.world, this.x + setStateX, this.y + setStateY, layer); - if (tile != lastTile) { - lastTile.onRemoved(this.world, this.x + x, this.y + y, layer); + if (setTile != lastTile) { + lastTile.onRemoved(this.world, this.x + setStateX, this.y + setStateY, layer); if (layer.canHoldTileEntities() && lastTile.canProvideTileEntity()) { - this.removeTileEntity(layer, this.x + x, this.y + y); + this.removeTileEntity(layer, this.x + setStateX, this.y + setStateY); } } - TileState[][] grid = this.getGrid(layer, !tile.isAir()); + TileState[][] grid = this.getGrid(layer, !setTile.isAir()); if (grid != null) { - grid[x][y] = state; + grid[setStateX][setStateY] = setState; } - if (tile != lastTile) { - if (layer.canHoldTileEntities() && tile.canProvideTileEntity()) { - TileEntity tileEntity = tile.provideTileEntity(this.world, this.x + x, this.y + y, layer); - if (tileEntity != null) { - this.addTileEntity(tileEntity); - } - } - - tile.onAdded(this.world, this.x + x, this.y + y, layer); - } - - boolean newHeightMap = tile.factorsIntoHeightMap(this.world, this.x + x, this.y + y, layer); - if (newHeightMap != oldHeightMap) { + boolean newTileHasHeightmap = setTile.factorsIntoHeightMap(this.world, this.x + setStateX, this.y + setStateY, layer); + if (newTileHasHeightmap != oldTileHadHeightmap) { int newHeight = 0; - if (!newHeightMap) { - for (int checkY = y - 1; checkY >= 0; checkY--) { - if (this.getStateInner(layer, x, checkY).getTile().factorsIntoHeightMap(this.world, this.x + x, this.y + checkY, layer)) { + if (!newTileHasHeightmap) { + for (int checkY = setStateY - 1; checkY >= 0; checkY--) { + TileState checkState = this.getStateInner(layer, setStateX, checkY); + if (checkState.getTile().factorsIntoHeightMap(this.world, this.x + setStateX, this.y + checkY, layer)) { newHeight = checkY + 1; break; } } } else { - newHeight = y + 1; + newHeight = setStateY + 1; } int[] heights = this.heights.computeIfAbsent(layer, l -> new int[Constants.CHUNK_SIZE]); - if (heights[x] < newHeight || heights[x] == y + 1) { - heights[x] = newHeight; + + int oldHeight = heights[setStateX]; + + if (oldHeight < newHeight || oldHeight == setStateY + 1) { + + if (layer == TileLayer.MAIN) { + int actualX = getX() + setStateX; + boolean emptyCol = newHeight == 0 && !getStateInner(setStateX, 0).getTile().factorsIntoHeightMap(this.world, actualX, getY(), TileLayer.MAIN); + int realOld = getY() + oldHeight; + int realNew = getY() + newHeight; + if (emptyCol) { + realNew = world.getChunkHeight(TileLayer.MAIN, actualX, getY() - Constants.CHUNK_SIZE + 1) + getY() - Constants.CHUNK_SIZE; + } + int curHighest = world.getHighestTile(actualX, realNew, true); + if (realNew > curHighest || realOld == curHighest) world.setHighestTile(actualX, realNew); + } + + heights[setStateX] = newHeight; Set uniqueHeights = new HashSet<>(); int totalHeight = 0; @@ -391,12 +398,23 @@ public void setStateInner(TileLayer layer, int x, int y, TileState state) { } } + if (setTile != lastTile) { + if (layer.canHoldTileEntities() && setTile.canProvideTileEntity()) { + TileEntity tileEntity = setTile.provideTileEntity(this.world, this.x + setStateX, this.y + setStateY, layer); + if (tileEntity != null) { + this.addTileEntity(tileEntity); + } + } + + setTile.onAdded(this.world, this.x + setStateX, this.y + setStateY, layer); + } + if (!this.isGenerating) { - this.world.causeLightUpdate(this.x + x, this.y + y); - this.world.notifyNeighborsOfChange(this.x + x, this.y + y, layer); + this.world.causeLightUpdate(this.x + setStateX, this.y + setStateY); + this.world.notifyNeighborsOfChange(this.x + setStateX, this.y + setStateY, layer); - if (this.world.isServer() && this.getStateInner(layer, x, y) == state) { - RockBottomAPI.getNet().sendToAllPlayersWithLoadedPos(this.world, new PacketTileChange(this.x + x, this.y + y, layer, this.world.getIdForState(state)), this.x + x, this.y + y); + if (this.world.isServer() && this.getStateInner(layer, setStateX, setStateY) == setState) { + RockBottomAPI.getNet().sendToAllPlayersWithLoadedPos(this.world, new PacketTileChange(this.x + setStateX, this.y + setStateY, layer, this.world.getIdForState(setState)), this.x + setStateX, this.y + setStateY); } this.setDirty(); diff --git a/src/main/java/de/ellpeck/rockbottom/world/tile/TileCaveMushroom.java b/src/main/java/de/ellpeck/rockbottom/world/tile/TileCaveMushroom.java index 28916322..44dbe286 100644 --- a/src/main/java/de/ellpeck/rockbottom/world/tile/TileCaveMushroom.java +++ b/src/main/java/de/ellpeck/rockbottom/world/tile/TileCaveMushroom.java @@ -34,6 +34,10 @@ public BoundBox getBoundBox(IWorld world, TileState state, int x, int y, TileLay return null; } + @Override + public int getLight(IWorld world, int x, int y, TileLayer layer) { + return 20; + } @Override public boolean canStay(IWorld world, int x, int y, TileLayer layer, int changedX, int changedY, TileLayer changedLayer) { diff --git a/src/main/java/de/ellpeck/rockbottom/world/tile/TileLog.java b/src/main/java/de/ellpeck/rockbottom/world/tile/TileLog.java index ee57fb8f..ca50fe01 100644 --- a/src/main/java/de/ellpeck/rockbottom/world/tile/TileLog.java +++ b/src/main/java/de/ellpeck/rockbottom/world/tile/TileLog.java @@ -48,6 +48,12 @@ public void onDestroyed(IWorld world, int x, int y, Entity destroyer, TileLayer } } + public float getTranslucentModifier(IWorld world, int x, int y, TileLayer layer, boolean skylight) { + if (world.getState(layer, x, y).get(StaticTileProps.LOG_VARIANT).isNatural()) + return skylight ? 1F : layer == TileLayer.BACKGROUND ? 0.9f : 0.8f; + return super.getTranslucentModifier(world, x, y, layer, skylight); + } + private void recursiveTreeCheck(IWorld world, int x, int y, TileLayer layer, int originalY, List alreadyChecked) { for (Direction direction : Direction.ADJACENT) { if (direction != Direction.DOWN) { diff --git a/src/main/java/de/ellpeck/rockbottom/world/tile/TileWoodDoor.java b/src/main/java/de/ellpeck/rockbottom/world/tile/TileWoodDoor.java index 554979d6..67c7aae9 100644 --- a/src/main/java/de/ellpeck/rockbottom/world/tile/TileWoodDoor.java +++ b/src/main/java/de/ellpeck/rockbottom/world/tile/TileWoodDoor.java @@ -75,6 +75,12 @@ public boolean onInteractWith(IWorld world, int x, int y, TileLayer layer, doubl } } + public float getTranslucentModifier(IWorld world, int x, int y, TileLayer layer, boolean skylight) { + if (!world.getState(layer, x, y).get(StaticTileProps.OPEN)) + return layer == TileLayer.BACKGROUND ? 0.9F : solidLightPropagation; + return super.getTranslucentModifier(world, x, y, layer, skylight); + } + @Override public void doBreak(IWorld world, int x, int y, TileLayer layer, AbstractEntityPlayer breaker, boolean isRightTool, boolean allowDrop) { if (!world.isClient()) {