From 4ab7cb738e955b375eb92518146c3d90fc1f462c Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Tue, 3 Aug 2021 17:53:49 -0400 Subject: [PATCH 01/49] Testing some stuff -Made functions to convert integers into natural numbers (cause why not) -Ideas/plans of dynamic/custom region file sizes --- .../progressia/test/TestWorldDiskIO.java | 47 ++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java index 97a0d99..1b93323 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java @@ -26,6 +26,10 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; @@ -42,10 +46,49 @@ import ru.windcorp.progressia.server.Server; public class TestWorldDiskIO { - private static final Path SAVE_DIR = Paths.get("tmp_world"); + private static Path SAVE_DIR = Paths.get("tmp_world"); private static final Logger LOG = LogManager.getLogger("TestWorldDiskIO"); - private static final boolean ENABLE = false; + private static final boolean ENABLE = true; + + private static final int maxSize = 1048576; + private static final int sectorSize = maxSize/256; + + private Map regions = new HashMap(); + + private int natFromInt(int loc) + { + if (loc<0) + return (-loc)<<1 + 1; + return loc<<1; + } + + private int intFromNat(int loc) // Possibly unused + { + if ((loc&1) == 1) + return -loc>>1; + return loc>>1; + } + + private Vec3i getRegionLoc(Vec3i chunkLoc) + { + return new Vec3i(natFromInt(chunkLoc.x),natFromInt(chunkLoc.y),natFromInt(chunkLoc.z)); + } + + public void initRegions() + { + initRegions(null); + } + + public void initRegions(Path worldPath) + { + if (worldPath!=null) + { + SAVE_DIR = worldPath; + } + + regions.put(new Vec3i(0,0,0), new Vec3i(1,1,1)); + } public static void saveChunk(ChunkData chunk, Server server) { if (!ENABLE) From a9ca5f6b1794174ade61850734caae19c8dce85b Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Tue, 3 Aug 2021 19:42:04 -0400 Subject: [PATCH 02/49] Everything Excpeti polishing and options -Added LayerTitle class that is the title menu -Edited the launcher and proxy so it only starts the game when it needs to -Made buttons work with MutableString objects --- .../progressia/ProgressiaLauncher.java | 24 +++++++++++-- .../progressia/client/ClientProxy.java | 19 ++++++---- .../client/graphics/gui/BasicButton.java | 11 ++++-- .../client/graphics/gui/Button.java | 4 +++ .../progressia/test/LayerButtonTest.java | 16 +++++++-- .../windcorp/progressia/test/LayerTitle.java | 35 +++++++++++++++++++ .../resources/assets/languages/en-US.lang | 7 +++- .../resources/assets/languages/ru-RU.lang | 7 +++- 8 files changed, 108 insertions(+), 15 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/test/LayerTitle.java diff --git a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java index c8935fc..2567d9d 100644 --- a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java +++ b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java @@ -18,18 +18,38 @@ package ru.windcorp.progressia; +import ru.windcorp.progressia.client.ClientProxy; +import ru.windcorp.progressia.client.graphics.GUI; +import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend; +import ru.windcorp.progressia.client.graphics.backend.RenderTaskQueue; +import ru.windcorp.progressia.client.graphics.flat.FlatRenderProgram; +import ru.windcorp.progressia.client.graphics.font.GNUUnifontLoader; +import ru.windcorp.progressia.client.graphics.font.Typefaces; +import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; +import ru.windcorp.progressia.client.localization.Localizer; +import ru.windcorp.progressia.common.resource.ResourceManager; import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer; import ru.windcorp.progressia.common.util.crash.providers.*; +import ru.windcorp.progressia.test.LayerTitle; public class ProgressiaLauncher { public static String[] arguments; + private static ClientProxy proxy; - public static void launch(String[] args, Proxy proxy) { + public static void launch(String[] args, ClientProxy inProxy) { arguments = args.clone(); setupCrashReports(); - proxy.initialize(); + + inProxy.initialize(); + proxy = inProxy; + GUI.addTopLayer(new LayerTitle("Title")); + } + + public static void play() + { + proxy.setupServer(); } private static void setupCrashReports() { diff --git a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java index 1d154e7..402c5e8 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java @@ -38,7 +38,9 @@ public class ClientProxy implements Proxy { @Override public void initialize() { + GraphicsBackend.initialize(); + try { RenderTaskQueue.waitAndInvoke(FlatRenderProgram::init); RenderTaskQueue.waitAndInvoke(WorldRenderProgram::init); @@ -47,21 +49,26 @@ public class ClientProxy implements Proxy { .setDefault(GNUUnifontLoader.load(ResourceManager.getResource("assets/unifont-13.0.03.hex.gz"))) ); } catch (InterruptedException e) { - throw CrashReports.report(e, "ClientProxy failed"); + throw CrashReports.report(e, "Menu launch failed"); } - + Localizer.getInstance().setLanguage("en-US"); - + TestContent.registerContent(); Atlases.loadAllAtlases(); AudioSystem.initialize(); - - ServerState.startServer(); - ClientState.connectToLocalServer(); TestMusicPlayer.start(); + + //setupServer(); + } + + public void setupServer() + { + ServerState.startServer(); + ClientState.connectToLocalServer(); } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java index cd30152..ddaab7b 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java @@ -42,10 +42,10 @@ public abstract class BasicButton extends Component { private boolean isPressed = false; private final Collection> actions = Collections.synchronizedCollection(new ArrayList<>()); - - public BasicButton(String name, String label, Font labelFont) { + + public BasicButton(String name, Label label) { super(name); - this.label = new Label(name + ".Label", labelFont, label); + this.label = label; setLayout(new LayoutAlign(10)); addChild(this.label); @@ -103,6 +103,11 @@ public abstract class BasicButton extends Component { }); } + + public BasicButton(String name, String label, Font labelFont) + { + this(name, new Label(name + ".Label", labelFont, label)); + } public BasicButton(String name, String label) { this(name, label, new Font()); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Button.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Button.java index bbeb361..c41dedc 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Button.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Button.java @@ -29,6 +29,10 @@ public class Button extends BasicButton { super(name, label, labelFont); } + public Button(String name, Label label) { + super(name, label); + } + public Button(String name, String label) { this(name, label, new Font()); } diff --git a/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java b/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java index e505291..65b1a07 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java @@ -17,7 +17,10 @@ */ package ru.windcorp.progressia.test; +import ru.windcorp.progressia.client.ClientState; import ru.windcorp.progressia.client.graphics.Colors; +import ru.windcorp.progressia.client.graphics.GUI; +import ru.windcorp.progressia.client.graphics.Layer; import ru.windcorp.progressia.client.graphics.font.Font; import ru.windcorp.progressia.client.graphics.gui.Button; import ru.windcorp.progressia.client.graphics.gui.Checkbox; @@ -25,6 +28,7 @@ import ru.windcorp.progressia.client.graphics.gui.Label; import ru.windcorp.progressia.client.graphics.gui.RadioButton; import ru.windcorp.progressia.client.graphics.gui.RadioButtonGroup; import ru.windcorp.progressia.client.graphics.gui.menu.MenuLayer; +import ru.windcorp.progressia.server.ServerState; public class LayerButtonTest extends MenuLayer { @@ -60,8 +64,16 @@ public class LayerButtonTest extends MenuLayer { getCloseAction().run(); })); - getContent().addChild(new Button("Quit", "Quit").addAction(b -> { - System.exit(0); + getContent().addChild(new Button("Menu", "Menu").addAction(b -> { + //System.exit(0); + for (Layer layer : GUI.getLayers()) + { + GUI.removeLayer(layer); + } + GUI.addTopLayer(new LayerTitle("Title")); + //ClientState.getInstance().; + + //ServerState.getInstance().shutdown("Safe Exit"); })); getContent().takeFocus(); diff --git a/src/main/java/ru/windcorp/progressia/test/LayerTitle.java b/src/main/java/ru/windcorp/progressia/test/LayerTitle.java new file mode 100644 index 0000000..8ef01fd --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/LayerTitle.java @@ -0,0 +1,35 @@ +package ru.windcorp.progressia.test; + +import ru.windcorp.progressia.ProgressiaLauncher; +import ru.windcorp.progressia.client.graphics.Colors; +import ru.windcorp.progressia.client.graphics.GUI; +import ru.windcorp.progressia.client.graphics.font.Font; +import ru.windcorp.progressia.client.graphics.gui.Button; +import ru.windcorp.progressia.client.graphics.gui.GUILayer; +import ru.windcorp.progressia.client.graphics.gui.Label; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical; +import ru.windcorp.progressia.client.localization.MutableString; +import ru.windcorp.progressia.client.localization.MutableStringLocalized; + +public class LayerTitle extends GUILayer { + + public LayerTitle(String name) { + super(name, new LayoutVertical(20,10)); + + MutableString title = new MutableStringLocalized("Layer"+name+".Title"); + Font titleFont = new Font().deriveBold().withColor(Colors.BLACK).withAlign(0.5f); + getRoot().addChild(new Label(name+".Title", titleFont, title)); + + Font buttonFont = titleFont; + MutableString playText = new MutableStringLocalized("Layer"+name+".Play"); + getRoot().addChild(new Button(name+".Play", new Label(name+".Play", buttonFont, playText)).addAction(b -> { + GUI.removeLayer(this); + ProgressiaLauncher.play();})); + + MutableString quitText = new MutableStringLocalized("Layer"+name+".Quit"); + getRoot().addChild(new Button(name+"Quit", new Label(name+".Quit", buttonFont, quitText)).addAction(b -> { + System.exit(0); + })); + } + +} diff --git a/src/main/resources/assets/languages/en-US.lang b/src/main/resources/assets/languages/en-US.lang index 4935e77..6bea171 100644 --- a/src/main/resources/assets/languages/en-US.lang +++ b/src/main/resources/assets/languages/en-US.lang @@ -22,4 +22,9 @@ LayerTestGUI.PlacementModeHint = (Blocks %s Tiles: Ctrl + Mouse Wheel) LayerTestGUI.IsFullscreen = Fullscreen: %5s (F11) LayerTestGUI.IsVSync = VSync: %5s (F12) -LayerButtonTest.Title = Button Test \ No newline at end of file +LayerButtonTest.Title = Button Test + +LayerTitle.Title = Progressia +LayerTitle.Play = Play World +LayerTitle.Options = Options +LayerTitle.Quit = Quit \ No newline at end of file diff --git a/src/main/resources/assets/languages/ru-RU.lang b/src/main/resources/assets/languages/ru-RU.lang index cd10faa..efb1757 100644 --- a/src/main/resources/assets/languages/ru-RU.lang +++ b/src/main/resources/assets/languages/ru-RU.lang @@ -22,4 +22,9 @@ LayerTestGUI.PlacementModeHint = (Блок %s плитки: Ctrl + прокру LayerTestGUI.IsFullscreen = Полный экран: %5s (F11) LayerTestGUI.IsVSync = Верт. синхр.: %5s (F12) -LayerButtonTest.Title = Тест Кнопок \ No newline at end of file +LayerButtonTest.Title = Тест Кнопок + +LayerTitle.Title = Прогрессия +LayerTitle.Play = ??????? +LayerTitle.Options = ???????? +LayerTitle.Quit = ???????? \ No newline at end of file From 94db44e44376e4fe259a2380f38af9cc5931ed91 Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Tue, 3 Aug 2021 22:42:46 -0400 Subject: [PATCH 03/49] Im tired i need sleep -Added listeners for saving and loading chunks -Made loading screens for between title and game(they dont work yet) -Added localized text(some) -Safeish deletion and saving of chunks -It still keeps them in memory I think so this needs work too --- .../progressia/ProgressiaLauncher.java | 8 --- .../progressia/client/ClientState.java | 53 +++++++++++++++++-- .../client/comms/localhost/LocalClient.java | 3 +- .../localhost/LocalServerCommsChannel.java | 2 +- .../progressia/server/ChunkManager.java | 50 +++++++++++++++++ .../progressia/server/PlayerManager.java | 5 ++ .../progressia/test/LayerButtonTest.java | 48 ++++++++++++++--- .../progressia/test/LayerTestText.java | 24 +++++++++ .../windcorp/progressia/test/LayerTitle.java | 1 + .../resources/assets/languages/en-US.lang | 6 ++- .../resources/assets/languages/ru-RU.lang | 6 ++- 11 files changed, 185 insertions(+), 21 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/test/LayerTestText.java diff --git a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java index 2567d9d..f32936f 100644 --- a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java +++ b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java @@ -20,14 +20,6 @@ package ru.windcorp.progressia; import ru.windcorp.progressia.client.ClientProxy; import ru.windcorp.progressia.client.graphics.GUI; -import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend; -import ru.windcorp.progressia.client.graphics.backend.RenderTaskQueue; -import ru.windcorp.progressia.client.graphics.flat.FlatRenderProgram; -import ru.windcorp.progressia.client.graphics.font.GNUUnifontLoader; -import ru.windcorp.progressia.client.graphics.font.Typefaces; -import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; -import ru.windcorp.progressia.client.localization.Localizer; -import ru.windcorp.progressia.common.resource.ResourceManager; import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer; import ru.windcorp.progressia.common.util.crash.providers.*; diff --git a/src/main/java/ru/windcorp/progressia/client/ClientState.java b/src/main/java/ru/windcorp/progressia/client/ClientState.java index 75f0f07..1525045 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientState.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientState.java @@ -18,18 +18,30 @@ package ru.windcorp.progressia.client; +import java.util.Collection; +import java.util.HashSet; + import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel; import ru.windcorp.progressia.client.graphics.GUI; +import ru.windcorp.progressia.client.graphics.Layer; import ru.windcorp.progressia.client.graphics.world.LayerWorld; +import ru.windcorp.progressia.client.localization.MutableString; +import ru.windcorp.progressia.client.localization.MutableStringLocalized; import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.server.ServerState; import ru.windcorp.progressia.test.LayerAbout; +import ru.windcorp.progressia.test.LayerTestText; import ru.windcorp.progressia.test.LayerTestUI; import ru.windcorp.progressia.test.TestContent; public class ClientState { private static Client instance; + + private static Collection layers; + + private static boolean firstLoad; + private static LayerTestText layer; public static Client getInstance() { return instance; @@ -46,6 +58,8 @@ public class ClientState { LocalServerCommsChannel channel = new LocalServerCommsChannel( ServerState.getInstance() ); + + firstLoad = true; Client client = new Client(world, channel); @@ -53,10 +67,43 @@ public class ClientState { setInstance(client); - GUI.addBottomLayer(new LayerWorld(client)); - GUI.addTopLayer(new LayerTestUI()); - GUI.addTopLayer(new LayerAbout()); + ServerState.getInstance().getChunkManager().register(bl -> { + if (!bl && firstLoad) + { + MutableString t = new MutableStringLocalized("LayerText.Load"); + layer = new LayerTestText("Text",() -> {t.update(); return t.get();}); + GUI.addTopLayer(layer); + } + else if (bl && firstLoad) + { + GUI.removeLayer(layer); + + LayerWorld layerWorld = new LayerWorld(client); + LayerTestUI layerUI = new LayerTestUI(); + LayerAbout layerAbout = new LayerAbout(); + GUI.addBottomLayer(layerWorld); + GUI.addTopLayer(layerUI); + GUI.addTopLayer(layerAbout); + layers = new HashSet(); + layers.add(layerWorld); + layers.add(layerUI); + layers.add(layerAbout); + + firstLoad = false; + } + }); + + } + + public static void disconnectFromLocalServer() + { + for (Layer layer : layers) + { + GUI.removeLayer(layer); + } + + ServerState.getInstance().getClientManager(); } private ClientState() { diff --git a/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalClient.java b/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalClient.java index 816fba8..f1fdf96 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalClient.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalClient.java @@ -53,7 +53,8 @@ public class LocalClient extends ClientPlayer { @Override public void disconnect() { - // Do nothing + setState(State.DISCONNECTING); + serverComms.disconnect(); } } diff --git a/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalServerCommsChannel.java b/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalServerCommsChannel.java index 194a2a1..b631a3c 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalServerCommsChannel.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalServerCommsChannel.java @@ -54,7 +54,7 @@ public class LocalServerCommsChannel extends ServerCommsChannel { @Override public void disconnect() { - // Do nothing + setState(State.DISCONNECTING); } } diff --git a/src/main/java/ru/windcorp/progressia/server/ChunkManager.java b/src/main/java/ru/windcorp/progressia/server/ChunkManager.java index b0b0777..5042954 100644 --- a/src/main/java/ru/windcorp/progressia/server/ChunkManager.java +++ b/src/main/java/ru/windcorp/progressia/server/ChunkManager.java @@ -18,10 +18,15 @@ package ru.windcorp.progressia.server; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Map; import java.util.WeakHashMap; +import org.apache.logging.log4j.LogManager; + import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.PacketRevokeChunk; @@ -74,6 +79,12 @@ public class ChunkManager { } } + + @FunctionalInterface + public interface ChunksLoadListener + { + void handle(boolean starting); + } private final Server server; @@ -82,6 +93,8 @@ public class ChunkManager { private final ChunkSet toLoad = ChunkSets.newHashSet(); private final ChunkSet toUnload = ChunkSets.newHashSet(); + private Collection listeners = Collections.synchronizedCollection( new ArrayList<>()); + // TODO replace with a normal Map managed by some sort of PlayerListener, // weak maps are weak private final Map visions = Collections.synchronizedMap(new WeakHashMap<>()); @@ -101,6 +114,16 @@ public class ChunkManager { } } + public void register(ChunksLoadListener cll) + { + listeners.add(cll); + } + + public void unregisterAll() + { + listeners.clear(); + } + private void gatherRequests() { requested.clear(); @@ -126,6 +149,12 @@ public class ChunkManager { } private void processQueues() { + + if (toUnload.size()!=0 || toLoad.size()!=0) + { + LogManager.getLogger().info(String.valueOf(toUnload.size())+" "+String.valueOf( toLoad.size())); + listeners.forEach(l -> l.handle(false)); + } toUnload.forEach(this::unloadChunk); toUnload.clear(); toLoad.forEach(this::loadChunk); @@ -134,6 +163,8 @@ public class ChunkManager { visions.forEach((p, v) -> { v.processQueues(p); }); + listeners.forEach(l -> l.handle(true)); + } private PlayerVision getVision(Player player, boolean createIfMissing) { @@ -174,6 +205,25 @@ public class ChunkManager { TestWorldDiskIO.saveChunk(chunk, getServer()); } + + public void unloadAll() // dont use probably + { + WorldData world = getServer().getWorld().getData(); + + //Collection chunks = world.getChunks(); + Collection chunkPoss = new HashSet(); + + world.forEachChunk(c -> { + chunkPoss.add(c.getPosition()); + }); + + chunkPoss.forEach(v -> { + ChunkData c = world.getChunk(v); + world.removeChunk(c); + + TestWorldDiskIO.saveChunk(c, getServer()); + }); + } public void sendChunk(Player player, Vec3i chunkPos) { ChunkData chunk = server.getWorld().getData().getChunk(chunkPos); diff --git a/src/main/java/ru/windcorp/progressia/server/PlayerManager.java b/src/main/java/ru/windcorp/progressia/server/PlayerManager.java index 38d0f32..b1447bf 100644 --- a/src/main/java/ru/windcorp/progressia/server/PlayerManager.java +++ b/src/main/java/ru/windcorp/progressia/server/PlayerManager.java @@ -72,6 +72,11 @@ public class PlayerManager { return player; } + + public void removePlayer(Player player) + { + players.remove(player); + } public Server getServer() { return server; diff --git a/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java b/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java index 65b1a07..bae1d67 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java @@ -17,6 +17,8 @@ */ package ru.windcorp.progressia.test; +import java.util.Collection; + import ru.windcorp.progressia.client.ClientState; import ru.windcorp.progressia.client.graphics.Colors; import ru.windcorp.progressia.client.graphics.GUI; @@ -28,9 +30,15 @@ import ru.windcorp.progressia.client.graphics.gui.Label; import ru.windcorp.progressia.client.graphics.gui.RadioButton; import ru.windcorp.progressia.client.graphics.gui.RadioButtonGroup; import ru.windcorp.progressia.client.graphics.gui.menu.MenuLayer; +import ru.windcorp.progressia.client.localization.MutableString; +import ru.windcorp.progressia.client.localization.MutableStringLocalized; +import ru.windcorp.progressia.server.ChunkManager; +import ru.windcorp.progressia.server.Player; import ru.windcorp.progressia.server.ServerState; public class LayerButtonTest extends MenuLayer { + + boolean alive = true; public LayerButtonTest() { super("ButtonTest"); @@ -64,15 +72,43 @@ public class LayerButtonTest extends MenuLayer { getCloseAction().run(); })); - getContent().addChild(new Button("Menu", "Menu").addAction(b -> { + getContent().addChild(new Button("Menu", "Back To Menu").addAction(b -> { //System.exit(0); - for (Layer layer : GUI.getLayers()) - { - GUI.removeLayer(layer); - } - GUI.addTopLayer(new LayerTitle("Title")); + //for (Layer layer : GUI.getLayers()) + //{ + // GUI.removeLayer(layer); + //} + getCloseAction().run(); + //ClientState.getInstance().; + Collection players = ServerState.getInstance().getPlayerManager().getPlayers(); + players.clear(); + + ClientState.disconnectFromLocalServer(); + + MutableString t = new MutableStringLocalized("LayerText.Save"); + LayerTestText layer = new LayerTestText("Text",() -> {t.update(); return t.get();}); + + GUI.addTopLayer(layer); + + ChunkManager cm = ServerState.getInstance().getChunkManager(); + alive = true; + cm.register(bl -> { + if (bl && alive) + { + GUI.removeLayer(layer); + GUI.addTopLayer(new LayerTitle("Title")); + //cm.unregisterAll(); + alive = false; + } + }); + + //ClientState.getInstance(); + ClientState.setInstance(null); + ServerState.setInstance(null); + //ServerState.getInstance().getChunkManager().unloadAll(); + //ServerState.getInstance().shutdown("Safe Exit"); })); diff --git a/src/main/java/ru/windcorp/progressia/test/LayerTestText.java b/src/main/java/ru/windcorp/progressia/test/LayerTestText.java new file mode 100644 index 0000000..3cfef00 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/LayerTestText.java @@ -0,0 +1,24 @@ +package ru.windcorp.progressia.test; + +import java.util.function.Supplier; + +import ru.windcorp.progressia.client.graphics.Colors; +import ru.windcorp.progressia.client.graphics.font.Font; +import ru.windcorp.progressia.client.graphics.gui.GUILayer; +import ru.windcorp.progressia.client.graphics.gui.Label; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical; + +public class LayerTestText extends GUILayer { + public LayerTestText(String name, Supplier value) { + super(name, new LayoutVertical(20,10)); + + //MutableString title = new MutableStringLocalized("Layer"+name+".Title"); + Font titleFont = new Font().deriveBold().withColor(Colors.BLACK).withAlign(0.5f); + getRoot().addChild(new Label(name+".Text", titleFont, value)); + } + + public LayerTestText(String name, String value) + { + this(name,() -> value); + } +} diff --git a/src/main/java/ru/windcorp/progressia/test/LayerTitle.java b/src/main/java/ru/windcorp/progressia/test/LayerTitle.java index 8ef01fd..c739651 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerTitle.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerTitle.java @@ -24,6 +24,7 @@ public class LayerTitle extends GUILayer { MutableString playText = new MutableStringLocalized("Layer"+name+".Play"); getRoot().addChild(new Button(name+".Play", new Label(name+".Play", buttonFont, playText)).addAction(b -> { GUI.removeLayer(this); + ProgressiaLauncher.play();})); MutableString quitText = new MutableStringLocalized("Layer"+name+".Quit"); diff --git a/src/main/resources/assets/languages/en-US.lang b/src/main/resources/assets/languages/en-US.lang index 6bea171..f1bb85c 100644 --- a/src/main/resources/assets/languages/en-US.lang +++ b/src/main/resources/assets/languages/en-US.lang @@ -23,8 +23,12 @@ LayerTestGUI.IsFullscreen = Fullscreen: %5s (F11) LayerTestGUI.IsVSync = VSync: %5s (F12) LayerButtonTest.Title = Button Test +LayerButtonTest.Return = Back To Menu LayerTitle.Title = Progressia LayerTitle.Play = Play World LayerTitle.Options = Options -LayerTitle.Quit = Quit \ No newline at end of file +LayerTitle.Quit = Quit + +LayerText.Load = Loading... +LayerText.Save = Saving... \ No newline at end of file diff --git a/src/main/resources/assets/languages/ru-RU.lang b/src/main/resources/assets/languages/ru-RU.lang index efb1757..92cc41b 100644 --- a/src/main/resources/assets/languages/ru-RU.lang +++ b/src/main/resources/assets/languages/ru-RU.lang @@ -23,8 +23,12 @@ LayerTestGUI.IsFullscreen = Полный экран: %5s (F11) LayerTestGUI.IsVSync = Верт. синхр.: %5s (F12) LayerButtonTest.Title = Тест Кнопок +LayerButtonTest.Return = Back To Menu [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ LayerTitle.Title = Прогрессия LayerTitle.Play = ??????? LayerTitle.Options = ???????? -LayerTitle.Quit = ???????? \ No newline at end of file +LayerTitle.Quit = ???????? + +LayerText.Load = Loading... (Change) +LayerText.Save = Saving...(Cahnsf) \ No newline at end of file From 6521cb5749fee75105de0bc4d18be57308275ef6 Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Wed, 4 Aug 2021 12:52:37 -0400 Subject: [PATCH 04/49] Better Listeners -Specific listeners for the start and stop of loading -Better(?) layer deletion after exiting a world -Actual server thread shutdown --- .../progressia/client/ClientState.java | 23 ++++++------- .../progressia/server/ChunkManager.java | 33 ++++++++++++++++++- .../progressia/server/ServerThread.java | 1 + .../progressia/test/LayerButtonTest.java | 13 +++++--- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/client/ClientState.java b/src/main/java/ru/windcorp/progressia/client/ClientState.java index 1525045..f8a1dfa 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientState.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientState.java @@ -28,6 +28,8 @@ import ru.windcorp.progressia.client.graphics.world.LayerWorld; import ru.windcorp.progressia.client.localization.MutableString; import ru.windcorp.progressia.client.localization.MutableStringLocalized; import ru.windcorp.progressia.common.world.WorldData; +import ru.windcorp.progressia.server.ChunkManager.ChunksLoadFinishListener; +import ru.windcorp.progressia.server.ChunkManager.ChunksLoadStartListener; import ru.windcorp.progressia.server.ServerState; import ru.windcorp.progressia.test.LayerAbout; import ru.windcorp.progressia.test.LayerTestText; @@ -38,8 +40,6 @@ public class ClientState { private static Client instance; - private static Collection layers; - private static boolean firstLoad; private static LayerTestText layer; @@ -67,14 +67,16 @@ public class ClientState { setInstance(client); - ServerState.getInstance().getChunkManager().register(bl -> { - if (!bl && firstLoad) + ServerState.getInstance().getChunkManager().register((ChunksLoadStartListener)() -> { + if (firstLoad) { MutableString t = new MutableStringLocalized("LayerText.Load"); layer = new LayerTestText("Text",() -> {t.update(); return t.get();}); GUI.addTopLayer(layer); - } - else if (bl && firstLoad) + }}); + + ServerState.getInstance().getChunkManager().register((ChunksLoadFinishListener)() -> { + if (firstLoad) { GUI.removeLayer(layer); @@ -84,11 +86,6 @@ public class ClientState { GUI.addBottomLayer(layerWorld); GUI.addTopLayer(layerUI); GUI.addTopLayer(layerAbout); - - layers = new HashSet(); - layers.add(layerWorld); - layers.add(layerUI); - layers.add(layerAbout); firstLoad = false; } @@ -98,12 +95,12 @@ public class ClientState { public static void disconnectFromLocalServer() { - for (Layer layer : layers) + for (Layer layer : GUI.getLayers()) { GUI.removeLayer(layer); } - ServerState.getInstance().getClientManager(); + //ServerState.getInstance().getClientManager(); } private ClientState() { diff --git a/src/main/java/ru/windcorp/progressia/server/ChunkManager.java b/src/main/java/ru/windcorp/progressia/server/ChunkManager.java index 5042954..badb061 100644 --- a/src/main/java/ru/windcorp/progressia/server/ChunkManager.java +++ b/src/main/java/ru/windcorp/progressia/server/ChunkManager.java @@ -85,6 +85,22 @@ public class ChunkManager { { void handle(boolean starting); } + + @FunctionalInterface + private interface ChunksLoadEventListener + { + void handle(); + } + + public interface ChunksLoadStartListener extends ChunksLoadEventListener + { + + } + + public interface ChunksLoadFinishListener extends ChunksLoadEventListener + { + + } private final Server server; @@ -94,6 +110,8 @@ public class ChunkManager { private final ChunkSet toUnload = ChunkSets.newHashSet(); private Collection listeners = Collections.synchronizedCollection( new ArrayList<>()); + private Collection startListeners = Collections.synchronizedCollection( new ArrayList<>()); + private Collection finishListeners = Collections.synchronizedCollection( new ArrayList<>()); // TODO replace with a normal Map managed by some sort of PlayerListener, // weak maps are weak @@ -119,6 +137,16 @@ public class ChunkManager { listeners.add(cll); } + public void register(ChunksLoadStartListener clsl) + { + startListeners.add(clsl); + } + + public void register(ChunksLoadFinishListener clfl) + { + finishListeners.add(clfl); + } + public void unregisterAll() { listeners.clear(); @@ -153,8 +181,10 @@ public class ChunkManager { if (toUnload.size()!=0 || toLoad.size()!=0) { LogManager.getLogger().info(String.valueOf(toUnload.size())+" "+String.valueOf( toLoad.size())); - listeners.forEach(l -> l.handle(false)); } + listeners.forEach(l -> l.handle(false)); + startListeners.forEach(sl -> sl.handle()); + toUnload.forEach(this::unloadChunk); toUnload.clear(); toLoad.forEach(this::loadChunk); @@ -164,6 +194,7 @@ public class ChunkManager { v.processQueues(p); }); listeners.forEach(l -> l.handle(true)); + finishListeners.forEach(fl -> fl.handle()); } diff --git a/src/main/java/ru/windcorp/progressia/server/ServerThread.java b/src/main/java/ru/windcorp/progressia/server/ServerThread.java index 90f3ce9..5a1333a 100644 --- a/src/main/java/ru/windcorp/progressia/server/ServerThread.java +++ b/src/main/java/ru/windcorp/progressia/server/ServerThread.java @@ -79,6 +79,7 @@ public class ServerThread implements Runnable { public void stop() { try { + executor.shutdown(); executor.awaitTermination(10, TimeUnit.MINUTES); } catch (InterruptedException e) { LogManager.getLogger().warn("Received interrupt in ServerThread.stop(), aborting wait"); diff --git a/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java b/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java index bae1d67..2b36bbd 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java @@ -33,6 +33,8 @@ import ru.windcorp.progressia.client.graphics.gui.menu.MenuLayer; import ru.windcorp.progressia.client.localization.MutableString; import ru.windcorp.progressia.client.localization.MutableStringLocalized; import ru.windcorp.progressia.server.ChunkManager; +import ru.windcorp.progressia.server.ChunkManager.ChunksLoadFinishListener; +import ru.windcorp.progressia.server.ChunkManager.ChunksLoadListener; import ru.windcorp.progressia.server.Player; import ru.windcorp.progressia.server.ServerState; @@ -94,22 +96,25 @@ public class LayerButtonTest extends MenuLayer { ChunkManager cm = ServerState.getInstance().getChunkManager(); alive = true; - cm.register(bl -> { - if (bl && alive) + cm.register((ChunksLoadFinishListener)() -> { + if (alive) { GUI.removeLayer(layer); GUI.addTopLayer(new LayerTitle("Title")); //cm.unregisterAll(); alive = false; + + ServerState.getInstance().shutdown("Safe Exit"); + + ServerState.setInstance(null); } }); //ClientState.getInstance(); ClientState.setInstance(null); - ServerState.setInstance(null); //ServerState.getInstance().getChunkManager().unloadAll(); - //ServerState.getInstance().shutdown("Safe Exit"); + })); getContent().takeFocus(); From c88dea6030db43b7910a5cf5da91bb2de8d9fcc5 Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Wed, 4 Aug 2021 16:57:21 -0400 Subject: [PATCH 05/49] Fixing Bugs mostly -Cleaning up imports -Better error detection -Actual thread deletion(still needs a bit of work to delete all conected objects) -Starting making format file and inplementing it --- .../progressia/client/ClientState.java | 3 - .../progressia/client/graphics/GUI.java | 4 + .../progressia/server/ServerThread.java | 19 +- .../server/world/ticking/Ticker.java | 2 + .../progressia/test/LayerButtonTest.java | 1 + .../progressia/test/TestWorldDiskIO.java | 321 +++++++++++++----- 6 files changed, 254 insertions(+), 96 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/client/ClientState.java b/src/main/java/ru/windcorp/progressia/client/ClientState.java index f8a1dfa..1092203 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientState.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientState.java @@ -18,9 +18,6 @@ package ru.windcorp.progressia.client; -import java.util.Collection; -import java.util.HashSet; - import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel; import ru.windcorp.progressia.client.graphics.GUI; import ru.windcorp.progressia.client.graphics.Layer; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/GUI.java b/src/main/java/ru/windcorp/progressia/client/graphics/GUI.java index bb4d85b..56829cf 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/GUI.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/GUI.java @@ -21,6 +21,7 @@ package ru.windcorp.progressia.client.graphics; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import com.google.common.eventbus.Subscribe; @@ -58,6 +59,7 @@ public class GUI { } public static void addBottomLayer(Layer layer) { + Objects.requireNonNull(layer, "layer"); modify(layers -> { layers.add(layer); layer.onAdded(); @@ -65,6 +67,7 @@ public class GUI { } public static void addTopLayer(Layer layer) { + Objects.requireNonNull(layer, "layer"); modify(layers -> { layers.add(0, layer); layer.onAdded(); @@ -72,6 +75,7 @@ public class GUI { } public static void removeLayer(Layer layer) { + Objects.requireNonNull(layer, "layer"); modify(layers -> { layers.remove(layer); layer.onRemoved(); diff --git a/src/main/java/ru/windcorp/progressia/server/ServerThread.java b/src/main/java/ru/windcorp/progressia/server/ServerThread.java index 5a1333a..d8d15a9 100644 --- a/src/main/java/ru/windcorp/progressia/server/ServerThread.java +++ b/src/main/java/ru/windcorp/progressia/server/ServerThread.java @@ -29,6 +29,8 @@ import ru.windcorp.progressia.server.world.ticking.TickerCoordinator; public class ServerThread implements Runnable { private static final ThreadLocal SERVER_THREADS_MAP = new ThreadLocal<>(); + + private static boolean isShuttingDown; public static Server getCurrentServer() { return SERVER_THREADS_MAP.get(); @@ -63,6 +65,7 @@ public class ServerThread implements Runnable { } public void start() { + isShuttingDown = false; ticker.start(); executor.scheduleAtFixedRate(this, 0, 1000 / 20, TimeUnit.MILLISECONDS); } @@ -70,6 +73,12 @@ public class ServerThread implements Runnable { @Override public void run() { try { + if (isShuttingDown) + { + getTicker().stop(); + executor.shutdown(); + return; + } server.tick(); ticker.runOneTick(); } catch (Throwable e) { @@ -78,14 +87,10 @@ public class ServerThread implements Runnable { } public void stop() { - try { - executor.shutdown(); - executor.awaitTermination(10, TimeUnit.MINUTES); - } catch (InterruptedException e) { - LogManager.getLogger().warn("Received interrupt in ServerThread.stop(), aborting wait"); - } + + isShuttingDown = true; - getTicker().stop(); + //getTicker().stop(); } public Server getServer() { diff --git a/src/main/java/ru/windcorp/progressia/server/world/ticking/Ticker.java b/src/main/java/ru/windcorp/progressia/server/world/ticking/Ticker.java index 5c4b83e..8a102ac 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/ticking/Ticker.java +++ b/src/main/java/ru/windcorp/progressia/server/world/ticking/Ticker.java @@ -115,6 +115,8 @@ class Ticker { } catch (Exception e) { getCoordinator().crash(e, this.name); } + + } private synchronized boolean sleep() { diff --git a/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java b/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java index 2b36bbd..c6e5d00 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java @@ -104,6 +104,7 @@ public class LayerButtonTest extends MenuLayer { //cm.unregisterAll(); alive = false; + //ServerState.getInstance().; ServerState.getInstance().shutdown("Safe Exit"); ServerState.setInstance(null); diff --git a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java index 1b93323..71e4225 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java @@ -15,21 +15,22 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.BufferedWriter; import java.io.DataInputStream; import java.io.DataOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; +import java.util.Scanner; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; @@ -47,47 +48,68 @@ import ru.windcorp.progressia.server.Server; public class TestWorldDiskIO { private static Path SAVE_DIR = Paths.get("tmp_world"); + private static String formatFile = "world.format"; private static final Logger LOG = LogManager.getLogger("TestWorldDiskIO"); private static final boolean ENABLE = true; - + private static final int maxSize = 1048576; - private static final int sectorSize = maxSize/256; - - private Map regions = new HashMap(); - - private int natFromInt(int loc) - { - if (loc<0) - return (-loc)<<1 + 1; - return loc<<1; + private static final int sectorSize = maxSize / 256; + + private static final int bestFormat = 2; + + // private Map regions = new HashMap(); + private static Vec3i regionSize; + private static int chunksPerRegion; + + private static int currentFormat = -1; + private static String extension = ".null"; + + private static int natFromInt(int loc) { + if (loc < 0) + return (-loc) << 1 + 1; + return loc << 1; } - - private int intFromNat(int loc) // Possibly unused + + private static int intFromNat(int loc) // Possibly unused { - if ((loc&1) == 1) - return -loc>>1; - return loc>>1; + if ((loc & 1) == 1) + return -loc >> 1; + return loc >> 1; } - - private Vec3i getRegionLoc(Vec3i chunkLoc) - { - return new Vec3i(natFromInt(chunkLoc.x),natFromInt(chunkLoc.y),natFromInt(chunkLoc.z)); + + private static Vec3i getRegionLoc(Vec3i chunkLoc) { + return new Vec3i(natFromInt(chunkLoc.x), natFromInt(chunkLoc.y), natFromInt(chunkLoc.z)); } - - public void initRegions() - { + + public static void initRegions() { initRegions(null); } - - public void initRegions(Path worldPath) - { - if (worldPath!=null) - { + + public static void initRegions(Path worldPath) { + if (worldPath != null) { SAVE_DIR = worldPath; } - - regions.put(new Vec3i(0,0,0), new Vec3i(1,1,1)); + + // regions.put(new Vec3i(0,0,0), new Vec3i(1,1,1)); + } + + private static void setRegionSize(int format) { + switch (format) { + case 0: + case 1: + regionSize = new Vec3i(1); + chunksPerRegion = 1; + currentFormat = format; + extension = ".progressia_chunk"; + break; + case 2: + regionSize = new Vec3i(16); + chunksPerRegion = 16 * 16 * 16; + currentFormat = 2; + extension = ".progressia_region"; + break; + } } public static void saveChunk(ChunkData chunk, Server server) { @@ -95,32 +117,65 @@ public class TestWorldDiskIO { return; try { - LOG.debug( - "Saving {} {} {}", - chunk.getPosition().x, - chunk.getPosition().y, - chunk.getPosition().z - ); - Files.createDirectories(SAVE_DIR); - - Path path = SAVE_DIR.resolve( - String.format( - "chunk_%+d_%+d_%+d.progressia_chunk", + if (currentFormat == 0) { + LOG.debug( + "Saving {} {} {}", chunk.getPosition().x, chunk.getPosition().y, chunk.getPosition().z - ) - ); + ); - try ( - DataOutputStream output = new DataOutputStream( - new DeflaterOutputStream(new BufferedOutputStream(Files.newOutputStream(path))) - ) - ) { - ChunkIO.save(chunk, output, IOContext.SAVE); - writeGenerationHint(chunk, output, server); + Files.createDirectories(SAVE_DIR); + + Path path = SAVE_DIR.resolve( + String.format( + "chunk_%+d_%+d_%+d" + extension, + chunk.getPosition().x, + chunk.getPosition().y, + chunk.getPosition().z + ) + ); + + try ( + DataOutputStream output = new DataOutputStream( + new DeflaterOutputStream(new BufferedOutputStream(Files.newOutputStream(path))) + ) + ) { + ChunkIO.save(chunk, output, IOContext.SAVE); + writeGenerationHint(chunk, output, server); + } + } else if (currentFormat == 1) { + LOG.debug( + "Saving {} {} {}", + chunk.getPosition().x, + chunk.getPosition().y, + chunk.getPosition().z + ); + + Files.createDirectories(SAVE_DIR); + + Vec3i saveCoords = getRegionLoc(chunk.getPosition()); + + Path path = SAVE_DIR.resolve( + String.format( + "chunk_%+d_%+d_%+d" + extension, + saveCoords.x, + saveCoords.y, + saveCoords.z + ) + ); + + try ( + DataOutputStream output = new DataOutputStream( + new DeflaterOutputStream(new BufferedOutputStream(Files.newOutputStream(path))) + ) + ) { + ChunkIO.save(chunk, output, IOContext.SAVE); + writeGenerationHint(chunk, output, server); + } } + // else if (currentFormat) } catch (IOException e) { e.printStackTrace(); } @@ -135,47 +190,141 @@ public class TestWorldDiskIO { if (!ENABLE) return null; - Path path = SAVE_DIR.resolve( - String.format( - "chunk_%+d_%+d_%+d.progressia_chunk", - chunkPos.x, - chunkPos.y, - chunkPos.z - ) - ); + if (currentFormat == -1) { + Path formatPath = SAVE_DIR.resolve(formatFile); + File format = formatPath.toFile(); - if (!Files.exists(path)) { - LOG.debug( - "Not found {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z - ); + if (format.exists()) { + String data = null; + try { + Scanner reader = new Scanner(format); - return null; + data = reader.next(); + + reader.close(); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + byte[] formatBytes = data.getBytes(); + int formatNum = formatBytes[0] * 256 * 256 * 256 + formatBytes[1] * 256 * 256 + formatBytes[2] * 256 + + formatBytes[3]; + + setRegionSize(formatNum); + } else { + setRegionSize(bestFormat); + + BufferedWriter bw; + try { + bw = new BufferedWriter(new FileWriter(format)); + + bw.write( + new char[] { + bestFormat / (256 * 256 * 256), + (bestFormat % 256) / (256 * 256), + (bestFormat % (256 * 256)) / (256), + bestFormat % (256 * 256 * 256) } + ); + + bw.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } } - try { - ChunkData result = load(path, chunkPos, world, server); + if (currentFormat == 0) { - LOG.debug( - "Loaded {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z + Path path = SAVE_DIR.resolve( + String.format( + "chunk_%+d_%+d_%+d" + extension, + chunkPos.x, + chunkPos.y, + chunkPos.z + ) ); - return result; - } catch (Exception e) { - e.printStackTrace(); - LOG.debug( - "Could not load {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z + if (!Files.exists(path)) { + LOG.debug( + "Not found {} {} {}", + chunkPos.x, + chunkPos.y, + chunkPos.z + ); + + return null; + } + + try { + ChunkData result = load(path, chunkPos, world, server); + + LOG.debug( + "Loaded {} {} {}", + chunkPos.x, + chunkPos.y, + chunkPos.z + ); + + return result; + } catch (Exception e) { + e.printStackTrace(); + LOG.debug( + "Could not load {} {} {}", + chunkPos.x, + chunkPos.y, + chunkPos.z + ); + return null; + } + } else if (currentFormat == 1) { + Vec3i saveCoords = getRegionLoc(chunkPos); + + Path path = SAVE_DIR.resolve( + String.format( + "chunk_%+d_%+d_%+d" + extension, + saveCoords.x, + saveCoords.y, + saveCoords.z + ) ); - return null; + + if (!Files.exists(path)) { + LOG.debug( + "Not found {} {} {}", + chunkPos.x, + chunkPos.y, + chunkPos.z + ); + + return null; + } + + try { + ChunkData result = load(path, chunkPos, world, server); + + LOG.debug( + "Loaded {} {} {}", + chunkPos.x, + chunkPos.y, + chunkPos.z + ); + + return result; + } catch (Exception e) { + e.printStackTrace(); + LOG.debug( + "Could not load {} {} {}", + chunkPos.x, + chunkPos.y, + chunkPos.z + ); + return null; + } } + return null; } private static ChunkData load(Path path, Vec3i chunkPos, WorldData world, Server server) From 0c66f1751e9e05e02b452b69b54dcf81f13e3f94 Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Wed, 4 Aug 2021 19:17:49 -0400 Subject: [PATCH 06/49] Made outline of region file -Improved loading screen loading(so it doesnt crash) -Implemented region file related things, but it doesnt quite work -Uses file header to try to look up location of data -Writes the data at the end of the file(I need info to how much it writes) --- .../progressia/client/ClientState.java | 6 +- .../progressia/test/TestWorldDiskIO.java | 187 ++++++++++++++++-- src/main/resources/log4j2.xml | 1 + 3 files changed, 173 insertions(+), 21 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/client/ClientState.java b/src/main/java/ru/windcorp/progressia/client/ClientState.java index 1092203..2ae791c 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientState.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientState.java @@ -64,11 +64,13 @@ public class ClientState { setInstance(client); + MutableString t = new MutableStringLocalized("LayerText.Load"); + layer = new LayerTestText("Text",() -> {t.update(); return t.get();}); + ServerState.getInstance().getChunkManager().register((ChunksLoadStartListener)() -> { if (firstLoad) { - MutableString t = new MutableStringLocalized("LayerText.Load"); - layer = new LayerTestText("Text",() -> {t.update(); return t.get();}); + GUI.addTopLayer(layer); }}); diff --git a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java index 71e4225..e8b53e9 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java @@ -27,6 +27,8 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.channels.Channels; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -53,14 +55,15 @@ public class TestWorldDiskIO { private static final boolean ENABLE = true; - private static final int maxSize = 1048576; - private static final int sectorSize = maxSize / 256; + private static int maxSize = 1048576; + private static int sectorSize = maxSize / 256; - private static final int bestFormat = 2; + private static final int bestFormat = 65536; // private Map regions = new HashMap(); private static Vec3i regionSize; private static int chunksPerRegion; + private static int offsetBytes; private static int currentFormat = -1; private static String extension = ".null"; @@ -71,15 +74,25 @@ public class TestWorldDiskIO { return loc << 1; } - private static int intFromNat(int loc) // Possibly unused + /*private static int intFromNat(int loc) // Possibly unused { if ((loc & 1) == 1) return -loc >> 1; return loc >> 1; - } + }*/ - private static Vec3i getRegionLoc(Vec3i chunkLoc) { - return new Vec3i(natFromInt(chunkLoc.x), natFromInt(chunkLoc.y), natFromInt(chunkLoc.z)); + private static Vec3i getRegion(Vec3i chunkLoc) { + return new Vec3i(natFromInt(chunkLoc.x/regionSize.x), natFromInt(chunkLoc.y/regionSize.y), natFromInt(chunkLoc.z/regionSize.z)); + } + + private static int mod(int a, int m) + { + return ((a%m)+m)%m; + } + + private static Vec3i getRegionLoc(Vec3i chunkLoc) + { + return new Vec3i(mod(chunkLoc.x,regionSize.x),mod(chunkLoc.y,regionSize.y),mod(chunkLoc.z,regionSize.z)); } public static void initRegions() { @@ -103,10 +116,11 @@ public class TestWorldDiskIO { currentFormat = format; extension = ".progressia_chunk"; break; - case 2: + case 65536: regionSize = new Vec3i(16); chunksPerRegion = 16 * 16 * 16; - currentFormat = 2; + currentFormat = 65536; + offsetBytes = 4; extension = ".progressia_region"; break; } @@ -155,11 +169,11 @@ public class TestWorldDiskIO { Files.createDirectories(SAVE_DIR); - Vec3i saveCoords = getRegionLoc(chunk.getPosition()); + Vec3i saveCoords = getRegion(chunk.getPosition()); Path path = SAVE_DIR.resolve( String.format( - "chunk_%+d_%+d_%+d" + extension, + "chunk_%d_%d_%d" + extension, saveCoords.x, saveCoords.y, saveCoords.z @@ -175,6 +189,59 @@ public class TestWorldDiskIO { writeGenerationHint(chunk, output, server); } } + else if (currentFormat == 65536) + { + LOG.debug( + "Saving {} {} {}", + chunk.getPosition().x, + chunk.getPosition().y, + chunk.getPosition().z + ); + + Files.createDirectories(SAVE_DIR); + + Vec3i saveCoords = getRegion(chunk.getPosition()); + + Path path = SAVE_DIR.resolve( + String.format( + "%d_%d_%d" + extension, + saveCoords.x, + saveCoords.y, + saveCoords.z + ) + ); + + try ( + RandomAccessFile output = new RandomAccessFile(path.toFile(), "rw") + ) { + //LOG.debug(output.read()); + if (output.read()<0) + { + output.writeChars("\0".repeat((offsetBytes+1)*chunksPerRegion)); + } + + Vec3i pos = getRegionLoc(chunk.getPosition()); + int shortOffset = (offsetBytes+1)*(pos.z+regionSize.z*(pos.y + regionSize.y*pos.x)); + int fullOffset = (offsetBytes+1)*(chunksPerRegion); + output.seek(shortOffset); + int offset = output.readInt(); + int sectorLength = output.read(); + if (sectorLength == 0) + { + offset = (int) (output.length()-fullOffset)/sectorSize; + output.seek(shortOffset); + output.writeInt(offset); + output.write(200); + } + output.seek(fullOffset+sectorSize*offset); + //output.mark(sectorSize*sectorLength); + + DataOutputStream trueOutput = new DataOutputStream(Channels.newOutputStream(output.getChannel())); + + ChunkIO.save(chunk, trueOutput, IOContext.SAVE); + writeGenerationHint(chunk, trueOutput, server); + } + } // else if (currentFormat) } catch (IOException e) { e.printStackTrace(); @@ -214,18 +281,29 @@ public class TestWorldDiskIO { setRegionSize(formatNum); } else { setRegionSize(bestFormat); + + LOG.debug("Making new world with format {}", bestFormat); BufferedWriter bw; try { bw = new BufferedWriter(new FileWriter(format)); + + int bfClone = bestFormat; + + for (int i=0;i<4;i++) + { + bw.write(bfClone>>24); + LOG.debug(bfClone>>24); + bfClone = bfClone << 8; + } - bw.write( + /*bw.write( new char[] { - bestFormat / (256 * 256 * 256), - (bestFormat % 256) / (256 * 256), - (bestFormat % (256 * 256)) / (256), - bestFormat % (256 * 256 * 256) } - ); + (char) bestFormat / (256 * 256 * 256), + (char) (bestFormat % 256) / (256 * 256), + (char) (bestFormat % (256 * 256)) / (256), + (char) (bestFormat % (256 * 256 * 256)) } + );*/ bw.close(); } catch (IOException e) { @@ -280,11 +358,11 @@ public class TestWorldDiskIO { return null; } } else if (currentFormat == 1) { - Vec3i saveCoords = getRegionLoc(chunkPos); + Vec3i saveCoords = getRegion(chunkPos); Path path = SAVE_DIR.resolve( String.format( - "chunk_%+d_%+d_%+d" + extension, + "chunk_%d_%d_%d" + extension, saveCoords.x, saveCoords.y, saveCoords.z @@ -312,6 +390,50 @@ public class TestWorldDiskIO { chunkPos.z ); + return result; + } catch (Exception e) { + e.printStackTrace(); + LOG.debug( + "Could not load {} {} {}", + chunkPos.x, + chunkPos.y, + chunkPos.z + ); + return null; + } + } else if (currentFormat == 65536) { + Vec3i saveCoords = getRegion(chunkPos); + + Path path = SAVE_DIR.resolve( + String.format( + "%d_%d_%d" + extension, + saveCoords.x, + saveCoords.y, + saveCoords.z + ) + ); + + if (!Files.exists(path)) { + LOG.debug( + "Not found {} {} {}", + chunkPos.x, + chunkPos.y, + chunkPos.z + ); + + return null; + } + + try { + ChunkData result = loadRegion(path, chunkPos, world, server); + + LOG.debug( + "Loaded {} {} {}", + chunkPos.x, + chunkPos.y, + chunkPos.z + ); + return result; } catch (Exception e) { e.printStackTrace(); @@ -340,6 +462,33 @@ public class TestWorldDiskIO { return chunk; } } + + private static ChunkData loadRegion(Path path, Vec3i chunkPos, WorldData world, Server server) throws IOException, DecodingException + { + try ( + DataInputStream input = new DataInputStream( + new InflaterInputStream(new BufferedInputStream(Files.newInputStream(path))) + ) + ) { + Vec3i pos = getRegionLoc(chunkPos); + int shortOffset = (offsetBytes+1)*(pos.z+regionSize.z*(pos.y + regionSize.y*pos.x)); + int fullOffset = (offsetBytes+1)*(chunksPerRegion); + input.skipNBytes(shortOffset); + int offset = 0; + for (int i=0;i --> + From 254faca0a50eca608218ee176000e0ce2a8f6fea Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Thu, 5 Aug 2021 12:29:29 -0400 Subject: [PATCH 07/49] Better deletion -Makes new TestPlayerControls instance each time you enter a world -Some dynamic sizing of chunk data within region files. --- .../progressia/client/ClientProxy.java | 1 + .../progressia/test/LayerButtonTest.java | 2 ++ .../progressia/test/TestPlayerControls.java | 7 ++++++- .../progressia/test/TestWorldDiskIO.java | 19 +++++++++++++++++-- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java index 402c5e8..cd75d42 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java @@ -33,6 +33,7 @@ import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.server.ServerState; import ru.windcorp.progressia.test.TestContent; import ru.windcorp.progressia.test.TestMusicPlayer; +import ru.windcorp.progressia.test.TestPlayerControls; public class ClientProxy implements Proxy { diff --git a/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java b/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java index c6e5d00..6f829da 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java @@ -108,6 +108,8 @@ public class LayerButtonTest extends MenuLayer { ServerState.getInstance().shutdown("Safe Exit"); ServerState.setInstance(null); + + TestPlayerControls.resetInstance(); } }); diff --git a/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java b/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java index 80e2146..960a97e 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java +++ b/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java @@ -44,7 +44,7 @@ import ru.windcorp.progressia.server.ServerState; public class TestPlayerControls { - private static final TestPlayerControls INSTANCE = new TestPlayerControls(); + private static TestPlayerControls INSTANCE = new TestPlayerControls(); public static TestPlayerControls getInstance() { return INSTANCE; @@ -90,6 +90,11 @@ public class TestPlayerControls { private LayerTestGUI debugLayer = null; private Runnable updateCallback = null; + + public static void resetInstance() + { + INSTANCE = new TestPlayerControls(); + } public void applyPlayerControls() { if (ClientState.getInstance() == null || !ClientState.getInstance().isReady()) { diff --git a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java index e8b53e9..897ee83 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java @@ -39,6 +39,8 @@ import java.util.zip.InflaterInputStream; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import com.google.common.io.CountingOutputStream; + import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.state.IOContext; import ru.windcorp.progressia.common.world.ChunkData; @@ -231,15 +233,28 @@ public class TestWorldDiskIO { offset = (int) (output.length()-fullOffset)/sectorSize; output.seek(shortOffset); output.writeInt(offset); - output.write(200); + //output.write(200); } output.seek(fullOffset+sectorSize*offset); + + int bytestoWrite = output.readInt(); //output.mark(sectorSize*sectorLength); - DataOutputStream trueOutput = new DataOutputStream(Channels.newOutputStream(output.getChannel())); + DataOutputStream trueOutput = new DataOutputStream(Channels.newOutputStream(output.getChannel())); + CountingOutputStream countOutput = new CountingOutputStream(trueOutput); + //trueOutput. ChunkIO.save(chunk, trueOutput, IOContext.SAVE); writeGenerationHint(chunk, trueOutput, server); + + while (countOutput.getCount()%sectorSize != 0) { + countOutput.write(0); + } + + output.seek(shortOffset+offsetBytes); + output.write((int) countOutput.getCount()/sectorSize); + + countOutput.close(); } } // else if (currentFormat) From 8bc23acb61c706dad83ed5e8672bbbfa01a9ba67 Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Thu, 5 Aug 2021 13:39:42 -0400 Subject: [PATCH 08/49] idk changes so I can show OLEGSHA -changed number of index bytes from 4 to 3 -exposed some variables for help with debugger --- .../progressia/test/TestWorldDiskIO.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java index 897ee83..e22bc45 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java @@ -122,11 +122,16 @@ public class TestWorldDiskIO { regionSize = new Vec3i(16); chunksPerRegion = 16 * 16 * 16; currentFormat = 65536; - offsetBytes = 4; + offsetBytes = 3; extension = ".progressia_region"; break; } } + + private static void expand(int sectors) + { + + } public static void saveChunk(ChunkData chunk, Server server) { if (!ENABLE) @@ -219,6 +224,7 @@ public class TestWorldDiskIO { //LOG.debug(output.read()); if (output.read()<0) { + LOG.info("Making header"); output.writeChars("\0".repeat((offsetBytes+1)*chunksPerRegion)); } @@ -227,17 +233,19 @@ public class TestWorldDiskIO { int fullOffset = (offsetBytes+1)*(chunksPerRegion); output.seek(shortOffset); int offset = output.readInt(); - int sectorLength = output.read(); + int sectorLength = offset&255; + offset = offset >> 8; if (sectorLength == 0) { - offset = (int) (output.length()-fullOffset)/sectorSize; + int outputLen = (int) output.length(); + offset = (int) (outputLen-fullOffset)/sectorSize; output.seek(shortOffset); - output.writeInt(offset); + output.writeInt(offset<<8); //output.write(200); } output.seek(fullOffset+sectorSize*offset); - int bytestoWrite = output.readInt(); + //int bytestoWrite = output.readInt(); //output.mark(sectorSize*sectorLength); DataOutputStream trueOutput = new DataOutputStream(Channels.newOutputStream(output.getChannel())); @@ -252,6 +260,7 @@ public class TestWorldDiskIO { } output.seek(shortOffset+offsetBytes); + LOG.info(countOutput.getCount()); output.write((int) countOutput.getCount()/sectorSize); countOutput.close(); From 8167c40f6463c40be4860049f763459d5653a58b Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Thu, 5 Aug 2021 14:12:37 -0400 Subject: [PATCH 09/49] IDK these errors are weird -Changed the loading to fit the byte changes --- .../progressia/test/TestWorldDiskIO.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java index e22bc45..842e7c1 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java @@ -249,21 +249,21 @@ public class TestWorldDiskIO { //output.mark(sectorSize*sectorLength); DataOutputStream trueOutput = new DataOutputStream(Channels.newOutputStream(output.getChannel())); - CountingOutputStream countOutput = new CountingOutputStream(trueOutput); + //CountingOutputStream countOutput = new CountingOutputStream(trueOutput); //trueOutput. ChunkIO.save(chunk, trueOutput, IOContext.SAVE); writeGenerationHint(chunk, trueOutput, server); - while (countOutput.getCount()%sectorSize != 0) { - countOutput.write(0); + while (trueOutput.size()%sectorSize != 0) { + trueOutput.write(0); } output.seek(shortOffset+offsetBytes); - LOG.info(countOutput.getCount()); - output.write((int) countOutput.getCount()/sectorSize); + LOG.info(trueOutput.size()); + output.write((int) trueOutput.size()/sectorSize); - countOutput.close(); + trueOutput.close(); } } // else if (currentFormat) @@ -494,17 +494,19 @@ public class TestWorldDiskIO { new InflaterInputStream(new BufferedInputStream(Files.newInputStream(path))) ) ) { + LOG.info(path.toString()); Vec3i pos = getRegionLoc(chunkPos); int shortOffset = (offsetBytes+1)*(pos.z+regionSize.z*(pos.y + regionSize.y*pos.x)); int fullOffset = (offsetBytes+1)*(chunksPerRegion); input.skipNBytes(shortOffset); - int offset = 0; - for (int i=0;i Date: Fri, 6 Aug 2021 12:56:21 -0400 Subject: [PATCH 10/49] Trying to get it to work -Uses many streams to keep track of things -Fixed some bad things, still are a ton. --- .../progressia/test/TestWorldDiskIO.java | 53 +++++++++++-------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java index 842e7c1..8bed37a 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java @@ -238,30 +238,41 @@ public class TestWorldDiskIO { if (sectorLength == 0) { int outputLen = (int) output.length(); - offset = (int) (outputLen-fullOffset)/sectorSize; + offset = (int) (outputLen-fullOffset)/sectorSize+1; output.seek(shortOffset); output.writeInt(offset<<8); + output.seek(outputLen); + while (output.length()> 8; input.skipNBytes(fullOffset-shortOffset-offsetBytes-1); input.skipNBytes(sectorSize*offset); input.mark(sectorSize*sectorLength); - ChunkData chunk = ChunkIO.load(world, chunkPos, input, IOContext.SAVE); - readGenerationHint(chunk, input, server); + DataInputStream trueInput = new DataInputStream( + new InflaterInputStream(input)); + ChunkData chunk = ChunkIO.load(world, chunkPos, trueInput, IOContext.SAVE); + readGenerationHint(chunk, trueInput, server); return chunk; } } From 9c26418354e95db8f93bf47c598c4ef269b7b14e Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Wed, 18 Aug 2021 13:15:30 -0400 Subject: [PATCH 11/49] Well, it works now ig -Better file lengthening -Made temp files -Exchanged temp files for ByteArrayIn/OutputBuffers -Fixed loadRegion to actually read sector sizes --- .../progressia/test/TestWorldDiskIO.java | 55 ++++++++++++++----- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java index 8bed37a..cbb294b 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java @@ -21,6 +21,8 @@ package ru.windcorp.progressia.test; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; @@ -52,7 +54,7 @@ import ru.windcorp.progressia.server.Server; public class TestWorldDiskIO { private static Path SAVE_DIR = Paths.get("tmp_world"); - private static String formatFile = "world.format"; + private static final String formatFile = "world.format"; private static final Logger LOG = LogManager.getLogger("TestWorldDiskIO"); private static final boolean ENABLE = true; @@ -218,6 +220,12 @@ public class TestWorldDiskIO { ) ); + /*if (!dosave) + { + return; + } + dosave = false;*/ + try ( RandomAccessFile output = new RandomAccessFile(path.toFile(), "rw") ) { @@ -242,27 +250,30 @@ public class TestWorldDiskIO { output.seek(shortOffset); output.writeInt(offset<<8); output.seek(outputLen); - while (output.length()> 8; + int sectorLength = input.read(); input.skipNBytes(fullOffset-shortOffset-offsetBytes-1); input.skipNBytes(sectorSize*offset); - input.mark(sectorSize*sectorLength); + + LOG.info("Read {} sectors", sectorLength); + + byte tempData[] = input.readNBytes(sectorSize*sectorLength); + DataInputStream trueInput = new DataInputStream( - new InflaterInputStream(input)); + new InflaterInputStream(new BufferedInputStream(new ByteArrayInputStream(tempData)))); ChunkData chunk = ChunkIO.load(world, chunkPos, trueInput, IOContext.SAVE); readGenerationHint(chunk, trueInput, server); + trueInput.close(); return chunk; } } From b7dcbb0f3019dbad848e12dcfc5209973aec91b1 Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Wed, 18 Aug 2021 13:21:54 -0400 Subject: [PATCH 12/49] Fixing stuff -Got rid of some annoying logging -Format --- .../java/ru/windcorp/jputil/ArrayUtil.java | 2 +- .../java/ru/windcorp/jputil/CSVWriter.java | 2 +- .../ru/windcorp/jputil/PrimitiveUtil.java | 2 +- .../java/ru/windcorp/jputil/SyncStreams.java | 2 +- .../ru/windcorp/jputil/SyntaxException.java | 2 +- .../jputil/chars/CharArrayIterator.java | 2 +- .../windcorp/jputil/chars/CharConsumer.java | 2 +- .../windcorp/jputil/chars/CharConsumers.java | 2 +- .../windcorp/jputil/chars/CharPredicate.java | 2 +- .../windcorp/jputil/chars/CharSupplier.java | 2 +- .../jputil/chars/EscapeException.java | 2 +- .../ru/windcorp/jputil/chars/Escaper.java | 2 +- .../jputil/chars/FancyCharacterIterator.java | 2 +- .../jputil/chars/IndentedStringBuilder.java | 2 +- .../ru/windcorp/jputil/chars/StringUtil.java | 2 +- .../chars/UncheckedEscapeException.java | 2 +- .../ru/windcorp/jputil/chars/WordReader.java | 2 +- .../chars/reader/AbstractCharReader.java | 2 +- .../jputil/chars/reader/ArrayCharReader.java | 2 +- .../chars/reader/BufferedCharReader.java | 2 +- .../jputil/chars/reader/CharReader.java | 2 +- .../jputil/chars/reader/CharReaders.java | 2 +- .../jputil/chars/reader/ReaderCharReader.java | 2 +- .../jputil/chars/reader/StringCharReader.java | 2 +- .../jputil/functions/FloatSupplier.java | 2 +- .../jputil/functions/ThrowingBiConsumer.java | 2 +- .../jputil/functions/ThrowingConsumer.java | 2 +- .../jputil/functions/ThrowingFunction.java | 2 +- .../jputil/functions/ThrowingRunnable.java | 2 +- .../jputil/functions/ThrowingSupplier.java | 2 +- .../jputil/iterators/ArrayIterator.java | 2 +- .../jputil/iterators/FunctionIterator.java | 2 +- .../jputil/iterators/PeekingIterator.java | 2 +- .../jputil/iterators/RangeIterator.java | 2 +- .../windcorp/jputil/iterators/Reiterator.java | 2 +- .../selectors/AbstractSelectorOperator.java | 2 +- .../selectors/NamedParameterizedSelector.java | 2 +- .../jputil/selectors/NamedSelector.java | 2 +- .../jputil/selectors/OperatorAnd.java | 2 +- .../jputil/selectors/OperatorExclude.java | 2 +- .../jputil/selectors/OperatorNot.java | 2 +- .../windcorp/jputil/selectors/OperatorOr.java | 2 +- .../jputil/selectors/OperatorXor.java | 2 +- .../jputil/selectors/PredicateWrapper.java | 2 +- .../windcorp/jputil/selectors/Selector.java | 2 +- .../jputil/selectors/SelectorOperator.java | 2 +- .../jputil/selectors/SelectorSystem.java | 2 +- .../ru/windcorp/progressia/Progressia.java | 2 +- .../progressia/ProgressiaLauncher.java | 9 +- .../java/ru/windcorp/progressia/Proxy.java | 2 +- .../ru/windcorp/progressia/client/Client.java | 2 +- .../progressia/client/ClientProxy.java | 19 +- .../progressia/client/ClientState.java | 48 ++-- .../client/ProgressiaClientMain.java | 2 +- .../progressia/client/audio/AudioFormat.java | 2 +- .../progressia/client/audio/AudioManager.java | 2 +- .../client/audio/AudioRegistry.java | 4 +- .../progressia/client/audio/AudioSystem.java | 2 +- .../progressia/client/audio/Music.java | 10 +- .../progressia/client/audio/Sound.java | 14 +- .../client/audio/backend/AudioReader.java | 2 +- .../client/audio/backend/Listener.java | 2 +- .../client/audio/backend/SoundType.java | 4 +- .../client/audio/backend/Speaker.java | 2 +- .../comms/DefaultClientCommsListener.java | 2 +- .../client/comms/ServerCommsChannel.java | 2 +- .../client/comms/controls/ControlTrigger.java | 2 +- .../controls/ControlTriggerInputBased.java | 2 +- .../comms/controls/ControlTriggerLambda.java | 2 +- .../controls/ControlTriggerLocalLambda.java | 2 +- .../controls/ControlTriggerRegistry.java | 2 +- .../comms/controls/ControlTriggers.java | 8 +- .../comms/controls/InputBasedControls.java | 2 +- .../client/comms/localhost/LocalClient.java | 2 +- .../localhost/LocalServerCommsChannel.java | 2 +- .../progressia/client/graphics/Colors.java | 4 +- .../progressia/client/graphics/GUI.java | 16 +- .../progressia/client/graphics/Layer.java | 16 +- .../client/graphics/backend/FaceCulling.java | 2 +- .../graphics/backend/GraphicsBackend.java | 18 +- .../graphics/backend/GraphicsInterface.java | 6 +- .../client/graphics/backend/InputHandler.java | 2 +- .../client/graphics/backend/InputTracker.java | 2 +- .../graphics/backend/LWJGLInitializer.java | 4 +- .../graphics/backend/OpenGLObjectTracker.java | 2 +- .../graphics/backend/RenderTaskQueue.java | 2 +- .../client/graphics/backend/RenderThread.java | 2 +- .../client/graphics/backend/Usage.java | 2 +- .../graphics/backend/VertexBufferObject.java | 2 +- .../backend/shaders/CombinedShader.java | 2 +- .../graphics/backend/shaders/Program.java | 2 +- .../graphics/backend/shaders/Shader.java | 2 +- .../backend/shaders/attributes/Attribute.java | 2 +- .../attributes/AttributeVertexArray.java | 2 +- .../backend/shaders/uniforms/Uniform.java | 2 +- .../shaders/uniforms/Uniform1Float.java | 2 +- .../backend/shaders/uniforms/Uniform1Int.java | 2 +- .../shaders/uniforms/Uniform2Float.java | 2 +- .../backend/shaders/uniforms/Uniform2Int.java | 2 +- .../shaders/uniforms/Uniform2Matrix.java | 2 +- .../shaders/uniforms/Uniform3Float.java | 2 +- .../backend/shaders/uniforms/Uniform3Int.java | 2 +- .../shaders/uniforms/Uniform3Matrix.java | 2 +- .../shaders/uniforms/Uniform4Float.java | 2 +- .../backend/shaders/uniforms/Uniform4Int.java | 2 +- .../shaders/uniforms/Uniform4Matrix.java | 2 +- .../graphics/flat/AssembledFlatLayer.java | 2 +- .../flat/AssembledFlatRenderHelper.java | 2 +- .../flat/DefaultFlatRenderHelper.java | 2 +- .../client/graphics/flat/FlatGraphics.java | 2 +- .../graphics/flat/FlatRenderHelper.java | 2 +- .../graphics/flat/FlatRenderProgram.java | 2 +- .../progressia/client/graphics/flat/Mask.java | 2 +- .../client/graphics/flat/MaskStack.java | 2 +- .../client/graphics/flat/RenderTarget.java | 4 +- .../client/graphics/flat/TransformedMask.java | 2 +- .../progressia/client/graphics/font/Font.java | 2 +- .../client/graphics/font/GNUUnifont.java | 2 +- .../graphics/font/GNUUnifontLoader.java | 2 +- .../client/graphics/font/SpriteTypeface.java | 2 +- .../client/graphics/font/Typeface.java | 2 +- .../client/graphics/font/Typefaces.java | 2 +- .../client/graphics/gui/BasicButton.java | 37 ++- .../client/graphics/gui/Button.java | 18 +- .../client/graphics/gui/Checkbox.java | 44 ++-- .../client/graphics/gui/Component.java | 14 +- .../client/graphics/gui/DynamicLabel.java | 2 +- .../client/graphics/gui/GUILayer.java | 2 +- .../progressia/client/graphics/gui/Group.java | 2 +- .../progressia/client/graphics/gui/Label.java | 4 +- .../client/graphics/gui/Layout.java | 2 +- .../progressia/client/graphics/gui/Panel.java | 14 +- .../client/graphics/gui/RadioButton.java | 79 +++--- .../client/graphics/gui/RadioButtonGroup.java | 45 ++-- .../graphics/gui/event/ButtonEvent.java | 10 +- .../graphics/gui/event/ChildAddedEvent.java | 2 +- .../client/graphics/gui/event/ChildEvent.java | 2 +- .../graphics/gui/event/ChildRemovedEvent.java | 2 +- .../graphics/gui/event/ComponentEvent.java | 2 +- .../graphics/gui/event/EnableEvent.java | 2 +- .../client/graphics/gui/event/FocusEvent.java | 2 +- .../graphics/gui/event/HierarchyEvent.java | 2 +- .../client/graphics/gui/event/HoverEvent.java | 2 +- .../gui/event/ParentChangedEvent.java | 2 +- .../graphics/gui/layout/LayoutAlign.java | 2 +- .../gui/layout/LayoutBorderHorizontal.java | 2 +- .../gui/layout/LayoutBorderVertical.java | 2 +- .../graphics/gui/layout/LayoutFill.java | 4 +- .../graphics/gui/layout/LayoutGrid.java | 8 +- .../graphics/gui/layout/LayoutHorizontal.java | 2 +- .../graphics/gui/layout/LayoutVertical.java | 2 +- .../client/graphics/gui/menu/MenuLayer.java | 36 +-- .../client/graphics/input/CursorEvent.java | 2 +- .../graphics/input/CursorMoveEvent.java | 2 +- .../graphics/input/FrameResizeEvent.java | 2 +- .../client/graphics/input/InputEvent.java | 2 +- .../client/graphics/input/KeyEvent.java | 2 +- .../client/graphics/input/KeyMatcher.java | 2 +- .../client/graphics/input/Keys.java | 2 +- .../client/graphics/input/WheelEvent.java | 2 +- .../graphics/input/WheelScrollEvent.java | 2 +- .../client/graphics/input/bus/Input.java | 2 +- .../client/graphics/input/bus/InputBus.java | 2 +- .../graphics/input/bus/InputListener.java | 2 +- .../graphics/model/BlockFaceVectors.java | 2 +- .../client/graphics/model/DynamicModel.java | 2 +- .../client/graphics/model/EmptyModel.java | 2 +- .../client/graphics/model/Face.java | 2 +- .../client/graphics/model/FaceGroup.java | 2 +- .../client/graphics/model/Faces.java | 2 +- .../client/graphics/model/LambdaModel.java | 2 +- .../client/graphics/model/Model.java | 2 +- .../client/graphics/model/Renderable.java | 2 +- .../client/graphics/model/Shape.java | 2 +- .../graphics/model/ShapeRenderHelper.java | 2 +- .../graphics/model/ShapeRenderProgram.java | 2 +- .../client/graphics/model/Shapes.java | 2 +- .../client/graphics/model/StaticModel.java | 4 +- .../client/graphics/texture/Atlases.java | 2 +- .../graphics/texture/ComplexTexture.java | 2 +- .../graphics/texture/SimpleTexture.java | 2 +- .../graphics/texture/SimpleTextures.java | 2 +- .../client/graphics/texture/Sprite.java | 2 +- .../client/graphics/texture/Texture.java | 2 +- .../client/graphics/texture/TextureData.java | 2 +- .../graphics/texture/TextureDataEditor.java | 2 +- .../graphics/texture/TextureLoader.java | 2 +- .../graphics/texture/TexturePrimitive.java | 2 +- .../graphics/texture/TextureSettings.java | 2 +- .../client/graphics/texture/TextureUtil.java | 2 +- .../client/graphics/world/Camera.java | 2 +- .../client/graphics/world/EntityAnchor.java | 2 +- .../client/graphics/world/LayerWorld.java | 4 +- .../client/graphics/world/LocalPlayer.java | 2 +- .../client/graphics/world/Selection.java | 2 +- .../graphics/world/WorldRenderHelper.java | 2 +- .../graphics/world/WorldRenderProgram.java | 2 +- .../client/localization/LocaleListener.java | 2 +- .../client/localization/Localizer.java | 2 +- .../client/localization/MutableString.java | 2 +- .../localization/MutableStringConcat.java | 2 +- .../localization/MutableStringFormatter.java | 2 +- .../localization/MutableStringFunc.java | 2 +- .../localization/MutableStringLocalized.java | 2 +- .../localization/MutableStringParented.java | 2 +- .../client/localization/Parser.java | 2 +- .../progressia/client/world/ChunkRender.java | 2 +- .../client/world/ChunkRenderModel.java | 45 ++-- .../client/world/ChunkUpdateListener.java | 18 +- .../progressia/client/world/WorldRender.java | 2 +- .../client/world/block/BlockRender.java | 2 +- .../client/world/block/BlockRenderNone.java | 2 +- .../world/block/BlockRenderOpaqueCube.java | 2 +- .../world/block/BlockRenderRegistry.java | 2 +- .../world/block/BlockRenderTexturedCube.java | 30 ++- .../block/BlockRenderTransparentCube.java | 2 +- .../cro/ChunkRenderOptimizerRegistry.java | 6 +- .../client/world/entity/EntityRender.java | 2 +- .../world/entity/EntityRenderRegistry.java | 2 +- .../client/world/entity/EntityRenderable.java | 2 +- .../client/world/entity/HumanoidModel.java | 2 +- .../client/world/entity/NPedModel.java | 2 +- .../client/world/entity/QuadripedModel.java | 2 +- .../client/world/tile/TileRender.java | 2 +- .../client/world/tile/TileRenderGrass.java | 2 +- .../client/world/tile/TileRenderNone.java | 4 +- .../world/tile/TileRenderOpaqueSurface.java | 2 +- .../client/world/tile/TileRenderRegistry.java | 2 +- .../client/world/tile/TileRenderStack.java | 2 +- .../client/world/tile/TileRenderSurface.java | 22 +- .../tile/TileRenderTransparentSurface.java | 2 +- .../ru/windcorp/progressia/common/Units.java | 2 +- .../progressia/common/collision/AABB.java | 2 +- .../progressia/common/collision/AABBoid.java | 2 +- .../common/collision/Collideable.java | 2 +- .../common/collision/CollisionModel.java | 2 +- .../collision/CollisionPathComputer.java | 2 +- .../collision/CompoundCollisionModel.java | 2 +- .../collision/TransformedCollisionModel.java | 2 +- .../common/collision/TranslatedAABB.java | 2 +- .../progressia/common/collision/Wall.java | 2 +- .../collision/WorldCollisionHelper.java | 2 +- .../collision/colliders/AABBoidCollider.java | 2 +- .../AnythingWithCompoundCollider.java | 2 +- .../common/collision/colliders/Collider.java | 2 +- .../progressia/common/comms/CommsChannel.java | 2 +- .../common/comms/CommsListener.java | 2 +- .../common/comms/controls/ControlData.java | 2 +- .../comms/controls/ControlDataRegistry.java | 2 +- .../common/comms/controls/PacketControl.java | 2 +- .../common/comms/packets/Packet.java | 2 +- .../common/hacks/GuavaEventBusHijacker.java | 2 +- .../progressia/common/resource/Resource.java | 6 +- .../common/resource/ResourceManager.java | 6 +- .../common/resource/ResourceReader.java | 2 +- .../state/AbstractStatefulObjectLayout.java | 2 +- .../common/state/HashMapStateStorage.java | 2 +- .../progressia/common/state/IOContext.java | 2 +- .../state/InspectingStatefulObjectLayout.java | 2 +- .../common/state/IntStateField.java | 2 +- .../common/state/OptimizedStateStorage.java | 2 +- .../state/OptimizedStatefulObjectLayout.java | 2 +- .../common/state/PrimitiveCounters.java | 2 +- .../progressia/common/state/StateChanger.java | 2 +- .../progressia/common/state/StateField.java | 2 +- .../common/state/StateFieldBuilder.java | 2 +- .../progressia/common/state/StateStorage.java | 2 +- .../common/state/StatefulObject.java | 2 +- .../common/state/StatefulObjectLayout.java | 2 +- .../common/state/StatefulObjectRegistry.java | 2 +- .../progressia/common/util/BinUtil.java | 2 +- .../common/util/ByteBufferInputStream.java | 2 +- .../common/util/ByteBufferOutputStream.java | 2 +- .../common/util/CoordinatePacker.java | 2 +- .../progressia/common/util/DataBuffer.java | 2 +- .../progressia/common/util/FloatMathUtil.java | 2 +- .../common/util/LowOverheadCache.java | 2 +- .../progressia/common/util/Matrices.java | 2 +- .../progressia/common/util/MultiLOC.java | 2 +- .../progressia/common/util/Named.java | 2 +- .../common/util/SizeLimitedList.java | 2 +- .../progressia/common/util/StashingStack.java | 2 +- .../progressia/common/util/TaskQueue.java | 2 +- .../progressia/common/util/VectorUtil.java | 2 +- .../progressia/common/util/Vectors.java | 2 +- .../common/util/crash/Analyzer.java | 2 +- .../common/util/crash/ContextProvider.java | 2 +- .../common/util/crash/CrashReports.java | 2 +- .../common/util/crash/ReportingEventBus.java | 2 +- .../crash/analyzers/OutOfMemoryAnalyzer.java | 2 +- .../crash/providers/ArgsContextProvider.java | 2 +- .../providers/JavaVersionContextProvider.java | 2 +- .../providers/LanguageContextProvider.java | 2 +- .../crash/providers/OSContextProvider.java | 2 +- .../providers/OpenALContextProvider.java | 2 +- .../crash/providers/RAMContextProvider.java | 2 +- .../common/util/dynstr/DoubleFlusher.java | 2 +- .../common/util/dynstr/DynamicString.java | 2 +- .../common/util/dynstr/DynamicStrings.java | 2 +- .../common/util/dynstr/FloatFlusher.java | 2 +- .../common/util/dynstr/IntFlusher.java | 2 +- .../util/namespaces/IllegalIdException.java | 2 +- .../common/util/namespaces/Namespaced.java | 2 +- .../namespaces/NamespacedFactoryRegistry.java | 2 +- .../NamespacedInstanceRegistry.java | 2 +- .../util/namespaces/NamespacedUtil.java | 2 +- .../progressia/common/world/BlockRay.java | 2 +- .../progressia/common/world/ChunkData.java | 2 +- .../common/world/ChunkDataListener.java | 2 +- .../common/world/ChunkDataListeners.java | 2 +- .../progressia/common/world/Coordinates.java | 4 +- .../common/world/DecodingException.java | 2 +- .../world/IllegalCoordinatesException.java | 2 +- .../common/world/PacketAffectChunk.java | 2 +- .../common/world/PacketAffectWorld.java | 2 +- .../common/world/PacketRevokeChunk.java | 2 +- .../common/world/PacketSendChunk.java | 2 +- .../common/world/PacketSetLocalPlayer.java | 2 +- .../progressia/common/world/PlayerData.java | 2 +- .../progressia/common/world/WorldData.java | 2 +- .../common/world/WorldDataListener.java | 2 +- .../common/world/block/BlockData.java | 2 +- .../common/world/block/BlockDataRegistry.java | 2 +- .../common/world/block/BlockFace.java | 2 +- .../common/world/block/BlockRelation.java | 4 +- .../common/world/block/PacketAffectBlock.java | 2 +- .../common/world/block/PacketSetBlock.java | 2 +- .../common/world/entity/EntityData.java | 2 +- .../world/entity/EntityDataRegistry.java | 2 +- .../world/entity/PacketAffectEntity.java | 2 +- .../world/entity/PacketChangeEntity.java | 2 +- .../world/entity/PacketRevokeEntity.java | 2 +- .../common/world/entity/PacketSendEntity.java | 2 +- .../common/world/generic/ChunkMap.java | 2 +- .../common/world/generic/ChunkSet.java | 2 +- .../common/world/generic/ChunkSets.java | 2 +- .../common/world/generic/GenericBlock.java | 2 +- .../common/world/generic/GenericChunk.java | 53 +++-- .../common/world/generic/GenericEntity.java | 2 +- .../common/world/generic/GenericTile.java | 2 +- .../world/generic/GenericTileStack.java | 2 +- .../common/world/generic/GenericWorld.java | 2 +- .../world/generic/LongBasedChunkMap.java | 2 +- .../world/generic/LongBasedChunkSet.java | 2 +- .../common/world/io/ChunkCodec.java | 2 +- .../progressia/common/world/io/ChunkIO.java | 2 +- .../common/world/tile/PacketAddTile.java | 2 +- .../common/world/tile/PacketAffectTile.java | 2 +- .../common/world/tile/PacketRemoveTile.java | 2 +- .../common/world/tile/TileData.java | 2 +- .../common/world/tile/TileDataRegistry.java | 2 +- .../common/world/tile/TileDataStack.java | 2 +- .../common/world/tile/TileReference.java | 2 +- .../world/tile/TileStackIsFullException.java | 2 +- .../progressia/server/ChunkLoader.java | 2 +- .../progressia/server/ChunkManager.java | 78 +++--- .../progressia/server/EntityManager.java | 2 +- .../ru/windcorp/progressia/server/Player.java | 2 +- .../progressia/server/PlayerManager.java | 7 +- .../progressia/server/ServerState.java | 2 +- .../progressia/server/ServerThread.java | 11 +- .../progressia/server/TickingSettings.java | 2 +- .../progressia/server/comms/Client.java | 2 +- .../progressia/server/comms/ClientChat.java | 2 +- .../server/comms/ClientManager.java | 2 +- .../progressia/server/comms/ClientPlayer.java | 2 +- .../comms/DefaultServerCommsListener.java | 2 +- .../server/comms/controls/ControlLogic.java | 2 +- .../comms/controls/ControlLogicRegistry.java | 2 +- .../progressia/server/world/ChunkLogic.java | 2 +- .../server/world/ChunkTickContext.java | 2 +- .../server/world/TickAndUpdateUtil.java | 2 +- .../progressia/server/world/TickContext.java | 2 +- .../server/world/TickContextMutable.java | 2 +- .../server/world/UpdateTriggerer.java | 2 +- .../progressia/server/world/WorldLogic.java | 2 +- .../server/world/block/BlockLogic.java | 2 +- .../world/block/BlockLogicRegistry.java | 2 +- .../server/world/block/BlockTickContext.java | 2 +- .../server/world/block/TickableBlock.java | 2 +- .../server/world/block/UpdateableBlock.java | 2 +- .../server/world/entity/EntityLogic.java | 2 +- .../world/entity/EntityLogicRegistry.java | 2 +- .../generation/AbstractWorldGenerator.java | 2 +- .../world/generation/WorldGenerator.java | 2 +- .../server/world/tasks/AddTile.java | 2 +- .../world/tasks/BlockTriggeredUpdate.java | 2 +- .../server/world/tasks/CachedBlockChange.java | 2 +- .../server/world/tasks/CachedChange.java | 2 +- .../server/world/tasks/CachedChunkChange.java | 2 +- .../server/world/tasks/CachedEvaluation.java | 2 +- .../server/world/tasks/CachedTileChange.java | 2 +- .../server/world/tasks/CachedWorldChange.java | 2 +- .../server/world/tasks/ChangeEntity.java | 2 +- .../server/world/tasks/RemoveTile.java | 2 +- .../server/world/tasks/SetBlock.java | 2 +- .../server/world/tasks/StateChange.java | 2 +- .../server/world/tasks/TickChunk.java | 2 +- .../server/world/tasks/TickEntitiesTask.java | 2 +- .../world/tasks/TileTriggeredUpdate.java | 2 +- .../server/world/tasks/WorldAccessor.java | 2 +- .../server/world/ticking/Change.java | 2 +- .../world/ticking/DevilInvasionException.java | 2 +- .../server/world/ticking/Evaluation.java | 2 +- .../server/world/ticking/Ticker.java | 5 +- .../world/ticking/TickerCoordinator.java | 8 +- .../server/world/ticking/TickerTask.java | 2 +- .../server/world/ticking/TickingPolicy.java | 2 +- .../server/world/tile/HangingTileLogic.java | 2 +- .../server/world/tile/TSTickContext.java | 2 +- .../server/world/tile/TickableTile.java | 2 +- .../server/world/tile/TileLogic.java | 2 +- .../server/world/tile/TileLogicRegistry.java | 2 +- .../server/world/tile/TileLogicStack.java | 2 +- .../server/world/tile/TileTickContext.java | 2 +- .../server/world/tile/UpdateableTile.java | 2 +- .../test/CollisionModelRenderer.java | 2 +- .../test/ControlBreakBlockData.java | 2 +- .../test/ControlPlaceBlockData.java | 2 +- .../progressia/test/ControlPlaceTileData.java | 2 +- .../windcorp/progressia/test/LayerAbout.java | 2 +- .../progressia/test/LayerButtonTest.java | 73 +++--- .../progressia/test/LayerTestGUI.java | 2 +- .../progressia/test/LayerTestText.java | 16 +- .../windcorp/progressia/test/LayerTestUI.java | 2 +- .../windcorp/progressia/test/LayerTitle.java | 25 +- .../progressia/test/TestBlockLogicAir.java | 2 +- .../progressia/test/TestBlockLogicGlass.java | 2 +- .../progressia/test/TestChunkCodec.java | 2 +- .../windcorp/progressia/test/TestContent.java | 4 +- .../progressia/test/TestEntityDataStatie.java | 2 +- .../test/TestEntityLogicStatie.java | 2 +- .../test/TestEntityRenderHuman.java | 2 +- .../test/TestEntityRenderJavapony.java | 2 +- .../test/TestEntityRenderStatie.java | 2 +- .../progressia/test/TestMusicPlayer.java | 55 ++--- .../progressia/test/TestPlayerControls.java | 9 +- .../progressia/test/TestTileLogicGrass.java | 2 +- .../progressia/test/TestWorldDiskIO.java | 225 +++++++++--------- .../test/gen/TestTerrainGenerator.java | 2 +- .../test/gen/TestWorldGenerator.java | 2 +- 441 files changed, 1011 insertions(+), 986 deletions(-) diff --git a/src/main/java/ru/windcorp/jputil/ArrayUtil.java b/src/main/java/ru/windcorp/jputil/ArrayUtil.java index 4c57314..65a9c15 100644 --- a/src/main/java/ru/windcorp/jputil/ArrayUtil.java +++ b/src/main/java/ru/windcorp/jputil/ArrayUtil.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil; import java.lang.reflect.Array; diff --git a/src/main/java/ru/windcorp/jputil/CSVWriter.java b/src/main/java/ru/windcorp/jputil/CSVWriter.java index 57ddec0..b74d88c 100644 --- a/src/main/java/ru/windcorp/jputil/CSVWriter.java +++ b/src/main/java/ru/windcorp/jputil/CSVWriter.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil; import java.io.OutputStream; diff --git a/src/main/java/ru/windcorp/jputil/PrimitiveUtil.java b/src/main/java/ru/windcorp/jputil/PrimitiveUtil.java index 7579413..4c475f5 100644 --- a/src/main/java/ru/windcorp/jputil/PrimitiveUtil.java +++ b/src/main/java/ru/windcorp/jputil/PrimitiveUtil.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil; import java.util.HashMap; diff --git a/src/main/java/ru/windcorp/jputil/SyncStreams.java b/src/main/java/ru/windcorp/jputil/SyncStreams.java index 9b2bc3a..f26ce1f 100644 --- a/src/main/java/ru/windcorp/jputil/SyncStreams.java +++ b/src/main/java/ru/windcorp/jputil/SyncStreams.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil; import java.util.function.*; diff --git a/src/main/java/ru/windcorp/jputil/SyntaxException.java b/src/main/java/ru/windcorp/jputil/SyntaxException.java index 02cc3c4..8fdb710 100644 --- a/src/main/java/ru/windcorp/jputil/SyntaxException.java +++ b/src/main/java/ru/windcorp/jputil/SyntaxException.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil; public class SyntaxException extends Exception { diff --git a/src/main/java/ru/windcorp/jputil/chars/CharArrayIterator.java b/src/main/java/ru/windcorp/jputil/chars/CharArrayIterator.java index be0940d..7af29de 100644 --- a/src/main/java/ru/windcorp/jputil/chars/CharArrayIterator.java +++ b/src/main/java/ru/windcorp/jputil/chars/CharArrayIterator.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars; import java.text.CharacterIterator; diff --git a/src/main/java/ru/windcorp/jputil/chars/CharConsumer.java b/src/main/java/ru/windcorp/jputil/chars/CharConsumer.java index 7b68bb1..55448b0 100644 --- a/src/main/java/ru/windcorp/jputil/chars/CharConsumer.java +++ b/src/main/java/ru/windcorp/jputil/chars/CharConsumer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars; import java.util.function.IntConsumer; diff --git a/src/main/java/ru/windcorp/jputil/chars/CharConsumers.java b/src/main/java/ru/windcorp/jputil/chars/CharConsumers.java index 1ac7973..12a518d 100644 --- a/src/main/java/ru/windcorp/jputil/chars/CharConsumers.java +++ b/src/main/java/ru/windcorp/jputil/chars/CharConsumers.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars; import java.util.Objects; diff --git a/src/main/java/ru/windcorp/jputil/chars/CharPredicate.java b/src/main/java/ru/windcorp/jputil/chars/CharPredicate.java index 03ded02..c02beed 100644 --- a/src/main/java/ru/windcorp/jputil/chars/CharPredicate.java +++ b/src/main/java/ru/windcorp/jputil/chars/CharPredicate.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars; import java.util.Arrays; diff --git a/src/main/java/ru/windcorp/jputil/chars/CharSupplier.java b/src/main/java/ru/windcorp/jputil/chars/CharSupplier.java index 0743d79..2a9749b 100644 --- a/src/main/java/ru/windcorp/jputil/chars/CharSupplier.java +++ b/src/main/java/ru/windcorp/jputil/chars/CharSupplier.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars; import java.util.function.IntSupplier; diff --git a/src/main/java/ru/windcorp/jputil/chars/EscapeException.java b/src/main/java/ru/windcorp/jputil/chars/EscapeException.java index 935f72f..544c50f 100644 --- a/src/main/java/ru/windcorp/jputil/chars/EscapeException.java +++ b/src/main/java/ru/windcorp/jputil/chars/EscapeException.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars; public class EscapeException extends Exception { diff --git a/src/main/java/ru/windcorp/jputil/chars/Escaper.java b/src/main/java/ru/windcorp/jputil/chars/Escaper.java index f19f6c7..1a65521 100644 --- a/src/main/java/ru/windcorp/jputil/chars/Escaper.java +++ b/src/main/java/ru/windcorp/jputil/chars/Escaper.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars; import java.text.CharacterIterator; diff --git a/src/main/java/ru/windcorp/jputil/chars/FancyCharacterIterator.java b/src/main/java/ru/windcorp/jputil/chars/FancyCharacterIterator.java index 183b672..1453f69 100644 --- a/src/main/java/ru/windcorp/jputil/chars/FancyCharacterIterator.java +++ b/src/main/java/ru/windcorp/jputil/chars/FancyCharacterIterator.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars; import java.text.CharacterIterator; diff --git a/src/main/java/ru/windcorp/jputil/chars/IndentedStringBuilder.java b/src/main/java/ru/windcorp/jputil/chars/IndentedStringBuilder.java index 92ba836..21afc6f 100644 --- a/src/main/java/ru/windcorp/jputil/chars/IndentedStringBuilder.java +++ b/src/main/java/ru/windcorp/jputil/chars/IndentedStringBuilder.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars; public class IndentedStringBuilder { diff --git a/src/main/java/ru/windcorp/jputil/chars/StringUtil.java b/src/main/java/ru/windcorp/jputil/chars/StringUtil.java index f08018a..92a6e27 100644 --- a/src/main/java/ru/windcorp/jputil/chars/StringUtil.java +++ b/src/main/java/ru/windcorp/jputil/chars/StringUtil.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars; import java.io.IOException; diff --git a/src/main/java/ru/windcorp/jputil/chars/UncheckedEscapeException.java b/src/main/java/ru/windcorp/jputil/chars/UncheckedEscapeException.java index 33717ee..66b7002 100644 --- a/src/main/java/ru/windcorp/jputil/chars/UncheckedEscapeException.java +++ b/src/main/java/ru/windcorp/jputil/chars/UncheckedEscapeException.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars; public class UncheckedEscapeException extends RuntimeException { diff --git a/src/main/java/ru/windcorp/jputil/chars/WordReader.java b/src/main/java/ru/windcorp/jputil/chars/WordReader.java index 22d6969..04dc5b6 100644 --- a/src/main/java/ru/windcorp/jputil/chars/WordReader.java +++ b/src/main/java/ru/windcorp/jputil/chars/WordReader.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars; import java.io.IOException; diff --git a/src/main/java/ru/windcorp/jputil/chars/reader/AbstractCharReader.java b/src/main/java/ru/windcorp/jputil/chars/reader/AbstractCharReader.java index d31e092..79aa679 100644 --- a/src/main/java/ru/windcorp/jputil/chars/reader/AbstractCharReader.java +++ b/src/main/java/ru/windcorp/jputil/chars/reader/AbstractCharReader.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars.reader; /** diff --git a/src/main/java/ru/windcorp/jputil/chars/reader/ArrayCharReader.java b/src/main/java/ru/windcorp/jputil/chars/reader/ArrayCharReader.java index f12f590..09f5e6c 100644 --- a/src/main/java/ru/windcorp/jputil/chars/reader/ArrayCharReader.java +++ b/src/main/java/ru/windcorp/jputil/chars/reader/ArrayCharReader.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars.reader; import java.util.Objects; diff --git a/src/main/java/ru/windcorp/jputil/chars/reader/BufferedCharReader.java b/src/main/java/ru/windcorp/jputil/chars/reader/BufferedCharReader.java index 83ae6b2..919a7c0 100644 --- a/src/main/java/ru/windcorp/jputil/chars/reader/BufferedCharReader.java +++ b/src/main/java/ru/windcorp/jputil/chars/reader/BufferedCharReader.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars.reader; /** diff --git a/src/main/java/ru/windcorp/jputil/chars/reader/CharReader.java b/src/main/java/ru/windcorp/jputil/chars/reader/CharReader.java index 147daf3..5623598 100644 --- a/src/main/java/ru/windcorp/jputil/chars/reader/CharReader.java +++ b/src/main/java/ru/windcorp/jputil/chars/reader/CharReader.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars.reader; import java.io.IOException; diff --git a/src/main/java/ru/windcorp/jputil/chars/reader/CharReaders.java b/src/main/java/ru/windcorp/jputil/chars/reader/CharReaders.java index a181dbf..d6978a0 100644 --- a/src/main/java/ru/windcorp/jputil/chars/reader/CharReaders.java +++ b/src/main/java/ru/windcorp/jputil/chars/reader/CharReaders.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars.reader; import java.io.InputStream; diff --git a/src/main/java/ru/windcorp/jputil/chars/reader/ReaderCharReader.java b/src/main/java/ru/windcorp/jputil/chars/reader/ReaderCharReader.java index 51a88db..fec35b2 100644 --- a/src/main/java/ru/windcorp/jputil/chars/reader/ReaderCharReader.java +++ b/src/main/java/ru/windcorp/jputil/chars/reader/ReaderCharReader.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars.reader; import java.io.IOException; diff --git a/src/main/java/ru/windcorp/jputil/chars/reader/StringCharReader.java b/src/main/java/ru/windcorp/jputil/chars/reader/StringCharReader.java index 5836d15..58ec176 100644 --- a/src/main/java/ru/windcorp/jputil/chars/reader/StringCharReader.java +++ b/src/main/java/ru/windcorp/jputil/chars/reader/StringCharReader.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.chars.reader; import java.util.Objects; diff --git a/src/main/java/ru/windcorp/jputil/functions/FloatSupplier.java b/src/main/java/ru/windcorp/jputil/functions/FloatSupplier.java index a157032..774e36b 100644 --- a/src/main/java/ru/windcorp/jputil/functions/FloatSupplier.java +++ b/src/main/java/ru/windcorp/jputil/functions/FloatSupplier.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.functions; @FunctionalInterface diff --git a/src/main/java/ru/windcorp/jputil/functions/ThrowingBiConsumer.java b/src/main/java/ru/windcorp/jputil/functions/ThrowingBiConsumer.java index be7cb8f..bb5da27 100644 --- a/src/main/java/ru/windcorp/jputil/functions/ThrowingBiConsumer.java +++ b/src/main/java/ru/windcorp/jputil/functions/ThrowingBiConsumer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.functions; import java.util.function.BiConsumer; diff --git a/src/main/java/ru/windcorp/jputil/functions/ThrowingConsumer.java b/src/main/java/ru/windcorp/jputil/functions/ThrowingConsumer.java index 14449ca..e404710 100644 --- a/src/main/java/ru/windcorp/jputil/functions/ThrowingConsumer.java +++ b/src/main/java/ru/windcorp/jputil/functions/ThrowingConsumer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.functions; import java.util.function.BiConsumer; diff --git a/src/main/java/ru/windcorp/jputil/functions/ThrowingFunction.java b/src/main/java/ru/windcorp/jputil/functions/ThrowingFunction.java index afdd078..8d283a8 100644 --- a/src/main/java/ru/windcorp/jputil/functions/ThrowingFunction.java +++ b/src/main/java/ru/windcorp/jputil/functions/ThrowingFunction.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.functions; import java.util.function.BiConsumer; diff --git a/src/main/java/ru/windcorp/jputil/functions/ThrowingRunnable.java b/src/main/java/ru/windcorp/jputil/functions/ThrowingRunnable.java index f27429b..8c2a989 100644 --- a/src/main/java/ru/windcorp/jputil/functions/ThrowingRunnable.java +++ b/src/main/java/ru/windcorp/jputil/functions/ThrowingRunnable.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.functions; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/jputil/functions/ThrowingSupplier.java b/src/main/java/ru/windcorp/jputil/functions/ThrowingSupplier.java index 84ad690..6583789 100644 --- a/src/main/java/ru/windcorp/jputil/functions/ThrowingSupplier.java +++ b/src/main/java/ru/windcorp/jputil/functions/ThrowingSupplier.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.functions; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/jputil/iterators/ArrayIterator.java b/src/main/java/ru/windcorp/jputil/iterators/ArrayIterator.java index 0b8fab2..aec4324 100644 --- a/src/main/java/ru/windcorp/jputil/iterators/ArrayIterator.java +++ b/src/main/java/ru/windcorp/jputil/iterators/ArrayIterator.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.iterators; import java.util.Iterator; diff --git a/src/main/java/ru/windcorp/jputil/iterators/FunctionIterator.java b/src/main/java/ru/windcorp/jputil/iterators/FunctionIterator.java index abc5b44..e32d250 100644 --- a/src/main/java/ru/windcorp/jputil/iterators/FunctionIterator.java +++ b/src/main/java/ru/windcorp/jputil/iterators/FunctionIterator.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.iterators; import java.util.Iterator; diff --git a/src/main/java/ru/windcorp/jputil/iterators/PeekingIterator.java b/src/main/java/ru/windcorp/jputil/iterators/PeekingIterator.java index 67f3da9..754e1ae 100644 --- a/src/main/java/ru/windcorp/jputil/iterators/PeekingIterator.java +++ b/src/main/java/ru/windcorp/jputil/iterators/PeekingIterator.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.iterators; import java.util.Iterator; diff --git a/src/main/java/ru/windcorp/jputil/iterators/RangeIterator.java b/src/main/java/ru/windcorp/jputil/iterators/RangeIterator.java index 7da8ada..13ad18c 100644 --- a/src/main/java/ru/windcorp/jputil/iterators/RangeIterator.java +++ b/src/main/java/ru/windcorp/jputil/iterators/RangeIterator.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.iterators; import java.util.Iterator; diff --git a/src/main/java/ru/windcorp/jputil/iterators/Reiterator.java b/src/main/java/ru/windcorp/jputil/iterators/Reiterator.java index 7969bc1..85d9122 100644 --- a/src/main/java/ru/windcorp/jputil/iterators/Reiterator.java +++ b/src/main/java/ru/windcorp/jputil/iterators/Reiterator.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.iterators; import java.util.ArrayList; diff --git a/src/main/java/ru/windcorp/jputil/selectors/AbstractSelectorOperator.java b/src/main/java/ru/windcorp/jputil/selectors/AbstractSelectorOperator.java index 481e558..3448929 100644 --- a/src/main/java/ru/windcorp/jputil/selectors/AbstractSelectorOperator.java +++ b/src/main/java/ru/windcorp/jputil/selectors/AbstractSelectorOperator.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.selectors; public abstract class AbstractSelectorOperator implements SelectorOperator { diff --git a/src/main/java/ru/windcorp/jputil/selectors/NamedParameterizedSelector.java b/src/main/java/ru/windcorp/jputil/selectors/NamedParameterizedSelector.java index e0676fd..d0a7692 100644 --- a/src/main/java/ru/windcorp/jputil/selectors/NamedParameterizedSelector.java +++ b/src/main/java/ru/windcorp/jputil/selectors/NamedParameterizedSelector.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.selectors; import ru.windcorp.jputil.SyntaxException; diff --git a/src/main/java/ru/windcorp/jputil/selectors/NamedSelector.java b/src/main/java/ru/windcorp/jputil/selectors/NamedSelector.java index 196be14..7765505 100644 --- a/src/main/java/ru/windcorp/jputil/selectors/NamedSelector.java +++ b/src/main/java/ru/windcorp/jputil/selectors/NamedSelector.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.selectors; import ru.windcorp.jputil.SyntaxException; diff --git a/src/main/java/ru/windcorp/jputil/selectors/OperatorAnd.java b/src/main/java/ru/windcorp/jputil/selectors/OperatorAnd.java index 603c6d4..4b68bb6 100644 --- a/src/main/java/ru/windcorp/jputil/selectors/OperatorAnd.java +++ b/src/main/java/ru/windcorp/jputil/selectors/OperatorAnd.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.selectors; import java.util.Deque; diff --git a/src/main/java/ru/windcorp/jputil/selectors/OperatorExclude.java b/src/main/java/ru/windcorp/jputil/selectors/OperatorExclude.java index a805a2f..810f15f 100644 --- a/src/main/java/ru/windcorp/jputil/selectors/OperatorExclude.java +++ b/src/main/java/ru/windcorp/jputil/selectors/OperatorExclude.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.selectors; import java.util.Deque; diff --git a/src/main/java/ru/windcorp/jputil/selectors/OperatorNot.java b/src/main/java/ru/windcorp/jputil/selectors/OperatorNot.java index 2bf0300..b12f5dc 100644 --- a/src/main/java/ru/windcorp/jputil/selectors/OperatorNot.java +++ b/src/main/java/ru/windcorp/jputil/selectors/OperatorNot.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.selectors; import java.util.Deque; diff --git a/src/main/java/ru/windcorp/jputil/selectors/OperatorOr.java b/src/main/java/ru/windcorp/jputil/selectors/OperatorOr.java index 367e6c3..2388105 100644 --- a/src/main/java/ru/windcorp/jputil/selectors/OperatorOr.java +++ b/src/main/java/ru/windcorp/jputil/selectors/OperatorOr.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.selectors; import java.util.Deque; diff --git a/src/main/java/ru/windcorp/jputil/selectors/OperatorXor.java b/src/main/java/ru/windcorp/jputil/selectors/OperatorXor.java index 467e6a0..9b8a719 100644 --- a/src/main/java/ru/windcorp/jputil/selectors/OperatorXor.java +++ b/src/main/java/ru/windcorp/jputil/selectors/OperatorXor.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.selectors; import java.util.Deque; diff --git a/src/main/java/ru/windcorp/jputil/selectors/PredicateWrapper.java b/src/main/java/ru/windcorp/jputil/selectors/PredicateWrapper.java index 278df45..f43760a 100644 --- a/src/main/java/ru/windcorp/jputil/selectors/PredicateWrapper.java +++ b/src/main/java/ru/windcorp/jputil/selectors/PredicateWrapper.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.selectors; import java.util.function.Predicate; diff --git a/src/main/java/ru/windcorp/jputil/selectors/Selector.java b/src/main/java/ru/windcorp/jputil/selectors/Selector.java index eec8b06..450e717 100644 --- a/src/main/java/ru/windcorp/jputil/selectors/Selector.java +++ b/src/main/java/ru/windcorp/jputil/selectors/Selector.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.selectors; import java.util.function.Predicate; diff --git a/src/main/java/ru/windcorp/jputil/selectors/SelectorOperator.java b/src/main/java/ru/windcorp/jputil/selectors/SelectorOperator.java index 665d231..20b46b3 100644 --- a/src/main/java/ru/windcorp/jputil/selectors/SelectorOperator.java +++ b/src/main/java/ru/windcorp/jputil/selectors/SelectorOperator.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.selectors; import java.util.Deque; diff --git a/src/main/java/ru/windcorp/jputil/selectors/SelectorSystem.java b/src/main/java/ru/windcorp/jputil/selectors/SelectorSystem.java index 0361795..fe626f0 100644 --- a/src/main/java/ru/windcorp/jputil/selectors/SelectorSystem.java +++ b/src/main/java/ru/windcorp/jputil/selectors/SelectorSystem.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.jputil.selectors; import java.util.ArrayList; diff --git a/src/main/java/ru/windcorp/progressia/Progressia.java b/src/main/java/ru/windcorp/progressia/Progressia.java index db899ea..fd3529f 100644 --- a/src/main/java/ru/windcorp/progressia/Progressia.java +++ b/src/main/java/ru/windcorp/progressia/Progressia.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia; public class Progressia { diff --git a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java index f32936f..630f9c6 100644 --- a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java +++ b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia; import ru.windcorp.progressia.client.ClientProxy; @@ -33,14 +33,13 @@ public class ProgressiaLauncher { public static void launch(String[] args, ClientProxy inProxy) { arguments = args.clone(); setupCrashReports(); - + inProxy.initialize(); proxy = inProxy; GUI.addTopLayer(new LayerTitle("Title")); } - - public static void play() - { + + public static void play() { proxy.setupServer(); } diff --git a/src/main/java/ru/windcorp/progressia/Proxy.java b/src/main/java/ru/windcorp/progressia/Proxy.java index a1af080..8b5542e 100644 --- a/src/main/java/ru/windcorp/progressia/Proxy.java +++ b/src/main/java/ru/windcorp/progressia/Proxy.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia; public interface Proxy { diff --git a/src/main/java/ru/windcorp/progressia/client/Client.java b/src/main/java/ru/windcorp/progressia/client/Client.java index d8800c7..543d3a6 100644 --- a/src/main/java/ru/windcorp/progressia/client/Client.java +++ b/src/main/java/ru/windcorp/progressia/client/Client.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client; import ru.windcorp.progressia.client.comms.DefaultClientCommsListener; diff --git a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java index cd75d42..ab0b476 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client; import ru.windcorp.progressia.Proxy; @@ -41,7 +41,7 @@ public class ClientProxy implements Proxy { public void initialize() { GraphicsBackend.initialize(); - + try { RenderTaskQueue.waitAndInvoke(FlatRenderProgram::init); RenderTaskQueue.waitAndInvoke(WorldRenderProgram::init); @@ -52,22 +52,21 @@ public class ClientProxy implements Proxy { } catch (InterruptedException e) { throw CrashReports.report(e, "Menu launch failed"); } - + Localizer.getInstance().setLanguage("en-US"); - + TestContent.registerContent(); Atlases.loadAllAtlases(); AudioSystem.initialize(); - + TestMusicPlayer.start(); - - //setupServer(); + + // setupServer(); } - - public void setupServer() - { + + public void setupServer() { ServerState.startServer(); ClientState.connectToLocalServer(); } diff --git a/src/main/java/ru/windcorp/progressia/client/ClientState.java b/src/main/java/ru/windcorp/progressia/client/ClientState.java index 2ae791c..c09a3d3 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientState.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientState.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client; import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel; @@ -36,7 +36,7 @@ import ru.windcorp.progressia.test.TestContent; public class ClientState { private static Client instance; - + private static boolean firstLoad; private static LayerTestText layer; @@ -55,7 +55,7 @@ public class ClientState { LocalServerCommsChannel channel = new LocalServerCommsChannel( ServerState.getInstance() ); - + firstLoad = true; Client client = new Client(world, channel); @@ -65,41 +65,41 @@ public class ClientState { setInstance(client); MutableString t = new MutableStringLocalized("LayerText.Load"); - layer = new LayerTestText("Text",() -> {t.update(); return t.get();}); - - ServerState.getInstance().getChunkManager().register((ChunksLoadStartListener)() -> { - if (firstLoad) - { - + layer = new LayerTestText("Text", () -> { + t.update(); + return t.get(); + }); + + ServerState.getInstance().getChunkManager().register((ChunksLoadStartListener) () -> { + if (firstLoad) { + GUI.addTopLayer(layer); - }}); - - ServerState.getInstance().getChunkManager().register((ChunksLoadFinishListener)() -> { - if (firstLoad) - { + } + }); + + ServerState.getInstance().getChunkManager().register((ChunksLoadFinishListener) () -> { + if (firstLoad) { GUI.removeLayer(layer); - + LayerWorld layerWorld = new LayerWorld(client); LayerTestUI layerUI = new LayerTestUI(); LayerAbout layerAbout = new LayerAbout(); GUI.addBottomLayer(layerWorld); GUI.addTopLayer(layerUI); GUI.addTopLayer(layerAbout); - + firstLoad = false; } }); - + } - - public static void disconnectFromLocalServer() - { - for (Layer layer : GUI.getLayers()) - { + + public static void disconnectFromLocalServer() { + for (Layer layer : GUI.getLayers()) { GUI.removeLayer(layer); } - - //ServerState.getInstance().getClientManager(); + + // ServerState.getInstance().getClientManager(); } private ClientState() { diff --git a/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java b/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java index bb0482d..d578c85 100644 --- a/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java +++ b/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client; import ru.windcorp.progressia.ProgressiaLauncher; diff --git a/src/main/java/ru/windcorp/progressia/client/audio/AudioFormat.java b/src/main/java/ru/windcorp/progressia/client/audio/AudioFormat.java index 848e66c..cade47d 100644 --- a/src/main/java/ru/windcorp/progressia/client/audio/AudioFormat.java +++ b/src/main/java/ru/windcorp/progressia/client/audio/AudioFormat.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.audio; public enum AudioFormat { diff --git a/src/main/java/ru/windcorp/progressia/client/audio/AudioManager.java b/src/main/java/ru/windcorp/progressia/client/audio/AudioManager.java index 49f2312..59be50b 100644 --- a/src/main/java/ru/windcorp/progressia/client/audio/AudioManager.java +++ b/src/main/java/ru/windcorp/progressia/client/audio/AudioManager.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.audio; import org.lwjgl.openal.*; diff --git a/src/main/java/ru/windcorp/progressia/client/audio/AudioRegistry.java b/src/main/java/ru/windcorp/progressia/client/audio/AudioRegistry.java index 3199622..2f1da30 100644 --- a/src/main/java/ru/windcorp/progressia/client/audio/AudioRegistry.java +++ b/src/main/java/ru/windcorp/progressia/client/audio/AudioRegistry.java @@ -21,9 +21,9 @@ import ru.windcorp.progressia.client.audio.backend.SoundType; import ru.windcorp.progressia.common.util.namespaces.NamespacedInstanceRegistry; public class AudioRegistry extends NamespacedInstanceRegistry { - + private static final AudioRegistry INSTANCE = new AudioRegistry(); - + /** * @return the instance */ diff --git a/src/main/java/ru/windcorp/progressia/client/audio/AudioSystem.java b/src/main/java/ru/windcorp/progressia/client/audio/AudioSystem.java index 24cc2de..a39b574 100644 --- a/src/main/java/ru/windcorp/progressia/client/audio/AudioSystem.java +++ b/src/main/java/ru/windcorp/progressia/client/audio/AudioSystem.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.audio; import ru.windcorp.progressia.common.resource.ResourceManager; diff --git a/src/main/java/ru/windcorp/progressia/client/audio/Music.java b/src/main/java/ru/windcorp/progressia/client/audio/Music.java index 031b58e..34e0943 100644 --- a/src/main/java/ru/windcorp/progressia/client/audio/Music.java +++ b/src/main/java/ru/windcorp/progressia/client/audio/Music.java @@ -15,18 +15,16 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.audio; import glm.vec._3.Vec3; import ru.windcorp.progressia.client.audio.backend.SoundType; import ru.windcorp.progressia.client.audio.backend.Speaker; -public class Music +public class Music extends Sound { - - - + public Music(SoundType soundType, int timeLength, float pitch, float gain) { super(soundType, timeLength, new Vec3(), new Vec3(), pitch, gain); } @@ -47,7 +45,7 @@ public class Music protected Speaker initSpeaker() { return AudioManager.initMusicSpeaker(soundType); } - + @Override public void setPosition(Vec3 position) { throw new UnsupportedOperationException(); diff --git a/src/main/java/ru/windcorp/progressia/client/audio/Sound.java b/src/main/java/ru/windcorp/progressia/client/audio/Sound.java index 77f0c9e..247aa48 100644 --- a/src/main/java/ru/windcorp/progressia/client/audio/Sound.java +++ b/src/main/java/ru/windcorp/progressia/client/audio/Sound.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.audio; import glm.vec._3.Vec3; @@ -29,9 +29,9 @@ public class Sound { protected float pitch = 1.0f; protected float gain = 1.0f; protected int timeLength = 0; - + protected SoundType soundType; - + public Sound(SoundType soundType) { this.soundType = soundType; } @@ -39,7 +39,7 @@ public class Sound { public Sound(String id) { this(AudioRegistry.getInstance().get(id)); } - + public Sound( String id, int timeLength, @@ -54,7 +54,7 @@ public class Sound { this.pitch = pitch; this.gain = gain; } - + public Sound( SoundType soundType, int timeLength, @@ -69,7 +69,7 @@ public class Sound { this.pitch = pitch; this.gain = gain; } - + protected Speaker initSpeaker() { return AudioManager.initSpeaker(soundType); } @@ -119,7 +119,7 @@ public class Sound { public float getPitch() { return pitch; } - + public double getDuration() { return soundType.getDuration(); } diff --git a/src/main/java/ru/windcorp/progressia/client/audio/backend/AudioReader.java b/src/main/java/ru/windcorp/progressia/client/audio/backend/AudioReader.java index 9fa48e0..c05d008 100644 --- a/src/main/java/ru/windcorp/progressia/client/audio/backend/AudioReader.java +++ b/src/main/java/ru/windcorp/progressia/client/audio/backend/AudioReader.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.audio.backend; import org.lwjgl.BufferUtils; diff --git a/src/main/java/ru/windcorp/progressia/client/audio/backend/Listener.java b/src/main/java/ru/windcorp/progressia/client/audio/backend/Listener.java index 8f6fe35..6a9dd84 100644 --- a/src/main/java/ru/windcorp/progressia/client/audio/backend/Listener.java +++ b/src/main/java/ru/windcorp/progressia/client/audio/backend/Listener.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.audio.backend; import glm.vec._3.Vec3; diff --git a/src/main/java/ru/windcorp/progressia/client/audio/backend/SoundType.java b/src/main/java/ru/windcorp/progressia/client/audio/backend/SoundType.java index cdb1954..59f7cf9 100644 --- a/src/main/java/ru/windcorp/progressia/client/audio/backend/SoundType.java +++ b/src/main/java/ru/windcorp/progressia/client/audio/backend/SoundType.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.audio.backend; import ru.windcorp.progressia.common.util.namespaces.Namespaced; @@ -56,7 +56,7 @@ public class SoundType extends Namespaced { public void initSpeaker(Speaker speaker) { speaker.setAudioData(audioBuffer); } - + public double getDuration() { return duration; } diff --git a/src/main/java/ru/windcorp/progressia/client/audio/backend/Speaker.java b/src/main/java/ru/windcorp/progressia/client/audio/backend/Speaker.java index c649a6a..def1e09 100644 --- a/src/main/java/ru/windcorp/progressia/client/audio/backend/Speaker.java +++ b/src/main/java/ru/windcorp/progressia/client/audio/backend/Speaker.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.audio.backend; import glm.vec._3.Vec3; diff --git a/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java b/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java index dad05fd..0413550 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.comms; import java.io.IOException; diff --git a/src/main/java/ru/windcorp/progressia/client/comms/ServerCommsChannel.java b/src/main/java/ru/windcorp/progressia/client/comms/ServerCommsChannel.java index 3a0a1b1..6bf9a8e 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/ServerCommsChannel.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/ServerCommsChannel.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.comms; import ru.windcorp.progressia.common.comms.CommsChannel; diff --git a/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTrigger.java b/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTrigger.java index 88e9fa3..0f0e091 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTrigger.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTrigger.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.comms.controls; import ru.windcorp.progressia.common.util.namespaces.Namespaced; diff --git a/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerInputBased.java b/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerInputBased.java index b2f8de4..f1985b3 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerInputBased.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerInputBased.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.comms.controls; import ru.windcorp.progressia.client.graphics.input.InputEvent; diff --git a/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerLambda.java b/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerLambda.java index 22004b8..03d7130 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerLambda.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerLambda.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.comms.controls; import java.util.function.BiConsumer; diff --git a/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerLocalLambda.java b/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerLocalLambda.java index b2ae739..483eabd 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerLocalLambda.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerLocalLambda.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.comms.controls; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerRegistry.java b/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerRegistry.java index a2ec71e..5a3f4a9 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerRegistry.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggerRegistry.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.comms.controls; import ru.windcorp.progressia.common.util.namespaces.NamespacedInstanceRegistry; diff --git a/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggers.java b/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggers.java index 2c0d61d..0de7c29 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggers.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggers.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.comms.controls; import java.util.function.BiConsumer; @@ -142,7 +142,7 @@ public class ControlTriggers { predicates ); } - + // // /// @@ -156,7 +156,7 @@ public class ControlTriggers { // // // - + public static ControlTriggerInputBased localOf( String id, Consumer action, @@ -239,7 +239,7 @@ public class ControlTriggers { ) { return (inputEvent, control) -> dataWriter.accept(inputType.cast(inputEvent), control); } - + private static Consumer createCheckedAction( Class inputType, Consumer action diff --git a/src/main/java/ru/windcorp/progressia/client/comms/controls/InputBasedControls.java b/src/main/java/ru/windcorp/progressia/client/comms/controls/InputBasedControls.java index 28b9e1b..36ba5a0 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/controls/InputBasedControls.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/controls/InputBasedControls.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.comms.controls; import ru.windcorp.progressia.client.Client; diff --git a/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalClient.java b/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalClient.java index f1fdf96..54903ab 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalClient.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalClient.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.comms.localhost; import java.io.IOException; diff --git a/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalServerCommsChannel.java b/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalServerCommsChannel.java index b631a3c..463112b 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalServerCommsChannel.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/localhost/LocalServerCommsChannel.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.comms.localhost; import ru.windcorp.progressia.client.comms.ServerCommsChannel; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/Colors.java b/src/main/java/ru/windcorp/progressia/client/graphics/Colors.java index b37a6a8..60d0cba 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/Colors.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/Colors.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics; import glm.vec._4.Vec4; @@ -35,7 +35,7 @@ public class Colors { DEBUG_CYAN = toVector(0xFF00FFFF), DEBUG_MAGENTA = toVector(0xFFFF00FF), DEBUG_YELLOW = toVector(0xFFFFFF00), - + LIGHT_GRAY = toVector(0xFFCBCBD0), BLUE = toVector(0xFF37A2E6), HOVER_BLUE = toVector(0xFFC3E4F7), diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/GUI.java b/src/main/java/ru/windcorp/progressia/client/graphics/GUI.java index 56829cf..59b89da 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/GUI.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/GUI.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics; import java.util.ArrayList; @@ -92,33 +92,33 @@ public class GUI { public static void render() { synchronized (LAYERS) { - + if (!MODIFICATION_QUEUE.isEmpty()) { MODIFICATION_QUEUE.forEach(action -> action.affect(LAYERS)); MODIFICATION_QUEUE.clear(); - + boolean isMouseCurrentlyCaptured = GraphicsInterface.isMouseCaptured(); Layer.CursorPolicy policy = Layer.CursorPolicy.REQUIRE; - + for (Layer layer : LAYERS) { Layer.CursorPolicy currentPolicy = layer.getCursorPolicy(); - + if (currentPolicy != Layer.CursorPolicy.INDIFFERENT) { policy = currentPolicy; break; } } - + boolean shouldCaptureMouse = (policy == Layer.CursorPolicy.FORBID); if (shouldCaptureMouse != isMouseCurrentlyCaptured) { GraphicsInterface.setMouseCaptured(shouldCaptureMouse); } } - + for (int i = LAYERS.size() - 1; i >= 0; --i) { LAYERS.get(i).render(); } - + } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/Layer.java b/src/main/java/ru/windcorp/progressia/client/graphics/Layer.java index dfa72d5..490ec04 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/Layer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/Layer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics; import java.util.concurrent.atomic.AtomicBoolean; @@ -30,7 +30,7 @@ public abstract class Layer { private boolean hasInitialized = false; private final AtomicBoolean isValid = new AtomicBoolean(false); - + /** * Represents various requests that a {@link Layer} can make regarding the * presence of a visible cursor. The value of the highest layer that is not @@ -53,13 +53,13 @@ public abstract class Layer { */ FORBID } - + private CursorPolicy cursorPolicy = CursorPolicy.INDIFFERENT; public Layer(String name) { this.name = name; } - + public String getName() { return name; } @@ -68,11 +68,11 @@ public abstract class Layer { public String toString() { return "Layer " + name; } - + public CursorPolicy getCursorPolicy() { return cursorPolicy; } - + public void setCursorPolicy(CursorPolicy cursorPolicy) { this.cursorPolicy = cursorPolicy; } @@ -115,11 +115,11 @@ public abstract class Layer { protected int getHeight() { return GraphicsInterface.getFrameHeight(); } - + protected void onAdded() { // Do nothing } - + protected void onRemoved() { // Do nothing } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/FaceCulling.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/FaceCulling.java index 61645f4..bdab268 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/FaceCulling.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/FaceCulling.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend; import java.util.ArrayDeque; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsBackend.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsBackend.java index 1635c7a..2723562 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsBackend.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsBackend.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend; import glm.vec._2.i.Vec2i; @@ -61,7 +61,7 @@ public class GraphicsBackend { static void setOpenGLInitialized(boolean isOpenGLInitialized) { GraphicsBackend.isOpenGLInitialized = isOpenGLInitialized; } - + public static void initialize() { startRenderThread(); } @@ -166,7 +166,8 @@ public class GraphicsBackend { 0, vidmode.width(), vidmode.height(), - 0); + 0 + ); isFullscreen = true; } @@ -179,7 +180,8 @@ public class GraphicsBackend { (vidmode.height() - getFrameHeight()) / 2, getFrameWidth(), getFrameHeight(), - 0); + 0 + ); isFullscreen = false; } @@ -192,18 +194,18 @@ public class GraphicsBackend { GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); return vidmode.refreshRate(); } - + public static boolean isMouseCaptured() { return glfwGetInputMode(windowHandle, GLFW_CURSOR) == GLFW_CURSOR_DISABLED; } - + public static void setMouseCaptured(boolean capture) { int mode = capture ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL; glfwSetInputMode(windowHandle, GLFW_CURSOR, mode); - + if (!capture) { glfwSetCursorPos(windowHandle, FRAME_SIZE.x / 2.0, FRAME_SIZE.y / 2.0); } } - + } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsInterface.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsInterface.java index ffd0b49..0a7a453 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsInterface.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsInterface.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend; import glm.vec._2.i.Vec2i; @@ -81,11 +81,11 @@ public class GraphicsInterface { } GraphicsBackend.setVSyncEnabled(GraphicsBackend.isVSyncEnabled()); } - + public static boolean isMouseCaptured() { return GraphicsBackend.isMouseCaptured(); } - + public static void setMouseCaptured(boolean capture) { GraphicsBackend.setMouseCaptured(capture); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputHandler.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputHandler.java index 34d936c..201ed4f 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputHandler.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputHandler.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend; import org.lwjgl.glfw.GLFW; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputTracker.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputTracker.java index 29dec99..ffd786b 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputTracker.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputTracker.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend; import glm.vec._2.d.Vec2d; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java index 9239150..55d5fbd 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend; import static org.lwjgl.opengl.GL11.*; @@ -66,7 +66,7 @@ class LWJGLInitializer { GraphicsBackend.setWindowHandle(handle); glfwMakeContextCurrent(handle); - glfwSwapInterval(0); // TODO: remove after config system is added + glfwSwapInterval(0); // TODO: remove after config system is added } private static void positionWindow() { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/OpenGLObjectTracker.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/OpenGLObjectTracker.java index c467d45..292eb62 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/OpenGLObjectTracker.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/OpenGLObjectTracker.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend; import java.lang.ref.PhantomReference; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/RenderTaskQueue.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/RenderTaskQueue.java index 0a1d722..93498ed 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/RenderTaskQueue.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/RenderTaskQueue.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend; import ru.windcorp.jputil.functions.ThrowingRunnable; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/RenderThread.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/RenderThread.java index 47d4306..d92385e 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/RenderThread.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/RenderThread.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend; import static org.lwjgl.glfw.GLFW.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/Usage.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/Usage.java index 8a526c1..1297ec7 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/Usage.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/Usage.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend; import static org.lwjgl.opengl.GL15.GL_DYNAMIC_DRAW; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/VertexBufferObject.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/VertexBufferObject.java index 7fe23f7..ef85ce3 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/VertexBufferObject.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/VertexBufferObject.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend; import static org.lwjgl.opengl.GL20.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/CombinedShader.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/CombinedShader.java index 63fb4c9..7735e4c 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/CombinedShader.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/CombinedShader.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders; import ru.windcorp.progressia.common.resource.Resource; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Program.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Program.java index 98d512e..b980c21 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Program.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Program.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders; import static org.lwjgl.opengl.GL11.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Shader.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Shader.java index 714fd1a..9ada432 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Shader.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Shader.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders; import static org.lwjgl.opengl.GL11.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/Attribute.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/Attribute.java index d56210a..028a0b3 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/Attribute.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/Attribute.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders.attributes; import ru.windcorp.progressia.client.graphics.backend.shaders.Program; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/AttributeVertexArray.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/AttributeVertexArray.java index 2ca192d..00fe302 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/AttributeVertexArray.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/AttributeVertexArray.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders.attributes; import static org.lwjgl.opengl.GL11.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform.java index 8de5f1c..aa09d49 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders.uniforms; import ru.windcorp.progressia.client.graphics.backend.shaders.Program; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform1Float.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform1Float.java index 6e2a62b..b41e313 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform1Float.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform1Float.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders.uniforms; import static org.lwjgl.opengl.GL20.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform1Int.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform1Int.java index 79d14a0..6389583 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform1Int.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform1Int.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders.uniforms; import static org.lwjgl.opengl.GL20.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform2Float.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform2Float.java index 166f47b..1c609c2 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform2Float.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform2Float.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders.uniforms; import static org.lwjgl.opengl.GL20.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform2Int.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform2Int.java index d8dde9b..679de9d 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform2Int.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform2Int.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders.uniforms; import static org.lwjgl.opengl.GL20.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform2Matrix.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform2Matrix.java index 6bbc3a9..b45c598 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform2Matrix.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform2Matrix.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders.uniforms; import static org.lwjgl.opengl.GL20.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform3Float.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform3Float.java index 21ea95b..d381a14 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform3Float.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform3Float.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders.uniforms; import static org.lwjgl.opengl.GL20.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform3Int.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform3Int.java index 1eb4690..283c459 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform3Int.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform3Int.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders.uniforms; import static org.lwjgl.opengl.GL20.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform3Matrix.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform3Matrix.java index 255fe2a..f2a0c12 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform3Matrix.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform3Matrix.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders.uniforms; import static org.lwjgl.opengl.GL20.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform4Float.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform4Float.java index daaab36..5aea97f 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform4Float.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform4Float.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders.uniforms; import static org.lwjgl.opengl.GL20.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform4Int.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform4Int.java index 6c2e760..31db411 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform4Int.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform4Int.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders.uniforms; import static org.lwjgl.opengl.GL20.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform4Matrix.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform4Matrix.java index e8281bd..e83cea5 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform4Matrix.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform4Matrix.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.backend.shaders.uniforms; import static org.lwjgl.opengl.GL20.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatLayer.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatLayer.java index 83f9d6f..7bf8161 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatLayer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatLayer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.flat; import ru.windcorp.progressia.client.graphics.Layer; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatRenderHelper.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatRenderHelper.java index 5696ac2..789a378 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatRenderHelper.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatRenderHelper.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.flat; import java.nio.FloatBuffer; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/DefaultFlatRenderHelper.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/DefaultFlatRenderHelper.java index 4ec676a..5550c24 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/DefaultFlatRenderHelper.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/DefaultFlatRenderHelper.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.flat; import java.nio.FloatBuffer; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatGraphics.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatGraphics.java index 2b615ec..e7723e6 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatGraphics.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatGraphics.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.flat; public class FlatGraphics { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderHelper.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderHelper.java index 704c579..ab52567 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderHelper.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderHelper.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.flat; import java.nio.FloatBuffer; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java index 774e6f3..c0361e4 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.flat; import java.nio.FloatBuffer; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/Mask.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/Mask.java index e13400a..d781c0b 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/Mask.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/Mask.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.flat; public class Mask { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/MaskStack.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/MaskStack.java index f114058..767e6d8 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/MaskStack.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/MaskStack.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.flat; import java.nio.FloatBuffer; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/RenderTarget.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/RenderTarget.java index 658b02d..e07afe6 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/RenderTarget.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/RenderTarget.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.flat; import java.util.ArrayList; @@ -189,7 +189,7 @@ public class RenderTarget { public void addCustomRenderer(Renderable renderable) { assembleCurrentClipFromFaces(); - + float depth = this.depth--; Mat4 transform = new Mat4().translate(0, 0, depth).mul(getTransform()); assembled.add(new Clip(maskStack, transform, renderable)); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/TransformedMask.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/TransformedMask.java index 5328cc8..db3d9c3 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/TransformedMask.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/TransformedMask.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.flat; import java.nio.FloatBuffer; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/font/Font.java b/src/main/java/ru/windcorp/progressia/client/graphics/font/Font.java index 591ff83..2863493 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/font/Font.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/font/Font.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.font; import java.util.function.Supplier; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifont.java b/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifont.java index f28975d..6b687b2 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifont.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifont.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.font; import gnu.trove.map.TCharObjectMap; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifontLoader.java b/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifontLoader.java index 9ead1db..74cb7c3 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifontLoader.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifontLoader.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.font; import java.io.BufferedReader; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/font/SpriteTypeface.java b/src/main/java/ru/windcorp/progressia/client/graphics/font/SpriteTypeface.java index 7920799..d2e61d7 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/font/SpriteTypeface.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/font/SpriteTypeface.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.font; import java.util.ArrayList; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/font/Typeface.java b/src/main/java/ru/windcorp/progressia/client/graphics/font/Typeface.java index 3be5ebb..3297fc0 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/font/Typeface.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/font/Typeface.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.font; import java.util.function.Supplier; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/font/Typefaces.java b/src/main/java/ru/windcorp/progressia/client/graphics/font/Typefaces.java index ed9c7c4..813087d 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/font/Typefaces.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/font/Typefaces.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.font; public class Typefaces { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java index ddaab7b..14c0e36 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java @@ -37,12 +37,12 @@ import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; import ru.windcorp.progressia.client.graphics.input.KeyEvent; public abstract class BasicButton extends Component { - + private final Label label; private boolean isPressed = false; private final Collection> actions = Collections.synchronizedCollection(new ArrayList<>()); - + public BasicButton(String name, Label label) { super(name); this.label = label; @@ -59,8 +59,8 @@ public abstract class BasicButton extends Component { return false; } else if ( e.isLeftMouseButton() || - e.getKey() == GLFW.GLFW_KEY_SPACE || - e.getKey() == GLFW.GLFW_KEY_ENTER + e.getKey() == GLFW.GLFW_KEY_SPACE || + e.getKey() == GLFW.GLFW_KEY_ENTER ) { setPressed(e.isPress()); return true; @@ -68,9 +68,9 @@ public abstract class BasicButton extends Component { return false; } }); - + addListener(new Object() { - + // Release when losing focus @Subscribe public void onFocusChange(FocusEvent e) { @@ -78,7 +78,7 @@ public abstract class BasicButton extends Component { setPressed(false); } } - + // Release when hover ends @Subscribe public void onHoverEnded(HoverEvent e) { @@ -86,7 +86,7 @@ public abstract class BasicButton extends Component { setPressed(false); } } - + // Release when disabled @Subscribe public void onDisabled(EnableEvent e) { @@ -94,18 +94,17 @@ public abstract class BasicButton extends Component { setPressed(false); } } - + // Trigger virtualClick when button is released @Subscribe public void onRelease(ButtonEvent.Release e) { virtualClick(); } - + }); } - - public BasicButton(String name, String label, Font labelFont) - { + + public BasicButton(String name, String label, Font labelFont) { this(name, new Label(name + ".Label", labelFont, label)); } @@ -116,7 +115,7 @@ public abstract class BasicButton extends Component { public boolean isPressed() { return isPressed; } - + public void click() { setPressed(true); setPressed(false); @@ -125,7 +124,7 @@ public abstract class BasicButton extends Component { public void setPressed(boolean isPressed) { if (this.isPressed != isPressed) { this.isPressed = isPressed; - + if (isPressed) { takeFocus(); } @@ -133,16 +132,16 @@ public abstract class BasicButton extends Component { dispatchEvent(ButtonEvent.create(this, this.isPressed)); } } - + public BasicButton addAction(Consumer action) { this.actions.add(Objects.requireNonNull(action, "action")); return this; } - + public boolean removeAction(Consumer action) { return this.actions.remove(action); } - + public void virtualClick() { this.actions.forEach(action -> { action.accept(this); @@ -152,5 +151,5 @@ public abstract class BasicButton extends Component { public Label getLabel() { return label; } - + } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Button.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Button.java index c41dedc..5d42241 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Button.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Button.java @@ -28,11 +28,11 @@ public class Button extends BasicButton { public Button(String name, String label, Font labelFont) { super(name, label, labelFont); } - + public Button(String name, Label label) { super(name, label); } - + public Button(String name, String label) { this(name, label, new Font()); } @@ -40,7 +40,7 @@ public class Button extends BasicButton { @Override protected void assembleSelf(RenderTarget target) { // Border - + Vec4 borderColor; if (isPressed() || isHovered() || isFocused()) { borderColor = Colors.BLUE; @@ -48,9 +48,9 @@ public class Button extends BasicButton { borderColor = Colors.LIGHT_GRAY; } target.fill(getX(), getY(), getWidth(), getHeight(), borderColor); - + // Inside area - + if (isPressed()) { // Do nothing } else { @@ -62,20 +62,20 @@ public class Button extends BasicButton { } target.fill(getX() + 2, getY() + 2, getWidth() - 4, getHeight() - 4, backgroundColor); } - + // Change label font color - + if (isPressed()) { getLabel().setFont(getLabel().getFont().withColor(Colors.WHITE)); } else { getLabel().setFont(getLabel().getFont().withColor(Colors.BLACK)); } } - + @Override protected void postAssembleSelf(RenderTarget target) { // Apply disable tint - + if (!isEnabled()) { target.fill(getX(), getY(), getWidth(), getHeight(), Colors.toVector(0x88FFFFFF)); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Checkbox.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Checkbox.java index 5f9d0df..990ed43 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Checkbox.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Checkbox.java @@ -27,24 +27,24 @@ import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; import ru.windcorp.progressia.client.graphics.gui.layout.LayoutHorizontal; public class Checkbox extends BasicButton { - + private class Tick extends Component { public Tick() { super(Checkbox.this.getName() + ".Tick"); - + setPreferredSize(new Vec2i(Typefaces.getDefault().getLineHeight() * 3 / 2)); } - + @Override protected void assembleSelf(RenderTarget target) { - + int size = getPreferredSize().x; int x = getX(); int y = getY() + (getHeight() - size) / 2; - + // Border - + Vec4 borderColor; if (Checkbox.this.isPressed() || Checkbox.this.isHovered() || Checkbox.this.isFocused()) { borderColor = Colors.BLUE; @@ -52,9 +52,9 @@ public class Checkbox extends BasicButton { borderColor = Colors.LIGHT_GRAY; } target.fill(x, y, size, size, borderColor); - + // Inside area - + if (Checkbox.this.isPressed()) { // Do nothing } else { @@ -66,9 +66,9 @@ public class Checkbox extends BasicButton { } target.fill(x + 2, y + 2, size - 4, size - 4, backgroundColor); } - + // "Tick" - + if (Checkbox.this.isChecked()) { target.fill(x + 4, y + 4, size - 8, size - 8, Colors.BLUE); } @@ -81,10 +81,10 @@ public class Checkbox extends BasicButton { public Checkbox(String name, String label, Font labelFont, boolean check) { super(name, label, labelFont); this.checked = check; - + assert getChildren().size() == 1 : "Checkbox expects that BasicButton contains exactly one child"; Component basicChild = getChild(0); - + Group group = new Group(getName() + ".LabelAndTick", new LayoutHorizontal(0, 10)); removeChild(basicChild); setLayout(new LayoutAlign(0, 0.5f, 10)); @@ -92,18 +92,18 @@ public class Checkbox extends BasicButton { group.addChild(new Tick()); group.addChild(basicChild); addChild(group); - + addAction(b -> switchState()); } - + public Checkbox(String name, String label, Font labelFont) { this(name, label, labelFont, false); } - + public Checkbox(String name, String label, boolean check) { this(name, label, new Font(), check); } - + public Checkbox(String name, String label) { this(name, label, false); } @@ -111,14 +111,14 @@ public class Checkbox extends BasicButton { public void switchState() { setChecked(!isChecked()); } - + /** * @return the checked */ public boolean isChecked() { return checked; } - + /** * @param checked the checked to set */ @@ -129,21 +129,21 @@ public class Checkbox extends BasicButton { @Override protected void assembleSelf(RenderTarget target) { // Change label font color - + if (isPressed()) { getLabel().setFont(getLabel().getFont().withColor(Colors.BLUE)); } else { getLabel().setFont(getLabel().getFont().withColor(Colors.BLACK)); } } - + @Override protected void postAssembleSelf(RenderTarget target) { // Apply disable tint - + if (!isEnabled()) { target.fill(getX(), getY(), getWidth(), getHeight(), Colors.toVector(0x88FFFFFF)); } } - + } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java index bb6f24d..ad4b5ba 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui; import java.util.Collections; @@ -66,7 +66,7 @@ public class Component extends Named { private Object layoutHint = null; private Layout layout = null; - + private boolean isEnabled = true; private boolean isFocusable = false; @@ -303,7 +303,7 @@ public class Component extends Named { public boolean isFocusable() { return isFocusable; } - + /** * Checks whether this component can become focused at this moment. *

@@ -460,11 +460,11 @@ public class Component extends Named { return null; } - + public boolean isEnabled() { return isEnabled; } - + /** * Enables or disables this component. An {@link EnableEvent} is dispatched * if the state changes. @@ -478,7 +478,7 @@ public class Component extends Named { if (isFocused() && isEnabled()) { focusNext(); } - + if (isEnabled()) { setHovered(false); } @@ -715,7 +715,7 @@ public class Component extends Named { protected void assembleChildren(RenderTarget target) { getChildren().forEach(child -> child.assemble(target)); } - + /* * Automatic Reassembly */ diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/DynamicLabel.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/DynamicLabel.java index bddad7b..ff62027 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/DynamicLabel.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/DynamicLabel.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui; import glm.mat._4.Mat4; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java index 2e0981c..9a4c648 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui; import ru.windcorp.progressia.client.graphics.flat.AssembledFlatLayer; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Group.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Group.java index d8a8b23..b6606fa 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Group.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Group.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui; public class Group extends Component { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Label.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Label.java index 4450f33..044b5d3 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Label.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Label.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui; import glm.mat._4.Mat4; @@ -82,7 +82,7 @@ public class Label extends Component { public Font getFont() { return font; } - + public void setFont(Font font) { this.font = font; requestReassembly(); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Layout.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Layout.java index 8d5d84f..4d08ed4 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Layout.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Layout.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui; import glm.vec._2.i.Vec2i; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Panel.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Panel.java index 90357ef..a3f9feb 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Panel.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Panel.java @@ -30,43 +30,43 @@ public class Panel extends Group { public Panel(String name, Layout layout, Vec4 fill, Vec4 border) { super(name, layout); - + this.fill = Objects.requireNonNull(fill, "fill"); this.border = border; } - + public Panel(String name, Layout layout) { this(name, layout, Colors.WHITE, Colors.LIGHT_GRAY); } - + /** * @return the fill */ public Vec4 getFill() { return fill; } - + /** * @param fill the fill to set */ public void setFill(Vec4 fill) { this.fill = Objects.requireNonNull(fill, "fill"); } - + /** * @return the border */ public Vec4 getBorder() { return border; } - + /** * @param border the border to set */ public void setBorder(Vec4 border) { this.border = border; } - + @Override protected void assembleSelf(RenderTarget target) { if (border == null) { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/RadioButton.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/RadioButton.java index 471efb6..1ee7f66 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/RadioButton.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/RadioButton.java @@ -30,30 +30,30 @@ import ru.windcorp.progressia.client.graphics.gui.layout.LayoutHorizontal; import ru.windcorp.progressia.client.graphics.input.KeyEvent; public class RadioButton extends BasicButton { - + private class Tick extends Component { public Tick() { super(RadioButton.this.getName() + ".Tick"); - + setPreferredSize(new Vec2i(Typefaces.getDefault().getLineHeight() * 3 / 2)); } - + private void cross(RenderTarget target, int x, int y, int size, Vec4 color) { target.fill(x + 4, y, size - 8, size, color); target.fill(x + 2, y + 2, size - 4, size - 4, color); target.fill(x, y + 4, size, size - 8, color); } - + @Override protected void assembleSelf(RenderTarget target) { - + int size = getPreferredSize().x; int x = getX(); int y = getY() + (getHeight() - size) / 2; - + // Border - + Vec4 borderColor; if (RadioButton.this.isPressed() || RadioButton.this.isHovered() || RadioButton.this.isFocused()) { borderColor = Colors.BLUE; @@ -61,9 +61,9 @@ public class RadioButton extends BasicButton { borderColor = Colors.LIGHT_GRAY; } cross(target, x, y, size, borderColor); - + // Inside area - + if (RadioButton.this.isPressed()) { // Do nothing } else { @@ -75,9 +75,9 @@ public class RadioButton extends BasicButton { } cross(target, x + 2, y + 2, size - 4, backgroundColor); } - + // "Tick" - + if (RadioButton.this.isChecked()) { cross(target, x + 4, y + 4, size - 8, Colors.BLUE); } @@ -86,16 +86,16 @@ public class RadioButton extends BasicButton { } private boolean checked; - + private RadioButtonGroup group = null; public RadioButton(String name, String label, Font labelFont, boolean check) { super(name, label, labelFont); this.checked = check; - + assert getChildren().size() == 1 : "RadioButton expects that BasicButton contains exactly one child"; Component basicChild = getChild(0); - + Group group = new Group(getName() + ".LabelAndTick", new LayoutHorizontal(0, 10)); removeChild(basicChild); setLayout(new LayoutAlign(0, 0.5f, 10)); @@ -103,16 +103,17 @@ public class RadioButton extends BasicButton { group.addChild(new Tick()); group.addChild(basicChild); addChild(group); - + addListener(KeyEvent.class, e -> { - if (e.isRelease()) return false; - + if (e.isRelease()) + return false; + if (e.getKey() == GLFW.GLFW_KEY_LEFT || e.getKey() == GLFW.GLFW_KEY_UP) { if (this.group != null) { this.group.selectPrevious(); this.group.getSelected().takeFocus(); } - + return true; } else if (e.getKey() == GLFW.GLFW_KEY_RIGHT || e.getKey() == GLFW.GLFW_KEY_DOWN) { if (this.group != null) { @@ -121,85 +122,87 @@ public class RadioButton extends BasicButton { } return true; } - + return false; }); - + addAction(b -> setChecked(true)); } - + public RadioButton(String name, String label, Font labelFont) { this(name, label, labelFont, false); } - + public RadioButton(String name, String label, boolean check) { this(name, label, new Font(), check); } - + public RadioButton(String name, String label) { this(name, label, false); } - + /** * @param group the group to set */ public RadioButton setGroup(RadioButtonGroup group) { - + if (this.group != null) { group.selectNext(); removeAction(group.listener); group.buttons.remove(this); - group.getSelected(); // Clear reference if this was the only button in the group + group.getSelected(); // Clear reference if this was the only button + // in the group } - + this.group = group; - + if (this.group != null) { group.buttons.add(this); addAction(group.listener); } - + setChecked(false); - + return this; } - + /** * @return the checked */ public boolean isChecked() { return checked; } - + /** * @param checked the checked to set */ public void setChecked(boolean checked) { this.checked = checked; - + if (group != null) { - group.listener.accept(this); // Failsafe for manual invocations of setChecked() + group.listener.accept(this); // Failsafe for manual invocations of + // setChecked() } } @Override protected void assembleSelf(RenderTarget target) { // Change label font color - + if (isPressed()) { getLabel().setFont(getLabel().getFont().withColor(Colors.BLUE)); } else { getLabel().setFont(getLabel().getFont().withColor(Colors.BLACK)); } } - + @Override protected void postAssembleSelf(RenderTarget target) { // Apply disable tint - + if (!isEnabled()) { target.fill(getX(), getY(), getWidth(), getHeight(), Colors.toVector(0x88FFFFFF)); } } - + } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/RadioButtonGroup.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/RadioButtonGroup.java index 3887018..a8d94dc 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/RadioButtonGroup.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/RadioButtonGroup.java @@ -26,92 +26,93 @@ import java.util.function.Consumer; public class RadioButtonGroup { - private final Collection> actions = Collections.synchronizedCollection(new ArrayList<>()); + private final Collection> actions = Collections + .synchronizedCollection(new ArrayList<>()); final List buttons = Collections.synchronizedList(new ArrayList<>()); - + private RadioButton selected = null; - + Consumer listener = b -> { if (b instanceof RadioButton && ((RadioButton) b).isChecked() && buttons.contains(b)) { select((RadioButton) b); } }; - + public RadioButtonGroup addAction(Consumer action) { this.actions.add(Objects.requireNonNull(action, "action")); return this; } - + public boolean removeAction(Consumer action) { return this.actions.remove(action); } - + public List getButtons() { return Collections.unmodifiableList(buttons); } - + public synchronized RadioButton getSelected() { if (!buttons.contains(selected)) { selected = null; } return selected; } - + public synchronized void select(RadioButton button) { if (button != null && !buttons.contains(button)) { throw new IllegalArgumentException("Button " + button + " is not in the group"); } - + getSelected(); // Clear if invalid - + if (selected == button) { return; // Terminate listener-setter recursion } - + if (selected != null) { selected.setChecked(false); } - + selected = button; - + if (selected != null) { selected.setChecked(true); } - + actions.forEach(action -> action.accept(this)); } - + public void selectNext() { selectNeighbour(+1); } - + public void selectPrevious() { selectNeighbour(-1); } - + private synchronized void selectNeighbour(int direction) { if (getSelected() == null) { if (buttons.isEmpty()) { throw new IllegalStateException("Cannot select neighbour button: group empty"); } - + select(buttons.get(0)); } else { RadioButton button; int index = buttons.indexOf(selected); - + do { index += direction; - + if (index >= buttons.size()) { index = 0; } else if (index < 0) { index = buttons.size() - 1; } - + button = buttons.get(index); } while (button != getSelected() && !button.isEnabled()); - + select(button); } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ButtonEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ButtonEvent.java index 071f06e..28c0cc3 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ButtonEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ButtonEvent.java @@ -21,26 +21,26 @@ package ru.windcorp.progressia.client.graphics.gui.event; import ru.windcorp.progressia.client.graphics.gui.BasicButton; public class ButtonEvent extends ComponentEvent { - + public static class Press extends ButtonEvent { public Press(BasicButton button) { super(button, true); } } - + public static class Release extends ButtonEvent { public Release(BasicButton button) { super(button, false); } } - + private final boolean isPress; protected ButtonEvent(BasicButton button, boolean isPress) { super(button); this.isPress = isPress; } - + public static ButtonEvent create(BasicButton button, boolean isPress) { if (isPress) { return new Press(button); @@ -56,5 +56,5 @@ public class ButtonEvent extends ComponentEvent { public boolean isRelease() { return !isPress; } - + } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ChildAddedEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ChildAddedEvent.java index f1611fe..9bbf93a 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ChildAddedEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ChildAddedEvent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui.event; import ru.windcorp.progressia.client.graphics.gui.Component; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ChildEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ChildEvent.java index a27cf79..0d63e38 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ChildEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ChildEvent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui.event; import ru.windcorp.progressia.client.graphics.gui.Component; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ChildRemovedEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ChildRemovedEvent.java index 897d787..ec2e46c 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ChildRemovedEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ChildRemovedEvent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui.event; import ru.windcorp.progressia.client.graphics.gui.Component; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ComponentEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ComponentEvent.java index b1d1175..dbf6e1c 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ComponentEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ComponentEvent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui.event; import ru.windcorp.progressia.client.graphics.gui.Component; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/EnableEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/EnableEvent.java index f56df2c..d8e5b5b 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/EnableEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/EnableEvent.java @@ -7,5 +7,5 @@ public class EnableEvent extends ComponentEvent { public EnableEvent(Component component) { super(component); } - + } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/FocusEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/FocusEvent.java index ff859f3..fe476c2 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/FocusEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/FocusEvent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui.event; import ru.windcorp.progressia.client.graphics.gui.Component; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/HierarchyEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/HierarchyEvent.java index d3a4984..5195c7e 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/HierarchyEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/HierarchyEvent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui.event; import ru.windcorp.progressia.client.graphics.gui.Component; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/HoverEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/HoverEvent.java index b1d63ad..1e788f9 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/HoverEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/HoverEvent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui.event; import ru.windcorp.progressia.client.graphics.gui.Component; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ParentChangedEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ParentChangedEvent.java index a7d9d40..ca5556a 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ParentChangedEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/event/ParentChangedEvent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui.event; import ru.windcorp.progressia.client.graphics.gui.Component; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutAlign.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutAlign.java index d521914..2fdf55d 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutAlign.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutAlign.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui.layout; import static java.lang.Math.max; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutBorderHorizontal.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutBorderHorizontal.java index 3e271de..2be127e 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutBorderHorizontal.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutBorderHorizontal.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui.layout; import static java.lang.Math.max; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutBorderVertical.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutBorderVertical.java index 0efcaa4..4584362 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutBorderVertical.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutBorderVertical.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui.layout; import static java.lang.Math.max; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutFill.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutFill.java index c65fc4a..c0c448a 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutFill.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutFill.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui.layout; import static java.lang.Math.max; @@ -27,7 +27,7 @@ import ru.windcorp.progressia.client.graphics.gui.Layout; public class LayoutFill implements Layout { private final int margin; - + public LayoutFill(int margin) { this.margin = margin; } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutGrid.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutGrid.java index a164378..02a519f 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutGrid.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutGrid.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui.layout; import java.util.Arrays; @@ -97,15 +97,15 @@ public class LayoutGrid implements Layout { void setBounds(int column, int row, Component child, Component parent) { if (!isSummed) throw new IllegalStateException("Not summed yet"); - + int width, height; - + if (column == columns.length - 1) { width = parent.getWidth() - margin - columns[column]; } else { width = columns[column + 1] - columns[column] - gap; } - + if (row == rows.length - 1) { height = parent.getHeight() - margin - rows[row]; } else { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutHorizontal.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutHorizontal.java index 85c37fa..fc940c3 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutHorizontal.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutHorizontal.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui.layout; import static java.lang.Math.max; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutVertical.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutVertical.java index 6e48d69..25c87ae 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutVertical.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutVertical.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui.layout; import static java.lang.Math.max; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/menu/MenuLayer.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/menu/MenuLayer.java index 4fa155c..7d6fff1 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/menu/MenuLayer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/menu/MenuLayer.java @@ -41,47 +41,47 @@ public class MenuLayer extends GUILayer { private final Component content; private final Component background; - + private final Runnable closeAction = () -> { GUI.removeLayer(this); }; - + public MenuLayer(String name, Component content) { super(name, new LayoutFill(0)); - + setCursorPolicy(CursorPolicy.REQUIRE); - + this.background = new Panel(name + ".Background", new LayoutAlign(10), Colors.toVector(0x66000000), null); this.content = content; - + background.addChild(content); getRoot().addChild(background); } - + public MenuLayer(String name, Layout contentLayout) { this(name, new Panel(name + ".Content", contentLayout)); } - + public MenuLayer(String name) { this(name, new LayoutVertical(20, 10)); } - + public Component getContent() { return content; } - + public Component getBackground() { return background; } - + protected void addTitle() { String translationKey = "Layer" + getName() + ".Title"; MutableString titleText = new MutableStringLocalized(translationKey); Font titleFont = new Font().deriveBold().withColor(Colors.BLACK).withAlign(0.5f); - + Label label = new Label(getName() + ".Title", titleFont, titleText); getContent().addChild(label); - + Panel panel = new Panel(getName() + ".Title.Underscore", null, Colors.BLUE, null); panel.setLayout(new LayoutFill() { @Override @@ -91,17 +91,17 @@ public class MenuLayer extends GUILayer { }); getContent().addChild(panel); } - + protected Runnable getCloseAction() { return closeAction; } - + @Override protected void handleInput(Input input) { - + if (!input.isConsumed()) { InputEvent event = input.getEvent(); - + if (event instanceof KeyEvent) { KeyEvent keyEvent = (KeyEvent) event; if (keyEvent.isPress() && keyEvent.getKey() == GLFW.GLFW_KEY_ESCAPE) { @@ -109,9 +109,9 @@ public class MenuLayer extends GUILayer { } } } - + super.handleInput(input); input.consume(); } - + } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/CursorEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/CursorEvent.java index 43dd965..8bc480b 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/CursorEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/CursorEvent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.input; import glm.vec._2.d.Vec2d; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/CursorMoveEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/CursorMoveEvent.java index c87fc62..d23af54 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/CursorMoveEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/CursorMoveEvent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.input; import glm.vec._2.Vec2; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/FrameResizeEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/FrameResizeEvent.java index 5589158..70c9870 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/FrameResizeEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/FrameResizeEvent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.input; import glm.vec._2.i.Vec2i; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/InputEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/InputEvent.java index b0c2483..dc8a187 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/InputEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/InputEvent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.input; public abstract class InputEvent { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyEvent.java index 291b89e..8df55be 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyEvent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.input; import org.lwjgl.glfw.GLFW; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyMatcher.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyMatcher.java index 6fedcd6..6073a7b 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyMatcher.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyMatcher.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.input; import java.util.function.Predicate; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/Keys.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/Keys.java index 3904f59..aa8940c 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/Keys.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/Keys.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.input; import java.lang.reflect.Field; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/WheelEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/WheelEvent.java index 24938c3..80c5282 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/WheelEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/WheelEvent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.input; public abstract class WheelEvent extends InputEvent { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/WheelScrollEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/WheelScrollEvent.java index 968ff64..0ba2d2b 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/WheelScrollEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/WheelScrollEvent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.input; import glm.vec._2.d.Vec2d; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/Input.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/Input.java index 1aad6bb..46da738 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/Input.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/Input.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.input.bus; import ru.windcorp.progressia.client.graphics.input.InputEvent; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputBus.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputBus.java index a22a243..233540a 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputBus.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputBus.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.input.bus; import java.util.ArrayList; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputListener.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputListener.java index 0d68b5e..f6e3811 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputListener.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputListener.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.input.bus; import ru.windcorp.progressia.client.graphics.input.InputEvent; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/BlockFaceVectors.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/BlockFaceVectors.java index 3b929c0..9b3abf9 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/BlockFaceVectors.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/BlockFaceVectors.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.model; import static ru.windcorp.progressia.common.world.block.BlockFace.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/DynamicModel.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/DynamicModel.java index 9460bd7..fb0e47d 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/DynamicModel.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/DynamicModel.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.model; import java.util.ArrayList; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/EmptyModel.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/EmptyModel.java index f9cff67..f3e40a0 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/EmptyModel.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/EmptyModel.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.model; import glm.mat._4.Mat4; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/Face.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/Face.java index 79da464..6b21711 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/Face.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/Face.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.model; import java.nio.ByteBuffer; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/FaceGroup.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/FaceGroup.java index ee91544..9df04df 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/FaceGroup.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/FaceGroup.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.model; import ru.windcorp.progressia.client.graphics.texture.Texture; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/Faces.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/Faces.java index d1e9c07..f685644 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/Faces.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/Faces.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.model; import java.nio.ShortBuffer; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/LambdaModel.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/LambdaModel.java index 0ae31bf..3f0d97d 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/LambdaModel.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/LambdaModel.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.model; import java.util.ArrayList; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/Model.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/Model.java index 47cd88b..5e59007 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/Model.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/Model.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.model; import glm.mat._4.Mat4; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/Renderable.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/Renderable.java index 6063685..b379b75 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/Renderable.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/Renderable.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.model; public interface Renderable { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/Shape.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/Shape.java index 145b149..3a29c74 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/Shape.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/Shape.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.model; import java.nio.ByteBuffer; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeRenderHelper.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeRenderHelper.java index 67578f6..b950d06 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeRenderHelper.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeRenderHelper.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.model; import glm.mat._4.Mat4; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeRenderProgram.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeRenderProgram.java index e27bc77..d2f0e3a 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeRenderProgram.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeRenderProgram.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.model; import java.nio.ByteBuffer; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java index 7ddd5d6..e1b2838 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.model; import java.util.Map; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/StaticModel.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/StaticModel.java index 4c489d3..32b7a8c 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/StaticModel.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/StaticModel.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.model; import java.util.ArrayList; @@ -78,7 +78,7 @@ public class StaticModel extends Model { private Mat4[] getTransforms() { return transforms.toArray(new Mat4[transforms.size()]); } - + public StaticModel build() { return new StaticModel(getParts(), getTransforms()); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/Atlases.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/Atlases.java index 94ed270..26a171d 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/Atlases.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/Atlases.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.texture; import java.io.IOException; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/ComplexTexture.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/ComplexTexture.java index a4f2881..9800508 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/ComplexTexture.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/ComplexTexture.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.texture; import java.util.Map; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTexture.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTexture.java index d772faa..f631f54 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTexture.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTexture.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.texture; public class SimpleTexture extends Texture { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTextures.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTextures.java index 12db086..f98b92d 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTextures.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTextures.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.texture; import java.io.IOException; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/Sprite.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/Sprite.java index fc13896..9655295 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/Sprite.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/Sprite.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.texture; import java.util.Objects; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/Texture.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/Texture.java index a4d89bf..3041679 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/Texture.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/Texture.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.texture; public abstract class Texture { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureData.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureData.java index 0453984..cc04c45 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureData.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureData.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.texture; import static org.lwjgl.opengl.GL11.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureDataEditor.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureDataEditor.java index 7079f59..8a7f5c3 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureDataEditor.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureDataEditor.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.texture; import static ru.windcorp.progressia.client.graphics.texture.TextureUtil.BYTES_PER_PIXEL; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureLoader.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureLoader.java index 18f2326..6b2ffdf 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureLoader.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureLoader.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.texture; import java.awt.Graphics2D; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java index a1895bb..62c981b 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.texture; import static org.lwjgl.opengl.GL11.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureSettings.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureSettings.java index 3dd43a4..0b75742 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureSettings.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureSettings.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.texture; public class TextureSettings { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureUtil.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureUtil.java index ea0fdee..adc5b9d 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureUtil.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureUtil.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.texture; import java.awt.Color; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java index 46b551c..58c84c1 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.world; import static java.lang.Math.*; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/EntityAnchor.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/EntityAnchor.java index d11ea92..b927133 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/EntityAnchor.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/EntityAnchor.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.world; import java.util.Collection; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java index 50709ac..72c9a2b 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.world; import java.util.ArrayList; @@ -57,7 +57,7 @@ public class LayerWorld extends Layer { super("World"); this.client = client; this.inputBasedControls = new InputBasedControls(client); - + setCursorPolicy(CursorPolicy.FORBID); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/LocalPlayer.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/LocalPlayer.java index 620185b..7a4443a 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/LocalPlayer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/LocalPlayer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.world; import ru.windcorp.progressia.client.Client; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/Selection.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/Selection.java index cd4ba29..3d997ee 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/Selection.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/Selection.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.world; import glm.vec._2.Vec2; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/WorldRenderHelper.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/WorldRenderHelper.java index de17238..b735876 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/WorldRenderHelper.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/WorldRenderHelper.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.world; import glm.mat._4.Mat4; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/WorldRenderProgram.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/WorldRenderProgram.java index 5e55297..75a6372 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/WorldRenderProgram.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/WorldRenderProgram.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.world; import java.nio.ByteBuffer; diff --git a/src/main/java/ru/windcorp/progressia/client/localization/LocaleListener.java b/src/main/java/ru/windcorp/progressia/client/localization/LocaleListener.java index b7c1f54..8e06d9f 100644 --- a/src/main/java/ru/windcorp/progressia/client/localization/LocaleListener.java +++ b/src/main/java/ru/windcorp/progressia/client/localization/LocaleListener.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.localization; @FunctionalInterface diff --git a/src/main/java/ru/windcorp/progressia/client/localization/Localizer.java b/src/main/java/ru/windcorp/progressia/client/localization/Localizer.java index b61d000..70ad714 100644 --- a/src/main/java/ru/windcorp/progressia/client/localization/Localizer.java +++ b/src/main/java/ru/windcorp/progressia/client/localization/Localizer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.localization; import java.lang.ref.WeakReference; diff --git a/src/main/java/ru/windcorp/progressia/client/localization/MutableString.java b/src/main/java/ru/windcorp/progressia/client/localization/MutableString.java index a96d804..702aafa 100644 --- a/src/main/java/ru/windcorp/progressia/client/localization/MutableString.java +++ b/src/main/java/ru/windcorp/progressia/client/localization/MutableString.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.localization; import java.lang.ref.WeakReference; diff --git a/src/main/java/ru/windcorp/progressia/client/localization/MutableStringConcat.java b/src/main/java/ru/windcorp/progressia/client/localization/MutableStringConcat.java index f31fbca..e16533e 100644 --- a/src/main/java/ru/windcorp/progressia/client/localization/MutableStringConcat.java +++ b/src/main/java/ru/windcorp/progressia/client/localization/MutableStringConcat.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.localization; public class MutableStringConcat extends MutableString { diff --git a/src/main/java/ru/windcorp/progressia/client/localization/MutableStringFormatter.java b/src/main/java/ru/windcorp/progressia/client/localization/MutableStringFormatter.java index fddba06..07fad9d 100644 --- a/src/main/java/ru/windcorp/progressia/client/localization/MutableStringFormatter.java +++ b/src/main/java/ru/windcorp/progressia/client/localization/MutableStringFormatter.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.localization; import java.util.IllegalFormatException; diff --git a/src/main/java/ru/windcorp/progressia/client/localization/MutableStringFunc.java b/src/main/java/ru/windcorp/progressia/client/localization/MutableStringFunc.java index d945618..82ae330 100644 --- a/src/main/java/ru/windcorp/progressia/client/localization/MutableStringFunc.java +++ b/src/main/java/ru/windcorp/progressia/client/localization/MutableStringFunc.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.localization; import java.util.function.Function; diff --git a/src/main/java/ru/windcorp/progressia/client/localization/MutableStringLocalized.java b/src/main/java/ru/windcorp/progressia/client/localization/MutableStringLocalized.java index 583d9e5..32a6d68 100644 --- a/src/main/java/ru/windcorp/progressia/client/localization/MutableStringLocalized.java +++ b/src/main/java/ru/windcorp/progressia/client/localization/MutableStringLocalized.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.localization; public class MutableStringLocalized extends MutableString { diff --git a/src/main/java/ru/windcorp/progressia/client/localization/MutableStringParented.java b/src/main/java/ru/windcorp/progressia/client/localization/MutableStringParented.java index d7b0fae..fd6c8fd 100644 --- a/src/main/java/ru/windcorp/progressia/client/localization/MutableStringParented.java +++ b/src/main/java/ru/windcorp/progressia/client/localization/MutableStringParented.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.localization; public abstract class MutableStringParented extends MutableString { diff --git a/src/main/java/ru/windcorp/progressia/client/localization/Parser.java b/src/main/java/ru/windcorp/progressia/client/localization/Parser.java index 7d587dc..d39e574 100644 --- a/src/main/java/ru/windcorp/progressia/client/localization/Parser.java +++ b/src/main/java/ru/windcorp/progressia/client/localization/Parser.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.localization; import ru.windcorp.jputil.chars.EscapeException; diff --git a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java index 21f6098..b4e4316 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world; import java.util.Collections; diff --git a/src/main/java/ru/windcorp/progressia/client/world/ChunkRenderModel.java b/src/main/java/ru/windcorp/progressia/client/world/ChunkRenderModel.java index 9653abe..ffd3b77 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/ChunkRenderModel.java +++ b/src/main/java/ru/windcorp/progressia/client/world/ChunkRenderModel.java @@ -39,9 +39,9 @@ import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.block.BlockFace; public class ChunkRenderModel implements Renderable { - + private final ChunkRender chunk; - + private final Collection optimizers = new ArrayList<>(); private Model model = null; @@ -51,8 +51,9 @@ public class ChunkRenderModel implements Renderable { @Override public void render(ShapeRenderHelper renderer) { - if (model == null) return; - + if (model == null) + return; + renderer.pushTransform().translate( chunk.getX() * ChunkData.BLOCKS_PER_CHUNK, chunk.getY() * ChunkData.BLOCKS_PER_CHUNK, @@ -63,32 +64,32 @@ public class ChunkRenderModel implements Renderable { renderer.popTransform(); } - + public void update() { setupCROs(); - + StaticModel.Builder sink = StaticModel.builder(); - + optimizers.forEach(ChunkRenderOptimizer::startRender); - + chunk.forEachBiC(blockInChunk -> { processBlockAndTiles(blockInChunk, sink); }); - + for (ChunkRenderOptimizer optimizer : optimizers) { Renderable renderable = optimizer.endRender(); if (renderable != null) { sink.addPart(renderable); } } - + this.model = sink.build(); this.optimizers.clear(); } private void setupCROs() { Set ids = ChunkRenderOptimizerRegistry.getInstance().keySet(); - + for (String id : ids) { ChunkRenderOptimizer optimizer = ChunkRenderOptimizerRegistry.getInstance().create(id); optimizer.setup(chunk); @@ -98,7 +99,7 @@ public class ChunkRenderModel implements Renderable { private void processBlockAndTiles(Vec3i blockInChunk, Builder sink) { processBlock(blockInChunk, sink); - + for (BlockFace face : BlockFace.getFaces()) { processTileStack(blockInChunk, face, sink); } @@ -106,18 +107,18 @@ public class ChunkRenderModel implements Renderable { private void processBlock(Vec3i blockInChunk, Builder sink) { BlockRender block = chunk.getBlock(blockInChunk); - + if (block instanceof BlockRenderNone) { return; } - + if (block.needsOwnRenderable()) { sink.addPart( - block.createRenderable(chunk.getData(), blockInChunk), + block.createRenderable(chunk.getData(), blockInChunk), new Mat4().identity().translate(blockInChunk.x, blockInChunk.y, blockInChunk.z) ); } - + processBlockWithCROs(block, blockInChunk); } @@ -129,26 +130,26 @@ public class ChunkRenderModel implements Renderable { private void processTileStack(Vec3i blockInChunk, BlockFace face, Builder sink) { TileRenderStack trs = chunk.getTilesOrNull(blockInChunk, face); - + if (trs == null || trs.isEmpty()) { return; } - + trs.forEach(tile -> processTile(tile, blockInChunk, face, sink)); } - private void processTile(TileRender tile, Vec3i blockInChunk, BlockFace face, Builder sink) { + private void processTile(TileRender tile, Vec3i blockInChunk, BlockFace face, Builder sink) { if (tile instanceof TileRenderNone) { return; } - + if (tile.needsOwnRenderable()) { sink.addPart( - tile.createRenderable(chunk.getData(), blockInChunk, face), + tile.createRenderable(chunk.getData(), blockInChunk, face), new Mat4().identity().translate(blockInChunk.x, blockInChunk.y, blockInChunk.z) ); } - + processTileWithCROs(tile, blockInChunk, face); } diff --git a/src/main/java/ru/windcorp/progressia/client/world/ChunkUpdateListener.java b/src/main/java/ru/windcorp/progressia/client/world/ChunkUpdateListener.java index c348498..ee606af 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/ChunkUpdateListener.java +++ b/src/main/java/ru/windcorp/progressia/client/world/ChunkUpdateListener.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world; import glm.vec._3.i.Vec3i; @@ -39,7 +39,7 @@ class ChunkUpdateListener implements ChunkDataListener { public void onChunkChanged(ChunkData chunk) { world.getChunk(chunk).markForUpdate(); } - + @Override public void onChunkLoaded(ChunkData chunk) { Vec3i cursor = new Vec3i(); @@ -49,12 +49,12 @@ class ChunkUpdateListener implements ChunkDataListener { world.markChunkForUpdate(cursor); } } - + @Override public void onChunkBlockChanged(ChunkData chunk, Vec3i blockInChunk, BlockData previous, BlockData current) { onLocationChanged(chunk, blockInChunk); } - + @Override public void onChunkTilesChanged( ChunkData chunk, @@ -68,18 +68,18 @@ class ChunkUpdateListener implements ChunkDataListener { private void onLocationChanged(ChunkData chunk, Vec3i blockInChunk) { Vec3i chunkPos = Vectors.grab3i().set(chunk.getX(), chunk.getY(), chunk.getZ()); - + checkCoordinate(blockInChunk, chunkPos, VectorUtil.Axis.X); checkCoordinate(blockInChunk, chunkPos, VectorUtil.Axis.Y); checkCoordinate(blockInChunk, chunkPos, VectorUtil.Axis.Z); - + Vectors.release(chunkPos); } private void checkCoordinate(Vec3i blockInChunk, Vec3i chunkPos, VectorUtil.Axis axis) { int block = VectorUtil.get(blockInChunk, axis); int diff = 0; - + if (block == 0) { diff = -1; } else if (block == ChunkData.BLOCKS_PER_CHUNK - 1) { @@ -87,12 +87,12 @@ class ChunkUpdateListener implements ChunkDataListener { } else { return; } - + int previousChunkPos = VectorUtil.get(chunkPos, axis); VectorUtil.set(chunkPos, axis, previousChunkPos + diff); world.markChunkForUpdate(chunkPos); - + VectorUtil.set(chunkPos, axis, previousChunkPos); } diff --git a/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java b/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java index 8be08c2..a83ee32 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world; import java.util.Collection; diff --git a/src/main/java/ru/windcorp/progressia/client/world/block/BlockRender.java b/src/main/java/ru/windcorp/progressia/client/world/block/BlockRender.java index d350fa8..6c3f939 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/block/BlockRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/block/BlockRender.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.block; import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; diff --git a/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderNone.java b/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderNone.java index 84a2c4b..3f422f2 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderNone.java +++ b/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderNone.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.block; import glm.vec._3.i.Vec3i; diff --git a/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderOpaqueCube.java b/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderOpaqueCube.java index e4d8723..e753667 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderOpaqueCube.java +++ b/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderOpaqueCube.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.block; import ru.windcorp.progressia.client.graphics.texture.Texture; diff --git a/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderRegistry.java b/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderRegistry.java index 29bac40..5724d27 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderRegistry.java +++ b/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderRegistry.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.block; import ru.windcorp.progressia.client.graphics.texture.Atlases; diff --git a/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderTexturedCube.java b/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderTexturedCube.java index 1042a46..d410a52 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderTexturedCube.java +++ b/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderTexturedCube.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.block; import static ru.windcorp.progressia.common.world.block.BlockFace.*; @@ -68,23 +68,27 @@ public abstract class BlockRenderTexturedCube public Texture getTexture(BlockFace blockFace) { return textures.get(blockFace); } - + public Vec4 getColorMultiplier(BlockFace blockFace) { return Colors.WHITE; } @Override public final void getFaces( - ChunkData chunk, Vec3i blockInChunk, BlockFace blockFace, + ChunkData chunk, + Vec3i blockInChunk, + BlockFace blockFace, boolean inner, Consumer output, Vec3 offset ) { output.accept(createFace(chunk, blockInChunk, blockFace, inner, offset)); } - + private Face createFace( - ChunkData chunk, Vec3i blockInChunk, BlockFace blockFace, + ChunkData chunk, + Vec3i blockInChunk, + BlockFace blockFace, boolean inner, Vec3 offset ) { @@ -101,19 +105,25 @@ public abstract class BlockRenderTexturedCube @Override public Renderable createRenderable(ChunkData chunk, Vec3i blockInChunk) { boolean opaque = isBlockOpaque(); - + Face[] faces = new Face[BLOCK_FACE_COUNT + (opaque ? BLOCK_FACE_COUNT : 0)]; - + for (int i = 0; i < BLOCK_FACE_COUNT; ++i) { faces[i] = createFace(chunk, blockInChunk, BlockFace.getFaces().get(i), false, Vectors.ZERO_3); } - + if (!opaque) { for (int i = 0; i < BLOCK_FACE_COUNT; ++i) { - faces[i + BLOCK_FACE_COUNT] = createFace(chunk, blockInChunk, BlockFace.getFaces().get(i), true, Vectors.ZERO_3); + faces[i + BLOCK_FACE_COUNT] = createFace( + chunk, + blockInChunk, + BlockFace.getFaces().get(i), + true, + Vectors.ZERO_3 + ); } } - + return new Shape(Usage.STATIC, WorldRenderProgram.getDefault(), faces); } diff --git a/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderTransparentCube.java b/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderTransparentCube.java index 7f3df03..02b8b45 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderTransparentCube.java +++ b/src/main/java/ru/windcorp/progressia/client/world/block/BlockRenderTransparentCube.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.block; import ru.windcorp.progressia.client.graphics.texture.Texture; diff --git a/src/main/java/ru/windcorp/progressia/client/world/cro/ChunkRenderOptimizerRegistry.java b/src/main/java/ru/windcorp/progressia/client/world/cro/ChunkRenderOptimizerRegistry.java index 7e4dc87..7676b4f 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/cro/ChunkRenderOptimizerRegistry.java +++ b/src/main/java/ru/windcorp/progressia/client/world/cro/ChunkRenderOptimizerRegistry.java @@ -15,15 +15,15 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.cro; import ru.windcorp.progressia.common.util.namespaces.NamespacedFactoryRegistry; public class ChunkRenderOptimizerRegistry extends NamespacedFactoryRegistry { - + private static final ChunkRenderOptimizerRegistry INSTANCE = new ChunkRenderOptimizerRegistry(); - + /** * @return the instance */ diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRender.java b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRender.java index 13a2b24..8243c9d 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRender.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.entity; import ru.windcorp.progressia.common.util.namespaces.Namespaced; diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java index 60b7bf6..1ffdda5 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.entity; import java.io.IOException; diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderable.java b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderable.java index eecaa16..361f7cd 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderable.java +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderable.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.entity; import glm.vec._3.Vec3; diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/HumanoidModel.java b/src/main/java/ru/windcorp/progressia/client/world/entity/HumanoidModel.java index 1609bfc..96704f3 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/entity/HumanoidModel.java +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/HumanoidModel.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.entity; import static java.lang.Math.*; diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/NPedModel.java b/src/main/java/ru/windcorp/progressia/client/world/entity/NPedModel.java index ead6565..05986e5 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/entity/NPedModel.java +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/NPedModel.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.entity; import static java.lang.Math.atan2; diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java b/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java index 8755b08..b586744 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.entity; import static java.lang.Math.*; diff --git a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRender.java b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRender.java index 4f82d86..6b6163b 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRender.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.tile; import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; diff --git a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderGrass.java b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderGrass.java index c73647b..762fcf4 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderGrass.java +++ b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderGrass.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.tile; import ru.windcorp.progressia.client.graphics.texture.Texture; diff --git a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderNone.java b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderNone.java index 8e2a6e4..56ea3cb 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderNone.java +++ b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderNone.java @@ -28,12 +28,12 @@ public class TileRenderNone extends TileRender { public TileRenderNone(String id) { super(id); } - + @Override public Renderable createRenderable(ChunkData chunk, Vec3i blockInChunk, BlockFace face) { return EmptyModel.getInstance(); } - + @Override public boolean needsOwnRenderable() { return false; diff --git a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderOpaqueSurface.java b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderOpaqueSurface.java index e4990e8..bcc9df5 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderOpaqueSurface.java +++ b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderOpaqueSurface.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.tile; import ru.windcorp.progressia.client.graphics.texture.Texture; diff --git a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderRegistry.java b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderRegistry.java index b240933..499db0e 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderRegistry.java +++ b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderRegistry.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.tile; import ru.windcorp.progressia.client.graphics.texture.Atlases; diff --git a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderStack.java b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderStack.java index 6bb8fb0..10b0757 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderStack.java +++ b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderStack.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.tile; import ru.windcorp.progressia.client.world.ChunkRender; diff --git a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderSurface.java b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderSurface.java index eebcb07..417bdbe 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderSurface.java +++ b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderSurface.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.tile; import java.util.function.Consumer; @@ -44,7 +44,7 @@ public abstract class TileRenderSurface extends TileRender implements TileOptimi super(id); this.texture = texture; } - + public TileRenderSurface(String id) { this(id, null); } @@ -52,23 +52,27 @@ public abstract class TileRenderSurface extends TileRender implements TileOptimi public Texture getTexture(BlockFace blockFace) { return texture; } - + public Vec4 getColorMultiplier(BlockFace blockFace) { return Colors.WHITE; } - + @Override public final void getFaces( - ChunkData chunk, Vec3i blockInChunk, BlockFace blockFace, + ChunkData chunk, + Vec3i blockInChunk, + BlockFace blockFace, boolean inner, Consumer output, Vec3 offset ) { output.accept(createFace(chunk, blockInChunk, blockFace, inner, offset)); } - + private Face createFace( - ChunkData chunk, Vec3i blockInChunk, BlockFace blockFace, + ChunkData chunk, + Vec3i blockInChunk, + BlockFace blockFace, boolean inner, Vec3 offset ) { @@ -87,9 +91,9 @@ public abstract class TileRenderSurface extends TileRender implements TileOptimi return new Shape( Usage.STATIC, WorldRenderProgram.getDefault(), - + createFace(chunk, blockInChunk, blockFace, false, Vectors.ZERO_3), - createFace(chunk, blockInChunk, blockFace, true, Vectors.ZERO_3) + createFace(chunk, blockInChunk, blockFace, true, Vectors.ZERO_3) ); } diff --git a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderTransparentSurface.java b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderTransparentSurface.java index b35986e..af512a9 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderTransparentSurface.java +++ b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderTransparentSurface.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.world.tile; import ru.windcorp.progressia.client.graphics.texture.Texture; diff --git a/src/main/java/ru/windcorp/progressia/common/Units.java b/src/main/java/ru/windcorp/progressia/common/Units.java index 842e378..979cc2d 100644 --- a/src/main/java/ru/windcorp/progressia/common/Units.java +++ b/src/main/java/ru/windcorp/progressia/common/Units.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common; import java.lang.annotation.ElementType; diff --git a/src/main/java/ru/windcorp/progressia/common/collision/AABB.java b/src/main/java/ru/windcorp/progressia/common/collision/AABB.java index fd8ffe9..3ecb58f 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/AABB.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/AABB.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.collision; import glm.vec._3.Vec3; diff --git a/src/main/java/ru/windcorp/progressia/common/collision/AABBoid.java b/src/main/java/ru/windcorp/progressia/common/collision/AABBoid.java index ab2cd80..04312f1 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/AABBoid.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/AABBoid.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.collision; import glm.vec._3.Vec3; diff --git a/src/main/java/ru/windcorp/progressia/common/collision/Collideable.java b/src/main/java/ru/windcorp/progressia/common/collision/Collideable.java index 8db7805..d96a472 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/Collideable.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/Collideable.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.collision; import glm.vec._3.Vec3; diff --git a/src/main/java/ru/windcorp/progressia/common/collision/CollisionModel.java b/src/main/java/ru/windcorp/progressia/common/collision/CollisionModel.java index 9ade6af..209063a 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/CollisionModel.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/CollisionModel.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.collision; import glm.vec._3.Vec3; diff --git a/src/main/java/ru/windcorp/progressia/common/collision/CollisionPathComputer.java b/src/main/java/ru/windcorp/progressia/common/collision/CollisionPathComputer.java index 4826bce..2f9598b 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/CollisionPathComputer.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/CollisionPathComputer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.collision; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/common/collision/CompoundCollisionModel.java b/src/main/java/ru/windcorp/progressia/common/collision/CompoundCollisionModel.java index 6f5ec24..a91dfdf 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/CompoundCollisionModel.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/CompoundCollisionModel.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.collision; import java.util.Collection; diff --git a/src/main/java/ru/windcorp/progressia/common/collision/TransformedCollisionModel.java b/src/main/java/ru/windcorp/progressia/common/collision/TransformedCollisionModel.java index 96bfbee..9622423 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/TransformedCollisionModel.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/TransformedCollisionModel.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.collision; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/common/collision/TranslatedAABB.java b/src/main/java/ru/windcorp/progressia/common/collision/TranslatedAABB.java index 4c33ad2..fd94cfc 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/TranslatedAABB.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/TranslatedAABB.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.collision; import glm.vec._3.Vec3; diff --git a/src/main/java/ru/windcorp/progressia/common/collision/Wall.java b/src/main/java/ru/windcorp/progressia/common/collision/Wall.java index 91ca006..91e9f72 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/Wall.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/Wall.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.collision; import glm.vec._3.Vec3; diff --git a/src/main/java/ru/windcorp/progressia/common/collision/WorldCollisionHelper.java b/src/main/java/ru/windcorp/progressia/common/collision/WorldCollisionHelper.java index 69d2d4a..5280994 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/WorldCollisionHelper.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/WorldCollisionHelper.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.collision; import java.util.ArrayList; diff --git a/src/main/java/ru/windcorp/progressia/common/collision/colliders/AABBoidCollider.java b/src/main/java/ru/windcorp/progressia/common/collision/colliders/AABBoidCollider.java index 5fab3d8..0750e79 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/colliders/AABBoidCollider.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/colliders/AABBoidCollider.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.collision.colliders; import glm.mat._3.Mat3; diff --git a/src/main/java/ru/windcorp/progressia/common/collision/colliders/AnythingWithCompoundCollider.java b/src/main/java/ru/windcorp/progressia/common/collision/colliders/AnythingWithCompoundCollider.java index 559de13..2680098 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/colliders/AnythingWithCompoundCollider.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/colliders/AnythingWithCompoundCollider.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.collision.colliders; import ru.windcorp.progressia.common.collision.Collideable; diff --git a/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java b/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java index 56bc8ad..fe47a8e 100644 --- a/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java +++ b/src/main/java/ru/windcorp/progressia/common/collision/colliders/Collider.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.collision.colliders; import java.util.Collection; diff --git a/src/main/java/ru/windcorp/progressia/common/comms/CommsChannel.java b/src/main/java/ru/windcorp/progressia/common/comms/CommsChannel.java index 288b5dd..45c6d0a 100644 --- a/src/main/java/ru/windcorp/progressia/common/comms/CommsChannel.java +++ b/src/main/java/ru/windcorp/progressia/common/comms/CommsChannel.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.comms; import java.io.IOException; diff --git a/src/main/java/ru/windcorp/progressia/common/comms/CommsListener.java b/src/main/java/ru/windcorp/progressia/common/comms/CommsListener.java index 7445e93..e133cf8 100644 --- a/src/main/java/ru/windcorp/progressia/common/comms/CommsListener.java +++ b/src/main/java/ru/windcorp/progressia/common/comms/CommsListener.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.comms; import java.io.IOException; diff --git a/src/main/java/ru/windcorp/progressia/common/comms/controls/ControlData.java b/src/main/java/ru/windcorp/progressia/common/comms/controls/ControlData.java index 46e4e94..d90505b 100644 --- a/src/main/java/ru/windcorp/progressia/common/comms/controls/ControlData.java +++ b/src/main/java/ru/windcorp/progressia/common/comms/controls/ControlData.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.comms.controls; import ru.windcorp.progressia.common.util.namespaces.Namespaced; diff --git a/src/main/java/ru/windcorp/progressia/common/comms/controls/ControlDataRegistry.java b/src/main/java/ru/windcorp/progressia/common/comms/controls/ControlDataRegistry.java index cd884e8..59a8529 100644 --- a/src/main/java/ru/windcorp/progressia/common/comms/controls/ControlDataRegistry.java +++ b/src/main/java/ru/windcorp/progressia/common/comms/controls/ControlDataRegistry.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.comms.controls; import ru.windcorp.progressia.common.util.namespaces.NamespacedFactoryRegistry; diff --git a/src/main/java/ru/windcorp/progressia/common/comms/controls/PacketControl.java b/src/main/java/ru/windcorp/progressia/common/comms/controls/PacketControl.java index d5abd39..2d352bb 100644 --- a/src/main/java/ru/windcorp/progressia/common/comms/controls/PacketControl.java +++ b/src/main/java/ru/windcorp/progressia/common/comms/controls/PacketControl.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.comms.controls; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/comms/packets/Packet.java b/src/main/java/ru/windcorp/progressia/common/comms/packets/Packet.java index 5421028..8669eb3 100644 --- a/src/main/java/ru/windcorp/progressia/common/comms/packets/Packet.java +++ b/src/main/java/ru/windcorp/progressia/common/comms/packets/Packet.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.comms.packets; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/hacks/GuavaEventBusHijacker.java b/src/main/java/ru/windcorp/progressia/common/hacks/GuavaEventBusHijacker.java index 6bc7901..ece4dc0 100644 --- a/src/main/java/ru/windcorp/progressia/common/hacks/GuavaEventBusHijacker.java +++ b/src/main/java/ru/windcorp/progressia/common/hacks/GuavaEventBusHijacker.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.hacks; import java.lang.reflect.Constructor; diff --git a/src/main/java/ru/windcorp/progressia/common/resource/Resource.java b/src/main/java/ru/windcorp/progressia/common/resource/Resource.java index 6cd4d32..41cf621 100644 --- a/src/main/java/ru/windcorp/progressia/common/resource/Resource.java +++ b/src/main/java/ru/windcorp/progressia/common/resource/Resource.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.resource; import java.io.IOException; @@ -34,7 +34,7 @@ import ru.windcorp.progressia.common.util.Named; import ru.windcorp.progressia.common.util.crash.CrashReports; public class Resource extends Named { - + private final ResourceReader resourceReader; public Resource(String name, ResourceReader resourceReader) { @@ -45,7 +45,7 @@ public class Resource extends Named { public InputStream getInputStream() { return getResourceReader().read(getName()); } - + public ResourceReader getResourceReader() { return resourceReader; } diff --git a/src/main/java/ru/windcorp/progressia/common/resource/ResourceManager.java b/src/main/java/ru/windcorp/progressia/common/resource/ResourceManager.java index 33db64d..fcfc43f 100644 --- a/src/main/java/ru/windcorp/progressia/common/resource/ResourceManager.java +++ b/src/main/java/ru/windcorp/progressia/common/resource/ResourceManager.java @@ -15,18 +15,18 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.resource; public class ResourceManager { - + private static final ResourceReader CLASSPATH_READER = new ClasspathResourceReader(); private static final ResourceReader FILESYSTEM_READER = new FilesystemResourceReader(); public static Resource getResource(String name) { return new Resource(name, CLASSPATH_READER); } - + public static Resource getFileResource(String name) { return new Resource(name, FILESYSTEM_READER); } diff --git a/src/main/java/ru/windcorp/progressia/common/resource/ResourceReader.java b/src/main/java/ru/windcorp/progressia/common/resource/ResourceReader.java index 1f95f2c..49c221c 100644 --- a/src/main/java/ru/windcorp/progressia/common/resource/ResourceReader.java +++ b/src/main/java/ru/windcorp/progressia/common/resource/ResourceReader.java @@ -20,7 +20,7 @@ package ru.windcorp.progressia.common.resource; import java.io.InputStream; public interface ResourceReader { - + InputStream read(String name); } diff --git a/src/main/java/ru/windcorp/progressia/common/state/AbstractStatefulObjectLayout.java b/src/main/java/ru/windcorp/progressia/common/state/AbstractStatefulObjectLayout.java index b2feb80..99a0340 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/AbstractStatefulObjectLayout.java +++ b/src/main/java/ru/windcorp/progressia/common/state/AbstractStatefulObjectLayout.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.state; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/state/HashMapStateStorage.java b/src/main/java/ru/windcorp/progressia/common/state/HashMapStateStorage.java index 52d446f..56ee25d 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/HashMapStateStorage.java +++ b/src/main/java/ru/windcorp/progressia/common/state/HashMapStateStorage.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.state; import gnu.trove.map.TIntIntMap; diff --git a/src/main/java/ru/windcorp/progressia/common/state/IOContext.java b/src/main/java/ru/windcorp/progressia/common/state/IOContext.java index b18f875..75d61fc 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/IOContext.java +++ b/src/main/java/ru/windcorp/progressia/common/state/IOContext.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.state; public enum IOContext { diff --git a/src/main/java/ru/windcorp/progressia/common/state/InspectingStatefulObjectLayout.java b/src/main/java/ru/windcorp/progressia/common/state/InspectingStatefulObjectLayout.java index 8b0a9fe..d8ec92e 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/InspectingStatefulObjectLayout.java +++ b/src/main/java/ru/windcorp/progressia/common/state/InspectingStatefulObjectLayout.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.state; import java.util.ArrayList; diff --git a/src/main/java/ru/windcorp/progressia/common/state/IntStateField.java b/src/main/java/ru/windcorp/progressia/common/state/IntStateField.java index abf8573..054740e 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/IntStateField.java +++ b/src/main/java/ru/windcorp/progressia/common/state/IntStateField.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.state; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/state/OptimizedStateStorage.java b/src/main/java/ru/windcorp/progressia/common/state/OptimizedStateStorage.java index 478fbac..fbedec7 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/OptimizedStateStorage.java +++ b/src/main/java/ru/windcorp/progressia/common/state/OptimizedStateStorage.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.state; public class OptimizedStateStorage extends StateStorage { diff --git a/src/main/java/ru/windcorp/progressia/common/state/OptimizedStatefulObjectLayout.java b/src/main/java/ru/windcorp/progressia/common/state/OptimizedStatefulObjectLayout.java index 1158ab0..0f0a173 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/OptimizedStatefulObjectLayout.java +++ b/src/main/java/ru/windcorp/progressia/common/state/OptimizedStatefulObjectLayout.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.state; import java.util.List; diff --git a/src/main/java/ru/windcorp/progressia/common/state/PrimitiveCounters.java b/src/main/java/ru/windcorp/progressia/common/state/PrimitiveCounters.java index d3e2dbb..243d62a 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/PrimitiveCounters.java +++ b/src/main/java/ru/windcorp/progressia/common/state/PrimitiveCounters.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.state; class PrimitiveCounters { diff --git a/src/main/java/ru/windcorp/progressia/common/state/StateChanger.java b/src/main/java/ru/windcorp/progressia/common/state/StateChanger.java index cc8cd5a..a93e64e 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/StateChanger.java +++ b/src/main/java/ru/windcorp/progressia/common/state/StateChanger.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.state; public interface StateChanger { diff --git a/src/main/java/ru/windcorp/progressia/common/state/StateField.java b/src/main/java/ru/windcorp/progressia/common/state/StateField.java index ca88c4f..ef56c0f 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/StateField.java +++ b/src/main/java/ru/windcorp/progressia/common/state/StateField.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.state; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/state/StateFieldBuilder.java b/src/main/java/ru/windcorp/progressia/common/state/StateFieldBuilder.java index 97c7176..935129a 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/StateFieldBuilder.java +++ b/src/main/java/ru/windcorp/progressia/common/state/StateFieldBuilder.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.state; public interface StateFieldBuilder { diff --git a/src/main/java/ru/windcorp/progressia/common/state/StateStorage.java b/src/main/java/ru/windcorp/progressia/common/state/StateStorage.java index 2f999f0..647ae00 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/StateStorage.java +++ b/src/main/java/ru/windcorp/progressia/common/state/StateStorage.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.state; public abstract class StateStorage { diff --git a/src/main/java/ru/windcorp/progressia/common/state/StatefulObject.java b/src/main/java/ru/windcorp/progressia/common/state/StatefulObject.java index 39f5b58..5a9ee27 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/StatefulObject.java +++ b/src/main/java/ru/windcorp/progressia/common/state/StatefulObject.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.state; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/state/StatefulObjectLayout.java b/src/main/java/ru/windcorp/progressia/common/state/StatefulObjectLayout.java index 4490cdf..60b95bf 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/StatefulObjectLayout.java +++ b/src/main/java/ru/windcorp/progressia/common/state/StatefulObjectLayout.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.state; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/state/StatefulObjectRegistry.java b/src/main/java/ru/windcorp/progressia/common/state/StatefulObjectRegistry.java index aa082a6..7811ec4 100644 --- a/src/main/java/ru/windcorp/progressia/common/state/StatefulObjectRegistry.java +++ b/src/main/java/ru/windcorp/progressia/common/state/StatefulObjectRegistry.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.state; import java.util.Collections; diff --git a/src/main/java/ru/windcorp/progressia/common/util/BinUtil.java b/src/main/java/ru/windcorp/progressia/common/util/BinUtil.java index ffc8a43..042d2a1 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/BinUtil.java +++ b/src/main/java/ru/windcorp/progressia/common/util/BinUtil.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util; public class BinUtil { diff --git a/src/main/java/ru/windcorp/progressia/common/util/ByteBufferInputStream.java b/src/main/java/ru/windcorp/progressia/common/util/ByteBufferInputStream.java index 6b317a7..f3380a9 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/ByteBufferInputStream.java +++ b/src/main/java/ru/windcorp/progressia/common/util/ByteBufferInputStream.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util; import java.io.InputStream; diff --git a/src/main/java/ru/windcorp/progressia/common/util/ByteBufferOutputStream.java b/src/main/java/ru/windcorp/progressia/common/util/ByteBufferOutputStream.java index 8931c75..152a17f 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/ByteBufferOutputStream.java +++ b/src/main/java/ru/windcorp/progressia/common/util/ByteBufferOutputStream.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util; import java.io.IOException; diff --git a/src/main/java/ru/windcorp/progressia/common/util/CoordinatePacker.java b/src/main/java/ru/windcorp/progressia/common/util/CoordinatePacker.java index 0ef2413..8a98dd3 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/CoordinatePacker.java +++ b/src/main/java/ru/windcorp/progressia/common/util/CoordinatePacker.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util; import glm.vec._2.i.Vec2i; diff --git a/src/main/java/ru/windcorp/progressia/common/util/DataBuffer.java b/src/main/java/ru/windcorp/progressia/common/util/DataBuffer.java index 23522c1..f018fc6 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/DataBuffer.java +++ b/src/main/java/ru/windcorp/progressia/common/util/DataBuffer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/util/FloatMathUtil.java b/src/main/java/ru/windcorp/progressia/common/util/FloatMathUtil.java index 43487c0..a1008de 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/FloatMathUtil.java +++ b/src/main/java/ru/windcorp/progressia/common/util/FloatMathUtil.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util; public class FloatMathUtil { diff --git a/src/main/java/ru/windcorp/progressia/common/util/LowOverheadCache.java b/src/main/java/ru/windcorp/progressia/common/util/LowOverheadCache.java index c5b2952..9d668e9 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/LowOverheadCache.java +++ b/src/main/java/ru/windcorp/progressia/common/util/LowOverheadCache.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util; import java.util.ArrayList; diff --git a/src/main/java/ru/windcorp/progressia/common/util/Matrices.java b/src/main/java/ru/windcorp/progressia/common/util/Matrices.java index 8804272..6534d5b 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/Matrices.java +++ b/src/main/java/ru/windcorp/progressia/common/util/Matrices.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util; import glm.mat._3.Mat3; diff --git a/src/main/java/ru/windcorp/progressia/common/util/MultiLOC.java b/src/main/java/ru/windcorp/progressia/common/util/MultiLOC.java index 295244d..3d417ac 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/MultiLOC.java +++ b/src/main/java/ru/windcorp/progressia/common/util/MultiLOC.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util; import java.util.HashMap; diff --git a/src/main/java/ru/windcorp/progressia/common/util/Named.java b/src/main/java/ru/windcorp/progressia/common/util/Named.java index d9fc97a..8722ad4 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/Named.java +++ b/src/main/java/ru/windcorp/progressia/common/util/Named.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util; import java.util.Objects; diff --git a/src/main/java/ru/windcorp/progressia/common/util/SizeLimitedList.java b/src/main/java/ru/windcorp/progressia/common/util/SizeLimitedList.java index 2010ccb..050fd94 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/SizeLimitedList.java +++ b/src/main/java/ru/windcorp/progressia/common/util/SizeLimitedList.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util; import java.util.Collection; diff --git a/src/main/java/ru/windcorp/progressia/common/util/StashingStack.java b/src/main/java/ru/windcorp/progressia/common/util/StashingStack.java index 394c79d..9f7f8e7 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/StashingStack.java +++ b/src/main/java/ru/windcorp/progressia/common/util/StashingStack.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util; import java.util.Arrays; diff --git a/src/main/java/ru/windcorp/progressia/common/util/TaskQueue.java b/src/main/java/ru/windcorp/progressia/common/util/TaskQueue.java index a081356..325619d 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/TaskQueue.java +++ b/src/main/java/ru/windcorp/progressia/common/util/TaskQueue.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util; import java.util.Collection; diff --git a/src/main/java/ru/windcorp/progressia/common/util/VectorUtil.java b/src/main/java/ru/windcorp/progressia/common/util/VectorUtil.java index 00ede3e..dfb9f1e 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/VectorUtil.java +++ b/src/main/java/ru/windcorp/progressia/common/util/VectorUtil.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/common/util/Vectors.java b/src/main/java/ru/windcorp/progressia/common/util/Vectors.java index 7d99ea5..fb0a20a 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/Vectors.java +++ b/src/main/java/ru/windcorp/progressia/common/util/Vectors.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util; import glm.vec._2.Vec2; diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java b/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java index 3289c3d..715aa66 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.crash; /** diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java index 5b62663..92d94ac 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.crash; import java.util.Map; diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReports.java b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReports.java index ab0ec3e..8c80681 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReports.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReports.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.crash; import org.apache.logging.log4j.LogManager; diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/ReportingEventBus.java b/src/main/java/ru/windcorp/progressia/common/util/crash/ReportingEventBus.java index 141efa9..d7e5315 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/ReportingEventBus.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/ReportingEventBus.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.crash; import com.google.common.eventbus.EventBus; diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java b/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java index c07152f..647e9b3 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.crash.analyzers; import ru.windcorp.progressia.common.util.crash.Analyzer; diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/ArgsContextProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/ArgsContextProvider.java index 6c16902..55786c5 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/ArgsContextProvider.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/ArgsContextProvider.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.crash.providers; import ru.windcorp.progressia.ProgressiaLauncher; diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/JavaVersionContextProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/JavaVersionContextProvider.java index b8f4358..184a916 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/JavaVersionContextProvider.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/JavaVersionContextProvider.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.crash.providers; import ru.windcorp.progressia.common.util.crash.ContextProvider; diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/LanguageContextProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/LanguageContextProvider.java index ca9d387..8de2668 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/LanguageContextProvider.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/LanguageContextProvider.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.crash.providers; import ru.windcorp.progressia.client.localization.Localizer; diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java index 7fd4610..56752fd 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.crash.providers; import ru.windcorp.progressia.common.util.crash.ContextProvider; diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OpenALContextProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OpenALContextProvider.java index ad31bba..77626b3 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OpenALContextProvider.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OpenALContextProvider.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.crash.providers; import ru.windcorp.progressia.client.audio.AudioManager; diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/RAMContextProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/RAMContextProvider.java index 9c60921..2d91e5f 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/RAMContextProvider.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/RAMContextProvider.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.crash.providers; import ru.windcorp.progressia.common.util.crash.ContextProvider; diff --git a/src/main/java/ru/windcorp/progressia/common/util/dynstr/DoubleFlusher.java b/src/main/java/ru/windcorp/progressia/common/util/dynstr/DoubleFlusher.java index 6068669..ab21b4b 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/dynstr/DoubleFlusher.java +++ b/src/main/java/ru/windcorp/progressia/common/util/dynstr/DoubleFlusher.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.dynstr; import gnu.trove.list.TCharList; diff --git a/src/main/java/ru/windcorp/progressia/common/util/dynstr/DynamicString.java b/src/main/java/ru/windcorp/progressia/common/util/dynstr/DynamicString.java index 8376a3d..2266943 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/dynstr/DynamicString.java +++ b/src/main/java/ru/windcorp/progressia/common/util/dynstr/DynamicString.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.dynstr; import java.util.function.Supplier; diff --git a/src/main/java/ru/windcorp/progressia/common/util/dynstr/DynamicStrings.java b/src/main/java/ru/windcorp/progressia/common/util/dynstr/DynamicStrings.java index 030cd9d..0b5745e 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/dynstr/DynamicStrings.java +++ b/src/main/java/ru/windcorp/progressia/common/util/dynstr/DynamicStrings.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.dynstr; import java.util.ArrayList; diff --git a/src/main/java/ru/windcorp/progressia/common/util/dynstr/FloatFlusher.java b/src/main/java/ru/windcorp/progressia/common/util/dynstr/FloatFlusher.java index 0b245ee..26a727e 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/dynstr/FloatFlusher.java +++ b/src/main/java/ru/windcorp/progressia/common/util/dynstr/FloatFlusher.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.dynstr; import gnu.trove.list.TCharList; diff --git a/src/main/java/ru/windcorp/progressia/common/util/dynstr/IntFlusher.java b/src/main/java/ru/windcorp/progressia/common/util/dynstr/IntFlusher.java index 9924f81..64f98a7 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/dynstr/IntFlusher.java +++ b/src/main/java/ru/windcorp/progressia/common/util/dynstr/IntFlusher.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.dynstr; import gnu.trove.list.TCharList; diff --git a/src/main/java/ru/windcorp/progressia/common/util/namespaces/IllegalIdException.java b/src/main/java/ru/windcorp/progressia/common/util/namespaces/IllegalIdException.java index d896bac..cb5da76 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/namespaces/IllegalIdException.java +++ b/src/main/java/ru/windcorp/progressia/common/util/namespaces/IllegalIdException.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.namespaces; public class IllegalIdException extends RuntimeException { diff --git a/src/main/java/ru/windcorp/progressia/common/util/namespaces/Namespaced.java b/src/main/java/ru/windcorp/progressia/common/util/namespaces/Namespaced.java index 2d87007..557804b 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/namespaces/Namespaced.java +++ b/src/main/java/ru/windcorp/progressia/common/util/namespaces/Namespaced.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.namespaces; public abstract class Namespaced { diff --git a/src/main/java/ru/windcorp/progressia/common/util/namespaces/NamespacedFactoryRegistry.java b/src/main/java/ru/windcorp/progressia/common/util/namespaces/NamespacedFactoryRegistry.java index 2a94593..e4a4303 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/namespaces/NamespacedFactoryRegistry.java +++ b/src/main/java/ru/windcorp/progressia/common/util/namespaces/NamespacedFactoryRegistry.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.namespaces; import java.util.Collection; diff --git a/src/main/java/ru/windcorp/progressia/common/util/namespaces/NamespacedInstanceRegistry.java b/src/main/java/ru/windcorp/progressia/common/util/namespaces/NamespacedInstanceRegistry.java index ce1f3cf..7b3f01d 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/namespaces/NamespacedInstanceRegistry.java +++ b/src/main/java/ru/windcorp/progressia/common/util/namespaces/NamespacedInstanceRegistry.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.namespaces; import java.util.Collection; diff --git a/src/main/java/ru/windcorp/progressia/common/util/namespaces/NamespacedUtil.java b/src/main/java/ru/windcorp/progressia/common/util/namespaces/NamespacedUtil.java index b969b8e..ecff557 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/namespaces/NamespacedUtil.java +++ b/src/main/java/ru/windcorp/progressia/common/util/namespaces/NamespacedUtil.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.util.namespaces; import java.util.Objects; diff --git a/src/main/java/ru/windcorp/progressia/common/world/BlockRay.java b/src/main/java/ru/windcorp/progressia/common/world/BlockRay.java index 4d5f1f9..0cfc0be 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/BlockRay.java +++ b/src/main/java/ru/windcorp/progressia/common/world/BlockRay.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world; import glm.vec._3.Vec3; diff --git a/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java b/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java index 252429c..b6a2c42 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world; import static ru.windcorp.progressia.common.world.block.BlockFace.*; diff --git a/src/main/java/ru/windcorp/progressia/common/world/ChunkDataListener.java b/src/main/java/ru/windcorp/progressia/common/world/ChunkDataListener.java index 72008c4..17abda8 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/ChunkDataListener.java +++ b/src/main/java/ru/windcorp/progressia/common/world/ChunkDataListener.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world; import glm.vec._3.i.Vec3i; diff --git a/src/main/java/ru/windcorp/progressia/common/world/ChunkDataListeners.java b/src/main/java/ru/windcorp/progressia/common/world/ChunkDataListeners.java index b39437c..fdae0ab 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/ChunkDataListeners.java +++ b/src/main/java/ru/windcorp/progressia/common/world/ChunkDataListeners.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/common/world/Coordinates.java b/src/main/java/ru/windcorp/progressia/common/world/Coordinates.java index 55f2076..ea1de1a 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/Coordinates.java +++ b/src/main/java/ru/windcorp/progressia/common/world/Coordinates.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world; import static ru.windcorp.progressia.common.world.ChunkData.BLOCKS_PER_CHUNK; @@ -158,7 +158,7 @@ public class Coordinates { return output; } - + public static boolean isOnChunkBorder(int blockInChunk) { return blockInChunk == 0 || blockInChunk == BLOCKS_PER_CHUNK - 1; } diff --git a/src/main/java/ru/windcorp/progressia/common/world/DecodingException.java b/src/main/java/ru/windcorp/progressia/common/world/DecodingException.java index 532d22f..410bfad 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/DecodingException.java +++ b/src/main/java/ru/windcorp/progressia/common/world/DecodingException.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world; /** diff --git a/src/main/java/ru/windcorp/progressia/common/world/IllegalCoordinatesException.java b/src/main/java/ru/windcorp/progressia/common/world/IllegalCoordinatesException.java index 69240cf..5fa2d9d 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/IllegalCoordinatesException.java +++ b/src/main/java/ru/windcorp/progressia/common/world/IllegalCoordinatesException.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world; public class IllegalCoordinatesException extends RuntimeException { diff --git a/src/main/java/ru/windcorp/progressia/common/world/PacketAffectChunk.java b/src/main/java/ru/windcorp/progressia/common/world/PacketAffectChunk.java index 95e6eab..fdd4ce3 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/PacketAffectChunk.java +++ b/src/main/java/ru/windcorp/progressia/common/world/PacketAffectChunk.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world; import glm.vec._3.i.Vec3i; diff --git a/src/main/java/ru/windcorp/progressia/common/world/PacketAffectWorld.java b/src/main/java/ru/windcorp/progressia/common/world/PacketAffectWorld.java index 8433b9b..1432f1c 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/PacketAffectWorld.java +++ b/src/main/java/ru/windcorp/progressia/common/world/PacketAffectWorld.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world; import ru.windcorp.progressia.common.comms.packets.Packet; diff --git a/src/main/java/ru/windcorp/progressia/common/world/PacketRevokeChunk.java b/src/main/java/ru/windcorp/progressia/common/world/PacketRevokeChunk.java index c65b045..c1ab7e3 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/PacketRevokeChunk.java +++ b/src/main/java/ru/windcorp/progressia/common/world/PacketRevokeChunk.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/world/PacketSendChunk.java b/src/main/java/ru/windcorp/progressia/common/world/PacketSendChunk.java index ca079ff..12a78c8 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/PacketSendChunk.java +++ b/src/main/java/ru/windcorp/progressia/common/world/PacketSendChunk.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/world/PacketSetLocalPlayer.java b/src/main/java/ru/windcorp/progressia/common/world/PacketSetLocalPlayer.java index f835614..625a4c5 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/PacketSetLocalPlayer.java +++ b/src/main/java/ru/windcorp/progressia/common/world/PacketSetLocalPlayer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/world/PlayerData.java b/src/main/java/ru/windcorp/progressia/common/world/PlayerData.java index 2123e3f..ecd512b 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/PlayerData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/PlayerData.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world; import ru.windcorp.progressia.common.world.entity.EntityData; diff --git a/src/main/java/ru/windcorp/progressia/common/world/WorldData.java b/src/main/java/ru/windcorp/progressia/common/world/WorldData.java index 85c6188..6201df9 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/WorldData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/WorldData.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world; import java.util.ArrayList; diff --git a/src/main/java/ru/windcorp/progressia/common/world/WorldDataListener.java b/src/main/java/ru/windcorp/progressia/common/world/WorldDataListener.java index 9211efd..9b81d12 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/WorldDataListener.java +++ b/src/main/java/ru/windcorp/progressia/common/world/WorldDataListener.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/common/world/block/BlockData.java b/src/main/java/ru/windcorp/progressia/common/world/block/BlockData.java index e94f838..2c9d352 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/block/BlockData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/block/BlockData.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.block; import ru.windcorp.progressia.common.collision.AABB; diff --git a/src/main/java/ru/windcorp/progressia/common/world/block/BlockDataRegistry.java b/src/main/java/ru/windcorp/progressia/common/world/block/BlockDataRegistry.java index ac1934c..68b7412 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/block/BlockDataRegistry.java +++ b/src/main/java/ru/windcorp/progressia/common/world/block/BlockDataRegistry.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.block; import ru.windcorp.progressia.common.util.namespaces.NamespacedInstanceRegistry; diff --git a/src/main/java/ru/windcorp/progressia/common/world/block/BlockFace.java b/src/main/java/ru/windcorp/progressia/common/world/block/BlockFace.java index 9023500..92210ea 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/block/BlockFace.java +++ b/src/main/java/ru/windcorp/progressia/common/world/block/BlockFace.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.block; import com.google.common.collect.ImmutableList; diff --git a/src/main/java/ru/windcorp/progressia/common/world/block/BlockRelation.java b/src/main/java/ru/windcorp/progressia/common/world/block/BlockRelation.java index 659a5fa..46ff044 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/block/BlockRelation.java +++ b/src/main/java/ru/windcorp/progressia/common/world/block/BlockRelation.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.block; import static java.lang.Math.abs; @@ -43,7 +43,7 @@ public class BlockRelation { public Vec3i getVector() { return vector; } - + public Vec3 getFloatVector() { return floatVector; } diff --git a/src/main/java/ru/windcorp/progressia/common/world/block/PacketAffectBlock.java b/src/main/java/ru/windcorp/progressia/common/world/block/PacketAffectBlock.java index 2c1c8a2..5a4a3ac 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/block/PacketAffectBlock.java +++ b/src/main/java/ru/windcorp/progressia/common/world/block/PacketAffectBlock.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.block; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/world/block/PacketSetBlock.java b/src/main/java/ru/windcorp/progressia/common/world/block/PacketSetBlock.java index 55d0eb2..a29fa2e 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/block/PacketSetBlock.java +++ b/src/main/java/ru/windcorp/progressia/common/world/block/PacketSetBlock.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.block; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java index 7b3325c..2ed2263 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityData.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.entity; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataRegistry.java b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataRegistry.java index 26f219d..34271ae 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataRegistry.java +++ b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataRegistry.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.entity; import ru.windcorp.progressia.common.state.StatefulObjectRegistry; diff --git a/src/main/java/ru/windcorp/progressia/common/world/entity/PacketAffectEntity.java b/src/main/java/ru/windcorp/progressia/common/world/entity/PacketAffectEntity.java index f3bf792..aefd64e 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/entity/PacketAffectEntity.java +++ b/src/main/java/ru/windcorp/progressia/common/world/entity/PacketAffectEntity.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.entity; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/world/entity/PacketChangeEntity.java b/src/main/java/ru/windcorp/progressia/common/world/entity/PacketChangeEntity.java index d09b0f3..515f1f0 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/entity/PacketChangeEntity.java +++ b/src/main/java/ru/windcorp/progressia/common/world/entity/PacketChangeEntity.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.entity; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/world/entity/PacketRevokeEntity.java b/src/main/java/ru/windcorp/progressia/common/world/entity/PacketRevokeEntity.java index 06dfc12..98b1d88 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/entity/PacketRevokeEntity.java +++ b/src/main/java/ru/windcorp/progressia/common/world/entity/PacketRevokeEntity.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.entity; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/world/entity/PacketSendEntity.java b/src/main/java/ru/windcorp/progressia/common/world/entity/PacketSendEntity.java index 6604d4a..93d724c 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/entity/PacketSendEntity.java +++ b/src/main/java/ru/windcorp/progressia/common/world/entity/PacketSendEntity.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.entity; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/world/generic/ChunkMap.java b/src/main/java/ru/windcorp/progressia/common/world/generic/ChunkMap.java index 6c35781..7176386 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/generic/ChunkMap.java +++ b/src/main/java/ru/windcorp/progressia/common/world/generic/ChunkMap.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.generic; import java.util.Collection; diff --git a/src/main/java/ru/windcorp/progressia/common/world/generic/ChunkSet.java b/src/main/java/ru/windcorp/progressia/common/world/generic/ChunkSet.java index 73c2267..c6e4fd3 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/generic/ChunkSet.java +++ b/src/main/java/ru/windcorp/progressia/common/world/generic/ChunkSet.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.generic; import java.util.Collection; diff --git a/src/main/java/ru/windcorp/progressia/common/world/generic/ChunkSets.java b/src/main/java/ru/windcorp/progressia/common/world/generic/ChunkSets.java index 93413e4..aa03957 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/generic/ChunkSets.java +++ b/src/main/java/ru/windcorp/progressia/common/world/generic/ChunkSets.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.generic; import java.util.Iterator; diff --git a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericBlock.java b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericBlock.java index d669b07..1d2c252 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericBlock.java +++ b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericBlock.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.generic; public interface GenericBlock { diff --git a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericChunk.java b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericChunk.java index 656304f..511c9aa 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericChunk.java +++ b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericChunk.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.generic; import java.util.function.Consumer; @@ -91,17 +91,20 @@ public interface GenericChunk, B exten Vectors.release(v); return result; } - + default boolean isSurfaceBiC(Vec3i blockInChunk) { int hits = 0; - - if (Coordinates.isOnChunkBorder(blockInChunk.x)) hits++; - if (Coordinates.isOnChunkBorder(blockInChunk.y)) hits++; - if (Coordinates.isOnChunkBorder(blockInChunk.z)) hits++; - + + if (Coordinates.isOnChunkBorder(blockInChunk.x)) + hits++; + if (Coordinates.isOnChunkBorder(blockInChunk.y)) + hits++; + if (Coordinates.isOnChunkBorder(blockInChunk.z)) + hits++; + return hits >= 1; } - + default boolean isSurfaceBiW(Vec3i blockInWorld) { Vec3i v = Vectors.grab3i(); @@ -113,17 +116,20 @@ public interface GenericChunk, B exten Vectors.release(v); return result; } - + default boolean isEdgeBiC(Vec3i blockInChunk) { int hits = 0; - - if (Coordinates.isOnChunkBorder(blockInChunk.x)) hits++; - if (Coordinates.isOnChunkBorder(blockInChunk.y)) hits++; - if (Coordinates.isOnChunkBorder(blockInChunk.z)) hits++; - + + if (Coordinates.isOnChunkBorder(blockInChunk.x)) + hits++; + if (Coordinates.isOnChunkBorder(blockInChunk.y)) + hits++; + if (Coordinates.isOnChunkBorder(blockInChunk.z)) + hits++; + return hits >= 2; } - + default boolean isEdgeBiW(Vec3i blockInWorld) { Vec3i v = Vectors.grab3i(); @@ -135,17 +141,20 @@ public interface GenericChunk, B exten Vectors.release(v); return result; } - + default boolean isVertexBiC(Vec3i blockInChunk) { int hits = 0; - - if (Coordinates.isOnChunkBorder(blockInChunk.x)) hits++; - if (Coordinates.isOnChunkBorder(blockInChunk.y)) hits++; - if (Coordinates.isOnChunkBorder(blockInChunk.z)) hits++; - + + if (Coordinates.isOnChunkBorder(blockInChunk.x)) + hits++; + if (Coordinates.isOnChunkBorder(blockInChunk.y)) + hits++; + if (Coordinates.isOnChunkBorder(blockInChunk.z)) + hits++; + return hits == 3; } - + default boolean isVertexBiW(Vec3i blockInWorld) { Vec3i v = Vectors.grab3i(); diff --git a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericEntity.java b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericEntity.java index c15bd39..ee802b9 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericEntity.java +++ b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericEntity.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.generic; import glm.vec._3.Vec3; diff --git a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericTile.java b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericTile.java index e35aec2..73bf63b 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericTile.java +++ b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericTile.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.generic; public interface GenericTile { diff --git a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericTileStack.java b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericTileStack.java index 31a5158..11eb5e4 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericTileStack.java +++ b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericTileStack.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.generic; import java.util.AbstractList; diff --git a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericWorld.java b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericWorld.java index 943067e..e1b71fa 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericWorld.java +++ b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericWorld.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.generic; import java.util.Collection; diff --git a/src/main/java/ru/windcorp/progressia/common/world/generic/LongBasedChunkMap.java b/src/main/java/ru/windcorp/progressia/common/world/generic/LongBasedChunkMap.java index 2fbc912..855f0d7 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/generic/LongBasedChunkMap.java +++ b/src/main/java/ru/windcorp/progressia/common/world/generic/LongBasedChunkMap.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.generic; import java.util.Collection; diff --git a/src/main/java/ru/windcorp/progressia/common/world/generic/LongBasedChunkSet.java b/src/main/java/ru/windcorp/progressia/common/world/generic/LongBasedChunkSet.java index cd5a755..f5112c8 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/generic/LongBasedChunkSet.java +++ b/src/main/java/ru/windcorp/progressia/common/world/generic/LongBasedChunkSet.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.generic; import java.util.Iterator; diff --git a/src/main/java/ru/windcorp/progressia/common/world/io/ChunkCodec.java b/src/main/java/ru/windcorp/progressia/common/world/io/ChunkCodec.java index 7c2a35c..d3bdb2b 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/io/ChunkCodec.java +++ b/src/main/java/ru/windcorp/progressia/common/world/io/ChunkCodec.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.io; import java.io.DataInputStream; diff --git a/src/main/java/ru/windcorp/progressia/common/world/io/ChunkIO.java b/src/main/java/ru/windcorp/progressia/common/world/io/ChunkIO.java index 025738f..1dec1b7 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/io/ChunkIO.java +++ b/src/main/java/ru/windcorp/progressia/common/world/io/ChunkIO.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.io; import java.io.DataInputStream; diff --git a/src/main/java/ru/windcorp/progressia/common/world/tile/PacketAddTile.java b/src/main/java/ru/windcorp/progressia/common/world/tile/PacketAddTile.java index 650b4a7..bfc47c2 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/tile/PacketAddTile.java +++ b/src/main/java/ru/windcorp/progressia/common/world/tile/PacketAddTile.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.tile; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/world/tile/PacketAffectTile.java b/src/main/java/ru/windcorp/progressia/common/world/tile/PacketAffectTile.java index b12012c..07d9105 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/tile/PacketAffectTile.java +++ b/src/main/java/ru/windcorp/progressia/common/world/tile/PacketAffectTile.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.tile; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/world/tile/PacketRemoveTile.java b/src/main/java/ru/windcorp/progressia/common/world/tile/PacketRemoveTile.java index 9a8ef6c..d05c0c4 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/tile/PacketRemoveTile.java +++ b/src/main/java/ru/windcorp/progressia/common/world/tile/PacketRemoveTile.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.tile; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/common/world/tile/TileData.java b/src/main/java/ru/windcorp/progressia/common/world/tile/TileData.java index d314445..b8f42aa 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/tile/TileData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/tile/TileData.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.tile; import ru.windcorp.progressia.common.util.namespaces.Namespaced; diff --git a/src/main/java/ru/windcorp/progressia/common/world/tile/TileDataRegistry.java b/src/main/java/ru/windcorp/progressia/common/world/tile/TileDataRegistry.java index 110baea..5508ded 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/tile/TileDataRegistry.java +++ b/src/main/java/ru/windcorp/progressia/common/world/tile/TileDataRegistry.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.tile; import ru.windcorp.progressia.common.util.namespaces.NamespacedInstanceRegistry; diff --git a/src/main/java/ru/windcorp/progressia/common/world/tile/TileDataStack.java b/src/main/java/ru/windcorp/progressia/common/world/tile/TileDataStack.java index 80f0ba4..78530a0 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/tile/TileDataStack.java +++ b/src/main/java/ru/windcorp/progressia/common/world/tile/TileDataStack.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.tile; import ru.windcorp.progressia.common.world.ChunkData; diff --git a/src/main/java/ru/windcorp/progressia/common/world/tile/TileReference.java b/src/main/java/ru/windcorp/progressia/common/world/tile/TileReference.java index 75fde58..b8d593f 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/tile/TileReference.java +++ b/src/main/java/ru/windcorp/progressia/common/world/tile/TileReference.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.tile; public interface TileReference { diff --git a/src/main/java/ru/windcorp/progressia/common/world/tile/TileStackIsFullException.java b/src/main/java/ru/windcorp/progressia/common/world/tile/TileStackIsFullException.java index c9f6240..8f01d7f 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/tile/TileStackIsFullException.java +++ b/src/main/java/ru/windcorp/progressia/common/world/tile/TileStackIsFullException.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.common.world.tile; public class TileStackIsFullException extends RuntimeException { diff --git a/src/main/java/ru/windcorp/progressia/server/ChunkLoader.java b/src/main/java/ru/windcorp/progressia/server/ChunkLoader.java index d708fe2..f2391a2 100644 --- a/src/main/java/ru/windcorp/progressia/server/ChunkLoader.java +++ b/src/main/java/ru/windcorp/progressia/server/ChunkLoader.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/server/ChunkManager.java b/src/main/java/ru/windcorp/progressia/server/ChunkManager.java index badb061..2e1623d 100644 --- a/src/main/java/ru/windcorp/progressia/server/ChunkManager.java +++ b/src/main/java/ru/windcorp/progressia/server/ChunkManager.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server; import java.util.ArrayList; @@ -79,27 +79,23 @@ public class ChunkManager { } } - + @FunctionalInterface - public interface ChunksLoadListener - { + public interface ChunksLoadListener { void handle(boolean starting); } - + @FunctionalInterface - private interface ChunksLoadEventListener - { + private interface ChunksLoadEventListener { void handle(); } - - public interface ChunksLoadStartListener extends ChunksLoadEventListener - { - + + public interface ChunksLoadStartListener extends ChunksLoadEventListener { + } - - public interface ChunksLoadFinishListener extends ChunksLoadEventListener - { - + + public interface ChunksLoadFinishListener extends ChunksLoadEventListener { + } private final Server server; @@ -109,10 +105,11 @@ public class ChunkManager { private final ChunkSet toLoad = ChunkSets.newHashSet(); private final ChunkSet toUnload = ChunkSets.newHashSet(); - private Collection listeners = Collections.synchronizedCollection( new ArrayList<>()); - private Collection startListeners = Collections.synchronizedCollection( new ArrayList<>()); - private Collection finishListeners = Collections.synchronizedCollection( new ArrayList<>()); - + private Collection listeners = Collections.synchronizedCollection(new ArrayList<>()); + private Collection startListeners = Collections.synchronizedCollection(new ArrayList<>()); + private Collection finishListeners = Collections + .synchronizedCollection(new ArrayList<>()); + // TODO replace with a normal Map managed by some sort of PlayerListener, // weak maps are weak private final Map visions = Collections.synchronizedMap(new WeakHashMap<>()); @@ -132,26 +129,22 @@ public class ChunkManager { } } - public void register(ChunksLoadListener cll) - { + public void register(ChunksLoadListener cll) { listeners.add(cll); } - - public void register(ChunksLoadStartListener clsl) - { + + public void register(ChunksLoadStartListener clsl) { startListeners.add(clsl); } - - public void register(ChunksLoadFinishListener clfl) - { + + public void register(ChunksLoadFinishListener clfl) { finishListeners.add(clfl); } - - public void unregisterAll() - { + + public void unregisterAll() { listeners.clear(); } - + private void gatherRequests() { requested.clear(); @@ -177,14 +170,13 @@ public class ChunkManager { } private void processQueues() { - - if (toUnload.size()!=0 || toLoad.size()!=0) - { - LogManager.getLogger().info(String.valueOf(toUnload.size())+" "+String.valueOf( toLoad.size())); + + if (toUnload.size() != 0 || toLoad.size() != 0) { + LogManager.getLogger().info(String.valueOf(toUnload.size()) + " " + String.valueOf(toLoad.size())); } listeners.forEach(l -> l.handle(false)); startListeners.forEach(sl -> sl.handle()); - + toUnload.forEach(this::unloadChunk); toUnload.clear(); toLoad.forEach(this::loadChunk); @@ -195,7 +187,7 @@ public class ChunkManager { }); listeners.forEach(l -> l.handle(true)); finishListeners.forEach(fl -> fl.handle()); - + } private PlayerVision getVision(Player player, boolean createIfMissing) { @@ -236,22 +228,22 @@ public class ChunkManager { TestWorldDiskIO.saveChunk(chunk, getServer()); } - + public void unloadAll() // dont use probably { WorldData world = getServer().getWorld().getData(); - - //Collection chunks = world.getChunks(); + + // Collection chunks = world.getChunks(); Collection chunkPoss = new HashSet(); - + world.forEachChunk(c -> { chunkPoss.add(c.getPosition()); }); - + chunkPoss.forEach(v -> { ChunkData c = world.getChunk(v); world.removeChunk(c); - + TestWorldDiskIO.saveChunk(c, getServer()); }); } diff --git a/src/main/java/ru/windcorp/progressia/server/EntityManager.java b/src/main/java/ru/windcorp/progressia/server/EntityManager.java index d904c83..3e2079a 100644 --- a/src/main/java/ru/windcorp/progressia/server/EntityManager.java +++ b/src/main/java/ru/windcorp/progressia/server/EntityManager.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server; import java.util.Collections; diff --git a/src/main/java/ru/windcorp/progressia/server/Player.java b/src/main/java/ru/windcorp/progressia/server/Player.java index ea373a8..9b29918 100644 --- a/src/main/java/ru/windcorp/progressia/server/Player.java +++ b/src/main/java/ru/windcorp/progressia/server/Player.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/server/PlayerManager.java b/src/main/java/ru/windcorp/progressia/server/PlayerManager.java index b1447bf..fac1119 100644 --- a/src/main/java/ru/windcorp/progressia/server/PlayerManager.java +++ b/src/main/java/ru/windcorp/progressia/server/PlayerManager.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server; import java.util.ArrayList; @@ -72,9 +72,8 @@ public class PlayerManager { return player; } - - public void removePlayer(Player player) - { + + public void removePlayer(Player player) { players.remove(player); } diff --git a/src/main/java/ru/windcorp/progressia/server/ServerState.java b/src/main/java/ru/windcorp/progressia/server/ServerState.java index 774f17d..d252e0c 100644 --- a/src/main/java/ru/windcorp/progressia/server/ServerState.java +++ b/src/main/java/ru/windcorp/progressia/server/ServerState.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server; import ru.windcorp.progressia.common.world.WorldData; diff --git a/src/main/java/ru/windcorp/progressia/server/ServerThread.java b/src/main/java/ru/windcorp/progressia/server/ServerThread.java index d8d15a9..7420c2b 100644 --- a/src/main/java/ru/windcorp/progressia/server/ServerThread.java +++ b/src/main/java/ru/windcorp/progressia/server/ServerThread.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server; import java.util.concurrent.Executors; @@ -29,7 +29,7 @@ import ru.windcorp.progressia.server.world.ticking.TickerCoordinator; public class ServerThread implements Runnable { private static final ThreadLocal SERVER_THREADS_MAP = new ThreadLocal<>(); - + private static boolean isShuttingDown; public static Server getCurrentServer() { @@ -73,8 +73,7 @@ public class ServerThread implements Runnable { @Override public void run() { try { - if (isShuttingDown) - { + if (isShuttingDown) { getTicker().stop(); executor.shutdown(); return; @@ -87,10 +86,10 @@ public class ServerThread implements Runnable { } public void stop() { - + isShuttingDown = true; - //getTicker().stop(); + // getTicker().stop(); } public Server getServer() { diff --git a/src/main/java/ru/windcorp/progressia/server/TickingSettings.java b/src/main/java/ru/windcorp/progressia/server/TickingSettings.java index 743da10..8cb77d6 100644 --- a/src/main/java/ru/windcorp/progressia/server/TickingSettings.java +++ b/src/main/java/ru/windcorp/progressia/server/TickingSettings.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server; import ru.windcorp.progressia.common.Units; diff --git a/src/main/java/ru/windcorp/progressia/server/comms/Client.java b/src/main/java/ru/windcorp/progressia/server/comms/Client.java index f439e27..fdc1e98 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/Client.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/Client.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.comms; import ru.windcorp.progressia.common.comms.CommsChannel; diff --git a/src/main/java/ru/windcorp/progressia/server/comms/ClientChat.java b/src/main/java/ru/windcorp/progressia/server/comms/ClientChat.java index 35b9ca2..3d46634 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/ClientChat.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/ClientChat.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.comms; public abstract class ClientChat extends Client { diff --git a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java index cb4b80b..e223443 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.comms; import java.util.Collection; diff --git a/src/main/java/ru/windcorp/progressia/server/comms/ClientPlayer.java b/src/main/java/ru/windcorp/progressia/server/comms/ClientPlayer.java index c455b8e..d414524 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/ClientPlayer.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/ClientPlayer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.comms; import glm.vec._3.i.Vec3i; diff --git a/src/main/java/ru/windcorp/progressia/server/comms/DefaultServerCommsListener.java b/src/main/java/ru/windcorp/progressia/server/comms/DefaultServerCommsListener.java index d570e01..a405f78 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/DefaultServerCommsListener.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/DefaultServerCommsListener.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.comms; import java.io.IOException; diff --git a/src/main/java/ru/windcorp/progressia/server/comms/controls/ControlLogic.java b/src/main/java/ru/windcorp/progressia/server/comms/controls/ControlLogic.java index 31e97a2..f9bfb3b 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/controls/ControlLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/controls/ControlLogic.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.comms.controls; import ru.windcorp.progressia.common.comms.controls.PacketControl; diff --git a/src/main/java/ru/windcorp/progressia/server/comms/controls/ControlLogicRegistry.java b/src/main/java/ru/windcorp/progressia/server/comms/controls/ControlLogicRegistry.java index 18ece0a..92112e3 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/controls/ControlLogicRegistry.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/controls/ControlLogicRegistry.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.comms.controls; import ru.windcorp.progressia.common.util.namespaces.NamespacedInstanceRegistry; diff --git a/src/main/java/ru/windcorp/progressia/server/world/ChunkLogic.java b/src/main/java/ru/windcorp/progressia/server/world/ChunkLogic.java index 37685d2..acea221 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/ChunkLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/ChunkLogic.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world; import java.util.ArrayList; diff --git a/src/main/java/ru/windcorp/progressia/server/world/ChunkTickContext.java b/src/main/java/ru/windcorp/progressia/server/world/ChunkTickContext.java index 5eed263..c197706 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/ChunkTickContext.java +++ b/src/main/java/ru/windcorp/progressia/server/world/ChunkTickContext.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/server/world/TickAndUpdateUtil.java b/src/main/java/ru/windcorp/progressia/server/world/TickAndUpdateUtil.java index 22d106e..acf9d1f 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/TickAndUpdateUtil.java +++ b/src/main/java/ru/windcorp/progressia/server/world/TickAndUpdateUtil.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world; import glm.vec._3.i.Vec3i; diff --git a/src/main/java/ru/windcorp/progressia/server/world/TickContext.java b/src/main/java/ru/windcorp/progressia/server/world/TickContext.java index 50dda55..0997c65 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/TickContext.java +++ b/src/main/java/ru/windcorp/progressia/server/world/TickContext.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world; import java.util.Random; diff --git a/src/main/java/ru/windcorp/progressia/server/world/TickContextMutable.java b/src/main/java/ru/windcorp/progressia/server/world/TickContextMutable.java index 68185d9..81f5c49 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/TickContextMutable.java +++ b/src/main/java/ru/windcorp/progressia/server/world/TickContextMutable.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world; import java.util.Objects; diff --git a/src/main/java/ru/windcorp/progressia/server/world/UpdateTriggerer.java b/src/main/java/ru/windcorp/progressia/server/world/UpdateTriggerer.java index 511170e..07acf55 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/UpdateTriggerer.java +++ b/src/main/java/ru/windcorp/progressia/server/world/UpdateTriggerer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world; import glm.vec._3.i.Vec3i; diff --git a/src/main/java/ru/windcorp/progressia/server/world/WorldLogic.java b/src/main/java/ru/windcorp/progressia/server/world/WorldLogic.java index 93a1028..abd10e4 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/WorldLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/WorldLogic.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world; import java.util.Collection; diff --git a/src/main/java/ru/windcorp/progressia/server/world/block/BlockLogic.java b/src/main/java/ru/windcorp/progressia/server/world/block/BlockLogic.java index 794259f..fcf141d 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/block/BlockLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/block/BlockLogic.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.block; import ru.windcorp.progressia.common.util.namespaces.Namespaced; diff --git a/src/main/java/ru/windcorp/progressia/server/world/block/BlockLogicRegistry.java b/src/main/java/ru/windcorp/progressia/server/world/block/BlockLogicRegistry.java index df18ff7..b50b02f 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/block/BlockLogicRegistry.java +++ b/src/main/java/ru/windcorp/progressia/server/world/block/BlockLogicRegistry.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.block; import ru.windcorp.progressia.common.util.namespaces.NamespacedInstanceRegistry; diff --git a/src/main/java/ru/windcorp/progressia/server/world/block/BlockTickContext.java b/src/main/java/ru/windcorp/progressia/server/world/block/BlockTickContext.java index a305b9a..d10f10c 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/block/BlockTickContext.java +++ b/src/main/java/ru/windcorp/progressia/server/world/block/BlockTickContext.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.block; import java.util.Objects; diff --git a/src/main/java/ru/windcorp/progressia/server/world/block/TickableBlock.java b/src/main/java/ru/windcorp/progressia/server/world/block/TickableBlock.java index 56ba938..62b830f 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/block/TickableBlock.java +++ b/src/main/java/ru/windcorp/progressia/server/world/block/TickableBlock.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.block; import ru.windcorp.progressia.server.world.ticking.TickingPolicy; diff --git a/src/main/java/ru/windcorp/progressia/server/world/block/UpdateableBlock.java b/src/main/java/ru/windcorp/progressia/server/world/block/UpdateableBlock.java index 1497c92..d9b931f 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/block/UpdateableBlock.java +++ b/src/main/java/ru/windcorp/progressia/server/world/block/UpdateableBlock.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.block; import org.apache.logging.log4j.LogManager; diff --git a/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogic.java b/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogic.java index 7725612..0f33517 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogic.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.entity; import ru.windcorp.progressia.common.util.namespaces.Namespaced; diff --git a/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogicRegistry.java b/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogicRegistry.java index d8b05d4..a3ecd20 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogicRegistry.java +++ b/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogicRegistry.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.entity; import ru.windcorp.progressia.common.util.namespaces.NamespacedInstanceRegistry; diff --git a/src/main/java/ru/windcorp/progressia/server/world/generation/AbstractWorldGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/AbstractWorldGenerator.java index ffb5c06..2753a8f 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/generation/AbstractWorldGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/AbstractWorldGenerator.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.generation; import java.io.DataInputStream; diff --git a/src/main/java/ru/windcorp/progressia/server/world/generation/WorldGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/WorldGenerator.java index afed281..41a7885 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/generation/WorldGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/WorldGenerator.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.generation; import java.io.DataInputStream; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/AddTile.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/AddTile.java index 6e9ea47..238a42f 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/AddTile.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/AddTile.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/BlockTriggeredUpdate.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/BlockTriggeredUpdate.java index 331a5c4..6d8d408 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/BlockTriggeredUpdate.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/BlockTriggeredUpdate.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedBlockChange.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedBlockChange.java index b005285..62cedac 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedBlockChange.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedBlockChange.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedChange.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedChange.java index e1eb5ca..d5db70a 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedChange.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedChange.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedChunkChange.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedChunkChange.java index d98c001..ef4a8cf 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedChunkChange.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedChunkChange.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedEvaluation.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedEvaluation.java index da865b4..5fe1320 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedEvaluation.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedEvaluation.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedTileChange.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedTileChange.java index 1b6cde2..3197def 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedTileChange.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedTileChange.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import java.util.Objects; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedWorldChange.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedWorldChange.java index 711bd5d..c01e83a 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedWorldChange.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedWorldChange.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/ChangeEntity.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/ChangeEntity.java index 08f1212..a7a7072 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/ChangeEntity.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/ChangeEntity.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/RemoveTile.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/RemoveTile.java index 42dea30..0f811b1 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/RemoveTile.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/RemoveTile.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/SetBlock.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/SetBlock.java index 330333b..e4cc4fb 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/SetBlock.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/SetBlock.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/StateChange.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/StateChange.java index 93d5f08..4aa8c7c 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/StateChange.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/StateChange.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; @FunctionalInterface diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/TickChunk.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/TickChunk.java index c0895e1..92e0ff6 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/TickChunk.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/TickChunk.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import java.util.ArrayList; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/TickEntitiesTask.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/TickEntitiesTask.java index 1e76b23..8376c8d 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/TickEntitiesTask.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/TickEntitiesTask.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import glm.vec._3.i.Vec3i; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/TileTriggeredUpdate.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/TileTriggeredUpdate.java index 76fc414..80b91bd 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/TileTriggeredUpdate.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/TileTriggeredUpdate.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/WorldAccessor.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/WorldAccessor.java index 2c83ccd..2069484 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/WorldAccessor.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/WorldAccessor.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/server/world/ticking/Change.java b/src/main/java/ru/windcorp/progressia/server/world/ticking/Change.java index b0fc7f2..4340327 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/ticking/Change.java +++ b/src/main/java/ru/windcorp/progressia/server/world/ticking/Change.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.ticking; import ru.windcorp.progressia.server.Server; diff --git a/src/main/java/ru/windcorp/progressia/server/world/ticking/DevilInvasionException.java b/src/main/java/ru/windcorp/progressia/server/world/ticking/DevilInvasionException.java index 50ff69c..fd146bc 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/ticking/DevilInvasionException.java +++ b/src/main/java/ru/windcorp/progressia/server/world/ticking/DevilInvasionException.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.ticking; public class DevilInvasionException extends RuntimeException { diff --git a/src/main/java/ru/windcorp/progressia/server/world/ticking/Evaluation.java b/src/main/java/ru/windcorp/progressia/server/world/ticking/Evaluation.java index f4f3922..a198361 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/ticking/Evaluation.java +++ b/src/main/java/ru/windcorp/progressia/server/world/ticking/Evaluation.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.ticking; import ru.windcorp.progressia.server.Server; diff --git a/src/main/java/ru/windcorp/progressia/server/world/ticking/Ticker.java b/src/main/java/ru/windcorp/progressia/server/world/ticking/Ticker.java index 8a102ac..d830d0e 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/ticking/Ticker.java +++ b/src/main/java/ru/windcorp/progressia/server/world/ticking/Ticker.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.ticking; import java.util.ArrayList; @@ -115,8 +115,7 @@ class Ticker { } catch (Exception e) { getCoordinator().crash(e, this.name); } - - + } private synchronized boolean sleep() { diff --git a/src/main/java/ru/windcorp/progressia/server/world/ticking/TickerCoordinator.java b/src/main/java/ru/windcorp/progressia/server/world/ticking/TickerCoordinator.java index 7d58d6d..57e742f 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/ticking/TickerCoordinator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/ticking/TickerCoordinator.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.ticking; import java.util.ArrayList; @@ -152,7 +152,7 @@ public class TickerCoordinator { public double getTPS() { return 1 / tickLength; } - + public long getUptimeTicks() { return ticks; } @@ -168,7 +168,7 @@ public class TickerCoordinator { tickStart = System.currentTimeMillis(); } - + private void onTickEnd() { ticks++; } @@ -191,7 +191,7 @@ public class TickerCoordinator { logger.debug("Pass complete"); passes++; } - + onTickEnd(); logger.debug("Tick complete; run {} passes", passes); diff --git a/src/main/java/ru/windcorp/progressia/server/world/ticking/TickerTask.java b/src/main/java/ru/windcorp/progressia/server/world/ticking/TickerTask.java index 4a075c0..fe25d8a 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/ticking/TickerTask.java +++ b/src/main/java/ru/windcorp/progressia/server/world/ticking/TickerTask.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.ticking; import glm.vec._3.i.Vec3i; diff --git a/src/main/java/ru/windcorp/progressia/server/world/ticking/TickingPolicy.java b/src/main/java/ru/windcorp/progressia/server/world/ticking/TickingPolicy.java index a5836fe..e391ca4 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/ticking/TickingPolicy.java +++ b/src/main/java/ru/windcorp/progressia/server/world/ticking/TickingPolicy.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.ticking; import ru.windcorp.progressia.server.world.block.TickableBlock; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/HangingTileLogic.java b/src/main/java/ru/windcorp/progressia/server/world/tile/HangingTileLogic.java index 745f289..fdd3a53 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tile/HangingTileLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/HangingTileLogic.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tile; import ru.windcorp.progressia.server.world.block.BlockLogic; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/TSTickContext.java b/src/main/java/ru/windcorp/progressia/server/world/tile/TSTickContext.java index 399f7b8..7121187 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tile/TSTickContext.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/TSTickContext.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tile; import java.util.Objects; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/TickableTile.java b/src/main/java/ru/windcorp/progressia/server/world/tile/TickableTile.java index 4def3b0..50a4b15 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tile/TickableTile.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/TickableTile.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tile; import ru.windcorp.progressia.server.world.ticking.TickingPolicy; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogic.java b/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogic.java index 4a97ead..c623999 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogic.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tile; import ru.windcorp.progressia.common.util.namespaces.Namespaced; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogicRegistry.java b/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogicRegistry.java index d8bceaf..cc0fca6 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogicRegistry.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogicRegistry.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tile; import ru.windcorp.progressia.common.util.namespaces.NamespacedInstanceRegistry; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogicStack.java b/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogicStack.java index 5e91963..99d23d5 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogicStack.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogicStack.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tile; import ru.windcorp.progressia.common.world.generic.GenericTileStack; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/TileTickContext.java b/src/main/java/ru/windcorp/progressia/server/world/tile/TileTickContext.java index 45f41ec..69dc77d 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tile/TileTickContext.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/TileTickContext.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tile; import ru.windcorp.progressia.common.world.tile.TileData; diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/UpdateableTile.java b/src/main/java/ru/windcorp/progressia/server/world/tile/UpdateableTile.java index bf114fa..0a5aca5 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tile/UpdateableTile.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/UpdateableTile.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tile; public interface UpdateableTile { diff --git a/src/main/java/ru/windcorp/progressia/test/CollisionModelRenderer.java b/src/main/java/ru/windcorp/progressia/test/CollisionModelRenderer.java index 4c7ca68..7328cef 100644 --- a/src/main/java/ru/windcorp/progressia/test/CollisionModelRenderer.java +++ b/src/main/java/ru/windcorp/progressia/test/CollisionModelRenderer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import glm.mat._4.Mat4; diff --git a/src/main/java/ru/windcorp/progressia/test/ControlBreakBlockData.java b/src/main/java/ru/windcorp/progressia/test/ControlBreakBlockData.java index a9df57a..d7e8a36 100644 --- a/src/main/java/ru/windcorp/progressia/test/ControlBreakBlockData.java +++ b/src/main/java/ru/windcorp/progressia/test/ControlBreakBlockData.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import glm.vec._3.i.Vec3i; diff --git a/src/main/java/ru/windcorp/progressia/test/ControlPlaceBlockData.java b/src/main/java/ru/windcorp/progressia/test/ControlPlaceBlockData.java index f3e45e2..f83a0cc 100644 --- a/src/main/java/ru/windcorp/progressia/test/ControlPlaceBlockData.java +++ b/src/main/java/ru/windcorp/progressia/test/ControlPlaceBlockData.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import glm.vec._3.i.Vec3i; diff --git a/src/main/java/ru/windcorp/progressia/test/ControlPlaceTileData.java b/src/main/java/ru/windcorp/progressia/test/ControlPlaceTileData.java index 5a37b6f..5835d7b 100644 --- a/src/main/java/ru/windcorp/progressia/test/ControlPlaceTileData.java +++ b/src/main/java/ru/windcorp/progressia/test/ControlPlaceTileData.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import glm.vec._3.i.Vec3i; diff --git a/src/main/java/ru/windcorp/progressia/test/LayerAbout.java b/src/main/java/ru/windcorp/progressia/test/LayerAbout.java index 7b45fd4..b0b89bb 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerAbout.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerAbout.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import ru.windcorp.progressia.client.graphics.Colors; diff --git a/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java b/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java index 6f829da..d715cea 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java @@ -39,87 +39,88 @@ import ru.windcorp.progressia.server.Player; import ru.windcorp.progressia.server.ServerState; public class LayerButtonTest extends MenuLayer { - + boolean alive = true; public LayerButtonTest() { super("ButtonTest"); - + addTitle(); - + Button blockableButton; getContent().addChild((blockableButton = new Button("BlockableButton", "Blockable")).addAction(b -> { System.out.println("Button Blockable!"); })); blockableButton.setEnabled(false); - + getContent().addChild(new Checkbox("EnableButton", "Enable").addAction(b -> { blockableButton.setEnabled(((Checkbox) b).isChecked()); })); - + RadioButtonGroup group = new RadioButtonGroup().addAction(g -> { System.out.println("RBG! " + g.getSelected().getLabel().getCurrentText()); }); - + getContent().addChild(new RadioButton("RB1", "Moon").setGroup(group)); getContent().addChild(new RadioButton("RB2", "Type").setGroup(group)); getContent().addChild(new RadioButton("RB3", "Ice").setGroup(group)); getContent().addChild(new RadioButton("RB4", "Cream").setGroup(group)); - + getContent().getChild(getContent().getChildren().size() - 1).setEnabled(false); - + getContent().addChild(new Label("Hint", new Font().withColor(Colors.LIGHT_GRAY), "This is a MenuLayer")); - + getContent().addChild(new Button("Continue", "Continue").addAction(b -> { getCloseAction().run(); })); - + getContent().addChild(new Button("Menu", "Back To Menu").addAction(b -> { - //System.exit(0); - //for (Layer layer : GUI.getLayers()) - //{ - // GUI.removeLayer(layer); - //} + // System.exit(0); + // for (Layer layer : GUI.getLayers()) + // { + // GUI.removeLayer(layer); + // } getCloseAction().run(); - - //ClientState.getInstance().; - + + // ClientState.getInstance().; + Collection players = ServerState.getInstance().getPlayerManager().getPlayers(); players.clear(); - + ClientState.disconnectFromLocalServer(); - + MutableString t = new MutableStringLocalized("LayerText.Save"); - LayerTestText layer = new LayerTestText("Text",() -> {t.update(); return t.get();}); - + LayerTestText layer = new LayerTestText("Text", () -> { + t.update(); + return t.get(); + }); + GUI.addTopLayer(layer); - + ChunkManager cm = ServerState.getInstance().getChunkManager(); alive = true; - cm.register((ChunksLoadFinishListener)() -> { - if (alive) - { + cm.register((ChunksLoadFinishListener) () -> { + if (alive) { GUI.removeLayer(layer); GUI.addTopLayer(new LayerTitle("Title")); - //cm.unregisterAll(); + // cm.unregisterAll(); alive = false; - - //ServerState.getInstance().; + + // ServerState.getInstance().; ServerState.getInstance().shutdown("Safe Exit"); ServerState.setInstance(null); - + TestPlayerControls.resetInstance(); } }); - - //ClientState.getInstance(); + + // ClientState.getInstance(); ClientState.setInstance(null); - //ServerState.getInstance().getChunkManager().unloadAll(); - - + // ServerState.getInstance().getChunkManager().unloadAll(); + })); - + getContent().takeFocus(); } diff --git a/src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java b/src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java index fb69ca3..e5b95fa 100755 --- a/src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import glm.vec._3.Vec3; diff --git a/src/main/java/ru/windcorp/progressia/test/LayerTestText.java b/src/main/java/ru/windcorp/progressia/test/LayerTestText.java index 3cfef00..fef1b23 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerTestText.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerTestText.java @@ -10,15 +10,15 @@ import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical; public class LayerTestText extends GUILayer { public LayerTestText(String name, Supplier value) { - super(name, new LayoutVertical(20,10)); - - //MutableString title = new MutableStringLocalized("Layer"+name+".Title"); + super(name, new LayoutVertical(20, 10)); + + // MutableString title = new + // MutableStringLocalized("Layer"+name+".Title"); Font titleFont = new Font().deriveBold().withColor(Colors.BLACK).withAlign(0.5f); - getRoot().addChild(new Label(name+".Text", titleFont, value)); + getRoot().addChild(new Label(name + ".Text", titleFont, value)); } - - public LayerTestText(String name, String value) - { - this(name,() -> value); + + public LayerTestText(String name, String value) { + this(name, () -> value); } } diff --git a/src/main/java/ru/windcorp/progressia/test/LayerTestUI.java b/src/main/java/ru/windcorp/progressia/test/LayerTestUI.java index c93a055..08d527e 100755 --- a/src/main/java/ru/windcorp/progressia/test/LayerTestUI.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerTestUI.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import org.lwjgl.glfw.GLFW; diff --git a/src/main/java/ru/windcorp/progressia/test/LayerTitle.java b/src/main/java/ru/windcorp/progressia/test/LayerTitle.java index c739651..d2ba139 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerTitle.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerTitle.java @@ -14,21 +14,22 @@ import ru.windcorp.progressia.client.localization.MutableStringLocalized; public class LayerTitle extends GUILayer { public LayerTitle(String name) { - super(name, new LayoutVertical(20,10)); - - MutableString title = new MutableStringLocalized("Layer"+name+".Title"); + super(name, new LayoutVertical(20, 10)); + + MutableString title = new MutableStringLocalized("Layer" + name + ".Title"); Font titleFont = new Font().deriveBold().withColor(Colors.BLACK).withAlign(0.5f); - getRoot().addChild(new Label(name+".Title", titleFont, title)); - + getRoot().addChild(new Label(name + ".Title", titleFont, title)); + Font buttonFont = titleFont; - MutableString playText = new MutableStringLocalized("Layer"+name+".Play"); - getRoot().addChild(new Button(name+".Play", new Label(name+".Play", buttonFont, playText)).addAction(b -> { + MutableString playText = new MutableStringLocalized("Layer" + name + ".Play"); + getRoot().addChild(new Button(name + ".Play", new Label(name + ".Play", buttonFont, playText)).addAction(b -> { GUI.removeLayer(this); - - ProgressiaLauncher.play();})); - - MutableString quitText = new MutableStringLocalized("Layer"+name+".Quit"); - getRoot().addChild(new Button(name+"Quit", new Label(name+".Quit", buttonFont, quitText)).addAction(b -> { + + ProgressiaLauncher.play(); + })); + + MutableString quitText = new MutableStringLocalized("Layer" + name + ".Quit"); + getRoot().addChild(new Button(name + "Quit", new Label(name + ".Quit", buttonFont, quitText)).addAction(b -> { System.exit(0); })); } diff --git a/src/main/java/ru/windcorp/progressia/test/TestBlockLogicAir.java b/src/main/java/ru/windcorp/progressia/test/TestBlockLogicAir.java index e378dbf..e9877e9 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestBlockLogicAir.java +++ b/src/main/java/ru/windcorp/progressia/test/TestBlockLogicAir.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import ru.windcorp.progressia.common.world.block.BlockFace; diff --git a/src/main/java/ru/windcorp/progressia/test/TestBlockLogicGlass.java b/src/main/java/ru/windcorp/progressia/test/TestBlockLogicGlass.java index eca9e5c..e58cc3d 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestBlockLogicGlass.java +++ b/src/main/java/ru/windcorp/progressia/test/TestBlockLogicGlass.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import ru.windcorp.progressia.common.world.block.BlockFace; diff --git a/src/main/java/ru/windcorp/progressia/test/TestChunkCodec.java b/src/main/java/ru/windcorp/progressia/test/TestChunkCodec.java index a4f891b..a39f53f 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestChunkCodec.java +++ b/src/main/java/ru/windcorp/progressia/test/TestChunkCodec.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import java.io.DataInput; diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java index dad5496..003f5a3 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import static ru.windcorp.progressia.client.world.block.BlockRenderRegistry.getBlockTexture; @@ -287,7 +287,7 @@ public class TestContent { ) ); logic.register(ControlLogic.of("Test:PlaceTile", TestContent::onTilePlaceReceived)); - + triggers.register( ControlTriggers.localOf( "Test:StartNextMusic", diff --git a/src/main/java/ru/windcorp/progressia/test/TestEntityDataStatie.java b/src/main/java/ru/windcorp/progressia/test/TestEntityDataStatie.java index 94f5043..6bbee70 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestEntityDataStatie.java +++ b/src/main/java/ru/windcorp/progressia/test/TestEntityDataStatie.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import ru.windcorp.progressia.common.collision.AABB; diff --git a/src/main/java/ru/windcorp/progressia/test/TestEntityLogicStatie.java b/src/main/java/ru/windcorp/progressia/test/TestEntityLogicStatie.java index 5fa66fb..f27abfe 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestEntityLogicStatie.java +++ b/src/main/java/ru/windcorp/progressia/test/TestEntityLogicStatie.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import ru.windcorp.progressia.common.world.entity.EntityData; diff --git a/src/main/java/ru/windcorp/progressia/test/TestEntityRenderHuman.java b/src/main/java/ru/windcorp/progressia/test/TestEntityRenderHuman.java index 388d89c..3357f82 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestEntityRenderHuman.java +++ b/src/main/java/ru/windcorp/progressia/test/TestEntityRenderHuman.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import static java.lang.Math.toRadians; diff --git a/src/main/java/ru/windcorp/progressia/test/TestEntityRenderJavapony.java b/src/main/java/ru/windcorp/progressia/test/TestEntityRenderJavapony.java index aefa1c6..1e567d6 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestEntityRenderJavapony.java +++ b/src/main/java/ru/windcorp/progressia/test/TestEntityRenderJavapony.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import java.util.ArrayList; diff --git a/src/main/java/ru/windcorp/progressia/test/TestEntityRenderStatie.java b/src/main/java/ru/windcorp/progressia/test/TestEntityRenderStatie.java index 47990fd..12fd113 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestEntityRenderStatie.java +++ b/src/main/java/ru/windcorp/progressia/test/TestEntityRenderStatie.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import ru.windcorp.progressia.client.graphics.model.Renderable; diff --git a/src/main/java/ru/windcorp/progressia/test/TestMusicPlayer.java b/src/main/java/ru/windcorp/progressia/test/TestMusicPlayer.java index 1674d5b..ac221d8 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestMusicPlayer.java +++ b/src/main/java/ru/windcorp/progressia/test/TestMusicPlayer.java @@ -38,41 +38,41 @@ import ru.windcorp.progressia.common.resource.ResourceManager; import ru.windcorp.progressia.common.util.crash.CrashReports; public class TestMusicPlayer implements Runnable { - + private static final int MIN_SILENCE = 15 * 1000; // 15 seconds private static final int MAX_SILENCE = 60 * 1000; // one minute - + private static TestMusicPlayer instance = null; - + private final List compositions = new ArrayList<>(); - + private final Random random = new Random(); private long nextStart; private Sound lastStarted = null; - + public TestMusicPlayer() { this.nextStart = System.currentTimeMillis(); - + instance = this; } - + public static void start() { Thread thread = new Thread(new TestMusicPlayer(), "Music Thread"); thread.setDaemon(true); thread.start(); } - + @Override public void run() { loadCompositions(); - + if (compositions.isEmpty()) { LogManager.getLogger().warn("No music found"); return; } - + while (true) { - + try { synchronized (this) { while (true) { @@ -88,39 +88,39 @@ public class TestMusicPlayer implements Runnable { LogManager.getLogger().warn("Received interrupt in music thread, terminating thread..."); return; } - + startNextComposition(); - + } } private void loadCompositions() { try { - + Path directory = Paths.get("music"); - + if (!Files.isDirectory(directory)) { Files.createDirectories(directory); } - + Iterator it = Files.walk(directory).filter(Files::isRegularFile).iterator(); int i = 0; - + while (it.hasNext()) { String file = it.next().toString(); if (!file.endsWith(".ogg") && !file.endsWith(".oga")) { LogManager.getLogger().warn("Skipping " + file + ": not .ogg nor .oga"); } - + String id = "Progressia:Music" + (i++); - + AudioManager.loadSound(ResourceManager.getFileResource(file.toString()), id, AudioFormat.STEREO); SoundType composition = AudioRegistry.getInstance().get(id); compositions.add(composition); - + LogManager.getLogger().info("Loaded " + file); } - + } catch (IOException e) { throw CrashReports.report(e, "Could not load music"); } @@ -129,20 +129,21 @@ public class TestMusicPlayer implements Runnable { private synchronized void startNextComposition() { int index = random.nextInt(compositions.size()); SoundType composition = compositions.get(index); - + long now = System.currentTimeMillis(); long durationInMs = (long) (composition.getDuration() * 1000); long silence = random.nextInt(MAX_SILENCE - MIN_SILENCE) + MIN_SILENCE; - + nextStart = now + durationInMs + silence; - + lastStarted = new Music(composition); lastStarted.play(false); } - + public static void startNextNow() { - if (instance == null) return; - + if (instance == null) + return; + synchronized (instance) { instance.nextStart = System.currentTimeMillis(); instance.notifyAll(); diff --git a/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java b/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java index 960a97e..f2d557e 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java +++ b/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import glm.Glm; @@ -90,9 +90,8 @@ public class TestPlayerControls { private LayerTestGUI debugLayer = null; private Runnable updateCallback = null; - - public static void resetInstance() - { + + public static void resetInstance() { INSTANCE = new TestPlayerControls(); } @@ -188,7 +187,7 @@ public class TestPlayerControls { case GLFW.GLFW_KEY_ESCAPE: if (!event.isPress()) return false; - + handleEscape(); break; diff --git a/src/main/java/ru/windcorp/progressia/test/TestTileLogicGrass.java b/src/main/java/ru/windcorp/progressia/test/TestTileLogicGrass.java index 06afc77..e6514ca 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestTileLogicGrass.java +++ b/src/main/java/ru/windcorp/progressia/test/TestTileLogicGrass.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test; import ru.windcorp.progressia.common.world.block.BlockFace; diff --git a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java index cbb294b..355b7dc 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java @@ -78,25 +78,29 @@ public class TestWorldDiskIO { return loc << 1; } - /*private static int intFromNat(int loc) // Possibly unused - { - if ((loc & 1) == 1) - return -loc >> 1; - return loc >> 1; - }*/ + /* + * private static int intFromNat(int loc) // Possibly unused + * { + * if ((loc & 1) == 1) + * return -loc >> 1; + * return loc >> 1; + * } + */ private static Vec3i getRegion(Vec3i chunkLoc) { - return new Vec3i(natFromInt(chunkLoc.x/regionSize.x), natFromInt(chunkLoc.y/regionSize.y), natFromInt(chunkLoc.z/regionSize.z)); + return new Vec3i( + natFromInt(chunkLoc.x / regionSize.x), + natFromInt(chunkLoc.y / regionSize.y), + natFromInt(chunkLoc.z / regionSize.z) + ); } - - private static int mod(int a, int m) - { - return ((a%m)+m)%m; + + private static int mod(int a, int m) { + return ((a % m) + m) % m; } - - private static Vec3i getRegionLoc(Vec3i chunkLoc) - { - return new Vec3i(mod(chunkLoc.x,regionSize.x),mod(chunkLoc.y,regionSize.y),mod(chunkLoc.z,regionSize.z)); + + private static Vec3i getRegionLoc(Vec3i chunkLoc) { + return new Vec3i(mod(chunkLoc.x, regionSize.x), mod(chunkLoc.y, regionSize.y), mod(chunkLoc.z, regionSize.z)); } public static void initRegions() { @@ -129,10 +133,9 @@ public class TestWorldDiskIO { break; } } - - private static void expand(int sectors) - { - + + private static void expand(int sectors) { + } public static void saveChunk(ChunkData chunk, Server server) { @@ -197,20 +200,18 @@ public class TestWorldDiskIO { ChunkIO.save(chunk, output, IOContext.SAVE); writeGenerationHint(chunk, output, server); } - } - else if (currentFormat == 65536) - { + } else if (currentFormat == 65536) { LOG.debug( "Saving {} {} {}", chunk.getPosition().x, chunk.getPosition().y, chunk.getPosition().z ); - + Files.createDirectories(SAVE_DIR); - + Vec3i saveCoords = getRegion(chunk.getPosition()); - + Path path = SAVE_DIR.resolve( String.format( "%d_%d_%d" + extension, @@ -219,49 +220,53 @@ public class TestWorldDiskIO { saveCoords.z ) ); - - /*if (!dosave) - { - return; - } - dosave = false;*/ - + + /* + * if (!dosave) + * { + * return; + * } + * dosave = false; + */ + try ( RandomAccessFile output = new RandomAccessFile(path.toFile(), "rw") ) { - //LOG.debug(output.read()); - if (output.read()<0) - { + // LOG.debug(output.read()); + if (output.read() < 0) { LOG.info("Making header"); - output.writeChars("\0".repeat((offsetBytes+1)*chunksPerRegion)); + output.writeChars("\0".repeat((offsetBytes + 1) * chunksPerRegion)); } - + Vec3i pos = getRegionLoc(chunk.getPosition()); - int shortOffset = (offsetBytes+1)*(pos.z+regionSize.z*(pos.y + regionSize.y*pos.x)); - int fullOffset = (offsetBytes+1)*(chunksPerRegion); + int shortOffset = (offsetBytes + 1) * (pos.z + regionSize.z * (pos.y + regionSize.y * pos.x)); + int fullOffset = (offsetBytes + 1) * (chunksPerRegion); output.seek(shortOffset); int offset = output.readInt(); - int sectorLength = offset&255; + int sectorLength = offset & 255; offset = offset >> 8; - if (sectorLength == 0) - { + if (sectorLength == 0) { int outputLen = (int) output.length(); - offset = (int) (outputLen-fullOffset)/sectorSize+1; + offset = (int) (outputLen - fullOffset) / sectorSize + 1; output.seek(shortOffset); - output.writeInt(offset<<8); + output.writeInt(offset << 8); output.seek(outputLen); - /*while (output.length()>24); - LOG.debug(bfClone>>24); + + for (int i = 0; i < 4; i++) { + bw.write(bfClone >> 24); + LOG.debug(bfClone >> 24); bfClone = bfClone << 8; } - /*bw.write( - new char[] { - (char) bestFormat / (256 * 256 * 256), - (char) (bestFormat % 256) / (256 * 256), - (char) (bestFormat % (256 * 256)) / (256), - (char) (bestFormat % (256 * 256 * 256)) } - );*/ + /* + * bw.write( + * new char[] { + * (char) bestFormat / (256 * 256 * 256), + * (char) (bestFormat % 256) / (256 * 256), + * (char) (bestFormat % (256 * 256)) / (256), + * (char) (bestFormat % (256 * 256 * 256)) } + * ); + */ bw.close(); } catch (IOException e) { @@ -470,7 +478,7 @@ public class TestWorldDiskIO { saveCoords.z ) ); - + if (!Files.exists(path)) { LOG.debug( "Not found {} {} {}", @@ -520,33 +528,34 @@ public class TestWorldDiskIO { return chunk; } } - - private static ChunkData loadRegion(Path path, Vec3i chunkPos, WorldData world, Server server) throws IOException, DecodingException - { + + private static ChunkData loadRegion(Path path, Vec3i chunkPos, WorldData world, Server server) + throws IOException, + DecodingException { try ( BufferedInputStream input = new BufferedInputStream(Files.newInputStream(path)) ) { - LOG.info(path.toString()); + // LOG.info(path.toString()); Vec3i pos = getRegionLoc(chunkPos); - int shortOffset = (offsetBytes+1)*(pos.z+regionSize.z*(pos.y + regionSize.y*pos.x)); - int fullOffset = (offsetBytes+1)*(chunksPerRegion); + int shortOffset = (offsetBytes + 1) * (pos.z + regionSize.z * (pos.y + regionSize.y * pos.x)); + int fullOffset = (offsetBytes + 1) * (chunksPerRegion); input.skipNBytes(shortOffset); int offset = 0; - for (int i=0;i. */ - + package ru.windcorp.progressia.test.gen; import kdotjpg.opensimplex2.areagen.OpenSimplex2S; diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestWorldGenerator.java b/src/main/java/ru/windcorp/progressia/test/gen/TestWorldGenerator.java index 1b35ffc..22eedc9 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestWorldGenerator.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/TestWorldGenerator.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.test.gen; import java.io.DataInputStream; From e4ced6507eb65ba37f0e1023b6176f52b4a94dce Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Wed, 18 Aug 2021 18:50:48 -0400 Subject: [PATCH 13/49] Hash Things -Removed unused imports -Using HashMap to keep track of RandomAccessFile instances -Using those instances to do stuff -Made new HashableVec3i class that allows for hashing of 3d vectors. --- .../progressia/client/ClientProxy.java | 1 - .../progressia/common/util/HashableVec3i.java | 26 ++++++++++ .../progressia/server/ServerThread.java | 1 + .../progressia/test/LayerButtonTest.java | 2 - .../progressia/test/TestWorldDiskIO.java | 48 +++++++++++-------- 5 files changed, 55 insertions(+), 23 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java diff --git a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java index ab0b476..65bd1c0 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java @@ -33,7 +33,6 @@ import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.server.ServerState; import ru.windcorp.progressia.test.TestContent; import ru.windcorp.progressia.test.TestMusicPlayer; -import ru.windcorp.progressia.test.TestPlayerControls; public class ClientProxy implements Proxy { diff --git a/src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java b/src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java new file mode 100644 index 0000000..e513b52 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java @@ -0,0 +1,26 @@ +package ru.windcorp.progressia.common.util; + +import glm.vec._3.i.Vec3i; + +public class HashableVec3i { + + public Vec3i value; + + public HashableVec3i(Vec3i inValue) + { + value = inValue; + } + + @Override + public int hashCode() // Uses first 3 primes greater than 2**30 + { + return 1073741827 * value.x + 1073741831 * value.y + 1073741833 * value.z; + } + + @Override + public boolean equals(Object comparee) + { + return hashCode() == comparee.hashCode(); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/server/ServerThread.java b/src/main/java/ru/windcorp/progressia/server/ServerThread.java index 7420c2b..aa0ff67 100644 --- a/src/main/java/ru/windcorp/progressia/server/ServerThread.java +++ b/src/main/java/ru/windcorp/progressia/server/ServerThread.java @@ -26,6 +26,7 @@ import org.apache.logging.log4j.LogManager; import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.server.world.ticking.TickerCoordinator; +@SuppressWarnings("unused") public class ServerThread implements Runnable { private static final ThreadLocal SERVER_THREADS_MAP = new ThreadLocal<>(); diff --git a/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java b/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java index d715cea..2b86ee0 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerButtonTest.java @@ -22,7 +22,6 @@ import java.util.Collection; import ru.windcorp.progressia.client.ClientState; import ru.windcorp.progressia.client.graphics.Colors; import ru.windcorp.progressia.client.graphics.GUI; -import ru.windcorp.progressia.client.graphics.Layer; import ru.windcorp.progressia.client.graphics.font.Font; import ru.windcorp.progressia.client.graphics.gui.Button; import ru.windcorp.progressia.client.graphics.gui.Checkbox; @@ -34,7 +33,6 @@ import ru.windcorp.progressia.client.localization.MutableString; import ru.windcorp.progressia.client.localization.MutableStringLocalized; import ru.windcorp.progressia.server.ChunkManager; import ru.windcorp.progressia.server.ChunkManager.ChunksLoadFinishListener; -import ru.windcorp.progressia.server.ChunkManager.ChunksLoadListener; import ru.windcorp.progressia.server.Player; import ru.windcorp.progressia.server.ServerState; diff --git a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java index 355b7dc..7122c25 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java @@ -34,6 +34,7 @@ import java.nio.channels.Channels; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.HashMap; import java.util.Scanner; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; @@ -41,10 +42,9 @@ import java.util.zip.InflaterInputStream; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import com.google.common.io.CountingOutputStream; - import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.state.IOContext; +import ru.windcorp.progressia.common.util.HashableVec3i; import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.WorldData; @@ -56,7 +56,8 @@ public class TestWorldDiskIO { private static Path SAVE_DIR = Paths.get("tmp_world"); private static final String formatFile = "world.format"; private static final Logger LOG = LogManager.getLogger("TestWorldDiskIO"); - + + private static HashMap randomAccessMap; private static final boolean ENABLE = true; private static int maxSize = 1048576; @@ -116,6 +117,7 @@ public class TestWorldDiskIO { } private static void setRegionSize(int format) { + randomAccessMap = new HashMap(); switch (format) { case 0: case 1: @@ -134,9 +136,9 @@ public class TestWorldDiskIO { } } - private static void expand(int sectors) { + /*private static void expand(int sectors) { - } + }*/ public static void saveChunk(ChunkData chunk, Server server) { if (!ENABLE) @@ -229,9 +231,13 @@ public class TestWorldDiskIO { * dosave = false; */ - try ( - RandomAccessFile output = new RandomAccessFile(path.toFile(), "rw") - ) { + + RandomAccessFile output = randomAccessMap.get(new HashableVec3i(saveCoords)); + if (output == null) + { + output = new RandomAccessFile(path.toFile(), "rw"); + randomAccessMap.put(new HashableVec3i(saveCoords), output); + } // LOG.debug(output.read()); if (output.read() < 0) { LOG.info("Making header"); @@ -303,9 +309,6 @@ public class TestWorldDiskIO { // LOG.info("Used {} sectors",(int) // tempData.length/sectorSize + 1); - output.close(); - - } } // else if (currentFormat) } catch (IOException e) { @@ -532,35 +535,40 @@ public class TestWorldDiskIO { private static ChunkData loadRegion(Path path, Vec3i chunkPos, WorldData world, Server server) throws IOException, DecodingException { - try ( - BufferedInputStream input = new BufferedInputStream(Files.newInputStream(path)) - ) { + Vec3i streamCoords = getRegion(chunkPos); + + RandomAccessFile input = randomAccessMap.get(new HashableVec3i(streamCoords)); + if (input == null) + { + input = new RandomAccessFile(path.toFile(), "rw"); + randomAccessMap.put(new HashableVec3i(streamCoords), input); + } + // LOG.info(path.toString()); Vec3i pos = getRegionLoc(chunkPos); + int shortOffset = (offsetBytes + 1) * (pos.z + regionSize.z * (pos.y + regionSize.y * pos.x)); int fullOffset = (offsetBytes + 1) * (chunksPerRegion); - input.skipNBytes(shortOffset); + input.seek(shortOffset); int offset = 0; for (int i = 0; i < offsetBytes; i++) { offset *= 256; offset += input.read(); } int sectorLength = input.read(); - input.skipNBytes(fullOffset - shortOffset - offsetBytes - 1); - input.skipNBytes(sectorSize * offset); + input.seek(fullOffset + sectorSize * offset); // LOG.info("Read {} sectors", sectorLength); - byte tempData[] = input.readNBytes(sectorSize * sectorLength); + byte tempData[] = new byte[sectorSize * sectorLength]; + input.read(tempData); DataInputStream trueInput = new DataInputStream( new InflaterInputStream(new BufferedInputStream(new ByteArrayInputStream(tempData))) ); ChunkData chunk = ChunkIO.load(world, chunkPos, trueInput, IOContext.SAVE); readGenerationHint(chunk, trueInput, server); - trueInput.close(); return chunk; - } } private static void readGenerationHint(ChunkData chunk, DataInputStream input, Server server) From fae09edb16d9acd4231eb30e7b6c69105852412c Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Thu, 19 Aug 2021 10:47:16 -0400 Subject: [PATCH 14/49] Fixes n Speed n Stuff -Better comparison for HashableVec3i -Changed RandomAccessFile to MappedByteBuffer -natFromInt now works properly -better region selection -Changes to make different strategies work --- .../progressia/common/util/HashableVec3i.java | 11 +- .../progressia/test/TestWorldDiskIO.java | 169 +++++++++++++----- 2 files changed, 138 insertions(+), 42 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java b/src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java index e513b52..b94f79d 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java +++ b/src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java @@ -20,7 +20,16 @@ public class HashableVec3i { @Override public boolean equals(Object comparee) { - return hashCode() == comparee.hashCode(); + if (comparee == null) + { + return false; + } + if (comparee.getClass() != HashableVec3i.class) + { + return false; + } + HashableVec3i compareeCast = (HashableVec3i) comparee; + return compareeCast.value == value; } } diff --git a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java index 7122c25..6859028 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java @@ -25,12 +25,15 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; +import java.io.EOFException; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.RandomAccessFile; -import java.nio.channels.Channels; +import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -57,7 +60,7 @@ public class TestWorldDiskIO { private static final String formatFile = "world.format"; private static final Logger LOG = LogManager.getLogger("TestWorldDiskIO"); - private static HashMap randomAccessMap; + private static HashMap mappedByteMap; private static final boolean ENABLE = true; private static int maxSize = 1048576; @@ -75,8 +78,8 @@ public class TestWorldDiskIO { private static int natFromInt(int loc) { if (loc < 0) - return (-loc) << 1 + 1; - return loc << 1; + return -2*loc - 1; + return 2*loc; } /* @@ -89,10 +92,40 @@ public class TestWorldDiskIO { */ private static Vec3i getRegion(Vec3i chunkLoc) { + int x = chunkLoc.x; + if (x<0) + { + x /= regionSize.x; + x--; + } + else + { + x /= regionSize.x; + } + int y = chunkLoc.y; + if (y<0) + { + y /= regionSize.y; + y--; + } + else + { + y /= regionSize.y; + } + int z = chunkLoc.z; + if (z<0) + { + z /= regionSize.z; + z--; + } + else + { + z /= regionSize.z; + } return new Vec3i( - natFromInt(chunkLoc.x / regionSize.x), - natFromInt(chunkLoc.y / regionSize.y), - natFromInt(chunkLoc.z / regionSize.z) + natFromInt(x), + natFromInt(y), + natFromInt(z) ); } @@ -115,9 +148,19 @@ public class TestWorldDiskIO { // regions.put(new Vec3i(0,0,0), new Vec3i(1,1,1)); } + + public static int getAvailableSector(MappedByteBuffer mbb) + { + int sectorsUsed = 0; + for (int i=offsetBytes; i<(offsetBytes+1)*chunksPerRegion; i+= (offsetBytes+1)) + { + sectorsUsed += mbb.get(i); + } + return sectorsUsed; + } private static void setRegionSize(int format) { - randomAccessMap = new HashMap(); + mappedByteMap = new HashMap(); switch (format) { case 0: case 1: @@ -232,38 +275,54 @@ public class TestWorldDiskIO { */ - RandomAccessFile output = randomAccessMap.get(new HashableVec3i(saveCoords)); + MappedByteBuffer output = mappedByteMap.get(new HashableVec3i(saveCoords)); + LOG.info("saveCoords {},{},{}", saveCoords.x, saveCoords.y, saveCoords.z); if (output == null) { - output = new RandomAccessFile(path.toFile(), "rw"); - randomAccessMap.put(new HashableVec3i(saveCoords), output); + output = makeNew(path, new HashableVec3i(saveCoords)); } // LOG.debug(output.read()); - if (output.read() < 0) { + if (output.get() < 0) { LOG.info("Making header"); - output.writeChars("\0".repeat((offsetBytes + 1) * chunksPerRegion)); + ByteBuffer headerBytes = ByteBuffer.allocate((offsetBytes + 1) * chunksPerRegion); + for (int i=0;i<(offsetBytes + 1) * chunksPerRegion;i++) + { + headerBytes.put(i, (byte) 0); + } + output.put(headerBytes); } Vec3i pos = getRegionLoc(chunk.getPosition()); int shortOffset = (offsetBytes + 1) * (pos.z + regionSize.z * (pos.y + regionSize.y * pos.x)); int fullOffset = (offsetBytes + 1) * (chunksPerRegion); - output.seek(shortOffset); - int offset = output.readInt(); - int sectorLength = offset & 255; - offset = offset >> 8; + output.position(shortOffset); + int offset = 0; + for (int i = 0; i < offsetBytes; i++) { + offset *= 256; + offset += output.get(); + } + ByteBuffer readOffset = ByteBuffer.allocate(offsetBytes); + int sectorLength = output.get(); if (sectorLength == 0) { - int outputLen = (int) output.length(); - offset = (int) (outputLen - fullOffset) / sectorSize + 1; - output.seek(shortOffset); - output.writeInt(offset << 8); - output.seek(outputLen); - /* - * while (output.length() Date: Wed, 25 Aug 2021 16:15:38 -0400 Subject: [PATCH 15/49] -Better HashableVec3i compare -Added RandomFileMapped class -Made it a wrapper for RandomAccessFile and contains maps of locations and lengths -Added confirmHeaderHealth method to made sure the file isnt corrupted -Changed everything from MappedByteBuffers to RandomFileMappeds. --- .../progressia/common/util/HashableVec3i.java | 2 +- .../progressia/test/TestWorldDiskIO.java | 307 +++++++++++------- 2 files changed, 198 insertions(+), 111 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java b/src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java index b94f79d..f003555 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java +++ b/src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java @@ -29,7 +29,7 @@ public class HashableVec3i { return false; } HashableVec3i compareeCast = (HashableVec3i) comparee; - return compareeCast.value == value; + return compareeCast.value.x == value.x && compareeCast.value.y == value.y && compareeCast.value.z == value.z ; } } diff --git a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java index b79a90e..e52c94c 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java @@ -31,14 +31,13 @@ import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; +import java.util.HashSet; import java.util.Scanner; +import java.util.Set; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; @@ -55,12 +54,78 @@ import ru.windcorp.progressia.common.world.io.ChunkIO; import ru.windcorp.progressia.server.Server; public class TestWorldDiskIO { + + private static final boolean resetCorrupted = true; + + public static class RandomFileMapped { + public RandomAccessFile file; + public HashMap offsets; + public HashMap lengths; + + public RandomFileMapped(RandomAccessFile inFile) + { + boolean check = false; + offsets = new HashMap<>(); + lengths = new HashMap<>(); + try { + check = confirmHeaderHealth(inFile, offsets, lengths); + } catch (IOException e) { + e.printStackTrace(); + } + if (!check) + { + LOG.debug("Uh the file broke"); + if (resetCorrupted) { + byte headerBytes[] = new byte[4 * chunksPerRegion]; + for (int i = 0; i < 4 * chunksPerRegion; i++) { + headerBytes[i] = (byte) 0; + } + try { + inFile.write(headerBytes); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + + file = inFile; + } + + public int getOffset(Vec3i chunkLoc) + { + return offsets.get(new HashableVec3i(chunkLoc)); + } + + public boolean hasOffset(Vec3i pos) { + return offsets.containsKey(new HashableVec3i(pos)); + } + + public void putOffset(Vec3i pos, int offset) + { + offsets.put(new HashableVec3i(pos), offset); + } + + public int getLength(Vec3i chunkLoc) + { + return lengths.get(new HashableVec3i(chunkLoc)); + } + + public boolean hasLength(Vec3i pos) { + return lengths.containsKey(new HashableVec3i(pos)); + } + + public void putLength(Vec3i pos, int length) + { + lengths.put(new HashableVec3i(pos), length); + } + } private static Path SAVE_DIR = Paths.get("tmp_world"); private static final String formatFile = "world.format"; private static final Logger LOG = LogManager.getLogger("TestWorldDiskIO"); - private static HashMap mappedByteMap; + private static HashMap inOutMap; private static final boolean ENABLE = true; private static int maxSize = 1048576; @@ -71,7 +136,6 @@ public class TestWorldDiskIO { // private Map regions = new HashMap(); private static Vec3i regionSize; private static int chunksPerRegion; - private static int offsetBytes; private static int currentFormat = -1; private static String extension = ".null"; @@ -149,18 +213,19 @@ public class TestWorldDiskIO { // regions.put(new Vec3i(0,0,0), new Vec3i(1,1,1)); } - public static int getAvailableSector(MappedByteBuffer mbb) + /*public static int getAvailableSector(MappedByteBuffer mbb) { int sectorsUsed = 0; for (int i=offsetBytes; i<(offsetBytes+1)*chunksPerRegion; i+= (offsetBytes+1)) { + sectorsUsed += mbb.get(i); } return sectorsUsed; - } + }*/ private static void setRegionSize(int format) { - mappedByteMap = new HashMap(); + inOutMap = new HashMap(); switch (format) { case 0: case 1: @@ -173,15 +238,49 @@ public class TestWorldDiskIO { regionSize = new Vec3i(16); chunksPerRegion = 16 * 16 * 16; currentFormat = 65536; - offsetBytes = 3; extension = ".progressia_region"; break; } } - /*private static void expand(int sectors) { - - }*/ + public static boolean confirmHeaderHealth(RandomAccessFile input, HashMap offsets, HashMap length) throws IOException + { + Set used = new HashSet(); + input.seek(0); + if (input.length() < 4*chunksPerRegion) + { + return false; + } + for (int i=0;i<4*chunksPerRegion;i+=4) + { + int offset = 0; + for (int ii = 0; ii < 3; ii++) { + offset *= 256; + offset += input.read(); + } + int sectorLength = input.read(); + if (sectorLength==0) + { + continue; + } + int headerPos = i/4; + int x = headerPos/regionSize.y/regionSize.z; + int y = (headerPos/regionSize.z)%regionSize.y; + int z = headerPos%regionSize.z; + HashableVec3i key = new HashableVec3i(new Vec3i(x,y,z)); + offsets.put(key , offset); + length.put(key, sectorLength); + for (int ii=0;ii>= 8; + } + output.write(readOffset); + + output.setLength(fullOffset + offset * sectorSize); + } + outputMap.putOffset(pos, offset); } - // int bytestoWrite = output.readInt(); - // output.mark(sectorSize*sectorLength); - - // BufferedOutputStream counter = new - // BufferedOutputStream(Files.newOutputStream( - // SAVE_DIR.resolve(tempFile))); ByteArrayOutputStream tempDataStream = new ByteArrayOutputStream(); DataOutputStream trueOutput = new DataOutputStream( new DeflaterOutputStream( new BufferedOutputStream(tempDataStream) ) ); - // CountingOutputStream countOutput = new - // CountingOutputStream(trueOutput); - - // LOG.info("Before: {}",output.); - // trueOutput.writeBytes("uh try this"); - // counter. ChunkIO.save(chunk, trueOutput, IOContext.SAVE); writeGenerationHint(chunk, trueOutput, server); - - /* - * while (counter.getCount()%sectorSize != 0) { - * counter.write(0); - * } - */ - - // LOG.info("Wrote {} bytes to - // {},{},{}",trueOutput.size(),chunk.getPosition().x,chunk.getPosition().y,chunk.getPosition().z); - + trueOutput.close(); byte tempData[] = tempDataStream.toByteArray(); - output.position( fullOffset + sectorSize * offset); - output.put(ByteBuffer.wrap( tempData)); + output.seek( fullOffset + sectorSize * offset); + output.write(tempData); - output.position(shortOffset + offsetBytes); - output.put(ByteBuffer.wrap( new byte[] {(byte) (tempData.length / sectorSize + 1)})); + output.seek(shortOffset + 3); + output.write(tempData.length / sectorSize + 1); + outputMap.putLength(pos, tempData.length / sectorSize + 1); // LOG.info("Used {} sectors",(int) // tempData.length/sectorSize + 1); @@ -375,15 +437,16 @@ public class TestWorldDiskIO { } } - private static MappedByteBuffer makeNew(Path path, Object hashObj) { + private static RandomFileMapped makeNew(Path path, Object hashObj) { try { RandomAccessFile raf = new RandomAccessFile(path.toFile(), "rw"); - FileChannel fc = raf.getChannel(); - MappedByteBuffer output = fc.map(FileChannel.MapMode.READ_WRITE, 0, maxSize*chunksPerRegion); - output.limit(maxSize*chunksPerRegion); - mappedByteMap.put((HashableVec3i) hashObj, output); - return output; + //FileChannel fc = raf.getChannel(); + //MappedByteBuffer output = fc.map(FileChannel.MapMode.READ_WRITE, 0, maxSize*chunksPerRegion); + //output.limit(maxSize*chunksPerRegion); + RandomFileMapped rfm = new RandomFileMapped(raf); + inOutMap.put((HashableVec3i) hashObj, rfm); + return rfm; } catch (IOException e) { @@ -611,37 +674,61 @@ public class TestWorldDiskIO { private static DefaultChunkData loadRegion(Path path, Vec3i chunkPos, DefaultWorldData world, Server server) throws IOException, DecodingException { + int offset = 0; + int sectorLength = 0; + Vec3i pos; + RandomFileMapped inputMap; + int fullOffset = 4 * (chunksPerRegion); try { Vec3i streamCoords = getRegion(chunkPos); - MappedByteBuffer input = mappedByteMap.get(new HashableVec3i(streamCoords)); - LOG.info("streamCoords {},{},{}", streamCoords.x,streamCoords.y,streamCoords.z); - if (input == null) + inputMap = inOutMap.get(new HashableVec3i(streamCoords)); + //LOG.info("streamCoords {},{},{}", streamCoords.x,streamCoords.y,streamCoords.z); + if (inputMap == null) { //input = new RandomAccessFile(path.toFile(), "rw"); //input = Files.newByteChannel(path); - input = makeNew(path, new HashableVec3i(streamCoords)); + inputMap = makeNew(path, new HashableVec3i(streamCoords)); } + + RandomAccessFile input = inputMap.file; + + + pos = getRegionLoc(chunkPos); + + if (inputMap.hasOffset(pos)) + { + offset = inputMap.getOffset(pos); + sectorLength = inputMap.getLength(pos); + //LOG.info("{},{}", offset, sectorLength); + } + else + { // LOG.info(path.toString()); - Vec3i pos = getRegionLoc(chunkPos); - int shortOffset = (offsetBytes + 1) * (pos.z + regionSize.z * (pos.y + regionSize.y * pos.x)); - int fullOffset = (offsetBytes + 1) * (chunksPerRegion); - input.position(shortOffset); - int offset = 0; - for (int i = 0; i < offsetBytes; i++) { + int shortOffset = 4 * (pos.z + regionSize.z * (pos.y + regionSize.y * pos.x)); + + input.seek(shortOffset); + for (int i = 0; i < 3; i++) { offset *= 256; - offset += input.get(); + offset += input.read(); } - int sectorLength = input.get(); - input.position(fullOffset + sectorSize * offset); + sectorLength = input.read(); + if (sectorLength == 0) + { + return null; + } + inputMap.putOffset(pos, offset); + inputMap.putLength(pos, sectorLength); + } + input.seek(fullOffset + sectorSize * offset); // LOG.info("Read {} sectors", sectorLength); byte tempData[] = new byte[sectorSize * sectorLength]; - input.get(tempData); + input.read(tempData); DataInputStream trueInput = new DataInputStream( new InflaterInputStream(new BufferedInputStream(new ByteArrayInputStream(tempData))) @@ -652,7 +739,7 @@ public class TestWorldDiskIO { } catch (EOFException e) { - LOG.warn("Reached end of file"); + LOG.warn("Reached end of file, offset was {}, sectors was {}", offset, sectorLength); e.printStackTrace(); } return null; From f74c731a3d7e5a091cd6c4f351f881e5f6205547 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Fri, 27 Aug 2021 12:20:58 +0300 Subject: [PATCH 16/49] Fixed GUI buttons and a rare crash on startup --- .../client/graphics/gui/BasicButton.java | 1 + .../client/graphics/model/Shapes.java | 18 ++++ .../server/comms/ClientManager.java | 2 +- .../planet/PlanetTerrainGenerator.java | 17 +++ .../progressia/test/TestBlockRenderTux.java | 100 ++++++++++++++++++ .../windcorp/progressia/test/TestContent.java | 4 + .../resources/assets/textures/blocks/Tux.png | Bin 0 -> 921 bytes 7 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/main/java/ru/windcorp/progressia/test/TestBlockRenderTux.java create mode 100644 src/main/resources/assets/textures/blocks/Tux.png diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java index cd30152..0ae328e 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java @@ -120,6 +120,7 @@ public abstract class BasicButton extends Component { public void setPressed(boolean isPressed) { if (this.isPressed != isPressed) { this.isPressed = isPressed; + requestReassembly(); if (isPressed) { takeFocus(); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java index 29d8629..803f05d 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java @@ -20,10 +20,12 @@ package ru.windcorp.progressia.client.graphics.model; import java.util.Map; +import glm.mat._4.Mat4; import glm.vec._3.Vec3; import glm.vec._4.Vec4; import ru.windcorp.progressia.client.graphics.backend.Usage; import ru.windcorp.progressia.client.graphics.texture.Texture; +import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.world.rels.AbsFace; public class Shapes { @@ -271,6 +273,22 @@ public class Shapes { return this; } + + public PppBuilder apply(Mat4 transform) { + VectorUtil.applyMat4(origin, transform); + VectorUtil.rotateOnly(width, transform); + VectorUtil.rotateOnly(height, transform); + VectorUtil.rotateOnly(depth, transform); + return this; + } + + public PppBuilder scale(float factor) { + origin.mul(factor); + width.mul(factor); + height.mul(factor); + depth.mul(factor); + return this; + } public PppBuilder flip() { this.flip = true; diff --git a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java index 6b1595e..dbcf081 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java @@ -95,7 +95,7 @@ public class ClientManager { } public void processPackets() { - getClients().forEach(CommsChannel::processPackets); + clients.forEach(CommsChannel::processPackets); } /** diff --git a/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetTerrainGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetTerrainGenerator.java index a43ad9f..cb4507c 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetTerrainGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetTerrainGenerator.java @@ -86,6 +86,11 @@ class PlanetTerrainGenerator { } private void generateBorderTerrain(Server server, DefaultChunkData chunk) { + if (chunk.getPosition().x == 0 && chunk.getPosition().y == 0 && chunk.getPosition().z == 0) { + generateCore(server, chunk); + return; + } + BlockData stone = BlockDataRegistry.getInstance().get("Test:Stone"); BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); @@ -109,4 +114,16 @@ class PlanetTerrainGenerator { }); } + private void generateCore(Server server, DefaultChunkData chunk) { + BlockData tux = BlockDataRegistry.getInstance().get("Test:Tux"); + BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); + + + GenericChunks.forEachBiC(bic -> { + chunk.setBlock(bic, air, false); + }); + + chunk.setBlock(new Vec3i(7, 7, 0), tux, false); + } + } diff --git a/src/main/java/ru/windcorp/progressia/test/TestBlockRenderTux.java b/src/main/java/ru/windcorp/progressia/test/TestBlockRenderTux.java new file mode 100644 index 0000000..de6d291 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/TestBlockRenderTux.java @@ -0,0 +1,100 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test; + +import glm.mat._4.Mat4; +import glm.vec._3.Vec3; +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.client.graphics.Colors; +import ru.windcorp.progressia.client.graphics.backend.Usage; +import ru.windcorp.progressia.client.graphics.model.Renderable; +import ru.windcorp.progressia.client.graphics.model.Shape; +import ru.windcorp.progressia.client.graphics.model.ShapeParts; +import ru.windcorp.progressia.client.graphics.model.Shapes; +import ru.windcorp.progressia.client.graphics.model.StaticModel; +import ru.windcorp.progressia.client.graphics.texture.ComplexTexture; +import ru.windcorp.progressia.client.graphics.texture.SimpleTextures; +import ru.windcorp.progressia.client.graphics.texture.TexturePrimitive; +import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; +import ru.windcorp.progressia.client.world.block.BlockRender; +import ru.windcorp.progressia.common.world.DefaultChunkData; + +public class TestBlockRenderTux extends BlockRender { + + private final Renderable model; + + public TestBlockRenderTux(String id) { + super(id); + + TexturePrimitive primitive = SimpleTextures.get("blocks/Tux").getSprite().getPrimitive(); + ComplexTexture texture = new ComplexTexture(primitive, 72, 60); + + WorldRenderProgram program = WorldRenderProgram.getDefault(); + StaticModel.Builder builder = StaticModel.builder(); + + final float scale = 1f / 40; + final float lift = -1f / 2 / scale; + + builder.addPart( + new Shapes.PppBuilder(program, texture.getCuboidTextures(0, 36, 12)).setSize(12) + .centerAt(0, 0, 18 + (12 / 2) + lift).scale(scale).create() + ); + builder.addPart( + new Shapes.PppBuilder(program, texture.getCuboidTextures(0, 0, 18)).setSize(18) + .centerAt(0, 0, 18 / 2 + lift).scale(scale).create() + ); + builder.addPart( + new Shape( + Usage.STATIC, + program, + ShapeParts.createRectangle( + program, + texture.get(48, 44, 24, 16), + Colors.WHITE, + new Vec3(18 / 2 + 1, -(24 / 2), lift), + new Vec3(0, 24, 0), + new Vec3(0, 0, 16), + false + ), + ShapeParts.createRectangle( + program, + texture.get(48, 44, 24, 16), + Colors.WHITE, + new Vec3(18 / 2 + 1, -(24 / 2), lift), + new Vec3(0, 24, 0), + new Vec3(0, 0, 16), + true + ) + ), + new Mat4().scale(scale) + ); + + this.model = builder.build(); + } + + @Override + public Renderable createRenderable(DefaultChunkData chunk, Vec3i relBlockInChunk) { + return model; + } + + @Override + public boolean needsOwnRenderable() { + return true; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java index 9ad6518..8396e21 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java @@ -135,6 +135,10 @@ public class TestContent { register(new BlockData("Test:StatieSpawner")); register(new BlockRenderOpaqueCube("Test:StatieSpawner", getBlockTexture("StatieSpawner"))); register(new TestBlockLogicStatieSpawner("Test:StatieSpawner")); + + register(new BlockData("Test:Tux")); + register(new TestBlockRenderTux("Test:Tux")); + register(new BlockLogic("Test:Tux")); BlockDataRegistry.getInstance().values().forEach(PLACEABLE_BLOCKS::add); PLACEABLE_BLOCKS.removeIf(b -> placeableBlacklist.contains(b.getId())); diff --git a/src/main/resources/assets/textures/blocks/Tux.png b/src/main/resources/assets/textures/blocks/Tux.png new file mode 100644 index 0000000000000000000000000000000000000000..f96c5be84944cf9b96fdab32a9cfb1d1ad0bfeb7 GIT binary patch literal 921 zcmV;K17`e*P)%TG!#CRnz{f002y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00RL@L_t(|+U=S>YU4l{hF^(* zNwKxq6s~s(F)6l{tA(wcYWp0(H_!oe1KlA3cUw6a0#fUMv2Wlai@UUHR$F90qmAcJ zqnWWR&j$fBqmea_-tTYX01YjU;|dn7D2f0_wsJQG01ToG7w~ofX0zJj=5`1G2tAfV zBRI?X#4CuW95SyUhH^Zh4>pK045ExV=K*~H%%^%hm@nbag}RG zNxg6}Rs~G9oKGs9Il8BI7R&P-05BepmBuZmGa z*Iv|{S8W&LZQhk~cpIb5iRJ|{>tKDW7}P~bO=8w^K9OE)q>^6DM#s)%dzZMm9irS# z|8pPFc~5+2YY`DZ(XT_K#k`h%7j7OXdU$Z=b9OR-pAd+ zA!VopToxqJOCCfSTK^9!j$``Rsh&<&9}!Sem(?tGiY5cotK$xT9^?UeKpv0>)H7So zCrY)`Spq6|Q>DJ_ECH#u8cqsDSy%7++^8v>v#F$Yz*u)Nl`|pN=SG49`tw%MpK^`M zVWFj@vk20c!-A=#>#uKKL3N|Eqb5oUYUep^t_V-&^}uLjh1_=ubN{S;}Tc z_T?31!o`v#v91KwwW`n3sczonL%Rmh8c>oXNYhkl{`c#v_Jh#cG);w&Wb>U;P#whkxPYzZC%TB9aFzo7hKKP zL8bx8vYIRqH??D{$SbG~AlBP+{YF`e)m5=G1-XLc5`^(y%r+z*9M|zk`G@49n#5$P vr^7SZ_jL}C?QXsf=cLoTtqped$LD_m@Eg96zGh_-00000NkvXXu0mjf;kBEA literal 0 HcmV?d00001 From 98250cd524d2bce8b982117baf298591cb28bc7c Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Fri, 27 Aug 2021 16:59:05 -0400 Subject: [PATCH 17/49] Some changes for efficiency(not yet) -Tried to use threads/executors in ChunkRequestDaemon, it just hangs. -Added isEmpty and isOpaque attributes to DefaultChunkData (should this just be in ChunkData?) -Added compute and getter functions to access(for everything after loading) -Doesn't render empty chunks(not yet used) -Using format 65537 allows the empty and opaqueness to be saved. They do not do anything yet and there is no way to set them yet -Added loadRegionX and ".progressia_chunkx" file -removed formats 0 and 1, which use individual chunk files. --- .../progressia/client/world/ChunkRender.java | 4 +- .../common/world/DefaultChunkData.java | 45 +- .../management/load/ChunkRequestDaemon.java | 13 +- .../planet/PlanetFeatureGenerator.java | 3 + .../progressia/test/TestWorldDiskIO.java | 391 ++++++++++-------- 5 files changed, 283 insertions(+), 173 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java index 41aa933..2d432ab 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java @@ -102,7 +102,9 @@ public class ChunkRender } public synchronized void render(ShapeRenderHelper renderer) { - model.render(renderer); + if (!data.isEmpty) { + model.render(renderer); + } } public synchronized void update() { diff --git a/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java b/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java index e11509b..967fe4e 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java @@ -25,8 +25,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Objects; - import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.block.BlockData; @@ -45,6 +45,11 @@ public class DefaultChunkData implements ChunkData { public static final int BLOCKS_PER_CHUNK = Coordinates.CHUNK_SIZE; public static final int CHUNK_RADIUS = BLOCKS_PER_CHUNK / 2; + + public boolean isEmpty = false; + public boolean isOpaque = false; + + public static HashSet transparent; private final Vec3i position = new Vec3i(); private final DefaultWorldData world; @@ -199,6 +204,44 @@ public class DefaultChunkData implements ChunkData { public void setGenerationHint(Object generationHint) { this.generationHint = generationHint; } + + public void computeOpaque() + { + for (int xyz=0;xyz buffer = new ArrayList<>(); private static class ChunkUnloadRequest { @@ -113,16 +116,16 @@ public class ChunkRequestDaemon { } private void processLoadQueues() { - toRequestUnload.forEach(this::scheduleUnload); + toRequestUnload.forEach((pos) -> executor.submit(() -> scheduleUnload(pos))); toRequestUnload.clear(); - toLoad.forEach(getChunkManager()::loadOrGenerateChunk); + toLoad.forEach((pos) -> executor.submit(() -> getChunkManager().loadOrGenerateChunk(pos))); toLoad.clear(); - toGenerate.forEach(getChunkManager()::loadOrGenerateChunk); + toGenerate.forEach((pos) -> executor.submit(() -> getChunkManager().loadOrGenerateChunk(pos))); toGenerate.clear(); - unloadScheduledChunks(); + executor.submit(() -> unloadScheduledChunks()); } private void scheduleUnload(Vec3i chunkPos) { diff --git a/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetFeatureGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetFeatureGenerator.java index 97e2424..205ea43 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetFeatureGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetFeatureGenerator.java @@ -56,6 +56,9 @@ public class PlanetFeatureGenerator { generateBorderFeatures(server, chunk); } + chunk.computeEmpty(); + chunk.computeOpaque(); + chunk.setGenerationHint(true); } diff --git a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java index e52c94c..d15e88f 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java @@ -126,7 +126,7 @@ public class TestWorldDiskIO { private static final Logger LOG = LogManager.getLogger("TestWorldDiskIO"); private static HashMap inOutMap; - private static final boolean ENABLE = true; + private static final boolean ENABLE = false; private static int maxSize = 1048576; private static int sectorSize = maxSize / 256; @@ -227,19 +227,19 @@ public class TestWorldDiskIO { private static void setRegionSize(int format) { inOutMap = new HashMap(); switch (format) { - case 0: - case 1: - regionSize = new Vec3i(1); - chunksPerRegion = 1; - currentFormat = format; - extension = ".progressia_chunk"; - break; case 65536: + default: regionSize = new Vec3i(16); chunksPerRegion = 16 * 16 * 16; currentFormat = 65536; extension = ".progressia_region"; break; + case 65537: + regionSize = new Vec3i(16); + chunksPerRegion = 16 * 16 * 16; + currentFormat = 65536; + extension = ".progressia_regionx"; + break; } } @@ -288,63 +288,7 @@ public class TestWorldDiskIO { try { - if (currentFormat == 0) { - LOG.debug( - "Saving {} {} {}", - chunk.getPosition().x, - chunk.getPosition().y, - chunk.getPosition().z - ); - - Files.createDirectories(SAVE_DIR); - - Path path = SAVE_DIR.resolve( - String.format( - "chunk_%+d_%+d_%+d" + extension, - chunk.getPosition().x, - chunk.getPosition().y, - chunk.getPosition().z - ) - ); - - try ( - DataOutputStream output = new DataOutputStream( - new DeflaterOutputStream(new BufferedOutputStream(Files.newOutputStream(path))) - ) - ) { - ChunkIO.save(chunk, output, IOContext.SAVE); - writeGenerationHint(chunk, output, server); - } - } else if (currentFormat == 1) { - LOG.debug( - "Saving {} {} {}", - chunk.getPosition().x, - chunk.getPosition().y, - chunk.getPosition().z - ); - - Files.createDirectories(SAVE_DIR); - - Vec3i saveCoords = getRegion(chunk.getPosition()); - - Path path = SAVE_DIR.resolve( - String.format( - "chunk_%d_%d_%d" + extension, - saveCoords.x, - saveCoords.y, - saveCoords.z - ) - ); - - try ( - DataOutputStream output = new DataOutputStream( - new DeflaterOutputStream(new BufferedOutputStream(Files.newOutputStream(path))) - ) - ) { - ChunkIO.save(chunk, output, IOContext.SAVE); - writeGenerationHint(chunk, output, server); - } - } else if (currentFormat == 65536) { + if (currentFormat == 65536) { LOG.debug( "Saving {} {} {}", chunk.getPosition().x, @@ -430,6 +374,97 @@ public class TestWorldDiskIO { // LOG.info("Used {} sectors",(int) // tempData.length/sectorSize + 1); + } + else if (currentFormat == 65537) { + LOG.debug( + "Saving {} {} {}", + chunk.getPosition().x, + chunk.getPosition().y, + chunk.getPosition().z + ); + + Files.createDirectories(SAVE_DIR); + + Vec3i saveCoords = getRegion(chunk.getPosition()); + + Path path = SAVE_DIR.resolve( + String.format( + "%d_%d_%d" + extension, + saveCoords.x, + saveCoords.y, + saveCoords.z + ) + ); + + + RandomFileMapped outputMap = inOutMap.get(new HashableVec3i(saveCoords)); + //LOG.info("saveCoords {},{},{}", saveCoords.x, saveCoords.y, saveCoords.z); + if (outputMap == null) + { + outputMap = makeNew(path, new HashableVec3i(saveCoords)); + } + RandomAccessFile output = outputMap.file; + + Vec3i pos = getRegionLoc(chunk.getPosition()); + int shortOffset = 4 * (pos.z + regionSize.z * (pos.y + regionSize.y * pos.x)); + int fullOffset = 4 * (chunksPerRegion); + int offset = 0; + + if (outputMap.hasOffset(pos)) + { + offset = outputMap.getOffset(pos); + } + else { + output.seek(shortOffset); + for (int i = 0; i < 3; i++) { + offset *= 256; + offset += output.read(); + } + int sectorLength = output.read(); + if (sectorLength == 0) { + int outputLen = (int) output.length(); + offset = (int) (outputLen - fullOffset) / sectorSize + 1; + int tempOffset = offset; + output.seek(shortOffset); + + byte readOffset[] = new byte[3]; + for (int i = 0; i < 3; i++) { + readOffset[2 - i] = (byte) (tempOffset % 256); + tempOffset >>= 8; + } + output.write(readOffset); + + output.setLength(fullOffset + offset * sectorSize); + } + outputMap.putOffset(pos, offset); + } + + ByteArrayOutputStream tempDataStream = new ByteArrayOutputStream(); + DataOutputStream trueOutput = new DataOutputStream( + new DeflaterOutputStream( + new BufferedOutputStream(tempDataStream) + ) + ); + ChunkIO.save(chunk, trueOutput, IOContext.SAVE); + writeGenerationHint(chunk, trueOutput, server); + + trueOutput.close(); + + byte tempData[] = tempDataStream.toByteArray(); + + output.seek( fullOffset + sectorSize * offset); + + chunk.computeOpaque(); + chunk.computeEmpty(); + output.write((chunk.isOpaque() ? 1 : 0) << 1 + (chunk.isEmpty() ? 1 : 0)); //Writes extra flag byte of whether or not the chunk is empty or solid + output.write(tempData); + + output.seek(shortOffset + 3); + output.write(tempData.length / sectorSize + 1); + outputMap.putLength(pos, tempData.length / sectorSize + 1); + // LOG.info("Used {} sectors",(int) + // tempData.length/sectorSize + 1); + } // else if (currentFormat) } catch (IOException e) { @@ -522,94 +557,7 @@ public class TestWorldDiskIO { } } - if (currentFormat == 0) { - - Path path = SAVE_DIR.resolve( - String.format( - "chunk_%+d_%+d_%+d" + extension, - chunkPos.x, - chunkPos.y, - chunkPos.z - ) - ); - - if (!Files.exists(path)) { - LOG.debug( - "Not found {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z - ); - - return null; - } - - try { - DefaultChunkData result = load(path, chunkPos, world, server); - - LOG.debug( - "Loaded {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z - ); - - return result; - } catch (Exception e) { - e.printStackTrace(); - LOG.debug( - "Could not load {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z - ); - return null; - } - } else if (currentFormat == 1) { - Vec3i saveCoords = getRegion(chunkPos); - - Path path = SAVE_DIR.resolve( - String.format( - "chunk_%d_%d_%d" + extension, - saveCoords.x, - saveCoords.y, - saveCoords.z - ) - ); - - if (!Files.exists(path)) { - LOG.debug( - "Not found {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z - ); - - return null; - } - - try { - DefaultChunkData result = load(path, chunkPos, world, server); - - LOG.debug( - "Loaded {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z - ); - - return result; - } catch (Exception e) { - e.printStackTrace(); - LOG.debug( - "Could not load {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z - ); - return null; - } - } else if (currentFormat == 65536) { + if (currentFormat == 65536) { Vec3i saveCoords = getRegion(chunkPos); Path path = SAVE_DIR.resolve( @@ -654,21 +602,52 @@ public class TestWorldDiskIO { return null; } } - return null; - } + else if (currentFormat == 65537) { + Vec3i saveCoords = getRegion(chunkPos); - private static DefaultChunkData load(Path path, Vec3i chunkPos, DefaultWorldData world, Server server) - throws IOException, - DecodingException { - try ( - DataInputStream input = new DataInputStream( - new InflaterInputStream(new BufferedInputStream(Files.newInputStream(path))) - ) - ) { - DefaultChunkData chunk = ChunkIO.load(world, chunkPos, input, IOContext.SAVE); - readGenerationHint(chunk, input, server); - return chunk; + Path path = SAVE_DIR.resolve( + String.format( + "%d_%d_%d" + extension, + saveCoords.x, + saveCoords.y, + saveCoords.z + ) + ); + + if (!Files.exists(path)) { + LOG.debug( + "Not found {} {} {}", + chunkPos.x, + chunkPos.y, + chunkPos.z + ); + + return null; + } + + try { + DefaultChunkData result = loadRegionX(path, chunkPos, world, server); + + LOG.debug( + "Loaded {} {} {}", + chunkPos.x, + chunkPos.y, + chunkPos.z + ); + + return result; + } catch (Exception e) { + e.printStackTrace(); + LOG.debug( + "Could not load {} {} {}", + chunkPos.x, + chunkPos.y, + chunkPos.z + ); + return null; + } } + return null; } private static DefaultChunkData loadRegion(Path path, Vec3i chunkPos, DefaultWorldData world, Server server) @@ -744,6 +723,86 @@ public class TestWorldDiskIO { } return null; } + + private static DefaultChunkData loadRegionX(Path path, Vec3i chunkPos, DefaultWorldData world, Server server) + throws IOException, + DecodingException { + int offset = 0; + int sectorLength = 0; + Vec3i pos; + RandomFileMapped inputMap; + int fullOffset = 4 * (chunksPerRegion); + try + { + Vec3i streamCoords = getRegion(chunkPos); + + inputMap = inOutMap.get(new HashableVec3i(streamCoords)); + //LOG.info("streamCoords {},{},{}", streamCoords.x,streamCoords.y,streamCoords.z); + if (inputMap == null) + { + //input = new RandomAccessFile(path.toFile(), "rw"); + //input = Files.newByteChannel(path); + inputMap = makeNew(path, new HashableVec3i(streamCoords)); + } + + RandomAccessFile input = inputMap.file; + + + pos = getRegionLoc(chunkPos); + + if (inputMap.hasOffset(pos)) + { + offset = inputMap.getOffset(pos); + sectorLength = inputMap.getLength(pos); + //LOG.info("{},{}", offset, sectorLength); + } + else + { + + // LOG.info(path.toString()); + + int shortOffset = 4 * (pos.z + regionSize.z * (pos.y + regionSize.y * pos.x)); + + input.seek(shortOffset); + for (int i = 0; i < 3; i++) { + offset *= 256; + offset += input.read(); + } + sectorLength = input.read(); + if (sectorLength == 0) + { + return null; + } + inputMap.putOffset(pos, offset); + inputMap.putLength(pos, sectorLength); + } + input.seek(fullOffset + sectorSize * offset); + + int xByte = input.read(); + + // LOG.info("Read {} sectors", sectorLength); + + byte tempData[] = new byte[sectorSize * sectorLength]; + input.read(tempData); + + DataInputStream trueInput = new DataInputStream( + new InflaterInputStream(new BufferedInputStream(new ByteArrayInputStream(tempData))) + ); + DefaultChunkData chunk = ChunkIO.load(world, chunkPos, trueInput, IOContext.SAVE); + readGenerationHint(chunk, trueInput, server); + + chunk.isOpaque = (xByte & 2)==2; + chunk.isEmpty = (xByte & 1)==1; + + return chunk; + } + catch (EOFException e) + { + LOG.warn("Reached end of file, offset was {}, sectors was {}", offset, sectorLength); + e.printStackTrace(); + } + return null; + } private static void readGenerationHint(DefaultChunkData chunk, DataInputStream input, Server server) throws IOException, From a222ea8f67ffd57db294dc70c115f8fddf579732 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Sat, 28 Aug 2021 21:14:35 +0300 Subject: [PATCH 18/49] Fixed multithread chunk IO --- .../common/world/DefaultChunkData.java | 38 ++-- .../ru/windcorp/progressia/server/Server.java | 12 +- .../progressia/server/ServerState.java | 2 +- .../management/load/ChunkRequestDaemon.java | 191 ++++++++++++------ .../server/world/DefaultChunkLogic.java | 4 +- .../server/world/DefaultWorldLogic.java | 3 +- .../test/gen/TestGenerationConfig.java | 45 +++-- 7 files changed, 191 insertions(+), 104 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java b/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java index 967fe4e..730580c 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java @@ -25,8 +25,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; import java.util.Objects; +import java.util.Set; + import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.block.BlockData; @@ -49,7 +50,7 @@ public class DefaultChunkData implements ChunkData { public boolean isEmpty = false; public boolean isOpaque = false; - public static HashSet transparent; + public static Set transparent = Collections.emptySet(); private final Vec3i position = new Vec3i(); private final DefaultWorldData world; @@ -204,45 +205,36 @@ public class DefaultChunkData implements ChunkData { public void setGenerationHint(Object generationHint) { this.generationHint = generationHint; } - - public void computeOpaque() - { - for (int xyz=0;xyz buffer = new ArrayList<>(); - + private static class ChunkUnloadRequest { private final Vec3i chunkPos; private final long unloadAt; - + public ChunkUnloadRequest(Vec3i chunkPos, long unloadAt) { this.chunkPos = chunkPos; this.unloadAt = unloadAt; } - + /** * @return the chunk position */ public Vec3i getChunkPos() { return chunkPos; } - + /** * @return the moment when the chunks becomes eligible for unloading */ @@ -72,19 +72,42 @@ public class ChunkRequestDaemon { return unloadAt; } } - + private final ChunkMap unloadSchedule = ChunkMaps.newHashMap(); + private Thread thread = null; + private final AtomicBoolean shouldRun = new AtomicBoolean(false); + public ChunkRequestDaemon(ChunkManager chunkManager) { this.chunkManager = chunkManager; this.loaded = getServer().getWorld().getData().getLoadedChunks(); } - - public void tick() { + + public synchronized void start() { + if (this.thread != null) { + throw new IllegalStateException("Already running"); + } + + this.thread = new Thread(this::runOffthread, getClass().getSimpleName()); + this.shouldRun.set(true); + this.thread.start(); + } + + public synchronized void stop() { + this.shouldRun.set(false); + + synchronized (this) { + notify(); + } + } + + public synchronized void tick() { synchronized (getServer().getWorld().getData()) { synchronized (getServer().getPlayerManager().getMutex()) { loadAndUnloadChunks(); sendAndRevokeChunks(); + + notify(); } } } @@ -116,18 +139,13 @@ public class ChunkRequestDaemon { } private void processLoadQueues() { - toRequestUnload.forEach((pos) -> executor.submit(() -> scheduleUnload(pos))); - toRequestUnload.clear(); - - toLoad.forEach((pos) -> executor.submit(() -> getChunkManager().loadOrGenerateChunk(pos))); - toLoad.clear(); - - toGenerate.forEach((pos) -> executor.submit(() -> getChunkManager().loadOrGenerateChunk(pos))); + toGenerate.forEach(getChunkManager()::loadOrGenerateChunk); toGenerate.clear(); - - executor.submit(() -> unloadScheduledChunks()); + + toRequestUnload.forEach(this::scheduleUnload); + toRequestUnload.clear(); } - + private void scheduleUnload(Vec3i chunkPos) { if (unloadSchedule.containsKey(chunkPos)) { // Unload already requested, skip @@ -136,27 +154,8 @@ public class ChunkRequestDaemon { long unloadAt = System.currentTimeMillis() + (long) (getUnloadDelay() * 1000); Vec3i chunkPosCopy = new Vec3i(chunkPos); - - unloadSchedule.put(chunkPosCopy, new ChunkUnloadRequest(chunkPosCopy, unloadAt)); - } - - private void unloadScheduledChunks() { - long now = System.currentTimeMillis(); - - for (Iterator it = unloadSchedule.values().iterator(); it.hasNext();) { - ChunkUnloadRequest request = it.next(); - - if (request.getUnloadAt() < now) { - it.remove(); - - if (requested.contains(request.getChunkPos())) { - continue; // do not unload chunks that became requested - } - - getChunkManager().unloadChunk(request.getChunkPos()); - } - } + unloadSchedule.put(chunkPosCopy, new ChunkUnloadRequest(chunkPosCopy, unloadAt)); } private void sendAndRevokeChunks() { @@ -172,51 +171,129 @@ public class ChunkRequestDaemon { toGenerate.add(chunk); return; } - + if (vision.isChunkVisible(chunk.getPosition())) { return; } - + buffer.add(chunk.getPosition()); }); - - if (buffer.isEmpty()) return; + + if (buffer.isEmpty()) + return; for (Vec3i chunkPos : buffer) { getChunkManager().sendChunk(vision.getPlayer(), chunkPos); } - + buffer.clear(); } - + private void revokeChunks(PlayerVision vision) { vision.getVisibleChunks().forEach(chunkPos -> { if (getChunkManager().isChunkLoaded(chunkPos) && vision.getRequestedChunks().contains(chunkPos)) return; buffer.add(new Vec3i(chunkPos)); }); - - if (buffer.isEmpty()) return; + + if (buffer.isEmpty()) + return; for (Vec3i chunkPos : buffer) { getChunkManager().revokeChunk(vision.getPlayer(), chunkPos); } - + buffer.clear(); } + /* + * Off-thread activity + */ + + private void runOffthread() { + while (true) { + + processLoadQueue(); + processUnloadQueue(); + + synchronized (this) { + try { + // We're not afraid of spurious wakeups + wait(); + } catch (InterruptedException e) { + // Pretend nothing happened + } + + if (!shouldRun.get()) { + return; + } + } + + } + } + + private void processQueueOffthread(ChunkSet queue, Consumer action) { + while (true) { + synchronized (this) { + Iterator iterator = toLoad.iterator(); + if (!iterator.hasNext()) { + return; + } + Vec3i position = iterator.next(); + iterator.remove(); + + action.accept(position); + } + } + } + + private void processLoadQueue() { + processQueueOffthread(toLoad, getChunkManager()::loadOrGenerateChunk); + } + + private void processUnloadQueue() { + long now = System.currentTimeMillis(); + + Collection toUnload = null; + + synchronized (this) { + for (Iterator it = unloadSchedule.values().iterator(); it.hasNext();) { + ChunkUnloadRequest request = it.next(); + + if (request.getUnloadAt() < now) { + it.remove(); + + if (requested.contains(request.getChunkPos())) { + continue; // do not unload chunks that became requested + } + + if (toUnload == null) { + toUnload = new ArrayList<>(); + } + toUnload.add(request.getChunkPos()); + } + } + } + + if (toUnload == null) { + return; + } + + toUnload.forEach(getChunkManager()::unloadChunk); + } + /** * @return the minimum amount of time a chunk will spend in the unload queue */ public float getUnloadDelay() { return CHUNK_UNLOAD_DELAY; } - + /** * @return the manager */ public ChunkManager getChunkManager() { return chunkManager; } - + public Server getServer() { return getChunkManager().getServer(); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java b/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java index d18ff11..7a05adf 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java @@ -34,7 +34,7 @@ import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.TileDataStack; import ru.windcorp.progressia.common.world.generic.GenericChunks; import ru.windcorp.progressia.common.world.TileDataReference; -import ru.windcorp.progressia.server.Server; +import ru.windcorp.progressia.server.ServerState; import ru.windcorp.progressia.server.world.block.BlockLogic; import ru.windcorp.progressia.server.world.block.BlockLogicRegistry; import ru.windcorp.progressia.server.world.block.TickableBlock; @@ -226,7 +226,7 @@ public class DefaultChunkLogic implements ChunkLogic { } private void tmp_generateTickLists() { - ServerWorldContextRO context = Server.getCurrentServer().createContext(getUp()); + ServerWorldContextRO context = ServerState.getInstance().createContext(getUp()); GenericChunks.forEachBiC(blockInChunk -> { diff --git a/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java b/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java index 3e654b6..5c4e75d 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java @@ -19,6 +19,7 @@ package ru.windcorp.progressia.server.world; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -43,7 +44,7 @@ public class DefaultWorldLogic implements WorldLogic { private final WorldGenerator generator; - private final Map chunks = new HashMap<>(); + private final Map chunks = Collections.synchronizedMap(new HashMap<>()); private final Evaluation tickEntitiesTask = new TickEntitiesTask(); diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java index ee0f312..76090d6 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java @@ -49,9 +49,18 @@ public class TestGenerationConfig { private static final float CURVATURE = Units.get("100 m"); private static final float INNER_RADIUS = Units.get("200 m"); - private static final Fields FIELDS = new Fields(SEED); + private final Fields fields = new Fields(SEED); + private final Function generator; + + public TestGenerationConfig() { + this.generator = createGenerator(); + } + + public Function getGenerator() { + return generator; + } - public static Function createGenerator() { + private Function createGenerator() { Planet planet = new Planet( ((int) PLANET_RADIUS) / Coordinates.CHUNK_SIZE, @@ -60,7 +69,7 @@ public class TestGenerationConfig { INNER_RADIUS ); - TestHeightMap heightMap = new TestHeightMap(planet, planet.getRadius() / 4, FIELDS); + TestHeightMap heightMap = new TestHeightMap(planet, planet.getRadius() / 4, fields); FloatRangeMap layers = new ArrayFloatRangeMap<>(); registerTerrainLayers(layers); @@ -72,11 +81,11 @@ public class TestGenerationConfig { } - private static void registerTerrainLayers(FloatRangeMap layers) { + private void registerTerrainLayers(FloatRangeMap layers) { BlockData dirt = BlockDataRegistry.getInstance().get("Test:Dirt"); BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); - SurfaceFloatField cliffs = FIELDS.get("Test:Cliff"); + SurfaceFloatField cliffs = fields.get("Test:Cliff"); WorleyProceduralNoise.Builder builder = WorleyProceduralNoise.builder(); TestContent.ROCKS.getRocks().forEach(rock -> { @@ -88,9 +97,9 @@ public class TestGenerationConfig { } }, 1); }); - SurfaceFloatField rockDepthOffsets = FIELDS.register( + SurfaceFloatField rockDepthOffsets = fields.register( "Test:RockDepthOffsets", - () -> tweak(FIELDS.primitive(), 40, 5) + () -> tweak(fields.primitive(), 40, 5) ); RockLayer rockLayer = new RockLayer(builder.build(SEED), rockDepthOffsets); @@ -105,28 +114,28 @@ public class TestGenerationConfig { layers.put(4, Float.POSITIVE_INFINITY, rockLayer); } - private static void registerFeatures(List features) { + private void registerFeatures(List features) { - SurfaceFloatField forestiness = FIELDS.register( + SurfaceFloatField forestiness = fields.register( "Test:Forest", - () -> squash(scale(FIELDS.primitive(), 200), 5) + () -> squash(scale(fields.primitive(), 200), 5) ); - SurfaceFloatField grassiness = FIELDS.register( + SurfaceFloatField grassiness = fields.register( "Test:Grass", f -> multiply( - tweak(octaves(FIELDS.primitive(), 2, 2), 40, 0.5, 1.2), - squash(tweak(FIELDS.get("Test:Forest", f), 1, -1, 1), 10), - anti(squash(FIELDS.get("Test:Cliff", f), 10)) + tweak(octaves(fields.primitive(), 2, 2), 40, 0.5, 1.2), + squash(tweak(fields.get("Test:Forest", f), 1, -1, 1), 10), + anti(squash(fields.get("Test:Cliff", f), 10)) ) ); - Function floweriness = flowerName -> FIELDS.register( + Function floweriness = flowerName -> fields.register( "Test:Flower" + flowerName, f -> multiply( - selectPositive(squash(scale(octaves(FIELDS.primitive(), 2, 3), 100), 2), 1, 0.5), - tweak(FIELDS.get("Test:Forest", f), 1, -1, 1.1), - anti(squash(FIELDS.get("Test:Cliff", f), 10)) + selectPositive(squash(scale(octaves(fields.primitive(), 2, 3), 100), 2), 1, 0.5), + tweak(fields.get("Test:Forest", f), 1, -1, 1.1), + anti(squash(fields.get("Test:Cliff", f), 10)) ) ); From 41a2909f7c1575774a1bc6b93ecfa9e316e55bd7 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Sat, 28 Aug 2021 21:31:34 +0300 Subject: [PATCH 19/49] Reverted last two commits because no one wants to fix the bugs --- .../common/world/DefaultChunkData.java | 38 ++-- .../ru/windcorp/progressia/server/Server.java | 12 +- .../progressia/server/ServerState.java | 2 +- .../management/load/ChunkRequestDaemon.java | 191 ++++++------------ .../server/world/DefaultChunkLogic.java | 4 +- .../server/world/DefaultWorldLogic.java | 3 +- .../test/gen/TestGenerationConfig.java | 45 ++--- 7 files changed, 104 insertions(+), 191 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java b/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java index 730580c..967fe4e 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java @@ -25,9 +25,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Objects; -import java.util.Set; - import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.block.BlockData; @@ -50,7 +49,7 @@ public class DefaultChunkData implements ChunkData { public boolean isEmpty = false; public boolean isOpaque = false; - public static Set transparent = Collections.emptySet(); + public static HashSet transparent; private final Vec3i position = new Vec3i(); private final DefaultWorldData world; @@ -205,36 +204,45 @@ public class DefaultChunkData implements ChunkData { public void setGenerationHint(Object generationHint) { this.generationHint = generationHint; } - - public void computeOpaque() { - for (int xyz = 0; xyz < BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK; xyz++) { - if (transparent.contains(blocks[xyz])) { + + public void computeOpaque() + { + for (int xyz=0;xyz buffer = new ArrayList<>(); - + private static class ChunkUnloadRequest { private final Vec3i chunkPos; private final long unloadAt; - + public ChunkUnloadRequest(Vec3i chunkPos, long unloadAt) { this.chunkPos = chunkPos; this.unloadAt = unloadAt; } - + /** * @return the chunk position */ public Vec3i getChunkPos() { return chunkPos; } - + /** * @return the moment when the chunks becomes eligible for unloading */ @@ -72,42 +72,19 @@ public class ChunkRequestDaemon { return unloadAt; } } - + private final ChunkMap unloadSchedule = ChunkMaps.newHashMap(); - private Thread thread = null; - private final AtomicBoolean shouldRun = new AtomicBoolean(false); - public ChunkRequestDaemon(ChunkManager chunkManager) { this.chunkManager = chunkManager; this.loaded = getServer().getWorld().getData().getLoadedChunks(); } - - public synchronized void start() { - if (this.thread != null) { - throw new IllegalStateException("Already running"); - } - - this.thread = new Thread(this::runOffthread, getClass().getSimpleName()); - this.shouldRun.set(true); - this.thread.start(); - } - - public synchronized void stop() { - this.shouldRun.set(false); - - synchronized (this) { - notify(); - } - } - - public synchronized void tick() { + + public void tick() { synchronized (getServer().getWorld().getData()) { synchronized (getServer().getPlayerManager().getMutex()) { loadAndUnloadChunks(); sendAndRevokeChunks(); - - notify(); } } } @@ -139,13 +116,18 @@ public class ChunkRequestDaemon { } private void processLoadQueues() { - toGenerate.forEach(getChunkManager()::loadOrGenerateChunk); - toGenerate.clear(); - - toRequestUnload.forEach(this::scheduleUnload); + toRequestUnload.forEach((pos) -> executor.submit(() -> scheduleUnload(pos))); toRequestUnload.clear(); + + toLoad.forEach((pos) -> executor.submit(() -> getChunkManager().loadOrGenerateChunk(pos))); + toLoad.clear(); + + toGenerate.forEach((pos) -> executor.submit(() -> getChunkManager().loadOrGenerateChunk(pos))); + toGenerate.clear(); + + executor.submit(() -> unloadScheduledChunks()); } - + private void scheduleUnload(Vec3i chunkPos) { if (unloadSchedule.containsKey(chunkPos)) { // Unload already requested, skip @@ -154,9 +136,28 @@ public class ChunkRequestDaemon { long unloadAt = System.currentTimeMillis() + (long) (getUnloadDelay() * 1000); Vec3i chunkPosCopy = new Vec3i(chunkPos); - + unloadSchedule.put(chunkPosCopy, new ChunkUnloadRequest(chunkPosCopy, unloadAt)); } + + private void unloadScheduledChunks() { + long now = System.currentTimeMillis(); + + for (Iterator it = unloadSchedule.values().iterator(); it.hasNext();) { + ChunkUnloadRequest request = it.next(); + + if (request.getUnloadAt() < now) { + + it.remove(); + + if (requested.contains(request.getChunkPos())) { + continue; // do not unload chunks that became requested + } + + getChunkManager().unloadChunk(request.getChunkPos()); + } + } + } private void sendAndRevokeChunks() { getChunkManager().getLoadManager().getVisionManager().forEachVision(vision -> { @@ -171,129 +172,51 @@ public class ChunkRequestDaemon { toGenerate.add(chunk); return; } - + if (vision.isChunkVisible(chunk.getPosition())) { return; } - + buffer.add(chunk.getPosition()); }); - - if (buffer.isEmpty()) - return; + + if (buffer.isEmpty()) return; for (Vec3i chunkPos : buffer) { getChunkManager().sendChunk(vision.getPlayer(), chunkPos); } - + buffer.clear(); } - + private void revokeChunks(PlayerVision vision) { vision.getVisibleChunks().forEach(chunkPos -> { if (getChunkManager().isChunkLoaded(chunkPos) && vision.getRequestedChunks().contains(chunkPos)) return; buffer.add(new Vec3i(chunkPos)); }); - - if (buffer.isEmpty()) - return; + + if (buffer.isEmpty()) return; for (Vec3i chunkPos : buffer) { getChunkManager().revokeChunk(vision.getPlayer(), chunkPos); } - + buffer.clear(); } - /* - * Off-thread activity - */ - - private void runOffthread() { - while (true) { - - processLoadQueue(); - processUnloadQueue(); - - synchronized (this) { - try { - // We're not afraid of spurious wakeups - wait(); - } catch (InterruptedException e) { - // Pretend nothing happened - } - - if (!shouldRun.get()) { - return; - } - } - - } - } - - private void processQueueOffthread(ChunkSet queue, Consumer action) { - while (true) { - synchronized (this) { - Iterator iterator = toLoad.iterator(); - if (!iterator.hasNext()) { - return; - } - Vec3i position = iterator.next(); - iterator.remove(); - - action.accept(position); - } - } - } - - private void processLoadQueue() { - processQueueOffthread(toLoad, getChunkManager()::loadOrGenerateChunk); - } - - private void processUnloadQueue() { - long now = System.currentTimeMillis(); - - Collection toUnload = null; - - synchronized (this) { - for (Iterator it = unloadSchedule.values().iterator(); it.hasNext();) { - ChunkUnloadRequest request = it.next(); - - if (request.getUnloadAt() < now) { - it.remove(); - - if (requested.contains(request.getChunkPos())) { - continue; // do not unload chunks that became requested - } - - if (toUnload == null) { - toUnload = new ArrayList<>(); - } - toUnload.add(request.getChunkPos()); - } - } - } - - if (toUnload == null) { - return; - } - - toUnload.forEach(getChunkManager()::unloadChunk); - } - /** * @return the minimum amount of time a chunk will spend in the unload queue */ public float getUnloadDelay() { return CHUNK_UNLOAD_DELAY; } - + /** * @return the manager */ public ChunkManager getChunkManager() { return chunkManager; } - + public Server getServer() { return getChunkManager().getServer(); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java b/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java index 7a05adf..d18ff11 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java @@ -34,7 +34,7 @@ import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.TileDataStack; import ru.windcorp.progressia.common.world.generic.GenericChunks; import ru.windcorp.progressia.common.world.TileDataReference; -import ru.windcorp.progressia.server.ServerState; +import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.block.BlockLogic; import ru.windcorp.progressia.server.world.block.BlockLogicRegistry; import ru.windcorp.progressia.server.world.block.TickableBlock; @@ -226,7 +226,7 @@ public class DefaultChunkLogic implements ChunkLogic { } private void tmp_generateTickLists() { - ServerWorldContextRO context = ServerState.getInstance().createContext(getUp()); + ServerWorldContextRO context = Server.getCurrentServer().createContext(getUp()); GenericChunks.forEachBiC(blockInChunk -> { diff --git a/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java b/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java index 5c4e75d..3e654b6 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java @@ -19,7 +19,6 @@ package ru.windcorp.progressia.server.world; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -44,7 +43,7 @@ public class DefaultWorldLogic implements WorldLogic { private final WorldGenerator generator; - private final Map chunks = Collections.synchronizedMap(new HashMap<>()); + private final Map chunks = new HashMap<>(); private final Evaluation tickEntitiesTask = new TickEntitiesTask(); diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java index 76090d6..ee0f312 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java @@ -49,18 +49,9 @@ public class TestGenerationConfig { private static final float CURVATURE = Units.get("100 m"); private static final float INNER_RADIUS = Units.get("200 m"); - private final Fields fields = new Fields(SEED); - private final Function generator; - - public TestGenerationConfig() { - this.generator = createGenerator(); - } - - public Function getGenerator() { - return generator; - } + private static final Fields FIELDS = new Fields(SEED); - private Function createGenerator() { + public static Function createGenerator() { Planet planet = new Planet( ((int) PLANET_RADIUS) / Coordinates.CHUNK_SIZE, @@ -69,7 +60,7 @@ public class TestGenerationConfig { INNER_RADIUS ); - TestHeightMap heightMap = new TestHeightMap(planet, planet.getRadius() / 4, fields); + TestHeightMap heightMap = new TestHeightMap(planet, planet.getRadius() / 4, FIELDS); FloatRangeMap layers = new ArrayFloatRangeMap<>(); registerTerrainLayers(layers); @@ -81,11 +72,11 @@ public class TestGenerationConfig { } - private void registerTerrainLayers(FloatRangeMap layers) { + private static void registerTerrainLayers(FloatRangeMap layers) { BlockData dirt = BlockDataRegistry.getInstance().get("Test:Dirt"); BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); - SurfaceFloatField cliffs = fields.get("Test:Cliff"); + SurfaceFloatField cliffs = FIELDS.get("Test:Cliff"); WorleyProceduralNoise.Builder builder = WorleyProceduralNoise.builder(); TestContent.ROCKS.getRocks().forEach(rock -> { @@ -97,9 +88,9 @@ public class TestGenerationConfig { } }, 1); }); - SurfaceFloatField rockDepthOffsets = fields.register( + SurfaceFloatField rockDepthOffsets = FIELDS.register( "Test:RockDepthOffsets", - () -> tweak(fields.primitive(), 40, 5) + () -> tweak(FIELDS.primitive(), 40, 5) ); RockLayer rockLayer = new RockLayer(builder.build(SEED), rockDepthOffsets); @@ -114,28 +105,28 @@ public class TestGenerationConfig { layers.put(4, Float.POSITIVE_INFINITY, rockLayer); } - private void registerFeatures(List features) { + private static void registerFeatures(List features) { - SurfaceFloatField forestiness = fields.register( + SurfaceFloatField forestiness = FIELDS.register( "Test:Forest", - () -> squash(scale(fields.primitive(), 200), 5) + () -> squash(scale(FIELDS.primitive(), 200), 5) ); - SurfaceFloatField grassiness = fields.register( + SurfaceFloatField grassiness = FIELDS.register( "Test:Grass", f -> multiply( - tweak(octaves(fields.primitive(), 2, 2), 40, 0.5, 1.2), - squash(tweak(fields.get("Test:Forest", f), 1, -1, 1), 10), - anti(squash(fields.get("Test:Cliff", f), 10)) + tweak(octaves(FIELDS.primitive(), 2, 2), 40, 0.5, 1.2), + squash(tweak(FIELDS.get("Test:Forest", f), 1, -1, 1), 10), + anti(squash(FIELDS.get("Test:Cliff", f), 10)) ) ); - Function floweriness = flowerName -> fields.register( + Function floweriness = flowerName -> FIELDS.register( "Test:Flower" + flowerName, f -> multiply( - selectPositive(squash(scale(octaves(fields.primitive(), 2, 3), 100), 2), 1, 0.5), - tweak(fields.get("Test:Forest", f), 1, -1, 1.1), - anti(squash(fields.get("Test:Cliff", f), 10)) + selectPositive(squash(scale(octaves(FIELDS.primitive(), 2, 3), 100), 2), 1, 0.5), + tweak(FIELDS.get("Test:Forest", f), 1, -1, 1.1), + anti(squash(FIELDS.get("Test:Cliff", f), 10)) ) ); From cd16334db8c043a9b67ee0153d2c8557d534405e Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Sat, 28 Aug 2021 23:31:50 +0300 Subject: [PATCH 20/49] Moved TestWorldDiskIO to a subpackage and introduced some abstractions --- .../ru/windcorp/progressia/server/Server.java | 13 ++++- .../progressia/server/ServerState.java | 13 ++++- .../server/management/load/ChunkManager.java | 10 +++- .../server/world/DefaultWorldLogic.java | 10 +++- .../server/world/io/WorldContainer.java | 37 ++++++++++++ .../server/world/io/WorldContainerFormat.java | 32 ++++++++++ .../test/gen/TestGenerationConfig.java | 45 ++++++++------ .../progressia/test/region/RegionFormat.java | 36 ++++++++++++ .../test/{ => region}/TestWorldDiskIO.java | 58 +++++++++++-------- 9 files changed, 204 insertions(+), 50 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java create mode 100644 src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java create mode 100644 src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java rename src/main/java/ru/windcorp/progressia/test/{ => region}/TestWorldDiskIO.java (92%) diff --git a/src/main/java/ru/windcorp/progressia/server/Server.java b/src/main/java/ru/windcorp/progressia/server/Server.java index ea8504f..1b67392 100644 --- a/src/main/java/ru/windcorp/progressia/server/Server.java +++ b/src/main/java/ru/windcorp/progressia/server/Server.java @@ -46,6 +46,7 @@ import ru.windcorp.progressia.server.world.context.impl.DefaultServerContext; import ru.windcorp.progressia.server.world.context.impl.ReportingServerContext; import ru.windcorp.progressia.server.world.context.impl.RotatingServerContext; import ru.windcorp.progressia.server.world.generation.WorldGenerator; +import ru.windcorp.progressia.server.world.io.WorldContainer; import ru.windcorp.progressia.server.world.tasks.WorldAccessor; import ru.windcorp.progressia.server.world.ticking.Change; import ru.windcorp.progressia.server.world.ticking.Evaluation; @@ -78,11 +79,16 @@ public class Server { private final TickingSettings tickingSettings = new TickingSettings(); - public Server(DefaultWorldData world, Function generatorCreator) { + public Server( + DefaultWorldData world, + Function generatorCreator, + WorldContainer worldContainer + ) { this.world = new DefaultWorldLogic( world, this, generatorCreator.apply(this), + worldContainer, worldAccessor ); this.serverThread = new ServerThread(this); @@ -241,14 +247,14 @@ public class Server { public void scheduleChange(Change change) { serverThread.getTicker().requestChange(change); } - + /** * Delayed */ public void scheduleEvaluation(Evaluation evaluation) { serverThread.getTicker().requestEvaluation(evaluation); } - + /** * Immediate if possible, otherwise delayed */ @@ -349,6 +355,7 @@ public class Server { public void shutdown(String message) { LogManager.getLogger().warn("Server.shutdown() is not yet implemented"); serverThread.stop(); + getWorld().getContainer().close(); } private void scheduleWorldTicks(Server server) { diff --git a/src/main/java/ru/windcorp/progressia/server/ServerState.java b/src/main/java/ru/windcorp/progressia/server/ServerState.java index 00aa901..c38f21b 100644 --- a/src/main/java/ru/windcorp/progressia/server/ServerState.java +++ b/src/main/java/ru/windcorp/progressia/server/ServerState.java @@ -18,8 +18,14 @@ package ru.windcorp.progressia.server; +import java.nio.file.Paths; +import java.util.function.Function; + import ru.windcorp.progressia.common.world.DefaultWorldData; +import ru.windcorp.progressia.server.world.generation.WorldGenerator; +import ru.windcorp.progressia.server.world.io.WorldContainer; import ru.windcorp.progressia.test.gen.TestGenerationConfig; +import ru.windcorp.progressia.test.region.RegionFormat; public class ServerState { @@ -34,9 +40,14 @@ public class ServerState { } public static void startServer() { - Server server = new Server(new DefaultWorldData(), TestGenerationConfig.createGenerator()); + + Function generator = new TestGenerationConfig().getGenerator(); + WorldContainer container = new RegionFormat("Test:Region").create(Paths.get("tmp_world")); + + Server server = new Server(new DefaultWorldData(), generator, container); setInstance(server); server.start(); + } private ServerState() { diff --git a/src/main/java/ru/windcorp/progressia/server/management/load/ChunkManager.java b/src/main/java/ru/windcorp/progressia/server/management/load/ChunkManager.java index 3071530..b58a3b2 100644 --- a/src/main/java/ru/windcorp/progressia/server/management/load/ChunkManager.java +++ b/src/main/java/ru/windcorp/progressia/server/management/load/ChunkManager.java @@ -24,7 +24,7 @@ import ru.windcorp.progressia.common.world.PacketSendChunk; import ru.windcorp.progressia.common.world.DefaultWorldData; import ru.windcorp.progressia.server.Player; import ru.windcorp.progressia.server.Server; -import ru.windcorp.progressia.test.TestWorldDiskIO; +import ru.windcorp.progressia.server.world.io.WorldContainer; /** * Chunk manager provides facilities to load, unload and generate chunks for a @@ -51,6 +51,10 @@ public class ChunkManager { public Server getServer() { return getLoadManager().getServer(); } + + public WorldContainer getContainer() { + return getServer().getWorld().getContainer(); + } /** * Describes the result of an attempt to load a chunk. @@ -115,7 +119,7 @@ public class ChunkManager { DefaultWorldData world = getServer().getWorld().getData(); - DefaultChunkData chunk = TestWorldDiskIO.tryToLoad(chunkPos, world, getServer()); + DefaultChunkData chunk = getServer().getWorld().getContainer().load(chunkPos, world, getServer()); if (chunk != null) { world.addChunk(chunk); return LoadResult.LOADED_FROM_DISK; @@ -141,7 +145,7 @@ public class ChunkManager { } world.removeChunk(chunk); - TestWorldDiskIO.saveChunk(chunk, getServer()); + getContainer().save(chunk, getServer().getWorld().getData(), getServer()); return true; } diff --git a/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java b/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java index 3e654b6..b573d07 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java @@ -32,6 +32,7 @@ import ru.windcorp.progressia.common.world.WorldDataListener; import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.generation.WorldGenerator; +import ru.windcorp.progressia.server.world.io.WorldContainer; import ru.windcorp.progressia.server.world.tasks.TickEntitiesTask; import ru.windcorp.progressia.server.world.tasks.WorldAccessor; import ru.windcorp.progressia.server.world.ticking.Evaluation; @@ -42,17 +43,20 @@ public class DefaultWorldLogic implements WorldLogic { private final Server server; private final WorldGenerator generator; + private final WorldContainer container; private final Map chunks = new HashMap<>(); private final Evaluation tickEntitiesTask = new TickEntitiesTask(); - public DefaultWorldLogic(DefaultWorldData data, Server server, WorldGenerator generator, WorldAccessor accessor) { + public DefaultWorldLogic(DefaultWorldData data, Server server, WorldGenerator generator, WorldContainer container, WorldAccessor accessor) { this.data = data; this.server = server; this.generator = generator; data.setGravityModel(getGenerator().getGravityModel()); + + this.container = container; data.addListener(new WorldDataListener() { @Override @@ -105,6 +109,10 @@ public class DefaultWorldLogic implements WorldLogic { public WorldGenerator getGenerator() { return generator; } + + public WorldContainer getContainer() { + return container; + } public DefaultChunkData generate(Vec3i chunkPos) { DefaultChunkData chunk = getGenerator().generate(chunkPos); diff --git a/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java new file mode 100644 index 0000000..07aa7b5 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java @@ -0,0 +1,37 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.server.world.io; + +import java.nio.file.Path; + +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.world.DefaultChunkData; +import ru.windcorp.progressia.common.world.DefaultWorldData; +import ru.windcorp.progressia.server.Server; + +public interface WorldContainer { + + Path getPath(); + + DefaultChunkData load(Vec3i position, DefaultWorldData world, Server server); + + void save(DefaultChunkData chunk, DefaultWorldData world, Server server); + + void close(); + +} diff --git a/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java new file mode 100644 index 0000000..9c8e0c8 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java @@ -0,0 +1,32 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.server.world.io; + +import java.nio.file.Path; + +import ru.windcorp.progressia.common.util.namespaces.Namespaced; + +public abstract class WorldContainerFormat extends Namespaced { + + public WorldContainerFormat(String id) { + super(id); + } + + public abstract WorldContainer create(Path directory); + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java index ee0f312..76090d6 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java @@ -49,9 +49,18 @@ public class TestGenerationConfig { private static final float CURVATURE = Units.get("100 m"); private static final float INNER_RADIUS = Units.get("200 m"); - private static final Fields FIELDS = new Fields(SEED); + private final Fields fields = new Fields(SEED); + private final Function generator; + + public TestGenerationConfig() { + this.generator = createGenerator(); + } + + public Function getGenerator() { + return generator; + } - public static Function createGenerator() { + private Function createGenerator() { Planet planet = new Planet( ((int) PLANET_RADIUS) / Coordinates.CHUNK_SIZE, @@ -60,7 +69,7 @@ public class TestGenerationConfig { INNER_RADIUS ); - TestHeightMap heightMap = new TestHeightMap(planet, planet.getRadius() / 4, FIELDS); + TestHeightMap heightMap = new TestHeightMap(planet, planet.getRadius() / 4, fields); FloatRangeMap layers = new ArrayFloatRangeMap<>(); registerTerrainLayers(layers); @@ -72,11 +81,11 @@ public class TestGenerationConfig { } - private static void registerTerrainLayers(FloatRangeMap layers) { + private void registerTerrainLayers(FloatRangeMap layers) { BlockData dirt = BlockDataRegistry.getInstance().get("Test:Dirt"); BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); - SurfaceFloatField cliffs = FIELDS.get("Test:Cliff"); + SurfaceFloatField cliffs = fields.get("Test:Cliff"); WorleyProceduralNoise.Builder builder = WorleyProceduralNoise.builder(); TestContent.ROCKS.getRocks().forEach(rock -> { @@ -88,9 +97,9 @@ public class TestGenerationConfig { } }, 1); }); - SurfaceFloatField rockDepthOffsets = FIELDS.register( + SurfaceFloatField rockDepthOffsets = fields.register( "Test:RockDepthOffsets", - () -> tweak(FIELDS.primitive(), 40, 5) + () -> tweak(fields.primitive(), 40, 5) ); RockLayer rockLayer = new RockLayer(builder.build(SEED), rockDepthOffsets); @@ -105,28 +114,28 @@ public class TestGenerationConfig { layers.put(4, Float.POSITIVE_INFINITY, rockLayer); } - private static void registerFeatures(List features) { + private void registerFeatures(List features) { - SurfaceFloatField forestiness = FIELDS.register( + SurfaceFloatField forestiness = fields.register( "Test:Forest", - () -> squash(scale(FIELDS.primitive(), 200), 5) + () -> squash(scale(fields.primitive(), 200), 5) ); - SurfaceFloatField grassiness = FIELDS.register( + SurfaceFloatField grassiness = fields.register( "Test:Grass", f -> multiply( - tweak(octaves(FIELDS.primitive(), 2, 2), 40, 0.5, 1.2), - squash(tweak(FIELDS.get("Test:Forest", f), 1, -1, 1), 10), - anti(squash(FIELDS.get("Test:Cliff", f), 10)) + tweak(octaves(fields.primitive(), 2, 2), 40, 0.5, 1.2), + squash(tweak(fields.get("Test:Forest", f), 1, -1, 1), 10), + anti(squash(fields.get("Test:Cliff", f), 10)) ) ); - Function floweriness = flowerName -> FIELDS.register( + Function floweriness = flowerName -> fields.register( "Test:Flower" + flowerName, f -> multiply( - selectPositive(squash(scale(octaves(FIELDS.primitive(), 2, 3), 100), 2), 1, 0.5), - tweak(FIELDS.get("Test:Forest", f), 1, -1, 1.1), - anti(squash(FIELDS.get("Test:Cliff", f), 10)) + selectPositive(squash(scale(octaves(fields.primitive(), 2, 3), 100), 2), 1, 0.5), + tweak(fields.get("Test:Forest", f), 1, -1, 1.1), + anti(squash(fields.get("Test:Cliff", f), 10)) ) ); diff --git a/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java b/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java new file mode 100644 index 0000000..85d1bbe --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java @@ -0,0 +1,36 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test.region; + +import java.nio.file.Path; + +import ru.windcorp.progressia.server.world.io.WorldContainer; +import ru.windcorp.progressia.server.world.io.WorldContainerFormat; + +public class RegionFormat extends WorldContainerFormat { + + public RegionFormat(String id) { + super(id); + } + + @Override + public WorldContainer create(Path directory) { + return new TestWorldDiskIO(directory); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java similarity index 92% rename from src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java rename to src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java index d15e88f..b391ec3 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package ru.windcorp.progressia.test; +package ru.windcorp.progressia.test.region; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -52,12 +52,13 @@ import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DefaultWorldData; import ru.windcorp.progressia.common.world.io.ChunkIO; import ru.windcorp.progressia.server.Server; +import ru.windcorp.progressia.server.world.io.WorldContainer; -public class TestWorldDiskIO { +public class TestWorldDiskIO implements WorldContainer { private static final boolean resetCorrupted = true; - public static class RandomFileMapped { + public class RandomFileMapped { public RandomAccessFile file; public HashMap offsets; public HashMap lengths; @@ -121,11 +122,11 @@ public class TestWorldDiskIO { } } - private static Path SAVE_DIR = Paths.get("tmp_world"); + private Path SAVE_DIR = Paths.get("tmp_world"); private static final String formatFile = "world.format"; private static final Logger LOG = LogManager.getLogger("TestWorldDiskIO"); - private static HashMap inOutMap; + private HashMap inOutMap; private static final boolean ENABLE = false; private static int maxSize = 1048576; @@ -134,11 +135,11 @@ public class TestWorldDiskIO { private static final int bestFormat = 65536; // private Map regions = new HashMap(); - private static Vec3i regionSize; - private static int chunksPerRegion; + private Vec3i regionSize; + private int chunksPerRegion; - private static int currentFormat = -1; - private static String extension = ".null"; + private int currentFormat = -1; + private String extension = ".null"; private static int natFromInt(int loc) { if (loc < 0) @@ -155,7 +156,7 @@ public class TestWorldDiskIO { * } */ - private static Vec3i getRegion(Vec3i chunkLoc) { + private Vec3i getRegion(Vec3i chunkLoc) { int x = chunkLoc.x; if (x<0) { @@ -197,15 +198,11 @@ public class TestWorldDiskIO { return ((a % m) + m) % m; } - private static Vec3i getRegionLoc(Vec3i chunkLoc) { + private Vec3i getRegionLoc(Vec3i chunkLoc) { return new Vec3i(mod(chunkLoc.x, regionSize.x), mod(chunkLoc.y, regionSize.y), mod(chunkLoc.z, regionSize.z)); } - public static void initRegions() { - initRegions(null); - } - - public static void initRegions(Path worldPath) { + public TestWorldDiskIO(Path worldPath) { if (worldPath != null) { SAVE_DIR = worldPath; } @@ -224,7 +221,7 @@ public class TestWorldDiskIO { return sectorsUsed; }*/ - private static void setRegionSize(int format) { + private void setRegionSize(int format) { inOutMap = new HashMap(); switch (format) { case 65536: @@ -243,7 +240,7 @@ public class TestWorldDiskIO { } } - public static boolean confirmHeaderHealth(RandomAccessFile input, HashMap offsets, HashMap length) throws IOException + public boolean confirmHeaderHealth(RandomAccessFile input, HashMap offsets, HashMap length) throws IOException { Set used = new HashSet(); input.seek(0); @@ -282,7 +279,8 @@ public class TestWorldDiskIO { return true; } - public static void saveChunk(DefaultChunkData chunk, Server server) { + @Override + public void save(DefaultChunkData chunk, DefaultWorldData world, Server server) { if (!ENABLE) return; @@ -472,7 +470,7 @@ public class TestWorldDiskIO { } } - private static RandomFileMapped makeNew(Path path, Object hashObj) { + private RandomFileMapped makeNew(Path path, Object hashObj) { try { RandomAccessFile raf = new RandomAccessFile(path.toFile(), "rw"); @@ -490,12 +488,13 @@ public class TestWorldDiskIO { return null; } - private static void writeGenerationHint(DefaultChunkData chunk, DataOutputStream output, Server server) + private void writeGenerationHint(DefaultChunkData chunk, DataOutputStream output, Server server) throws IOException { server.getWorld().getGenerator().writeGenerationHint(output, chunk.getGenerationHint()); } - public static DefaultChunkData tryToLoad(Vec3i chunkPos, DefaultWorldData world, Server server) { + @Override + public DefaultChunkData load(Vec3i chunkPos, DefaultWorldData world, Server server) { if (!ENABLE) return null; @@ -650,7 +649,7 @@ public class TestWorldDiskIO { return null; } - private static DefaultChunkData loadRegion(Path path, Vec3i chunkPos, DefaultWorldData world, Server server) + private DefaultChunkData loadRegion(Path path, Vec3i chunkPos, DefaultWorldData world, Server server) throws IOException, DecodingException { int offset = 0; @@ -724,7 +723,7 @@ public class TestWorldDiskIO { return null; } - private static DefaultChunkData loadRegionX(Path path, Vec3i chunkPos, DefaultWorldData world, Server server) + private DefaultChunkData loadRegionX(Path path, Vec3i chunkPos, DefaultWorldData world, Server server) throws IOException, DecodingException { int offset = 0; @@ -810,4 +809,15 @@ public class TestWorldDiskIO { chunk.setGenerationHint(server.getWorld().getGenerator().readGenerationHint(input)); } + @Override + public Path getPath() { + return SAVE_DIR; + } + + @Override + public void close() { + // TODO Auto-generated method stub + + } + } From f4300558d518ce42a9de50cb1c76d5d9828ee63e Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Sun, 29 Aug 2021 02:08:19 +0300 Subject: [PATCH 21/49] Formatted and broke the saving mechanism. I'm too tired to bugfix - Refactored and formatted TestWorldDiskIO - Removed HashableVec3i - Added Coordinates methods for custom bit count - Properly reverted commit 98250cd - Known bugs: - Server shutdown close()s regions too early - Re-entering a world does not show saved changes --- .../progressia/client/world/ChunkRender.java | 4 +- .../progressia/common/util/HashableVec3i.java | 35 - .../progressia/common/world/Coordinates.java | 67 ++ .../common/world/DefaultChunkData.java | 45 +- .../management/load/ChunkRequestDaemon.java | 13 +- .../planet/PlanetFeatureGenerator.java | 3 - .../progressia/test/region/Region.java | 249 +++++ .../test/region/TestWorldDiskIO.java | 848 +++--------------- 8 files changed, 428 insertions(+), 836 deletions(-) delete mode 100644 src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java create mode 100644 src/main/java/ru/windcorp/progressia/test/region/Region.java diff --git a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java index 2d432ab..41aa933 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java @@ -102,9 +102,7 @@ public class ChunkRender } public synchronized void render(ShapeRenderHelper renderer) { - if (!data.isEmpty) { - model.render(renderer); - } + model.render(renderer); } public synchronized void update() { diff --git a/src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java b/src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java deleted file mode 100644 index f003555..0000000 --- a/src/main/java/ru/windcorp/progressia/common/util/HashableVec3i.java +++ /dev/null @@ -1,35 +0,0 @@ -package ru.windcorp.progressia.common.util; - -import glm.vec._3.i.Vec3i; - -public class HashableVec3i { - - public Vec3i value; - - public HashableVec3i(Vec3i inValue) - { - value = inValue; - } - - @Override - public int hashCode() // Uses first 3 primes greater than 2**30 - { - return 1073741827 * value.x + 1073741831 * value.y + 1073741833 * value.z; - } - - @Override - public boolean equals(Object comparee) - { - if (comparee == null) - { - return false; - } - if (comparee.getClass() != HashableVec3i.class) - { - return false; - } - HashableVec3i compareeCast = (HashableVec3i) comparee; - return compareeCast.value.x == value.x && compareeCast.value.y == value.y && compareeCast.value.z == value.z ; - } - -} diff --git a/src/main/java/ru/windcorp/progressia/common/world/Coordinates.java b/src/main/java/ru/windcorp/progressia/common/world/Coordinates.java index b43231b..634b05e 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/Coordinates.java +++ b/src/main/java/ru/windcorp/progressia/common/world/Coordinates.java @@ -162,5 +162,72 @@ public class Coordinates { public static boolean isOnChunkBorder(int blockInChunk) { return blockInChunk == 0 || blockInChunk == BLOCKS_PER_CHUNK - 1; } + + /* + * Generalized versions + */ + + public static int convertGlobalToCell(int bits, int global) { + return global >> bits; + } + + public static Vec3i convertGlobalToCell( + int bits, + Vec3i global, + Vec3i output + ) { + if (output == null) + output = new Vec3i(); + + output.x = convertGlobalToCell(bits, global.x); + output.y = convertGlobalToCell(bits, global.y); + output.z = convertGlobalToCell(bits, global.z); + + return output; + } + + public static int convertGlobalToInCell(int bits, int global) { + int mask = (1 << bits) - 1; + return global & mask; + } + + public static Vec3i convertGlobalToInCell( + int bits, + Vec3i global, + Vec3i output + ) { + if (output == null) + output = new Vec3i(); + + output.x = convertGlobalToInCell(bits, global.x); + output.y = convertGlobalToInCell(bits, global.y); + output.z = convertGlobalToInCell(bits, global.z); + + return output; + } + + public static int getGlobal(int bits, int cell, int inCell) { + return inCell | (cell << bits); + } + + public static Vec3i getGlobal( + int bits, + Vec3i cell, + Vec3i inCell, + Vec3i output + ) { + if (output == null) + output = new Vec3i(); + + output.x = getGlobal(bits, cell.x, inCell.x); + output.y = getGlobal(bits, cell.y, inCell.y); + output.z = getGlobal(bits, cell.z, inCell.z); + + return output; + } + + public static boolean isOnCellBorder(int bits, int inCell) { + return inCell == 0 || inCell == (1 << bits) - 1; + } } diff --git a/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java b/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java index 967fe4e..e11509b 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/DefaultChunkData.java @@ -25,8 +25,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; import java.util.Objects; + import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.block.BlockData; @@ -45,11 +45,6 @@ public class DefaultChunkData implements ChunkData { public static final int BLOCKS_PER_CHUNK = Coordinates.CHUNK_SIZE; public static final int CHUNK_RADIUS = BLOCKS_PER_CHUNK / 2; - - public boolean isEmpty = false; - public boolean isOpaque = false; - - public static HashSet transparent; private final Vec3i position = new Vec3i(); private final DefaultWorldData world; @@ -204,44 +199,6 @@ public class DefaultChunkData implements ChunkData { public void setGenerationHint(Object generationHint) { this.generationHint = generationHint; } - - public void computeOpaque() - { - for (int xyz=0;xyz buffer = new ArrayList<>(); private static class ChunkUnloadRequest { @@ -116,16 +113,16 @@ public class ChunkRequestDaemon { } private void processLoadQueues() { - toRequestUnload.forEach((pos) -> executor.submit(() -> scheduleUnload(pos))); + toRequestUnload.forEach(this::scheduleUnload); toRequestUnload.clear(); - toLoad.forEach((pos) -> executor.submit(() -> getChunkManager().loadOrGenerateChunk(pos))); + toLoad.forEach(getChunkManager()::loadOrGenerateChunk); toLoad.clear(); - toGenerate.forEach((pos) -> executor.submit(() -> getChunkManager().loadOrGenerateChunk(pos))); + toGenerate.forEach(getChunkManager()::loadOrGenerateChunk); toGenerate.clear(); - executor.submit(() -> unloadScheduledChunks()); + unloadScheduledChunks(); } private void scheduleUnload(Vec3i chunkPos) { diff --git a/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetFeatureGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetFeatureGenerator.java index 205ea43..97e2424 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetFeatureGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetFeatureGenerator.java @@ -56,9 +56,6 @@ public class PlanetFeatureGenerator { generateBorderFeatures(server, chunk); } - chunk.computeEmpty(); - chunk.computeOpaque(); - chunk.setGenerationHint(true); } diff --git a/src/main/java/ru/windcorp/progressia/test/region/Region.java b/src/main/java/ru/windcorp/progressia/test/region/Region.java new file mode 100644 index 0000000..7afd862 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/region/Region.java @@ -0,0 +1,249 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test.region; + +import static ru.windcorp.progressia.test.region.TestWorldDiskIO.REGION_DIAMETER; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.InflaterInputStream; + +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.state.IOContext; +import ru.windcorp.progressia.common.world.DecodingException; +import ru.windcorp.progressia.common.world.DefaultChunkData; +import ru.windcorp.progressia.common.world.DefaultWorldData; +import ru.windcorp.progressia.common.world.generic.ChunkMap; +import ru.windcorp.progressia.common.world.generic.ChunkMaps; +import ru.windcorp.progressia.common.world.io.ChunkIO; +import ru.windcorp.progressia.server.Server; + +public class Region { + + private static final boolean RESET_CORRUPTED = true; + + // 1 MiB + private static final int MAX_CHUNK_SIZE = 1024 * 1024; + private static final int SECTOR_SIZE = MAX_CHUNK_SIZE / 256; + + private static final int HEADER_SIZE = Integer.BYTES * REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; + + private final RandomAccessFile file; + + private final ChunkMap offsets = ChunkMaps.newHashMap(); + private final ChunkMap lengths = ChunkMaps.newHashMap(); + + public Region(RandomAccessFile file) throws IOException { + this.file = file; + + try { + confirmHeaderHealth(); + } catch (IOException e) { + + TestWorldDiskIO.LOG.debug("Uh the file broke"); + if (RESET_CORRUPTED) { + byte headerBytes[] = new byte[HEADER_SIZE]; + Arrays.fill(headerBytes, (byte) 0); + + try { + file.write(headerBytes); + } catch (IOException e1) { + e.addSuppressed(e1); + throw e; + } + } + + } + } + + public RandomAccessFile getFile() { + return file; + } + + public void close() throws IOException { + this.file.close(); + } + + public int getOffset(Vec3i chunkLoc) { + return offsets.get(chunkLoc); + } + + public boolean hasOffset(Vec3i pos) { + return offsets.containsKey(pos); + } + + public void putOffset(Vec3i pos, int offset) { + offsets.put(pos, offset); + } + + public int getLength(Vec3i chunkLoc) { + return lengths.get(chunkLoc); + } + + public boolean hasLength(Vec3i pos) { + return lengths.containsKey(pos); + } + + public void putLength(Vec3i pos, int length) { + lengths.put(pos, length); + } + + private void confirmHeaderHealth() throws IOException { + + Set used = new HashSet(); + final int chunksPerRegion = REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; + + file.seek(0); + + if (file.length() < HEADER_SIZE) { + throw new IOException("File is too short to contain a header"); + } + + for (int i = 0; i < chunksPerRegion; i++) { + int offset = file.readInt(); + + int sectorLength = file.read(); + if (sectorLength == 0) { + continue; + } + + Vec3i pos = new Vec3i(); + pos.x = i / REGION_DIAMETER / REGION_DIAMETER; + pos.y = (i / REGION_DIAMETER) % REGION_DIAMETER; + pos.z = i % REGION_DIAMETER; + + offsets.put(pos, offset); + lengths.put(pos, sectorLength); + + for (int sector = 0; sector < sectorLength; sector++) { + if (!used.add(offset + sector)) { + throw new IOException("A sector is used twice"); + } + } + } + + } + + public void save(DefaultChunkData chunk, Server server) throws IOException { + Vec3i pos = TestWorldDiskIO.getInRegionCoords(chunk.getPosition()); + int definitionOffset = Integer.BYTES * (pos.z + REGION_DIAMETER * (pos.y + REGION_DIAMETER * pos.x)); + + if (!hasOffset(pos)) { + allocateChunk(definitionOffset, pos); + } + int dataOffset = getOffset(pos); + + byte[] buffer = saveToBuffer(chunk, server); + writeBuffer(buffer, definitionOffset, dataOffset, pos); + } + + private byte[] saveToBuffer(DefaultChunkData chunk, Server server) throws IOException { + ByteArrayOutputStream arrayStream = new ByteArrayOutputStream(); + try ( + DataOutputStream dataStream = new DataOutputStream( + new DeflaterOutputStream( + new BufferedOutputStream(arrayStream) + ) + ) + ) { + ChunkIO.save(chunk, dataStream, IOContext.SAVE); + TestWorldDiskIO.writeGenerationHint(chunk, dataStream, server); + } + + return arrayStream.toByteArray(); + } + + private void writeBuffer(byte[] buffer, int definitionOffset, int dataOffset, Vec3i pos) throws IOException { + file.seek(HEADER_SIZE + SECTOR_SIZE * dataOffset); + file.write(buffer); + + file.seek(definitionOffset + Integer.BYTES - 1); + + int sectors = buffer.length / SECTOR_SIZE + 1; + file.write(sectors); + + putLength(pos, sectors); + } + + private void allocateChunk(int definitionOffset, Vec3i pos) throws IOException { + int outputLen = (int) file.length(); + + int dataOffset = (int) (outputLen - HEADER_SIZE) / SECTOR_SIZE + 1; + + file.seek(definitionOffset); + file.writeInt(dataOffset); + + file.setLength(HEADER_SIZE + dataOffset * SECTOR_SIZE); + putOffset(pos, dataOffset); + } + + public DefaultChunkData load(Vec3i chunkPos, DefaultWorldData world, Server server) + throws IOException, + DecodingException { + + int dataOffset = 0; + int sectorLength = 0; + Vec3i pos = TestWorldDiskIO.getInRegionCoords(chunkPos); + + if (hasOffset(pos)) { + dataOffset = getOffset(pos); + sectorLength = getLength(pos); + } else { + return null; + } + + byte[] buffer = readBuffer(dataOffset, sectorLength); + DefaultChunkData result = loadFromBuffer(buffer, chunkPos, world, server); + return result; + } + + private DefaultChunkData loadFromBuffer(byte[] buffer, Vec3i chunkPos, DefaultWorldData world, Server server) + throws IOException, + DecodingException { + + DataInputStream dataStream = new DataInputStream( + new InflaterInputStream( + new BufferedInputStream( + new ByteArrayInputStream(buffer) + ) + ) + ); + + DefaultChunkData result = ChunkIO.load(world, chunkPos, dataStream, IOContext.SAVE); + TestWorldDiskIO.readGenerationHint(result, dataStream, server); + return result; + } + + private byte[] readBuffer(int dataOffset, int sectorLength) throws IOException { + file.seek(HEADER_SIZE + SECTOR_SIZE * dataOffset); + + byte buffer[] = new byte[SECTOR_SIZE * sectorLength]; + file.read(buffer); + return buffer; + } +} \ No newline at end of file diff --git a/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java index b391ec3..da0da50 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java @@ -18,792 +18,149 @@ package ru.windcorp.progressia.test.region; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedWriter; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; -import java.io.EOFException; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Scanner; -import java.util.Set; -import java.util.zip.DeflaterOutputStream; -import java.util.zip.InflaterInputStream; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import glm.vec._3.i.Vec3i; -import ru.windcorp.progressia.common.state.IOContext; -import ru.windcorp.progressia.common.util.HashableVec3i; +import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.world.DefaultChunkData; +import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DefaultWorldData; -import ru.windcorp.progressia.common.world.io.ChunkIO; +import ru.windcorp.progressia.common.world.generic.ChunkMap; +import ru.windcorp.progressia.common.world.generic.ChunkMaps; import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.io.WorldContainer; public class TestWorldDiskIO implements WorldContainer { - - private static final boolean resetCorrupted = true; - - public class RandomFileMapped { - public RandomAccessFile file; - public HashMap offsets; - public HashMap lengths; - - public RandomFileMapped(RandomAccessFile inFile) - { - boolean check = false; - offsets = new HashMap<>(); - lengths = new HashMap<>(); - try { - check = confirmHeaderHealth(inFile, offsets, lengths); - } catch (IOException e) { - e.printStackTrace(); - } - if (!check) - { - LOG.debug("Uh the file broke"); - if (resetCorrupted) { - byte headerBytes[] = new byte[4 * chunksPerRegion]; - for (int i = 0; i < 4 * chunksPerRegion; i++) { - headerBytes[i] = (byte) 0; - } - try { - inFile.write(headerBytes); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - - file = inFile; - } - - public int getOffset(Vec3i chunkLoc) - { - return offsets.get(new HashableVec3i(chunkLoc)); - } - public boolean hasOffset(Vec3i pos) { - return offsets.containsKey(new HashableVec3i(pos)); - } - - public void putOffset(Vec3i pos, int offset) - { - offsets.put(new HashableVec3i(pos), offset); - } - - public int getLength(Vec3i chunkLoc) - { - return lengths.get(new HashableVec3i(chunkLoc)); - } + private static final boolean ENABLE = true; - public boolean hasLength(Vec3i pos) { - return lengths.containsKey(new HashableVec3i(pos)); - } - - public void putLength(Vec3i pos, int length) - { - lengths.put(new HashableVec3i(pos), length); - } + private static final String FILE_NAME_FORMAT = "region_%d_%d_%d.progressia_region"; + + private static final int BITS_IN_CHUNK_COORDS = 4; + public static final int REGION_DIAMETER = 1 << BITS_IN_CHUNK_COORDS; + + public static Vec3i getRegionCoords(Vec3i chunkCoords) { + return Coordinates.convertGlobalToCell(BITS_IN_CHUNK_COORDS, chunkCoords, null); } - private Path SAVE_DIR = Paths.get("tmp_world"); - private static final String formatFile = "world.format"; - private static final Logger LOG = LogManager.getLogger("TestWorldDiskIO"); - - private HashMap inOutMap; - private static final boolean ENABLE = false; - - private static int maxSize = 1048576; - private static int sectorSize = maxSize / 256; - - private static final int bestFormat = 65536; - - // private Map regions = new HashMap(); - private Vec3i regionSize; - private int chunksPerRegion; - - private int currentFormat = -1; - private String extension = ".null"; - - private static int natFromInt(int loc) { - if (loc < 0) - return -2*loc - 1; - return 2*loc; + public static Vec3i getInRegionCoords(Vec3i chunkCoords) { + return Coordinates.convertGlobalToInCell(BITS_IN_CHUNK_COORDS, chunkCoords, null); } - /* - * private static int intFromNat(int loc) // Possibly unused - * { - * if ((loc & 1) == 1) - * return -loc >> 1; - * return loc >> 1; - * } - */ + static final Logger LOG = LogManager.getLogger(); - private Vec3i getRegion(Vec3i chunkLoc) { - int x = chunkLoc.x; - if (x<0) - { - x /= regionSize.x; - x--; - } - else - { - x /= regionSize.x; - } - int y = chunkLoc.y; - if (y<0) - { - y /= regionSize.y; - y--; - } - else - { - y /= regionSize.y; - } - int z = chunkLoc.z; - if (z<0) - { - z /= regionSize.z; - z--; - } - else - { - z /= regionSize.z; - } - return new Vec3i( - natFromInt(x), - natFromInt(y), - natFromInt(z) - ); - } + private final Path path; + private final ChunkMap regions = ChunkMaps.newHashMap(); - private static int mod(int a, int m) { - return ((a % m) + m) % m; - } - - private Vec3i getRegionLoc(Vec3i chunkLoc) { - return new Vec3i(mod(chunkLoc.x, regionSize.x), mod(chunkLoc.y, regionSize.y), mod(chunkLoc.z, regionSize.z)); - } - - public TestWorldDiskIO(Path worldPath) { - if (worldPath != null) { - SAVE_DIR = worldPath; - } - - // regions.put(new Vec3i(0,0,0), new Vec3i(1,1,1)); - } - - /*public static int getAvailableSector(MappedByteBuffer mbb) - { - int sectorsUsed = 0; - for (int i=offsetBytes; i<(offsetBytes+1)*chunksPerRegion; i+= (offsetBytes+1)) - { - - sectorsUsed += mbb.get(i); - } - return sectorsUsed; - }*/ - - private void setRegionSize(int format) { - inOutMap = new HashMap(); - switch (format) { - case 65536: - default: - regionSize = new Vec3i(16); - chunksPerRegion = 16 * 16 * 16; - currentFormat = 65536; - extension = ".progressia_region"; - break; - case 65537: - regionSize = new Vec3i(16); - chunksPerRegion = 16 * 16 * 16; - currentFormat = 65536; - extension = ".progressia_regionx"; - break; - } - } - - public boolean confirmHeaderHealth(RandomAccessFile input, HashMap offsets, HashMap length) throws IOException - { - Set used = new HashSet(); - input.seek(0); - if (input.length() < 4*chunksPerRegion) - { - return false; - } - for (int i=0;i<4*chunksPerRegion;i+=4) - { - int offset = 0; - for (int ii = 0; ii < 3; ii++) { - offset *= 256; - offset += input.read(); - } - int sectorLength = input.read(); - if (sectorLength==0) - { - continue; - } - int headerPos = i/4; - int x = headerPos/regionSize.y/regionSize.z; - int y = (headerPos/regionSize.z)%regionSize.y; - int z = headerPos%regionSize.z; - HashableVec3i key = new HashableVec3i(new Vec3i(x,y,z)); - offsets.put(key , offset); - length.put(key, sectorLength); - for (int ii=0;ii>= 8; - } - output.write(readOffset); - - output.setLength(fullOffset + offset * sectorSize); - } - outputMap.putOffset(pos, offset); - } - - ByteArrayOutputStream tempDataStream = new ByteArrayOutputStream(); - DataOutputStream trueOutput = new DataOutputStream( - new DeflaterOutputStream( - new BufferedOutputStream(tempDataStream) - ) - ); - ChunkIO.save(chunk, trueOutput, IOContext.SAVE); - writeGenerationHint(chunk, trueOutput, server); - - trueOutput.close(); - - byte tempData[] = tempDataStream.toByteArray(); - - output.seek( fullOffset + sectorSize * offset); - output.write(tempData); - - output.seek(shortOffset + 3); - output.write(tempData.length / sectorSize + 1); - outputMap.putLength(pos, tempData.length / sectorSize + 1); - // LOG.info("Used {} sectors",(int) - // tempData.length/sectorSize + 1); - - } - else if (currentFormat == 65537) { - LOG.debug( - "Saving {} {} {}", - chunk.getPosition().x, - chunk.getPosition().y, - chunk.getPosition().z - ); - - Files.createDirectories(SAVE_DIR); - - Vec3i saveCoords = getRegion(chunk.getPosition()); - - Path path = SAVE_DIR.resolve( - String.format( - "%d_%d_%d" + extension, - saveCoords.x, - saveCoords.y, - saveCoords.z - ) - ); - - - RandomFileMapped outputMap = inOutMap.get(new HashableVec3i(saveCoords)); - //LOG.info("saveCoords {},{},{}", saveCoords.x, saveCoords.y, saveCoords.z); - if (outputMap == null) - { - outputMap = makeNew(path, new HashableVec3i(saveCoords)); - } - RandomAccessFile output = outputMap.file; - - Vec3i pos = getRegionLoc(chunk.getPosition()); - int shortOffset = 4 * (pos.z + regionSize.z * (pos.y + regionSize.y * pos.x)); - int fullOffset = 4 * (chunksPerRegion); - int offset = 0; - - if (outputMap.hasOffset(pos)) - { - offset = outputMap.getOffset(pos); - } - else { - output.seek(shortOffset); - for (int i = 0; i < 3; i++) { - offset *= 256; - offset += output.read(); - } - int sectorLength = output.read(); - if (sectorLength == 0) { - int outputLen = (int) output.length(); - offset = (int) (outputLen - fullOffset) / sectorSize + 1; - int tempOffset = offset; - output.seek(shortOffset); - - byte readOffset[] = new byte[3]; - for (int i = 0; i < 3; i++) { - readOffset[2 - i] = (byte) (tempOffset % 256); - tempOffset >>= 8; - } - output.write(readOffset); - - output.setLength(fullOffset + offset * sectorSize); - } - outputMap.putOffset(pos, offset); - } - - ByteArrayOutputStream tempDataStream = new ByteArrayOutputStream(); - DataOutputStream trueOutput = new DataOutputStream( - new DeflaterOutputStream( - new BufferedOutputStream(tempDataStream) - ) - ); - ChunkIO.save(chunk, trueOutput, IOContext.SAVE); - writeGenerationHint(chunk, trueOutput, server); - - trueOutput.close(); - - byte tempData[] = tempDataStream.toByteArray(); - - output.seek( fullOffset + sectorSize * offset); - - chunk.computeOpaque(); - chunk.computeEmpty(); - output.write((chunk.isOpaque() ? 1 : 0) << 1 + (chunk.isEmpty() ? 1 : 0)); //Writes extra flag byte of whether or not the chunk is empty or solid - output.write(tempData); - - output.seek(shortOffset + 3); - output.write(tempData.length / sectorSize + 1); - outputMap.putLength(pos, tempData.length / sectorSize + 1); - // LOG.info("Used {} sectors",(int) - // tempData.length/sectorSize + 1); - - } - // else if (currentFormat) - } catch (IOException e) { - e.printStackTrace(); - } - } - - private RandomFileMapped makeNew(Path path, Object hashObj) { - try - { - RandomAccessFile raf = new RandomAccessFile(path.toFile(), "rw"); - //FileChannel fc = raf.getChannel(); - //MappedByteBuffer output = fc.map(FileChannel.MapMode.READ_WRITE, 0, maxSize*chunksPerRegion); - //output.limit(maxSize*chunksPerRegion); - RandomFileMapped rfm = new RandomFileMapped(raf); - inOutMap.put((HashableVec3i) hashObj, rfm); - return rfm; - } - catch (IOException e) - { - LOG.warn("bad things"); - } - return null; - } - - private void writeGenerationHint(DefaultChunkData chunk, DataOutputStream output, Server server) - throws IOException { - server.getWorld().getGenerator().writeGenerationHint(output, chunk.getGenerationHint()); + public TestWorldDiskIO(Path path) { + this.path = path; } @Override public DefaultChunkData load(Vec3i chunkPos, DefaultWorldData world, Server server) { - if (!ENABLE) + if (!ENABLE) { return null; - - if (currentFormat == -1) { - Path formatPath = SAVE_DIR.resolve(formatFile); - File format = formatPath.toFile(); - - if (format.exists()) { - String data = null; - try { - Scanner reader = new Scanner(format); - - data = reader.next(); - - reader.close(); - } catch (FileNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - byte[] formatBytes = data.getBytes(); - int formatNum = formatBytes[0] * 256 * 256 * 256 + formatBytes[1] * 256 * 256 + formatBytes[2] * 256 - + formatBytes[3]; - - setRegionSize(formatNum); - } else { - setRegionSize(bestFormat); - - LOG.debug("Making new world with format {}", bestFormat); - - BufferedWriter bw; - try { - bw = new BufferedWriter(new FileWriter(format)); - - int bfClone = bestFormat; - - for (int i = 0; i < 4; i++) { - bw.write(bfClone >> 24); - LOG.debug(bfClone >> 24); - bfClone = bfClone << 8; - } - - /* - * bw.write( - * new char[] { - * (char) bestFormat / (256 * 256 * 256), - * (char) (bestFormat % 256) / (256 * 256), - * (char) (bestFormat % (256 * 256)) / (256), - * (char) (bestFormat % (256 * 256 * 256)) } - * ); - */ - - bw.close(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - } } - if (currentFormat == 65536) { - Vec3i saveCoords = getRegion(chunkPos); + try { - Path path = SAVE_DIR.resolve( + Region region = getRegion(chunkPos, false); + if (region == null) { + return null; + } + + DefaultChunkData result = region.load(chunkPos, world, server); + return result; + + } catch (IOException | DecodingException e) { + LOG.warn( + "Failed to load chunk {} {} {}", + chunkPos.x, + chunkPos.y, + chunkPos.z + ); + e.printStackTrace(); + return null; + } + } + + @Override + public void save(DefaultChunkData chunk, DefaultWorldData world, Server server) { + if (!ENABLE) { + return; + } + + try { + LOG.debug( + "Saving {} {} {}", + chunk.getPosition().x, + chunk.getPosition().y, + chunk.getPosition().z + ); + + Region region = getRegion(chunk.getPosition(), true); + region.save(chunk, server); + } catch (IOException e) { + LOG.warn( + "Failed to save chunk {} {} {}", + chunk.getPosition().x, + chunk.getPosition().y, + chunk.getPosition().z + ); + e.printStackTrace(); + } + } + + private Region getRegion(Vec3i position, boolean createIfMissing) throws IOException { + if (regions.isEmpty()) { + Files.createDirectories(getPath()); + } + + Vec3i regionCoords = getRegionCoords(position); + + Region region = regions.get(regionCoords); + if (region == null) { + + Path path = getPath().resolve( String.format( - "%d_%d_%d" + extension, - saveCoords.x, - saveCoords.y, - saveCoords.z + FILE_NAME_FORMAT, + regionCoords.x, + regionCoords.y, + regionCoords.z ) ); - if (!Files.exists(path)) { - LOG.debug( - "Not found {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z - ); - + if (!Files.exists(path) && !createIfMissing) { return null; } - try { - DefaultChunkData result = loadRegion(path, chunkPos, world, server); - - LOG.debug( - "Loaded {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z - ); - - return result; - } catch (Exception e) { - e.printStackTrace(); - LOG.debug( - "Could not load {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z - ); - return null; - } + region = openRegion(path, regionCoords); } - else if (currentFormat == 65537) { - Vec3i saveCoords = getRegion(chunkPos); - Path path = SAVE_DIR.resolve( - String.format( - "%d_%d_%d" + extension, - saveCoords.x, - saveCoords.y, - saveCoords.z - ) - ); - - if (!Files.exists(path)) { - LOG.debug( - "Not found {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z - ); - - return null; - } - - try { - DefaultChunkData result = loadRegionX(path, chunkPos, world, server); - - LOG.debug( - "Loaded {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z - ); - - return result; - } catch (Exception e) { - e.printStackTrace(); - LOG.debug( - "Could not load {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z - ); - return null; - } - } - return null; + return region; } - private DefaultChunkData loadRegion(Path path, Vec3i chunkPos, DefaultWorldData world, Server server) - throws IOException, - DecodingException { - int offset = 0; - int sectorLength = 0; - Vec3i pos; - RandomFileMapped inputMap; - int fullOffset = 4 * (chunksPerRegion); - try - { - Vec3i streamCoords = getRegion(chunkPos); - - inputMap = inOutMap.get(new HashableVec3i(streamCoords)); - //LOG.info("streamCoords {},{},{}", streamCoords.x,streamCoords.y,streamCoords.z); - if (inputMap == null) - { - //input = new RandomAccessFile(path.toFile(), "rw"); - //input = Files.newByteChannel(path); - inputMap = makeNew(path, new HashableVec3i(streamCoords)); - } - - RandomAccessFile input = inputMap.file; - - - pos = getRegionLoc(chunkPos); - - if (inputMap.hasOffset(pos)) - { - offset = inputMap.getOffset(pos); - sectorLength = inputMap.getLength(pos); - //LOG.info("{},{}", offset, sectorLength); - } - else - { - - // LOG.info(path.toString()); - - int shortOffset = 4 * (pos.z + regionSize.z * (pos.y + regionSize.y * pos.x)); - - input.seek(shortOffset); - for (int i = 0; i < 3; i++) { - offset *= 256; - offset += input.read(); - } - sectorLength = input.read(); - if (sectorLength == 0) - { - return null; - } - inputMap.putOffset(pos, offset); - inputMap.putLength(pos, sectorLength); - } - input.seek(fullOffset + sectorSize * offset); - - // LOG.info("Read {} sectors", sectorLength); - - byte tempData[] = new byte[sectorSize * sectorLength]; - input.read(tempData); - - DataInputStream trueInput = new DataInputStream( - new InflaterInputStream(new BufferedInputStream(new ByteArrayInputStream(tempData))) - ); - DefaultChunkData chunk = ChunkIO.load(world, chunkPos, trueInput, IOContext.SAVE); - readGenerationHint(chunk, trueInput, server); - return chunk; - } - catch (EOFException e) - { - LOG.warn("Reached end of file, offset was {}, sectors was {}", offset, sectorLength); - e.printStackTrace(); - } - return null; - } - - private DefaultChunkData loadRegionX(Path path, Vec3i chunkPos, DefaultWorldData world, Server server) - throws IOException, - DecodingException { - int offset = 0; - int sectorLength = 0; - Vec3i pos; - RandomFileMapped inputMap; - int fullOffset = 4 * (chunksPerRegion); - try - { - Vec3i streamCoords = getRegion(chunkPos); - - inputMap = inOutMap.get(new HashableVec3i(streamCoords)); - //LOG.info("streamCoords {},{},{}", streamCoords.x,streamCoords.y,streamCoords.z); - if (inputMap == null) - { - //input = new RandomAccessFile(path.toFile(), "rw"); - //input = Files.newByteChannel(path); - inputMap = makeNew(path, new HashableVec3i(streamCoords)); - } - - RandomAccessFile input = inputMap.file; - - - pos = getRegionLoc(chunkPos); - - if (inputMap.hasOffset(pos)) - { - offset = inputMap.getOffset(pos); - sectorLength = inputMap.getLength(pos); - //LOG.info("{},{}", offset, sectorLength); - } - else - { - - // LOG.info(path.toString()); - - int shortOffset = 4 * (pos.z + regionSize.z * (pos.y + regionSize.y * pos.x)); - - input.seek(shortOffset); - for (int i = 0; i < 3; i++) { - offset *= 256; - offset += input.read(); - } - sectorLength = input.read(); - if (sectorLength == 0) - { - return null; - } - inputMap.putOffset(pos, offset); - inputMap.putLength(pos, sectorLength); - } - input.seek(fullOffset + sectorSize * offset); - - int xByte = input.read(); - - // LOG.info("Read {} sectors", sectorLength); - - byte tempData[] = new byte[sectorSize * sectorLength]; - input.read(tempData); - - DataInputStream trueInput = new DataInputStream( - new InflaterInputStream(new BufferedInputStream(new ByteArrayInputStream(tempData))) - ); - DefaultChunkData chunk = ChunkIO.load(world, chunkPos, trueInput, IOContext.SAVE); - readGenerationHint(chunk, trueInput, server); - - chunk.isOpaque = (xByte & 2)==2; - chunk.isEmpty = (xByte & 1)==1; - - return chunk; - } - catch (EOFException e) - { - LOG.warn("Reached end of file, offset was {}, sectors was {}", offset, sectorLength); - e.printStackTrace(); - } - return null; + private Region openRegion(Path path, Vec3i regionCoords) throws IOException { + RandomAccessFile raf = new RandomAccessFile(path.toFile(), "rw"); + Region region = new Region(raf); + regions.put(regionCoords, region); + return region; } - private static void readGenerationHint(DefaultChunkData chunk, DataInputStream input, Server server) + static void writeGenerationHint(DefaultChunkData chunk, DataOutputStream output, Server server) + throws IOException { + server.getWorld().getGenerator().writeGenerationHint(output, chunk.getGenerationHint()); + } + + static void readGenerationHint(DefaultChunkData chunk, DataInputStream input, Server server) throws IOException, DecodingException { chunk.setGenerationHint(server.getWorld().getGenerator().readGenerationHint(input)); @@ -811,13 +168,18 @@ public class TestWorldDiskIO implements WorldContainer { @Override public Path getPath() { - return SAVE_DIR; + return path; } @Override public void close() { - // TODO Auto-generated method stub - + try { + for (Region region : regions.values()) { + region.close(); + } + } catch (IOException e) { + CrashReports.report(e, "Could not close region files"); + } } } From d2ffe1fe0e7297479828d0e0554af675c5b0ffc5 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Sun, 29 Aug 2021 12:04:02 +0300 Subject: [PATCH 22/49] Fixed the bug that opfromthestart found, reloading now works --- .../progressia/test/region/Region.java | 8 ++- .../test/region/TestWorldDiskIO.java | 60 ++++++++++--------- src/main/resources/log4j2.xml | 5 +- 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/test/region/Region.java b/src/main/java/ru/windcorp/progressia/test/region/Region.java index 7afd862..251f36e 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/Region.java +++ b/src/main/java/ru/windcorp/progressia/test/region/Region.java @@ -50,8 +50,10 @@ public class Region { // 1 MiB private static final int MAX_CHUNK_SIZE = 1024 * 1024; private static final int SECTOR_SIZE = MAX_CHUNK_SIZE / 256; + + private static final int DEFINITION_SIZE = Integer.BYTES + 1; - private static final int HEADER_SIZE = Integer.BYTES * REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; + private static final int HEADER_SIZE = DEFINITION_SIZE * REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; private final RandomAccessFile file; @@ -151,7 +153,7 @@ public class Region { public void save(DefaultChunkData chunk, Server server) throws IOException { Vec3i pos = TestWorldDiskIO.getInRegionCoords(chunk.getPosition()); - int definitionOffset = Integer.BYTES * (pos.z + REGION_DIAMETER * (pos.y + REGION_DIAMETER * pos.x)); + int definitionOffset = DEFINITION_SIZE * (pos.z + REGION_DIAMETER * (pos.y + REGION_DIAMETER * pos.x)); if (!hasOffset(pos)) { allocateChunk(definitionOffset, pos); @@ -182,7 +184,7 @@ public class Region { file.seek(HEADER_SIZE + SECTOR_SIZE * dataOffset); file.write(buffer); - file.seek(definitionOffset + Integer.BYTES - 1); + file.seek(definitionOffset + Integer.BYTES); int sectors = buffer.length / SECTOR_SIZE + 1; file.write(sectors); diff --git a/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java index da0da50..f8b015f 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java @@ -55,7 +55,7 @@ public class TestWorldDiskIO implements WorldContainer { return Coordinates.convertGlobalToInCell(BITS_IN_CHUNK_COORDS, chunkCoords, null); } - static final Logger LOG = LogManager.getLogger(); + static final Logger LOG = LogManager.getLogger("TestWorldDiskIO"); private final Path path; private final ChunkMap regions = ChunkMaps.newHashMap(); @@ -74,6 +74,7 @@ public class TestWorldDiskIO implements WorldContainer { Region region = getRegion(chunkPos, false); if (region == null) { + debug("Could not load chunk {} {} {}: region did not load", chunkPos); return null; } @@ -81,12 +82,7 @@ public class TestWorldDiskIO implements WorldContainer { return result; } catch (IOException | DecodingException e) { - LOG.warn( - "Failed to load chunk {} {} {}", - chunkPos.x, - chunkPos.y, - chunkPos.z - ); + warn("Failed to load chunk {} {} {}", chunkPos); e.printStackTrace(); return null; } @@ -99,22 +95,11 @@ public class TestWorldDiskIO implements WorldContainer { } try { - LOG.debug( - "Saving {} {} {}", - chunk.getPosition().x, - chunk.getPosition().y, - chunk.getPosition().z - ); - + debug("Saving chunk {} {} {}", chunk.getPosition()); Region region = getRegion(chunk.getPosition(), true); region.save(chunk, server); } catch (IOException e) { - LOG.warn( - "Failed to save chunk {} {} {}", - chunk.getPosition().x, - chunk.getPosition().y, - chunk.getPosition().z - ); + warn("Failed to save chunk {} {} {}", chunk.getPosition()); e.printStackTrace(); } } @@ -128,21 +113,17 @@ public class TestWorldDiskIO implements WorldContainer { Region region = regions.get(regionCoords); if (region == null) { + debug("Region {} {} {} is not loaded, loading", regionCoords); - Path path = getPath().resolve( - String.format( - FILE_NAME_FORMAT, - regionCoords.x, - regionCoords.y, - regionCoords.z - ) - ); + Path path = getRegionPath(regionCoords); - if (!Files.exists(path) && !createIfMissing) { + if (!createIfMissing && !Files.exists(path)) { + debug("Region {} {} {} does not exist on disk, aborting load", regionCoords); return null; } region = openRegion(path, regionCoords); + debug("Region {} {} {} loaded", regionCoords); } return region; @@ -170,6 +151,17 @@ public class TestWorldDiskIO implements WorldContainer { public Path getPath() { return path; } + + private Path getRegionPath(Vec3i regionPos) { + return getPath().resolve( + String.format( + FILE_NAME_FORMAT, + regionPos.x, + regionPos.y, + regionPos.z + ) + ); + } @Override public void close() { @@ -181,5 +173,15 @@ public class TestWorldDiskIO implements WorldContainer { CrashReports.report(e, "Could not close region files"); } } + + private static void debug(String message, Vec3i vector) { + if (LOG.isDebugEnabled()) { + LOG.debug(message, vector.x, vector.y, vector.z); + } + } + + private static void warn(String message, Vec3i vector) { + LOG.warn(message, vector.x, vector.y, vector.z); + } } diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index b249e72..68d804f 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -26,7 +26,10 @@ --> - + + From e967a644010bb05d0e5f8ac6847fe834b5e074df Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Mon, 30 Aug 2021 10:52:56 -0400 Subject: [PATCH 23/49] More Compact region files -Sector length increased to a short, the minimum sector size is now 16 bytes --- .../ru/windcorp/progressia/test/region/Region.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/test/region/Region.java b/src/main/java/ru/windcorp/progressia/test/region/Region.java index 251f36e..e26396d 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/Region.java +++ b/src/main/java/ru/windcorp/progressia/test/region/Region.java @@ -49,9 +49,10 @@ public class Region { // 1 MiB private static final int MAX_CHUNK_SIZE = 1024 * 1024; - private static final int SECTOR_SIZE = MAX_CHUNK_SIZE / 256; + private static final int SECTORS_BYTES = Short.BYTES; + private static final int SECTOR_SIZE = MAX_CHUNK_SIZE >> (SECTORS_BYTES*8); - private static final int DEFINITION_SIZE = Integer.BYTES + 1; + private static final int DEFINITION_SIZE = Integer.BYTES + Short.BYTES; private static final int HEADER_SIZE = DEFINITION_SIZE * REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; @@ -129,7 +130,7 @@ public class Region { for (int i = 0; i < chunksPerRegion; i++) { int offset = file.readInt(); - int sectorLength = file.read(); + int sectorLength = file.readShort(); if (sectorLength == 0) { continue; } @@ -186,8 +187,8 @@ public class Region { file.seek(definitionOffset + Integer.BYTES); - int sectors = buffer.length / SECTOR_SIZE + 1; - file.write(sectors); + int sectors = (int) buffer.length / SECTOR_SIZE + 1; + file.writeShort(sectors); putLength(pos, sectors); } From 0100c8791d98b4358a7c4be7bcd0299c9be76cb9 Mon Sep 17 00:00:00 2001 From: serega404 Date: Mon, 30 Aug 2021 18:23:42 +0300 Subject: [PATCH 24/49] Added player saving and loading from disk --- .../progressia/ProgressiaLauncher.java | 4 - .../progressia/client/ClientProxy.java | 7 -- .../progressia/server/PlayerManager.java | 46 ++++----- .../progressia/server/ServerState.java | 3 +- .../server/comms/ClientManager.java | 5 +- .../server/world/io/WorldContainer.java | 18 ++-- .../server/world/io/WorldContainerFormat.java | 3 +- .../windcorp/progressia/test/LayerTitle.java | 23 +++-- .../progressia/test/region/RegionFormat.java | 3 +- .../test/region/TestWorldDiskIO.java | 99 +++++++++++++++---- 10 files changed, 141 insertions(+), 70 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java index 630f9c6..e85e2f0 100644 --- a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java +++ b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java @@ -39,10 +39,6 @@ public class ProgressiaLauncher { GUI.addTopLayer(new LayerTitle("Title")); } - public static void play() { - proxy.setupServer(); - } - private static void setupCrashReports() { // Context providers CrashReports.registerProvider(new OSContextProvider()); diff --git a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java index ffb9bd7..ac9d61f 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java @@ -30,7 +30,6 @@ import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; import ru.windcorp.progressia.client.localization.Localizer; import ru.windcorp.progressia.common.resource.ResourceManager; import ru.windcorp.progressia.common.util.crash.CrashReports; -import ru.windcorp.progressia.server.ServerState; import ru.windcorp.progressia.test.TestContent; import ru.windcorp.progressia.test.TestMusicPlayer; @@ -62,10 +61,4 @@ public class ClientProxy implements Proxy { TestMusicPlayer.start(); } - - public void setupServer() { - ServerState.startServer(); - ClientState.connectToLocalServer(); - } - } diff --git a/src/main/java/ru/windcorp/progressia/server/PlayerManager.java b/src/main/java/ru/windcorp/progressia/server/PlayerManager.java index a7184e9..5e94784 100644 --- a/src/main/java/ru/windcorp/progressia/server/PlayerManager.java +++ b/src/main/java/ru/windcorp/progressia/server/PlayerManager.java @@ -15,21 +15,21 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server; +import glm.vec._3.Vec3; +import ru.windcorp.progressia.common.world.entity.EntityData; +import ru.windcorp.progressia.common.world.entity.EntityDataRegistry; +import ru.windcorp.progressia.server.comms.ClientPlayer; +import ru.windcorp.progressia.server.events.PlayerJoinedEvent; +import ru.windcorp.progressia.server.events.PlayerLeftEvent; +import ru.windcorp.progressia.test.TestContent; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import glm.vec._3.Vec3; -import ru.windcorp.progressia.common.util.crash.CrashReports; -import ru.windcorp.progressia.common.world.entity.EntityData; -import ru.windcorp.progressia.common.world.entity.EntityDataRegistry; -import ru.windcorp.progressia.server.events.PlayerJoinedEvent; -import ru.windcorp.progressia.server.events.PlayerLeftEvent; -import ru.windcorp.progressia.test.TestContent; - public class PlayerManager { private final Server server; @@ -48,36 +48,38 @@ public class PlayerManager { this.players.add(player); getServer().postEvent(new PlayerJoinedEvent.Immutable(getServer(), player)); } - + public void removePlayer(Player player) { + server.getWorld().getContainer().savePlayer(player, server); this.players.remove(player); getServer().postEvent(new PlayerLeftEvent.Immutable(getServer(), player)); } - public EntityData conjurePlayerEntity(String login) { - // TODO Live up to the name - if (TestContent.PLAYER_LOGIN.equals(login)) { - EntityData entity = spawnPlayerEntity(login); - return entity; - } else { - throw CrashReports.report(null, "Unknown login %s, javahorse stupid", login); + public Player conjurePlayer(ClientPlayer clientPlayer, String login) { + + Player player = getServer().getWorld().getContainer().loadPlayer(login, clientPlayer, getServer()); + if (player == null) { // create new player + EntityData entity = spawnPlayerEntity(clientPlayer, login); + player = new Player(entity, getServer(), clientPlayer); } + + getServer().getWorld().getData().addEntity(player.getEntity()); + + return player; } - private EntityData spawnPlayerEntity(String login) { + private EntityData spawnPlayerEntity(ClientPlayer clientPlayer, String login) { EntityData player = EntityDataRegistry.getInstance().create("Test:Player"); player.setEntityId(TestContent.PLAYER_ENTITY_ID); player.setPosition(getServer().getWorld().getGenerator().suggestSpawnLocation()); - + player.setUpVector(new Vec3(0, 0, 1)); player.setLookingAt(new Vec3(2, 1, 0)); - getServer().getWorld().getData().addEntity(player); - return player; } - + public Object getMutex() { return players; } diff --git a/src/main/java/ru/windcorp/progressia/server/ServerState.java b/src/main/java/ru/windcorp/progressia/server/ServerState.java index c38f21b..79844cb 100644 --- a/src/main/java/ru/windcorp/progressia/server/ServerState.java +++ b/src/main/java/ru/windcorp/progressia/server/ServerState.java @@ -18,6 +18,7 @@ package ru.windcorp.progressia.server; +import java.io.IOException; import java.nio.file.Paths; import java.util.function.Function; @@ -39,7 +40,7 @@ public class ServerState { ServerState.instance = instance; } - public static void startServer() { + public static void startServer() throws IOException { Function generator = new TestGenerationConfig().getGenerator(); WorldContainer container = new RegionFormat("Test:Region").create(Paths.get("tmp_world")); diff --git a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java index fc55cbb..095c403 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java @@ -80,12 +80,11 @@ public class ClientManager { setGravityModelPacket.set(getServer().getWorld().getData().getGravityModel()); client.sendPacket(setGravityModelPacket); - EntityData entity = getServer().getPlayerManager().conjurePlayerEntity(login); - Player player = new Player(entity, getServer(), client); + Player player = getServer().getPlayerManager().conjurePlayer(client, login); getServer().getPlayerManager().addPlayer(player); PacketSetLocalPlayer packet = new PacketSetLocalPlayer(); - packet.set(entity.getEntityId()); + packet.set(player.getEntity().getEntityId()); client.sendPacket(packet); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java index 07aa7b5..42451ad 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java +++ b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainer.java @@ -17,21 +17,27 @@ */ package ru.windcorp.progressia.server.world.io; -import java.nio.file.Path; - import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.DefaultWorldData; +import ru.windcorp.progressia.server.Player; import ru.windcorp.progressia.server.Server; +import ru.windcorp.progressia.server.comms.ClientPlayer; + +import java.nio.file.Path; public interface WorldContainer { - + Path getPath(); - + DefaultChunkData load(Vec3i position, DefaultWorldData world, Server server); - + void save(DefaultChunkData chunk, DefaultWorldData world, Server server); - + + Player loadPlayer(String login, ClientPlayer clientPlayer, Server server); + + void savePlayer(Player player, Server server); + void close(); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java index 9c8e0c8..4c89621 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java +++ b/src/main/java/ru/windcorp/progressia/server/world/io/WorldContainerFormat.java @@ -17,6 +17,7 @@ */ package ru.windcorp.progressia.server.world.io; +import java.io.IOException; import java.nio.file.Path; import ru.windcorp.progressia.common.util.namespaces.Namespaced; @@ -27,6 +28,6 @@ public abstract class WorldContainerFormat extends Namespaced { super(id); } - public abstract WorldContainer create(Path directory); + public abstract WorldContainer create(Path directory) throws IOException; } diff --git a/src/main/java/ru/windcorp/progressia/test/LayerTitle.java b/src/main/java/ru/windcorp/progressia/test/LayerTitle.java index d2ba139..e497252 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerTitle.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerTitle.java @@ -1,15 +1,20 @@ package ru.windcorp.progressia.test; -import ru.windcorp.progressia.ProgressiaLauncher; +import ru.windcorp.progressia.client.ClientState; import ru.windcorp.progressia.client.graphics.Colors; import ru.windcorp.progressia.client.graphics.GUI; import ru.windcorp.progressia.client.graphics.font.Font; +import ru.windcorp.progressia.client.graphics.gui.BasicButton; import ru.windcorp.progressia.client.graphics.gui.Button; import ru.windcorp.progressia.client.graphics.gui.GUILayer; import ru.windcorp.progressia.client.graphics.gui.Label; import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical; import ru.windcorp.progressia.client.localization.MutableString; import ru.windcorp.progressia.client.localization.MutableStringLocalized; +import ru.windcorp.progressia.common.util.crash.CrashReports; +import ru.windcorp.progressia.server.ServerState; + +import java.io.IOException; public class LayerTitle extends GUILayer { @@ -22,11 +27,7 @@ public class LayerTitle extends GUILayer { Font buttonFont = titleFont; MutableString playText = new MutableStringLocalized("Layer" + name + ".Play"); - getRoot().addChild(new Button(name + ".Play", new Label(name + ".Play", buttonFont, playText)).addAction(b -> { - GUI.removeLayer(this); - - ProgressiaLauncher.play(); - })); + getRoot().addChild(new Button(name + ".Play", new Label(name + ".Play", buttonFont, playText)).addAction(this::startGame)); MutableString quitText = new MutableStringLocalized("Layer" + name + ".Quit"); getRoot().addChild(new Button(name + "Quit", new Label(name + ".Quit", buttonFont, quitText)).addAction(b -> { @@ -34,4 +35,14 @@ public class LayerTitle extends GUILayer { })); } + private void startGame(BasicButton basicButton) { + GUI.removeLayer(this); + try { + ServerState.startServer(); + ClientState.connectToLocalServer(); + } catch (IOException e) { + throw CrashReports.report(e, "Problem with loading server"); + } + } + } diff --git a/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java b/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java index 85d1bbe..ad67074 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java +++ b/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java @@ -17,6 +17,7 @@ */ package ru.windcorp.progressia.test.region; +import java.io.IOException; import java.nio.file.Path; import ru.windcorp.progressia.server.world.io.WorldContainer; @@ -29,7 +30,7 @@ public class RegionFormat extends WorldContainerFormat { } @Override - public WorldContainer create(Path directory) { + public WorldContainer create(Path directory) throws IOException { return new TestWorldDiskIO(directory); } diff --git a/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java index f8b015f..2bc3f50 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java @@ -18,31 +18,37 @@ package ru.windcorp.progressia.test.region; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.file.Files; -import java.nio.file.Path; +import glm.vec._3.i.Vec3i; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; - -import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.state.IOContext; import ru.windcorp.progressia.common.util.crash.CrashReports; -import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.DecodingException; +import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.DefaultWorldData; +import ru.windcorp.progressia.common.world.entity.EntityData; +import ru.windcorp.progressia.common.world.entity.EntityDataRegistry; import ru.windcorp.progressia.common.world.generic.ChunkMap; import ru.windcorp.progressia.common.world.generic.ChunkMaps; +import ru.windcorp.progressia.server.Player; import ru.windcorp.progressia.server.Server; +import ru.windcorp.progressia.server.comms.ClientPlayer; import ru.windcorp.progressia.server.world.io.WorldContainer; +import ru.windcorp.progressia.test.TestContent; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; public class TestWorldDiskIO implements WorldContainer { private static final boolean ENABLE = true; - private static final String FILE_NAME_FORMAT = "region_%d_%d_%d.progressia_region"; + private static final String REGION_FOLDER_NAME = "regions"; + private static final String PLAYERS_FOLDER_NAME = "players"; + private static final String REGION_NAME_FORMAT = REGION_FOLDER_NAME + "/" + "region_%d_%d_%d.progressia_region"; + private static final String PLAYER_NAME_FORMAT = PLAYERS_FOLDER_NAME + "/" + "%s.progressia_player"; private static final int BITS_IN_CHUNK_COORDS = 4; public static final int REGION_DIAMETER = 1 << BITS_IN_CHUNK_COORDS; @@ -60,8 +66,12 @@ public class TestWorldDiskIO implements WorldContainer { private final Path path; private final ChunkMap regions = ChunkMaps.newHashMap(); - public TestWorldDiskIO(Path path) { + public TestWorldDiskIO(Path path) throws IOException { this.path = path; + + Files.createDirectories(getPath()); + Files.createDirectories(getPath().resolve(REGION_FOLDER_NAME)); + Files.createDirectories(getPath().resolve(PLAYERS_FOLDER_NAME)); } @Override @@ -104,11 +114,53 @@ public class TestWorldDiskIO implements WorldContainer { } } - private Region getRegion(Vec3i position, boolean createIfMissing) throws IOException { - if (regions.isEmpty()) { - Files.createDirectories(getPath()); + @Override + public Player loadPlayer(String login, ClientPlayer clientPlayer, Server server) { + + Path path = getPlayerPath(login); + if (!Files.exists(path)) { + LOG.debug("Could not load player {} because file {} does not exist", login, path); + return null; } + EntityData player = EntityDataRegistry.getInstance().create("Test:Player"); + try ( + DataInputStream dataInputStream = new DataInputStream( + new BufferedInputStream( + Files.newInputStream( + getPlayerPath(login) + ) + ) + ) + ) { + player.read(dataInputStream, IOContext.SAVE); + player.setEntityId(TestContent.PLAYER_ENTITY_ID); + return new Player(player, server, clientPlayer); + } catch (IOException ioException) { + throw CrashReports.report(ioException, "Could not load player data: " + login); + } + } + + @Override + public void savePlayer(Player player, Server server) { + Path path = getPlayerPath(player.getLogin()); + try ( + DataOutputStream dataOutputStream = new DataOutputStream( + new BufferedOutputStream( + Files.newOutputStream(path) + ) + ) + ) { + player.getEntity(). + + write(dataOutputStream, IOContext.SAVE); + } catch (IOException ioException) { + throw CrashReports.report(ioException, "Could not save player %s data in file ", player.getLogin(), path); + } + } + + private Region getRegion(Vec3i position, boolean createIfMissing) throws IOException { + Vec3i regionCoords = getRegionCoords(position); Region region = regions.get(regionCoords); @@ -151,11 +203,11 @@ public class TestWorldDiskIO implements WorldContainer { public Path getPath() { return path; } - + private Path getRegionPath(Vec3i regionPos) { return getPath().resolve( String.format( - FILE_NAME_FORMAT, + REGION_NAME_FORMAT, regionPos.x, regionPos.y, regionPos.z @@ -163,6 +215,15 @@ public class TestWorldDiskIO implements WorldContainer { ); } + private Path getPlayerPath(String login) { + return getPath().resolve( + String.format( + PLAYER_NAME_FORMAT, + login + ) + ); + } + @Override public void close() { try { @@ -170,16 +231,16 @@ public class TestWorldDiskIO implements WorldContainer { region.close(); } } catch (IOException e) { - CrashReports.report(e, "Could not close region files"); + throw CrashReports.report(e, "Could not close region files"); } } - + private static void debug(String message, Vec3i vector) { if (LOG.isDebugEnabled()) { LOG.debug(message, vector.x, vector.y, vector.z); } } - + private static void warn(String message, Vec3i vector) { LOG.warn(message, vector.x, vector.y, vector.z); } From 711e4a2bb4d272726f2b6aa7c6c86b5ffd9cf971 Mon Sep 17 00:00:00 2001 From: serega404 Date: Mon, 30 Aug 2021 19:51:28 +0300 Subject: [PATCH 25/49] Added formatting templates guide for Intellij IDEA --- docs/building/IntelliJIDEAGuide.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/building/IntelliJIDEAGuide.md b/docs/building/IntelliJIDEAGuide.md index 7ce7c4c..e40bd69 100644 --- a/docs/building/IntelliJIDEAGuide.md +++ b/docs/building/IntelliJIDEAGuide.md @@ -41,4 +41,17 @@ Run configurations are used by Intellij IDEA to specify how a project must be ru 8. Append `\run` to the 'Working directory' field. Alternatively, specify another location outside of the project's root directory. 9. Click 'Apply' to save changes. -Step 8 is required to specify that the game must run in some directory other than the project root, which is the default in Intellij IDEA. \ No newline at end of file +Step 8 is required to specify that the game must run in some directory other than the project root, which is the default in Intellij IDEA. + +### Applying formatting templates + +Windcorp's Progressia repository is formatted with a style defined for Eclipse IDE (sic) in +`templates_and_presets/eclipse_ide`. +Please apply these templates to the project to automatically format the source in a similar fashion. + +1. In project context menu, click 'File->Properties'. (`Ctrl+Alt+S`) +2. In 'Editor' > 'Code Style' > 'Java', press gear icon, then click 'Import Scheme' > 'Eclipse code style' +3. In Scheme select 'Project' +4. Open the file `templates_and_presets/eclipse_ide/FormatterProfile.xml` in 'Select Path'. +5. Inside 'Import Scheme' widow click 'Current Scheme' check box after press OK + From a85fc27f8b45eed030324200acf666f6c9bb1d4a Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Tue, 31 Aug 2021 17:27:08 +0300 Subject: [PATCH 26/49] Added _UNFINISHED_ water, beaches and mantle - Refactored terrain generation - Added PiecewiseLinearFunction - Added some placeholder content - Added Test:Water, the solid, opaque water - Added beaches - Added Test:Mantle - Tweaked rock distribution parameters --- .../common/util/math/FloatFunction.java | 25 ++++ .../common/util/math/FloatFunction2D.java | 24 ++++ .../common/util/math/FloatFunction3D.java | 24 ++++ .../util/math/PiecewiseLinearFunction.java | 124 ++++++++++++++++++ .../generation/planet/PlanetGenerator.java | 7 +- .../planet/PlanetTerrainGenerator.java | 7 +- .../surface/SurfaceTerrainGenerator.java | 9 +- ...TerrainLayer.java => TerrainSupplier.java} | 2 +- .../windcorp/progressia/test/TestContent.java | 2 + .../test/gen/TestGenerationConfig.java | 63 ++++----- .../MultiblockVegetationFeature.java | 2 +- .../gen/{ => feature}/TestBushFeature.java | 2 +- .../gen/{ => feature}/TestFlowerFeature.java | 2 +- .../gen/{ => feature}/TestGrassFeature.java | 14 +- .../gen/{ => feature}/TestTreeFeature.java | 2 +- .../progressia/test/gen/terrain/AirLayer.java | 42 ++++++ .../test/gen/terrain/BeachLayer.java | 55 ++++++++ .../test/gen/terrain/CliffLayer.java | 64 +++++++++ .../test/gen/terrain/CrustLayer.java | 69 ++++++++++ .../test/gen/terrain/LayeredTerrain.java | 61 +++++++++ .../test/gen/terrain/MantleLayer.java | 42 ++++++ .../RockStrata.java} | 35 +++-- .../test/gen/terrain/SoilLayer.java | 59 +++++++++ .../test/gen/terrain/TerrainLayer.java | 34 +++++ .../test/gen/terrain/WaterLayer.java | 45 +++++++ .../assets/textures/blocks/Mantle.png | Bin 0 -> 1529 bytes .../assets/textures/blocks/Water.png | Bin 0 -> 1605 bytes 27 files changed, 741 insertions(+), 74 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction.java create mode 100644 src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction2D.java create mode 100644 src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction3D.java create mode 100644 src/main/java/ru/windcorp/progressia/common/util/math/PiecewiseLinearFunction.java rename src/main/java/ru/windcorp/progressia/server/world/generation/surface/{TerrainLayer.java => TerrainSupplier.java} (96%) rename src/main/java/ru/windcorp/progressia/test/gen/{ => feature}/MultiblockVegetationFeature.java (98%) rename src/main/java/ru/windcorp/progressia/test/gen/{ => feature}/TestBushFeature.java (97%) rename src/main/java/ru/windcorp/progressia/test/gen/{ => feature}/TestFlowerFeature.java (98%) rename src/main/java/ru/windcorp/progressia/test/gen/{ => feature}/TestGrassFeature.java (93%) rename src/main/java/ru/windcorp/progressia/test/gen/{ => feature}/TestTreeFeature.java (98%) create mode 100644 src/main/java/ru/windcorp/progressia/test/gen/terrain/AirLayer.java create mode 100644 src/main/java/ru/windcorp/progressia/test/gen/terrain/BeachLayer.java create mode 100644 src/main/java/ru/windcorp/progressia/test/gen/terrain/CliffLayer.java create mode 100644 src/main/java/ru/windcorp/progressia/test/gen/terrain/CrustLayer.java create mode 100644 src/main/java/ru/windcorp/progressia/test/gen/terrain/LayeredTerrain.java create mode 100644 src/main/java/ru/windcorp/progressia/test/gen/terrain/MantleLayer.java rename src/main/java/ru/windcorp/progressia/test/gen/{RockLayer.java => terrain/RockStrata.java} (64%) create mode 100644 src/main/java/ru/windcorp/progressia/test/gen/terrain/SoilLayer.java create mode 100644 src/main/java/ru/windcorp/progressia/test/gen/terrain/TerrainLayer.java create mode 100644 src/main/java/ru/windcorp/progressia/test/gen/terrain/WaterLayer.java create mode 100644 src/main/resources/assets/textures/blocks/Mantle.png create mode 100644 src/main/resources/assets/textures/blocks/Water.png diff --git a/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction.java b/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction.java new file mode 100644 index 0000000..f2438b3 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction.java @@ -0,0 +1,25 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.common.util.math; + +@FunctionalInterface +public interface FloatFunction { + + float apply(float x); + +} diff --git a/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction2D.java b/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction2D.java new file mode 100644 index 0000000..f41ea25 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction2D.java @@ -0,0 +1,24 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.common.util.math; + +public interface FloatFunction2D { + + float apply(float x, float y); + +} diff --git a/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction3D.java b/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction3D.java new file mode 100644 index 0000000..3e5e7a7 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/math/FloatFunction3D.java @@ -0,0 +1,24 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.common.util.math; + +public interface FloatFunction3D { + + float apply(float x, float y, float z); + +} diff --git a/src/main/java/ru/windcorp/progressia/common/util/math/PiecewiseLinearFunction.java b/src/main/java/ru/windcorp/progressia/common/util/math/PiecewiseLinearFunction.java new file mode 100644 index 0000000..051d7f2 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/math/PiecewiseLinearFunction.java @@ -0,0 +1,124 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.common.util.math; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import glm.vec._2.Vec2; + +public class PiecewiseLinearFunction implements FloatFunction { + + public static class Builder { + + private final List points = new ArrayList<>(); + private float slopeAtNegInf = 0; + private float slopeAtPosInf = 0; + + public Builder add(float x, float y) { + points.add(new Vec2(x, y)); + return this; + } + + public Builder setNegativeSlope(float slope) { + slopeAtNegInf = slope; + return this; + } + + public Builder setPositiveSlope(float slope) { + slopeAtPosInf = slope; + return this; + } + + public Builder setDefaultUndefined() { + slopeAtPosInf = Float.NaN; + slopeAtNegInf = Float.NaN; + return this; + } + + public PiecewiseLinearFunction build() { + float[] pointXs = new float[points.size()]; + float[] pointYs = new float[points.size()]; + + points.sort(Comparator.comparingDouble(v -> v.x)); + for (int i = 0; i < points.size(); ++i) { + pointXs[i] = points.get(i).x; + pointYs[i] = points.get(i).y; + } + + return new PiecewiseLinearFunction(pointXs, pointYs, slopeAtNegInf, slopeAtPosInf); + } + + } + + public static Builder builder() { + return new Builder(); + } + + /** + * The set of the X coordinates of all defining points, sorted in increasing order + */ + private final float[] pointXs; + + /** + * The set of the Y coordinates of all defining points, sorted to match the order of {@link #pointXs} + */ + private final float[] pointYs; + + /** + * Slope of the segment (-inf; x[0]), or NaN to exclude the segment from the function + */ + private final float slopeAtNegInf; + + /** + * Slope of the segment (x[x.length - 1]; +inf), or NaN to exclude the segment from the function + */ + private final float slopeAtPosInf; + + protected PiecewiseLinearFunction(float[] pointXs, float[] pointYs, float slopeAtNegInf, float slopeAtPosInf) { + this.pointXs = pointXs; + this.pointYs = pointYs; + this.slopeAtNegInf = slopeAtNegInf; + this.slopeAtPosInf = slopeAtPosInf; + } + + @Override + public float apply(float x) { + int index = Arrays.binarySearch(pointXs, x); + + if (index >= 0) { + // Wow, exact match, me surprised + return pointYs[index]; + } + + int bigger = -index - 1; + int smaller = bigger - 1; + + if (smaller == -1) { + return pointYs[bigger] + (x - pointXs[bigger]) * slopeAtNegInf; + } else if (bigger == pointXs.length) { + return pointYs[smaller] + (x - pointXs[smaller]) * slopeAtPosInf; + } else { + float t = (x - pointXs[smaller]) / (pointXs[bigger] - pointXs[smaller]); + return pointYs[smaller] * (1 - t) + pointYs[bigger] * t; + } + } + +} diff --git a/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetGenerator.java index b2c5c8c..dad0435 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetGenerator.java @@ -24,7 +24,6 @@ import java.util.List; import glm.vec._3.Vec3; import glm.vec._3.i.Vec3i; -import ru.windcorp.progressia.common.util.FloatRangeMap; import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.DecodingException; @@ -32,7 +31,7 @@ import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.generation.AbstractWorldGenerator; import ru.windcorp.progressia.server.world.generation.surface.SurfaceFeature; import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; -import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer; +import ru.windcorp.progressia.server.world.generation.surface.TerrainSupplier; public class PlanetGenerator extends AbstractWorldGenerator { @@ -46,7 +45,7 @@ public class PlanetGenerator extends AbstractWorldGenerator { Server server, Planet planet, SurfaceFloatField heightMap, - FloatRangeMap layers, + TerrainSupplier terrain, List features ) { super(id, server, Boolean.class, "Test:PlanetGravityModel"); @@ -56,7 +55,7 @@ public class PlanetGenerator extends AbstractWorldGenerator { PlanetGravityModel model = (PlanetGravityModel) this.getGravityModel(); model.configure(planet.getGravityModelSettings()); - this.terrainGenerator = new PlanetTerrainGenerator(this, heightMap, layers); + this.terrainGenerator = new PlanetTerrainGenerator(this, heightMap, terrain); this.featureGenerator = new PlanetFeatureGenerator(this, features); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetTerrainGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetTerrainGenerator.java index cb4507c..368a59a 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetTerrainGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetTerrainGenerator.java @@ -21,7 +21,6 @@ import java.util.Map; import glm.vec._3.Vec3; import glm.vec._3.i.Vec3i; -import ru.windcorp.progressia.common.util.FloatRangeMap; import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.Coordinates; @@ -33,7 +32,7 @@ import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.generation.surface.Surface; import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; import ru.windcorp.progressia.server.world.generation.surface.SurfaceTerrainGenerator; -import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer; +import ru.windcorp.progressia.server.world.generation.surface.TerrainSupplier; class PlanetTerrainGenerator { @@ -43,7 +42,7 @@ class PlanetTerrainGenerator { public PlanetTerrainGenerator( PlanetGenerator generator, SurfaceFloatField heightMap, - FloatRangeMap layers + TerrainSupplier terrain ) { this.parent = generator; @@ -53,7 +52,7 @@ class PlanetTerrainGenerator { face -> new SurfaceTerrainGenerator( new Surface(face, seaLevel), heightMap, - layers + terrain ) ); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceTerrainGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceTerrainGenerator.java index ea7cb9b..ead1d47 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceTerrainGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceTerrainGenerator.java @@ -19,7 +19,6 @@ package ru.windcorp.progressia.server.world.generation.surface; import glm.vec._3.Vec3; import glm.vec._3.i.Vec3i; -import ru.windcorp.progressia.common.util.FloatRangeMap; import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.block.BlockData; @@ -33,12 +32,12 @@ public class SurfaceTerrainGenerator { private final Surface surface; private final SurfaceFloatField heightMap; - private final FloatRangeMap layers; + private final TerrainSupplier terrain; - public SurfaceTerrainGenerator(Surface surface, SurfaceFloatField heightMap, FloatRangeMap layers) { + public SurfaceTerrainGenerator(Surface surface, SurfaceFloatField heightMap, TerrainSupplier terrain) { this.surface = surface; this.heightMap = heightMap; - this.layers = layers; + this.terrain = terrain; } public void generateTerrain(Server server, DefaultChunkData chunk) { @@ -74,7 +73,7 @@ public class SurfaceTerrainGenerator { location.set(north, west, altitude); SurfaceBlockContext blockContext = context.push(location); - BlockData block = layers.get(depth).get(blockContext, depth); + BlockData block = terrain.get(blockContext, depth); blockContext.pop(); diff --git a/src/main/java/ru/windcorp/progressia/server/world/generation/surface/TerrainLayer.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/TerrainSupplier.java similarity index 96% rename from src/main/java/ru/windcorp/progressia/server/world/generation/surface/TerrainLayer.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/TerrainSupplier.java index 5ec131c..a3a1376 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/generation/surface/TerrainLayer.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/TerrainSupplier.java @@ -21,7 +21,7 @@ import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; @FunctionalInterface -public interface TerrainLayer { +public interface TerrainSupplier { BlockData get(SurfaceBlockContext context, float depth); diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java index 8396e21..75e32e4 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java @@ -104,6 +104,8 @@ public class TestContent { registerSimplestBlock("Dirt"); registerSimplestBlock("Chernozem"); registerSimplestBlock("Stone"); + registerSimplestBlock("Mantle"); + registerSimplestBlock("Water"); registerSimplestBlock("Brick"); registerSimplestBlock("BrickWhite"); registerSimplestBlock("Sand"); diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java index ee0f312..2147889 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java @@ -24,21 +24,18 @@ import java.util.List; import java.util.function.Function; import ru.windcorp.progressia.common.Units; -import ru.windcorp.progressia.common.util.ArrayFloatRangeMap; -import ru.windcorp.progressia.common.util.FloatRangeMap; import ru.windcorp.progressia.common.util.noise.discrete.WorleyProceduralNoise; import ru.windcorp.progressia.common.world.Coordinates; -import ru.windcorp.progressia.common.world.block.BlockData; -import ru.windcorp.progressia.common.world.block.BlockDataRegistry; import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.generation.WorldGenerator; import ru.windcorp.progressia.server.world.generation.planet.Planet; import ru.windcorp.progressia.server.world.generation.planet.PlanetGenerator; import ru.windcorp.progressia.server.world.generation.surface.SurfaceFeature; import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; -import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer; -import ru.windcorp.progressia.test.Rocks.RockVariant; +import ru.windcorp.progressia.test.Rocks.Rock; import ru.windcorp.progressia.test.TestContent; +import ru.windcorp.progressia.test.gen.feature.*; +import ru.windcorp.progressia.test.gen.terrain.*; public class TestGenerationConfig { @@ -62,47 +59,45 @@ public class TestGenerationConfig { TestHeightMap heightMap = new TestHeightMap(planet, planet.getRadius() / 4, FIELDS); - FloatRangeMap layers = new ArrayFloatRangeMap<>(); - registerTerrainLayers(layers); + LayeredTerrain terrain = new LayeredTerrain(); + registerTerrainLayers(terrain); List features = new ArrayList<>(); registerFeatures(features); - return server -> new PlanetGenerator("Test:PlanetGenerator", server, planet, heightMap, layers, features); + return server -> new PlanetGenerator("Test:PlanetGenerator", server, planet, heightMap, terrain, features); } - private static void registerTerrainLayers(FloatRangeMap layers) { - BlockData dirt = BlockDataRegistry.getInstance().get("Test:Dirt"); - BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); - + private static void registerTerrainLayers(LayeredTerrain terrain) { SurfaceFloatField cliffs = FIELDS.get("Test:Cliff"); + SurfaceFloatField beaches = FIELDS.register( + "Test:Beach", + f -> multiply( + anti(FIELDS.get("Test:Cliff", f)) + ) + ); + RockStrata rockStrata = createStrata(); - WorleyProceduralNoise.Builder builder = WorleyProceduralNoise.builder(); - TestContent.ROCKS.getRocks().forEach(rock -> { - builder.add((c, d) -> { - if (c.getRandom().nextInt(3) == 0) { - return rock.getBlock(RockVariant.CRACKED); - } else { - return rock.getBlock(RockVariant.MONOLITH); - } - }, 1); - }); + terrain.addLayer(new AirLayer("Test:Air")); + terrain.addLayer(new MantleLayer("Test:Mantle")); + terrain.addLayer(new CrustLayer("Test:Crust", rockStrata)); + terrain.addLayer(new WaterLayer("Test:Water")); + terrain.addLayer(new SoilLayer("Test:Soil")); + terrain.addLayer(new CliffLayer("Test:Cliffs", cliffs, rockStrata)); + terrain.addLayer(new BeachLayer("Test:Beaches", beaches, rockStrata)); + } + + private static RockStrata createStrata() { + WorleyProceduralNoise.Builder builder = WorleyProceduralNoise.builder(); + TestContent.ROCKS.getRocks().forEach(rock -> builder.add(rock, 1)); + SurfaceFloatField rockDepthOffsets = FIELDS.register( "Test:RockDepthOffsets", () -> tweak(FIELDS.primitive(), 40, 5) ); - RockLayer rockLayer = new RockLayer(builder.build(SEED), rockDepthOffsets); - - layers.put(Float.NEGATIVE_INFINITY, 0, (c, d) -> air); - layers.put(0, 4, (c, d) -> { - if (cliffs.get(c.getSurface().getUp(), c.getLocation().x, c.getLocation().y) > 0) { - return rockLayer.get(c, d); - } else { - return dirt; - } - }); - layers.put(4, Float.POSITIVE_INFINITY, rockLayer); + + return new RockStrata(builder.build(SEED), rockDepthOffsets); } private static void registerFeatures(List features) { diff --git a/src/main/java/ru/windcorp/progressia/test/gen/MultiblockVegetationFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/MultiblockVegetationFeature.java similarity index 98% rename from src/main/java/ru/windcorp/progressia/test/gen/MultiblockVegetationFeature.java rename to src/main/java/ru/windcorp/progressia/test/gen/feature/MultiblockVegetationFeature.java index 5cfcc43..ecd738d 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/MultiblockVegetationFeature.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/MultiblockVegetationFeature.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen; +package ru.windcorp.progressia.test.gen.feature; import java.util.Set; import java.util.function.Consumer; diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestBushFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestBushFeature.java similarity index 97% rename from src/main/java/ru/windcorp/progressia/test/gen/TestBushFeature.java rename to src/main/java/ru/windcorp/progressia/test/gen/feature/TestBushFeature.java index ca2765c..b559582 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestBushFeature.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestBushFeature.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen; +package ru.windcorp.progressia.test.gen.feature; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.block.BlockData; diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestFlowerFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestFlowerFeature.java similarity index 98% rename from src/main/java/ru/windcorp/progressia/test/gen/TestFlowerFeature.java rename to src/main/java/ru/windcorp/progressia/test/gen/feature/TestFlowerFeature.java index 33460a1..19a97aa 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestFlowerFeature.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestFlowerFeature.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen; +package ru.windcorp.progressia.test.gen.feature; import java.util.Set; import java.util.function.Function; diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestGrassFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestGrassFeature.java similarity index 93% rename from src/main/java/ru/windcorp/progressia/test/gen/TestGrassFeature.java rename to src/main/java/ru/windcorp/progressia/test/gen/feature/TestGrassFeature.java index 2c564b7..add06ec 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestGrassFeature.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestGrassFeature.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen; +package ru.windcorp.progressia.test.gen.feature; import java.util.List; import java.util.Set; @@ -104,7 +104,17 @@ public class TestGrassFeature extends SurfaceTopLayerFeature { } private void growGrass(SurfaceBlockContext context, double grassiness) { - TileData flatGrass = flatGrasses.get((float) grassiness); + + double flatGrassiness = grassiness; + BlockData soil = context.getBlock(); + if (soil.getId().endsWith("Sand")) { + flatGrassiness = flatGrassiness / 2 - 0.2; + if (flatGrassiness < 0) { + flatGrassiness = 0; + } + } + + TileData flatGrass = flatGrasses.get((float) flatGrassiness); if (flatGrass != null) { for (RelFace face : RelFace.getFaces()) { if (face == RelFace.DOWN) diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestTreeFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestTreeFeature.java similarity index 98% rename from src/main/java/ru/windcorp/progressia/test/gen/TestTreeFeature.java rename to src/main/java/ru/windcorp/progressia/test/gen/feature/TestTreeFeature.java index d08862e..611ec07 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestTreeFeature.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestTreeFeature.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen; +package ru.windcorp.progressia.test.gen.feature; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.block.BlockData; diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/AirLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/AirLayer.java new file mode 100644 index 0000000..dbafbd4 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/AirLayer.java @@ -0,0 +1,42 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test.gen.terrain; + +import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.common.world.block.BlockDataRegistry; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; + +public class AirLayer extends TerrainLayer { + + private final BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); + + public AirLayer(String id) { + super(id); + } + + @Override + public BlockData generate(SurfaceBlockContext context, float depth, float intensity) { + return air; + } + + @Override + public float getIntensity(SurfaceBlockContext context, float depth) { + return depth <= 0 ? 1 : 0; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/BeachLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/BeachLayer.java new file mode 100644 index 0000000..24880ab --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/BeachLayer.java @@ -0,0 +1,55 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test.gen.terrain; + +import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; +import ru.windcorp.progressia.test.Rocks.RockVariant; + +public class BeachLayer extends TerrainLayer { + + private final SurfaceFloatField beachSelector; + private final RockStrata strata; + + public BeachLayer(String id, SurfaceFloatField beachSelector, RockStrata strata) { + super(id); + this.beachSelector = beachSelector; + this.strata = strata; + } + + @Override + public BlockData generate(SurfaceBlockContext context, float depth, float intensity) { + return strata.get(context, depth).getBlock(RockVariant.SAND); + } + + @Override + public float getIntensity(SurfaceBlockContext context, float depth) { + if (depth < 0 || depth > 3) { + return 0; + } + + float altitude = context.getLocation().z; + if (altitude < -5| altitude > 1) { + return 0; + } + + return 3 * beachSelector.get(context); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/CliffLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/CliffLayer.java new file mode 100644 index 0000000..59f487a --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/CliffLayer.java @@ -0,0 +1,64 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test.gen.terrain; + +import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; +import ru.windcorp.progressia.test.Rocks.RockVariant; + +public class CliffLayer extends TerrainLayer { + + private final SurfaceFloatField cliffSelector; + private final RockStrata strata; + + public CliffLayer(String id, SurfaceFloatField cliffSelector, RockStrata strata) { + super(id); + this.cliffSelector = cliffSelector; + this.strata = strata; + } + + @Override + public BlockData generate(SurfaceBlockContext context, float depth, float intensity) { + + RockVariant variant; + switch (context.getRandom().nextInt(4)) { + case 0: + variant = RockVariant.GRAVEL; + break; + case 1: + variant = RockVariant.MONOLITH; + break; + default: + variant = RockVariant.CRACKED; + break; + } + + return strata.get(context, depth).getBlock(variant); + } + + @Override + public float getIntensity(SurfaceBlockContext context, float depth) { + if (depth < 0 || depth > 7) { + return 0; + } + + return 100 * cliffSelector.get(context); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/CrustLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/CrustLayer.java new file mode 100644 index 0000000..2ce53a6 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/CrustLayer.java @@ -0,0 +1,69 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test.gen.terrain; + +import ru.windcorp.progressia.common.util.ArrayFloatRangeMap; +import ru.windcorp.progressia.common.util.FloatRangeMap; +import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; +import ru.windcorp.progressia.test.Rocks.RockVariant; + +public class CrustLayer extends TerrainLayer { + + private static final FloatRangeMap WEAR_TABLE = new ArrayFloatRangeMap<>(); + static { + WEAR_TABLE.put(Float.NEGATIVE_INFINITY, 0.25f, RockVariant.MONOLITH); + WEAR_TABLE.put(0.25f, 0.5f, RockVariant.CRACKED); + WEAR_TABLE.put(0.5f, 0.75f, RockVariant.GRAVEL); + WEAR_TABLE.put(0.75f, Float.POSITIVE_INFINITY, RockVariant.SAND); + } + + private final RockStrata strata; + + public CrustLayer(String id, RockStrata strata) { + super(id); + this.strata = strata; + } + + @Override + public BlockData generate(SurfaceBlockContext context, float depth, float intensity) { + + RockVariant variant; + if (depth < 8) { + float wear = 1 - depth / 8; + float offset = (context.getRandom().nextFloat() * 2 - 1) * 0.5f; + variant = WEAR_TABLE.get(wear + offset); + } else { + variant = RockVariant.MONOLITH; + } + + return strata.get(context, depth).getBlock(variant); + } + + @Override + public float getIntensity(SurfaceBlockContext context, float depth) { + if (depth < 0) { + return 0; + } else if (context.getLocation().z > -100) { + return 1; + } else { + return 0; + } + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/LayeredTerrain.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/LayeredTerrain.java new file mode 100644 index 0000000..ac802c2 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/LayeredTerrain.java @@ -0,0 +1,61 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test.gen.terrain; + +import java.util.ArrayList; +import java.util.List; + +import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.server.world.generation.surface.TerrainSupplier; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; + +public class LayeredTerrain implements TerrainSupplier { + + private final List layers = new ArrayList<>(); + + public void addLayer(TerrainLayer layer) { + this.layers.add(layer); + } + + @Override + public BlockData get(SurfaceBlockContext context, float depth) { + TerrainLayer layer = null; + float intensity = 0; + + for (int i = 0; i < layers.size(); ++i) { + TerrainLayer currentLayer = layers.get(i); + + float currentIntensity = currentLayer.getIntensity(context, depth); + if (currentIntensity <= 0) { + continue; + } + + if (intensity < currentIntensity) { + intensity = currentIntensity; + layer = currentLayer; + } + } + + if (layer == null) { + layer = layers.get(0); + } + + return layer.generate(context, depth, intensity); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/MantleLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/MantleLayer.java new file mode 100644 index 0000000..a72f95e --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/MantleLayer.java @@ -0,0 +1,42 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test.gen.terrain; + +import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.common.world.block.BlockDataRegistry; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; + +public class MantleLayer extends TerrainLayer { + + private final BlockData material = BlockDataRegistry.getInstance().get("Test:Mantle"); + + public MantleLayer(String id) { + super(id); + } + + @Override + public BlockData generate(SurfaceBlockContext context, float depth, float intensity) { + return material; + } + + @Override + public float getIntensity(SurfaceBlockContext context, float depth) { + return context.getLocation().z <= -100 ? 1 : 0; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/RockLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/RockStrata.java similarity index 64% rename from src/main/java/ru/windcorp/progressia/test/gen/RockLayer.java rename to src/main/java/ru/windcorp/progressia/test/gen/terrain/RockStrata.java index 5b41ef1..218b51a 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/RockLayer.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/RockStrata.java @@ -15,43 +15,38 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen; +package ru.windcorp.progressia.test.gen.terrain; import ru.windcorp.progressia.common.util.noise.discrete.DiscreteNoise; -import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; -import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer; import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; +import ru.windcorp.progressia.test.Rocks.Rock; -public class RockLayer implements TerrainLayer { - - private final DiscreteNoise strata; +public class RockStrata { + + private final DiscreteNoise distribution; private final SurfaceFloatField depthOffsets; - private final double horizontalScale = 200; - private final double verticalScale = 10; - private final double depthInfluense = 0.1; + private final double horizontalScale = 800; + private final double verticalScale = 20; + private final double depthInfluence = 0.1; - public RockLayer(DiscreteNoise strata, SurfaceFloatField depthOffsets) { - this.strata = strata; + public RockStrata(DiscreteNoise distribution, SurfaceFloatField depthOffsets) { + this.distribution = distribution; this.depthOffsets = depthOffsets; } - - @Override - public BlockData get(SurfaceBlockContext context, float depth) { - + + public Rock get(SurfaceBlockContext context, float depth) { double z = context.getLocation().z; - z -= depth * depthInfluense; + z -= depth * depthInfluence; z += depthOffsets.get(context); z /= verticalScale; - return strata - .get( + return distribution.get( context.getLocation().x / horizontalScale, context.getLocation().y / horizontalScale, z - ) - .get(context, depth); + ); } } diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/SoilLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/SoilLayer.java new file mode 100644 index 0000000..44875a0 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/SoilLayer.java @@ -0,0 +1,59 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test.gen.terrain; + +import ru.windcorp.progressia.common.Units; +import ru.windcorp.progressia.common.util.math.PiecewiseLinearFunction; +import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.common.world.block.BlockDataRegistry; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; + +public class SoilLayer extends TerrainLayer { + + private static final PiecewiseLinearFunction THICKNESS = PiecewiseLinearFunction.builder() + .add(Units.get("-5 m"), Units.get("1 m")) + .add(Units.get("0 m"), Units.get("4 m")) + .add(Units.get("5 km"), Units.get("0 m")) + .build(); + + private final BlockData soil = BlockDataRegistry.getInstance().get("Test:Dirt"); + + public SoilLayer(String id) { + super(id); + } + + @Override + public BlockData generate(SurfaceBlockContext context, float depth, float intensity) { + return soil; + } + + @Override + public float getIntensity(SurfaceBlockContext context, float depth) { + if (depth < 0) return 0; + + float altitude = context.getLocation().z; + float thickness = THICKNESS.apply(altitude); + + if (depth < thickness) { + return 2; + } else { + return 0; + } + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/TerrainLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/TerrainLayer.java new file mode 100644 index 0000000..e9eeb4b --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/TerrainLayer.java @@ -0,0 +1,34 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test.gen.terrain; + +import ru.windcorp.progressia.common.util.namespaces.Namespaced; +import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; + +public abstract class TerrainLayer extends Namespaced { + + public TerrainLayer(String id) { + super(id); + } + + public abstract BlockData generate(SurfaceBlockContext context, float depth, float intensity); + + public abstract float getIntensity(SurfaceBlockContext context, float depth); + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/terrain/WaterLayer.java b/src/main/java/ru/windcorp/progressia/test/gen/terrain/WaterLayer.java new file mode 100644 index 0000000..3813f68 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/terrain/WaterLayer.java @@ -0,0 +1,45 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test.gen.terrain; + +import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.common.world.block.BlockDataRegistry; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; + +public class WaterLayer extends TerrainLayer { + + private final BlockData water = BlockDataRegistry.getInstance().get("Test:Water"); + + public WaterLayer(String id) { + super(id); + } + + @Override + public BlockData generate(SurfaceBlockContext context, float depth, float intensity) { + return water; + } + + @Override + public float getIntensity(SurfaceBlockContext context, float depth) { + if (depth <= 0 && context.getLocation().z <= 0) { + return 2; + } + return 0; + } + +} diff --git a/src/main/resources/assets/textures/blocks/Mantle.png b/src/main/resources/assets/textures/blocks/Mantle.png new file mode 100644 index 0000000000000000000000000000000000000000..838daff45e1cfd8408fcfc730898705503361358 GIT binary patch literal 1529 zcmV}^ANIZa%Sgf_ZUhnSQ(>;CG(N)FwfnWdn=aAS*h3Y+|Lk zRv4jGo2|n`|fdr z0$}Wzzz9a^C@}G+ZIRXpnE@f&vVwBBz56h1J+710 z>g)4{4MWE`6jDN9WO0}$aVG{Q1^^)CB1>Y3p;WYK>#pS{MnVXwRNHl@s*%dDZ0Ezn zBZPPmiZh0hp(j~-xk&e?>QEGhHfEE2cRU#oB))sKod5gwqm9id3}qMq4Vd7Bc*nA8 z`qs7VG!E6NjG_=%eVfJ6x$4h#N4db*>^gd}m|6%0f%nh%x7Ulw?fsKcpCdmQq#UF? zlxGM5aa_kX7Z~&q2-f4sCq>D9?o{xe{weeSzHO8k9<>3niGI1c(g-$GM8qqbMgzdA8h9j66VLT1rIhml zS=-Z@b6QlDp^Vuy-&XamrVN`Whz$eAQ3xRbyr-UHS3SMRbKJBYGO-~^KwQsxaWOmA zjZ%6wpPIIFy_o*|``@g0M{MB(#)Fb|U0asfQHmRzU>o(Emt_?QF#%GNWUp1-_84lW zjYXDydfuo(IkvekO9eD>EiQ(ZviUeAj`OtLzO)Q9io&Yz8Kaa7d*C>qd^uOIFBean zZ4!ExW5*r|eF7o$9LMz>)>CLG7h7={o~yH#^73+}>l*#-mp_h2A%-Z6LMtNAhhjOO zfB5o{C!?N=e3S|~P$44UPm^Fd9u-wp9?Bob@k8CFqikQ4hvTWUJ#@8LW~0EhZ3BRi zgwt8}>Hce;X2rRf=h^+^v*$UY@2jq@>eh9ghEhkX+wCz4gTuLEf~RQ~5)WO@XMNWz zU}&W`ha&>WC!}qwH#aYK`;!6T$A`5vP*v3yhS)?}!S4tDpP~V_qm@J$yQV1^hu5oV zmPSAuoHLBf&Aw>+jtc$$!zZa!({o@L7~__*h7JgtWm)~Nq01!Ja+pnLCPt^S416DY z4tkX)1cUh`9f$tKd;SuVmhI$ zK`&M-O)0i;-?O&wDeI*igpeU|ER4$2@e1ktvKz&rW#Xs(Nh#n5zGY(Ha{@wuVHC&1 zd^*7v#1z{?3|h-L@`5-~Qa!8>Ro!;`ljr+8k627TZ4XIAjA4k0*9z8CrW~_lLdfBD zn%v(%qSbshio$6Uj`OTIH=EsQy)U9L6ik@N@QBSQHvm8oC4{t;QO<2_HEnBJRu*|u f4fm(>Xf*mi0i;XR%b^Q200000NkvXXu0mjfJg3>@ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/blocks/Water.png b/src/main/resources/assets/textures/blocks/Water.png new file mode 100644 index 0000000000000000000000000000000000000000..e609712fefc2816886f21bd4dc3276dccaa0100b GIT binary patch literal 1605 zcmV-L2DEX>4Tx04R}tkv&MmKpe$iQ>8^Jf_4xQ$xxlFh>8diyL*qjcYshUG1crC2UN{6 z648j5&a8^QSNJi6UW{Q@Vx}HTE~e0SeBHyt*Sj#!YJcv}(XC`n26#l`Ii?#H@dokq zrloV$2XA8`C}a>?W> zf{|kZWvGxGKlmT~?$*prPPj>d2+;Xr+aJS#Zx^UnZTtJ!w(BQ=_Zhg-n*MSPnE52V z+SEcvK+iUCaoyD9J>YT&=zr2BLvkc9O(B;9-p}ZpGC@V1PFdS8{+@~02y>eSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{ z00b>bL_t(I%O%rWlG{WS0MPsFmMnW_m;fn?eX$?bzz+E#RY{SIEld5l4?Z}1IQYk( ze`O{DAW>a6vl(W@Y;!OR64@L`lpd@KfMElW(p~B@`w0LUfy{yc0U73q*mHL?)-ro{ zw{Xi$fE2AHf{5Xs0AYi*%zgkM003ecPKb{}oNR$v~Z!8)ffCM($@vQ4QdJ8jThV)FxOe8Ax zQkTv9A#++k96HkRem+rg|zBC1lV)*Hzp}O>Tqz^N@TwmN`yS-#Ov4mM`Bf@;N zL`Xyy_1+D~a=B$@(c)%uKJU!pW-K!L8IZ@_koocNm$GiN4`j5~h=^ENw3HIn6SXS<13puCI_tEMcDR0zh;0WqXlwxz$3h}-M?>|N_p z>J=%E$A^uvZr3?xy}ru#FMks=5!oCp%A%10h(O4!ub)4u3Pgn2^pH~aAKwr$GXa1I zZBAqw=PujpI{^6Tq7{ioKeevR%u=)#OhAD1JP~oU10Vs>&9p31YepghvJjxSO|1(q zDs_2t#tIr$F6o0LM#%&Lp_^MG{ElyU5{pCn2|?U+)kn}rPk z)a61_q$DzD1QCZ>S%HX-$9;~@Dnx8&2S|}+i3p#=BdC<|+)+q$K_X_(aO>UY@UT)> z04(bTGGBiBl!OuKHr-5$%Cfyh*m?gBB0h)K>NX=oP>Cg3*Lp#~^YNWTby?ef2fz%_ zbz4`lK`(DVg}Xd|d_`trA*3K?Da;B0;iElUW{4DblTsmbwo_CAaLn`Ee;_jeWF{g? zW@7w5%#pc|4ge^UW^PkT4f5HW&#v`yK0eB}r5hkht>ORIK>!dU%8Ya;k(W=u&e46E z6z#`RMKZiScVZ@Htrg%k+>kZh>*eLR{|f*%x|I4KNF^+*b&3H^00000NkvXXu0mjf Dw$tC0 literal 0 HcmV?d00001 From c5dfe3d0b7e1679c8263d3bc0e2c3f8460dede31 Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Thu, 9 Sep 2021 16:52:55 -0400 Subject: [PATCH 27/49] Saving Modifications -Safer saving, it waits for the file to stop being used to close(still has holes) -If a chunk is too large, it is moved to the end of the file. -Calculates the efficiency of each region file in confirmHeaderHealth -Fixed import warning --- .../server/comms/ClientManager.java | 1 - .../progressia/test/region/Region.java | 39 ++++++++++++++++++- .../test/region/TestWorldDiskIO.java | 27 ++++++++++++- 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java index 095c403..e031c27 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java @@ -31,7 +31,6 @@ import ru.windcorp.progressia.common.comms.CommsChannel.State; import ru.windcorp.progressia.common.comms.packets.Packet; import ru.windcorp.progressia.common.world.PacketSetGravityModel; import ru.windcorp.progressia.common.world.PacketSetLocalPlayer; -import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.server.Player; import ru.windcorp.progressia.server.Server; diff --git a/src/main/java/ru/windcorp/progressia/test/region/Region.java b/src/main/java/ru/windcorp/progressia/test/region/Region.java index e26396d..8706ae4 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/Region.java +++ b/src/main/java/ru/windcorp/progressia/test/region/Region.java @@ -30,9 +30,12 @@ import java.io.RandomAccessFile; import java.util.Arrays; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; +import org.apache.logging.log4j.LogManager; + import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.state.IOContext; import ru.windcorp.progressia.common.world.DecodingException; @@ -52,10 +55,15 @@ public class Region { private static final int SECTORS_BYTES = Short.BYTES; private static final int SECTOR_SIZE = MAX_CHUNK_SIZE >> (SECTORS_BYTES*8); + public int loadedChunks; + private static final int DEFINITION_SIZE = Integer.BYTES + Short.BYTES; private static final int HEADER_SIZE = DEFINITION_SIZE * REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; + private AtomicBoolean isUsing = new AtomicBoolean(false); + private AtomicBoolean isClosed = new AtomicBoolean(false); + private final RandomAccessFile file; private final ChunkMap offsets = ChunkMaps.newHashMap(); @@ -90,6 +98,7 @@ public class Region { public void close() throws IOException { this.file.close(); + isClosed.lazySet(true);; } public int getOffset(Vec3i chunkLoc) { @@ -115,10 +124,21 @@ public class Region { public void putLength(Vec3i pos, int length) { lengths.put(pos, length); } + + public AtomicBoolean isClosed() + { + return isClosed; + } + + public AtomicBoolean isUsing() + { + return isUsing; + } private void confirmHeaderHealth() throws IOException { Set used = new HashSet(); + int maxUsed = 0; final int chunksPerRegion = REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; file.seek(0); @@ -142,6 +162,11 @@ public class Region { offsets.put(pos, offset); lengths.put(pos, sectorLength); + + if (offset+sectorLength > maxUsed) + { + maxUsed = offset + sectorLength; + } for (int sector = 0; sector < sectorLength; sector++) { if (!used.add(offset + sector)) { @@ -149,10 +174,11 @@ public class Region { } } } - + LogManager.getLogger("Region").debug("Efficiency of {}", (double) used.size()/maxUsed); } public void save(DefaultChunkData chunk, Server server) throws IOException { + isUsing.set(true); Vec3i pos = TestWorldDiskIO.getInRegionCoords(chunk.getPosition()); int definitionOffset = DEFINITION_SIZE * (pos.z + REGION_DIAMETER * (pos.y + REGION_DIAMETER * pos.x)); @@ -162,7 +188,16 @@ public class Region { int dataOffset = getOffset(pos); byte[] buffer = saveToBuffer(chunk, server); + if (hasLength(pos) && buffer.length > getLength(pos)*SECTOR_SIZE ) + { + byte emptyBuffer[] = new byte[getLength(pos)*SECTOR_SIZE]; + writeBuffer(emptyBuffer, definitionOffset, dataOffset, pos); + allocateChunk(definitionOffset, pos); + dataOffset = getOffset(pos); + } + writeBuffer(buffer, definitionOffset, dataOffset, pos); + isUsing.set(false); } private byte[] saveToBuffer(DefaultChunkData chunk, Server server) throws IOException { @@ -208,6 +243,7 @@ public class Region { public DefaultChunkData load(Vec3i chunkPos, DefaultWorldData world, Server server) throws IOException, DecodingException { + isUsing.set(true); int dataOffset = 0; int sectorLength = 0; @@ -222,6 +258,7 @@ public class Region { byte[] buffer = readBuffer(dataOffset, sectorLength); DefaultChunkData result = loadFromBuffer(buffer, chunkPos, world, server); + isUsing.set(false); return result; } diff --git a/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java index 2bc3f50..f8f247f 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java @@ -18,6 +18,8 @@ package ru.windcorp.progressia.test.region; +import java.util.concurrent.atomic.AtomicBoolean; + import glm.vec._3.i.Vec3i; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -227,8 +229,29 @@ public class TestWorldDiskIO implements WorldContainer { @Override public void close() { try { - for (Region region : regions.values()) { - region.close(); + ChunkMap isCloseds = ChunkMaps.newHashMap(); + ChunkMap isUsings = ChunkMaps.newHashMap(); + + for (Vec3i region : regions.keys()) + { + isCloseds.put(region, regions.get(region).isClosed()); + isUsings.put(region, regions.get(region).isUsing()); + } + + boolean stillOpen = true; + while (stillOpen) + { + stillOpen = false; + for (Vec3i region : regions.keys()) { + if (!isCloseds.get(region).get() && !isUsings.get(region).get()) + { + regions.get(region).close(); + } + else if (isUsings.get(region).get()) + { + stillOpen = false; + } + } } } catch (IOException e) { throw CrashReports.report(e, "Could not close region files"); From 46bcb85044efe4c0bd560ac9df1f5be710e740d5 Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Thu, 9 Sep 2021 19:58:44 -0400 Subject: [PATCH 28/49] Region File better???? -Moved most of the file accessing of Region to RegionFile -Disabled most of the header check except the length check(it will be back soon) -Max chunk size arbitrarily raised to 4MiB because I wanted sectors longer than 16B -Sectors now have a mandatory 1B header that identifies it -0 is a null sector, it ends every chunk -1 is a normal data sector, it has a "parity" byte that makes sure it is reading chunks in linear order(fun fact: it isnt at the moment) -2 is a jump to a different location. this isnt implemented well yet -3 will be a "bulk data" sector. Multiple chunks with identical data can point here. Probably only useful when it is easily identifiable, like multiple chunks being one entire block, like air. -Removed all chunk length references as I think they do not make sense when it can use different sectors for non-data purposes. --- .../progressia/test/region/Region.java | 143 +----------- .../progressia/test/region/RegionFile.java | 217 ++++++++++++++++++ 2 files changed, 229 insertions(+), 131 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/test/region/RegionFile.java diff --git a/src/main/java/ru/windcorp/progressia/test/region/Region.java b/src/main/java/ru/windcorp/progressia/test/region/Region.java index 8706ae4..0f38ee0 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/Region.java +++ b/src/main/java/ru/windcorp/progressia/test/region/Region.java @@ -17,8 +17,6 @@ */ package ru.windcorp.progressia.test.region; -import static ru.windcorp.progressia.test.region.TestWorldDiskIO.REGION_DIAMETER; - import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; @@ -27,15 +25,10 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.RandomAccessFile; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; -import org.apache.logging.log4j.LogManager; - import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.state.IOContext; import ru.windcorp.progressia.common.world.DecodingException; @@ -47,58 +40,40 @@ import ru.windcorp.progressia.common.world.io.ChunkIO; import ru.windcorp.progressia.server.Server; public class Region { - + private static final boolean RESET_CORRUPTED = true; - - // 1 MiB - private static final int MAX_CHUNK_SIZE = 1024 * 1024; - private static final int SECTORS_BYTES = Short.BYTES; - private static final int SECTOR_SIZE = MAX_CHUNK_SIZE >> (SECTORS_BYTES*8); public int loadedChunks; - - private static final int DEFINITION_SIZE = Integer.BYTES + Short.BYTES; - - private static final int HEADER_SIZE = DEFINITION_SIZE * REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; private AtomicBoolean isUsing = new AtomicBoolean(false); private AtomicBoolean isClosed = new AtomicBoolean(false); - private final RandomAccessFile file; + private final RegionFile file; private final ChunkMap offsets = ChunkMaps.newHashMap(); - private final ChunkMap lengths = ChunkMaps.newHashMap(); public Region(RandomAccessFile file) throws IOException { - this.file = file; + this.file = new RegionFile(file); try { - confirmHeaderHealth(); + this.file.confirmHeaderHealth(offsets); } catch (IOException e) { TestWorldDiskIO.LOG.debug("Uh the file broke"); if (RESET_CORRUPTED) { - byte headerBytes[] = new byte[HEADER_SIZE]; - Arrays.fill(headerBytes, (byte) 0); - - try { - file.write(headerBytes); - } catch (IOException e1) { - e.addSuppressed(e1); - throw e; - } + this.file.makeHeader(); } } } - public RandomAccessFile getFile() { + public RegionFile getFile() { return file; } public void close() throws IOException { this.file.close(); - isClosed.lazySet(true);; + isClosed.lazySet(true); } public int getOffset(Vec3i chunkLoc) { @@ -112,18 +87,6 @@ public class Region { public void putOffset(Vec3i pos, int offset) { offsets.put(pos, offset); } - - public int getLength(Vec3i chunkLoc) { - return lengths.get(chunkLoc); - } - - public boolean hasLength(Vec3i pos) { - return lengths.containsKey(pos); - } - - public void putLength(Vec3i pos, int length) { - lengths.put(pos, length); - } public AtomicBoolean isClosed() { @@ -135,68 +98,18 @@ public class Region { return isUsing; } - private void confirmHeaderHealth() throws IOException { - - Set used = new HashSet(); - int maxUsed = 0; - final int chunksPerRegion = REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; - - file.seek(0); - - if (file.length() < HEADER_SIZE) { - throw new IOException("File is too short to contain a header"); - } - - for (int i = 0; i < chunksPerRegion; i++) { - int offset = file.readInt(); - - int sectorLength = file.readShort(); - if (sectorLength == 0) { - continue; - } - - Vec3i pos = new Vec3i(); - pos.x = i / REGION_DIAMETER / REGION_DIAMETER; - pos.y = (i / REGION_DIAMETER) % REGION_DIAMETER; - pos.z = i % REGION_DIAMETER; - - offsets.put(pos, offset); - lengths.put(pos, sectorLength); - - if (offset+sectorLength > maxUsed) - { - maxUsed = offset + sectorLength; - } - - for (int sector = 0; sector < sectorLength; sector++) { - if (!used.add(offset + sector)) { - throw new IOException("A sector is used twice"); - } - } - } - LogManager.getLogger("Region").debug("Efficiency of {}", (double) used.size()/maxUsed); - } - public void save(DefaultChunkData chunk, Server server) throws IOException { isUsing.set(true); Vec3i pos = TestWorldDiskIO.getInRegionCoords(chunk.getPosition()); - int definitionOffset = DEFINITION_SIZE * (pos.z + REGION_DIAMETER * (pos.y + REGION_DIAMETER * pos.x)); - + if (!hasOffset(pos)) { - allocateChunk(definitionOffset, pos); + putOffset(pos, file.allocateChunk(pos)); } int dataOffset = getOffset(pos); byte[] buffer = saveToBuffer(chunk, server); - if (hasLength(pos) && buffer.length > getLength(pos)*SECTOR_SIZE ) - { - byte emptyBuffer[] = new byte[getLength(pos)*SECTOR_SIZE]; - writeBuffer(emptyBuffer, definitionOffset, dataOffset, pos); - allocateChunk(definitionOffset, pos); - dataOffset = getOffset(pos); - } - writeBuffer(buffer, definitionOffset, dataOffset, pos); + file.writeBuffer(buffer, dataOffset, pos); isUsing.set(false); } @@ -216,29 +129,7 @@ public class Region { return arrayStream.toByteArray(); } - private void writeBuffer(byte[] buffer, int definitionOffset, int dataOffset, Vec3i pos) throws IOException { - file.seek(HEADER_SIZE + SECTOR_SIZE * dataOffset); - file.write(buffer); - - file.seek(definitionOffset + Integer.BYTES); - - int sectors = (int) buffer.length / SECTOR_SIZE + 1; - file.writeShort(sectors); - - putLength(pos, sectors); - } - - private void allocateChunk(int definitionOffset, Vec3i pos) throws IOException { - int outputLen = (int) file.length(); - - int dataOffset = (int) (outputLen - HEADER_SIZE) / SECTOR_SIZE + 1; - - file.seek(definitionOffset); - file.writeInt(dataOffset); - - file.setLength(HEADER_SIZE + dataOffset * SECTOR_SIZE); - putOffset(pos, dataOffset); - } + public DefaultChunkData load(Vec3i chunkPos, DefaultWorldData world, Server server) throws IOException, @@ -246,17 +137,15 @@ public class Region { isUsing.set(true); int dataOffset = 0; - int sectorLength = 0; Vec3i pos = TestWorldDiskIO.getInRegionCoords(chunkPos); if (hasOffset(pos)) { dataOffset = getOffset(pos); - sectorLength = getLength(pos); } else { return null; } - byte[] buffer = readBuffer(dataOffset, sectorLength); + byte[] buffer = file.readBuffer(dataOffset); DefaultChunkData result = loadFromBuffer(buffer, chunkPos, world, server); isUsing.set(false); return result; @@ -278,12 +167,4 @@ public class Region { TestWorldDiskIO.readGenerationHint(result, dataStream, server); return result; } - - private byte[] readBuffer(int dataOffset, int sectorLength) throws IOException { - file.seek(HEADER_SIZE + SECTOR_SIZE * dataOffset); - - byte buffer[] = new byte[SECTOR_SIZE * sectorLength]; - file.read(buffer); - return buffer; - } } \ No newline at end of file diff --git a/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java b/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java new file mode 100644 index 0000000..f37aaa4 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java @@ -0,0 +1,217 @@ +package ru.windcorp.progressia.test.region; + +import static ru.windcorp.progressia.test.region.TestWorldDiskIO.REGION_DIAMETER; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.logging.log4j.LogManager; + +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.world.generic.ChunkMap; + +/**Backend for the .progressia_region file. + * Use similarly to a file object + * + */ +public class RegionFile { + // 4 MiB + private static final int MAX_CHUNK_SIZE = 4 * 1024 * 1024; + private static final int SECTORS_BYTES = Short.BYTES; + private static final int SECTOR_SIZE = MAX_CHUNK_SIZE >> (SECTORS_BYTES*8); + private static final int SECTOR_HEADER_LENGTH = 1; + + final byte endBytes[] = new byte[SECTOR_SIZE]; + + private Map isFilledMap = new HashMap(); // TODO ill do this at the same time I finish the new confirmheaderhealth + + public enum SectorType + { + Ending (0), // Just an empty block + Data (1), // has a byte counting up in position 1, and then + PartitionLink (2), + BulkSaved (3); // TODO implement this + + private final byte data; + + SectorType(int i) + { + this.data = (byte) i; + } + + } + + private static final int DEFINITION_SIZE = Integer.BYTES; + + private static final int HEADER_SIZE = DEFINITION_SIZE * REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; + + private final RandomAccessFile file; + + public RegionFile(RandomAccessFile inFile) + { + file = inFile; + } + + public void confirmHeaderHealth(ChunkMap offsets) throws IOException { + + Set used = new HashSet(); + int maxUsed = 0; + final int chunksPerRegion = REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; + + file.seek(0); + + if (file.length() < HEADER_SIZE) { + throw new IOException("File is too short to contain a header"); + } + +// for (int i = 0; i < chunksPerRegion; i++) { // TODO ill make the rest in a bit +// int offset = file.readInt(); +// +// if (offset == 0) { +// continue; +// } +// +// Vec3i pos = new Vec3i(); +// pos.x = i / REGION_DIAMETER / REGION_DIAMETER; +// pos.y = (i / REGION_DIAMETER) % REGION_DIAMETER; +// pos.z = i % REGION_DIAMETER; +// +// offsets.put(pos, offset); +// +// boolean shouldEnd = false; +// while (!shouldEnd) +// { +// if (offset > maxUsed) +// { +// maxUsed = offset; +// } +// +// if (!used.add(offset)) { +// throw new IOException("A sector is used twice"); +// } +// +// } +// } + LogManager.getLogger("Region").debug("Efficiency of {}", (double) used.size()/maxUsed); + } + + public void makeHeader() throws IOException + { + file.seek(0); + for (int i=0;i Date: Fri, 10 Sep 2021 13:51:37 -0400 Subject: [PATCH 29/49] Finished Partition Logic Note: it still does waste a lot of space, I will work on that next -Added back the confirmHeaderHealth logic -Checks to make sure it will not overwrite important chunks -Uses PartitionLink chunks to move to a different part of the file -Added allocateEmptySector() to allow for the file size to be increased without moving the origin point of the chunk. --- .../progressia/test/region/RegionFile.java | 136 ++++++++++++------ 1 file changed, 92 insertions(+), 44 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java b/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java index f37aaa4..385d97d 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java +++ b/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java @@ -4,9 +4,8 @@ import static ru.windcorp.progressia.test.region.TestWorldDiskIO.REGION_DIAMETER import java.io.IOException; import java.io.RandomAccessFile; -import java.util.HashMap; +import java.nio.ByteBuffer; import java.util.HashSet; -import java.util.Map; import java.util.Set; import org.apache.logging.log4j.LogManager; @@ -23,13 +22,11 @@ public class RegionFile { private static final int MAX_CHUNK_SIZE = 4 * 1024 * 1024; private static final int SECTORS_BYTES = Short.BYTES; private static final int SECTOR_SIZE = MAX_CHUNK_SIZE >> (SECTORS_BYTES*8); - private static final int SECTOR_HEADER_LENGTH = 1; + private static final int SECTOR_HEADER_SIZE = 1; final byte endBytes[] = new byte[SECTOR_SIZE]; - private Map isFilledMap = new HashMap(); // TODO ill do this at the same time I finish the new confirmheaderhealth - - public enum SectorType + public static enum SectorType { Ending (0), // Just an empty block Data (1), // has a byte counting up in position 1, and then @@ -62,40 +59,61 @@ public class RegionFile { int maxUsed = 0; final int chunksPerRegion = REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; - file.seek(0); - if (file.length() < HEADER_SIZE) { throw new IOException("File is too short to contain a header"); } -// for (int i = 0; i < chunksPerRegion; i++) { // TODO ill make the rest in a bit -// int offset = file.readInt(); -// -// if (offset == 0) { -// continue; -// } -// -// Vec3i pos = new Vec3i(); -// pos.x = i / REGION_DIAMETER / REGION_DIAMETER; -// pos.y = (i / REGION_DIAMETER) % REGION_DIAMETER; -// pos.z = i % REGION_DIAMETER; -// -// offsets.put(pos, offset); -// -// boolean shouldEnd = false; -// while (!shouldEnd) -// { -// if (offset > maxUsed) -// { -// maxUsed = offset; -// } -// -// if (!used.add(offset)) { -// throw new IOException("A sector is used twice"); -// } -// -// } -// } + for (int i = 0; i < chunksPerRegion; i++) { + file.seek(i*DEFINITION_SIZE); + int offset = file.readInt(); + + if (offset == 0) { + continue; + } + + Vec3i pos = new Vec3i(); + pos.x = i / REGION_DIAMETER / REGION_DIAMETER; + pos.y = (i / REGION_DIAMETER) % REGION_DIAMETER; + pos.z = i % REGION_DIAMETER; + + offsets.put(pos, offset); + + boolean shouldEnd = false; + byte counter = 0; + while (!shouldEnd) + { + if (offset > maxUsed) + { + maxUsed = offset; + } + + if (!used.add(offset)) { + throw new IOException("A sector is used twice"); + } + + file.seek(HEADER_SIZE + SECTOR_SIZE*offset); + byte type = file.readByte(); + + if (type == SectorType.Data.data) + { + byte fileCounter = file.readByte(); + if (fileCounter != counter) + { + throw new IOException("An unexpected block was found"); + } + counter++; + offset++; + } + else if (type == SectorType.Ending.data) { + shouldEnd = true; + } + else if (type == SectorType.PartitionLink.data) + { + offset = file.readInt(); + } + + } + } LogManager.getLogger("Region").debug("Efficiency of {}", (double) used.size()/maxUsed); } @@ -116,14 +134,30 @@ public class RegionFile { boolean isDone = false; while (!isDone) { + if (file.length() > HEADER_SIZE + SECTOR_SIZE * (dataOffset + 1)) { + file.seek(HEADER_SIZE + SECTOR_SIZE * (dataOffset + 1)); + byte header = file.readByte(); + if (header == SectorType.Data.data) { + byte fileCounter = file.readByte(); + if (fileCounter != counter+1) // This makes the actual + // partition place + { + int newOffset = allocateEmptySector(); + file.seek(HEADER_SIZE + SECTOR_SIZE * dataOffset); + file.write(2); + file.writeInt(newOffset); + dataOffset = newOffset; + } + } + } tempBuffer[0] = 1; tempBuffer[1] = counter; counter++; - for (int i=0;i<(SECTOR_SIZE-SECTOR_HEADER_LENGTH-1);i++) + for (int i=0;i<(SECTOR_SIZE-SECTOR_HEADER_SIZE-1);i++) { - if (loc*(SECTOR_SIZE-SECTOR_HEADER_LENGTH-1) + i Date: Fri, 10 Sep 2021 14:14:18 -0400 Subject: [PATCH 30/49] Bug fixes -Now offset technically starts at 1, so any chunks with offset 0 are ignored. -Reduced number of unused chunks, storage efficiency is at about 99% (if null sectors are counted as useful) --- .../ru/windcorp/progressia/test/region/RegionFile.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java b/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java index 385d97d..fa064b8 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java +++ b/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java @@ -70,6 +70,8 @@ public class RegionFile { if (offset == 0) { continue; } + + offset--; Vec3i pos = new Vec3i(); pos.x = i / REGION_DIAMETER / REGION_DIAMETER; @@ -181,10 +183,10 @@ public class RegionFile { int outputLen = (int) file.length(); - int dataOffset = (int) (outputLen - HEADER_SIZE) / SECTOR_SIZE + 1; + int dataOffset = (int) Math.ceil((double) (outputLen - HEADER_SIZE) / SECTOR_SIZE); file.seek(definitionOffset); - file.writeInt(dataOffset); + file.writeInt(dataOffset+1); file.setLength(HEADER_SIZE + dataOffset * SECTOR_SIZE); return dataOffset; @@ -194,7 +196,7 @@ public class RegionFile { { int outputLen = (int) file.length(); - int dataOffset = (int) (outputLen - HEADER_SIZE) / SECTOR_SIZE + 1; + int dataOffset = (int) Math.ceil((double) (outputLen - HEADER_SIZE) / SECTOR_SIZE); file.setLength(HEADER_SIZE + dataOffset * SECTOR_SIZE); From e2308b825db8c99b888a7e9a614eaf5ae241e4e7 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Fri, 10 Sep 2021 23:31:14 +0300 Subject: [PATCH 31/49] Removed warnings and formatted code --- .../progressia/ProgressiaLauncher.java | 13 +- .../progressia/test/region/Region.java | 22 +-- .../progressia/test/region/RegionFile.java | 184 ++++++++---------- .../test/region/TestWorldDiskIO.java | 17 +- 4 files changed, 103 insertions(+), 133 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java index e85e2f0..099d378 100644 --- a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java +++ b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java @@ -18,7 +18,6 @@ package ru.windcorp.progressia; -import ru.windcorp.progressia.client.ClientProxy; import ru.windcorp.progressia.client.graphics.GUI; import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer; @@ -28,16 +27,20 @@ import ru.windcorp.progressia.test.LayerTitle; public class ProgressiaLauncher { public static String[] arguments; - private static ClientProxy proxy; + private static Proxy proxy; - public static void launch(String[] args, ClientProxy inProxy) { + public static void launch(String[] args, Proxy proxy) { arguments = args.clone(); setupCrashReports(); - inProxy.initialize(); - proxy = inProxy; + proxy.initialize(); + ProgressiaLauncher.proxy = proxy; GUI.addTopLayer(new LayerTitle("Title")); } + + public static Proxy getProxy() { + return proxy; + } private static void setupCrashReports() { // Context providers diff --git a/src/main/java/ru/windcorp/progressia/test/region/Region.java b/src/main/java/ru/windcorp/progressia/test/region/Region.java index 0f38ee0..3ff1804 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/Region.java +++ b/src/main/java/ru/windcorp/progressia/test/region/Region.java @@ -40,14 +40,14 @@ import ru.windcorp.progressia.common.world.io.ChunkIO; import ru.windcorp.progressia.server.Server; public class Region { - + private static final boolean RESET_CORRUPTED = true; - + public int loadedChunks; private AtomicBoolean isUsing = new AtomicBoolean(false); private AtomicBoolean isClosed = new AtomicBoolean(false); - + private final RegionFile file; private final ChunkMap offsets = ChunkMaps.newHashMap(); @@ -87,28 +87,26 @@ public class Region { public void putOffset(Vec3i pos, int offset) { offsets.put(pos, offset); } - - public AtomicBoolean isClosed() - { + + public AtomicBoolean isClosed() { return isClosed; } - - public AtomicBoolean isUsing() - { + + public AtomicBoolean isUsing() { return isUsing; } public void save(DefaultChunkData chunk, Server server) throws IOException { isUsing.set(true); Vec3i pos = TestWorldDiskIO.getInRegionCoords(chunk.getPosition()); - + if (!hasOffset(pos)) { putOffset(pos, file.allocateChunk(pos)); } int dataOffset = getOffset(pos); byte[] buffer = saveToBuffer(chunk, server); - + file.writeBuffer(buffer, dataOffset, pos); isUsing.set(false); } @@ -129,8 +127,6 @@ public class Region { return arrayStream.toByteArray(); } - - public DefaultChunkData load(Vec3i chunkPos, DefaultWorldData world, Server server) throws IOException, DecodingException { diff --git a/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java b/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java index fa064b8..ee30f1a 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java +++ b/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java @@ -13,46 +13,43 @@ import org.apache.logging.log4j.LogManager; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.generic.ChunkMap; -/**Backend for the .progressia_region file. +/** + * Backend for the .progressia_region file. * Use similarly to a file object - * */ public class RegionFile { // 4 MiB private static final int MAX_CHUNK_SIZE = 4 * 1024 * 1024; private static final int SECTORS_BYTES = Short.BYTES; - private static final int SECTOR_SIZE = MAX_CHUNK_SIZE >> (SECTORS_BYTES*8); + private static final int SECTOR_SIZE = MAX_CHUNK_SIZE >> (SECTORS_BYTES * 8); private static final int SECTOR_HEADER_SIZE = 1; - + final byte endBytes[] = new byte[SECTOR_SIZE]; - - public static enum SectorType - { - Ending (0), // Just an empty block - Data (1), // has a byte counting up in position 1, and then - PartitionLink (2), - BulkSaved (3); // TODO implement this - + + public static enum SectorType { + Ending(0), // Just an empty block + Data(1), // has a byte counting up in position 1, and then + PartitionLink(2), + BulkSaved(3); // TODO implement this + private final byte data; - - SectorType(int i) - { + + SectorType(int i) { this.data = (byte) i; } - + } - + private static final int DEFINITION_SIZE = Integer.BYTES; private static final int HEADER_SIZE = DEFINITION_SIZE * REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; - + private final RandomAccessFile file; - - public RegionFile(RandomAccessFile inFile) - { + + public RegionFile(RandomAccessFile inFile) { file = inFile; } - + public void confirmHeaderHealth(ChunkMap offsets) throws IOException { Set used = new HashSet(); @@ -63,14 +60,14 @@ public class RegionFile { throw new IOException("File is too short to contain a header"); } - for (int i = 0; i < chunksPerRegion; i++) { - file.seek(i*DEFINITION_SIZE); + for (int i = 0; i < chunksPerRegion; i++) { + file.seek(i * DEFINITION_SIZE); int offset = file.readInt(); if (offset == 0) { continue; } - + offset--; Vec3i pos = new Vec3i(); @@ -79,70 +76,60 @@ public class RegionFile { pos.z = i % REGION_DIAMETER; offsets.put(pos, offset); - + boolean shouldEnd = false; byte counter = 0; - while (!shouldEnd) - { - if (offset > maxUsed) - { + while (!shouldEnd) { + if (offset > maxUsed) { maxUsed = offset; } if (!used.add(offset)) { throw new IOException("A sector is used twice"); } - - file.seek(HEADER_SIZE + SECTOR_SIZE*offset); + + file.seek(HEADER_SIZE + SECTOR_SIZE * offset); byte type = file.readByte(); - - if (type == SectorType.Data.data) - { + + if (type == SectorType.Data.data) { byte fileCounter = file.readByte(); - if (fileCounter != counter) - { + if (fileCounter != counter) { throw new IOException("An unexpected block was found"); } counter++; offset++; - } - else if (type == SectorType.Ending.data) { + } else if (type == SectorType.Ending.data) { shouldEnd = true; - } - else if (type == SectorType.PartitionLink.data) - { + } else if (type == SectorType.PartitionLink.data) { offset = file.readInt(); } - + } } - LogManager.getLogger("Region").debug("Efficiency of {}", (double) used.size()/maxUsed); + LogManager.getLogger("Region").debug("Efficiency of {}", (double) used.size() / maxUsed); } - - public void makeHeader() throws IOException - { + + public void makeHeader() throws IOException { file.seek(0); - for (int i=0;i HEADER_SIZE + SECTOR_SIZE * (dataOffset + 1)) { file.seek(HEADER_SIZE + SECTOR_SIZE * (dataOffset + 1)); byte header = file.readByte(); if (header == SectorType.Data.data) { byte fileCounter = file.readByte(); - if (fileCounter != counter+1) // This makes the actual - // partition place + if (fileCounter != counter + 1) // This makes the actual + // partition place { int newOffset = allocateEmptySector(); file.seek(HEADER_SIZE + SECTOR_SIZE * dataOffset); @@ -155,51 +142,47 @@ public class RegionFile { tempBuffer[0] = 1; tempBuffer[1] = counter; counter++; - for (int i=0;i<(SECTOR_SIZE-SECTOR_HEADER_SIZE-1);i++) - { - if (loc*(SECTOR_SIZE-SECTOR_HEADER_SIZE-1) + i isCloseds = ChunkMaps.newHashMap(); ChunkMap isUsings = ChunkMaps.newHashMap(); - - for (Vec3i region : regions.keys()) - { + + for (Vec3i region : regions.keys()) { isCloseds.put(region, regions.get(region).isClosed()); isUsings.put(region, regions.get(region).isUsing()); } - + boolean stillOpen = true; - while (stillOpen) - { + while (stillOpen) { stillOpen = false; for (Vec3i region : regions.keys()) { - if (!isCloseds.get(region).get() && !isUsings.get(region).get()) - { + if (!isCloseds.get(region).get() && !isUsings.get(region).get()) { regions.get(region).close(); - } - else if (isUsings.get(region).get()) - { + } else if (isUsings.get(region).get()) { stillOpen = false; } } From 6b33f231b47331067bea07d8b264a480cbe22476 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Fri, 10 Sep 2021 23:59:03 +0300 Subject: [PATCH 32/49] Moved region implementation to .server.world.io.region --- .../ru/windcorp/progressia/server/ServerState.java | 2 +- .../{test => server/world/io}/region/Region.java | 12 ++++++------ .../{test => server/world/io}/region/RegionFile.java | 4 ++-- .../world/io}/region/RegionFormat.java | 4 ++-- .../world/io/region/RegionWorldContainer.java} | 6 +++--- .../ru/windcorp/progressia/test/TestContent.java | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) rename src/main/java/ru/windcorp/progressia/{test => server/world/io}/region/Region.java (91%) rename src/main/java/ru/windcorp/progressia/{test => server/world/io}/region/RegionFile.java (97%) rename src/main/java/ru/windcorp/progressia/{test => server/world/io}/region/RegionFormat.java (91%) rename src/main/java/ru/windcorp/progressia/{test/region/TestWorldDiskIO.java => server/world/io/region/RegionWorldContainer.java} (97%) diff --git a/src/main/java/ru/windcorp/progressia/server/ServerState.java b/src/main/java/ru/windcorp/progressia/server/ServerState.java index 79844cb..41b2c6b 100644 --- a/src/main/java/ru/windcorp/progressia/server/ServerState.java +++ b/src/main/java/ru/windcorp/progressia/server/ServerState.java @@ -25,8 +25,8 @@ import java.util.function.Function; import ru.windcorp.progressia.common.world.DefaultWorldData; import ru.windcorp.progressia.server.world.generation.WorldGenerator; import ru.windcorp.progressia.server.world.io.WorldContainer; +import ru.windcorp.progressia.server.world.io.region.RegionFormat; import ru.windcorp.progressia.test.gen.TestGenerationConfig; -import ru.windcorp.progressia.test.region.RegionFormat; public class ServerState { diff --git a/src/main/java/ru/windcorp/progressia/test/region/Region.java b/src/main/java/ru/windcorp/progressia/server/world/io/region/Region.java similarity index 91% rename from src/main/java/ru/windcorp/progressia/test/region/Region.java rename to src/main/java/ru/windcorp/progressia/server/world/io/region/Region.java index 3ff1804..990ae8a 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/Region.java +++ b/src/main/java/ru/windcorp/progressia/server/world/io/region/Region.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.region; +package ru.windcorp.progressia.server.world.io.region; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -59,7 +59,7 @@ public class Region { this.file.confirmHeaderHealth(offsets); } catch (IOException e) { - TestWorldDiskIO.LOG.debug("Uh the file broke"); + RegionWorldContainer.LOG.debug("Uh the file broke"); if (RESET_CORRUPTED) { this.file.makeHeader(); } @@ -98,7 +98,7 @@ public class Region { public void save(DefaultChunkData chunk, Server server) throws IOException { isUsing.set(true); - Vec3i pos = TestWorldDiskIO.getInRegionCoords(chunk.getPosition()); + Vec3i pos = RegionWorldContainer.getInRegionCoords(chunk.getPosition()); if (!hasOffset(pos)) { putOffset(pos, file.allocateChunk(pos)); @@ -121,7 +121,7 @@ public class Region { ) ) { ChunkIO.save(chunk, dataStream, IOContext.SAVE); - TestWorldDiskIO.writeGenerationHint(chunk, dataStream, server); + RegionWorldContainer.writeGenerationHint(chunk, dataStream, server); } return arrayStream.toByteArray(); @@ -133,7 +133,7 @@ public class Region { isUsing.set(true); int dataOffset = 0; - Vec3i pos = TestWorldDiskIO.getInRegionCoords(chunkPos); + Vec3i pos = RegionWorldContainer.getInRegionCoords(chunkPos); if (hasOffset(pos)) { dataOffset = getOffset(pos); @@ -160,7 +160,7 @@ public class Region { ); DefaultChunkData result = ChunkIO.load(world, chunkPos, dataStream, IOContext.SAVE); - TestWorldDiskIO.readGenerationHint(result, dataStream, server); + RegionWorldContainer.readGenerationHint(result, dataStream, server); return result; } } \ No newline at end of file diff --git a/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java b/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionFile.java similarity index 97% rename from src/main/java/ru/windcorp/progressia/test/region/RegionFile.java rename to src/main/java/ru/windcorp/progressia/server/world/io/region/RegionFile.java index ee30f1a..2060b9c 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/RegionFile.java +++ b/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionFile.java @@ -1,6 +1,6 @@ -package ru.windcorp.progressia.test.region; +package ru.windcorp.progressia.server.world.io.region; -import static ru.windcorp.progressia.test.region.TestWorldDiskIO.REGION_DIAMETER; +import static ru.windcorp.progressia.server.world.io.region.RegionWorldContainer.REGION_DIAMETER; import java.io.IOException; import java.io.RandomAccessFile; diff --git a/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java b/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionFormat.java similarity index 91% rename from src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java rename to src/main/java/ru/windcorp/progressia/server/world/io/region/RegionFormat.java index ad67074..89c5361 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/RegionFormat.java +++ b/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionFormat.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.region; +package ru.windcorp.progressia.server.world.io.region; import java.io.IOException; import java.nio.file.Path; @@ -31,7 +31,7 @@ public class RegionFormat extends WorldContainerFormat { @Override public WorldContainer create(Path directory) throws IOException { - return new TestWorldDiskIO(directory); + return new RegionWorldContainer(directory); } } diff --git a/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java b/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionWorldContainer.java similarity index 97% rename from src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java rename to src/main/java/ru/windcorp/progressia/server/world/io/region/RegionWorldContainer.java index 0d2879a..378e01e 100644 --- a/src/main/java/ru/windcorp/progressia/test/region/TestWorldDiskIO.java +++ b/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionWorldContainer.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package ru.windcorp.progressia.test.region; +package ru.windcorp.progressia.server.world.io.region; import java.util.concurrent.atomic.AtomicBoolean; @@ -43,7 +43,7 @@ import java.io.*; import java.nio.file.Files; import java.nio.file.Path; -public class TestWorldDiskIO implements WorldContainer { +public class RegionWorldContainer implements WorldContainer { private static final boolean ENABLE = true; @@ -68,7 +68,7 @@ public class TestWorldDiskIO implements WorldContainer { private final Path path; private final ChunkMap regions = ChunkMaps.newHashMap(); - public TestWorldDiskIO(Path path) throws IOException { + public RegionWorldContainer(Path path) throws IOException { this.path = path; Files.createDirectories(getPath()); diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java index d927613..4ba3ea6 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java @@ -380,7 +380,7 @@ public class TestContent { ru.windcorp.progressia.client.Client client = ClientState.getInstance(); if (client == null || !client.isReady()) return null; - + return client.getLocalPlayer().getSelection(); } From a633c8324e3dcd38d4b726e7467f62878bef9e70 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Sat, 11 Sep 2021 00:47:28 +0300 Subject: [PATCH 33/49] Added Reset World button and fixed some translations --- .../windcorp/progressia/test/LayerTitle.java | 57 +++++++++++++++++-- .../resources/assets/languages/en-US.lang | 1 + .../resources/assets/languages/ru-RU.lang | 15 ++--- 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/test/LayerTitle.java b/src/main/java/ru/windcorp/progressia/test/LayerTitle.java index e497252..365e437 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerTitle.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerTitle.java @@ -7,7 +7,9 @@ import ru.windcorp.progressia.client.graphics.font.Font; import ru.windcorp.progressia.client.graphics.gui.BasicButton; import ru.windcorp.progressia.client.graphics.gui.Button; import ru.windcorp.progressia.client.graphics.gui.GUILayer; +import ru.windcorp.progressia.client.graphics.gui.Group; import ru.windcorp.progressia.client.graphics.gui.Label; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical; import ru.windcorp.progressia.client.localization.MutableString; import ru.windcorp.progressia.client.localization.MutableStringLocalized; @@ -15,24 +17,45 @@ import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.server.ServerState; import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; public class LayerTitle extends GUILayer { + + private final BasicButton resetButton; public LayerTitle(String name) { - super(name, new LayoutVertical(20, 10)); + super(name, new LayoutAlign(0.5f, 0.7f, 15)); + Group content = new Group("Layer" + name + ".Group", new LayoutVertical(15)); MutableString title = new MutableStringLocalized("Layer" + name + ".Title"); Font titleFont = new Font().deriveBold().withColor(Colors.BLACK).withAlign(0.5f); - getRoot().addChild(new Label(name + ".Title", titleFont, title)); + content.addChild(new Label(name + ".Title", titleFont, title)); - Font buttonFont = titleFont; + Font buttonFont = titleFont.deriveNotBold(); MutableString playText = new MutableStringLocalized("Layer" + name + ".Play"); - getRoot().addChild(new Button(name + ".Play", new Label(name + ".Play", buttonFont, playText)).addAction(this::startGame)); + content.addChild(new Button(name + ".Play", new Label(name + ".Play", buttonFont, playText)).addAction(this::startGame)); + + MutableString resetText = new MutableStringLocalized("Layer" + name + ".Reset"); + this.resetButton = new Button(name + ".Reset", new Label(name + ".Reset", buttonFont, resetText)).addAction(this::resetWorld); + content.addChild(resetButton); + + updateResetButton(); MutableString quitText = new MutableStringLocalized("Layer" + name + ".Quit"); - getRoot().addChild(new Button(name + "Quit", new Label(name + ".Quit", buttonFont, quitText)).addAction(b -> { + content.addChild(new Button(name + "Quit", new Label(name + ".Quit", buttonFont, quitText)).addAction(b -> { System.exit(0); })); + + getRoot().addChild(content); + } + + private void updateResetButton() { + resetButton.setEnabled(Files.exists(Paths.get("tmp_world"))); } private void startGame(BasicButton basicButton) { @@ -44,5 +67,29 @@ public class LayerTitle extends GUILayer { throw CrashReports.report(e, "Problem with loading server"); } } + + private void resetWorld(BasicButton basicButton) { + Path rootPath = Paths.get("tmp_world"); + + try { + Files.walkFileTree(rootPath, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + throw CrashReports.report(e, "Could not reset world"); + } + + updateResetButton(); + } } diff --git a/src/main/resources/assets/languages/en-US.lang b/src/main/resources/assets/languages/en-US.lang index e6ab183..b3de478 100644 --- a/src/main/resources/assets/languages/en-US.lang +++ b/src/main/resources/assets/languages/en-US.lang @@ -26,6 +26,7 @@ LayerButtonTest.Return = Back To Menu LayerTitle.Title = Progressia LayerTitle.Play = Play World +LayerTitle.Reset = Reset World LayerTitle.Options = Options LayerTitle.Quit = Quit diff --git a/src/main/resources/assets/languages/ru-RU.lang b/src/main/resources/assets/languages/ru-RU.lang index 09c9c33..69e07f2 100644 --- a/src/main/resources/assets/languages/ru-RU.lang +++ b/src/main/resources/assets/languages/ru-RU.lang @@ -21,13 +21,14 @@ LayerTestGUI.PlacementModeHint = (Блок %s плитки: Ctrl + прокру LayerTestGUI.IsFullscreen = Полный экран: %5s (F11) LayerTestGUI.IsVSync = Верт. синхр.: %5s (F12) -LayerButtonTest.Title = Тест Кнопок -LayerButtonTest.Return = Back To Menu [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ +LayerButtonTest.Title = Тест кнопок +LayerButtonTest.Return = Главное меню LayerTitle.Title = Прогрессия -LayerTitle.Play = ??????? -LayerTitle.Options = ???????? -LayerTitle.Quit = ???????? +LayerTitle.Play = Играть +LayerTitle.Reset = Сбросить мир +LayerTitle.Options = Настройки +LayerTitle.Quit = Выход -LayerText.Load = Loading... (Change) -LayerText.Save = Saving...(Cahnsf) \ No newline at end of file +LayerText.Load = Загрузка... +LayerText.Save = Сохранение... \ No newline at end of file From 0c41350ae7230617e3c2156c5deeae0ff9ce9329 Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Fri, 10 Sep 2021 22:19:18 -0400 Subject: [PATCH 34/49] Added file identification header -All files now start with a 16 byte header consisting of "PROG" followed by the integer position of the region in region coordinates. -regionCoords is passed through some functions to allow for this to be confirmed. --- .../server/world/io/region/Region.java | 6 ++-- .../server/world/io/region/RegionFile.java | 35 ++++++++++++++++--- .../world/io/region/RegionWorldContainer.java | 2 +- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/server/world/io/region/Region.java b/src/main/java/ru/windcorp/progressia/server/world/io/region/Region.java index 990ae8a..b25535c 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/io/region/Region.java +++ b/src/main/java/ru/windcorp/progressia/server/world/io/region/Region.java @@ -52,16 +52,16 @@ public class Region { private final ChunkMap offsets = ChunkMaps.newHashMap(); - public Region(RandomAccessFile file) throws IOException { + public Region(RandomAccessFile file, Vec3i regionCoords) throws IOException { this.file = new RegionFile(file); try { - this.file.confirmHeaderHealth(offsets); + this.file.confirmHeaderHealth(offsets, regionCoords); } catch (IOException e) { RegionWorldContainer.LOG.debug("Uh the file broke"); if (RESET_CORRUPTED) { - this.file.makeHeader(); + this.file.makeHeader(regionCoords); } } diff --git a/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionFile.java b/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionFile.java index 2060b9c..520d24e 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionFile.java +++ b/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionFile.java @@ -23,6 +23,8 @@ public class RegionFile { private static final int SECTORS_BYTES = Short.BYTES; private static final int SECTOR_SIZE = MAX_CHUNK_SIZE >> (SECTORS_BYTES * 8); private static final int SECTOR_HEADER_SIZE = 1; + private static final int ID_HEADER_SIZE = 16; + private static final byte[] HEADER_ID = {'P','R','O','G'}; final byte endBytes[] = new byte[SECTOR_SIZE]; @@ -42,7 +44,7 @@ public class RegionFile { private static final int DEFINITION_SIZE = Integer.BYTES; - private static final int HEADER_SIZE = DEFINITION_SIZE * REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; + private static final int HEADER_SIZE = DEFINITION_SIZE * REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER + ID_HEADER_SIZE; private final RandomAccessFile file; @@ -50,7 +52,7 @@ public class RegionFile { file = inFile; } - public void confirmHeaderHealth(ChunkMap offsets) throws IOException { + public void confirmHeaderHealth(ChunkMap offsets, Vec3i regionCoords) throws IOException { Set used = new HashSet(); int maxUsed = 0; @@ -59,9 +61,28 @@ public class RegionFile { if (file.length() < HEADER_SIZE) { throw new IOException("File is too short to contain a header"); } + + + char prog; + for (int i=0;i<4;i++) { + prog = file.readChar(); + if (prog != HEADER_ID[i]) + { + throw new IOException("File is not a .progressia_chunk file"); + } + } + + int tempX = file.readInt(); + int tempY = file.readInt(); + int tempZ = file.readInt(); + + if (regionCoords.x != tempX || regionCoords.y != tempY || regionCoords.z != tempZ) + { + throw new IOException("Region file is in the wrong place/ has the wrong name."); + } for (int i = 0; i < chunksPerRegion; i++) { - file.seek(i * DEFINITION_SIZE); + file.seek(i * DEFINITION_SIZE + ID_HEADER_SIZE); int offset = file.readInt(); if (offset == 0) { @@ -109,8 +130,12 @@ public class RegionFile { LogManager.getLogger("Region").debug("Efficiency of {}", (double) used.size() / maxUsed); } - public void makeHeader() throws IOException { + public void makeHeader(Vec3i regionCoords) throws IOException { file.seek(0); + file.write(HEADER_ID); + file.writeInt(regionCoords.x); + file.writeInt(regionCoords.y); + file.writeInt(regionCoords.z); for (int i = 0; i < HEADER_SIZE; i++) { file.write(0); } @@ -163,7 +188,7 @@ public class RegionFile { } public int allocateChunk(Vec3i pos) throws IOException { - int definitionOffset = DEFINITION_SIZE * (pos.z + REGION_DIAMETER * (pos.y + REGION_DIAMETER * pos.x)); + int definitionOffset = ID_HEADER_SIZE + DEFINITION_SIZE * (pos.z + REGION_DIAMETER * (pos.y + REGION_DIAMETER * pos.x)); int outputLen = (int) file.length(); diff --git a/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionWorldContainer.java b/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionWorldContainer.java index 378e01e..ca83027 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionWorldContainer.java +++ b/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionWorldContainer.java @@ -185,7 +185,7 @@ public class RegionWorldContainer implements WorldContainer { private Region openRegion(Path path, Vec3i regionCoords) throws IOException { RandomAccessFile raf = new RandomAccessFile(path.toFile(), "rw"); - Region region = new Region(raf); + Region region = new Region(raf, regionCoords); regions.put(regionCoords, region); return region; } From eb5aa59941efdf5605b805f0c4b7fa54eb3658b8 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Sat, 11 Sep 2021 21:12:42 +0300 Subject: [PATCH 35/49] Removed plain sand block and tile; incremented version To be honest, I kinda forgot to increment version in last commit, so I decided to make a pointless change to justify an entire commit =\ --- .../ru/windcorp/progressia/test/LayerAbout.java | 2 +- .../ru/windcorp/progressia/test/TestContent.java | 2 -- .../test/gen/feature/TestGrassFeature.java | 1 - .../resources/assets/textures/blocks/Sand.png | Bin 1649 -> 0 bytes .../resources/assets/textures/tiles/Sand.png | Bin 8841 -> 0 bytes 5 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 src/main/resources/assets/textures/blocks/Sand.png delete mode 100644 src/main/resources/assets/textures/tiles/Sand.png diff --git a/src/main/java/ru/windcorp/progressia/test/LayerAbout.java b/src/main/java/ru/windcorp/progressia/test/LayerAbout.java index 334b462..fae2357 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerAbout.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerAbout.java @@ -50,7 +50,7 @@ public class LayerAbout extends GUILayer { new Label( "Version", font, - new MutableStringLocalized("LayerAbout.Version").format("pre-alpha 2") + new MutableStringLocalized("LayerAbout.Version").format("pre-alpha 3") ) ); diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java index 3651f60..5e9ea98 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java @@ -108,7 +108,6 @@ public class TestContent { registerSimplestBlock("Water"); registerSimplestBlock("Brick"); registerSimplestBlock("BrickWhite"); - registerSimplestBlock("Sand"); registerSimplestBlock("Concrete"); registerSimplestBlock("WoodenPlank"); @@ -195,7 +194,6 @@ public class TestContent { }); registerSimplestTransparentTile("Stones"); - registerSimplestTransparentTile("Sand"); registerSimplestOpaqueTile("SnowOpaque"); Arrays.asList( diff --git a/src/main/java/ru/windcorp/progressia/test/gen/feature/TestGrassFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestGrassFeature.java index add06ec..d854bf4 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/feature/TestGrassFeature.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestGrassFeature.java @@ -67,7 +67,6 @@ public class TestGrassFeature extends SurfaceTopLayerFeature { private final List scatter = ImmutableList.of( TileDataRegistry.getInstance().get("Test:Stones"), - TileDataRegistry.getInstance().get("Test:Sand"), TileDataRegistry.getInstance().get("Test:Bush"), TileDataRegistry.getInstance().get("Test:Fern") ); diff --git a/src/main/resources/assets/textures/blocks/Sand.png b/src/main/resources/assets/textures/blocks/Sand.png deleted file mode 100644 index 3520cb2df143df7dd3796ddaeaff2834075880e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1649 zcmV-%29EiOP)EX>4Tx04R}tkvmAkP!xv$riu?LB6bjQ2vR#)5EXHhDi*;)X)CnqU~glg%>V!Z8FWQhbVF}#ZDnqB07G(RVRU6=Aa`kWXdp*PO;A^X4i^9b z1X@W%K~y-)EtJcS9LE(zBW`A8Rllld1|&s^V}Q^`{sDi!_u6U4g>AqvAY0^UT0Pxe z&&<5{deQoVIPpO6=b!)Xo<(+QLux*#F77MYlF5Am1H6drRIlzi#&tZ$X~i zSG612nJ+mnU;wD9ZnJv@j1V%l>7DtcHknT`HP2PgDL&8h8z6wGy#;v?5qFQ_(QI{O zksW{#j#baX0E(lo>o-ap!(OBnvl+14_>1}C$beM6xMwpnTg_&W!p>}%*MF&A35lT- z?ujUJXwzfY9o$QF)J^x1OsRP&$-U!%|-zG?N7P933oZah#UYk z&30Y?0AM}~5!dxfq*^N=WHcMAUbdSb%+_hTRQ)4_{&@Vf=2s$_jbtKI*B#roB?H+6 z>0{LkfEXUluI7tyBXVfde$69b07^Lp*cd#U=qWj>I<2wo`szw6VYr`n`7wt=l@2saj#wX(LAf3$asg}?;p)4cayss*#y~< zDTe-jeK8!(G7%l7b~Rf8%Xt*(9A4@PkfwQ9mgVkL0Oaxl28RJy^KW1P(6&9VBD00000NkvXXu0mjf-zf&z diff --git a/src/main/resources/assets/textures/tiles/Sand.png b/src/main/resources/assets/textures/tiles/Sand.png deleted file mode 100644 index 2530ce81eed34fc677b31117a1b7edfeab824ad4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8841 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 Date: Wed, 22 Sep 2021 23:48:38 +0300 Subject: [PATCH 36/49] Added more flowers and more grass types, fixed cross tile render - Added Clover, Daisy, Dandelion, Geranium, Knapweed, Yellow Pea, Bluegrass - Renamed grass herbs and flat flowers - Cross tile renderer now uses a kostyl that forces face normals to be oriented vertically - Refactored flower generation - Added a coherent error message when a texture could not be found --- .../client/graphics/model/ShapeParts.java | 79 +++++++--- .../graphics/texture/TextureLoader.java | 8 +- .../graphics/world/WorldRenderProgram.java | 38 ++++- .../client/world/tile/TileRenderCross.java | 6 +- .../ru/windcorp/progressia/test/Flowers.java | 147 ++++++++++++++++++ .../windcorp/progressia/test/TestContent.java | 49 +++--- .../windcorp/progressia/test/gen/Fields.java | 4 + .../test/gen/TestGenerationConfig.java | 14 +- .../test/gen/feature/TestFlowerFeature.java | 59 +++++-- .../test/gen/feature/TestGrassFeature.java | 27 +++- .../assets/textures/tiles/BlueFlowers.png | Bin 481 -> 0 bytes .../resources/assets/textures/tiles/Bush.png | Bin 2015 -> 15810 bytes .../resources/assets/textures/tiles/Fern.png | Bin 11312 -> 14608 bytes .../textures/tiles/FlowerCloverFlat.png | Bin 0 -> 301 bytes .../textures/tiles/FlowerCloverHerb.png | Bin 0 -> 977 bytes .../textures/tiles/FlowerCloverTiny.png | Bin 0 -> 600 bytes .../assets/textures/tiles/FlowerDaisyFlat.png | Bin 0 -> 12979 bytes .../assets/textures/tiles/FlowerDaisyTiny.png | Bin 0 -> 8447 bytes .../textures/tiles/FlowerDandelionFlat.png | Bin 0 -> 384 bytes .../textures/tiles/FlowerDandelionTiny.png | Bin 0 -> 458 bytes .../textures/tiles/FlowerGeraniumFlat.png | Bin 0 -> 379 bytes .../textures/tiles/FlowerGeraniumTiny.png | Bin 0 -> 361 bytes .../textures/tiles/FlowerKnapweedFlat.png | Bin 0 -> 424 bytes .../textures/tiles/FlowerKnapweedTiny.png | Bin 0 -> 465 bytes .../textures/tiles/FlowerLavanderFlat.png | Bin 0 -> 402 bytes ...nderFlowers.png => FlowerLavanderTiny.png} | Bin .../textures/tiles/FlowerYellowPeaFlat.png | Bin 0 -> 314 bytes .../textures/tiles/FlowerYellowPeaTiny.png | Bin 0 -> 337 bytes .../assets/textures/tiles/GrassBluegrass0.png | Bin 0 -> 1261 bytes .../assets/textures/tiles/GrassBluegrass1.png | Bin 0 -> 1490 bytes .../assets/textures/tiles/GrassBluegrass2.png | Bin 0 -> 1508 bytes .../assets/textures/tiles/GrassMeadow0.png | Bin 0 -> 7353 bytes .../assets/textures/tiles/GrassMeadow1.png | Bin 0 -> 9044 bytes .../assets/textures/tiles/GrassMeadow2.png | Bin 0 -> 13721 bytes .../assets/textures/tiles/LowGrass.png | Bin 448 -> 0 bytes .../assets/textures/tiles/MediumGrass.png | Bin 690 -> 0 bytes .../assets/textures/tiles/PurpleFlowers.png | Bin 519 -> 0 bytes .../assets/textures/tiles/TallGrass.png | Bin 8990 -> 0 bytes .../textures/tiles/TinyDandelionFlowers.png | Bin 4380 -> 0 bytes .../assets/textures/tiles/WhiteFlowers.png | Bin 586 -> 0 bytes .../assets/textures/tiles/YellowFlowers.png | Bin 9945 -> 0 bytes 41 files changed, 355 insertions(+), 76 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/test/Flowers.java delete mode 100644 src/main/resources/assets/textures/tiles/BlueFlowers.png create mode 100644 src/main/resources/assets/textures/tiles/FlowerCloverFlat.png create mode 100644 src/main/resources/assets/textures/tiles/FlowerCloverHerb.png create mode 100644 src/main/resources/assets/textures/tiles/FlowerCloverTiny.png create mode 100644 src/main/resources/assets/textures/tiles/FlowerDaisyFlat.png create mode 100644 src/main/resources/assets/textures/tiles/FlowerDaisyTiny.png create mode 100644 src/main/resources/assets/textures/tiles/FlowerDandelionFlat.png create mode 100644 src/main/resources/assets/textures/tiles/FlowerDandelionTiny.png create mode 100644 src/main/resources/assets/textures/tiles/FlowerGeraniumFlat.png create mode 100644 src/main/resources/assets/textures/tiles/FlowerGeraniumTiny.png create mode 100644 src/main/resources/assets/textures/tiles/FlowerKnapweedFlat.png create mode 100644 src/main/resources/assets/textures/tiles/FlowerKnapweedTiny.png create mode 100644 src/main/resources/assets/textures/tiles/FlowerLavanderFlat.png rename src/main/resources/assets/textures/tiles/{TinyLavanderFlowers.png => FlowerLavanderTiny.png} (100%) create mode 100644 src/main/resources/assets/textures/tiles/FlowerYellowPeaFlat.png create mode 100644 src/main/resources/assets/textures/tiles/FlowerYellowPeaTiny.png create mode 100644 src/main/resources/assets/textures/tiles/GrassBluegrass0.png create mode 100644 src/main/resources/assets/textures/tiles/GrassBluegrass1.png create mode 100644 src/main/resources/assets/textures/tiles/GrassBluegrass2.png create mode 100644 src/main/resources/assets/textures/tiles/GrassMeadow0.png create mode 100644 src/main/resources/assets/textures/tiles/GrassMeadow1.png create mode 100644 src/main/resources/assets/textures/tiles/GrassMeadow2.png delete mode 100644 src/main/resources/assets/textures/tiles/LowGrass.png delete mode 100644 src/main/resources/assets/textures/tiles/MediumGrass.png delete mode 100644 src/main/resources/assets/textures/tiles/PurpleFlowers.png delete mode 100644 src/main/resources/assets/textures/tiles/TallGrass.png delete mode 100644 src/main/resources/assets/textures/tiles/TinyDandelionFlowers.png delete mode 100644 src/main/resources/assets/textures/tiles/WhiteFlowers.png delete mode 100644 src/main/resources/assets/textures/tiles/YellowFlowers.png diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeParts.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeParts.java index 50f744f..4030249 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeParts.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeParts.java @@ -25,13 +25,14 @@ import glm.vec._3.Vec3; import glm.vec._4.Vec4; import ru.windcorp.progressia.client.graphics.model.ShapeRenderProgram.VertexBuilder; import ru.windcorp.progressia.client.graphics.texture.Texture; +import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram.WRPVertexBuilder; import ru.windcorp.progressia.common.world.rels.AbsFace; public class ShapeParts { private ShapeParts() { } - + public static ShapePart createRectangle( ShapeRenderProgram program, Texture texture, @@ -41,25 +42,65 @@ public class ShapeParts { Vec3 height, boolean flip ) { - VertexBuilder builder = program.getVertexBuilder(); + return createRectangle(program, texture, colorMultiplier, origin, width, height, flip, null); + } - builder.addVertex( - origin, - colorMultiplier, - new Vec2(0, 0) - ).addVertex( - origin.add_(height), - colorMultiplier, - new Vec2(0, 1) - ).addVertex( - origin.add_(width), - colorMultiplier, - new Vec2(1, 0) - ).addVertex( - origin.add_(width).add(height), - colorMultiplier, - new Vec2(1, 1) - ); + public static ShapePart createRectangle( + ShapeRenderProgram program, + Texture texture, + Vec4 colorMultiplier, + Vec3 origin, + Vec3 width, + Vec3 height, + boolean flip, + Vec3 forcedNormals + ) { + VertexBuilder builder = program.getVertexBuilder(); + + if (forcedNormals != null && builder instanceof WRPVertexBuilder) { + ((WRPVertexBuilder) builder).addVertex( + origin, + colorMultiplier, + new Vec2(0, 0), + forcedNormals + ); + ((WRPVertexBuilder) builder).addVertex( + origin.add_(height), + colorMultiplier, + new Vec2(0, 1), + forcedNormals + ); + ((WRPVertexBuilder) builder).addVertex( + origin.add_(width), + colorMultiplier, + new Vec2(1, 0), + forcedNormals + ); + ((WRPVertexBuilder) builder).addVertex( + origin.add_(width).add(height), + colorMultiplier, + new Vec2(1, 1), + forcedNormals + ); + } else { + builder.addVertex( + origin, + colorMultiplier, + new Vec2(0, 0) + ).addVertex( + origin.add_(height), + colorMultiplier, + new Vec2(0, 1) + ).addVertex( + origin.add_(width), + colorMultiplier, + new Vec2(1, 0) + ).addVertex( + origin.add_(width).add(height), + colorMultiplier, + new Vec2(1, 1) + ); + } ShortBuffer buffer = flip ? ShortBuffer.wrap( new short[] { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureLoader.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureLoader.java index 18f2326..1ce3998 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureLoader.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TextureLoader.java @@ -28,6 +28,7 @@ import javax.imageio.ImageIO; import ru.windcorp.progressia.common.resource.Resource; import ru.windcorp.progressia.common.util.BinUtil; +import ru.windcorp.progressia.common.util.crash.CrashReports; public class TextureLoader { @@ -99,7 +100,12 @@ public class TextureLoader { TextureSettings settings ) throws IOException { - return loadPixels(resource.getInputStream(), settings); + + InputStream stream = resource.getInputStream(); + if (stream == null) { + throw CrashReports.report(null, "Texture \"%s\" not found", resource.getName()); + } + return loadPixels(stream, settings); } private TextureLoader() { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/WorldRenderProgram.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/WorldRenderProgram.java index c005454..55ef3f8 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/WorldRenderProgram.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/WorldRenderProgram.java @@ -199,6 +199,10 @@ public class WorldRenderProgram extends ShapeRenderProgram { int offset = vertices.position() + index * getBytesPerVertex() + (3 * Float.BYTES + 4 * Float.BYTES + 2 * Float.BYTES); + + if (!Float.isNaN(vertices.getFloat(offset + 0 * Float.BYTES))) { + return; // normals are forced + } vertices.putFloat(offset + 0 * Float.BYTES, normal.x); vertices.putFloat(offset + 1 * Float.BYTES, normal.y); @@ -212,7 +216,7 @@ public class WorldRenderProgram extends ShapeRenderProgram { return new WRPVertexBuilder(); } - private static class WRPVertexBuilder implements VertexBuilder { + public static class WRPVertexBuilder implements VertexBuilder { // TODO Throw VertexBuilders out the window and rewrite completely. // I want to _extend_ VBs, not re-implement them for children of SRP @@ -220,11 +224,17 @@ public class WorldRenderProgram extends ShapeRenderProgram { final Vec3 position; final Vec4 colorMultiplier; final Vec2 textureCoords; - + final Vec3 normals; + Vertex(Vec3 position, Vec4 colorMultiplier, Vec2 textureCoords) { + this(position, colorMultiplier, textureCoords, new Vec3(Float.NaN, Float.NaN, Float.NaN)); + } + + Vertex(Vec3 position, Vec4 colorMultiplier, Vec2 textureCoords, Vec3 normals) { this.position = position; this.colorMultiplier = colorMultiplier; this.textureCoords = textureCoords; + this.normals = normals; } } @@ -291,6 +301,24 @@ public class WorldRenderProgram extends ShapeRenderProgram { return this; } + + public VertexBuilder addVertex( + Vec3 position, + Vec4 colorMultiplier, + Vec2 textureCoords, + Vec3 normals + ) { + vertices.add( + new Vertex( + new Vec3(position), + new Vec4(colorMultiplier), + new Vec2(textureCoords), + new Vec3(normals) + ) + ); + + return this; + } @Override public ByteBuffer assemble() { @@ -309,9 +337,9 @@ public class WorldRenderProgram extends ShapeRenderProgram { .putFloat(v.colorMultiplier.w) .putFloat(v.textureCoords.x) .putFloat(v.textureCoords.y) - .putFloat(Float.NaN) - .putFloat(Float.NaN) - .putFloat(Float.NaN); + .putFloat(v.normals.x) + .putFloat(v.normals.y) + .putFloat(v.normals.z); } result.flip(); diff --git a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderCross.java b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderCross.java index 01af8f6..f312ed2 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderCross.java +++ b/src/main/java/ru/windcorp/progressia/client/world/tile/TileRenderCross.java @@ -114,7 +114,8 @@ public class TileRenderCross extends TileRender implements TileOptimizedCustom { origin, width, height, - false + false, + new Vec3(0, 0, 1) ) ); output.accept( @@ -125,7 +126,8 @@ public class TileRenderCross extends TileRender implements TileOptimizedCustom { origin, width, height, - true + true, + new Vec3(0, 0, 1) ) ); } diff --git a/src/main/java/ru/windcorp/progressia/test/Flowers.java b/src/main/java/ru/windcorp/progressia/test/Flowers.java new file mode 100644 index 0000000..9eb45a8 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/Flowers.java @@ -0,0 +1,147 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import ru.windcorp.progressia.client.graphics.texture.Texture; +import ru.windcorp.progressia.client.world.tile.TileRenderRegistry; +import ru.windcorp.progressia.client.world.tile.TileRenderTransparentSurface; +import ru.windcorp.progressia.common.world.tile.TileData; +import ru.windcorp.progressia.common.world.tile.TileDataRegistry; +import ru.windcorp.progressia.server.world.tile.HangingTileLogic; +import ru.windcorp.progressia.server.world.tile.TileLogicRegistry; + +public class Flowers { + + private static final int HERB_MAX_COUNT = 3; + private static final int TINY_MAX_COUNT = 8; + private static final float TINY_SIZE = 0.5f; + + public enum FlowerVariant { + + FLAT("Flat"), + TINY("Tiny"), + HERB("Herb"); + + private final String name; + + private FlowerVariant(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + } + + public static class Flower { + + private final String name; + + /** + * 1 disables spawning, 0 spawns everywhere + */ + private final float rarity; + + private final FlowerVariant[] requestedVariants; + private final Map tiles = new HashMap<>(); + + public Flower(String name, float rarity, FlowerVariant... variants) { + Objects.requireNonNull(name, "name"); + Objects.requireNonNull(variants, "variants"); + + this.name = name; + this.rarity = rarity; + this.requestedVariants = variants; + } + + public String getName() { + return name; + } + + public float getRarity() { + return rarity; + } + + public TileData getTile(FlowerVariant variant) { + return tiles.get(variant); + } + + public Collection getTiles() { + return tiles.values(); + } + + private void register() { + for (FlowerVariant variant : requestedVariants) { + + String fullName = "Flower" + name + variant.getName(); + String id = "Test:" + fullName; + + TileData tileData = new TileData(id); + tiles.put(variant, tileData); + TileDataRegistry.getInstance().register(tileData); + + Texture texture = TileRenderRegistry.getTileTexture(fullName); + + TileLogicRegistry logic = TileLogicRegistry.getInstance(); + TileRenderRegistry render = TileRenderRegistry.getInstance(); + + switch (variant) { + case HERB: + logic.register(new HangingTileLogic(id)); + render.register(new TileRenderHerb(id, texture, HERB_MAX_COUNT)); + break; + case TINY: + logic.register(new HangingTileLogic(id)); + render.register(new TileRenderTinyFlower(id, texture, TINY_MAX_COUNT, TINY_SIZE)); + break; + case FLAT: + default: + logic.register(new TestTileLogicGrass(id)); + render.register(new TileRenderTransparentSurface(id, texture)); + break; + } + + } + } + + } + + private final Map flowersByName = Collections.synchronizedMap(new HashMap<>()); + + public Flower create(String name, float rarity, FlowerVariant... variants) { + Flower flower = new Flower(name, rarity, variants); + flowersByName.put(name, flower); + return flower; + } + + public void registerAllFlowers() { + getFlowers().forEach(Flower::register); + } + + public Collection getFlowers() { + return flowersByName.values(); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java index 5e9ea98..e027cef 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java @@ -62,6 +62,7 @@ import ru.windcorp.progressia.server.world.context.ServerTileStackContext; import ru.windcorp.progressia.server.world.entity.*; import ru.windcorp.progressia.server.world.generation.planet.PlanetGravityModel; import ru.windcorp.progressia.server.world.tile.*; +import ru.windcorp.progressia.test.Flowers.FlowerVariant; import ru.windcorp.progressia.test.Rocks.RockType; import ru.windcorp.progressia.test.gen.TestGravityModel; @@ -75,6 +76,7 @@ public class TestContent { public static final List PLACEABLE_TILES = new ArrayList<>(); public static final Rocks ROCKS = new Rocks(); + public static final Flowers FLOWERS = new Flowers(); public static void registerContent() { registerWorldContent(); @@ -183,15 +185,8 @@ public class TestContent { ); register(new TestTileLogicGrass(id)); }); - - Arrays.asList( - "Yellow", - "White", - "Purple", - "Blue" - ).forEach(color -> { - registerSimplestTransparentTile(color + "Flowers"); - }); + + registerFlowers(); registerSimplestTransparentTile("Stones"); @@ -216,21 +211,12 @@ public class TestContent { registerSimplestOpaqueTile("TilesLarge"); registerSimplestOpaqueTile("TilesSmall"); - registerHerb("LowGrass", 6); - registerHerb("MediumGrass", 6); - registerHerb("TallGrass", 6); - - Arrays.asList( - "Dandelion", - "Lavander" - ).forEach(variant -> { - String fullName = "Tiny" + variant + "Flowers"; - String id = "Test:" + fullName; - - register(new TileData(id)); - register(new TileRenderTinyFlower(id, getTileTexture(fullName), 8, 0.5f)); - register(new HangingTileLogic(id)); - }); + registerHerb("GrassMeadow0", 6); + registerHerb("GrassMeadow1", 6); + registerHerb("GrassMeadow2", 6); + registerHerb("GrassBluegrass0", 6); + registerHerb("GrassBluegrass1", 6); + registerHerb("GrassBluegrass2", 6); registerHerb("Bush", 1); registerHerb("Fern", 3); @@ -240,6 +226,21 @@ public class TestContent { PLACEABLE_TILES.sort(Comparator.comparing(TileData::getId)); } + private static void registerFlowers() { + + final float common = 0.8f; + + FLOWERS.create("Clover", common, FlowerVariant.HERB, FlowerVariant.TINY, FlowerVariant.FLAT); + FLOWERS.create("Dandelion", common, FlowerVariant.TINY, FlowerVariant.FLAT); + FLOWERS.create("Geranium", common, FlowerVariant.TINY, FlowerVariant.FLAT); + FLOWERS.create("Knapweed", common, FlowerVariant.TINY, FlowerVariant.FLAT); + FLOWERS.create("YellowPea", common, FlowerVariant.TINY, FlowerVariant.FLAT); + FLOWERS.create("Daisy", common, FlowerVariant.TINY, FlowerVariant.FLAT); + FLOWERS.create("Lavander", common, FlowerVariant.TINY, FlowerVariant.FLAT); + + FLOWERS.registerAllFlowers(); + } + private static void registerSimplestBlock(String name) { String id = "Test:" + name; register(new BlockData(id)); diff --git a/src/main/java/ru/windcorp/progressia/test/gen/Fields.java b/src/main/java/ru/windcorp/progressia/test/gen/Fields.java index 26ccdca..36abefb 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/Fields.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/Fields.java @@ -218,6 +218,10 @@ public class Fields { public static Field anti(Field f) { return tweak(f, 1, -1, 1); } + + public static Field rarify(Field f, float rarity) { + return (x, y) -> Math.max((f.compute(x, y) - rarity) / (1 - rarity), 0); + } public static Field octaves(Field f, double scaleFactor, double amplitudeFactor, int octaves) { return (x, y) -> { diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java index 1fe8334..1896db4 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java @@ -26,6 +26,7 @@ import java.util.function.Function; import ru.windcorp.progressia.common.Units; import ru.windcorp.progressia.common.util.noise.discrete.WorleyProceduralNoise; import ru.windcorp.progressia.common.world.Coordinates; +import ru.windcorp.progressia.common.world.rels.AbsFace; import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.generation.WorldGenerator; import ru.windcorp.progressia.server.world.generation.planet.Planet; @@ -125,19 +126,16 @@ public class TestGenerationConfig { ) ); - Function floweriness = flowerName -> fields.register( - "Test:Flower" + flowerName, - f -> multiply( - selectPositive(squash(scale(octaves(fields.primitive(), 2, 3), 100), 2), 1, 0.5), - tweak(fields.get("Test:Forest", f), 1, -1, 1.1), - anti(squash(fields.get("Test:Cliff", f), 10)) - ) + Function floweriness = f -> multiply( + amplify(withMin(squash(scale(octaves(fields.primitive(), 2, 3), 100), 5), 0), 2), + tweak(fields.get("Test:Forest", f), 1, -1, 1.1), + anti(squash(fields.get("Test:Cliff", f), 10)) ); features.add(new TestBushFeature("Test:BushFeature", forestiness)); features.add(new TestTreeFeature("Test:TreeFeature", forestiness)); features.add(new TestGrassFeature("Test:GrassFeature", grassiness)); - features.add(new TestFlowerFeature("Test:FlowerFeature", floweriness)); + features.add(new TestFlowerFeature("Test:FlowerFeature", TestContent.FLOWERS, floweriness, fields)); } } diff --git a/src/main/java/ru/windcorp/progressia/test/gen/feature/TestFlowerFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestFlowerFeature.java index 19a97aa..03fd251 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/feature/TestFlowerFeature.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestFlowerFeature.java @@ -17,35 +17,73 @@ */ package ru.windcorp.progressia.test.gen.feature; +import java.util.ArrayList; +import java.util.List; import java.util.Set; import java.util.function.Function; import com.google.common.collect.ImmutableSet; +import ru.windcorp.progressia.common.world.rels.AbsFace; import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.tile.TileData; -import ru.windcorp.progressia.common.world.tile.TileDataRegistry; import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; import ru.windcorp.progressia.server.world.generation.surface.SurfaceTopLayerFeature; import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; +import ru.windcorp.progressia.test.Flowers; +import ru.windcorp.progressia.test.Flowers.Flower; +import ru.windcorp.progressia.test.Flowers.FlowerVariant; import ru.windcorp.progressia.test.TestContent; +import ru.windcorp.progressia.test.gen.Fields; +import ru.windcorp.progressia.test.gen.Fields.Field; public class TestFlowerFeature extends SurfaceTopLayerFeature { private static class FlowerGenerator { - private final TileData tile; + + private final TileData[] variants; private final SurfaceFloatField floweriness; - public FlowerGenerator(TileData tile, Function flowerinessGenerator) { - this.tile = tile; - this.floweriness = flowerinessGenerator.apply(tile.getName()); + public FlowerGenerator(Flower flower, Function flowerinessGenerator, Fields fields) { + this.floweriness = fields.register( + "Test:Flower" + flower.getName(), + f -> Fields.rarify(flowerinessGenerator.apply(f), flower.getRarity()) + ); + + List tiles = new ArrayList<>(); + for (FlowerVariant variant : FlowerVariant.values()) { + TileData tile = flower.getTile(variant); + if (tile == null) { + continue; + } + + tiles.add(tile); + } + + this.variants = tiles.toArray(new TileData[tiles.size()]); } public void generate(SurfaceBlockContext context) { - if (context.getRandom().nextDouble() < floweriness.get(context)) { - context.addTile(RelFace.UP, tile); + float floweriness = this.floweriness.get(context); + + if (floweriness <= 0) { + return; } + + float random = context.getRandom().nextFloat(); + + int variant = (int) Math.floor((random + floweriness - 1) * variants.length); + + if (variant < 0) { + return; + } else if (variant >= variants.length) { + // Screw doing float math properly, just clamp it + variant = variants.length - 1; + } + + context.addTile(RelFace.UP, variants[variant]); } + } private final Set soilWhitelist; @@ -58,12 +96,11 @@ public class TestFlowerFeature extends SurfaceTopLayerFeature { private final FlowerGenerator[] flowers; - public TestFlowerFeature(String id, Function flowerinessGenerator) { + public TestFlowerFeature(String id, Flowers flowers, Function flowerinessGenerator, Fields fields) { super(id); - this.flowers = TileDataRegistry.getInstance().values().stream() - .filter(tile -> tile.getName().endsWith("Flowers")) - .map(tile -> new FlowerGenerator(tile, flowerinessGenerator)) + this.flowers = flowers.getFlowers().stream() + .map(flower -> new FlowerGenerator(flower, flowerinessGenerator, fields)) .toArray(FlowerGenerator[]::new); } diff --git a/src/main/java/ru/windcorp/progressia/test/gen/feature/TestGrassFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestGrassFeature.java index d854bf4..d7b4bae 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/feature/TestGrassFeature.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestGrassFeature.java @@ -19,6 +19,7 @@ package ru.windcorp.progressia.test.gen.feature; import java.util.List; import java.util.Set; +import java.util.function.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -57,12 +58,26 @@ public class TestGrassFeature extends SurfaceTopLayerFeature { flatGrasses.put(0.1f, 0.2f, TileDataRegistry.getInstance().get("Test:GrassWeb")); flatGrasses.put(0.05f, 0.1f, TileDataRegistry.getInstance().get("Test:GrassThreads")); } + + private static final Function randomPicker(String commonId, String rareId) { + TileData common = TileDataRegistry.getInstance().get(commonId); + TileData rare = TileDataRegistry.getInstance().get(rareId); + final float rareChance = 0.2f; + + return context -> { + if (context.getRandom().nextFloat() < rareChance) { + return rare; + } else { + return common; + } + }; + } - private final FloatRangeMap herbGrasses = new ArrayFloatRangeMap<>(); + private final FloatRangeMap> herbGrasses = new ArrayFloatRangeMap<>(); { - herbGrasses.put(0.6f, 1, TileDataRegistry.getInstance().get("Test:TallGrass")); - herbGrasses.put(0.4f, 0.6f, TileDataRegistry.getInstance().get("Test:MediumGrass")); - herbGrasses.put(0.1f, 0.4f, TileDataRegistry.getInstance().get("Test:LowGrass")); + herbGrasses.put(0.6f, 1, randomPicker("Test:GrassMeadow2", "Test:GrassBluegrass2")); + herbGrasses.put(0.4f, 0.6f, randomPicker("Test:GrassMeadow1", "Test:GrassBluegrass1")); + herbGrasses.put(0.1f, 0.4f, randomPicker("Test:GrassMeadow0", "Test:GrassBluegrass0")); } private final List scatter = ImmutableList.of( @@ -134,9 +149,9 @@ public class TestGrassFeature extends SurfaceTopLayerFeature { } if (context.getRandom().nextDouble() < grassiness) { - TileData herbGrass = herbGrasses.get((float) grassiness); + Function herbGrass = herbGrasses.get((float) grassiness); if (herbGrass != null) { - context.addTile(RelFace.UP, herbGrass); + context.addTile(RelFace.UP, herbGrass.apply(context)); } } } diff --git a/src/main/resources/assets/textures/tiles/BlueFlowers.png b/src/main/resources/assets/textures/tiles/BlueFlowers.png deleted file mode 100644 index 82c50471282d17f2b0ec2cd9325fd08c18a3b727..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 481 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjY)RhkEbHUgGKN%Knr?RD{?1P(pwOP)M@GHKN2hKQ}iuuY|$5C^fMpHASI3 zvm`^o-P1Q9ypd0wfq~J})5S5wYVFCHdwSB7M9J@IV+AuseVO$)V6`#CD=KB<%uzmM)n9^lt z#7@e$%1{kfkt@HnF`55qj^|3#WfOhe{Y4XmzfGTYyTY|?=c09SN>PvU&h6Qb`9v_7m2R7&zQv==+1c`#`k!$sfyF4pnI z@@3&CTsFP`wPao@M`Phs=OzXQm-Rfq)h>OP@!TAw7pVM4SpW8hKaouZA{VY}2sC$; zFDjpKM8vaKLSa(P@e}JapFYVKW7*8mHGl12R%!L4 Vkr{i8+JGU?;OXk;vd$@?2>|EyyqW+2 diff --git a/src/main/resources/assets/textures/tiles/Bush.png b/src/main/resources/assets/textures/tiles/Bush.png index 0922df3d30e45d70d47fbd758e127dc49663d326..27163187a0163121b9c7be7a16fceecfe3dcf13d 100644 GIT binary patch literal 15810 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 z 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 diff --git a/src/main/resources/assets/textures/tiles/FlowerCloverFlat.png b/src/main/resources/assets/textures/tiles/FlowerCloverFlat.png new file mode 100644 index 0000000000000000000000000000000000000000..c8d54c7d3c04654628c5bd36d178abd8ecbbbee0 GIT binary patch literal 301 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjY)RhkE)4%caKYZ?lYt_f1s;*b z3=De8Ak0{?)V>TT$X?><>&pI=Q%po$w9!wo2q+|3;u=xnoS&PUnpeW$T$GwvlA5AW zo>`Ki;O^-g5Z=fq4pcPN)5S5w<9Kp{1nZIp|7gAc|F=B-RG;-K*-8Az?|;&VU*B{6 zzfrR3Y{T`v-T(gA{_m~0o?tvjtjg`60Bd~Oy8r&y|1_G)KVbSFzdv!oOjZ!}b|>y!~9&3FtruPgg&ebxsLQ0KlMg!2kdN literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/tiles/FlowerCloverHerb.png b/src/main/resources/assets/textures/tiles/FlowerCloverHerb.png new file mode 100644 index 0000000000000000000000000000000000000000..2d6c505365725387ea8e708b8dc07ca50f6793ec GIT binary patch literal 977 zcmV;?11|iDP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00TKmL_t(Y$L*6{Oq*30$A9nJ zz7$rVv;`Utwv>h*{EyoLE6IT= zq?Peq{8UP((*X4J^!%rx^8~3Q?+O6FMv~laH|hs{;<{?2w8F&up&=t zs*1zmV85kV02m%~<@J+qFX%kaN>5z*j!Y(l$KzrDXdjmK3Emn%BPoi)@5-FGzG*=i z3N@TXI2}6YeoxYG+ zIV?ImI|&2=e6~~1+vX6*hK>q=G0N zcrUifI<$(GYFicW?P+J^#xKHLZDz3lD@&dLB8&|H*V7J>jHgr@3M}mCv`Uxo~@b(@OT3O3VLdChoMRX=g_uVh> z^T;LcZ+rlk(?xx4JstdjqppFPZ8d!S?QzlC(u%XrMU}Cdd+*xKxo^&Ku=N=!?;muW zd{z7wnj>~C#vP5@0BE|inWe-c6SEW4TCB*j%-OHcqE$3#v>HrRCd$goNUf$2>jFim zu+wH|J{Co<)8|AIz|);iiQZR^OWxi?qSj*N!ti+jGU+S;n@Wl(HWpK3t)WbBe zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00F>BL_t(2&t=a~Xp(Up$MN^~ zaW?nI2^m-z*aWu-f_h{K3p{t|65V25>J(w9)Iu0kP=P|RtEa9dU6SbBRj@ITrQ}>b zEGgQErcck~^wD3Jrcj^r`vu>x@OPO^29L*sWm#miSpW{+Y$)-#nY(gcjyg%F(>z>W zQOX(eY@;9m{eGXPi%Y6|>< zx0~l%ZzV9Su~KL^I1QX~?IF$jf1 z41#^-%=Z*PEEdByZ7!U+D8F8n)uT%{RHxG!15MMo8oeg%{WjCyDGbBFJowG(oKMl( zL^(q&%Nm2r-gBy0EHb?}D*!u#Z8htgAGQH)dnbiLVGJg|eIgo-A|eF3r^M>m zSRI>yc~Y`ptI}}l>dyM@(NEfw?M+#XN0hGX#N%-QUM$^X*JY@xxup(2_a)Sumj^HJ zD*&xtud`cjN$>QbDwRr1xLw?OzlLqvEKHphfJUQ%x8)N6P1kiQl?vs;N2!@r<@5)m mdxOCskw}DmK96A-0Q><>@xLVBe9MUd0000 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/tiles/FlowerDaisyTiny.png b/src/main/resources/assets/textures/tiles/FlowerDaisyTiny.png new file mode 100644 index 0000000000000000000000000000000000000000..5fca23e30d95d2aa66a2320c158bda8f298222b8 GIT binary patch literal 8447 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/tiles/FlowerDandelionFlat.png b/src/main/resources/assets/textures/tiles/FlowerDandelionFlat.png new file mode 100644 index 0000000000000000000000000000000000000000..c72e70dd0627fccab67ee1451aba3a3d0fbad1d9 GIT binary patch literal 384 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjY)RhkE)4%caKYZ?lYt_f1s;*b z3=De8Ak0{?)V>TT$X?><>&pI=Q%r=#@Xn$ZL!gjkiEBiObAE1aYF-J0b5UwyNotBh zd1gt5g1e`0KzJjcI8f0GPZ!4!kK=DApUytyAaNvp@kXy=P1cVAi@KLyvHMrEUhY=5 zgN~@Y;IA9gwzQk+YFuTR8&}=AB*mPiFoFMc`H#2f%#}S3Ezyw(+t=_RwCL5&|DWEx zU3mCP!_P%6>Z%3LO@p1Kid43pJzcNwclOv%)dTX;vt5<4yRQ6bI_KDPc9O-rGcDg# z>-VlV_@W%q&dIMj^Jfj)a-Uh9wHLQA=Iz$odc@?5YI0bB{cMi6_7##IexaPRi*nXw z98B)Mx~g|^n?BdYCow@Km$QrROgCZMVW+quM*PYm{;O#}YFv{WG`b4yf8P5jl6zTS YZ_^5yE`wPHKtD5hy85}Sb4q9e07mSY>Hq)$ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/tiles/FlowerDandelionTiny.png b/src/main/resources/assets/textures/tiles/FlowerDandelionTiny.png new file mode 100644 index 0000000000000000000000000000000000000000..3477cd4a0b32bd0c6a846a6fb14ca8787a0e9899 GIT binary patch literal 458 zcmV;*0X6=KP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00A;dL_t(2&yA6>OF{t<#(($p zSwj#GEkP0m+0xK|(%4|WMOuUi#L|#3eS|m#K|(}2I2h6560{lg2S`rg*rKC@KGfGW zgvQGTzwz$(arfQ9AH`xZ=29dQnF}@mEXzVfa9!8a%w#e%20wslnmCR_xm*Td*vqTB zZFKyCZ6h-iT-T*qtxk)s^GNHxff%dv!1_X*XNM_3rxZeI$=G#Pbt7n<5~ft z(Wr+NfMUI%AN964j)TwVBe=V)q3{~bT1zUG3IO?s3q9Y@{^U_rlBI+uO9{0s3xM?9 zsRE>KPc&D{s;d582|x@X5HQ)^+tT<_TsC($IKDbkF@*7G>|JT1%O_hG76S~2BZ4bI zx}RP8y*`D*qNpk&;x$YkR!*zm^z)@k?!fji-}MT5HA3$YUjP6A07*qoM6N<$f-TXy AJ^%m! literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/tiles/FlowerGeraniumFlat.png b/src/main/resources/assets/textures/tiles/FlowerGeraniumFlat.png new file mode 100644 index 0000000000000000000000000000000000000000..16ff34c3b58c3c5a56c6c6e2c6d4d9102d7d73b4 GIT binary patch literal 379 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjY)RhkE)4%caKYZ?lYt_f1s;*b z3=De8Ak0{?)V>TT$X?><>&pI=Q%qP#aQ{7-Yd|5%64!_l=ltB<)VvY~=c3falGGH1 z^30M91$R&1fbd2>aiF5do-U3d9>SNV){ z=GA|(_bhbay0_=Sga3(h`1{uF{y2Y`7)R8bWQ!fYxN>z4iWk04lUrc1_+d};)yv=h zi5uG<-cb24@s_CQ>*w!}z5)uCC5qnP{N_ykp0A9m73VJ*|NlNO=db;rPmB!8dn;ll TFS!v1^e%&^tDnm{r-UW|<+Y^- literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/tiles/FlowerGeraniumTiny.png b/src/main/resources/assets/textures/tiles/FlowerGeraniumTiny.png new file mode 100644 index 0000000000000000000000000000000000000000..5aa25210da324a9cd69d99534a9e4227c8179ef0 GIT binary patch literal 361 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&kwj^(N7lw8a%vC;94HV%l@Q5sC zV9-+rVaAH3_GLgp_7YEDSN5lzVmt;$Z?;_70u+)gag8W(&d<$F%`0JWE=o--Nlj5G z&n(GMaQE~L2yf&Q2P(Sg>EaloalSXumb)oH#CBWA?9S@s>KhkyzNr6lJ@?++f>T#l zX@?}Qmq+u%8yD2l{`MaML?-_OH?3Mn=Q^vWqlGT=@jPt20oA1@Y ztEy(Vr{0nNs`|vW?dGSBJtwTvWDkD++pz4_j``PS^epEs*W4h}t#e$7!J_8didR8; z)ny(MO$A2{ZicU{3Vq=6huiOC@O*{?yDL~2E}AOMJg{W`uOphz4u!O6YxpH`gikOu zpB10bzHQCHsTG?RvdC}n*wOT_l40hT*O%gR&Qw~l_G$YAJ;&hb>gTe~DWM4fUs8#_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/tiles/FlowerKnapweedFlat.png b/src/main/resources/assets/textures/tiles/FlowerKnapweedFlat.png new file mode 100644 index 0000000000000000000000000000000000000000..dd888ea67b4590e8fda41d170f37a71e814b6e09 GIT binary patch literal 424 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjY)RhkE)4%caKYZ?lYt_f1s;*b z3=De8Ak0{?)V>TT$X?><>&pI=Q%r=JbyN5=XP}T|iEBiObAE1aYF-J0b5UwyNotBh zd1gt5g1e`0KzJjcI0FNtfTxRNh{y4_A*a0#2ME|sb`d+n7h5vy<8HR@I zp=WNjIu<#7H%WNE?)>j`li2V%@FWSK9$ zVp!T=!_=}h>tKxG!?K!bagEnQW1==2)OBwxzA$0uG7WwCKIUt7uJMXj8on%erMwOp OfDE3lelF{r5}E*=NvqQU literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/tiles/FlowerKnapweedTiny.png b/src/main/resources/assets/textures/tiles/FlowerKnapweedTiny.png new file mode 100644 index 0000000000000000000000000000000000000000..226d59edeaeab3460dcafb8eebda3e64d571809e GIT binary patch literal 465 zcmV;?0WSWDP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00B8kL_t(2&)tyEE5mUd#$WGQ z&HPHXHb183va+()N_L!x8=?3Q++5w<9Mldjl;q&-;_N@*Lb5ToB{W0G>ihldCvPV^ z$Y0>OJR}G z07)e?TDU8)X>IU+S&~MhL2MzScFATvlBD`pLt2D-sg7r?2Zyu6$@JEQJfFYHz^GpX zfdFN@!sE${%qM4M<#?Gw_7VM31}1w&ex{?*D4|e@a<`>#sSh#6;2G}LcDqZ`=`{I# z9smJIBof4yM%3NmCVQ5{+|)$+zf_)_GBg#?s;RNFx+ee*m&?V__@K77w_=qn?CYw~ z_o;22Zj3S1Ds@zUofi&=iO1tj9}EVWUzt$=pU;Qi?{BhigX@4F<~t{o00000NkvXX Hu0mjfLH^9d literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/tiles/FlowerLavanderFlat.png b/src/main/resources/assets/textures/tiles/FlowerLavanderFlat.png new file mode 100644 index 0000000000000000000000000000000000000000..52be47898d2b990d67c174dfe311f1c25500ebd8 GIT binary patch literal 402 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjY)RhkE)4%caKYZ?lYt_f1s;*b z3=De8Ak0{?)V>TT$X?><>&pI=Q%roN+P^3I;PP5koK|Ns9l*P1uK>XE(C z{3^C|ncw}sGOHi$d$INZ$&D#NcglEbBOW(&_s?$xf<(V-f|G(A-Z}BREmE?qon@@d z%*=dv{rdZyQdZ{G@^$V3Lhm+T{wB!dwaVqgsXLqhXJ#D)nlCB#e9jMlV{WnZxrbgd zA5#nsnUHhv(wbn2d$VU3c9=+SXuW;sit`79xwCdnei37Ig;Pn@h+*{7@=y4S(0 pD`Hx)SpKP5^EUnd|3O=eVgB=<=1uoB4*^4g!PC{xWt~$(698*AqiFyD literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/tiles/TinyLavanderFlowers.png b/src/main/resources/assets/textures/tiles/FlowerLavanderTiny.png similarity index 100% rename from src/main/resources/assets/textures/tiles/TinyLavanderFlowers.png rename to src/main/resources/assets/textures/tiles/FlowerLavanderTiny.png diff --git a/src/main/resources/assets/textures/tiles/FlowerYellowPeaFlat.png b/src/main/resources/assets/textures/tiles/FlowerYellowPeaFlat.png new file mode 100644 index 0000000000000000000000000000000000000000..e254421e7eb8361e603afb203182f85b906cf770 GIT binary patch literal 314 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjY)RhkE)4%caKYZ?lYt_f1s;*b z3=De8Ak0{?)V>TT$X?><>&pI=Q%qRbyyV1+ETE8NiEBiObAE1aYF-J0b5UwyNotBh zd1gt5g1e`0KzJjcI8f0dPZ!4!kK@UI{{OdU)@2lC?q%#^T_0x=eAl|CS*zn+Y_Z~9 z)Bpeft8?Ao|Lo)Z39}|2e`9z>AeT|`&*RD8ffE0X-`wxb;{5yg!M#}XSGPLe%!bKx9v~;J^7PzWMVj|JHvyz`NQlt)#KinD^i2 z4F(1ouimGt+-l>D{#|hE086rt^`{Q3vqsz^LYdEByjac*)z4ggTe~DWM4f$M%F) literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/tiles/GrassBluegrass0.png b/src/main/resources/assets/textures/tiles/GrassBluegrass0.png new file mode 100644 index 0000000000000000000000000000000000000000..6d61e41215508faa449a419120a6ccd79166bd5c GIT binary patch literal 1261 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 KMNUMnLSTa7hT$>* literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/tiles/GrassMeadow0.png b/src/main/resources/assets/textures/tiles/GrassMeadow0.png new file mode 100644 index 0000000000000000000000000000000000000000..221fb88b0269b0d0608acc34ff6f6f687d0062e2 GIT binary patch literal 7353 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 L2lE2c9g+V66={@@ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/tiles/GrassMeadow1.png b/src/main/resources/assets/textures/tiles/GrassMeadow1.png new file mode 100644 index 0000000000000000000000000000000000000000..7aff0be0a500176809e342dae3ca6f13fda9258c GIT binary patch literal 9044 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 A0{{R3 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/tiles/LowGrass.png b/src/main/resources/assets/textures/tiles/LowGrass.png deleted file mode 100644 index 2f3726f711014b8e6b6cd4b663bc78788ba2f1bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 448 zcmV;x0YCnUP)rHBor*Q#hU;C02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00AgTL_t(Y$L-ItOF~f;$MNq~ zB1@~MkP#^jCQS`yxHPm`e}HS$9}sPU&=52Q{Q*HW1cFmEX@h}-Bu-Hc)lm9WBBGR6 zsDoPXwppP=OWXZS_Z;pyKMp90q9}^;Uy|1e`PaXepT$w`pfk9CzSnu5mdXPSG$Lm=c5#L>3}lS9}2nJZfUQsGt@A0000rH8Ww|ozsdjr02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00J6GL_t(Y$L*0_OOs(7#(&Qq zpS@^vFKs^7Hj4&Hu%H*PgU$k@FW`}xeThI6j5-SX070dwD-Dbw%aDv95!VJ1+j@~` z%*}y0XK8!O>7Kg-aUdE>C!Oqfbo1xpy11?zs#K{`rOJO|Jp57|RIA%hFgiIZ0LEv> zE2cF@nSTlx2t25m+@HQD0NPsHq-TMrV)1vfqFc^p0JuGTb4Qb&;jaCg4Tbszz{H0M z0WcOA6MexxF%lXQw?=x!b}+z1}+ z)`Fd)EsxviqI~tJ`31aoFBy?$DU-%#vm?tgwMHYFrqOYsQ~K*f7L$!wJjTje zhPl`r!N?3PCoVFdO5!LwSS+MSW)diM3i)3J&U(+_ln!GpTQL+&yUceqc=P$SNV7x( zD(l4!HgYALjs{Yx6wRJy!k@zE4GKP=k4Q9vPA?NHennMP3`PSAdh*30CcU2amTMK? YKjn_o4iOM9H2?qr07*qoM6N<$f}58l2mk;8 diff --git a/src/main/resources/assets/textures/tiles/PurpleFlowers.png b/src/main/resources/assets/textures/tiles/PurpleFlowers.png deleted file mode 100644 index e118fdd8758a9431ba97926565e0c1b3517a2c77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 519 zcmV+i0{H!jP)oN6DoX>PZae zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00D1FL_t(Y$K_SQPQp+SoWDdP zAfzM}NJ`@8croh12vQOy9zAKI2ctj%krp8qL|$xOIe=j4dQ&lNp%9J6J-uW$yV;r9 zx4@iXDlvRpm<dJJ$M$+C3IJu z7uOdPniYiix7KRX!G=lzz;DCLyQo`^f%TXp*3w#dyb0l-N4FgG#C_?Im)gGV`B{e} zuN~sm`NYbKnq!eYK_O;5Q#RQohvE^82V?Nka*jwRJQ!ft!Jij+II(C~DAH0z1g*;eG5;0)}GO-~B=tl#lZgzT_@_P~aE zF?|Iyk~bTUBFdspBkPsqFL!|5O>>@;8q{NKF~=Py+w?1`eFIBm(DO4478?Kn002ov JPDHLkV1i7;(&YdE diff --git a/src/main/resources/assets/textures/tiles/TallGrass.png b/src/main/resources/assets/textures/tiles/TallGrass.png deleted file mode 100644 index ce41bcf0ba8f10dac05529d4c65d57a0396393bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8990 zcmV+(BjMbMP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3;uk|e2;t^c!%UV<^hau`M44tn|h9WalK$jYpi z`=l!>V{mgf2UPV83U1ba|G#bii~q`Fg9$O0R8xBRFVs+7|L#xwg!BFW@wsMy zK5o7)I3Du+^!LxS-sd+SkH21!!~1yu`MAmBy-#^>^j`Sf(CeKYzr4>Y?~S~>kK6Ze zQ{UIM@NGKpzdhW!9Q(cW``;n67&CG|?~GgC`iJjD@8b2(`o_<~cjukEk2W8D;(PG! z&ueGCe*JCnzJB{{?Vk2N?tdJ)f`2S7C~Sh)tr|`5MMn>sak=gPpe7 zZP)oZ>|lt&EtmP}+#m*etoZDz8!W$N;rX)LWncX?M929-)Vw0{H5Pl`x1RSKB<*~r z<(bZMGplI+{$>93;Q!Cp*Nyg8>RS7hueD-aPFce+6ghq8Sp>xHcTMA2-}7a@<<0Xg zu$~CUv&@AFwx{1)^k{$OmOpX!JTE@MJhwD#p6?A zy4oh!w%=jLop#=3*WJFN_D1z*)a-AO`}e5XH)@JlIM2(!qQ=8He{Nv~Cs8pYVlG%B zo)rNS+9_sFu^~7`PBD9`qbQ;yYBnl3(<)*_Ff8lhwqLRP6}f+nn~C8+iktge4%_!A&iq1N>A8(`x}%@zI!j~y#mnW8O&b%il~S*bO^rNzBg z%PXYvP#dMKkT=U&``Wv%Xwu%)avq)coN28x^LDHGl(r9pDGuPR7lnEN>ucq?TI3y^ zzIpDeQ8Z_Y2Gi}1X~vej<*j)jl+h|cx~cIxR@i-aN^cGQOC#D?b_=VqK08hy2tU|u zgR^PZV8_aiD|7YaN?7Zub0_B8%hDaXk}R??lc#N)yw+KMk+lyXVmNoMDeL?M|!a-CNz{W6U;=sVKDBVrVfj&UAN1lXVA1XWgVkL-6S-)Kj&2C$gMKWG11c%{i`z^k=2)N{pUW z%ux2Xd5_ko?L+K!G{w2H`ih_$u+(Z`RC4)gBY>c+66w?oLs)uhT&&ss&4YS2`Mvs7n(jrBP`G{#3L{e;U1=4`B~bT$ z!(r0-86{8ePgaX{QPo=ri&9DuX$L=^hw^>uUL=;@a0A!#{6>mZa~70h*vp4pn81=y zx{+j&s2T7)-UaXu5ldluYDSm=sZRLp)e@0HjHGu<1JbBYSDH*#?Fg^fTMj? z1QEV9!Jj_#8C{-n0c>q9a1Qd0$TMLVEJ4;!7B)7L2b~oG7D6?c;)b9yue1wD;?d$X zg=hL~Sia%;i#mwIl5SP&uq${v&(iPb{A>@^LJ}cTdYz8@fXKul`&5C0YCPi3cA!Q| zB|ktTk5V2P1i8ujkj3rfJxMiBQk}9|f|gO8(>HG{W$X#SO|y8?EZ&X7@}0GJE-^uVj6=c0nQ1RXU&4T49u=YvP~gGcejqt>x9 zk%8;qi~DDFN&sjNPSj-+OLro)QGE=zP{hGh5fLB*B}3{GO;OB98bFedziGft!kAY0 zAKM52*W-F)6_gsq8#qhBC60ugGR_MQSfxiYp+sbdikTJ0d_-bt#kccdDCTWJ@9zSe z+UpWGZbfY5&WQUuHytp4>;ho0O{CcoIJxawbU$KQg-ur2JQH}tOgFhlexFEy0^+am zbYKsR_&iQIp^qL-YXO2GE;6%EQ1~fpu4%B2M^8N~j6(e2=W_G$!_W?V?WYiAn=*f^ z4(6!?6i>{Iv~-iuRyMCzEsV~%hg@(;bFkV_KQf4tJyb0>(=Js&X235DM&tmwl6o~n zE|K`~Hj)V5!DxlcD?vbtYI=EPkz#+p%3`k(p&elABv<%E(cR>8@pFfNyUwzkOFL!% zd);Fkf1<{B(D39!HAGLV8Clmdg=);2R9`?Ual&^J`>+F3n`DOw9fUXq6Tb?E(rd=W zUJzI))(%&qhyYc}B(#QcB$J`ld@4{70-)J`3gyXxw~X^l6eSc4LY+b7BVW)H2&W() zmU4yH|HK@r{c$PGf3OxOlZ6U#A?T6So@!}%WKw^b4YIX?t*-LIWW4kJ@hr~(R8Hy$ z^GKXC35lPB2B?rtlJ^Xyop0QTY#{Nhzl@)1KhX2?{R=$Ln>|MgT^*z%Yyxn5M3DJX zL4kMJFlxqhFj%lMTPhzVE!K{Uay^SqMgM8`=G*j7A&&)Vm4K0e6(msCXk&Ki?8~%L z+C-sCt+#G3*u`ul_eMMOM(?LP*x1$2CxwL}Yd`91F1&N_L{WNR$L$hg2^RnIA}W5Qo({n6E^uCy6E3 zZsG0&;urIi^iwxtY{q)%1emwzIMn>#l+k*kTIDtHFj*dOxR zFaO;2=|Sr=9<7foG!l*+0O^9wGvoAFQqsht)bSlKvqwjCGgkqIl#p@S;c<)&2%bqG zF1eMsJV*^}D!j%L5L}3oWNst2K^a+?A~{Bs-45`y;z`Y_9x~H9Ot;g?;}JkUEDZ}w z!bWNA@Sxv8@^DImq(arICJ0J^7MW)00n@qU&#UfmW#O7%;yFh=CTW&rhbmE>=#W;- z7(-gHK8Pd>I&{lTp~U}9hcxeC`e-ZOj;t@{Xj~>Wr;;^`7_nmE*OV$Mh|zQRyfmfx zHKpvHmvo-ouk#^GPxKdba{SAqj6 zm8yPrp%`}{-HF+@5LZFBAemg%Vl$<)EOlT6D)OK2t3c@4$7O*qW-S0Kfd$IeYGrvv zeiA;1I&)8k$)`!UVHv?*Agpq}N`(x4QEe@mg?Qt(k(P`kVX%s?5C)>?9s8kj|}1sS@8u0g3`8?uRUJ0#3F zP3!tp;A>`1yn%*MD^=Mk0t6lFr^Ab~YzB zaHU{pRsf6A1!Ip-?!!;4lT{DQQm4p6*av2};c@;*fne7<9x<4HGngz;24no!F-yu| zoRU*gk~e(w>e`$o9|31PNJM+4%)Jxmi(7mkvki)fFt9K5PVT%t0$H6G>Uvg7nQjX zxB%}O{8p2zlO!s!s~0E7{HR0P7P%cjJuFICte{6W1M0gQU}w#m@HfB$v`ydy=jD}? zR&uiDMTGDPWE^jN1&kw}6WW?)o~+&iVtGwqINgqtdW~92a2U)4R9TtI2oXmE zT{oymEeo^?eH3fp5B`@zEB)l){K`RPAmSTHq2x3lK?Zf;hufSvQ-WEOA#ZL zPMi1jmF6PGS&eeK5$R{si^A_@;oq(ugN)uou*dXos!=9%F133}zh|q7J(3znE#V0; zwuoHvY;+P*oePsR;snq=y$#eh*@gF@-oE5{LCcL~{qt$Gf?u=Sk>nI`S;7 z*R%GMC+IY(eDz4=Sjl5DRXb5T21XUnIA@fk1|rdkZcT?`Thb1tGp$jWWPkA5P#XWB z$bU7ch(`o)0BQ04Jv~-JIH!PDhnA?$1i03Gi|(W=(Y$MTTKWnMLvj2;#f7kIhK>?k zr#=~~Jv5Y_tA6bVNsF8oPEa}b0u16HJZg|I<))T)=L+enWTpBoz6{bu5cdh7VFVsc z9xf)T;dJ*XE40Rdg1p(TM^hVREkHq&+#!f3B(2f z6juzd>rYsiu+|7En#DZYGkDa_)i_YkP;^l5C+C#ZssUOY2;AQ;ZEQc<)x_&wGk>@^ z9cU<6R7bMksY1f?O?M4|P@qai@9+Ji^!?(`Yfa5EiK4boHx|3SK7HBjagZM~6UNUq zL1cq>f4`d4KRa{`xJBbS&ccQ9SmYARKFQ<>D=)9!-02;&63q3K4v9l_F(e!7k4*xq z9Egl25ci|*nYx^6_Wu#|cg*ESOc?Etsawm>DOmDQVb3J3WF+88ZBa6_=pP}#c#g<3 zT0tf7CKji?0|;v3r-@RvnKqGIJ2##$Oee1vZlTSm+xd_LF(R38>OqPqGN5OTlRkEt zq2Q*hy$8niNyUB^_R~fU@a`H&1D=GMZ3%tAIA?cQGs^qv&KqAuUad+|Ua79~TfU7K}5J>K8N=XuU1~*EXezNQ( zP1eRhSl#xd_I`%MYo?~P(YXrDHnpEQ(17u7C$%HatCh-CA0I7NeUm9>YED0x;vAOCWZ{2h#8FPe`Hwl(w3`R&6WP5-w{=1cS)h+dIyMB}(X{MIKK_z9wi(4Fl9) zK5Ma^W&k3C4}|?MSK<-g)kxaTPlp|WLuwwJwlc_qkd>0!CZe)RjJh`2&!}TkA3l2M z3@L83vzhC8hj8{&63mJ}C%P7qHTKjN9!Oqf43^rKK<4dMoZ63T5rC|HSbf< zU*)Tg-mirG;}bLrg$btotta-I{pn`>n>sr3rYg6?Z4{z_Kl_3tp4`Z1XVCoG8npgN z386y0OGiosw(<5J$}tys8Goe&D`;`aX_A5wd`;2R(=PTMDQ&6migfSVrYzJ=RrakK z27=*~E+`buen|jsvS`js1>cCM;1#R^^KC1f+HFr=Wj<@T)l0I0nhI zMeT!%wvYuPY*?ihkPtlx&_59}P*;TPh}Ms+J!iCFx+Cf5jd?yKQ4pj9<5zF*;_PDf zQ*-IoyZhUfppM2N@9w|I+gN$lKGi1G62`&!U_V%xpc7$@_uRy5+ir^H@iM0j-0g7R z$}-F*&nSwXRo%6ly z5<9i%LWff0<0(i4c3?ypEX28Xb(0R%1e94C-6HUvB(oP1W!@&YQO}!~n_Cb%jGO0B zb`e3YYTBwBqdYx5 zj|D$4GW*%6JY1DWGB%Bkc-j`GM8gHeSNo@MqF#ZAIHiEtKl}v9YeM^rP0UXRRXqyWKaYhO`9%jODI#?h=FWPDh6D10)1i)?AfbKB& zpit}ThX6ADSoWCh1uzDx{#BcR6Sr(kIcaMo4Uh9cnQ4ny8@kmD?VAJ?)ln+vghf+u z(8;-kQ~BrMW|qR$hL=bvp3@`i`cKlKE`TO-`JRMLTXsVO zbiQe_D;E_OuNeyyZY=XyYaA_r?E4jaA|IHWT^r3hi8)IL<2AGdF?Bj=Vo}Cwbaza+ zNg}WxyOrvu)sVHPQ&Dl*4UM=KZSGJsjm1oWX@DT{H(ur!$!}ntOE24fDYOwfivoXg4aHZ6s50LZORTQzb9!s1aUS+R zNz#!0&pB?Ss(trl`j0)C4)P!rTPeRc|nBb|`0H*tdL(%Ho zIx?oIs{q(6R;D5a%>goKld??`cMuG2x)d?po~LeZ01io~Ay@ldBOqRQ#@q(+2ugb<`WV zo%6fOprrkQn*J8wGIk0R#q@q-}RN1w{C@ZH1DN@(U%Wn%z zlw(G`wg+o1q$CWf><@M2~HrwVE0(vH?e>_o!Y&SVhEW^irA-K5+iU;h=iWd=z*_Uj5;*bR!4zq zx)>=A|ICVXYy{b};xt401r z=QAi)bU^n#x+^h1u5og9-L^f)Sy}O}GJ{N!%P*!ay5Bi|miuRY=mAz2aL=&ziN>_W79+wA6|k zIy$vS9lH(m!gjDXs=DfESvUB>$NM63sXz=U^~u&s0#XtlR6Q>z+-|DdNhxas^BTaZ z?PSW`EcLi_vLHxjosJ7Lo!V^rr?DWh&QV`VM<-D~C5)7d<}_4UHz=*E_tDS_%TbDn7tpYl~}u9Q)@6 zNf*_@`)T8EayPIU*@lyWj=?%8TD_C04$6-D00GM)+n}v@V7~08&0jqBMewBkU?q)t zcRIq7+V{-5N)Z{_zxu~RlJ)W;c8ODC1SB1s~K+~3om+8_Qp z3H)aUCetz2dzkPR#Hw#W97~J&Q7>^nsJ*2mwL-P^0z4`@A+RJMqE4~P_8QL=qISsw zGf;3=IvGtdN?!G{$PKTC zi4xK-`@I{8#X35q_5eHeor4sa9Z|A(aa>K4*XL6xjxoPDlMJJ(LPN^ z_l_igXt9MjXIM%{N~C&E=;3k^n{F+9*CF?5-g8@&+7P#SCZOJ|ui^c0N)PgU=K}`M zn>X6+1{QevzC8|Gy8*q_5|x?P3;=|#H%7I9H_IzKQ4+VojjPgL400>#a4-NdQo#~Z z+1UtMzCz-(p>vs`>~u5u4GU-tgxzDTPC_93{D6je&Spw_&-m1T^x06>61x9#eW-7P zsXvxzJr()u8RmV8P9;z6 z<@&e6hdbwH+X01@&gnnvJ$E?Fp!!-E2${Kx2MUJNa$lVeyt?&=G|=^{>C*wkQ=bk( z;#QPa(GHo9K73_-gMT*5qJH+fQ>x7xkCL$Z+!#!uHIX#8c z=+_*Y60AN(RVgxz{5hG;sxx}vj@rr;8EY5f0z`p~rtZl(6~LQfNFBzTS1xC?pWbad z8oqD$@xV32uI%6sBPrDI1GH!PO@qyz z{)v?gkJZJ!nh5dpR5i*ds;-Y$G<|*qzPQD9@XDcc6Z##hxXs;rBvj{z^sxc(*|ZJz zW|0G2C-ju&tfE)y65U_OL7uK7H6m~_uwM`FYGJamC!I%c)A+uIKGVP&r+Q=L0z5nx=?{Cr0HUPGnOam*>pbM4lbyk|ek*6Lw zEtF2bAEgWaen5&aO>;^o&94o<*W7^~Cwaa!dXUP)IYp_G0t+utrRzA$QQyJH>Fl%b zjphRuQ6MF*XQl7J3k_J9Q{^C8w$-UX4zeE5jSgXD)<~-6cA)F|m=_<094C~k1Lc>-DH1z6THPTZ zi`C&u6qiM@b#UZRAmI6abm&pa<+E+NgZf(By%L%K0qqWX<>Cz)n*aa+24YJ`L;&Id z;sD}LHK zL_t(Y$F)_@Q(ILO{_aciUdWG^XE7nA8IZ!rO#R8ig_1C%n^HGjSjw)pn|48A)BYuG zvw)4TP@tt%bhI#I)g(CTptOv&Ob08K3Dg8AAwOR762fu8-0OP~m~OnQ``&%;eBb%b zcg|%*g#U9%e3MKiF%}!Opndh*mjnRAQ=imikxV6#OeJ3o007qhS+g8IUw^(E=0W*Ndk2{LIh)A> z06zQvQvv{8*K5}xpUY!ta*zNZIuWHS=dLmU_~z%Y2>^njU`-jDTAKg>dO^qe?h9;c z?k?T_X@WR=0nq)|#H2u8;jPJROzL$KsK7Nfnss|svdxq`H zAk+|os;K~gO1ZL+X?4450rC307?~cXwP$OHPDDvoWQ%;wZO!{_n$P6{06RN7qR<@F zC>cd)*)+^z~e3eP{aE=K7`x7`=6a4(x;3*;xcbL2!BA^uNVMriaB3 zW@nl0?DDu?tkD3VkSkzhdYDvA#e>v+;!e4E`Vuor2F`|iSx@I##)I1IHp~Be4Iu#l zZ;<#xj5=GxLd&-sI+)^A1aq&?YpF$iDMoIOTLe=z6`d_%X0D?I0GUh%JJnt7r{?aG zRH9HqsjiGzQ@J`vCyqwg}_1$?Nl? zujewe04zUQ1^_5dMFeiGYhzD}f0DV09GuCp8@9>;erN`%1C0K&&3qJb*q3gQbf zGG97&yBz?~@@mV$88~DI_FgC+)dNYAz!*b5o8QMUpUp#7WMng0*lae0TOzC`K)5Z! z_|)XtsG16`UV}q+An{k+G9{1rkBF;M1lv=CWGab&0an%4goUf<2mk;807*qoM6N<$ Ef(NEM*Z=?k diff --git a/src/main/resources/assets/textures/tiles/TinyDandelionFlowers.png b/src/main/resources/assets/textures/tiles/TinyDandelionFlowers.png deleted file mode 100644 index 35f651c32d37762df94046375ee0face811ec567..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4380 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 W7`x7?IKtlm0000oN5GGye zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00FW|L_t(Y$Hi4^OXE-wJ^#`b ze1QdZcd-f)f0!sJYO&U$3(IP)Rx!0yOInjQ-lVmTQhNNb1fzMh#)|VTcbIeUIcH`9 z3>i)_g)a-|dJeAbqO>~}$Z0tl9;kLY4o3t(*X%&f)>G(7hyJsbU4e1;dO_RJ842Df z=GcGiL)#92QMXwmNt)+*#~eI1^0X zR|=uvzc*hQtz-u4tqRl0jJ8f@Ki4S>YY)->oTXry*8i^g6VE~mW4U-Ba78e`-ij?= z%?d1A5avUtQHeDl>8;`V+4G@!_4f@RNjkR|Oe9~oWyBV$i>c(^v<;mkV=t(dtEeAO z4hB=D$*OqyJu$+&lugVeY#9PJwm-*MW3fqnmL6Y^t zUXbCaG)+9s9#j8!zuSkl|G}HjS*Y&fV}g5`{iW*DD4_W}A#hk|d7 Y7d)&d7qy-G;{X5v07*qoM6N<$f+jHjWB>pF diff --git a/src/main/resources/assets/textures/tiles/YellowFlowers.png b/src/main/resources/assets/textures/tiles/YellowFlowers.png deleted file mode 100644 index 3f7b8bc71bb04850106c5568e0eba3a22a2bef1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9945 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 XJ**CxP$kOe00000NkvXXu0mjfAyzIm From c04894a0c9348e3700c8a11439db52dd59fe3ded Mon Sep 17 00:00:00 2001 From: opfromthestart Date: Sun, 24 Oct 2021 20:09:11 -0400 Subject: [PATCH 37/49] Finally made this I think its pretty good, but I cant think very well rn. --- docs/ProgressiaRegion.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 docs/ProgressiaRegion.md diff --git a/docs/ProgressiaRegion.md b/docs/ProgressiaRegion.md new file mode 100644 index 0000000..2afea24 --- /dev/null +++ b/docs/ProgressiaRegion.md @@ -0,0 +1,14 @@ +# Progressia Region File +## Description +The .progressia_region file type is used for all region files in the game Progressia. Each region file contains a cube of 16x16x16 chunks. +## Header +The header of the file is 16,400 bytes. Every file starts with the string "PROG", followed with the three integer values of the region position, in region coordinates. After this, there is exactly 16KiB of space in the header, which stores the offsets to the chunks' data. This space holds an integer, 4 bytes, for each chunk in the region. The integer value starts at 0 for every chunk, and is changed to the location of the chunk data once created. These are indexed in order by flattening the 3D in-chunk coordinates into a number between 0 and 4095 according to the formula $n=256x+16y+z$, where the offset of the chunk at (x,y,z) is n. To convert from this offset value to the offset in bytes, use $d=16400+64*n$. +## Sectors +Sectors are what is used to store chunk data, and are not linear, but are followed until they reach an ending block. Each is 64 bytes, which is used in the header section to find the byte offset. Each sector starts with a identification byte, followed by the sector data. + + 0. Ending - This sector is empty, and marks the end of the chunk data (This may change in the future. + 1. Data - This sector contains chunk data for a single chunk. The second byte of this sector contains a counter byte, which is a form of "checksum" to make sure that the program is reading the proper sectors in order. This starts at 0 for the first data sector and increments by one for each new data sector. + 2. Partition Link - This sector only contains another offset value, which is where the next sector is. This allows for infinite chunk size, avoiding "chunk dupes" as were present in Minecraft without reverting any chunks. + 3. Bulk Data - These would be used for many chunks in the same region that contain exactly the same data, eg all solid chunks underground. Exists so the program knows not to overwrite them, and just make new chunk data if modified. Not yet implemented. + +> Written with [StackEdit](https://stackedit.io/). \ No newline at end of file From 4b10dc82edfc1a21294fa0853f37ffddf61be05f Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Sun, 31 Oct 2021 16:19:21 +0300 Subject: [PATCH 38/49] Improved formatting and phrasing --- docs/ProgressiaRegion.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/ProgressiaRegion.md b/docs/ProgressiaRegion.md index 2afea24..b3404e1 100644 --- a/docs/ProgressiaRegion.md +++ b/docs/ProgressiaRegion.md @@ -1,14 +1,12 @@ # Progressia Region File ## Description -The .progressia_region file type is used for all region files in the game Progressia. Each region file contains a cube of 16x16x16 chunks. +The `.progressia_region` file type is used for all region files in the game Progressia. Each region file contains a cube of 16x16x16 chunks. ## Header -The header of the file is 16,400 bytes. Every file starts with the string "PROG", followed with the three integer values of the region position, in region coordinates. After this, there is exactly 16KiB of space in the header, which stores the offsets to the chunks' data. This space holds an integer, 4 bytes, for each chunk in the region. The integer value starts at 0 for every chunk, and is changed to the location of the chunk data once created. These are indexed in order by flattening the 3D in-chunk coordinates into a number between 0 and 4095 according to the formula $n=256x+16y+z$, where the offset of the chunk at (x,y,z) is n. To convert from this offset value to the offset in bytes, use $d=16400+64*n$. +The header of the file is 16 400 bytes. Every file starts with the string byte sequence `\x50\x52\x4F\x47` (UTF-8 for `PROG`), followed with the three integer values of the region position, in region coordinates. After this, there is exactly 16KiB of space in the header, which stores the offsets to the chunks' data. This space holds an integer, 4 bytes, for each chunk in the region. The integer value starts at 0 for every chunk, and is changed to the location of the chunk data once created. These are indexed in order by flattening the 3D in-chunk coordinates into a number between 0 and 4095 according to the formula `offset = 256*x+ 16*y + z` for chunk at (x, y, z). To convert from this offset value to the offset in bytes, use `byte_offset = 16400 + 64*n`. ## Sectors Sectors are what is used to store chunk data, and are not linear, but are followed until they reach an ending block. Each is 64 bytes, which is used in the header section to find the byte offset. Each sector starts with a identification byte, followed by the sector data. 0. Ending - This sector is empty, and marks the end of the chunk data (This may change in the future. 1. Data - This sector contains chunk data for a single chunk. The second byte of this sector contains a counter byte, which is a form of "checksum" to make sure that the program is reading the proper sectors in order. This starts at 0 for the first data sector and increments by one for each new data sector. 2. Partition Link - This sector only contains another offset value, which is where the next sector is. This allows for infinite chunk size, avoiding "chunk dupes" as were present in Minecraft without reverting any chunks. - 3. Bulk Data - These would be used for many chunks in the same region that contain exactly the same data, eg all solid chunks underground. Exists so the program knows not to overwrite them, and just make new chunk data if modified. Not yet implemented. - -> Written with [StackEdit](https://stackedit.io/). \ No newline at end of file + 3. Bulk Data - These would be used for many chunks in the same region that contain exactly the same data, e.g. all solid chunks underground. Exists so the program knows not to overwrite them, and just make new chunk data if modified. Not yet implemented. \ No newline at end of file From efc6a8ecd05b61dfc20448d660e201f03de1ab4c Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Fri, 19 Nov 2021 21:26:04 +0300 Subject: [PATCH 39/49] Hastily added pine trees and hazel bushes - Added ShapePrototype wrapper for ShapePart batch creation - Added pine trees and hazel bushes - Leaves with custom block models - Improved tree generator --- .../client/graphics/model/ShapeParts.java | 2 +- .../client/graphics/model/ShapePrototype.java | 248 ++++++++++++++++++ .../windcorp/progressia/test/TestContent.java | 9 +- .../test/gen/feature/TestBushFeature.java | 8 +- .../test/gen/feature/TestTreeFeature.java | 41 +-- .../test/trees/BlockRenderLeavesHazel.java | 99 +++++++ .../test/trees/BlockRenderLeavesPine.java | 106 ++++++++ .../assets/textures/blocks/LeavesHazel.png | Bin 0 -> 408 bytes .../assets/textures/blocks/LeavesPine.png | Bin 0 -> 6521 bytes .../assets/textures/blocks/LogSide.png | Bin 7213 -> 6976 bytes .../assets/textures/blocks/LogTop.png | Bin 8247 -> 6645 bytes 11 files changed, 493 insertions(+), 20 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/client/graphics/model/ShapePrototype.java create mode 100644 src/main/java/ru/windcorp/progressia/test/trees/BlockRenderLeavesHazel.java create mode 100644 src/main/java/ru/windcorp/progressia/test/trees/BlockRenderLeavesPine.java create mode 100644 src/main/resources/assets/textures/blocks/LeavesHazel.png create mode 100644 src/main/resources/assets/textures/blocks/LeavesPine.png diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeParts.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeParts.java index 4030249..807fcda 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeParts.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeParts.java @@ -153,6 +153,6 @@ public class ShapeParts { height, inner ); - } + } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapePrototype.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapePrototype.java new file mode 100644 index 0000000..f2cc631 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapePrototype.java @@ -0,0 +1,248 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.client.graphics.model; + +import java.nio.ShortBuffer; +import java.util.Objects; + +import glm.mat._3.Mat3; +import glm.mat._4.Mat4; +import glm.vec._2.Vec2; +import glm.vec._3.Vec3; +import glm.vec._4.Vec4; +import ru.windcorp.progressia.client.graphics.Colors; +import ru.windcorp.progressia.client.graphics.model.ShapeRenderProgram.VertexBuilder; +import ru.windcorp.progressia.client.graphics.texture.Texture; +import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; +import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram.WRPVertexBuilder; +import ru.windcorp.progressia.common.util.StashingStack; +import ru.windcorp.progressia.common.util.VectorUtil; + +public class ShapePrototype { + + private final ShapeRenderProgram program; + + private Texture texture; + + private final Vec3[] positions; + private final Vec4[] colorMultipliers; + private final Vec2[] textureCoords; + private final Vec3[] forcedNormals; + + private ShortBuffer indices; + private ShortBuffer flippedIndices = null; + + protected static final int TRANSFORM_STACK_SIZE = 64; + private final StashingStack transformStack = new StashingStack<>( + TRANSFORM_STACK_SIZE, + Mat4::new + ); + + public ShapePrototype( + ShapeRenderProgram program, + Texture texture, + Vec3[] positions, + Vec4[] colorMultipliers, + Vec2[] textureCoords, + Vec3[] forcedNormals, + ShortBuffer indices + ) { + this.program = Objects.requireNonNull(program, "program"); + this.texture = texture; + this.indices = Objects.requireNonNull(indices, "indices"); + + Objects.requireNonNull(positions, "positions"); + Objects.requireNonNull(colorMultipliers, "colorMultipliers"); + Objects.requireNonNull(textureCoords, "textureCoords"); + + if (forcedNormals != null && !(program instanceof WorldRenderProgram)) { + throw new IllegalArgumentException("Cannot force normals on non-WorldRenderPrograms cuz javahorse stupiddd"); + } + + if (forcedNormals == null) { + forcedNormals = new Vec3[positions.length]; + } + + this.positions = positions; + this.colorMultipliers = colorMultipliers; + this.textureCoords = textureCoords; + this.forcedNormals = forcedNormals; + + if (positions.length != colorMultipliers.length) { + throw new IllegalArgumentException("positions.length (" + positions.length + ") != colorMultipliers.length (" + colorMultipliers + ")"); + } + + if (positions.length != textureCoords.length) { + throw new IllegalArgumentException("positions.length (" + positions.length + ") != textureCoords.length (" + textureCoords + ")"); + } + + if (positions.length != forcedNormals.length) { + throw new IllegalArgumentException("positions.length (" + positions.length + ") != forcedNormals.length (" + forcedNormals + ")"); + } + + transformStack.push().identity(); + } + + public ShapePart build() { + VertexBuilder builder = program.getVertexBuilder(); + + Vec3 transformedPosition = new Vec3(); + + for (int i = 0; i < positions.length; ++i) { + + transformedPosition.set(positions[i]); + if (transformStack.getSize() > 1) { + VectorUtil.applyMat4(transformedPosition, transformStack.getHead()); + } + + if (forcedNormals[i] != null && builder instanceof WRPVertexBuilder) { + ((WRPVertexBuilder) builder).addVertex( + transformedPosition, colorMultipliers[i], textureCoords[i], forcedNormals[i] + ); + } else { + builder.addVertex(transformedPosition, colorMultipliers[i], textureCoords[i]); + } + } + + return new ShapePart(texture, builder.assemble(), indices); + } + + public ShapePrototype apply(Mat4 transform) { + for (Vec3 vector : positions) { + VectorUtil.applyMat4(vector, transform); + } + return this; + } + + public ShapePrototype apply(Mat3 transform) { + for (Vec3 vector : positions) { + transform.mul(vector); + } + return this; + } + + public Mat4 push() { + Mat4 previous = transformStack.getHead(); + return transformStack.push().set(previous); + } + + public ShapePrototype pop() { + transformStack.pop(); + return this; + } + + public ShapePrototype setTexture(Texture texture) { + this.texture = texture; + return this; + } + + public ShapePrototype deleteTexture() { + this.texture = null; + return this; + } + + public ShapePrototype resetColorMultiplier() { + for (Vec4 color : colorMultipliers) { + color.set(Colors.WHITE); + } + return this; + } + + public ShapePrototype addColorMultiplier(Vec4 color) { + for (Vec4 c : colorMultipliers) { + c.mul(color); + } + return this; + } + + public ShapePrototype flip() { + ShortBuffer tmp = indices; + indices = flippedIndices; + flippedIndices = tmp; + + if (indices == null) { + int length = flippedIndices.limit(); + indices = ShortBuffer.allocate(length); + for (int i = 0; i < length; ++i) { + indices.put(i, flippedIndices.get(length - i - 1)); + } + } + + return this; + } + + public ShapePrototype makeDoubleSided() { + int length = indices.limit(); + ShortBuffer newIndices = ShortBuffer.allocate(length * 2); + + for (int i = 0; i < length; ++i) { + newIndices.put(i, indices.get(i)); + } + for (int i = 0; i < length; ++i) { + newIndices.put(i + length, indices.get(length - i - 1)); + } + + indices = flippedIndices = newIndices; + + return this; + } + + public static ShapePrototype unitSquare(Texture texture, Vec4 color, ShapeRenderProgram program) { + return new ShapePrototype( + program, + texture, + new Vec3[] { + new Vec3(0, 0, 0), + new Vec3(0, 1, 0), + new Vec3(1, 0, 0), + new Vec3(1, 1, 0) + }, + new Vec4[] { + new Vec4(color), + new Vec4(color), + new Vec4(color), + new Vec4(color) + }, + new Vec2[] { + new Vec2(0, 0), + new Vec2(0, 1), + new Vec2(1, 0), + new Vec2(1, 1) + }, + null, + ShortBuffer.wrap(new short[] {3, 1, 0, 2, 3, 0}) + ); + } + + public static ShapePrototype unitSquare(Texture texture, Vec4 color) { + return unitSquare(texture, color, WorldRenderProgram.getDefault()); + } + + public static ShapePrototype unitSquare(Texture texture) { + return unitSquare(texture, Colors.WHITE, WorldRenderProgram.getDefault()); + } + + public static ShapePrototype unitSquare(Vec4 color) { + return unitSquare(null, color, WorldRenderProgram.getDefault()); + } + + public static ShapePrototype unitSquare() { + return unitSquare(null, Colors.WHITE, WorldRenderProgram.getDefault()); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java index e027cef..c2444d2 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java @@ -65,6 +65,8 @@ import ru.windcorp.progressia.server.world.tile.*; import ru.windcorp.progressia.test.Flowers.FlowerVariant; import ru.windcorp.progressia.test.Rocks.RockType; import ru.windcorp.progressia.test.gen.TestGravityModel; +import ru.windcorp.progressia.test.trees.BlockRenderLeavesHazel; +import ru.windcorp.progressia.test.trees.BlockRenderLeavesPine; public class TestContent { @@ -131,7 +133,7 @@ public class TestContent { register(new BlockLogic("Test:Log")); register(new BlockData("Test:TemporaryLeaves")); - register(new BlockRenderTransparentCube("Test:TemporaryLeaves", getBlockTexture("TemporaryLeaves"))); + register(new BlockRenderLeavesHazel("Test:TemporaryLeaves", getBlockTexture("LeavesHazel"))); // Sic, using Glass logic for leaves because Test register(new TestBlockLogicGlass("Test:TemporaryLeaves")); @@ -142,6 +144,11 @@ public class TestContent { register(new BlockData("Test:Tux")); register(new TestBlockRenderTux("Test:Tux")); register(new BlockLogic("Test:Tux")); + + register(new BlockData("Test:LeavesPine")); + register(new BlockRenderLeavesPine("Test:LeavesPine", getBlockTexture("LeavesPine"))); + // Sic, using Glass logic for leaves because Test + register(new TestBlockLogicGlass("Test:LeavesPine")); BlockDataRegistry.getInstance().values().forEach(PLACEABLE_BLOCKS::add); PLACEABLE_BLOCKS.removeIf(b -> placeableBlacklist.contains(b.getId())); diff --git a/src/main/java/ru/windcorp/progressia/test/gen/feature/TestBushFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestBushFeature.java index b559582..84328bd 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/feature/TestBushFeature.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestBushFeature.java @@ -38,10 +38,12 @@ public class TestBushFeature extends MultiblockVegetationFeature { Vec3i center = context.getLocation().add_(0, 0, 1); - context.setBlock(center, trunk); - context.setBlock(center.add_(0, 0, 1), leaves); + if (size > 0.8) { + context.setBlock(center, trunk); + context.setBlock(center.add_(0, 0, 1), leaves); + } - iterateBlob(center, stretch(size, 1.3, 2.5), stretch(size, 0.6, 1.5), 0.7, 2, p -> { + iterateBlob(center, stretch(size, 0.5, 2.5), stretch(size, 0.6, 1.5), 0.7, 2, p -> { setLeaves(context, p, leaves); }); } diff --git a/src/main/java/ru/windcorp/progressia/test/gen/feature/TestTreeFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestTreeFeature.java index 611ec07..72becc1 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/feature/TestTreeFeature.java +++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestTreeFeature.java @@ -24,33 +24,44 @@ import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; public class TestTreeFeature extends MultiblockVegetationFeature { - + private final BlockData trunk = BlockDataRegistry.getInstance().get("Test:Log"); - private final BlockData leaves = BlockDataRegistry.getInstance().get("Test:TemporaryLeaves"); + private final BlockData leaves = BlockDataRegistry.getInstance().get("Test:LeavesPine"); public TestTreeFeature(String id, SurfaceFloatField selector) { - super(id, selector, 10 * 10); + super(id, selector, 7 * 7); } - + @Override protected void grow(SurfaceBlockContext context, double selectorValue) { - + Vec3i start = context.getLocation().add_(0, 0, 1); Vec3i center = start.add_(0); double size = selectorValue * randomDouble(context, 0.8, 1.2); - - int height = (int) stretch(size, 3, 7); + double volume = stretch(size, 2.5, 1); + + int height = (int) stretch(size, 8, 12); for (; center.z < start.z + height; ++center.z) { context.setBlock(center, trunk); } - - double branchHorDistance = 0; + --center.z; + + iterateBlob(center, 1.5 * volume, 1.75, 0.5, 3, p -> { + setLeaves(context, p, leaves); + }); + + int branchCount = 1 + context.getRandom().nextInt(2) + (int) (stretch(size, 0, 4)); + + for (int i = 0; i < branchCount; ++i) { - do { - double branchSize = 0.5 + randomDouble(context, 1, 2) * size; double branchHorAngle = randomDouble(context, 0, 2 * Math.PI); - int branchVertOffset = (int) randomDouble(context, -2, 0); + double branchHorDistance = randomDouble(context, 0.7, 1.5) * volume; + + int branchVertOffset = (int) randomDouble(context, -height / 3.0, -height / 1.5); + + double branchSize = randomDouble(context, 1, 2) * volume; + double branchHeight = 1.5; Vec3i branchCenter = center.add_( (int) (Math.sin(branchHorAngle) * branchHorDistance), @@ -58,12 +69,12 @@ public class TestTreeFeature extends MultiblockVegetationFeature { branchVertOffset ); - iterateBlob(branchCenter, 1 * branchSize, 2.3 * branchSize, 0.5, 3, p -> { + iterateBlob(branchCenter, branchSize, branchHeight, 0.5, 3, p -> { setLeaves(context, p, leaves); }); - branchHorDistance = randomDouble(context, 0.7, 1.5); - } while (context.getRandom().nextInt(8) > 1); + } + } } diff --git a/src/main/java/ru/windcorp/progressia/test/trees/BlockRenderLeavesHazel.java b/src/main/java/ru/windcorp/progressia/test/trees/BlockRenderLeavesHazel.java new file mode 100644 index 0000000..9626b16 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/trees/BlockRenderLeavesHazel.java @@ -0,0 +1,99 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test.trees; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Random; +import java.util.function.Consumer; + +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.client.graphics.backend.Usage; +import ru.windcorp.progressia.client.graphics.model.Renderable; +import ru.windcorp.progressia.client.graphics.model.Shape; +import ru.windcorp.progressia.client.graphics.model.ShapePart; +import ru.windcorp.progressia.client.graphics.model.ShapePrototype; +import ru.windcorp.progressia.client.graphics.texture.Texture; +import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; +import ru.windcorp.progressia.client.world.block.BlockRender; +import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerSimple.BlockOptimizedSimple; +import ru.windcorp.progressia.common.world.DefaultChunkData; + +public class BlockRenderLeavesHazel extends BlockRender implements BlockOptimizedSimple { + + private final Texture texture; + + public BlockRenderLeavesHazel(String id, Texture texture) { + super(id); + this.texture = texture; + } + + @Override + public void getShapeParts(DefaultChunkData chunk, Vec3i bic, Consumer output) { + ShapePrototype sp = ShapePrototype.unitSquare(texture).makeDoubleSided(); + sp.push().translate(bic.x, bic.y, bic.z); + + Random random = new Random(chunk.getX() ^ bic.x); + random.setSeed(random.nextLong() ^ chunk.getY() ^ bic.y); + random.setSeed(random.nextLong() ^ chunk.getZ() ^ bic.z); + + final float angle = (float) (Math.PI / 4); + + sp.push().translate(0, 0, random.nextFloat() * 0.5f) + .rotateZ(random.nextFloat() * Math.PI) + .rotateX(-0.3f + random.nextFloat() * 0.6) + .scale(1.3f); + + sp.push().translate(0, 0, -0.5f).rotateX(angle).translate(-0.5f, -0.5f, 0); + output.accept(sp.build()); + sp.pop(); + + sp.push().translate(0, 0, -0.5f).rotateX(-angle).translate(-0.5f, -0.5f, 0); + output.accept(sp.build()); + sp.pop(); + + sp.push().translate(0, 0, -0.5f).rotateY(angle).translate(-0.5f, -0.5f, 0); + output.accept(sp.build()); + sp.pop(); + + sp.push().translate(0, 0, -0.5f).rotateY(-angle).translate(-0.5f, -0.5f, 0); + output.accept(sp.build()); + sp.pop(); + + sp.pop(); + } + + @Override + public Renderable createRenderable(DefaultChunkData chunk, Vec3i blockInChunk) { + Collection parts = new ArrayList<>(6); + + getShapeParts(chunk, blockInChunk, parts::add); + + return new Shape( + Usage.STATIC, + WorldRenderProgram.getDefault(), + parts.toArray(new ShapePart[parts.size()]) + ); + } + + @Override + public boolean needsOwnRenderable() { + return false; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/trees/BlockRenderLeavesPine.java b/src/main/java/ru/windcorp/progressia/test/trees/BlockRenderLeavesPine.java new file mode 100644 index 0000000..32f98b5 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/trees/BlockRenderLeavesPine.java @@ -0,0 +1,106 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test.trees; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Random; +import java.util.function.Consumer; + +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.client.graphics.Colors; +import ru.windcorp.progressia.client.graphics.backend.Usage; +import ru.windcorp.progressia.client.graphics.model.Renderable; +import ru.windcorp.progressia.client.graphics.model.Shape; +import ru.windcorp.progressia.client.graphics.model.ShapePart; +import ru.windcorp.progressia.client.graphics.model.ShapePrototype; +import ru.windcorp.progressia.client.graphics.texture.Texture; +import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; +import ru.windcorp.progressia.client.world.block.BlockRender; +import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerSimple.BlockOptimizedSimple; +import ru.windcorp.progressia.common.world.DefaultChunkData; + +public class BlockRenderLeavesPine extends BlockRender implements BlockOptimizedSimple { + + private final Texture texture; + + public BlockRenderLeavesPine(String id, Texture texture) { + super(id); + this.texture = texture; + } + + @Override + public void getShapeParts(DefaultChunkData chunk, Vec3i bic, Consumer output) { + Random random = new Random(chunk.getX() ^ bic.x); + random.setSeed(random.nextLong() ^ chunk.getY() ^ bic.y); + random.setSeed(random.nextLong() ^ chunk.getZ() ^ bic.z); + + ShapePrototype sp = ShapePrototype.unitSquare(texture).makeDoubleSided(); + sp.push().translate( + bic.x + random.nextFloat() * 0.3f - 0.15f, + bic.y + random.nextFloat() * 0.3f - 0.15f, + bic.z + ); + + final float angle = 0.5f; + + for (float offset : new float[] { -0.25f, -0.75f }) { + sp.push().translate(0, 0, offset + random.nextFloat() * 0.5f) + .rotateZ(-0.3f + random.nextFloat() * 0.6) + .rotateX(-0.3f + random.nextFloat() * 0.6); + + sp.push().translate(0, 0, -0.3f).rotateX(angle).translate(-0.5f, -0.5f, 0.5f); + output.accept(sp.build()); + sp.pop(); + + sp.push().translate(0, 0, -0.3f).rotateX(-angle).translate(-0.5f, -0.5f, 0.5f); + output.accept(sp.build()); + sp.pop(); + + sp.push().translate(0, 0, -0.3f).rotateY(angle).translate(-0.5f, -0.5f, 0.5f); + output.accept(sp.build()); + sp.pop(); + + sp.push().translate(0, 0, -0.3f).rotateY(-angle).translate(-0.5f, -0.5f, 0.5f); + output.accept(sp.build()); + sp.pop(); + + sp.pop(); + sp.addColorMultiplier(Colors.GRAY_A); + } + } + + @Override + public Renderable createRenderable(DefaultChunkData chunk, Vec3i blockInChunk) { + Collection parts = new ArrayList<>(6); + + getShapeParts(chunk, blockInChunk, parts::add); + + return new Shape( + Usage.STATIC, + WorldRenderProgram.getDefault(), + parts.toArray(new ShapePart[parts.size()]) + ); + } + + @Override + public boolean needsOwnRenderable() { + return false; + } + +} diff --git a/src/main/resources/assets/textures/blocks/LeavesHazel.png b/src/main/resources/assets/textures/blocks/LeavesHazel.png new file mode 100644 index 0000000000000000000000000000000000000000..ec12d2db91219e8965ad3cf09cd405552fb2b8f1 GIT binary patch literal 408 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;w=>VS)S3yRGxSW9GqTsBG(89Xt z^47$@X8ErH3%oqwT1C=qB1o;IsI6S+N2IO!SctjR6Fz6|RFk{71`!b*)dx@v7 zEBjM!VF79ODWM`efI^Zbt`Q~9`MJ5Nc_j?aMX8A;sVNHOnI#zt?w-B@;f;LaKt=aF zT^vIsF6&O%?RVHgz_tJS?*hpmOp~85`z%`0mm+;@s{9gJ#fJgAiZp^1e&nVF=9!k4 zq&>@W`08~!wrx`9@{qQ^-q>gf*SX2vn(T3he2#mBZ=18IIo;-c+NAX^Hy3-{|KUIB z;enEF5{gl&%~xF{~S^j6%LF8?s`cxaZ-vh?lDeFVdQ&MBb@06hDg$^ZZW literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/blocks/LeavesPine.png b/src/main/resources/assets/textures/blocks/LeavesPine.png new file mode 100644 index 0000000000000000000000000000000000000000..f01e1272c1bc4b150b434fdfadb93d5a1cc4de14 GIT binary patch literal 6521 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 KMNUMnLSTXhkb}wq literal 7213 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 diff --git a/src/main/resources/assets/textures/blocks/LogTop.png b/src/main/resources/assets/textures/blocks/LogTop.png index fb61de591b093117c175c363f463e61dfa1db4ab..99adc8997c407be90898523bab85ff15a099dc93 100644 GIT binary patch delta 6616 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 Ww^jOkR5A)s1Y!o3gV9Vo(DM6p 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 Z^FLzu9_^002ovPDHLkV1kN}E9(FN From b4ff5114bdcf214b3cd5dd8dcdf2271676bc946e Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Wed, 8 Dec 2021 18:06:30 +0300 Subject: [PATCH 40/49] Refactored input event pipeline - Merged Input functionality into InputEvent; removed Input - InputEvents can now be consumed directly - Removed Input.Target; functionality moved into InputBus - Refactored GUI input event handling - Optimized and reduced recursion by unrolling recursion - All input events are now delivered to all components - Filtering occurs at listener level - Refactored InputBus - Listeners may override former Input.Target logic - Improved registration method - Added exception handling - Improved KeyMatcher - Removed builder in favour of copying with modifications - Added String parsing - Added KeyMatcher.matchesIgnoringAction() - Added integration with InputBus - Renamed Component.{add,remove}Listener methods about InputListeners to Component.{add,remove}InputListener to avoid confusion --- .../comms/controls/InputBasedControls.java | 8 +- .../progressia/client/graphics/GUI.java | 55 +-- .../progressia/client/graphics/Layer.java | 4 +- .../graphics/backend/GraphicsInterface.java | 4 + .../client/graphics/backend/InputHandler.java | 20 +- .../graphics/backend/LWJGLInitializer.java | 19 +- .../client/graphics/gui/BasicButton.java | 13 +- .../client/graphics/gui/Component.java | 129 +----- .../client/graphics/gui/GUILayer.java | 89 ++++- .../client/graphics/gui/RadioButton.java | 12 +- .../client/graphics/gui/menu/MenuLayer.java | 11 +- .../client/graphics/input/InputEvent.java | 36 +- .../client/graphics/input/KeyMatcher.java | 124 ++++-- .../client/graphics/input/Keys.java | 2 +- .../client/graphics/input/bus/Input.java | 62 --- .../client/graphics/input/bus/InputBus.java | 378 ++++++++++++++++-- .../graphics/input/bus/InputListener.java | 2 +- .../client/graphics/world/LayerWorld.java | 12 +- .../windcorp/progressia/test/LayerTestUI.java | 4 +- .../windcorp/progressia/test/TestContent.java | 9 +- .../progressia/test/TestPlayerControls.java | 11 +- 21 files changed, 654 insertions(+), 350 deletions(-) delete mode 100644 src/main/java/ru/windcorp/progressia/client/graphics/input/bus/Input.java diff --git a/src/main/java/ru/windcorp/progressia/client/comms/controls/InputBasedControls.java b/src/main/java/ru/windcorp/progressia/client/comms/controls/InputBasedControls.java index 28b9e1b..1eea281 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/controls/InputBasedControls.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/controls/InputBasedControls.java @@ -19,7 +19,7 @@ package ru.windcorp.progressia.client.comms.controls; import ru.windcorp.progressia.client.Client; -import ru.windcorp.progressia.client.graphics.input.bus.Input; +import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.common.comms.packets.Packet; public class InputBasedControls { @@ -36,12 +36,12 @@ public class InputBasedControls { .toArray(ControlTriggerInputBased[]::new); } - public void handleInput(Input input) { + public void handleInput(InputEvent event) { for (ControlTriggerInputBased c : controls) { - Packet packet = c.onInputEvent(input.getEvent()); + Packet packet = c.onInputEvent(event); if (packet != null) { - input.consume(); + event.consume(); client.getComms().sendPacket(packet); break; } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/GUI.java b/src/main/java/ru/windcorp/progressia/client/graphics/GUI.java index 59b89da..5834380 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/GUI.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/GUI.java @@ -23,15 +23,8 @@ import java.util.Collections; import java.util.List; import java.util.Objects; -import com.google.common.eventbus.Subscribe; - import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; -import ru.windcorp.progressia.client.graphics.input.CursorEvent; -import ru.windcorp.progressia.client.graphics.input.FrameResizeEvent; import ru.windcorp.progressia.client.graphics.input.InputEvent; -import ru.windcorp.progressia.client.graphics.input.KeyEvent; -import ru.windcorp.progressia.client.graphics.input.WheelEvent; -import ru.windcorp.progressia.client.graphics.input.bus.Input; public class GUI { @@ -46,15 +39,6 @@ public class GUI { private static final List MODIFICATION_QUEUE = Collections .synchronizedList(new ArrayList<>()); - private static class ModifiableInput extends Input { - @Override - public void initialize(InputEvent event, Target target) { - super.initialize(event, target); - } - } - - private static final ModifiableInput THE_INPUT = new ModifiableInput(); - private GUI() { } @@ -126,43 +110,12 @@ public class GUI { LAYERS.forEach(Layer::invalidate); } - private static void dispatchInputEvent(InputEvent event) { - Input.Target target; - - if (event instanceof KeyEvent) { - if (((KeyEvent) event).isMouse()) { - target = Input.Target.HOVERED; - } else { - target = Input.Target.FOCUSED; + public static void dispatchInput(InputEvent event) { + synchronized (LAYERS) { + for (int i = 0; i < LAYERS.size(); ++i) { + LAYERS.get(i).handleInput(event); } - } else if (event instanceof CursorEvent) { - target = Input.Target.HOVERED; - } else if (event instanceof WheelEvent) { - target = Input.Target.HOVERED; - } else if (event instanceof FrameResizeEvent) { - return; - } else { - target = Input.Target.ALL; } - - THE_INPUT.initialize(event, target); - LAYERS.forEach(l -> l.handleInput(THE_INPUT)); - } - - public static Object getEventSubscriber() { - return new Object() { - - @Subscribe - public void onFrameResized(FrameResizeEvent event) { - GUI.invalidateEverything(); - } - - @Subscribe - public void onInput(InputEvent event) { - dispatchInputEvent(event); - } - - }; } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/Layer.java b/src/main/java/ru/windcorp/progressia/client/graphics/Layer.java index dfa72d5..ad685e4 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/Layer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/Layer.java @@ -21,7 +21,7 @@ package ru.windcorp.progressia.client.graphics; import java.util.concurrent.atomic.AtomicBoolean; import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; -import ru.windcorp.progressia.client.graphics.input.bus.Input; +import ru.windcorp.progressia.client.graphics.input.InputEvent; public abstract class Layer { @@ -106,7 +106,7 @@ public abstract class Layer { protected abstract void doRender(); - protected abstract void handleInput(Input input); + public abstract void handleInput(InputEvent input); protected int getWidth() { return GraphicsInterface.getFrameWidth(); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsInterface.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsInterface.java index ffd0b49..6f59d39 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsInterface.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsInterface.java @@ -68,6 +68,10 @@ public class GraphicsInterface { public static void subscribeToInputEvents(Object listener) { InputHandler.register(listener); } + + public static void unsubscribeFromInputEvents(Object listener) { + InputHandler.unregister(listener); + } public static void startNextLayer() { GraphicsBackend.startNextLayer(); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputHandler.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputHandler.java index 34d936c..560ccaf 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputHandler.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/InputHandler.java @@ -39,6 +39,7 @@ public class InputHandler { public void initialize(int key, int scancode, int action, int mods) { this.setTime(GraphicsInterface.getTime()); + this.setConsumed(false); this.key = key; this.scancode = scancode; this.action = action; @@ -59,7 +60,7 @@ public class InputHandler { if (GraphicsBackend.getWindowHandle() != window) return; THE_KEY_EVENT.initialize(key, scancode, action, mods); - dispatch(THE_KEY_EVENT); + INPUT_EVENT_BUS.post(THE_KEY_EVENT); switch (action) { case GLFW.GLFW_PRESS: @@ -90,6 +91,7 @@ public class InputHandler { public void initialize(double x, double y) { this.setTime(GraphicsInterface.getTime()); + this.setConsumed(false); getNewPosition().set(x, y); } @@ -109,7 +111,7 @@ public class InputHandler { InputTracker.initializeCursorPosition(x, y); THE_CURSOR_MOVE_EVENT.initialize(x, y); - dispatch(THE_CURSOR_MOVE_EVENT); + INPUT_EVENT_BUS.post(THE_CURSOR_MOVE_EVENT); InputTracker.getCursorPosition().set(x, y); } @@ -124,6 +126,7 @@ public class InputHandler { public void initialize(double xOffset, double yOffset) { this.setTime(GraphicsInterface.getTime()); + this.setConsumed(false); this.getOffset().set(xOffset, yOffset); } @@ -139,7 +142,7 @@ public class InputHandler { if (GraphicsBackend.getWindowHandle() != window) return; THE_WHEEL_SCROLL_EVENT.initialize(xoffset, yoffset); - dispatch(THE_WHEEL_SCROLL_EVENT); + INPUT_EVENT_BUS.post(THE_WHEEL_SCROLL_EVENT); } // FrameResizeEvent @@ -152,6 +155,7 @@ public class InputHandler { public void initialize(int width, int height) { this.setTime(GraphicsInterface.getTime()); + this.setConsumed(false); this.getNewSize().set(width, height); } @@ -167,17 +171,17 @@ public class InputHandler { int height ) { THE_FRAME_RESIZE_EVENT.initialize(width, height); - dispatch(THE_FRAME_RESIZE_EVENT); + INPUT_EVENT_BUS.post(THE_FRAME_RESIZE_EVENT); } // Misc - private static void dispatch(InputEvent event) { - INPUT_EVENT_BUS.post(event); - } - public static void register(Object listener) { INPUT_EVENT_BUS.register(listener); } + + public static void unregister(Object listener) { + INPUT_EVENT_BUS.unregister(listener); + } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java index 9239150..9bc280e 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java @@ -24,7 +24,11 @@ import static org.lwjgl.system.MemoryUtil.*; import org.lwjgl.opengl.GL; +import com.google.common.eventbus.Subscribe; + import ru.windcorp.progressia.client.graphics.GUI; +import ru.windcorp.progressia.client.graphics.input.FrameResizeEvent; +import ru.windcorp.progressia.client.graphics.input.InputEvent; class LWJGLInitializer { @@ -107,7 +111,20 @@ class LWJGLInitializer { glfwSetScrollCallback(handle, InputHandler::handleWheelScroll); - GraphicsInterface.subscribeToInputEvents(GUI.getEventSubscriber()); + GraphicsInterface.subscribeToInputEvents(new Object() { + + @Subscribe + public void onFrameResized(FrameResizeEvent event) { + GUI.invalidateEverything(); + } + + @Subscribe + public void onInputEvent(InputEvent event) { + GUI.dispatchInput(event); + } + + }); + } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java index 6b86627..20f1ef4 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/BasicButton.java @@ -54,18 +54,17 @@ public abstract class BasicButton extends Component { reassembleAt(ARTrigger.HOVER, ARTrigger.FOCUS, ARTrigger.ENABLE); // Click triggers - addListener(KeyEvent.class, e -> { - if (e.isRepeat()) { - return false; - } else if ( + addInputListener(KeyEvent.class, e -> { + if (e.isRepeat()) + return; + + if ( e.isLeftMouseButton() || e.getKey() == GLFW.GLFW_KEY_SPACE || e.getKey() == GLFW.GLFW_KEY_ENTER ) { setPressed(e.isPress()); - return true; - } else { - return false; + e.consume(); } }); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java index 8f1aa9a..417c6ea 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java @@ -25,8 +25,6 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; -import org.lwjgl.glfw.GLFW; - import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; @@ -39,9 +37,10 @@ import ru.windcorp.progressia.client.graphics.gui.event.EnableEvent; import ru.windcorp.progressia.client.graphics.gui.event.FocusEvent; import ru.windcorp.progressia.client.graphics.gui.event.HoverEvent; import ru.windcorp.progressia.client.graphics.gui.event.ParentChangedEvent; +import ru.windcorp.progressia.client.graphics.input.CursorMoveEvent; import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.client.graphics.input.KeyEvent; -import ru.windcorp.progressia.client.graphics.input.bus.Input; +import ru.windcorp.progressia.client.graphics.input.KeyMatcher; import ru.windcorp.progressia.client.graphics.input.bus.InputBus; import ru.windcorp.progressia.client.graphics.input.bus.InputListener; import ru.windcorp.progressia.common.util.Named; @@ -55,7 +54,7 @@ public class Component extends Named { private Component parent = null; private EventBus eventBus = null; - private InputBus inputBus = null; + private final InputBus inputBus = new InputBus(this); private int x, y; private int width, height; @@ -76,6 +75,9 @@ public class Component extends Named { public Component(String name) { super(name); + + // Update hover flag when cursor moves + addInputListener(CursorMoveEvent.class, this::updateHoverFlag, InputBus.Option.ALWAYS); } public Component getParent() { @@ -521,6 +523,10 @@ public class Component extends Named { dispatchEvent(new HoverEvent(this, isHovered)); } } + + private void updateHoverFlag(CursorMoveEvent e) { + setHovered(contains((int) InputTracker.getCursorX(), (int) InputTracker.getCursorY())); + } public void addListener(Object listener) { if (eventBus == null) { @@ -542,121 +548,28 @@ public class Component extends Named { eventBus.post(event); } - public void addListener( - Class type, - boolean handlesConsumed, - InputListener listener - ) { - if (inputBus == null) { - inputBus = new InputBus(); - } - - inputBus.register(type, handlesConsumed, listener); + public void addInputListener(Class type, InputListener listener, InputBus.Option... options) { + inputBus.register(type, listener, options); + } + + public void addKeyListener(KeyMatcher matcher, InputListener listener, InputBus.Option... options) { + inputBus.register(matcher, listener, options); } - public void addListener(Class type, InputListener listener) { - if (inputBus == null) { - inputBus = new InputBus(); - } - - inputBus.register(type, listener); - } - - public void removeListener(InputListener listener) { + public void removeInputListener(InputListener listener) { if (inputBus != null) { inputBus.unregister(listener); } } - - protected void handleInput(Input input) { - if (inputBus != null && isEnabled()) { - inputBus.dispatch(input); - } + + InputBus getInputBus() { + return inputBus; } - - public void dispatchInput(Input input) { - try { - switch (input.getTarget()) { - case FOCUSED: - dispatchInputToFocused(input); - break; - case HOVERED: - dispatchInputToHovered(input); - break; - case ALL: - default: - dispatchInputToAll(input); - break; - } - } catch (Exception e) { - throw CrashReports.report(e, "Could not dispatch input to Component %s", this); - } - } - - private void dispatchInputToFocused(Input input) { - Component c = findFocused(); - - if (c == null) - return; - if (attemptFocusTransfer(input, c)) - return; - - while (c != null) { - c.handleInput(input); - c = c.getParent(); - } - } - - private void dispatchInputToHovered(Input input) { - getChildren().forEach(child -> { - if (child.containsCursor()) { - child.setHovered(true); - - if (!input.isConsumed()) { - child.dispatchInput(input); - } - } else { - child.setHovered(false); - } - }); - - handleInput(input); - } - - private void dispatchInputToAll(Input input) { - getChildren().forEach(c -> c.dispatchInput(input)); - handleInput(input); - } - - private boolean attemptFocusTransfer(Input input, Component focused) { - if (input.isConsumed()) - return false; - if (!(input.getEvent() instanceof KeyEvent)) - return false; - - KeyEvent keyInput = (KeyEvent) input.getEvent(); - - if (keyInput.getKey() == GLFW.GLFW_KEY_TAB && !keyInput.isRelease()) { - input.consume(); - if (keyInput.hasShift()) { - focused.focusPrevious(); - } else { - focused.focusNext(); - } - return true; - } - - return false; - } - + public synchronized boolean contains(int x, int y) { return x >= getX() && x < getX() + getWidth() && y >= getY() && y < getY() + getHeight(); } - public boolean containsCursor() { - return contains((int) InputTracker.getCursorX(), (int) InputTracker.getCursorY()); - } - public void requestReassembly() { if (parent != null) { parent.requestReassembly(); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java index 2e0981c..b808aed 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java @@ -15,12 +15,19 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.gui; +import java.util.Iterator; + +import org.lwjgl.glfw.GLFW; + import ru.windcorp.progressia.client.graphics.flat.AssembledFlatLayer; import ru.windcorp.progressia.client.graphics.flat.RenderTarget; -import ru.windcorp.progressia.client.graphics.input.bus.Input; +import ru.windcorp.progressia.client.graphics.input.InputEvent; +import ru.windcorp.progressia.client.graphics.input.KeyEvent; +import ru.windcorp.progressia.client.graphics.input.bus.InputBus; +import ru.windcorp.progressia.common.util.StashingStack; public abstract class GUILayer extends AssembledFlatLayer { @@ -33,7 +40,9 @@ public abstract class GUILayer extends AssembledFlatLayer { public GUILayer(String name, Layout layout) { super(name); + getRoot().setLayout(layout); + getRoot().addInputListener(KeyEvent.class, this::attemptFocusTransfer, InputBus.Option.IGNORE_FOCUS); } public Component getRoot() { @@ -47,9 +56,81 @@ public abstract class GUILayer extends AssembledFlatLayer { getRoot().assemble(target); } + /** + * Stack frame for {@link #handleInput(InputEvent)}. + */ + private static class EventHandlingFrame { + Component component; + Iterator children; + + void init(Component c) { + component = c; + children = c.getChildren().iterator(); + } + + void reset() { + component = null; + children = null; + } + } + + /** + * Stack for {@link #handleInput(InputEvent)}. + */ + private StashingStack path = new StashingStack<>(64, EventHandlingFrame::new); + + /* + * This is essentially a depth-first iteration of the component tree. The + * recursive procedure has been unrolled to reduce call stack length. + */ @Override - protected void handleInput(Input input) { - getRoot().dispatchInput(input); + public void handleInput(InputEvent event) { + if (!path.isEmpty()) { + throw new IllegalStateException( + "path is not empty: " + path + ". Are events being processed concurrently?" + ); + } + + path.push().init(root); + + while (!path.isEmpty()) { + + Iterator it = path.peek().children; + if (it.hasNext()) { + + Component c = it.next(); + + if (c.isEnabled()) { + if (c.getChildren().isEmpty()) { + c.getInputBus().dispatch(event); + } else { + path.push().init(c); + } + } + + } else { + path.peek().component.getInputBus().dispatch(event); + path.pop().reset(); + } + + } + } + + private void attemptFocusTransfer(KeyEvent e) { + Component focused = getRoot().findFocused(); + + if (focused == null) { + return; + } + + if (e.getKey() == GLFW.GLFW_KEY_TAB && !e.isRelease()) { + e.consume(); + if (e.hasShift()) { + focused.focusPrevious(); + } else { + focused.focusNext(); + } + } } @Override diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/RadioButton.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/RadioButton.java index 1ee7f66..8ea76f3 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/RadioButton.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/RadioButton.java @@ -104,26 +104,22 @@ public class RadioButton extends BasicButton { group.addChild(basicChild); addChild(group); - addListener(KeyEvent.class, e -> { - if (e.isRelease()) - return false; + addInputListener(KeyEvent.class, e -> { + if (e.isRelease()) return; if (e.getKey() == GLFW.GLFW_KEY_LEFT || e.getKey() == GLFW.GLFW_KEY_UP) { if (this.group != null) { this.group.selectPrevious(); this.group.getSelected().takeFocus(); } - - return true; + e.consume(); } else if (e.getKey() == GLFW.GLFW_KEY_RIGHT || e.getKey() == GLFW.GLFW_KEY_DOWN) { if (this.group != null) { this.group.selectNext(); this.group.getSelected().takeFocus(); } - return true; + e.consume(); } - - return false; }); addAction(b -> setChecked(true)); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/menu/MenuLayer.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/menu/MenuLayer.java index 4fa155c..2c42cf0 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/menu/MenuLayer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/menu/MenuLayer.java @@ -33,7 +33,6 @@ import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill; import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical; import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.client.graphics.input.KeyEvent; -import ru.windcorp.progressia.client.graphics.input.bus.Input; import ru.windcorp.progressia.client.localization.MutableString; import ru.windcorp.progressia.client.localization.MutableStringLocalized; @@ -97,11 +96,9 @@ public class MenuLayer extends GUILayer { } @Override - protected void handleInput(Input input) { + public void handleInput(InputEvent event) { - if (!input.isConsumed()) { - InputEvent event = input.getEvent(); - + if (!event.isConsumed()) { if (event instanceof KeyEvent) { KeyEvent keyEvent = (KeyEvent) event; if (keyEvent.isPress() && keyEvent.getKey() == GLFW.GLFW_KEY_ESCAPE) { @@ -110,8 +107,8 @@ public class MenuLayer extends GUILayer { } } - super.handleInput(input); - input.consume(); + super.handleInput(event); + event.consume(); } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/InputEvent.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/InputEvent.java index b0c2483..5edf055 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/InputEvent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/InputEvent.java @@ -15,13 +15,35 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.input; +import ru.windcorp.progressia.client.graphics.gui.Component; + +/** + * An instance of user input. + *

+ * User input events are typically generated by graphics backend between frames + * and passed to the graphics layers from top to bottom. Layers that use + * {@link Component}s will forward this event through the Component hierarchy. + *

+ * Events have a {@code consumed} flag. A freshly-generated event will have this + * flag set to {@code false}. Event listeners that process the event will + * usually choose to raise the flag ("consume the event") to ask future + * listeners to ignore this event. This is done to avoid multiple UI interfaces + * reacting to single input. By default, listeners will not receive consumed + * events; however, some listeners may choose to receive, handle and even + * un-consume the event. + *

+ * {@code InputEvent} objects may be reused for future input events after their + * processing is complete; to obtain a static copy, use {@link #snapshot()}. + */ public abstract class InputEvent { private double time; + private boolean isConsumed = false; + public InputEvent(double time) { this.time = time; } @@ -36,4 +58,16 @@ public abstract class InputEvent { public abstract InputEvent snapshot(); + public boolean isConsumed() { + return isConsumed; + } + + public void setConsumed(boolean isConsumed) { + this.isConsumed = isConsumed; + } + + public void consume() { + setConsumed(true); + } + } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyMatcher.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyMatcher.java index 6fedcd6..048ddb5 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyMatcher.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyMatcher.java @@ -18,16 +18,75 @@ package ru.windcorp.progressia.client.graphics.input; -import java.util.function.Predicate; +import java.util.Map; +import java.util.regex.Pattern; import org.lwjgl.glfw.GLFW; +import com.google.common.collect.ImmutableMap; + public class KeyMatcher { + + private static final Pattern DECLAR_SPLIT_REGEX = Pattern.compile("\\s*\\+\\s*"); + private static final Map MOD_TOKENS = ImmutableMap.of( + "SHIFT", GLFW.GLFW_MOD_SHIFT, + "CONTROL", GLFW.GLFW_MOD_CONTROL, + "ALT", GLFW.GLFW_MOD_ALT, + "SUPER", GLFW.GLFW_MOD_SUPER + ); + + public static final KeyMatcher LMB = new KeyMatcher(GLFW.GLFW_MOUSE_BUTTON_LEFT); + public static final KeyMatcher RMB = new KeyMatcher(GLFW.GLFW_MOUSE_BUTTON_RIGHT); + public static final KeyMatcher MMB = new KeyMatcher(GLFW.GLFW_MOUSE_BUTTON_MIDDLE); private final int key; private final int mods; - protected KeyMatcher(int key, int mods) { + public KeyMatcher(int key, int mods) { + this.key = key; + this.mods = mods; + } + + public KeyMatcher(int key) { + this.key = key; + this.mods = 0; + } + + public KeyMatcher(String declar) { + String[] tokens = DECLAR_SPLIT_REGEX.split(declar); + if (tokens.length == 0) { + throw new IllegalArgumentException("No tokens found in \"" + declar + "\""); + } + + int key = -1; + int mods = 0; + + for (String token : tokens) { + token = token.toUpperCase(); + + if (MOD_TOKENS.containsKey(token)) { + int mod = MOD_TOKENS.get(token); + if ((mods & mod) != 0) { + throw new IllegalArgumentException("Duplicate modifier \"" + token + "\" in \"" + declar + "\""); + } + mods |= mod; + } else if (key != -1) { + throw new IllegalArgumentException("Too many non-modifier tokens in \"" + declar + "\": maximum one key, first offender: \"" + token + "\""); + } else { + token = token.replace(' ', '_'); + + if (token.startsWith("KEYPAD_")) { + token = "KP_" + token.substring("KEYPAD_".length()); + } + + key = Keys.getCode(token); + + if (key == -1) { + throw new IllegalArgumentException("Unknown token \"" + token + "\" in \"" + declar + "\""); + } + } + } + this.key = key; this.mods = mods; } @@ -42,6 +101,15 @@ public class KeyMatcher { return true; } + + public boolean matchesIgnoringAction(KeyEvent event) { + if (event.getKey() != getKey()) + return false; + if ((event.getMods() & getMods()) != getMods()) + return false; + + return true; + } public int getKey() { return key; @@ -50,49 +118,25 @@ public class KeyMatcher { public int getMods() { return mods; } - - public static KeyMatcher.Builder of(int key) { - return new KeyMatcher.Builder(key); + + public KeyMatcher with(int modifier) { + return new KeyMatcher(key, mods | modifier); } - public static class Builder { + public KeyMatcher withShift() { + return with(GLFW.GLFW_MOD_SHIFT); + } - private final int key; - private int mods = 0; + public KeyMatcher withCtrl() { + return with(GLFW.GLFW_MOD_CONTROL); + } - public Builder(int key) { - this.key = key; - } - - public Builder with(int modifier) { - this.mods += modifier; - return this; - } - - public Builder withShift() { - return with(GLFW.GLFW_MOD_SHIFT); - } - - public Builder withCtrl() { - return with(GLFW.GLFW_MOD_CONTROL); - } - - public Builder withAlt() { - return with(GLFW.GLFW_MOD_ALT); - } - - public Builder withSuper() { - return with(GLFW.GLFW_MOD_SUPER); - } - - public KeyMatcher build() { - return new KeyMatcher(key, mods); - } - - public Predicate matcher() { - return build()::matches; - } + public KeyMatcher withAlt() { + return with(GLFW.GLFW_MOD_ALT); + } + public KeyMatcher withSuper() { + return with(GLFW.GLFW_MOD_SUPER); } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/Keys.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/Keys.java index 3904f59..9132c37 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/Keys.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/Keys.java @@ -139,7 +139,7 @@ public class Keys { } public static int getCode(String internalName) { - if (NAMES_TO_CODES.containsKey(internalName)) { + if (!NAMES_TO_CODES.containsKey(internalName)) { return -1; } else { return NAMES_TO_CODES.get(internalName); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/Input.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/Input.java deleted file mode 100644 index 1aad6bb..0000000 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/Input.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Progressia - * Copyright (C) 2020-2021 Wind Corporation and contributors - * - * 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 . - */ - -package ru.windcorp.progressia.client.graphics.input.bus; - -import ru.windcorp.progressia.client.graphics.input.InputEvent; - -public class Input { - - public static enum Target { - FOCUSED, HOVERED, ALL - } - - private InputEvent event; - - private boolean isConsumed; - - private Target target; - - protected void initialize(InputEvent event, Target target) { - this.event = event; - this.target = target; - - this.isConsumed = false; - } - - public InputEvent getEvent() { - return event; - } - - public boolean isConsumed() { - return isConsumed; - } - - public void setConsumed(boolean isConsumed) { - this.isConsumed = isConsumed; - } - - public void consume() { - setConsumed(true); - } - - public Target getTarget() { - return target; - } - -} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputBus.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputBus.java index a22a243..82f7275 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputBus.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputBus.java @@ -15,73 +15,401 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.client.graphics.input.bus; import java.util.ArrayList; import java.util.Collection; +import java.util.Objects; +import ru.windcorp.jputil.ArrayUtil; +import ru.windcorp.progressia.client.graphics.gui.Component; +import ru.windcorp.progressia.client.graphics.input.CursorEvent; import ru.windcorp.progressia.client.graphics.input.InputEvent; +import ru.windcorp.progressia.client.graphics.input.KeyEvent; +import ru.windcorp.progressia.client.graphics.input.KeyMatcher; +import ru.windcorp.progressia.client.graphics.input.WheelEvent; +import ru.windcorp.progressia.common.util.crash.CrashReports; +/** + * An event bus optionally related to a {@link Component} that delivers input + * events to input listeners. This bus may skip listeners based on circumstance; + * behavior can be customized for each listener with {@link Option}s. + *

+ * By default, events are filtered by four checks before being delivered to each + * listener: + *

    + *
  1. Consumption check: unless {@link Option#RECEIVE_CONSUMED + * RECEIVE_CONSUMED} is set, events that are consumed will not be + * delivered.
  2. + *
  3. Hover check: for certain event types (for example, + * {@link WheelEvent} or {@link KeyEvent} that {@link KeyEvent#isMouse() + * isMouse()}), the event will only be delivered if the component is hovered. + * This check may be bypassed with option {@link Option#IGNORE_HOVER + * IGNORE_HOVER} or made mandatory for all events with + * {@link Option#REQUIRE_HOVER REQUIRE_HOVER}. Hover check automatically + * succeeds if no component is provided.
  4. + *
  5. Focus check: for certain event types (for example, + * {@link KeyEvent} that {@code !isMouse()}), the event will only be delivered + * if the component has focus. This check may be bypassed with option + * {@link Option#IGNORE_FOCUS IGNORE_FOCUS} or made mandatory for all events + * with {@link Option#REQUIRE_FOCUS REQUIRE_FOCUS}. Focus check automatically + * succeeds if no component is provided.
  6. + *
  7. Type check: events of type {@code E} are only delivered to + * listeners registered with event type {@code T} if objects of type {@code E} + * can be cast to {@code T}.
  8. + *
+ * Checks 1-3 are bypassed when option {@link Option#ALWAYS ALWAYS} is + * specified. + */ public class InputBus { - private static class WrappedListener { + /** + * Options that allow customization of checks for listeners. + */ + public enum Option { + + /** + * Ignore checks for consumed events, hover and focus; deliver event if + * at all possible. This is shorthand for {@link #RECEIVE_CONSUMED}, + * {@link #IGNORE_HOVER} and {@link #IGNORE_FOCUS}. + */ + ALWAYS, + + /** + * Receive events that were previously consumed. + */ + RECEIVE_CONSUMED, + + /** + * Do not process events if the listener is registered with a component + * and the component is not hovered. + */ + REQUIRE_HOVER, + + /** + * Deliver events even if the event is limited to hovered components by + * default. + */ + IGNORE_HOVER, + + /** + * Do not process events if the listener is registered with a component + * and the component is not focused. + */ + REQUIRE_FOCUS, + + /** + * Deliver events even if the event is limited to focused components by + * default. + */ + IGNORE_FOCUS, + + /** + * Deliver events according to + * {@link KeyMatcher#matchesIgnoringAction(KeyEvent)} rather than + * {@link KeyMatcher#matches(KeyEvent)} when a {@link KeyMatcher} is + * specified. + */ + IGNORE_ACTION; + + } + + private enum YesNoDefault { + YES, NO, DEFAULT; + } + + /** + * A listener with check preferences resolved and type specified. + */ + private class WrappedListener { private final Class type; - private final boolean handleConsumed; + + private final boolean dropIfConsumed; + private final YesNoDefault dropIfNotHovered; + private final YesNoDefault dropIfNotFocused; + private final InputListener listener; public WrappedListener( Class type, - boolean handleConsumed, + boolean dropIfConsumed, + YesNoDefault dropIfNotHovered, + YesNoDefault dropIfNotFocused, InputListener listener ) { this.type = type; - this.handleConsumed = handleConsumed; + this.dropIfConsumed = dropIfConsumed; + this.dropIfNotHovered = dropIfNotHovered; + this.dropIfNotFocused = dropIfNotFocused; this.listener = listener; } - private boolean handles(Input input) { - return (!input.isConsumed() || handleConsumed) && - type.isInstance(input.getEvent()); + private boolean handles(InputEvent input) { + if (dropIfConsumed && input.isConsumed()) + return false; + + switch (dropIfNotHovered) { + case YES: + if (!isHovered()) + return false; + break; + case NO: + break; + default: + + if (isHovered()) + break; + + if (input instanceof KeyEvent && ((KeyEvent) input).isMouse()) + return false; + + if (input instanceof CursorEvent) + return false; + + if (input instanceof WheelEvent) + return false; + + break; + } + + switch (dropIfNotFocused) { + case YES: + if (!isFocused()) + return false; + break; + case NO: + break; + default: + + if (isFocused()) + break; + + if (input instanceof KeyEvent && !((KeyEvent) input).isMouse()) + return false; + + break; + } + + if (!type.isInstance(input)) + return false; + + return true; } + /** + * Invokes the listener if the event is deemed appropriate by the four + * checks. + * + * @param event the event to deliver + */ @SuppressWarnings("unchecked") - public void handle(Input input) { - if (handles(input)) { - boolean consumed = ((InputListener) listener) - .handle( - (InputEvent) type.cast(input.getEvent()) - ); + public void handle(InputEvent event) { + if (handles(event)) { + // A runtime check of types has been performed; this is safe. + InputListener castListener = (InputListener) listener; - input.setConsumed(consumed); + try { + castListener.handle(event); + } catch (Exception e) { + throw CrashReports.report( + e, + "InputListener %s for component %s has failed to receive event %s", + listener, + owner, + event + ); + } } } } + /** + * The component queried for focus and hover. May be {@code null}. + */ + private final Component owner; + + /** + * Registered listeners. + */ private final Collection listeners = new ArrayList<>(4); - public void dispatch(Input input) { - listeners.forEach(l -> l.handle(input)); + /** + * Creates a new input bus that consults the specified {@link Component} to + * determine hover and focus. + * + * @param owner the component to use for hover and focus tests + * @see #InputBus() + */ + public InputBus(Component owner) { + this.owner = Objects.requireNonNull(owner, "owner"); } + /** + * Creates a new input bus that assumes all hover and focus checks are + * successful. + * + * @see #InputBus(Component) + */ + public InputBus() { + this.owner = null; + } + + /** + * Determines whether hover should be assumed for this event bus. + * + * @return {@code true} iff no component is linked or the linked component + * is hovered + */ + private boolean isHovered() { + return owner == null ? true : owner.isHovered(); + } + + /** + * Determines whether focus should be assumed for this event bus. + * + * @return {@code true} iff no component is linked or the linked component + * is focused + */ + private boolean isFocused() { + return owner == null ? true : owner.isFocused(); + } + + /** + * Dispatches (delivers) the provided event to all appropriate listeners. + * + * @param event the event to process + */ + public void dispatch(InputEvent event) { + Objects.requireNonNull(event, "event"); + for (WrappedListener listener : listeners) { + listener.handle(event); + } + } + + /** + * Registers a listener on this bus. + *

+ * {@code type} specifies the class of events that should be passed to this + * listener. Only events of types that extend, implement or equal + * {@code type} are processed. + *

+ * Zero or more {@link Option}s may be specified to enable or disable the + * processing of certain events in certain circumstances. See + * {@linkplain InputBus class description} for a detailed breakdown of the + * checks performed and the effects of various options. When providing + * options to this method, later options override the effects of previous + * options. + *

+ * Option {@link Option#IGNORE_ACTION IGNORE_ACTION} is ignored silently. + * + * @param type the event class to deliver + * @param listener the listener + * @param options the options for this listener + */ public void register( Class type, - boolean handlesConsumed, - InputListener listener + InputListener listener, + Option... options ) { - listeners.add(new WrappedListener(type, handlesConsumed, listener)); + Objects.requireNonNull(type, "type"); + Objects.requireNonNull(listener, "listener"); + + boolean dropIfConsumed = true; + YesNoDefault dropIfNotHovered = YesNoDefault.DEFAULT; + YesNoDefault dropIfNotFocused = YesNoDefault.DEFAULT; + + if (options != null) { + for (Option option : options) { + switch (option) { + case ALWAYS: + dropIfConsumed = false; + dropIfNotHovered = YesNoDefault.NO; + dropIfNotFocused = YesNoDefault.NO; + break; + case RECEIVE_CONSUMED: + dropIfConsumed = false; + break; + case REQUIRE_HOVER: + dropIfNotHovered = YesNoDefault.YES; + break; + case IGNORE_HOVER: + dropIfNotFocused = YesNoDefault.NO; + break; + case REQUIRE_FOCUS: + dropIfNotHovered = YesNoDefault.YES; + break; + case IGNORE_FOCUS: + dropIfNotFocused = YesNoDefault.NO; + break; + case IGNORE_ACTION: + // Ignore + break; + default: + throw new IllegalArgumentException("Unexpected option " + option); + } + } + } + + listeners.add(new WrappedListener(type, dropIfConsumed, dropIfNotHovered, dropIfNotFocused, listener)); } - public void register( - Class type, - InputListener listener - ) { - register(type, false, listener); + /** + * Registers a {@link KeyEvent} listener on this bus. An event has to match + * the provided {@link KeyMatcher} to be delivered to the listener. + *

+ * Zero or more {@link Option}s may be specified to enable or disable the + * processing of certain events in certain circumstances. See + * {@linkplain InputBus class description} for a detailed breakdown of the + * checks performed and the effects of various options. When providing + * options to this method, later options override the effects of previous + * options. + *

+ * Option {@link Option#IGNORE_ACTION IGNORE_ACTION} requests that events + * are delivered according to + * {@link KeyMatcher#matchesIgnoringAction(KeyEvent)} rather than + * {@link KeyMatcher#matches(KeyEvent)}. + * specified. + * + * @param matcher an event filter + * @param listener the listener + * @param options the options for this listener + */ + public void register(KeyMatcher matcher, InputListener listener, Option... options) { + Objects.requireNonNull(matcher, "matcher"); + Objects.requireNonNull(listener, "listener"); + + InputListener filteringListener; + + if (ArrayUtil.firstIndexOf(options, Option.IGNORE_ACTION) != -1) { + filteringListener = e -> { + if (matcher.matchesIgnoringAction(e)) { + listener.handle(e); + } + }; + } else { + filteringListener = e -> { + if (matcher.matches(e)) { + listener.handle(e); + } + }; + } + + register(KeyEvent.class, filteringListener, options); } + /** + * Removes all occurrences of the provided listener from this bus. + * + * @param listener the listener to unregister + */ public void unregister(InputListener listener) { + if (listener == null) { + return; + } + listeners.removeIf(l -> l.listener == listener); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputListener.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputListener.java index 0d68b5e..1db2410 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputListener.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/bus/InputListener.java @@ -23,6 +23,6 @@ import ru.windcorp.progressia.client.graphics.input.InputEvent; @FunctionalInterface public interface InputListener { - boolean handle(T event); + void handle(T event); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java index c81e7a7..b25eaa5 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java @@ -31,7 +31,7 @@ import ru.windcorp.progressia.client.comms.controls.InputBasedControls; import ru.windcorp.progressia.client.graphics.Layer; import ru.windcorp.progressia.client.graphics.backend.FaceCulling; import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; -import ru.windcorp.progressia.client.graphics.input.bus.Input; +import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.client.graphics.model.ShapeRenderProgram; import ru.windcorp.progressia.client.graphics.model.Shapes.PppBuilder; @@ -225,14 +225,14 @@ public class LayerWorld extends Layer { } @Override - protected void handleInput(Input input) { - if (input.isConsumed()) + public void handleInput(InputEvent event) { + if (event.isConsumed()) return; - tmp_testControls.handleInput(input); + tmp_testControls.handleInput(event); - if (!input.isConsumed()) { - inputBasedControls.handleInput(input); + if (!event.isConsumed()) { + inputBasedControls.handleInput(event); } } diff --git a/src/main/java/ru/windcorp/progressia/test/LayerTestUI.java b/src/main/java/ru/windcorp/progressia/test/LayerTestUI.java index 19c10aa..686fc3a 100755 --- a/src/main/java/ru/windcorp/progressia/test/LayerTestUI.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerTestUI.java @@ -27,8 +27,8 @@ import ru.windcorp.progressia.client.graphics.Colors; import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; import ru.windcorp.progressia.client.graphics.flat.AssembledFlatLayer; import ru.windcorp.progressia.client.graphics.flat.RenderTarget; +import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.client.graphics.input.KeyEvent; -import ru.windcorp.progressia.client.graphics.input.bus.Input; public class LayerTestUI extends AssembledFlatLayer { @@ -91,7 +91,7 @@ public class LayerTestUI extends AssembledFlatLayer { } @Override - protected void handleInput(Input input) { + public void handleInput(InputEvent event) { // Do nothing } diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java index c2444d2..5f136aa 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java @@ -28,7 +28,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.function.Consumer; -import org.lwjgl.glfw.GLFW; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.client.ClientState; @@ -298,7 +297,7 @@ public class TestContent { "Test:BreakBlock", KeyEvent.class, TestContent::onBlockBreakTrigger, - KeyMatcher.of(GLFW.GLFW_MOUSE_BUTTON_LEFT).matcher(), + KeyMatcher.LMB::matches, i -> isAnythingSelected() ) ); @@ -310,7 +309,7 @@ public class TestContent { "Test:PlaceBlock", KeyEvent.class, TestContent::onBlockPlaceTrigger, - KeyMatcher.of(GLFW.GLFW_MOUSE_BUTTON_RIGHT).matcher(), + KeyMatcher.RMB::matches, i -> isAnythingSelected() && TestPlayerControls.getInstance().isBlockSelected() ) ); @@ -323,7 +322,7 @@ public class TestContent { "Test:PlaceTile", KeyEvent.class, TestContent::onTilePlaceTrigger, - KeyMatcher.of(GLFW.GLFW_MOUSE_BUTTON_RIGHT).matcher(), + KeyMatcher.RMB::matches, i -> isAnythingSelected() && !TestPlayerControls.getInstance().isBlockSelected() ) ); @@ -334,7 +333,7 @@ public class TestContent { "Test:StartNextMusic", KeyEvent.class, TestMusicPlayer::startNextNow, - KeyMatcher.of(GLFW.GLFW_KEY_M).matcher() + new KeyMatcher("M")::matches ) ); } diff --git a/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java b/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java index 4ca0ea6..8c03c99 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java +++ b/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java @@ -32,7 +32,6 @@ import ru.windcorp.progressia.client.graphics.input.CursorMoveEvent; import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.client.graphics.input.KeyEvent; import ru.windcorp.progressia.client.graphics.input.WheelScrollEvent; -import ru.windcorp.progressia.client.graphics.input.bus.Input; import ru.windcorp.progressia.client.graphics.world.LocalPlayer; import ru.windcorp.progressia.client.localization.Localizer; import ru.windcorp.progressia.common.Units; @@ -162,19 +161,17 @@ public class TestPlayerControls { ); } - public void handleInput(Input input) { - InputEvent event = input.getEvent(); - + public void handleInput(InputEvent event) { if (event instanceof KeyEvent) { if (onKeyEvent((KeyEvent) event)) { - input.consume(); + event.consume(); } } else if (event instanceof CursorMoveEvent) { onMouseMoved((CursorMoveEvent) event); - input.consume(); + event.consume(); } else if (event instanceof WheelScrollEvent) { onWheelScroll((WheelScrollEvent) event); - input.consume(); + event.consume(); } } From c4a9a17c7c6fd39d232199cb4227edd580fb988e Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Fri, 10 Dec 2021 11:05:30 +0300 Subject: [PATCH 41/49] Update log4j dependency to version 2.15.0 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 5adae10..4080ac6 100644 --- a/build.gradle +++ b/build.gradle @@ -66,8 +66,8 @@ dependencies { // Log4j // A logging library - implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.13.3' - implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.13.3' + implementation 'org.apache.logging.log4j:log4j-api:2.15.0' + implementation 'org.apache.logging.log4j:log4j-core:2.15.0' // JUnit // A unit-testing library From 75ea7baf9ce2c4e3ff5af53d71e95651f77fbeec Mon Sep 17 00:00:00 2001 From: serega404 Date: Sun, 12 Dec 2021 15:41:10 +0300 Subject: [PATCH 42/49] Update junit dependency to version 4.13.2 Fix for CVE-2020-15250 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4080ac6..d1f1729 100644 --- a/build.gradle +++ b/build.gradle @@ -71,7 +71,7 @@ dependencies { // JUnit // A unit-testing library - testImplementation 'junit:junit:4.12' + testImplementation 'junit:junit:4.13.2' // See LWJGL dependencies below } From c93f0df30d0b202fc52c8020e933e23dbb34798b Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Mon, 13 Dec 2021 11:06:28 +0300 Subject: [PATCH 43/49] Refactored movement controls - Movement control code is now in its own class - Movement direction controls are now more bug-resistant - No longer event-driven; uses InputTracker instead - Temporarily? function with menus open - Other movement controls are now registered local Controls - Removed flying and sprinting indicators from F3 layer - TestPlayerControls is now a singleton - resetInstance() now resets the instance's fields --- .../comms/controls/ControlTriggers.java | 14 - .../progressia/test/LayerTestGUI.java | 16 - .../windcorp/progressia/test/TestContent.java | 33 ++ .../progressia/test/TestPlayerControls.java | 271 +++-------------- .../test/controls/MovementControls.java | 287 ++++++++++++++++++ .../resources/assets/languages/en-US.lang | 2 - .../resources/assets/languages/ru-RU.lang | 2 - 7 files changed, 362 insertions(+), 263 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/test/controls/MovementControls.java diff --git a/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggers.java b/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggers.java index 2c0d61d..2cc73f4 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggers.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/controls/ControlTriggers.java @@ -143,20 +143,6 @@ public class ControlTriggers { ); } - // - // - /// - /// - // - // - // - // - // - // - // - // - // - public static ControlTriggerInputBased localOf( String id, Consumer action, diff --git a/src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java b/src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java index 0c082fa..faf9851 100755 --- a/src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java @@ -58,22 +58,6 @@ public class LayerTestGUI extends GUILayer { TestPlayerControls tpc = TestPlayerControls.getInstance(); - group.addChild( - new Label( - "IsFlyingDisplay", - font, - tmp_dynFormat("LayerTestGUI.IsFlyingDisplay", tpc::isFlying) - ) - ); - - group.addChild( - new Label( - "IsSprintingDisplay", - font, - tmp_dynFormat("LayerTestGUI.IsSprintingDisplay", tpc::isSprinting) - ) - ); - group.addChild( new Label( "CameraModeDisplay", diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java index 5f136aa..c7d7e8a 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java @@ -29,12 +29,16 @@ import java.util.List; import java.util.Set; import java.util.function.Consumer; +import org.lwjgl.glfw.GLFW; + import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.client.ClientState; import ru.windcorp.progressia.client.audio.Sound; import ru.windcorp.progressia.client.comms.controls.*; +import ru.windcorp.progressia.client.graphics.backend.InputTracker; import ru.windcorp.progressia.client.graphics.input.KeyEvent; import ru.windcorp.progressia.client.graphics.input.KeyMatcher; +import ru.windcorp.progressia.client.graphics.input.WheelScrollEvent; import ru.windcorp.progressia.client.graphics.world.Selection; import ru.windcorp.progressia.client.world.block.*; import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerRegistry; @@ -287,6 +291,8 @@ public class TestContent { } private static void regsiterControls() { + TestPlayerControls.getInstance().registerControls(); + ControlDataRegistry data = ControlDataRegistry.getInstance(); ControlTriggerRegistry triggers = ControlTriggerRegistry.getInstance(); ControlLogicRegistry logic = ControlLogicRegistry.getInstance(); @@ -327,6 +333,33 @@ public class TestContent { ) ); logic.register(ControlLogic.of("Test:PlaceTile", TestContent::onTilePlaceReceived)); + + triggers.register( + ControlTriggers.localOf( + "Test:SwitchPlacingModeMMB", + KeyEvent.class, + () -> TestPlayerControls.getInstance().switchPlacingMode(), + KeyMatcher.MMB::matches + ) + ); + + triggers.register( + ControlTriggers.localOf( + "Test:SwitchPlacingModeWheel", + WheelScrollEvent.class, + () -> TestPlayerControls.getInstance().switchPlacingMode(), + e -> e.hasHorizontalMovement() || InputTracker.isKeyPressed(GLFW.GLFW_KEY_LEFT_CONTROL) + ) + ); + + triggers.register( + ControlTriggers.localOf( + "Test:SelectNextBlockOrTile", + WheelScrollEvent.class, + e -> TestPlayerControls.getInstance().selectNextBlockOrTile(e), + e -> !e.hasHorizontalMovement() && !InputTracker.isKeyPressed(GLFW.GLFW_KEY_LEFT_CONTROL) + ) + ); triggers.register( ControlTriggers.localOf( diff --git a/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java b/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java index 8c03c99..e1878da 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java +++ b/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java @@ -19,7 +19,6 @@ package ru.windcorp.progressia.test; import glm.Glm; -import glm.mat._3.Mat3; import glm.mat._4.Mat4; import glm.vec._3.Vec3; import org.lwjgl.glfw.GLFW; @@ -27,61 +26,29 @@ import ru.windcorp.progressia.client.ClientState; import ru.windcorp.progressia.client.graphics.GUI; import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend; import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; -import ru.windcorp.progressia.client.graphics.backend.InputTracker; import ru.windcorp.progressia.client.graphics.input.CursorMoveEvent; import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.client.graphics.input.KeyEvent; import ru.windcorp.progressia.client.graphics.input.WheelScrollEvent; import ru.windcorp.progressia.client.graphics.world.LocalPlayer; import ru.windcorp.progressia.client.localization.Localizer; -import ru.windcorp.progressia.common.Units; import ru.windcorp.progressia.common.util.Matrices; import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.tile.TileData; -import ru.windcorp.progressia.server.ServerState; +import ru.windcorp.progressia.test.controls.MovementControls; public class TestPlayerControls { - private static TestPlayerControls instance = new TestPlayerControls(); + private static final TestPlayerControls INSTANCE = new TestPlayerControls(); public static TestPlayerControls getInstance() { - return instance; + return INSTANCE; } - - private static final double MODE_SWITCH_MAX_DELAY = 300 * Units.MILLISECONDS; - private static final double MODE_SPRINT_SWITCH_MAX_DELAY = 100 * Units.MILLISECONDS; - private static final double MIN_JUMP_DELAY = 300 * Units.MILLISECONDS; - - // Horizontal and vertical max control speed when flying - private static final float FLYING_SPEED = Units.get("6 m/s"); - - // (0; 1], 1 is instant change, 0 is no control authority - private static final float FLYING_CONTROL_AUTHORITY = Units.get("2 1/s"); - - // Horizontal max control speed when walking - private static final float WALKING_SPEED = Units.get("4 m/s"); - - // Horizontal max control speed when sprinting - private static final float SPRINTING_SPEED = Units.get("6 m/s"); - - // (0; 1], 1 is instant change, 0 is no control authority - private static final float WALKING_CONTROL_AUTHORITY = Units.get("15 1/s"); - - // Vertical velocity instantly added to player when they jump - private static final float JUMP_VELOCITY = 5f * Units.METERS_PER_SECOND; - - private boolean isFlying = true; - private boolean isSprinting = false; - - private int movementForward = 0; - private int movementRight = 0; - private int movementUp = 0; - - private double lastSpacePress = Double.NEGATIVE_INFINITY; - private double lastSprintPress = Double.NEGATIVE_INFINITY; + + private final MovementControls movementControls = new MovementControls(); private int selectedBlock = 0; private int selectedTile = 0; @@ -90,75 +57,30 @@ public class TestPlayerControls { private LayerTestGUI debugLayer = null; private Runnable updateCallback = null; + { + reset(); + } + public static void resetInstance() { - instance = new TestPlayerControls(); + INSTANCE.reset(); + } + + private void reset() { + movementControls.reset(); + + debugLayer = null; + updateCallback = null; + selectedBlock = 0; + selectedTile = 0; + isBlockSelected = true; } public void applyPlayerControls() { - if (ClientState.getInstance() == null || !ClientState.getInstance().isReady()) { - return; - } - - EntityData player = getEntity(); - - final float speed, authority; - - if (isFlying) { - speed = FLYING_SPEED; - authority = FLYING_CONTROL_AUTHORITY; - } else { - speed = isSprinting ? SPRINTING_SPEED : WALKING_SPEED; - authority = WALKING_CONTROL_AUTHORITY; - } - - Mat3 movementTransform = getMovementTransform(player, null); - Vec3 desiredVelocity = new Vec3(movementForward, movementRight, 0); - if (movementForward != 0 && movementRight != 0) { - desiredVelocity.normalize(); - } - desiredVelocity.z = movementUp; - movementTransform.mul_(desiredVelocity); // bug in jglm, .mul() and .mul_() are - // swapped - desiredVelocity.mul(speed); - - Vec3 newVelocity = new Vec3() - .set(desiredVelocity) - .sub(player.getVelocity()) - .mul((float) Math.exp(-authority * GraphicsInterface.getFrameLength())) - .negate() - .add(desiredVelocity); - - if (!isFlying) { - Vec3 up = player.getUpVector(); - Vec3 wantedVertical = VectorUtil.projectOnVector(player.getVelocity(), up, null); - VectorUtil.projectOnSurface(newVelocity, up).add(wantedVertical); - } - - player.getVelocity().set(newVelocity); - - // THIS IS TERRIBLE TEST - EntityData serverEntity = ServerState.getInstance().getWorld().getData() - .getEntity(TestContent.PLAYER_ENTITY_ID); - if (serverEntity != null) { - serverEntity.setPosition(player.getPosition()); - } - + movementControls.applyPlayerControls(); } - - private Mat3 getMovementTransform(EntityData player, Mat3 mat) { - if (mat == null) { - mat = new Mat3(); - } - - Vec3 f = player.getForwardVector(null); - Vec3 u = player.getUpVector(); - Vec3 s = u.cross_(f); - - return mat.set( - +f.x, +f.y, +f.z, - -s.x, -s.y, -s.z, - +u.x, +u.y, +u.z - ); + + public void registerControls() { + movementControls.registerControls(); } public void handleInput(InputEvent event) { @@ -169,81 +91,39 @@ public class TestPlayerControls { } else if (event instanceof CursorMoveEvent) { onMouseMoved((CursorMoveEvent) event); event.consume(); - } else if (event instanceof WheelScrollEvent) { - onWheelScroll((WheelScrollEvent) event); - event.consume(); } } private boolean onKeyEvent(KeyEvent event) { - if (event.isRepeat()) + if (!event.isPress()) return false; - int multiplier = event.isPress() ? 1 : -1; switch (event.getKey()) { - case GLFW.GLFW_KEY_W: - movementForward += +1 * multiplier; - handleSprint(event); - break; - case GLFW.GLFW_KEY_S: - movementForward += -1 * multiplier; - break; - case GLFW.GLFW_KEY_A: - movementRight += -1 * multiplier; - break; - case GLFW.GLFW_KEY_D: - movementRight += +1 * multiplier; - break; - case GLFW.GLFW_KEY_SPACE: - handleSpace(multiplier); - break; - case GLFW.GLFW_KEY_LEFT_SHIFT: - handleShift(multiplier); - break; case GLFW.GLFW_KEY_ESCAPE: - if (!event.isPress()) - return false; - handleEscape(); break; case GLFW.GLFW_KEY_F11: - if (!event.isPress()) - return false; GraphicsInterface.makeFullscreen(!GraphicsBackend.isFullscreen()); updateGUI(); break; case GLFW.GLFW_KEY_F12: - if (!event.isPress()) - return false; GraphicsBackend.setVSyncEnabled(!GraphicsBackend.isVSyncEnabled()); updateGUI(); break; case GLFW.GLFW_KEY_F3: - if (!event.isPress()) - return false; handleDebugLayerSwitch(); break; case GLFW.GLFW_KEY_F5: - if (!event.isPress()) - return false; handleCameraMode(); break; case GLFW.GLFW_KEY_L: - if (!event.isPress()) - return false; handleLanguageSwitch(); break; - case GLFW.GLFW_MOUSE_BUTTON_3: - if (!event.isPress()) - return false; - switchPlacingMode(); - break; - default: return false; } @@ -251,70 +131,7 @@ public class TestPlayerControls { return true; } - private void handleSpace(int multiplier) { - boolean isPressed = multiplier > 0; - - double timeSinceLastSpacePress = GraphicsInterface.getTime() - lastSpacePress; - - if (isPressed && timeSinceLastSpacePress < MODE_SWITCH_MAX_DELAY) { - isSprinting = false; - isFlying = !isFlying; - updateGUI(); - movementUp = +1; - } else { - if (isFlying) { - movementUp += +1 * multiplier; - } else { - if (isPressed && timeSinceLastSpacePress > MIN_JUMP_DELAY) { - jump(); - } - } - } - - lastSpacePress = GraphicsInterface.getTime(); - } - - private void handleSprint(KeyEvent event) { - - double timeSinceLastSpacePress = GraphicsInterface.getTime() - lastSprintPress; - - if (event.isPress() && timeSinceLastSpacePress < MODE_SPRINT_SWITCH_MAX_DELAY && !isFlying) { - isSprinting = !isSprinting; - updateGUI(); - } - - lastSprintPress = GraphicsInterface.getTime(); - - if (isSprinting && event.isRelease()) { - isSprinting = false; - updateGUI(); - } - } - - private void jump() { - if (ClientState.getInstance() == null || !ClientState.getInstance().isReady()) { - return; - } - - Vec3 up = getEntity().getUpVector(); - - getEntity().getVelocity().add( - up.x * JUMP_VELOCITY, - up.y * JUMP_VELOCITY, - up.z * JUMP_VELOCITY - ); - } - - private void handleShift(int multiplier) { - if (isFlying) { - movementUp += -1 * multiplier; - } - } - private void handleEscape() { - movementForward = 0; - movementRight = 0; - movementUp = 0; GUI.addTopLayer(new LayerButtonTest()); } @@ -390,15 +207,12 @@ public class TestPlayerControls { Matrices.release(mat); } - private void onWheelScroll(WheelScrollEvent event) { - if (event.hasHorizontalMovement()) { - switchPlacingMode(); - } - if (InputTracker.isKeyPressed(GLFW.GLFW_KEY_LEFT_CONTROL)) { - switchPlacingMode(); - return; - } - + public void switchPlacingMode() { + isBlockSelected = !isBlockSelected; + updateGUI(); + } + + public void selectNextBlockOrTile(WheelScrollEvent event) { if (isBlockSelected) { selectedBlock += event.isUp() ? +1 : -1; @@ -424,11 +238,6 @@ public class TestPlayerControls { updateGUI(); } - private void switchPlacingMode() { - isBlockSelected = !isBlockSelected; - updateGUI(); - } - public EntityData getEntity() { return getPlayer().getEntity(); } @@ -442,13 +251,9 @@ public class TestPlayerControls { this.updateCallback.run(); } } - - public boolean isFlying() { - return isFlying; - } - - public boolean isSprinting() { - return isSprinting; + + public MovementControls getMovementControls() { + return movementControls; } public BlockData getSelectedBlock() { @@ -462,5 +267,13 @@ public class TestPlayerControls { public boolean isBlockSelected() { return isBlockSelected; } + + public boolean isFlying() { + return movementControls.isFlying(); + } + + public boolean isSprinting() { + return movementControls.isSprinting(); + } } diff --git a/src/main/java/ru/windcorp/progressia/test/controls/MovementControls.java b/src/main/java/ru/windcorp/progressia/test/controls/MovementControls.java new file mode 100644 index 0000000..14f6207 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/controls/MovementControls.java @@ -0,0 +1,287 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ +package ru.windcorp.progressia.test.controls; + +import org.lwjgl.glfw.GLFW; + +import glm.mat._3.Mat3; +import glm.vec._3.Vec3; +import ru.windcorp.progressia.client.ClientState; +import ru.windcorp.progressia.client.comms.controls.ControlTriggerRegistry; +import ru.windcorp.progressia.client.comms.controls.ControlTriggers; +import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; +import ru.windcorp.progressia.client.graphics.backend.InputTracker; +import ru.windcorp.progressia.client.graphics.input.KeyEvent; +import ru.windcorp.progressia.client.graphics.input.KeyMatcher; +import ru.windcorp.progressia.common.Units; +import ru.windcorp.progressia.common.util.VectorUtil; +import ru.windcorp.progressia.common.world.entity.EntityData; +import ru.windcorp.progressia.server.ServerState; +import ru.windcorp.progressia.test.TestContent; + +public class MovementControls { + + /** + * Max delay between space presses that can toggle flying + */ + private static final double FLYING_SWITCH_MAX_DELAY = Units.get("300 ms"); + + /** + * Max delay between W presses that can toggle sprinting + */ + private static final double SPRINTING_SWITCH_MAX_DELAY = Units.get("300 ms"); + + /** + * Min delay between jumps + */ + private static final double JUMP_MIN_DELAY = Units.get("300 ms"); + + /** + * Horizontal and vertical max control speed when flying + */ + private static final float FLYING_SPEED = Units.get("6 m/s"); + + /** + * (0; 1], 1 is instant change, 0 is no control authority + */ + private static final float FLYING_CONTROL_AUTHORITY = Units.get("2 1/s"); + + /** + * Horizontal max control speed when walking + */ + private static final float WALKING_SPEED = Units.get("4 m/s"); + + /** + * Horizontal max control speed when sprinting + */ + private static final float SPRINTING_SPEED = Units.get("6 m/s"); + + /** + * (0; 1], 1 is instant change, 0 is no control authority + */ + private static final float WALKING_CONTROL_AUTHORITY = Units.get("15 1/s"); + + /** + * Vertical velocity instantly added to player when they jump + */ + private static final float JUMP_VELOCITY = Units.get("5 m/s"); + + private boolean isFlying; + private boolean isSprinting; + + private double lastSpacePress; + private double lastSprintPress; + + { + reset(); + } + + public void applyPlayerControls() { + if (ClientState.getInstance() == null || !ClientState.getInstance().isReady()) { + return; + } + + EntityData player = ClientState.getInstance().getLocalPlayer().getEntity(); + assert player != null; + + final float speed, authority; + + if (isFlying) { + speed = FLYING_SPEED; + authority = FLYING_CONTROL_AUTHORITY; + } else { + speed = isSprinting ? SPRINTING_SPEED : WALKING_SPEED; + authority = WALKING_CONTROL_AUTHORITY; + } + + Mat3 movementTransform = getMovementTransform(player, null); + Vec3 desiredVelocity = getDesiredVelocity(movementTransform, speed); + Vec3 newVelocity = getNewVelocity(desiredVelocity, player.getVelocity(), authority, player.getUpVector()); + player.getVelocity().set(newVelocity); + + tmp_syncServerEntity(); + } + + private void tmp_syncServerEntity() { + // THIS IS TERRIBLE TEST + EntityData serverEntity = ServerState.getInstance().getWorld().getData() + .getEntity(TestContent.PLAYER_ENTITY_ID); + if (serverEntity != null) { + ClientState.getInstance().getLocalPlayer().getEntity().copy(serverEntity); + } + } + + private Mat3 getMovementTransform(EntityData player, Mat3 mat) { + if (mat == null) { + mat = new Mat3(); + } + + Vec3 f = player.getForwardVector(null); + Vec3 u = player.getUpVector(); + Vec3 s = f.cross_(u); + + //@formatter:off + return mat.set( + f.x, f.y, f.z, + s.x, s.y, s.z, + u.x, u.y, u.z + ); + //@formatter:on + } + + private Vec3 getDesiredVelocity(Mat3 movementTransform, float speed) { + int forward = 0; + int right = 0; + int up = 0; + + forward += InputTracker.isKeyPressed(GLFW.GLFW_KEY_W) ? 1 : 0; + forward -= InputTracker.isKeyPressed(GLFW.GLFW_KEY_S) ? 1 : 0; + + right += InputTracker.isKeyPressed(GLFW.GLFW_KEY_D) ? 1 : 0; + right -= InputTracker.isKeyPressed(GLFW.GLFW_KEY_A) ? 1 : 0; + + if (isFlying) { + up += InputTracker.isKeyPressed(GLFW.GLFW_KEY_SPACE) ? 1 : 0; + up -= InputTracker.isKeyPressed(GLFW.GLFW_KEY_LEFT_SHIFT) ? 1 : 0; + } + + Vec3 desiredVelocity = new Vec3(forward, right, 0); + if (forward != 0 && right != 0) { + desiredVelocity.normalize(); + } + desiredVelocity.z = up; + + // bug in jglm, .mul() and .mul_() are swapped + movementTransform.mul_(desiredVelocity); + desiredVelocity.mul(speed); + + return desiredVelocity; + } + + private Vec3 getNewVelocity(Vec3 desiredVelocity, Vec3 oldVelocity, float authority, Vec3 up) { + + // newVelocity = oldVelocity + small change toward desiredVelocity + Vec3 newVelocity = new Vec3() + .set(desiredVelocity) + .sub(oldVelocity) + .mul((float) Math.exp(-authority * GraphicsInterface.getFrameLength())) + .negate() + .add(desiredVelocity); + + // If we aren't flying, don't change vertical component + if (!isFlying) { + Vec3 wantedVertical = VectorUtil.projectOnVector(oldVelocity, up, null); + VectorUtil.projectOnSurface(newVelocity, up); + newVelocity.add(wantedVertical); + } + + return newVelocity; + } + + public void reset() { + isFlying = true; + isSprinting = false; + lastSpacePress = Double.NEGATIVE_INFINITY; + lastSprintPress = Double.NEGATIVE_INFINITY; + } + + public void registerControls() { + ControlTriggerRegistry triggers = ControlTriggerRegistry.getInstance(); + + triggers.register( + ControlTriggers.localOf( + "Test:JumpOrToggleFlight", + KeyEvent.class, + this::handleSpacePress, + new KeyMatcher("Space")::matches + ) + ); + + triggers.register( + ControlTriggers.localOf( + "Test:ToggleSprint", + KeyEvent.class, + this::toggleSprint, + + new KeyMatcher("W")::matches, + e -> !isFlying + ) + ); + + triggers.register( + ControlTriggers.localOf( + "Test:DisableSprint", + KeyEvent.class, + this::disableSprint, + + new KeyMatcher("W")::matchesIgnoringAction, + KeyEvent::isRelease + ) + ); + } + + private void handleSpacePress(KeyEvent e) { + double timeSinceLastSpacePress = e.getTime() - lastSpacePress; + + if (timeSinceLastSpacePress < FLYING_SWITCH_MAX_DELAY) { + isSprinting = false; + isFlying = !isFlying; + } else if (!isFlying && timeSinceLastSpacePress >= JUMP_MIN_DELAY) { + jump(); + } + + lastSpacePress = e.getTime(); + } + + private void jump() { + if (ClientState.getInstance() == null || !ClientState.getInstance().isReady()) { + return; + } + + EntityData player = ClientState.getInstance().getLocalPlayer().getEntity(); + assert player != null; + + Vec3 up = player.getUpVector(); + + player.getVelocity().add( + up.x * JUMP_VELOCITY, + up.y * JUMP_VELOCITY, + up.z * JUMP_VELOCITY + ); + } + + private void toggleSprint(KeyEvent e) { + if (e.getTime() - lastSprintPress < SPRINTING_SWITCH_MAX_DELAY) { + isSprinting = !isSprinting; + } + lastSprintPress = e.getTime(); + } + + private void disableSprint(KeyEvent e) { + isSprinting = false; + } + + public boolean isFlying() { + return isFlying; + } + + public boolean isSprinting() { + return isSprinting; + } + +} diff --git a/src/main/resources/assets/languages/en-US.lang b/src/main/resources/assets/languages/en-US.lang index b3de478..bc8b1a9 100644 --- a/src/main/resources/assets/languages/en-US.lang +++ b/src/main/resources/assets/languages/en-US.lang @@ -4,8 +4,6 @@ LayerAbout.Title = Progressia LayerAbout.Version = Version: %s LayerAbout.DebugHint = Debug GUI: F3 -LayerTestGUI.IsFlyingDisplay = Flying: %5s (Space bar x2) -LayerTestGUI.IsSprintingDisplay = Sprinting: %5s (W x2) LayerTestGUI.CameraModeDisplay = Camera mode: %5d (F5) LayerTestGUI.LanguageDisplay = Language: %5s (L) LayerTestGUI.FPSDisplay = FPS: diff --git a/src/main/resources/assets/languages/ru-RU.lang b/src/main/resources/assets/languages/ru-RU.lang index 69e07f2..0169f47 100644 --- a/src/main/resources/assets/languages/ru-RU.lang +++ b/src/main/resources/assets/languages/ru-RU.lang @@ -4,8 +4,6 @@ LayerAbout.Title = Прогрессия LayerAbout.Version = Версия: %s LayerAbout.DebugHint = Отладочный GUI: F3 -LayerTestGUI.IsFlyingDisplay = Полёт: %5s (Пробел x2) -LayerTestGUI.IsSprintingDisplay = Бег: %5s (W x2) LayerTestGUI.CameraModeDisplay = Камера: %5d (F5) LayerTestGUI.LanguageDisplay = Язык: %5s (L) LayerTestGUI.FPSDisplay = FPS: From 49d283e7a3c3991da3f44458352db85cfc894cfd Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Mon, 13 Dec 2021 17:03:23 +0300 Subject: [PATCH 44/49] Refactored F3 layer - Renamed from LayerTestGUI to LayerDebug - Many of the displays have been removed - Fullscreen and VSync displays have been merged with FPS display - Updates are automatic --- .../windcorp/progressia/test/LayerDebug.java | 260 +++++++++++ .../progressia/test/LayerTestGUI.java | 406 ------------------ .../progressia/test/TestPlayerControls.java | 21 +- .../resources/assets/languages/en-US.lang | 24 +- .../resources/assets/languages/ru-RU.lang | 24 +- 5 files changed, 282 insertions(+), 453 deletions(-) create mode 100755 src/main/java/ru/windcorp/progressia/test/LayerDebug.java delete mode 100755 src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java diff --git a/src/main/java/ru/windcorp/progressia/test/LayerDebug.java b/src/main/java/ru/windcorp/progressia/test/LayerDebug.java new file mode 100755 index 0000000..f6509d5 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/LayerDebug.java @@ -0,0 +1,260 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * 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 . + */ + +package ru.windcorp.progressia.test; + +import glm.vec._3.Vec3; +import ru.windcorp.progressia.client.Client; +import ru.windcorp.progressia.client.ClientState; +import ru.windcorp.progressia.client.graphics.Colors; +import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend; +import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; +import ru.windcorp.progressia.client.graphics.font.Font; +import ru.windcorp.progressia.client.graphics.gui.DynamicLabel; +import ru.windcorp.progressia.client.graphics.gui.GUILayer; +import ru.windcorp.progressia.client.graphics.gui.Label; +import ru.windcorp.progressia.client.graphics.gui.Group; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical; +import ru.windcorp.progressia.client.localization.Localizer; +import ru.windcorp.progressia.client.localization.MutableString; +import ru.windcorp.progressia.client.localization.MutableStringLocalized; +import ru.windcorp.progressia.client.world.WorldRender; +import ru.windcorp.progressia.common.Units; +import ru.windcorp.progressia.common.util.dynstr.DynamicStrings; +import ru.windcorp.progressia.server.Server; +import ru.windcorp.progressia.server.ServerState; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Supplier; + +public class LayerDebug extends GUILayer { + + private final List updateTriggers = new ArrayList<>(); + + public LayerDebug() { + super("LayerDebug", new LayoutAlign(0, 1, 5)); + getRoot().addChild(new Group("Displays", new LayoutVertical(5))); + + TestPlayerControls tpc = TestPlayerControls.getInstance(); + + addDynamicDisplay( + "FPSDisplay", + DynamicStrings.builder() + .addDyn(new MutableStringLocalized("LayerDebug.FPSDisplay")) + .addDyn(() -> FPS_RECORD.update(GraphicsInterface.getFPS()), 5, 1) + .addDyn(() -> GraphicsBackend.isFullscreen() ? " Fullscreen" : "") + .addDyn(() -> GraphicsBackend.isVSyncEnabled() ? " VSync" : "") + .buildSupplier() + ); + + addDynamicDisplay("TPSDisplay", LayerDebug::getTPS); + + addDynamicDisplay( + "ChunkStatsDisplay", + DynamicStrings.builder() + .addDyn(new MutableStringLocalized("LayerDebug.ChunkStatsDisplay")) + .addDyn(() -> { + if (ClientState.getInstance() == null) { + return -1; + } else { + WorldRender world = ClientState.getInstance().getWorld(); + return world.getChunks().size() - world.getPendingChunkUpdates(); + } + }, 4) + .add('/') + .addDyn(() -> { + if (ClientState.getInstance() == null) { + return -1; + } else { + return ClientState.getInstance().getWorld().getPendingChunkUpdates(); + } + }, 4) + .add('/') + .addDyn(() -> { + if (ServerState.getInstance() == null) { + return -1; + } else { + return ServerState.getInstance().getWorld().getChunks().size(); + } + }, 4) + .buildSupplier() + ); + + addDynamicDisplay("PosDisplay", LayerDebug::getPos); + + addDisplay("SelectedBlockDisplay", () -> tpc.isBlockSelected() ? ">" : " ", () -> tpc.getSelectedBlock().getId()); + addDisplay("SelectedTileDisplay", () -> tpc.isBlockSelected() ? " " : ">", () -> tpc.getSelectedTile().getId()); + addDisplay("PlacementModeHint", () -> "\u2B04"); + } + + private void addDisplay(String name, Supplier... params) { + Font font = new Font().withColor(Colors.WHITE).deriveOutlined(); + Label component = new Label(name, font, tmp_dynFormat("LayerDebug." + name, params)); + getRoot().getChild(0).addChild(component); + + for (Supplier param : params) { + if (param == null) { + continue; + } + + updateTriggers.add(new Runnable() { + + private Object displayedValue; + + @Override + public void run() { + Object newValue = param.get(); + if (!Objects.equals(newValue, displayedValue)) { + component.update(); + } + displayedValue = newValue; + } + + }); + } + } + + private void addDynamicDisplay(String name, Supplier contents) { + Font font = new Font().withColor(Colors.WHITE).deriveOutlined(); + DynamicLabel component = new DynamicLabel(name, font, contents, 128); + getRoot().getChild(0).addChild(component); + } + + @Override + protected void doRender() { + updateTriggers.forEach(Runnable::run); + super.doRender(); + } + + private static class Averager { + + private static final int DISPLAY_INERTIA = 32; + private static final double UPDATE_INTERVAL = Units.get(50.0, "ms"); + + private final double[] values = new double[DISPLAY_INERTIA]; + private int size; + private int head; + + private long lastUpdate; + + public void add(double value) { + if (size == values.length) { + values[head] = value; + head++; + if (head == values.length) + head = 0; + } else { + values[size] = value; + size++; + } + } + + public double average() { + double product = 1; + + if (size == values.length) { + for (double d : values) + product *= d; + } else { + for (int i = 0; i < size; ++i) + product *= values[i]; + } + + return Math.pow(product, 1.0 / size); + } + + public double update(double value) { + long now = (long) (GraphicsInterface.getTime() / UPDATE_INTERVAL); + if (lastUpdate != now) { + lastUpdate = now; + add(value); + } + + return average(); + } + + } + + private static final String[] CLOCK_CHARS = "\u2591\u2598\u259d\u2580\u2596\u258c\u259e\u259b\u2597\u259a\u2590\u259c\u2584\u2599\u259f\u2588" + .chars().mapToObj(c -> ((char) c) + "").toArray(String[]::new); + + private static String getTPSClockChar() { + return CLOCK_CHARS[(int) (ServerState.getInstance().getUptimeTicks() % CLOCK_CHARS.length)]; + } + + private static final Averager FPS_RECORD = new Averager(); + private static final Averager TPS_RECORD = new Averager(); + + private static final Supplier TPS_STRING = DynamicStrings.builder() + .addDyn(new MutableStringLocalized("LayerDebug.TPSDisplay")) + .addDyn(() -> TPS_RECORD.update(ServerState.getInstance().getTPS()), 5, 1) + .add(' ') + .addDyn(LayerDebug::getTPSClockChar) + .buildSupplier(); + + private static final Supplier POS_STRING = DynamicStrings.builder() + .addDyn(new MutableStringLocalized("LayerDebug.PosDisplay")) + .addDyn(() -> ClientState.getInstance().getCamera().getLastAnchorPosition().x, 7, 1) + .addDyn(() -> ClientState.getInstance().getCamera().getLastAnchorPosition().y, 7, 1) + .addDyn(() -> ClientState.getInstance().getCamera().getLastAnchorPosition().z, 7, 1) + .buildSupplier(); + + private static CharSequence getTPS() { + Server server = ServerState.getInstance(); + if (server == null) + return Localizer.getInstance().getValue("LayerDebug.TPSDisplay.NA"); + + return TPS_STRING.get(); + } + + private static CharSequence getPos() { + Client client = ClientState.getInstance(); + if (client == null) + return Localizer.getInstance().getValue("LayerDebug.PosDisplay.NA.Client"); + + Vec3 pos = client.getCamera().getLastAnchorPosition(); + if (Float.isNaN(pos.x)) { + return Localizer.getInstance().getValue("LayerDebug.PosDisplay.NA.Entity"); + } else { + return POS_STRING.get(); + } + } + + private static MutableString tmp_dynFormat(String formatKey, Supplier... suppliers) { + return new MutableStringLocalized(formatKey).apply(s -> { + Object[] args = new Object[suppliers.length]; + + for (int i = 0; i < suppliers.length; ++i) { + Supplier supplier = suppliers[i]; + + Object value = supplier != null ? supplier.get() : "null"; + if (!(value instanceof Number)) { + value = Objects.toString(value); + } + + args[i] = value; + } + + return String.format(s, args); + }); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java b/src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java deleted file mode 100755 index faf9851..0000000 --- a/src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Progressia - * Copyright (C) 2020-2021 Wind Corporation and contributors - * - * 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 . - */ - -package ru.windcorp.progressia.test; - -import glm.vec._3.Vec3; -import glm.vec._4.Vec4; -import ru.windcorp.progressia.client.Client; -import ru.windcorp.progressia.client.ClientState; -import ru.windcorp.progressia.client.graphics.Colors; -import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend; -import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; -import ru.windcorp.progressia.client.graphics.font.Font; -import ru.windcorp.progressia.client.graphics.gui.DynamicLabel; -import ru.windcorp.progressia.client.graphics.gui.GUILayer; -import ru.windcorp.progressia.client.graphics.gui.Label; -import ru.windcorp.progressia.client.graphics.gui.Group; -import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; -import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical; -import ru.windcorp.progressia.client.localization.Localizer; -import ru.windcorp.progressia.client.localization.MutableString; -import ru.windcorp.progressia.client.localization.MutableStringLocalized; -import ru.windcorp.progressia.client.world.WorldRender; -import ru.windcorp.progressia.common.Units; -import ru.windcorp.progressia.common.util.dynstr.DynamicStrings; -import ru.windcorp.progressia.server.Server; -import ru.windcorp.progressia.server.ServerState; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Objects; -import java.util.function.Supplier; - -public class LayerTestGUI extends GUILayer { - - public LayerTestGUI() { - super("LayerTestGui", new LayoutAlign(0, 1, 5)); - - Group group = new Group("ControlDisplays", new LayoutVertical(5)); - - Vec4 color = Colors.WHITE; - Font font = new Font().withColor(color).deriveOutlined(); - - TestPlayerControls tpc = TestPlayerControls.getInstance(); - - group.addChild( - new Label( - "CameraModeDisplay", - font, - tmp_dynFormat( - "LayerTestGUI.CameraModeDisplay", - ClientState.getInstance().getCamera()::getCurrentModeIndex - ) - ) - ); - - group.addChild( - new Label( - "LanguageDisplay", - font, - tmp_dynFormat("LayerTestGUI.LanguageDisplay", Localizer.getInstance()::getLanguage) - ) - ); - - group.addChild( - new Label( - "FullscreenDisplay", - font, - tmp_dynFormat("LayerTestGUI.IsFullscreen", GraphicsBackend::isFullscreen) - ) - ); - - group.addChild( - new Label( - "VSyncDisplay", - font, - tmp_dynFormat("LayerTestGUI.IsVSync", GraphicsBackend::isVSyncEnabled) - ) - ); - - group.addChild( - new DynamicLabel( - "FPSDisplay", - font, - DynamicStrings.builder() - .addDyn(new MutableStringLocalized("LayerTestGUI.FPSDisplay")) - .addDyn(() -> FPS_RECORD.update(GraphicsInterface.getFPS()), 5, 1) - .buildSupplier(), - 128 - ) - ); - - group.addChild( - new DynamicLabel( - "TPSDisplay", - font, - LayerTestGUI::getTPS, - 128 - ) - ); - - group.addChild( - new DynamicLabel( - "ChunkStatsDisplay", - font, - DynamicStrings.builder() - .addDyn(new MutableStringLocalized("LayerTestGUI.ChunkStatsDisplay")) - .addDyn(() -> { - if (ClientState.getInstance() == null) { - return -1; - } else { - WorldRender world = ClientState.getInstance().getWorld(); - return world.getChunks().size() - world.getPendingChunkUpdates(); - } - }, 4) - .add('/') - .addDyn(() -> { - if (ClientState.getInstance() == null) { - return -1; - } else { - return ClientState.getInstance().getWorld().getPendingChunkUpdates(); - } - }, 4) - .add('/') - .addDyn(() -> { - if (ServerState.getInstance() == null) { - return -1; - } else { - return ServerState.getInstance().getWorld().getChunks().size(); - } - }, 4) - .buildSupplier(), - 128 - ) - ); - - group.addChild( - new DynamicLabel( - "PosDisplay", - font, - LayerTestGUI::getPos, - 128 - ) - ); - - group.addChild( - new Label( - "SelectedBlockDisplay", - font, - tmp_dynFormat( - "LayerTestGUI.SelectedBlockDisplay", - () -> tpc.isBlockSelected() ? ">" : " ", - () -> tpc.getSelectedBlock().getId() - ) - ) - ); - group.addChild( - new Label( - "SelectedTileDisplay", - font, - tmp_dynFormat( - "LayerTestGUI.SelectedTileDisplay", - () -> tpc.isBlockSelected() ? " " : ">", - () -> tpc.getSelectedTile().getId() - ) - ) - ); - group.addChild( - new Label( - "PlacementModeHint", - font, - new MutableStringLocalized("LayerTestGUI.PlacementModeHint").format("\u2B04") - ) - ); - - getRoot().addChild(group); - } - - public Runnable getUpdateCallback() { - Collection