From b41a7b369488b1e7fba2f79359a79d150c9de323 Mon Sep 17 00:00:00 2001 From: Bixilon Date: Wed, 30 Sep 2020 16:35:02 +0200 Subject: [PATCH 1/5] rendering: improve face preparation, fix some bugs in world rendering/handling --- .../game/datatypes/world/BlockPosition.java | 1 + .../minosoft/game/datatypes/world/Chunk.java | 13 +- .../game/datatypes/world/ChunkNibble.java | 20 ++- .../minosoft/game/datatypes/world/World.java | 19 +-- .../clientbound/play/PacketChunkData.java | 6 +- .../play/PacketMultiBlockChange.java | 2 +- .../protocol/protocol/PacketHandler.java | 15 +- .../minosoft/render/WorldRenderer.java | 138 ++++++++++++++---- .../de/bixilon/minosoft/util/ChunkUtil.java | 14 +- 9 files changed, 158 insertions(+), 70 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/world/BlockPosition.java b/src/main/java/de/bixilon/minosoft/game/datatypes/world/BlockPosition.java index 52d1d82f9..0e818ef54 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/world/BlockPosition.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/world/BlockPosition.java @@ -63,6 +63,7 @@ public class BlockPosition { public ChunkLocation getChunkLocation() { int x = getX() / 16; int z = getZ() / 16; + //ToDo if (getX() < 0) { x--; } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/world/Chunk.java b/src/main/java/de/bixilon/minosoft/game/datatypes/world/Chunk.java index b5e636736..cc7d5739f 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/world/Chunk.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/world/Chunk.java @@ -18,14 +18,15 @@ import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Blocks; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Collection of 16 chunks nibbles */ public class Chunk { - final HashMap nibbles; + final ConcurrentHashMap nibbles; - public Chunk(HashMap chunks) { + public Chunk(ConcurrentHashMap chunks) { this.nibbles = chunks; } @@ -46,17 +47,17 @@ public class Chunk { public void setBlock(int x, int y, int z, Block block) { byte section = (byte) (y / 16); - createSection(section); + createSectionIfNotExist(section); nibbles.get(section).setBlock(x, y % 16, z, block); } public void setBlock(InChunkLocation location, Block block) { byte section = (byte) (location.getY() / 16); - createSection(section); + createSectionIfNotExist(section); nibbles.get(section).setBlock(location.getChunkNibbleLocation(), block); } - void createSection(byte section) { + void createSectionIfNotExist(byte section) { if (nibbles.get(section) == null) { // nibble was empty before, creating it nibbles.put(section, new ChunkNibble()); @@ -69,7 +70,7 @@ public class Chunk { } } - public HashMap getNibbles() { + public ConcurrentHashMap getNibbles() { return nibbles; } } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/world/ChunkNibble.java b/src/main/java/de/bixilon/minosoft/game/datatypes/world/ChunkNibble.java index 2445e1a28..01f633b34 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/world/ChunkNibble.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/world/ChunkNibble.java @@ -14,25 +14,29 @@ package de.bixilon.minosoft.game.datatypes.world; import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Block; +import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Blocks; -import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; /** * Collection of 16x16x16 blocks */ public class ChunkNibble { - final HashMap blocks; + final ConcurrentHashMap blocks; - public ChunkNibble(HashMap blocks) { + public ChunkNibble(ConcurrentHashMap blocks) { this.blocks = blocks; } public ChunkNibble() { // empty - this.blocks = new HashMap<>(); + this.blocks = new ConcurrentHashMap<>(); } public Block getBlock(ChunkNibbleLocation loc) { + if (!blocks.containsKey(loc)) { + return null; + } return blocks.get(loc); } @@ -41,14 +45,18 @@ public class ChunkNibble { } public void setBlock(int x, int y, int z, Block block) { - blocks.put(new ChunkNibbleLocation(x, y, z), block); + setBlock(new ChunkNibbleLocation(x, y, z), block); } public void setBlock(ChunkNibbleLocation location, Block block) { + if (block == null || block.equals(Blocks.nullBlock)) { + blocks.remove(location); + return; + } blocks.put(location, block); } - public HashMap getBlocks() { + public ConcurrentHashMap getBlocks() { return blocks; } } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/world/World.java b/src/main/java/de/bixilon/minosoft/game/datatypes/world/World.java index a5acd585d..c21864766 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/world/World.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/world/World.java @@ -17,20 +17,20 @@ import de.bixilon.minosoft.game.datatypes.entities.Entity; import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Block; import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Blocks; import de.bixilon.minosoft.game.datatypes.objectLoader.dimensions.Dimension; -import de.bixilon.minosoft.render.GameWindow; import de.bixilon.minosoft.util.nbt.tag.CompoundTag; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Collection of ChunkColumns */ public class World { - final HashMap chunks = new HashMap<>(); - final HashMap entities = new HashMap<>(); + final ConcurrentHashMap chunks = new ConcurrentHashMap<>(); + final ConcurrentHashMap entities = new ConcurrentHashMap<>(); final String name; - final HashMap blockEntityMeta = new HashMap<>(); + final ConcurrentHashMap blockEntityMeta = new ConcurrentHashMap<>(); boolean hardcore; boolean raining; Dimension dimension; // used for sky color, etc @@ -47,7 +47,7 @@ public class World { return chunks.get(loc); } - public HashMap getAllChunks() { + public ConcurrentHashMap getAllChunks() { return chunks; } @@ -65,7 +65,6 @@ public class World { public void setBlock(BlockPosition pos, Block block) { if (getChunk(pos.getChunkLocation()) != null) { getChunk(pos.getChunkLocation()).setBlock(pos.getInChunkLocation(), block); - GameWindow.getRenderer().prepareChunkNibble(pos.getChunkLocation(), (byte) (pos.getY() / 16), getChunk(pos.getChunkLocation()).getNibbles().get((byte) (pos.getY() / 16))); } // do nothing if chunk is unloaded } @@ -76,14 +75,10 @@ public class World { public void setChunk(ChunkLocation location, Chunk chunk) { chunks.put(location, chunk); - GameWindow.getRenderer().queueChunk(location, chunk); } public void setChunks(HashMap chunkMap) { - for (Map.Entry set : chunkMap.entrySet()) { - chunks.put(set.getKey(), set.getValue()); - } - GameWindow.getRenderer().queueChunkBulk(chunkMap); + chunkMap.forEach(chunks::put); } public boolean isHardcore() { @@ -135,7 +130,7 @@ public class World { return blockEntityMeta.get(position); } - public void setBlockEntityData(HashMap blockEntities) { + public void setBlockEntityData(ConcurrentHashMap blockEntities) { for (Map.Entry entrySet : blockEntities.entrySet()) { blockEntityMeta.put(entrySet.getKey(), entrySet.getValue()); } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkData.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkData.java index da59b57e0..ed2b09332 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkData.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkData.java @@ -24,10 +24,10 @@ import de.bixilon.minosoft.util.ChunkUtil; import de.bixilon.minosoft.util.Util; import de.bixilon.minosoft.util.nbt.tag.CompoundTag; -import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; public class PacketChunkData implements ClientboundPacket { - final HashMap blockEntities = new HashMap<>(); + final ConcurrentHashMap blockEntities = new ConcurrentHashMap<>(); ChunkLocation location; Chunk chunk; CompoundTag heightMap; @@ -122,7 +122,7 @@ public class PacketChunkData implements ClientboundPacket { return chunk; } - public HashMap getBlockEntities() { + public ConcurrentHashMap getBlockEntities() { return blockEntities; } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketMultiBlockChange.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketMultiBlockChange.java index d46cd8750..54f9cbe68 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketMultiBlockChange.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketMultiBlockChange.java @@ -55,7 +55,7 @@ public class PacketMultiBlockChange implements ClientboundPacket { byte pos = buffer.readByte(); byte y = buffer.readByte(); int blockId = buffer.readVarInt(); - blocks.put(new InChunkLocation((pos & 0xF0 >>> 4) & 0xF, y, pos & 0xF), buffer.getConnection().getMapping().getBlockById(blockId)); + blocks.put(new InChunkLocation((pos >>> 4) & 0xF, y, pos & 0xF), buffer.getConnection().getMapping().getBlockById(blockId)); } return true; } diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java index e003f3c01..b775dbced 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java @@ -29,6 +29,7 @@ import de.bixilon.minosoft.game.datatypes.scoreboard.ScoreboardScore; import de.bixilon.minosoft.game.datatypes.scoreboard.Team; import de.bixilon.minosoft.game.datatypes.world.BlockPosition; import de.bixilon.minosoft.game.datatypes.world.Chunk; +import de.bixilon.minosoft.game.datatypes.world.ChunkLocation; import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.protocol.network.Connection; import de.bixilon.minosoft.protocol.packets.clientbound.login.*; @@ -38,10 +39,10 @@ import de.bixilon.minosoft.protocol.packets.clientbound.status.PacketStatusRespo import de.bixilon.minosoft.protocol.packets.serverbound.login.PacketEncryptionResponse; import de.bixilon.minosoft.protocol.packets.serverbound.play.PacketKeepAliveResponse; import de.bixilon.minosoft.protocol.packets.serverbound.play.PacketResourcePackStatus; -import de.bixilon.minosoft.util.nbt.tag.CompoundTag; -import de.bixilon.minosoft.util.nbt.tag.StringTag; import de.bixilon.minosoft.render.GameWindow; import de.bixilon.minosoft.render.utility.Vec3; +import de.bixilon.minosoft.util.nbt.tag.CompoundTag; +import de.bixilon.minosoft.util.nbt.tag.StringTag; import javax.crypto.SecretKey; import java.math.BigInteger; @@ -67,7 +68,7 @@ public class PacketHandler { if (version == null) { Log.fatal(String.format("Server is running on unknown version or a invalid version was forced (version=%d, brand=\"%s\")", versionId, pkg.getResponse().getServerBrand())); } else { - connection.setVersion(version); + connection.setVersion(version); } Log.info(String.format("Status response received: %s/%s online. MotD: '%s'", pkg.getResponse().getPlayerOnline(), pkg.getResponse().getMaxPlayers(), pkg.getResponse().getMotd().getColoredMessage())); connection.handlePingCallbacks(pkg.getResponse()); @@ -172,6 +173,7 @@ public class PacketHandler { public void handle(PacketChunkBulk pkg) { connection.getPlayer().getWorld().setChunks(pkg.getChunkMap()); + GameWindow.getRenderer().queueChunkBulk(pkg.getChunkMap()); } public void handle(PacketUpdateHealth pkg) { @@ -288,7 +290,10 @@ public class PacketHandler { } public void handle(PacketBlockChange pkg) { - connection.getPlayer().getWorld().setBlock(pkg.getPosition(), pkg.getBlock()); + ChunkLocation chunkLocation = pkg.getPosition().getChunkLocation(); + Chunk chunk = connection.getPlayer().getWorld().getChunk(chunkLocation); + chunk.setBlock(pkg.getPosition().getInChunkLocation(), pkg.getBlock()); + GameWindow.getRenderer().queueChunk(chunkLocation, chunk); // ToDo: only recalculate the changed nibbles } public void handle(PacketMultiBlockChange pkg) { @@ -298,6 +303,7 @@ public class PacketHandler { return; } chunk.setBlocks(pkg.getBlocks()); + GameWindow.getRenderer().queueChunk(pkg.getLocation(), chunk); // ToDo: only recalculate the changed nibbles } public void handle(PacketRespawn pkg) { @@ -328,6 +334,7 @@ public class PacketHandler { public void handle(PacketChunkData pkg) { connection.getPlayer().getWorld().setChunk(pkg.getLocation(), pkg.getChunk()); connection.getPlayer().getWorld().setBlockEntityData(pkg.getBlockEntities()); + GameWindow.getRenderer().queueChunk(pkg.getLocation(), pkg.getChunk()); } public void handle(PacketEntityEffect pkg) { diff --git a/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java b/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java index 4af617faa..ce3b18b77 100644 --- a/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java +++ b/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java @@ -22,8 +22,10 @@ import javafx.util.Pair; import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.atomic.AtomicInteger; import static org.lwjgl.opengl.GL11.*; @@ -33,6 +35,11 @@ public class WorldRenderer { private LinkedBlockingQueue> queuedChunks; + public int getCountOfFaces() { + AtomicInteger count = new AtomicInteger(); + faces.forEach((chunkLocation, nibbleMap) -> nibbleMap.forEach((height, faceMap) -> faceMap.forEach(((nibbleLocation, faces) -> faces.forEach((face -> count.incrementAndGet())))))); + return count.get(); + } public void init() { queuedChunks = new LinkedBlockingQueue<>(); @@ -44,7 +51,8 @@ public class WorldRenderer { while (true) { try { Pair current = queuedChunks.take(); - prepareChunk(current.getKey(), current.getValue()); + prepareChunk(current.getKey(), current.getValue(), true); + //Log.verbose(String.format("Count of faces: %d", getCountOfFaces())); } catch (InterruptedException e) { e.printStackTrace(); } @@ -62,52 +70,113 @@ public class WorldRenderer { queuedChunks.add(new Pair<>(location, chunk)); } - public void prepareChunk(ChunkLocation location, Chunk chunk) { + public void prepareChunk(ChunkLocation location, Chunk chunk, boolean checkEdges) { // clear or create current chunk - faces.put(location, new ConcurrentHashMap<>()); - chunk.getNibbles().forEach(((height, chunkNibble) -> prepareChunkNibble(location, height, chunkNibble))); + ConcurrentHashMap>> chunkFaces = new ConcurrentHashMap<>(); + chunk.getNibbles().forEach(((height, chunkNibble) -> chunkFaces.put(height, getFacesForChunkNibble(location, height, chunkNibble)))); + faces.put(location, chunkFaces); + if (!checkEdges) { + return; + } + //ToDo + } - public void prepareChunkNibble(ChunkLocation chunkLocation, byte height, ChunkNibble nibble) { + public ConcurrentHashMap> getFacesForChunkNibble(ChunkLocation chunkLocation, byte sectionHeight, ChunkNibble nibble) { + ConcurrentHashMap world = GameWindow.getConnection().getPlayer().getWorld().getAllChunks(); // clear or create current chunk nibble ConcurrentHashMap> nibbleMap = new ConcurrentHashMap<>(); - faces.get(chunkLocation).put(height, nibbleMap); - HashMap nibbleBlocks = nibble.getBlocks(); - nibbleBlocks.forEach((location, block) -> { + ConcurrentHashMap nibbleBlocks = nibble.getBlocks(); + for (Map.Entry entry : nibbleBlocks.entrySet()) { + ChunkNibbleLocation location = entry.getKey(); + Block block = entry.getValue(); HashSet facesToDraw = new HashSet<>(); for (FaceOrientation orientation : FaceOrientation.values()) { - if ((location.getX() == 0 && orientation == FaceOrientation.WEST) || (location.getX() == 15 && orientation == FaceOrientation.EAST)) { - facesToDraw.add(orientation); - continue; - } - if ((location.getY() == 0 && orientation == FaceOrientation.DOWN) || (location.getY() == 15 && orientation == FaceOrientation.UP)) { - facesToDraw.add(orientation); - continue; - } - if ((location.getZ() == 0 && orientation == FaceOrientation.NORTH) || (location.getZ() == 15 && orientation == FaceOrientation.SOUTH)) { - facesToDraw.add(orientation); - continue; - } - //BlockPosition neighbourPos = location.add(faceDir[orientation.ordinal()]); - boolean isNeighbourFull = switch (orientation) { - case DOWN -> assetsLoader.getBlockModelLoader().isFull(nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY() - 1, location.getZ()))); - case UP -> assetsLoader.getBlockModelLoader().isFull(nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY() + 1, location.getZ()))); - case WEST -> assetsLoader.getBlockModelLoader().isFull(nibbleBlocks.get(new ChunkNibbleLocation(location.getX() - 1, location.getY(), location.getZ()))); - case EAST -> assetsLoader.getBlockModelLoader().isFull(nibbleBlocks.get(new ChunkNibbleLocation(location.getX() + 1, location.getY(), location.getZ()))); - case NORTH -> assetsLoader.getBlockModelLoader().isFull(nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY(), location.getZ() - 1))); - case SOUTH -> assetsLoader.getBlockModelLoader().isFull(nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY(), location.getZ() + 1))); + Block dependedBlock = switch (orientation) { + case DOWN -> { + if (location.getY() == 0) { + // need to check upper section (nibble) + if (sectionHeight == 0) { + // y = 0, there can't be any blocks below me + yield null; + } + // check if block over us is a full block + byte bottomSection = (byte) (sectionHeight - 1); + if (!world.get(chunkLocation).getNibbles().containsKey(bottomSection)) { + yield null; + } + yield world.get(chunkLocation).getNibbles().get(bottomSection).getBlock(location.getX(), 15, location.getZ()); + } + yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY() - 1, location.getZ())); + } + case UP -> { + if (location.getY() == 15) { + // need to check upper section (nibble) + if (sectionHeight == 15) { + // y = 255, there can't be any blocks above me + yield null; + } + // check if block over us is a full block + byte upperSection = (byte) (sectionHeight + 1); + if (!world.get(chunkLocation).getNibbles().containsKey(upperSection)) { + yield null; + } + yield world.get(chunkLocation).getNibbles().get(upperSection).getBlock(location.getX(), 0, location.getZ()); + } + yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY() + 1, location.getZ())); + } + case WEST -> { + if (location.getX() == 0) { + ChunkNibble otherChunkNibble = getChunkNibbleOfWorld(world, new ChunkLocation(chunkLocation.getX() - 1, chunkLocation.getZ()), sectionHeight); + if (otherChunkNibble != null) { + yield otherChunkNibble.getBlock(15, location.getY(), location.getZ()); + } + } + yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX() - 1, location.getY(), location.getZ())); + } + case EAST -> { + if (location.getX() == 15) { + ChunkNibble otherChunkNibble = getChunkNibbleOfWorld(world, new ChunkLocation(chunkLocation.getX() + 1, chunkLocation.getZ()), sectionHeight); + if (otherChunkNibble != null) { + yield otherChunkNibble.getBlock(0, location.getY(), location.getZ()); + } + } + yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX() + 1, location.getY(), location.getZ())); + } + case NORTH -> { + if (location.getZ() == 0) { + ChunkNibble otherChunkNibble = getChunkNibbleOfWorld(world, new ChunkLocation(chunkLocation.getX(), chunkLocation.getZ() - 1), sectionHeight); + if (otherChunkNibble != null) { + yield otherChunkNibble.getBlock(location.getX(), location.getY(), 15); + } + } + yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY(), location.getZ() - 1)); + } + case SOUTH -> { + if (location.getZ() == 15) { + ChunkNibble otherChunkNibble = getChunkNibbleOfWorld(world, new ChunkLocation(chunkLocation.getX(), chunkLocation.getZ() + 1), sectionHeight); + if (otherChunkNibble != null) { + yield otherChunkNibble.getBlock(location.getX(), location.getY(), 0); + } + } + yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY(), location.getZ() + 1)); + } }; - if (!isNeighbourFull) { + if (dependedBlock == null || !assetsLoader.getBlockModelLoader().isFull(dependedBlock)) { facesToDraw.add(orientation); } - } if (facesToDraw.size() > 0) { nibbleMap.put(location, assetsLoader.getBlockModelLoader().prepare(block, facesToDraw)); } - }); + } + return nibbleMap; + } + + public void prepareChunkNibble(ChunkLocation chunkLocation, byte sectionHeight, ChunkNibble nibble) { + faces.get(chunkLocation).put(sectionHeight, getFacesForChunkNibble(chunkLocation, sectionHeight, nibble)); } @@ -122,4 +191,11 @@ public class WorldRenderer { public AssetsLoader getAssetsLoader() { return assetsLoader; } + + private ChunkNibble getChunkNibbleOfWorld(ConcurrentHashMap world, ChunkLocation location, byte sectionHeight) { + if (world.containsKey(location) && world.get(location).getNibbles().containsKey(sectionHeight)) { + return world.get(location).getNibbles().get(sectionHeight); + } + return null; + } } diff --git a/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java b/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java index a61606332..4d6874510 100644 --- a/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java +++ b/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java @@ -23,7 +23,7 @@ import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.protocol.protocol.InByteBuffer; import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; -import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; public final class ChunkUtil { public static Chunk readChunkPacket(InByteBuffer buffer, short sectionBitMask, short addBitMask, boolean groundUpContinuous, boolean containsSkyLight) { @@ -51,11 +51,11 @@ public final class ChunkUtil { //parse data int arrayPos = 0; - HashMap nibbleMap = new HashMap<>(); + ConcurrentHashMap nibbleMap = new ConcurrentHashMap<>(); for (byte c = 0; c < 16; c++) { // max sections per chunks in chunk column if (BitByte.isBitSet(sectionBitMask, c)) { - HashMap blockMap = new HashMap<>(); + ConcurrentHashMap blockMap = new ConcurrentHashMap<>(); for (int nibbleY = 0; nibbleY < 16; nibbleY++) { for (int nibbleZ = 0; nibbleZ < 16; nibbleZ++) { @@ -115,12 +115,12 @@ public final class ChunkUtil { } int arrayPos = 0; - HashMap nibbleMap = new HashMap<>(); + ConcurrentHashMap nibbleMap = new ConcurrentHashMap<>(); for (byte c = 0; c < 16; c++) { // max sections per chunks in chunk column if (!BitByte.isBitSet(sectionBitMask, c)) { continue; } - HashMap blockMap = new HashMap<>(); + ConcurrentHashMap blockMap = new ConcurrentHashMap<>(); for (int nibbleY = 0; nibbleY < 16; nibbleY++) { for (int nibbleZ = 0; nibbleZ < 16; nibbleZ++) { @@ -141,7 +141,7 @@ public final class ChunkUtil { return new Chunk(nibbleMap); } // really big thanks to: https://wiki.vg/index.php?title=Chunk_Format&oldid=13712 - HashMap nibbleMap = new HashMap<>(); + ConcurrentHashMap nibbleMap = new ConcurrentHashMap<>(); for (byte c = 0; c < 16; c++) { // max sections per chunks in chunk column if (!BitByte.isBitSet(sectionBitMask, c)) { continue; @@ -155,7 +155,7 @@ public final class ChunkUtil { long[] data = buffer.readLongArray(buffer.readVarInt()); - HashMap blockMap = new HashMap<>(); + ConcurrentHashMap blockMap = new ConcurrentHashMap<>(); for (int nibbleY = 0; nibbleY < 16; nibbleY++) { for (int nibbleZ = 0; nibbleZ < 16; nibbleZ++) { for (int nibbleX = 0; nibbleX < 16; nibbleX++) { From ae139f0ca054339604f3f214cdc5813dd2bcd9ae Mon Sep 17 00:00:00 2001 From: Bixilon Date: Wed, 30 Sep 2020 17:41:43 +0200 Subject: [PATCH 2/5] improve rendering even more (face preparations) --- .../protocol/protocol/PacketHandler.java | 9 +- .../minosoft/render/WorldRenderer.java | 120 +++++++++++++++--- 2 files changed, 107 insertions(+), 22 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java index b775dbced..68e6809d7 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java @@ -29,7 +29,6 @@ import de.bixilon.minosoft.game.datatypes.scoreboard.ScoreboardScore; import de.bixilon.minosoft.game.datatypes.scoreboard.Team; import de.bixilon.minosoft.game.datatypes.world.BlockPosition; import de.bixilon.minosoft.game.datatypes.world.Chunk; -import de.bixilon.minosoft.game.datatypes.world.ChunkLocation; import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.protocol.network.Connection; import de.bixilon.minosoft.protocol.packets.clientbound.login.*; @@ -290,10 +289,8 @@ public class PacketHandler { } public void handle(PacketBlockChange pkg) { - ChunkLocation chunkLocation = pkg.getPosition().getChunkLocation(); - Chunk chunk = connection.getPlayer().getWorld().getChunk(chunkLocation); - chunk.setBlock(pkg.getPosition().getInChunkLocation(), pkg.getBlock()); - GameWindow.getRenderer().queueChunk(chunkLocation, chunk); // ToDo: only recalculate the changed nibbles + connection.getPlayer().getWorld().getChunk(pkg.getPosition().getChunkLocation()).setBlock(pkg.getPosition().getInChunkLocation(), pkg.getBlock()); + GameWindow.getRenderer().queueBlock(pkg.getPosition(), pkg.getBlock()); } public void handle(PacketMultiBlockChange pkg) { @@ -303,7 +300,7 @@ public class PacketHandler { return; } chunk.setBlocks(pkg.getBlocks()); - GameWindow.getRenderer().queueChunk(pkg.getLocation(), chunk); // ToDo: only recalculate the changed nibbles + GameWindow.getRenderer().queueChunk(pkg.getLocation(), chunk); } public void handle(PacketRespawn pkg) { diff --git a/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java b/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java index ce3b18b77..0e12055bb 100644 --- a/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java +++ b/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java @@ -1,6 +1,6 @@ /* * Codename Minosoft - * Copyright (C) 2020 Lukas Eisenhauer + * Copyright (C) 2020 Lukas Eisenhauer, Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -14,11 +14,11 @@ package de.bixilon.minosoft.render; import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Block; +import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Blocks; import de.bixilon.minosoft.game.datatypes.world.*; import de.bixilon.minosoft.protocol.network.Connection; import de.bixilon.minosoft.render.blockModels.Face.Face; import de.bixilon.minosoft.render.blockModels.Face.FaceOrientation; -import javafx.util.Pair; import java.util.HashMap; import java.util.HashSet; @@ -33,7 +33,7 @@ public class WorldRenderer { private final ConcurrentHashMap>>> faces = new ConcurrentHashMap<>(); private AssetsLoader assetsLoader; - private LinkedBlockingQueue> queuedChunks; + private LinkedBlockingQueue queuedMapData; public int getCountOfFaces() { AtomicInteger count = new AtomicInteger(); @@ -42,7 +42,7 @@ public class WorldRenderer { } public void init() { - queuedChunks = new LinkedBlockingQueue<>(); + queuedMapData = new LinkedBlockingQueue<>(); assetsLoader = new AssetsLoader(); } @@ -50,8 +50,7 @@ public class WorldRenderer { Thread chunkLoadThread = new Thread(() -> { while (true) { try { - Pair current = queuedChunks.take(); - prepareChunk(current.getKey(), current.getValue(), true); + queuedMapData.take().run(); //Log.verbose(String.format("Count of faces: %d", getCountOfFaces())); } catch (InterruptedException e) { e.printStackTrace(); @@ -67,22 +66,30 @@ public class WorldRenderer { } public void queueChunk(ChunkLocation location, Chunk chunk) { - queuedChunks.add(new Pair<>(location, chunk)); + queuedMapData.add(() -> prepareChunk(location, chunk)); } - public void prepareChunk(ChunkLocation location, Chunk chunk, boolean checkEdges) { + public void queueChunkNibble(ChunkLocation location, byte sectionHeight, ChunkNibble nibble) { + queuedMapData.add(() -> prepareChunkNibble(location, sectionHeight, nibble)); + } + + public void queueBlock(BlockPosition position, Block block) { + queuedMapData.add(() -> prepareBlock(position, block, false)); + } + + private void prepareChunk(ChunkLocation location, Chunk chunk) { // clear or create current chunk ConcurrentHashMap>> chunkFaces = new ConcurrentHashMap<>(); chunk.getNibbles().forEach(((height, chunkNibble) -> chunkFaces.put(height, getFacesForChunkNibble(location, height, chunkNibble)))); faces.put(location, chunkFaces); - if (!checkEdges) { - return; - } - //ToDo - } - public ConcurrentHashMap> getFacesForChunkNibble(ChunkLocation chunkLocation, byte sectionHeight, ChunkNibble nibble) { + private void prepareChunkNibble(ChunkLocation chunkLocation, byte sectionHeight, ChunkNibble nibble) { + faces.get(chunkLocation).put(sectionHeight, getFacesForChunkNibble(chunkLocation, sectionHeight, nibble)); + } + + + private ConcurrentHashMap> getFacesForChunkNibble(ChunkLocation chunkLocation, byte sectionHeight, ChunkNibble nibble) { ConcurrentHashMap world = GameWindow.getConnection().getPlayer().getWorld().getAllChunks(); // clear or create current chunk nibble ConcurrentHashMap> nibbleMap = new ConcurrentHashMap<>(); @@ -175,8 +182,88 @@ public class WorldRenderer { return nibbleMap; } - public void prepareChunkNibble(ChunkLocation chunkLocation, byte sectionHeight, ChunkNibble nibble) { - faces.get(chunkLocation).put(sectionHeight, getFacesForChunkNibble(chunkLocation, sectionHeight, nibble)); + + private void prepareBlock(BlockPosition position, Block block, boolean trustEdges) { + HashSet facesToDraw = new HashSet<>(); + + if (block != null && !block.equals(Blocks.nullBlock)) { + for (FaceOrientation orientation : FaceOrientation.values()) { + Block dependedBlock = switch (orientation) { + case DOWN -> { + if (position.getY() == 0) { + facesToDraw.add(orientation); + yield null; + } + yield GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX(), position.getY() - 1, position.getZ())); + } + case UP -> { + if (position.getY() == 255) { + facesToDraw.add(orientation); + yield null; + } + yield GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX(), position.getY() + 1, position.getZ())); + } + case NORTH -> { + if (position.getY() == 255) { + facesToDraw.add(orientation); + yield null; + } + yield GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX(), position.getY(), position.getZ() - 1)); + } + case SOUTH -> { + if (position.getY() == 255) { + facesToDraw.add(orientation); + yield null; + } + yield GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX(), position.getY(), position.getZ() + 1)); + } + case WEST -> { + if (position.getY() == 255) { + facesToDraw.add(orientation); + yield null; + } + yield GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX() - 1, position.getY(), position.getZ())); + } + case EAST -> { + if (position.getY() == 255) { + facesToDraw.add(orientation); + yield null; + } + yield GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX() + 1, position.getY(), position.getZ())); + } + }; + if (dependedBlock == null || !assetsLoader.getBlockModelLoader().isFull(dependedBlock)) { + facesToDraw.add(orientation); + } + } + } + ConcurrentHashMap> nibbleMap = faces.get(position.getChunkLocation()).get((byte) (position.getY() / 16)); + if (facesToDraw.size() == 0) { + // remove all faces + nibbleMap.remove(position.getInChunkLocation().getChunkNibbleLocation()); + } else { + nibbleMap.put(position.getInChunkLocation().getChunkNibbleLocation(), assetsLoader.getBlockModelLoader().prepare(block, facesToDraw)); + } + + if (trustEdges) { + return; + } + if (position.getY() != 0) { + // bottom + prepareBlock(new BlockPosition(position.getX(), position.getY() - 1, position.getZ()), true); + } + if (position.getY() != 255) { + // bottom + prepareBlock(new BlockPosition(position.getX(), position.getY() + 1, position.getZ()), true); + } + prepareBlock(new BlockPosition(position.getX() + 1, position.getY(), position.getZ()), true); + prepareBlock(new BlockPosition(position.getX() - 1, position.getY(), position.getZ()), true); + prepareBlock(new BlockPosition(position.getX(), position.getY(), position.getZ() + 1), true); + prepareBlock(new BlockPosition(position.getX(), position.getY(), position.getZ() - 1), true); + } + + private void prepareBlock(BlockPosition position, boolean trustEdges) { + prepareBlock(position, GameWindow.getConnection().getPlayer().getWorld().getBlock(position), trustEdges); } @@ -198,4 +285,5 @@ public class WorldRenderer { } return null; } + } From 340a154ca912cad9d17586b2bd80451d77996843 Mon Sep 17 00:00:00 2001 From: Bixilon Date: Wed, 30 Sep 2020 19:04:54 +0200 Subject: [PATCH 3/5] replace magic chunk numbers with constants --- .../datatypes/objectLoader/blocks/Block.java | 4 +- .../game/datatypes/world/BlockPosition.java | 20 ++--- .../minosoft/game/datatypes/world/Chunk.java | 19 ++--- .../game/datatypes/world/InChunkLocation.java | 13 +--- .../minosoft/render/WorldRenderer.java | 73 +++++++------------ .../blockModels/Face/RenderConstants.java | 19 ++++- .../subBlocks/SubBlockPosition.java | 19 ++--- .../minosoft/render/texture/InFaceUV.java | 10 +-- .../render/texture/TextureLoader.java | 16 ++-- .../de/bixilon/minosoft/util/ChunkUtil.java | 37 +++++----- 10 files changed, 100 insertions(+), 130 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/blocks/Block.java b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/blocks/Block.java index 42418c8a5..a22b95cdf 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/blocks/Block.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/blocks/Block.java @@ -73,7 +73,7 @@ public class Block { out.append("rotation="); out.append(getRotation()); } - if (properties.size() > 0) { + if (!properties.isEmpty()) { if (out.length() > 0) { out.append(", "); } else { @@ -91,7 +91,7 @@ public class Block { @Override public int hashCode() { int ret = mod.hashCode() * identifier.hashCode() * rotation.hashCode(); - if (properties.size() > 0) { + if (!properties.isEmpty()) { ret *= properties.hashCode(); } return ret; diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/world/BlockPosition.java b/src/main/java/de/bixilon/minosoft/game/datatypes/world/BlockPosition.java index 0e818ef54..271571c71 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/world/BlockPosition.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/world/BlockPosition.java @@ -13,6 +13,7 @@ package de.bixilon.minosoft.game.datatypes.world; +import de.bixilon.minosoft.render.blockModels.Face.RenderConstants; import de.bixilon.minosoft.render.utility.Vec3; public class BlockPosition { @@ -21,7 +22,6 @@ public class BlockPosition { final int z; public BlockPosition(int x, int y, int z) { - // y min -2048, max 2047 this.x = x; this.y = y; this.z = z; @@ -34,9 +34,9 @@ public class BlockPosition { } public BlockPosition(ChunkLocation chunkLocation, Byte height, ChunkNibbleLocation nibbleLocation) { - this.x = chunkLocation.getX() * 16 + nibbleLocation.getX(); - this.y = height * 16 + nibbleLocation.getY(); - this.z = chunkLocation.getZ() * 16 + nibbleLocation.getZ(); + this.x = chunkLocation.getX() * RenderConstants.SECTION_WIDTH + nibbleLocation.getX(); + this.y = height * RenderConstants.SECTION_HEIGHT + nibbleLocation.getY(); + this.z = chunkLocation.getZ() * RenderConstants.SECTION_WIDTH + nibbleLocation.getZ(); } public int getX() { @@ -61,8 +61,8 @@ public class BlockPosition { } public ChunkLocation getChunkLocation() { - int x = getX() / 16; - int z = getZ() / 16; + int x = getX() / RenderConstants.SECTION_WIDTH; + int z = getZ() / RenderConstants.SECTION_WIDTH; //ToDo if (getX() < 0) { x--; @@ -84,13 +84,13 @@ public class BlockPosition { } public InChunkLocation getInChunkLocation() { - int x = getX() % 16; + int x = getX() % RenderConstants.SECTION_WIDTH; if (x < 0) { - x = 16 + x; + x += RenderConstants.SECTION_WIDTH; } - int z = getZ() % 16; + int z = getZ() % RenderConstants.SECTION_WIDTH; if (z < 0) { - z = 16 + z; + z += RenderConstants.SECTION_WIDTH; } return new InChunkLocation(x, getY(), z); } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/world/Chunk.java b/src/main/java/de/bixilon/minosoft/game/datatypes/world/Chunk.java index cc7d5739f..ec94869e0 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/world/Chunk.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/world/Chunk.java @@ -14,7 +14,7 @@ package de.bixilon.minosoft.game.datatypes.world; import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Block; -import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Blocks; +import de.bixilon.minosoft.render.blockModels.Face.RenderConstants; import java.util.HashMap; import java.util.Map; @@ -31,14 +31,8 @@ public class Chunk { } public Block getBlock(int x, int y, int z) { - if (x > 15 || y > 255 || z > 15 || x < 0 || y < 0 || z < 0) { - throw new IllegalArgumentException(String.format("Invalid chunk location %s %s %s", x, y, z)); - } - byte section = (byte) (y / 16); - if (nibbles.get(section) == null) { - return Blocks.nullBlock; - } - return nibbles.get(section).getBlock(x, y % 16, z); + byte section = (byte) (y / RenderConstants.SECTION_HEIGHT); + return nibbles.get(section).getBlock(x, y % RenderConstants.SECTION_HEIGHT, z); } public Block getBlock(InChunkLocation location) { @@ -46,20 +40,19 @@ public class Chunk { } public void setBlock(int x, int y, int z, Block block) { - byte section = (byte) (y / 16); + byte section = (byte) (y / RenderConstants.SECTION_HEIGHT); createSectionIfNotExist(section); - nibbles.get(section).setBlock(x, y % 16, z, block); + nibbles.get(section).setBlock(x, y % RenderConstants.SECTION_HEIGHT, z, block); } public void setBlock(InChunkLocation location, Block block) { - byte section = (byte) (location.getY() / 16); + byte section = (byte) (location.getY() / RenderConstants.SECTION_HEIGHT); createSectionIfNotExist(section); nibbles.get(section).setBlock(location.getChunkNibbleLocation(), block); } void createSectionIfNotExist(byte section) { if (nibbles.get(section) == null) { - // nibble was empty before, creating it nibbles.put(section, new ChunkNibble()); } } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/world/InChunkLocation.java b/src/main/java/de/bixilon/minosoft/game/datatypes/world/InChunkLocation.java index 06c9c3bb4..8ec71d63d 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/world/InChunkLocation.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/world/InChunkLocation.java @@ -13,21 +13,14 @@ package de.bixilon.minosoft.game.datatypes.world; -/** - * Chunk X, Y and Z location (max 16x16x16) - */ +import de.bixilon.minosoft.render.blockModels.Face.RenderConstants; + public class InChunkLocation { final int x; final int y; final int z; public InChunkLocation(int x, int y, int z) { - // x 0 - 16 - // y 0 - 255 - // z 0 - 16 - if (x > 15 || y > 255 || z > 15 || x < 0 || y < 0 || z < 0) { - throw new IllegalArgumentException(String.format("Invalid chunk location %s %s %s", x, y, z)); - } this.x = x; this.y = y; this.z = z; @@ -55,7 +48,7 @@ public class InChunkLocation { } public ChunkNibbleLocation getChunkNibbleLocation() { - return new ChunkNibbleLocation(getX(), getY() % 16, getZ()); + return new ChunkNibbleLocation(getX(), getY() % RenderConstants.SECTION_HEIGHT, getZ()); } @Override diff --git a/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java b/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java index 0e12055bb..67fa5fe2f 100644 --- a/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java +++ b/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java @@ -19,6 +19,7 @@ import de.bixilon.minosoft.game.datatypes.world.*; import de.bixilon.minosoft.protocol.network.Connection; import de.bixilon.minosoft.render.blockModels.Face.Face; import de.bixilon.minosoft.render.blockModels.Face.FaceOrientation; +import de.bixilon.minosoft.render.blockModels.Face.RenderConstants; import java.util.HashMap; import java.util.HashSet; @@ -102,9 +103,9 @@ public class WorldRenderer { for (FaceOrientation orientation : FaceOrientation.values()) { Block dependedBlock = switch (orientation) { case DOWN -> { - if (location.getY() == 0) { + if (location.getY() == RenderConstants.SECTIONS_MIN_Y) { // need to check upper section (nibble) - if (sectionHeight == 0) { + if (sectionHeight == RenderConstants.SECTIONS_MIN_Y) { // y = 0, there can't be any blocks below me yield null; } @@ -113,14 +114,14 @@ public class WorldRenderer { if (!world.get(chunkLocation).getNibbles().containsKey(bottomSection)) { yield null; } - yield world.get(chunkLocation).getNibbles().get(bottomSection).getBlock(location.getX(), 15, location.getZ()); + yield world.get(chunkLocation).getNibbles().get(bottomSection).getBlock(location.getX(), RenderConstants.SECTIONS_MAX_Y, location.getZ()); } yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY() - 1, location.getZ())); } case UP -> { - if (location.getY() == 15) { + if (location.getY() == RenderConstants.SECTIONS_MAX_Y) { // need to check upper section (nibble) - if (sectionHeight == 15) { + if (sectionHeight == RenderConstants.SECTIONS_MAX_Y) { // y = 255, there can't be any blocks above me yield null; } @@ -129,42 +130,42 @@ public class WorldRenderer { if (!world.get(chunkLocation).getNibbles().containsKey(upperSection)) { yield null; } - yield world.get(chunkLocation).getNibbles().get(upperSection).getBlock(location.getX(), 0, location.getZ()); + yield world.get(chunkLocation).getNibbles().get(upperSection).getBlock(location.getX(), RenderConstants.SECTIONS_MIN_Y, location.getZ()); } yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY() + 1, location.getZ())); } case WEST -> { - if (location.getX() == 0) { + if (location.getX() == RenderConstants.SECTIONS_MIN_X) { ChunkNibble otherChunkNibble = getChunkNibbleOfWorld(world, new ChunkLocation(chunkLocation.getX() - 1, chunkLocation.getZ()), sectionHeight); if (otherChunkNibble != null) { - yield otherChunkNibble.getBlock(15, location.getY(), location.getZ()); + yield otherChunkNibble.getBlock(RenderConstants.SECTIONS_MAX_X, location.getY(), location.getZ()); } } yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX() - 1, location.getY(), location.getZ())); } case EAST -> { - if (location.getX() == 15) { + if (location.getX() == RenderConstants.SECTIONS_MIN_X) { ChunkNibble otherChunkNibble = getChunkNibbleOfWorld(world, new ChunkLocation(chunkLocation.getX() + 1, chunkLocation.getZ()), sectionHeight); if (otherChunkNibble != null) { - yield otherChunkNibble.getBlock(0, location.getY(), location.getZ()); + yield otherChunkNibble.getBlock(RenderConstants.SECTIONS_MAX_X, location.getY(), location.getZ()); } } yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX() + 1, location.getY(), location.getZ())); } case NORTH -> { - if (location.getZ() == 0) { + if (location.getZ() == RenderConstants.SECTIONS_MIN_Z) { ChunkNibble otherChunkNibble = getChunkNibbleOfWorld(world, new ChunkLocation(chunkLocation.getX(), chunkLocation.getZ() - 1), sectionHeight); if (otherChunkNibble != null) { - yield otherChunkNibble.getBlock(location.getX(), location.getY(), 15); + yield otherChunkNibble.getBlock(location.getX(), location.getY(), RenderConstants.SECTIONS_MAX_Z); } } yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY(), location.getZ() - 1)); } case SOUTH -> { - if (location.getZ() == 15) { + if (location.getZ() == RenderConstants.SECTIONS_MAX_Z) { ChunkNibble otherChunkNibble = getChunkNibbleOfWorld(world, new ChunkLocation(chunkLocation.getX(), chunkLocation.getZ() + 1), sectionHeight); if (otherChunkNibble != null) { - yield otherChunkNibble.getBlock(location.getX(), location.getY(), 0); + yield otherChunkNibble.getBlock(location.getX(), location.getY(), RenderConstants.SECTIONS_MIN_Z); } } yield nibbleBlocks.get(new ChunkNibbleLocation(location.getX(), location.getY(), location.getZ() + 1)); @@ -174,7 +175,7 @@ public class WorldRenderer { facesToDraw.add(orientation); } } - if (facesToDraw.size() > 0) { + if (!facesToDraw.isEmpty()) { nibbleMap.put(location, assetsLoader.getBlockModelLoader().prepare(block, facesToDraw)); } @@ -190,54 +191,30 @@ public class WorldRenderer { for (FaceOrientation orientation : FaceOrientation.values()) { Block dependedBlock = switch (orientation) { case DOWN -> { - if (position.getY() == 0) { + if (position.getY() == RenderConstants.CHUNK_MIN_Y) { facesToDraw.add(orientation); yield null; } yield GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX(), position.getY() - 1, position.getZ())); } case UP -> { - if (position.getY() == 255) { + if (position.getY() == RenderConstants.CHUNK_MAX_Y) { facesToDraw.add(orientation); yield null; } yield GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX(), position.getY() + 1, position.getZ())); } - case NORTH -> { - if (position.getY() == 255) { - facesToDraw.add(orientation); - yield null; - } - yield GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX(), position.getY(), position.getZ() - 1)); - } - case SOUTH -> { - if (position.getY() == 255) { - facesToDraw.add(orientation); - yield null; - } - yield GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX(), position.getY(), position.getZ() + 1)); - } - case WEST -> { - if (position.getY() == 255) { - facesToDraw.add(orientation); - yield null; - } - yield GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX() - 1, position.getY(), position.getZ())); - } - case EAST -> { - if (position.getY() == 255) { - facesToDraw.add(orientation); - yield null; - } - yield GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX() + 1, position.getY(), position.getZ())); - } + case NORTH -> GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX(), position.getY(), position.getZ() - 1)); + case SOUTH -> GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX(), position.getY(), position.getZ() + 1)); + case WEST -> GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX() - 1, position.getY(), position.getZ())); + case EAST -> GameWindow.getConnection().getPlayer().getWorld().getBlock(new BlockPosition(position.getX() + 1, position.getY(), position.getZ())); }; if (dependedBlock == null || !assetsLoader.getBlockModelLoader().isFull(dependedBlock)) { facesToDraw.add(orientation); } } } - ConcurrentHashMap> nibbleMap = faces.get(position.getChunkLocation()).get((byte) (position.getY() / 16)); + ConcurrentHashMap> nibbleMap = faces.get(position.getChunkLocation()).get((byte) (position.getY() / RenderConstants.SECTION_HEIGHT)); if (facesToDraw.size() == 0) { // remove all faces nibbleMap.remove(position.getInChunkLocation().getChunkNibbleLocation()); @@ -248,11 +225,11 @@ public class WorldRenderer { if (trustEdges) { return; } - if (position.getY() != 0) { + if (position.getY() != RenderConstants.CHUNK_MIN_Y) { // bottom prepareBlock(new BlockPosition(position.getX(), position.getY() - 1, position.getZ()), true); } - if (position.getY() != 255) { + if (position.getY() != RenderConstants.CHUNK_MAX_Y) { // bottom prepareBlock(new BlockPosition(position.getX(), position.getY() + 1, position.getZ()), true); } diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/Face/RenderConstants.java b/src/main/java/de/bixilon/minosoft/render/blockModels/Face/RenderConstants.java index 2bc5ae502..f01298a41 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/Face/RenderConstants.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/Face/RenderConstants.java @@ -14,13 +14,24 @@ package de.bixilon.minosoft.render.blockModels.Face; public class RenderConstants { - public static final int TEXTURE_PACK_RES = 16; + public static final int TEXTURE_PACK_RESOLUTION = 16; + public static final int BLOCK_RESOLUTION = 16; - public static final int texturePackRes = 16; + public static final byte SECTION_HEIGHT = 16; + public static final byte SECTION_WIDTH = 16; + public static final byte SECTIONS_PER_CHUNK = 16; - public static final int blockRes = 16; + public static final byte SECTIONS_MIN_X = 0; + public static final byte SECTIONS_MIN_Y = 0; + public static final byte SECTIONS_MIN_Z = 0; + public static final byte SECTIONS_MAX_X = SECTION_WIDTH - 1; + public static final byte SECTIONS_MAX_Y = SECTION_HEIGHT - 1; + public static final byte SECTIONS_MAX_Z = SECTION_WIDTH - 1; - public static final int[][] faceDir = new int[][]{ + public static final byte CHUNK_MIN_Y = 0; + public static final int CHUNK_MAX_Y = SECTION_HEIGHT * SECTIONS_PER_CHUNK - 1; + + public static final int[][] FACE_DIRECTIONS = new int[][]{ {1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlockPosition.java b/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlockPosition.java index 5673a9568..87da51177 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlockPosition.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlockPosition.java @@ -17,27 +17,23 @@ import com.google.gson.JsonArray; import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Block; import de.bixilon.minosoft.game.datatypes.world.BlockPosition; import de.bixilon.minosoft.render.blockModels.Face.Axis; +import de.bixilon.minosoft.render.blockModels.Face.RenderConstants; -import static de.bixilon.minosoft.render.blockModels.Face.RenderConstants.blockRes; import static org.lwjgl.opengl.GL11.glVertex3f; public class SubBlockPosition { - public float x; - public float y; - public float z; - private static final SubBlockPosition middlePos = new SubBlockPosition(8, 8, 8); - private static final SubBlockRotation westRotator = new SubBlockRotation(middlePos, Axis.Y, 90); private static final SubBlockRotation eastRotator = new SubBlockRotation(middlePos, Axis.Y, 270); private static final SubBlockRotation southRotator = new SubBlockRotation(middlePos, Axis.Y, 180); - private static final SubBlockRotation xAxisRotator = new SubBlockRotation(middlePos, Axis.Z, 90); private static final SubBlockRotation zAxisRotator = new SubBlockRotation(middlePos, Axis.X, 90); - private static final SubBlockRotation downRotator = new SubBlockRotation(middlePos, Axis.X, 90); private static final SubBlockRotation downAltRotator = new SubBlockRotation(middlePos, Axis.X, 180); private static final SubBlockRotation upRotator = new SubBlockRotation(middlePos, Axis.X, -90); + public float x; + public float y; + public float z; public SubBlockPosition(JsonArray json) { @@ -67,10 +63,9 @@ public class SubBlockPosition { } public void draw(BlockPosition pos) { - glVertex3f( - pos.getX() + x / blockRes, - pos.getY() + y / blockRes, - pos.getZ() + z / blockRes); + glVertex3f(pos.getX() + x / RenderConstants.BLOCK_RESOLUTION, + pos.getY() + y / RenderConstants.BLOCK_RESOLUTION, + pos.getZ() + z / RenderConstants.BLOCK_RESOLUTION); } public SubBlockPosition rotated(Block block) { diff --git a/src/main/java/de/bixilon/minosoft/render/texture/InFaceUV.java b/src/main/java/de/bixilon/minosoft/render/texture/InFaceUV.java index 6e65c2845..9a36bad64 100644 --- a/src/main/java/de/bixilon/minosoft/render/texture/InFaceUV.java +++ b/src/main/java/de/bixilon/minosoft/render/texture/InFaceUV.java @@ -16,7 +16,7 @@ package de.bixilon.minosoft.render.texture; import com.google.gson.JsonArray; import de.bixilon.minosoft.render.GameWindow; -import static de.bixilon.minosoft.render.blockModels.Face.RenderConstants.texturePackRes; +import static de.bixilon.minosoft.render.blockModels.Face.RenderConstants.TEXTURE_PACK_RESOLUTION; import static org.lwjgl.opengl.GL11.glTexCoord2f; public class InFaceUV { @@ -38,11 +38,11 @@ public class InFaceUV { public void prepare(float texture) { realU1 = texture + u1 * GameWindow.getRenderer().getAssetsLoader().getTextureLoader().getStep() - / texturePackRes; + / TEXTURE_PACK_RESOLUTION; realU2 = texture + u2 * GameWindow.getRenderer().getAssetsLoader().getTextureLoader().getStep() - / texturePackRes; - realV1 = (float) v1 / texturePackRes; - realV2 = (float) v2 / texturePackRes; + / TEXTURE_PACK_RESOLUTION; + realV1 = (float) v1 / TEXTURE_PACK_RESOLUTION; + realV2 = (float) v2 / TEXTURE_PACK_RESOLUTION; } public void draw(int i) { diff --git a/src/main/java/de/bixilon/minosoft/render/texture/TextureLoader.java b/src/main/java/de/bixilon/minosoft/render/texture/TextureLoader.java index 62cfd22b7..bd83f9bc6 100644 --- a/src/main/java/de/bixilon/minosoft/render/texture/TextureLoader.java +++ b/src/main/java/de/bixilon/minosoft/render/texture/TextureLoader.java @@ -27,7 +27,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; -import static de.bixilon.minosoft.render.blockModels.Face.RenderConstants.TEXTURE_PACK_RES; +import static de.bixilon.minosoft.render.blockModels.Face.RenderConstants.TEXTURE_PACK_RESOLUTION; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL30.glGenerateMipmap; @@ -36,7 +36,7 @@ public class TextureLoader { private int textureID; private float step; private int totalTextures = 0; - private HashMap> images; + private final HashMap> images; public TextureLoader(HashMap> textures, HashMap> tints) { textureCoordinates = new HashMap<>(); @@ -99,20 +99,20 @@ public class TextureLoader { // greatly improves performance in opengl // TEXTURE_PACK_RESxTEXTURE_PACK_RES textures only int imageLength = 1; - while (totalTextures * TEXTURE_PACK_RES > imageLength) { + while (totalTextures * TEXTURE_PACK_RESOLUTION > imageLength) { imageLength *= 2; //figure out the right length for the image } - BufferedImage totalImage = new BufferedImage(imageLength, TEXTURE_PACK_RES, + BufferedImage totalImage = new BufferedImage(imageLength, TEXTURE_PACK_RESOLUTION, BufferedImage.TYPE_4BYTE_ABGR); int currentPos = 0; for (Map.Entry> mod : images.entrySet()) { HashMap modMap = new HashMap<>(); for (Map.Entry texture : mod.getValue().entrySet()) { - for (int y = 0; y < TEXTURE_PACK_RES; y++) { - for (int xPixel = 0; xPixel < TEXTURE_PACK_RES; xPixel++) { + for (int y = 0; y < TEXTURE_PACK_RESOLUTION; y++) { + for (int xPixel = 0; xPixel < TEXTURE_PACK_RESOLUTION; xPixel++) { int rgb = texture.getValue().getRGB(xPixel, y); - totalImage.setRGB(currentPos * TEXTURE_PACK_RES + xPixel, y, rgb); + totalImage.setRGB(currentPos * TEXTURE_PACK_RESOLUTION + xPixel, y, rgb); } } modMap.put(texture.getKey(), currentPos++); @@ -126,7 +126,7 @@ public class TextureLoader { } catch (IOException e) { e.printStackTrace(); } - step = (float) 1 / (float) imageLength * TEXTURE_PACK_RES; + step = (float) 1 / (float) imageLength * TEXTURE_PACK_RESOLUTION; } private int bindTexture(ByteBuffer buf, int width, int height) { diff --git a/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java b/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java index 4d6874510..62d8d37ba 100644 --- a/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java +++ b/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java @@ -22,6 +22,7 @@ import de.bixilon.minosoft.game.datatypes.world.palette.Palette; import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.protocol.protocol.InByteBuffer; import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; +import de.bixilon.minosoft.render.blockModels.Face.RenderConstants; import java.util.concurrent.ConcurrentHashMap; @@ -34,7 +35,7 @@ public final class ChunkUtil { } //chunk byte sections = BitByte.getBitCount(sectionBitMask); - int totalBytes = 4096 * sections; // 16 * 16 * 16 * sections; Section Width * Section Height * Section Width * sections + int totalBytes = RenderConstants.SECTION_HEIGHT * RenderConstants.SECTION_WIDTH * RenderConstants.SECTION_WIDTH * sections; int halfBytes = totalBytes / 2; // half bytes byte[] blockTypes = buffer.readBytes(totalBytes); @@ -44,22 +45,22 @@ public final class ChunkUtil { if (containsSkyLight) { skyLight = buffer.readBytes(halfBytes); } - byte[] addBlockTypes = buffer.readBytes(Integer.bitCount(addBitMask) * 2048); // 16 * 16 * 16 * addBlocks / 2 + byte[] addBlockTypes = buffer.readBytes(Integer.bitCount(addBitMask) * RenderConstants.SECTION_HEIGHT * RenderConstants.SECTION_WIDTH * RenderConstants.SECTION_WIDTH / 2); // 16 * 16 * 16 * addBlocks / 2 if (groundUpContinuous) { - byte[] biomes = buffer.readBytes(256); + byte[] biomes = buffer.readBytes(RenderConstants.SECTION_WIDTH * RenderConstants.SECTION_WIDTH); } //parse data int arrayPos = 0; ConcurrentHashMap nibbleMap = new ConcurrentHashMap<>(); - for (byte c = 0; c < 16; c++) { // max sections per chunks in chunk column + for (byte c = 0; c < RenderConstants.SECTIONS_PER_CHUNK; c++) { // max sections per chunks in chunk column if (BitByte.isBitSet(sectionBitMask, c)) { ConcurrentHashMap blockMap = new ConcurrentHashMap<>(); - for (int nibbleY = 0; nibbleY < 16; nibbleY++) { - for (int nibbleZ = 0; nibbleZ < 16; nibbleZ++) { - for (int nibbleX = 0; nibbleX < 16; nibbleX++) { + for (int nibbleY = 0; nibbleY < RenderConstants.SECTION_HEIGHT; nibbleY++) { + for (int nibbleZ = 0; nibbleZ < RenderConstants.SECTION_WIDTH; nibbleZ++) { + for (int nibbleX = 0; nibbleX < RenderConstants.SECTION_WIDTH; nibbleX++) { short singeBlockId = (short) (blockTypes[arrayPos] & 0xFF); byte singleMeta; @@ -99,7 +100,7 @@ public final class ChunkUtil { return null; } byte sections = BitByte.getBitCount(sectionBitMask); - int totalBlocks = 4096 * sections; // 16 * 16 * 16 * sections; Section Width * Section Height * Section Width * sections + int totalBlocks = RenderConstants.SECTION_HEIGHT * RenderConstants.SECTION_WIDTH * RenderConstants.SECTION_WIDTH * sections; int halfBytes = totalBlocks / 2; // half bytes short[] blockData = buffer.readLEShorts(totalBlocks); // blocks >>> 4, data & 0xF @@ -111,20 +112,20 @@ public final class ChunkUtil { } if (groundUpContinuous) { - byte[] biomes = buffer.readBytes(256); + byte[] biomes = buffer.readBytes(RenderConstants.SECTION_WIDTH * RenderConstants.SECTION_WIDTH); } int arrayPos = 0; ConcurrentHashMap nibbleMap = new ConcurrentHashMap<>(); - for (byte c = 0; c < 16; c++) { // max sections per chunks in chunk column + for (byte c = 0; c < RenderConstants.SECTIONS_PER_CHUNK; c++) { // max sections per chunks in chunk column if (!BitByte.isBitSet(sectionBitMask, c)) { continue; } ConcurrentHashMap blockMap = new ConcurrentHashMap<>(); - for (int nibbleY = 0; nibbleY < 16; nibbleY++) { - for (int nibbleZ = 0; nibbleZ < 16; nibbleZ++) { - for (int nibbleX = 0; nibbleX < 16; nibbleX++) { + for (int nibbleY = 0; nibbleY < RenderConstants.SECTION_HEIGHT; nibbleY++) { + for (int nibbleZ = 0; nibbleZ < RenderConstants.SECTION_WIDTH; nibbleZ++) { + for (int nibbleX = 0; nibbleX < RenderConstants.SECTION_WIDTH; nibbleX++) { int blockId = blockData[arrayPos] & 0xFFFF; Block block = buffer.getConnection().getMapping().getBlockById(blockId); if (block.equals(Blocks.nullBlock)) { @@ -142,7 +143,7 @@ public final class ChunkUtil { } // really big thanks to: https://wiki.vg/index.php?title=Chunk_Format&oldid=13712 ConcurrentHashMap nibbleMap = new ConcurrentHashMap<>(); - for (byte c = 0; c < 16; c++) { // max sections per chunks in chunk column + for (byte c = 0; c < RenderConstants.SECTIONS_PER_CHUNK; c++) { // max sections per chunks in chunk column if (!BitByte.isBitSet(sectionBitMask, c)) { continue; } @@ -156,9 +157,9 @@ public final class ChunkUtil { long[] data = buffer.readLongArray(buffer.readVarInt()); ConcurrentHashMap blockMap = new ConcurrentHashMap<>(); - for (int nibbleY = 0; nibbleY < 16; nibbleY++) { - for (int nibbleZ = 0; nibbleZ < 16; nibbleZ++) { - for (int nibbleX = 0; nibbleX < 16; nibbleX++) { + for (int nibbleY = 0; nibbleY < RenderConstants.SECTION_HEIGHT; nibbleY++) { + for (int nibbleZ = 0; nibbleZ < RenderConstants.SECTION_WIDTH; nibbleZ++) { + for (int nibbleX = 0; nibbleX < RenderConstants.SECTION_WIDTH; nibbleX++) { int blockNumber = (((nibbleY * 16) + nibbleZ) * 16) + nibbleX; int startLong = (blockNumber * palette.getBitsPerBlock()) / 64; @@ -203,7 +204,7 @@ public final class ChunkUtil { nibbleMap.put(c, new ChunkNibble(blockMap)); } if (buffer.getProtocolId() < 552) { - byte[] biomes = buffer.readBytes(256); + byte[] biomes = buffer.readBytes(RenderConstants.SECTION_WIDTH * RenderConstants.SECTION_WIDTH); } return new Chunk(nibbleMap); } From 4c305adf13270b90c433999fffc96d6b81184727 Mon Sep 17 00:00:00 2001 From: Bixilon Date: Wed, 30 Sep 2020 19:26:19 +0200 Subject: [PATCH 4/5] remove many static imports and reformat code --- .../minosoft/game/datatypes/Player.java | 9 ++--- .../bixilon/minosoft/render/GameWindow.java | 7 ++-- .../bixilon/minosoft/render/OpenGLWindow.java | 17 ++++----- .../blockModels/BlockConfiguration.java | 6 +-- .../blockModels/BlockConfigurationTrue.java | 3 -- .../blockModels/BlockModelInterface.java | 33 +++++++---------- .../render/blockModels/BlockModelLoader.java | 5 +-- .../render/blockModels/Face/Axis.java | 4 +- .../blockModels/Face/RenderConstants.java | 9 ----- .../blockModels/specialModels/BlockModel.java | 6 +-- .../blockModels/specialModels/CropModel.java | 11 ++---- .../blockModels/specialModels/DoorModel.java | 20 +++------- .../blockModels/specialModels/FenceModel.java | 6 +-- .../specialModels/StairsModel.java | 15 ++++---- .../blockModels/subBlocks/SubBlock.java | 19 +++------- .../subBlocks/SubBlockPosition.java | 14 ++----- .../subBlocks/SubBlockRotation.java | 14 ++----- .../render/movement/CameraMovement.java | 8 ++-- .../render/movement/CollisionHandler.java | 13 ++----- .../render/movement/PlayerController.java | 16 ++++---- .../render/movement/PlayerMovement.java | 14 +++---- .../minosoft/render/texture/InFaceUV.java | 28 +++++--------- .../render/texture/TextureLoader.java | 23 +++++------- .../render/utility/AdditionalMath.java | 3 +- .../bixilon/minosoft/render/utility/Vec3.java | 37 +++++-------------- .../de/bixilon/minosoft/util/ChunkUtil.java | 2 +- 26 files changed, 119 insertions(+), 223 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/Player.java b/src/main/java/de/bixilon/minosoft/game/datatypes/Player.java index b3f3c5bd3..c57658949 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/Player.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/Player.java @@ -22,13 +22,12 @@ import de.bixilon.minosoft.game.datatypes.player.PlayerListItem; import de.bixilon.minosoft.game.datatypes.scoreboard.ScoreboardManager; import de.bixilon.minosoft.game.datatypes.world.BlockPosition; import de.bixilon.minosoft.game.datatypes.world.World; +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; import de.bixilon.minosoft.util.mojang.api.MojangAccount; import java.util.HashMap; import java.util.UUID; -import static de.bixilon.minosoft.protocol.protocol.ProtocolDefinition.PLAYER_INVENTORY_ID; - public class Player { final MojangAccount account; final ScoreboardManager scoreboardManager = new ScoreboardManager(); @@ -52,7 +51,7 @@ public class Player { public Player(MojangAccount account) { this.account = account; // create our own inventory without any properties - inventories.put(PLAYER_INVENTORY_ID, new Inventory(null)); + inventories.put(ProtocolDefinition.PLAYER_INVENTORY_ID, new Inventory(null)); } public String getPlayerName() { @@ -136,11 +135,11 @@ public class Player { } public Inventory getPlayerInventory() { - return getInventory(PLAYER_INVENTORY_ID); + return getInventory(ProtocolDefinition.PLAYER_INVENTORY_ID); } public void setPlayerInventory(Slot[] data) { - setInventory(PLAYER_INVENTORY_ID, data); + setInventory(ProtocolDefinition.PLAYER_INVENTORY_ID, data); } public Inventory getInventory(int id) { diff --git a/src/main/java/de/bixilon/minosoft/render/GameWindow.java b/src/main/java/de/bixilon/minosoft/render/GameWindow.java index e3eeabd6f..25d5d3261 100644 --- a/src/main/java/de/bixilon/minosoft/render/GameWindow.java +++ b/src/main/java/de/bixilon/minosoft/render/GameWindow.java @@ -25,13 +25,12 @@ public class GameWindow { private static final int WIDTH = 800; private static final int HEIGHT = 800; private static final boolean FULLSCREEN = false; + public static boolean paused = false; private static OpenGLWindow openGLWindow; private static WorldRenderer renderer; private static Connection connection; private static PlayerController playerController; - private static boolean running = false; - public static boolean paused = false; public static void prepare() { Thread guiLoaderThread = new Thread(() -> { @@ -42,7 +41,7 @@ public class GameWindow { renderer.init(); Log.info("Finished loading game Assets"); try { - while (! running) { + while (!running) { Thread.sleep(100); } openGLWindow.start(); @@ -101,7 +100,7 @@ public class GameWindow { } public static void pause() { - paused = ! paused; + paused = !paused; openGLWindow.mouseEnable(paused); } } diff --git a/src/main/java/de/bixilon/minosoft/render/OpenGLWindow.java b/src/main/java/de/bixilon/minosoft/render/OpenGLWindow.java index 027a0ad92..30fc446d0 100644 --- a/src/main/java/de/bixilon/minosoft/render/OpenGLWindow.java +++ b/src/main/java/de/bixilon/minosoft/render/OpenGLWindow.java @@ -28,6 +28,7 @@ import static org.lwjgl.system.MemoryUtil.NULL; public class OpenGLWindow { private final boolean fullscreen; + boolean escDown = false; private long window; private int width, height; private double mouseX; @@ -51,8 +52,9 @@ public class OpenGLWindow { public void init() { GLFWErrorCallback.createPrint(System.err).set(); - if (!glfwInit()) + if (!glfwInit()) { throw new IllegalStateException("Unable to initialize GLFW"); + } glfwDefaultWindowHints(); glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); @@ -66,8 +68,9 @@ public class OpenGLWindow { } window = glfwCreateWindow(width, height, "RENDER", NULL, NULL); - if (window == NULL) + if (window == NULL) { throw new RuntimeException("Failed to create the GLFW window"); + } try (MemoryStack stack = stackPush()) { IntBuffer pWidth = stack.mallocInt(1); // int* @@ -77,11 +80,7 @@ public class OpenGLWindow { GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); - glfwSetWindowPos( - window, - (vidmode.width() - pWidth.get(0)) / 2, - (vidmode.height() - pHeight.get(0)) / 2 - ); + glfwSetWindowPos(window, (vidmode.width() - pWidth.get(0)) / 2, (vidmode.height() - pHeight.get(0)) / 2); } glfwMakeContextCurrent(window); @@ -138,11 +137,9 @@ public class OpenGLWindow { return mouseY; } - boolean escDown = false; - public float loop() { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { - if (! escDown) { + if (!escDown) { GameWindow.pause(); escDown = true; } diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/BlockConfiguration.java b/src/main/java/de/bixilon/minosoft/render/blockModels/BlockConfiguration.java index 2aeb386ea..b87200eb5 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/BlockConfiguration.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/BlockConfiguration.java @@ -48,8 +48,7 @@ public class BlockConfiguration { } BlockProperties property = properties.get(json.get(propertyName).getAsString()); if (property == null) { - throw new RuntimeException(String.format("Unknown block property: %s -> %s", - propertyName, json.get(propertyName).getAsString())); + throw new RuntimeException(String.format("Unknown block property: %s -> %s", propertyName, json.get(propertyName).getAsString())); } blockProperties.add(property); } @@ -67,8 +66,7 @@ public class BlockConfiguration { } public boolean equals(BlockConfiguration blockConfiguration) { - return rotation.equals(blockConfiguration.getRotation()) && - blockProperties.equals(blockConfiguration.getBlockProperties()); + return rotation.equals(blockConfiguration.getRotation()) && blockProperties.equals(blockConfiguration.getBlockProperties()); } public boolean contains(Block block) { diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/BlockConfigurationTrue.java b/src/main/java/de/bixilon/minosoft/render/blockModels/BlockConfigurationTrue.java index 0acf8e3c3..fe8933df0 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/BlockConfigurationTrue.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/BlockConfigurationTrue.java @@ -16,9 +16,6 @@ package de.bixilon.minosoft.render.blockModels; import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Block; public class BlockConfigurationTrue extends BlockConfiguration { - public BlockConfigurationTrue() { - } - @Override public boolean contains(Block block) { return true; diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelInterface.java b/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelInterface.java index 6835482b5..786f40287 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelInterface.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelInterface.java @@ -3,11 +3,11 @@ * Copyright (C) 2020 Lukas Eisenhauer * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License along with this program. If not, see . - * + * * This software is not affiliated with Mojang AB, the original developer of Minecraft. */ @@ -24,27 +24,16 @@ import de.bixilon.minosoft.render.blockModels.Face.Face; import de.bixilon.minosoft.render.blockModels.Face.FaceOrientation; import de.bixilon.minosoft.render.blockModels.subBlocks.SubBlock; import de.bixilon.minosoft.render.texture.TextureLoader; +import de.bixilon.minosoft.util.Util; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; -import static de.bixilon.minosoft.util.Util.readJsonFromFile; public interface BlockModelInterface { - HashSet prepare(Block block, HashSet facesToDraw); - - boolean isFull(); - HashSet getAllTextures(); - void applyTextures(String mod, TextureLoader loader); - - HashBiMap rotationAdjust = HashBiMap.create(Map.of( - BlockRotations.EAST, BlockRotations.SOUTH, - BlockRotations.SOUTH, BlockRotations.WEST, - BlockRotations.WEST, BlockRotations.NORTH, - BlockRotations.NORTH, BlockRotations.EAST - )); + HashBiMap rotationAdjust = HashBiMap.create(Map.of(BlockRotations.EAST, BlockRotations.SOUTH, BlockRotations.SOUTH, BlockRotations.WEST, BlockRotations.WEST, BlockRotations.NORTH, BlockRotations.NORTH, BlockRotations.EAST)); static void applyConfigurationTextures(HashSet subBlocks, String mod, TextureLoader loader) { for (SubBlock subBlock : subBlocks) { @@ -72,11 +61,9 @@ public interface BlockModelInterface { String path = Config.homeDir + "assets/" + mod + "/models/block/" + identifier + ".json"; JsonObject json = null; try { - json = readJsonFromFile(path); + json = Util.readJsonFromFile(path); } catch (IOException e) { e.printStackTrace(); - } - if (json == null) { Log.warn("File not found: " + path); return null; } @@ -107,4 +94,12 @@ public interface BlockModelInterface { static HashSet load(String mod, String identifier) { return load(mod, identifier, new HashMap<>()); } + + HashSet prepare(Block block, HashSet facesToDraw); + + boolean isFull(); + + HashSet getAllTextures(); + + void applyTextures(String mod, TextureLoader loader); } diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelLoader.java b/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelLoader.java index adea697c8..dfbe9f3cf 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelLoader.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelLoader.java @@ -21,6 +21,7 @@ import de.bixilon.minosoft.render.blockModels.Face.Face; import de.bixilon.minosoft.render.blockModels.Face.FaceOrientation; import de.bixilon.minosoft.render.blockModels.specialModels.*; import de.bixilon.minosoft.render.texture.TextureLoader; +import de.bixilon.minosoft.util.Util; import org.apache.commons.collections.primitives.ArrayFloatList; import java.io.IOException; @@ -28,7 +29,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; -import static de.bixilon.minosoft.util.Util.readJsonAsset; public class BlockModelLoader { private final HashMap> blockDescriptionMap; @@ -40,7 +40,7 @@ public class BlockModelLoader { tints = new HashMap<>(); textures = new HashMap<>(); try { - JsonObject json = readJsonAsset("mapping/blockModels.json"); + JsonObject json = Util.readJsonAsset("mapping/blockModels.json"); String mod = "minecraft"; tints.put(mod, readTints(json)); textures.put(mod, loadModels(json.get("blocks").getAsJsonObject(), mod)); @@ -95,7 +95,6 @@ public class BlockModelLoader { HashSet result = new HashSet<>(); try { String type = ""; - if (block.has("type")) { type = block.get("type").getAsString(); } diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/Face/Axis.java b/src/main/java/de/bixilon/minosoft/render/blockModels/Face/Axis.java index 59265e311..743801507 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/Face/Axis.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/Face/Axis.java @@ -14,5 +14,7 @@ package de.bixilon.minosoft.render.blockModels.Face; public enum Axis { - X, Y, Z + X, + Y, + Z } diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/Face/RenderConstants.java b/src/main/java/de/bixilon/minosoft/render/blockModels/Face/RenderConstants.java index f01298a41..516c85604 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/Face/RenderConstants.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/Face/RenderConstants.java @@ -30,13 +30,4 @@ public class RenderConstants { public static final byte CHUNK_MIN_Y = 0; public static final int CHUNK_MAX_Y = SECTION_HEIGHT * SECTIONS_PER_CHUNK - 1; - - public static final int[][] FACE_DIRECTIONS = new int[][]{ - {1, 0, 0}, - {-1, 0, 0}, - {0, 1, 0}, - {0, -1, 0}, - {0, 0, 1}, - {0, 0, -1} - }; } diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/BlockModel.java b/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/BlockModel.java index 65da43044..11a38c0b7 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/BlockModel.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/BlockModel.java @@ -36,14 +36,12 @@ public class BlockModel implements BlockModelInterface { blockConfigurationStates = new HashMap<>(); if (block.has("blockModel")) { - blockConfigurationStates.put(new BlockConfigurationTrue(), - BlockModelInterface.load(mod, block.get("blockModel").getAsString())); + blockConfigurationStates.put(new BlockConfigurationTrue(), BlockModelInterface.load(mod, block.get("blockModel").getAsString())); } else if (block.has("states")) { for (JsonElement element : block.get("states").getAsJsonArray()) { JsonObject state = element.getAsJsonObject(); BlockConfiguration configuration = new BlockConfiguration(state.get("properties").getAsJsonObject()); - blockConfigurationStates.put(configuration, - BlockModelInterface.load(mod, state.get("blockModel").getAsString())); + blockConfigurationStates.put(configuration, BlockModelInterface.load(mod, state.get("blockModel").getAsString())); } } // TODO diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/CropModel.java b/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/CropModel.java index 5afc38e20..abe054107 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/CropModel.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/CropModel.java @@ -16,7 +16,6 @@ package de.bixilon.minosoft.render.blockModels.specialModels; import com.google.gson.JsonObject; import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Block; import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.BlockProperties; -import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.render.blockModels.BlockModelInterface; import de.bixilon.minosoft.render.blockModels.Face.Face; import de.bixilon.minosoft.render.blockModels.Face.FaceOrientation; @@ -26,7 +25,6 @@ import de.bixilon.minosoft.render.texture.TextureLoader; import java.util.HashMap; import java.util.HashSet; -import static de.bixilon.minosoft.render.blockModels.specialModels.BlockModel.prepareBlockState; public class CropModel implements BlockModelInterface { private final HashMap> modelMap; @@ -35,20 +33,17 @@ public class CropModel implements BlockModelInterface { int stages = block.get("stages").getAsInt(); modelMap = new HashMap<>(); for (int i = 0; i < stages; i++) { - modelMap.put(String.format("%s%d", "AGE_", i), - BlockModelInterface.load(mod, - String.format("%s%d", block.get("base_name").getAsString(), i))); + modelMap.put(String.format("%s%d", "AGE_", i), BlockModelInterface.load(mod, String.format("%s%d", block.get("base_name").getAsString(), i))); } } public HashSet prepare(Block block, HashSet facesToDraw) { for (BlockProperties property : block.getProperties()) { if (modelMap.containsKey(property.name())) { - return prepareBlockState(modelMap.get(property.name()), facesToDraw, block); + return BlockModel.prepareBlockState(modelMap.get(property.name()), facesToDraw, block); } } - Log.warn("failed to prepare block: " + block.toString()); - return new HashSet<>(); + throw new RuntimeException("Failed to prepare block: " + block.toString()); } public boolean isFull() { diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/DoorModel.java b/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/DoorModel.java index e35f14fa2..6d9b0e8da 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/DoorModel.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/DoorModel.java @@ -26,7 +26,6 @@ import de.bixilon.minosoft.render.texture.TextureLoader; import java.util.HashSet; -import static de.bixilon.minosoft.render.blockModels.specialModels.BlockModel.prepareBlockState; public class DoorModel implements BlockModelInterface { private final HashSet bottom; @@ -43,25 +42,18 @@ public class DoorModel implements BlockModelInterface { top_hinge = BlockModelInterface.load(mod, block.get("top_hinge").getAsString()); } - private static HashSet prepareHinge(HashSet bottom, HashSet top, Block block, - HashSet adjacentBlocks) { + private static HashSet prepareHinge(HashSet bottom, HashSet top, Block block, HashSet adjacentBlocks) { if (block.getProperties().contains(BlockProperties.OPEN)) { - return prepareHalf(bottom, top, block, adjacentBlocks, - rotationAdjust.inverse().get(block.getRotation())); - } else { - return prepareHalf(bottom, top, block, adjacentBlocks, block.getRotation()); + return prepareHalf(bottom, top, block, adjacentBlocks, rotationAdjust.inverse().get(block.getRotation())); } + return prepareHalf(bottom, top, block, adjacentBlocks, block.getRotation()); } - private static HashSet prepareHalf(HashSet bottom, HashSet top, - Block block, HashSet adjacentBlocks, - BlockRotations rotation) { + private static HashSet prepareHalf(HashSet bottom, HashSet top, Block block, HashSet adjacentBlocks, BlockRotations rotation) { if (block.getProperties().contains(BlockProperties.HALF_LOWER)) { - return prepareBlockState(bottom, adjacentBlocks, new Block("", "", - rotation)); + return BlockModel.prepareBlockState(bottom, adjacentBlocks, new Block("", "", rotation)); } else if (block.getProperties().contains(BlockProperties.HALF_UPPER)) { - return prepareBlockState(top, adjacentBlocks, new Block("", "", - rotation)); + return BlockModel.prepareBlockState(top, adjacentBlocks, new Block("", "", rotation)); } Log.warn("now"); return null; diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/FenceModel.java b/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/FenceModel.java index f40cfed23..b91b7cc82 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/FenceModel.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/FenceModel.java @@ -3,11 +3,11 @@ * Copyright (C) 2020 Lukas Eisenhauer * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License along with this program. If not, see . - * + * * This software is not affiliated with Mojang AB, the original developer of Minecraft. */ diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/StairsModel.java b/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/StairsModel.java index fb9bdba53..0e512a2ee 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/StairsModel.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/specialModels/StairsModel.java @@ -36,6 +36,13 @@ public class StairsModel implements BlockModelInterface { outer = BlockModelInterface.load(mod, block.get("outer").getAsString()); } + public static HashSet prepareCorner(HashSet subBlocks, BlockProperties property, BlockRotations rotation) { + if (property.name().contains("LEFT")) { + return BlockModelInterface.prepareState(subBlocks, rotation); + } + return BlockModelInterface.prepareState(subBlocks, rotationAdjust.get(rotation)); + } + @Override public HashSet prepare(Block block, HashSet facesToDraw) { HashSet properties = block.getProperties(); @@ -50,14 +57,6 @@ public class StairsModel implements BlockModelInterface { return BlockModelInterface.prepareState(straight, rotationAdjust.get(block.getRotation())); } - public static HashSet prepareCorner(HashSet subBlocks, BlockProperties property, - BlockRotations rotation) { - if (property.name().contains("LEFT")) { - return BlockModelInterface.prepareState(subBlocks, rotation); - } - return BlockModelInterface.prepareState(subBlocks, rotationAdjust.get(rotation)); - } - @Override public boolean isFull() { return false; diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlock.java b/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlock.java index a59a6b7d7..fb868d394 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlock.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlock.java @@ -25,22 +25,16 @@ import java.util.HashSet; import java.util.Map; public class SubBlock { - private final HashMap textureCoordinates; - private final HashMap textures; - private final HashMap textureRotations; - private final HashSet cullFaceTextures; - private final HashMap uv; + private final HashMap textureCoordinates = new HashMap<>(); + private final HashMap textures = new HashMap<>(); + private final HashMap textureRotations = new HashMap<>(); + private final HashSet cullFaceTextures = new HashSet<>(); + private final HashMap uv = new HashMap<>(); private final Cuboid cuboid; private final boolean isFull; private SubBlockRotation rotation; public SubBlock(JsonObject json, HashMap variables) { - uv = new HashMap<>(); - textures = new HashMap<>(); - textureRotations = new HashMap<>(); - textureCoordinates = new HashMap<>(); - cullFaceTextures = new HashSet<>(); - SubBlockPosition from = new SubBlockPosition(json.getAsJsonArray("from")); SubBlockPosition to = new SubBlockPosition(json.getAsJsonArray("to")); if (json.has("rotation")) { @@ -142,8 +136,7 @@ public class SubBlock { if (textureCoordinates.get(orientation) == null) { continue; } - result.add(new Face(textureCoordinates.get(orientation), uv.get(orientation), - cuboid.getFacePositions(orientation, block))); + result.add(new Face(textureCoordinates.get(orientation), uv.get(orientation), cuboid.getFacePositions(orientation, block))); } return result; } diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlockPosition.java b/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlockPosition.java index 87da51177..482a8a185 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlockPosition.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlockPosition.java @@ -49,23 +49,15 @@ public class SubBlockPosition { } public static SubBlockPosition add(SubBlockPosition pos1, SubBlockPosition pos2) { - return new SubBlockPosition( - pos1.x + pos2.x, - pos1.y + pos2.y, - pos1.z + pos2.z); + return new SubBlockPosition(pos1.x + pos2.x, pos1.y + pos2.y, pos1.z + pos2.z); } public static SubBlockPosition subtract(SubBlockPosition pos1, SubBlockPosition pos2) { - return new SubBlockPosition( - pos1.x - pos2.x, - pos1.y - pos2.y, - pos1.z - pos2.z); + return new SubBlockPosition(pos1.x - pos2.x, pos1.y - pos2.y, pos1.z - pos2.z); } public void draw(BlockPosition pos) { - glVertex3f(pos.getX() + x / RenderConstants.BLOCK_RESOLUTION, - pos.getY() + y / RenderConstants.BLOCK_RESOLUTION, - pos.getZ() + z / RenderConstants.BLOCK_RESOLUTION); + glVertex3f(pos.getX() + x / RenderConstants.BLOCK_RESOLUTION, pos.getY() + y / RenderConstants.BLOCK_RESOLUTION, pos.getZ() + z / RenderConstants.BLOCK_RESOLUTION); } public SubBlockPosition rotated(Block block) { diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlockRotation.java b/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlockRotation.java index 1e889fcb3..73f3507cb 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlockRotation.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlockRotation.java @@ -17,13 +17,11 @@ import com.google.gson.JsonObject; import de.bixilon.minosoft.render.blockModels.Face.Axis; import javafx.util.Pair; -import static java.lang.StrictMath.cos; -import static java.lang.StrictMath.sin; public class SubBlockRotation { private final SubBlockPosition origin; - private Axis direction; private final float angle; + private Axis direction; public SubBlockRotation(SubBlockPosition origin, Axis direction, float angle) { this.origin = origin; @@ -44,13 +42,9 @@ public class SubBlockRotation { public static Pair rotate(float x, float y, float angle) { float angleRad = (float) Math.toRadians(angle); - float newX = x * (float) cos(angleRad) + y * (float) sin(angleRad); - float newY = -x * (float) sin(angleRad) + y * (float) cos(angleRad); - - return new Pair<>( - newX, - newY - ); + float newX = x * (float) StrictMath.cos(angleRad) + y * (float) StrictMath.sin(angleRad); + float newY = -x * (float) StrictMath.sin(angleRad) + y * (float) StrictMath.cos(angleRad); + return new Pair<>(newX, newY); } public SubBlockPosition apply(SubBlockPosition position) { diff --git a/src/main/java/de/bixilon/minosoft/render/movement/CameraMovement.java b/src/main/java/de/bixilon/minosoft/render/movement/CameraMovement.java index d9fd6ebf9..cdb152acf 100644 --- a/src/main/java/de/bixilon/minosoft/render/movement/CameraMovement.java +++ b/src/main/java/de/bixilon/minosoft/render/movement/CameraMovement.java @@ -16,8 +16,6 @@ package de.bixilon.minosoft.render.movement; import de.bixilon.minosoft.render.GameWindow; import de.bixilon.minosoft.render.utility.Vec3; -import static de.bixilon.minosoft.render.utility.Vec3.normalize; -import static java.lang.StrictMath.*; import static org.lwjgl.opengl.GL11.glRotatef; public class CameraMovement { @@ -61,10 +59,10 @@ public class CameraMovement { } Vec3 front = new Vec3(); - front.x = (float) -(sin(toRadians(yaw)) * cos(toRadians(pitch))); + front.x = (float) -(StrictMath.sin(StrictMath.toRadians(yaw)) * StrictMath.cos(StrictMath.toRadians(pitch))); front.y = 0; - front.z = (float) ((cos(toRadians(yaw))) * cos(toRadians(pitch))); - cameraFront = normalize(front); + front.z = (float) ((StrictMath.cos(StrictMath.toRadians(yaw))) * StrictMath.cos(StrictMath.toRadians(pitch))); + cameraFront = Vec3.normalize(front); } public void loop() { diff --git a/src/main/java/de/bixilon/minosoft/render/movement/CollisionHandler.java b/src/main/java/de/bixilon/minosoft/render/movement/CollisionHandler.java index ff189e523..cfcacc675 100644 --- a/src/main/java/de/bixilon/minosoft/render/movement/CollisionHandler.java +++ b/src/main/java/de/bixilon/minosoft/render/movement/CollisionHandler.java @@ -17,11 +17,9 @@ import de.bixilon.minosoft.game.datatypes.world.BlockPosition; import de.bixilon.minosoft.game.datatypes.world.World; import de.bixilon.minosoft.render.GameWindow; import de.bixilon.minosoft.render.blockModels.BlockModelLoader; +import de.bixilon.minosoft.render.utility.AdditionalMath; import de.bixilon.minosoft.render.utility.Vec3; -import static de.bixilon.minosoft.render.utility.AdditionalMath.betterRound; -import static de.bixilon.minosoft.render.utility.AdditionalMath.valuesBetween; - public class CollisionHandler { private final World world; private final PlayerController controller; @@ -93,14 +91,11 @@ public class CollisionHandler { private boolean isPositionValid(Vec3 testPos) { float width = controller.getPlayerWidth(); - int[] xPositions = valuesBetween(betterRound(testPos.x + width), - betterRound(testPos.x - width)); + int[] xPositions = AdditionalMath.valuesBetween(AdditionalMath.betterRound(testPos.x + width), AdditionalMath.betterRound(testPos.x - width)); - int[] yPositions = valuesBetween(betterRound(testPos.y), - betterRound(testPos.y + controller.getPlayerHeight())); + int[] yPositions = AdditionalMath.valuesBetween(AdditionalMath.betterRound(testPos.y), AdditionalMath.betterRound(testPos.y + controller.getPlayerHeight())); - int[] zPositions = valuesBetween(betterRound(testPos.z + width), - betterRound(testPos.z - width)); + int[] zPositions = AdditionalMath.valuesBetween(AdditionalMath.betterRound(testPos.z + width), AdditionalMath.betterRound(testPos.z - width)); for (int xPos : xPositions) { for (int yPos : yPositions) { diff --git a/src/main/java/de/bixilon/minosoft/render/movement/PlayerController.java b/src/main/java/de/bixilon/minosoft/render/movement/PlayerController.java index c84f2cfc6..0d0bb1023 100644 --- a/src/main/java/de/bixilon/minosoft/render/movement/PlayerController.java +++ b/src/main/java/de/bixilon/minosoft/render/movement/PlayerController.java @@ -18,14 +18,13 @@ import de.bixilon.minosoft.game.datatypes.world.World; import de.bixilon.minosoft.render.GameWindow; import de.bixilon.minosoft.render.utility.Vec3; -import static de.bixilon.minosoft.render.utility.Vec3.mul; import static org.lwjgl.opengl.GL11.glTranslatef; public class PlayerController { private static final float playerHeight = 1.8f; private static final float playerWidth = 0.25f; private static final float gravity = 13; - + public Vec3 oldPos; CameraMovement cameraMovement; PlayerMovement playerMovement; Vec3 playerPos = new Vec3(); // the feet position of the player @@ -33,7 +32,6 @@ public class PlayerController { private boolean onGround; private boolean enableGravity; private CollisionHandler collisionHandler; - public Vec3 oldPos; public PlayerController(long window) { cameraMovement = new CameraMovement(); @@ -78,7 +76,7 @@ public class PlayerController { collisionHandler.handleCollisions(); } - public boolean isEnableGravity() { + public boolean isGravityEnabled() { return enableGravity; } @@ -91,7 +89,7 @@ public class PlayerController { } private void applyVelocity(float deltaTime) { - playerPos.add(mul(playerVelocity, deltaTime)); + playerPos.add(Vec3.mul(playerVelocity, deltaTime)); } private void handleGravity(float deltaTime) { @@ -110,6 +108,10 @@ public class PlayerController { return onGround; } + public void setOnGround(boolean onGround) { + this.onGround = onGround; + } + public void jump() { playerVelocity.y = 10; onGround = false; @@ -122,8 +124,4 @@ public class PlayerController { public float getPlayerHeight() { return playerHeight; } - - public void setOnGround(boolean onGround) { - this.onGround = onGround; - } } diff --git a/src/main/java/de/bixilon/minosoft/render/movement/PlayerMovement.java b/src/main/java/de/bixilon/minosoft/render/movement/PlayerMovement.java index b5b4a80bf..fd21bd787 100644 --- a/src/main/java/de/bixilon/minosoft/render/movement/PlayerMovement.java +++ b/src/main/java/de/bixilon/minosoft/render/movement/PlayerMovement.java @@ -16,8 +16,6 @@ package de.bixilon.minosoft.render.movement; import de.bixilon.minosoft.render.GameWindow; import de.bixilon.minosoft.render.utility.Vec3; -import static de.bixilon.minosoft.render.utility.Vec3.cross; -import static de.bixilon.minosoft.render.utility.Vec3.mul; import static org.lwjgl.glfw.GLFW.*; public class PlayerMovement { @@ -36,25 +34,25 @@ public class PlayerMovement { float cameraSpeed = FLY_SPEED / deltaTime; if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { - playerPos.add(mul(cameraFront, -cameraSpeed * deltaTime)); + playerPos.add(Vec3.mul(cameraFront, -cameraSpeed * deltaTime)); } if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { - playerPos.add(mul(cameraFront, cameraSpeed * deltaTime)); + playerPos.add(Vec3.mul(cameraFront, cameraSpeed * deltaTime)); } if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { - playerPos.add(mul(cross(CAMERA_UP, cameraFront), -cameraSpeed * deltaTime)); + playerPos.add(Vec3.mul(Vec3.cross(CAMERA_UP, cameraFront), -cameraSpeed * deltaTime)); } if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { - playerPos.add(mul(cross(CAMERA_UP, cameraFront), cameraSpeed * deltaTime)); + playerPos.add(Vec3.mul(Vec3.cross(CAMERA_UP, cameraFront), cameraSpeed * deltaTime)); } if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) { - if (!GameWindow.getPlayerController().isEnableGravity()) { + if (!GameWindow.getPlayerController().isGravityEnabled()) { playerPos.add(0, -cameraSpeed * deltaTime, 0); } } if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) { - if (!GameWindow.getPlayerController().isEnableGravity()) { + if (!GameWindow.getPlayerController().isGravityEnabled()) { playerPos.add(0, cameraSpeed * deltaTime, 0); } if (GameWindow.getPlayerController().isOnGround()) { diff --git a/src/main/java/de/bixilon/minosoft/render/texture/InFaceUV.java b/src/main/java/de/bixilon/minosoft/render/texture/InFaceUV.java index 9a36bad64..e560b8bea 100644 --- a/src/main/java/de/bixilon/minosoft/render/texture/InFaceUV.java +++ b/src/main/java/de/bixilon/minosoft/render/texture/InFaceUV.java @@ -15,8 +15,8 @@ package de.bixilon.minosoft.render.texture; import com.google.gson.JsonArray; import de.bixilon.minosoft.render.GameWindow; +import de.bixilon.minosoft.render.blockModels.Face.RenderConstants; -import static de.bixilon.minosoft.render.blockModels.Face.RenderConstants.TEXTURE_PACK_RESOLUTION; import static org.lwjgl.opengl.GL11.glTexCoord2f; public class InFaceUV { @@ -37,12 +37,10 @@ public class InFaceUV { } public void prepare(float texture) { - realU1 = texture + u1 * GameWindow.getRenderer().getAssetsLoader().getTextureLoader().getStep() - / TEXTURE_PACK_RESOLUTION; - realU2 = texture + u2 * GameWindow.getRenderer().getAssetsLoader().getTextureLoader().getStep() - / TEXTURE_PACK_RESOLUTION; - realV1 = (float) v1 / TEXTURE_PACK_RESOLUTION; - realV2 = (float) v2 / TEXTURE_PACK_RESOLUTION; + realU1 = texture + u1 * GameWindow.getRenderer().getAssetsLoader().getTextureLoader().getStep() / RenderConstants.TEXTURE_PACK_RESOLUTION; + realU2 = texture + u2 * GameWindow.getRenderer().getAssetsLoader().getTextureLoader().getStep() / RenderConstants.TEXTURE_PACK_RESOLUTION; + realV1 = (float) v1 / RenderConstants.TEXTURE_PACK_RESOLUTION; + realV2 = (float) v2 / RenderConstants.TEXTURE_PACK_RESOLUTION; } public void draw(int i) { @@ -50,18 +48,10 @@ public class InFaceUV { i -= 4; } switch (i) { - case 0: - glTexCoord2f(realU1, realV1); - break; - case 1: - glTexCoord2f(realU2, realV1); - break; - case 2: - glTexCoord2f(realU2, realV2); - break; - case 3: - glTexCoord2f(realU1, realV2); - break; + case 0 -> glTexCoord2f(realU1, realV1); + case 1 -> glTexCoord2f(realU2, realV1); + case 2 -> glTexCoord2f(realU2, realV2); + case 3 -> glTexCoord2f(realU1, realV2); } } } diff --git a/src/main/java/de/bixilon/minosoft/render/texture/TextureLoader.java b/src/main/java/de/bixilon/minosoft/render/texture/TextureLoader.java index bd83f9bc6..55a9b26e1 100644 --- a/src/main/java/de/bixilon/minosoft/render/texture/TextureLoader.java +++ b/src/main/java/de/bixilon/minosoft/render/texture/TextureLoader.java @@ -14,6 +14,7 @@ package de.bixilon.minosoft.render.texture; import de.bixilon.minosoft.Config; +import de.bixilon.minosoft.render.blockModels.Face.RenderConstants; import de.matthiasmann.twl.utils.PNGDecoder; import javax.imageio.ImageIO; @@ -27,16 +28,15 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; -import static de.bixilon.minosoft.render.blockModels.Face.RenderConstants.TEXTURE_PACK_RESOLUTION; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL30.glGenerateMipmap; public class TextureLoader { private final HashMap> textureCoordinates; + private final HashMap> images; private int textureID; private float step; private int totalTextures = 0; - private final HashMap> images; public TextureLoader(HashMap> textures, HashMap> tints) { textureCoordinates = new HashMap<>(); @@ -46,8 +46,7 @@ public class TextureLoader { } combineTextures(); try { - PNGDecoder decoder = new PNGDecoder(new FileInputStream( - Config.homeDir + "assets/allTextures.png")); + PNGDecoder decoder = new PNGDecoder(new FileInputStream(Config.homeDir + "assets/allTextures.png")); ByteBuffer buf = ByteBuffer.allocateDirect(decoder.getWidth() * decoder.getHeight() * 4); decoder.decode(buf, decoder.getWidth() * 4, PNGDecoder.Format.RGBA); textureID = bindTexture(buf, decoder.getWidth(), decoder.getHeight()); @@ -99,20 +98,19 @@ public class TextureLoader { // greatly improves performance in opengl // TEXTURE_PACK_RESxTEXTURE_PACK_RES textures only int imageLength = 1; - while (totalTextures * TEXTURE_PACK_RESOLUTION > imageLength) { + while (totalTextures * RenderConstants.TEXTURE_PACK_RESOLUTION > imageLength) { imageLength *= 2; //figure out the right length for the image } - BufferedImage totalImage = new BufferedImage(imageLength, TEXTURE_PACK_RESOLUTION, - BufferedImage.TYPE_4BYTE_ABGR); + BufferedImage totalImage = new BufferedImage(imageLength, RenderConstants.TEXTURE_PACK_RESOLUTION, BufferedImage.TYPE_4BYTE_ABGR); int currentPos = 0; for (Map.Entry> mod : images.entrySet()) { HashMap modMap = new HashMap<>(); for (Map.Entry texture : mod.getValue().entrySet()) { - for (int y = 0; y < TEXTURE_PACK_RESOLUTION; y++) { - for (int xPixel = 0; xPixel < TEXTURE_PACK_RESOLUTION; xPixel++) { + for (int y = 0; y < RenderConstants.TEXTURE_PACK_RESOLUTION; y++) { + for (int xPixel = 0; xPixel < RenderConstants.TEXTURE_PACK_RESOLUTION; xPixel++) { int rgb = texture.getValue().getRGB(xPixel, y); - totalImage.setRGB(currentPos * TEXTURE_PACK_RESOLUTION + xPixel, y, rgb); + totalImage.setRGB(currentPos * RenderConstants.TEXTURE_PACK_RESOLUTION + xPixel, y, rgb); } } modMap.put(texture.getKey(), currentPos++); @@ -126,7 +124,7 @@ public class TextureLoader { } catch (IOException e) { e.printStackTrace(); } - step = (float) 1 / (float) imageLength * TEXTURE_PACK_RESOLUTION; + step = (float) 1 / (float) imageLength * RenderConstants.TEXTURE_PACK_RESOLUTION; } private int bindTexture(ByteBuffer buf, int width, int height) { @@ -134,8 +132,7 @@ public class TextureLoader { int textureID = glGenTextures(); glBindTexture(GL_TEXTURE_2D, textureID); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, - height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); glGenerateMipmap(GL_TEXTURE_2D); //disable smoothing out of textures glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); diff --git a/src/main/java/de/bixilon/minosoft/render/utility/AdditionalMath.java b/src/main/java/de/bixilon/minosoft/render/utility/AdditionalMath.java index 20d6f5b06..221b6696a 100644 --- a/src/main/java/de/bixilon/minosoft/render/utility/AdditionalMath.java +++ b/src/main/java/de/bixilon/minosoft/render/utility/AdditionalMath.java @@ -13,11 +13,10 @@ package de.bixilon.minosoft.render.utility; -import static java.lang.Math.abs; public class AdditionalMath { public static int[] valuesBetween(int x, int y) { - int[] result = new int[abs(x - y) + 1]; + int[] result = new int[Math.abs(x - y) + 1]; if (x > y) { for (int z = y; z <= x; z++) { result[x - z] = z; diff --git a/src/main/java/de/bixilon/minosoft/render/utility/Vec3.java b/src/main/java/de/bixilon/minosoft/render/utility/Vec3.java index 1c1fbc9e1..b8ed06b76 100644 --- a/src/main/java/de/bixilon/minosoft/render/utility/Vec3.java +++ b/src/main/java/de/bixilon/minosoft/render/utility/Vec3.java @@ -15,8 +15,6 @@ package de.bixilon.minosoft.render.utility; import de.bixilon.minosoft.game.datatypes.entities.Location; -import static java.lang.Math.pow; -import static java.lang.Math.sqrt; public class Vec3 { public float x, y, z; @@ -38,44 +36,27 @@ public class Vec3 { } public static Vec3 add(Vec3 v1, Vec3 v2) { - return new Vec3( - v1.x + v2.x, - v1.y + v2.y, - v1.z + v2.z - ); + return new Vec3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); } public static Vec3 mul(Vec3 v, float n) { - return new Vec3( - v.x * n, - v.y * n, - v.z * n - ); + return new Vec3(v.x * n, v.y * n, v.z * n); } public static Vec3 mul(Vec3 v1, Vec3 v2) { - return new Vec3( - v1.x * v2.x, - v1.y * v2.y, - v1.z * v2.z - ); + return new Vec3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z); } public static Vec3 normalize(Vec3 v) { float l = v.len(); - Vec3 out = v; - out.x /= l; - out.y /= l; - out.z /= l; - return out; + v.x /= l; + v.y /= l; + v.z /= l; + return v; } public static Vec3 cross(Vec3 v1, Vec3 v2) { - return new Vec3( - v1.y * v2.z - v1.z * v2.y, - v1.z * v2.x - v1.x * v2.z, - v1.x * v2.y - v1.y * v2.x - ); + return new Vec3(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); } public void add(Vec3 v) { @@ -92,7 +73,7 @@ public class Vec3 { } public float len() { - return (float) sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2)); + return (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2)); } public void normalize() { diff --git a/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java b/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java index 62d8d37ba..5079ba473 100644 --- a/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java +++ b/src/main/java/de/bixilon/minosoft/util/ChunkUtil.java @@ -45,7 +45,7 @@ public final class ChunkUtil { if (containsSkyLight) { skyLight = buffer.readBytes(halfBytes); } - byte[] addBlockTypes = buffer.readBytes(Integer.bitCount(addBitMask) * RenderConstants.SECTION_HEIGHT * RenderConstants.SECTION_WIDTH * RenderConstants.SECTION_WIDTH / 2); // 16 * 16 * 16 * addBlocks / 2 + byte[] addBlockTypes = buffer.readBytes(Integer.bitCount(addBitMask) * RenderConstants.SECTION_HEIGHT * RenderConstants.SECTION_WIDTH * RenderConstants.SECTION_WIDTH / 2); if (groundUpContinuous) { byte[] biomes = buffer.readBytes(RenderConstants.SECTION_WIDTH * RenderConstants.SECTION_WIDTH); } From 4dc509efd8107391189be975ebb1b0462fe3459c Mon Sep 17 00:00:00 2001 From: Bixilon Date: Wed, 30 Sep 2020 20:56:05 +0200 Subject: [PATCH 5/5] config: fix config creation bug --- .../java/de/bixilon/minosoft/Minosoft.java | 4 +- .../minosoft/config/Configuration.java | 71 +++++++++++-------- .../de/bixilon/minosoft/gui/main/Server.java | 5 +- .../minosoft/gui/main/SettingsWindow.java | 3 +- .../util/mojang/api/MojangAccount.java | 5 +- 5 files changed, 49 insertions(+), 39 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/Minosoft.java b/src/main/java/de/bixilon/minosoft/Minosoft.java index 36586ba46..74ab5c2c4 100644 --- a/src/main/java/de/bixilon/minosoft/Minosoft.java +++ b/src/main/java/de/bixilon/minosoft/Minosoft.java @@ -105,7 +105,7 @@ public class Minosoft { public static void checkClientToken() { if (config.getString(GameConfiguration.CLIENT_TOKEN) == null || config.getString(GameConfiguration.CLIENT_TOKEN).equals("randomGenerated")) { config.putString(GameConfiguration.CLIENT_TOKEN, UUID.randomUUID().toString()); - config.saveToFile(Config.configFileName); + config.saveToFile(); } } @@ -125,7 +125,7 @@ public class Minosoft { if (account == null) { selectedAccount = null; config.putString(GameConfiguration.ACCOUNT_SELECTED, null); - config.saveToFile(Config.configFileName); + config.saveToFile(); return; } MojangAccount.RefreshStates refreshState = account.refreshToken(); diff --git a/src/main/java/de/bixilon/minosoft/config/Configuration.java b/src/main/java/de/bixilon/minosoft/config/Configuration.java index b2cfaef7d..dd1213631 100644 --- a/src/main/java/de/bixilon/minosoft/config/Configuration.java +++ b/src/main/java/de/bixilon/minosoft/config/Configuration.java @@ -30,6 +30,7 @@ import java.util.UUID; public class Configuration { final LinkedHashMap config; + final Thread thread; public Configuration(String filename) throws IOException { File file = new File(Config.homeDir + "config/" + filename); @@ -50,6 +51,45 @@ public class Configuration { FileInputStream inputStream = new FileInputStream(file); config = yml.load(inputStream); inputStream.close(); + + final File finalFile = file; + thread = new Thread(() -> { + while (true) { + // wait for interrupt + try { + Thread.sleep(Integer.MAX_VALUE); + } catch (InterruptedException ignored) { + } + // write config to temp file, delete original config, rename temp file to original file to avoid conflicts if minosoft gets closed while saving the config + File tempFile = new File(Config.homeDir + "config/" + filename + ".tmp"); + Yaml yaml = new Yaml(); + FileWriter writer; + try { + writer = new FileWriter(tempFile); + } catch (IOException e) { + e.printStackTrace(); + return; + } + synchronized (config) { + yaml.dump(config, writer); + } + try { + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + if (finalFile.exists()) { + finalFile.delete(); + } + if (!tempFile.renameTo(finalFile)) { + Log.fatal("An error occurred while saving the config file"); + } else { + Log.verbose(String.format("Configuration saved to file %s", filename)); + } + } + }); + thread.setName("IO-Thread"); + thread.start(); } public boolean getBoolean(String path) { @@ -173,35 +213,8 @@ public class Configuration { config.remove(path); } - public void saveToFile(String filename) { - Thread thread = new Thread(() -> { - // write config to temp file, delete original config, rename temp file to original file to avoid conflicts if minosoft gets closed while saving the config - File tempFile = new File(Config.homeDir + "config/" + filename + ".tmp"); - File file = new File(Config.homeDir + "config/" + filename); - Yaml yaml = new Yaml(); - FileWriter writer; - try { - writer = new FileWriter(tempFile); - } catch (IOException e) { - e.printStackTrace(); - return; - } - synchronized (config) { - yaml.dump(config, writer); - } - try { - writer.close(); - } catch (IOException e) { - e.printStackTrace(); - } - if (!file.delete() || !tempFile.renameTo(file)) { - Log.fatal("An error occurred while saving the config file"); - } else { - Log.verbose(String.format("Configuration saved to file %s", filename)); - } - }); - thread.setName("IO-Thread"); - thread.start(); + public void saveToFile() { + thread.interrupt(); } public HashBiMap getMojangAccounts() { diff --git a/src/main/java/de/bixilon/minosoft/gui/main/Server.java b/src/main/java/de/bixilon/minosoft/gui/main/Server.java index 0cc1f91cf..abdb12646 100644 --- a/src/main/java/de/bixilon/minosoft/gui/main/Server.java +++ b/src/main/java/de/bixilon/minosoft/gui/main/Server.java @@ -13,7 +13,6 @@ package de.bixilon.minosoft.gui.main; -import de.bixilon.minosoft.Config; import de.bixilon.minosoft.Minosoft; import de.bixilon.minosoft.protocol.network.Connection; import de.bixilon.minosoft.protocol.protocol.ConnectionReasons; @@ -95,12 +94,12 @@ public class Server { public void saveToConfig() { Minosoft.getConfig().putServer(this); - Minosoft.getConfig().saveToFile(Config.configFileName); + Minosoft.getConfig().saveToFile(); } public void delete() { Minosoft.getConfig().removeServer(this); - Minosoft.getConfig().saveToFile(Config.configFileName); + Minosoft.getConfig().saveToFile(); } public Connection getLastPing() { diff --git a/src/main/java/de/bixilon/minosoft/gui/main/SettingsWindow.java b/src/main/java/de/bixilon/minosoft/gui/main/SettingsWindow.java index bd382f45f..65a29ca27 100644 --- a/src/main/java/de/bixilon/minosoft/gui/main/SettingsWindow.java +++ b/src/main/java/de/bixilon/minosoft/gui/main/SettingsWindow.java @@ -13,7 +13,6 @@ package de.bixilon.minosoft.gui.main; -import de.bixilon.minosoft.Config; import de.bixilon.minosoft.Minosoft; import de.bixilon.minosoft.config.GameConfiguration; import de.bixilon.minosoft.logging.Log; @@ -43,7 +42,7 @@ public class SettingsWindow implements Initializable { } Log.setLevel(newLevel); Minosoft.getConfig().putString(GameConfiguration.GENERAL_LOG_LEVEL, newLevel.name()); - Minosoft.getConfig().saveToFile(Config.configFileName); + Minosoft.getConfig().saveToFile(); })); } } diff --git a/src/main/java/de/bixilon/minosoft/util/mojang/api/MojangAccount.java b/src/main/java/de/bixilon/minosoft/util/mojang/api/MojangAccount.java index def15d439..697b6d059 100644 --- a/src/main/java/de/bixilon/minosoft/util/mojang/api/MojangAccount.java +++ b/src/main/java/de/bixilon/minosoft/util/mojang/api/MojangAccount.java @@ -14,7 +14,6 @@ package de.bixilon.minosoft.util.mojang.api; import com.google.gson.JsonObject; -import de.bixilon.minosoft.Config; import de.bixilon.minosoft.Minosoft; import de.bixilon.minosoft.util.Util; @@ -92,7 +91,7 @@ public class MojangAccount { public void saveToConfig() { Minosoft.getConfig().putMojangAccount(this); - Minosoft.getConfig().saveToFile(Config.configFileName); + Minosoft.getConfig().saveToFile(); } @Override @@ -103,7 +102,7 @@ public class MojangAccount { public void delete() { Minosoft.getAccountList().remove(this.getUserId()); Minosoft.getConfig().removeAccount(this); - Minosoft.getConfig().saveToFile(Config.configFileName); + Minosoft.getConfig().saveToFile(); } @Override