mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-18 18:23:06 +00:00
Merge remote-tracking branch 'upstream/master' into saplingOverrides
This commit is contained in:
commit
25bcd0f2a9
71
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
71
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
name: Iris Bug Report
|
||||
description: File a bug report for Iris
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to fill this out!
|
||||
If this does not work for you, feel free to use the [blank](https://github.com/VolmitSoftware/Iris/issues/new) format.
|
||||
- type: textarea
|
||||
id: how
|
||||
attributes:
|
||||
label: Problem
|
||||
description: Please give a text description of how you reached the problem
|
||||
value: |
|
||||
1. Install Iris...
|
||||
2. Do this...
|
||||
3. Do that...
|
||||
4. Observe the error...
|
||||
render: txt
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what
|
||||
attributes:
|
||||
label: Solution
|
||||
description: Explain where you think the problem comes from (optional)
|
||||
placeholder: The code to place a is missing b and c...
|
||||
validations:
|
||||
required: false
|
||||
- type: dropdown
|
||||
id: mcversion
|
||||
attributes:
|
||||
label: Minecraft Version
|
||||
description: What version of Minecraft is the server on?
|
||||
options:
|
||||
- 1.14 to 1.16.5
|
||||
- 1.17.x
|
||||
- 1.18.x
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: irisversion
|
||||
attributes:
|
||||
label: Iris Version
|
||||
description: What version of Iris are you running? (see console)
|
||||
placeholder: DO NOT SAY "LATEST"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: logs
|
||||
attributes:
|
||||
label: Log
|
||||
description: Paste a full log. Always use [mclogs](https://mclo.gs) Or [Pastebin](https://pastebin.com/). Must not be a crash report. Must be a full log. Must not be a screenshot of a log.
|
||||
placeholder: https://mslog.gs/...
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: checksum
|
||||
attributes:
|
||||
label: Checklist
|
||||
description: Please ensure you meet each of the requirements below
|
||||
options:
|
||||
- label: I am using an unmodified version of Iris. (If you modified the plugin and see an issue, make sure it is reproducable on the latest spigot version or contact [support](discord.gg/volmit))
|
||||
required: true
|
||||
- label: I am using Spigot, Paper, Tuinity, or Purpur. (If you are not, and still think it is a valid issue, contact [support](discord.gg/volmit))
|
||||
required: true
|
||||
- type: markdown
|
||||
id: thanks
|
||||
attributes:
|
||||
value: "Thank you for filling out the form! We will be with you soon. Please do not ask support to review your report."
|
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,34 +0,0 @@
|
||||
---
|
||||
name: Bug report about: Create a report to help us improve title: ''
|
||||
labels: Bug assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots or Video Recordings**
|
||||
If applicable, add screenshots or video recordings to help explain your problem.
|
||||
|
||||
**Server and Plugin Information**
|
||||
|
||||
- Installed plugins:
|
||||
- Iris Version:
|
||||
- Server Platform and Version [eg: PaperSpigot 1.16.3 #240]:
|
||||
- Operating System (if applicable):
|
||||
- Server Logs:
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here, server timings reports, Iris dump information, complete console log etc.
|
||||
Please do not make Pastebin dumps or screenshot expire.
|
46
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
46
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
name: Iris Feature Request
|
||||
description: File a feature request for Iris. If you want to report a bug this is not the place.
|
||||
labels: [feature]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to fill this out!
|
||||
If this does not work for you, feel free to use the [blank](https://github.com/VolmitSoftware/Iris/issues/new) format.
|
||||
- type: dropdown
|
||||
id: arc
|
||||
attributes:
|
||||
label: Adding, Removing, or Changing
|
||||
description: What are you doing
|
||||
options:
|
||||
- Adding
|
||||
- Removing
|
||||
- Changing
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: atype
|
||||
attributes:
|
||||
label: Type of Modification
|
||||
description: What is it for?
|
||||
value: I want to ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: desc
|
||||
attributes:
|
||||
label: What are you trying to modify
|
||||
description: Give as detailed of a description as you can for the modification that you want done (include pictures if applicable)
|
||||
value: The way I would implement this is ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternative
|
||||
attributes:
|
||||
label: Alternatives
|
||||
description: What alternatives have you considered?
|
||||
value: If this could not be implemented I would ...
|
||||
- type: markdown
|
||||
id: thanks
|
||||
attributes:
|
||||
value: "Thank you for filling out the form! We will be with you soon. Please do not ask support to review your report."
|
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,17 +0,0 @@
|
||||
---
|
||||
name: Feature request about: Suggest an idea for this project title: ''
|
||||
labels: Enhancement, Addition assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
36
README.md
36
README.md
@ -3,7 +3,39 @@
|
||||
For 1.16 and below, see the 1.14-1.16 branch. The master branch is for the latest version of minecraft.
|
||||
|
||||
# [Support](https://discord.gg/3xxPTpT) **|** [Documentation](https://docs.volmit.com/iris/) **
|
||||
|
||||
|** [Git](https://github.com/IrisDimensions)
|
||||
|
||||

|
||||
## Iris Toolbelt
|
||||
|
||||
Everyone needs a toolbelt.
|
||||
|
||||
```java
|
||||
package com.volmit.iris.core.tools
|
||||
|
||||
// Get IrisDataManager from a world
|
||||
IrisToolbelt.access(anyWorld).getCompound().getData();
|
||||
|
||||
// Get Default Engine from world
|
||||
IrisToolbelt.access(anyWorld).getCompound().getDefaultEngine();
|
||||
|
||||
// Get the engine at the given height
|
||||
IrisToolbelt.access(anyWorld).getCompound().getEngineForHeight(68);
|
||||
|
||||
// IS THIS THING ON?
|
||||
boolean yes = IrisToolbelt.isIrisWorld(world);
|
||||
|
||||
// GTFO for worlds (moves players to any other world, just not this one)
|
||||
IrisToolbelt.evacuate(world);
|
||||
|
||||
IrisAccess access = IrisToolbelt.createWorld() // If you like builders...
|
||||
.name("myWorld") // The world name
|
||||
.dimension("terrifyinghands")
|
||||
.seed(69133742) // The world seed
|
||||
.headless(true) // Headless make gen go fast
|
||||
.pregen(PregenTask // Define a pregen job to run
|
||||
.builder()
|
||||
.center(new Position2(0,0)) // REGION coords (1 region = 32x32 chunks)
|
||||
.radius(4) // Radius in REGIONS. Rad of 4 means a 9x9 Region map.
|
||||
.build())
|
||||
.create();
|
||||
```
|
||||
|
@ -5,7 +5,7 @@ plugins {
|
||||
}
|
||||
|
||||
group 'com.volmit.iris'
|
||||
version '1.5.2'
|
||||
version '1.5.6'
|
||||
def apiVersion = '1.17'
|
||||
def name = 'Iris'
|
||||
def main = 'com.volmit.iris.Iris'
|
||||
@ -81,6 +81,8 @@ shadowJar
|
||||
}
|
||||
}
|
||||
|
||||
manifest()
|
||||
|
||||
dependencies {
|
||||
compileOnly 'org.projectlombok:lombok:1.18.20'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.20'
|
||||
|
@ -26,12 +26,13 @@ import com.volmit.iris.core.link.BKLink;
|
||||
import com.volmit.iris.core.link.MultiverseCoreLink;
|
||||
import com.volmit.iris.core.link.MythicMobsLink;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.engine.IrisWorlds;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.engine.framework.EngineCompositeGenerator;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisCompat;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.format.C;
|
||||
@ -79,9 +80,6 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
public static MythicMobsLink linkMythicMobs;
|
||||
public static TreeManager saplingManager;
|
||||
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
||||
public static boolean customModels = doesSupportCustomModels();
|
||||
public static boolean awareEntities = doesSupportAwareness();
|
||||
public static boolean lowMemoryMode = false;
|
||||
public static IrisCompat compat;
|
||||
public static FileWatcher configWatcher;
|
||||
|
||||
@ -95,7 +93,6 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
instance = this;
|
||||
INMS.get();
|
||||
IO.delete(new File("iris"));
|
||||
lowMemoryMode = Runtime.getRuntime().maxMemory() < 4000000000L; // 4 * 1000 * 1000 * 1000 // 4;
|
||||
installDataPacks();
|
||||
}
|
||||
|
||||
@ -156,54 +153,6 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
Iris.info("Data Packs Setup!");
|
||||
}
|
||||
|
||||
public static int getThreadCount() {
|
||||
int tc = IrisSettings.get().getConcurrency().getThreadCount();
|
||||
|
||||
if (tc <= 0) {
|
||||
int p = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
return p > 16 ? 16 : Math.max(p, 4);
|
||||
}
|
||||
|
||||
return tc;
|
||||
}
|
||||
|
||||
private static boolean doesSupport3DBiomes() {
|
||||
try {
|
||||
int v = Integer.parseInt(Bukkit.getBukkitVersion().split("\\Q-\\E")[0].split("\\Q.\\E")[1]);
|
||||
|
||||
return v >= 15;
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean doesSupportCustomModels() {
|
||||
try {
|
||||
int v = Integer.parseInt(Bukkit.getBukkitVersion().split("\\Q-\\E")[0].split("\\Q.\\E")[1]);
|
||||
|
||||
return v >= 14;
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean doesSupportAwareness() {
|
||||
try {
|
||||
int v = Integer.parseInt(Bukkit.getBukkitVersion().split("\\Q-\\E")[0].split("\\Q.\\E")[1]);
|
||||
|
||||
return v >= 15;
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
|
||||
@ -276,6 +225,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
board.disable();
|
||||
Bukkit.getScheduler().cancelTasks(this);
|
||||
HandlerList.unregisterAll((Plugin) this);
|
||||
MultiBurst.burst.shutdown();
|
||||
super.onDisable();
|
||||
}
|
||||
|
||||
@ -571,18 +521,6 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
}
|
||||
|
||||
Iris.info("\n\n " + new KList<>(splash).toString("\n") + "\n");
|
||||
|
||||
if (lowMemoryMode) {
|
||||
Iris.verbose("* Low Memory mode Activated! For better performance, allocate 4gb or more to this server.");
|
||||
}
|
||||
|
||||
if (!customModels) {
|
||||
Iris.verbose("* This version of minecraft does not support custom model data in loot items (1.14 and up). Iris will generate as normal, but loot will not have custom models.");
|
||||
}
|
||||
|
||||
if (!doesSupportAwareness()) {
|
||||
Iris.verbose("* This version of minecraft does not support entity awareness.");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -19,7 +19,7 @@
|
||||
package com.volmit.iris.core;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.IrisWorlds;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.util.board.BoardManager;
|
||||
|
@ -23,7 +23,7 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.report.Report;
|
||||
import com.volmit.iris.core.report.ReportType;
|
||||
import com.volmit.iris.engine.IrisWorldCreator;
|
||||
import com.volmit.iris.core.tools.IrisWorldCreator;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
@ -273,8 +273,9 @@ public class IrisProject {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generation Complete"));
|
||||
if (sender.isPlayer()) {
|
||||
sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generation Complete"));
|
||||
}
|
||||
});
|
||||
|
||||
//@builder
|
||||
@ -307,9 +308,9 @@ public class IrisProject {
|
||||
|
||||
public void close() {
|
||||
activeProvider.close();
|
||||
File folder = activeProvider.getTarget().getWorld().getWorldFolder();
|
||||
Iris.linkMultiverseCore.removeFromConfig(activeProvider.getTarget().getWorld().getName());
|
||||
Bukkit.unloadWorld(activeProvider.getTarget().getWorld().getName(), false);
|
||||
File folder = activeProvider.getTarget().getWorld().worldFolder();
|
||||
Iris.linkMultiverseCore.removeFromConfig(activeProvider.getTarget().getWorld().name());
|
||||
Bukkit.unloadWorld(activeProvider.getTarget().getWorld().name(), false);
|
||||
J.attemptAsync(() -> IO.delete(folder));
|
||||
activeProvider = null;
|
||||
}
|
||||
|
@ -56,14 +56,27 @@ public class IrisSettings {
|
||||
return getParallax().getParallaxRegionEvictionMS();
|
||||
}
|
||||
|
||||
public static int getThreadCount(int c) {
|
||||
if (c < 2 && c >= 0) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return Math.max(2, c < 0 ? Runtime.getRuntime().availableProcessors() / -c : c);
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsCache {
|
||||
public int streamingCacheSize = 8192;
|
||||
public int complexCacheSize = 131072;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class IrisSettingsConcurrency {
|
||||
public int threadCount = -1;
|
||||
public int engineThreadCount = -1;
|
||||
public int engineThreadPriority = 6;
|
||||
public int pregenThreadCount = -1;
|
||||
public int pregenThreadPriority = 8;
|
||||
public int miscThreadCount = -4;
|
||||
public int miscThreadPriority = 3;
|
||||
}
|
||||
|
||||
@Data
|
||||
@ -99,8 +112,7 @@ public class IrisSettings {
|
||||
public boolean systemEffects = true;
|
||||
public boolean systemEntitySpawnOverrides = true;
|
||||
public boolean systemEntityInitialSpawns = true;
|
||||
public int maxBiomeChildDepth = 5;
|
||||
|
||||
public int maxBiomeChildDepth = 4;
|
||||
}
|
||||
|
||||
@Data
|
||||
|
@ -33,6 +33,9 @@ public class CommandIris extends MortarCommand {
|
||||
@Command
|
||||
private CommandIrisCreate create;
|
||||
|
||||
@Command
|
||||
private CommandIrisVerify verify;
|
||||
|
||||
@Command
|
||||
private CommandIrisFix fix;
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
package com.volmit.iris.core.command;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.IrisWorlds;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.plugin.MortarCommand;
|
||||
|
@ -56,7 +56,7 @@ public class CommandIrisStudioClose extends MortarCommand {
|
||||
World f = null;
|
||||
|
||||
for (World i : Bukkit.getWorlds()) {
|
||||
if (i.getWorldFolder().getAbsolutePath().equals(Iris.proj.getActiveProject().getActiveProvider().getTarget().getWorld().getWorldFolder().getAbsolutePath())) {
|
||||
if (i.getWorldFolder().getAbsolutePath().equals(Iris.proj.getActiveProject().getActiveProvider().getTarget().getWorld().worldFolder().getAbsolutePath())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ package com.volmit.iris.core.command.studio;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.gui.IrisExplorer;
|
||||
import com.volmit.iris.core.gui.NoiseExplorerGUI;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.plugin.Command;
|
||||
import com.volmit.iris.util.plugin.MortarCommand;
|
||||
@ -57,7 +57,7 @@ public class CommandIrisStudioExplorer extends MortarCommand {
|
||||
return true;
|
||||
}
|
||||
|
||||
IrisExplorer.launch();
|
||||
NoiseExplorerGUI.launch();
|
||||
sender.sendMessage("Opening Noise Explorer!");
|
||||
}
|
||||
return true;
|
||||
|
@ -21,7 +21,7 @@ package com.volmit.iris.core.command.studio;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.gui.IrisExplorer;
|
||||
import com.volmit.iris.core.gui.NoiseExplorerGUI;
|
||||
import com.volmit.iris.engine.object.IrisGenerator;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
@ -63,14 +63,14 @@ public class CommandIrisStudioExplorerGenerator extends MortarCommand {
|
||||
|
||||
if (Iris.proj.isProjectOpen()) {
|
||||
generator = Iris.proj.getActiveProject().getActiveProvider().getData().getGeneratorLoader().load(args[0]);
|
||||
seed = Iris.proj.getActiveProject().getActiveProvider().getTarget().getWorld().getSeed();
|
||||
seed = Iris.proj.getActiveProject().getActiveProvider().getTarget().getWorld().seed();
|
||||
} else {
|
||||
generator = IrisDataManager.loadAnyGenerator(args[0]);
|
||||
}
|
||||
|
||||
if (generator != null) {
|
||||
long finalSeed = seed;
|
||||
IrisExplorer.launch((x, z) ->
|
||||
NoiseExplorerGUI.launch((x, z) ->
|
||||
generator.getHeight(x, z, new RNG(finalSeed).nextParallelRNG(3245).lmax()), "Gen: " + generator.getLoadKey());
|
||||
|
||||
sender.sendMessage("Opening Noise Explorer for gen " + generator.getLoadKey() + " (" + generator.getLoader().getDataFolder().getName() + ")");
|
||||
|
@ -20,7 +20,7 @@ package com.volmit.iris.core.command.studio;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.engine.IrisWorlds;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
|
@ -20,7 +20,7 @@ package com.volmit.iris.core.command.studio;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.IrisWorlds;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.plugin.MortarCommand;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
|
@ -20,7 +20,7 @@ package com.volmit.iris.core.command.studio;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.IrisWorlds;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.engine.object.InventorySlotType;
|
||||
import com.volmit.iris.engine.object.IrisLootTable;
|
||||
|
@ -20,8 +20,8 @@ package com.volmit.iris.core.command.studio;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.gui.IrisVision;
|
||||
import com.volmit.iris.engine.IrisWorlds;
|
||||
import com.volmit.iris.core.gui.VisionGUI;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
@ -57,12 +57,12 @@ public class CommandIrisStudioMap extends MortarCommand {
|
||||
|
||||
try {
|
||||
IrisAccess g = Iris.proj.getActiveProject().getActiveProvider();
|
||||
IrisVision.launch(g, 0);
|
||||
VisionGUI.launch(g, 0);
|
||||
sender.sendMessage("Opening Map!");
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
IrisAccess g = IrisWorlds.access(sender.player().getWorld());
|
||||
IrisVision.launch(g, 0);
|
||||
VisionGUI.launch(g, 0);
|
||||
sender.sendMessage("Opening Map!");
|
||||
}
|
||||
return true;
|
||||
|
@ -20,7 +20,7 @@ package com.volmit.iris.core.command.studio;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.IrisWorlds;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.engine.object.IrisEntity;
|
||||
|
@ -57,7 +57,7 @@ public class CommandIrisStudioTPStudio extends MortarCommand {
|
||||
|
||||
try {
|
||||
sender.sendMessage("Teleporting you to the active studio world.");
|
||||
sender.player().teleport(Iris.proj.getActiveProject().getActiveProvider().getTarget().getWorld().getSpawnLocation());
|
||||
sender.player().teleport(Iris.proj.getActiveProject().getActiveProvider().getTarget().getWorld().spawnLocation());
|
||||
sender.player().setGameMode(GameMode.SPECTATOR);
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
|
@ -20,7 +20,7 @@ package com.volmit.iris.core.command.what;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.engine.IrisWorlds;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
|
@ -19,7 +19,7 @@
|
||||
package com.volmit.iris.core.command.what;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.IrisWorlds;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
|
@ -21,10 +21,9 @@ package com.volmit.iris.core.command.world;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.gui.Pregenerator;
|
||||
import com.volmit.iris.core.link.MultiverseCoreLink;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.engine.IrisWorldCreator;
|
||||
import com.volmit.iris.core.tools.IrisWorldCreator;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
@ -161,8 +160,7 @@ public class CommandIrisCreate extends MortarCommand {
|
||||
sender.sendMessage("Pregenerating " + worldName + " " + size + " x " + size);
|
||||
sender.sendMessage("Expect server lag during this time. Use '/iris pregen stop' to cancel");
|
||||
|
||||
new Pregenerator(world.get(), size, () ->
|
||||
b.set(true));
|
||||
|
||||
}
|
||||
|
||||
World ww = world.get();
|
||||
@ -223,7 +221,6 @@ public class CommandIrisCreate extends MortarCommand {
|
||||
.productionMode().seed(seed).create();
|
||||
|
||||
J.s(() -> {
|
||||
sender.sendMessage("Generating with " + Iris.getThreadCount() + " threads per chunk");
|
||||
O<Boolean> done = new O<>();
|
||||
done.set(false);
|
||||
|
||||
@ -249,15 +246,6 @@ public class CommandIrisCreate extends MortarCommand {
|
||||
|
||||
World w = INMS.get().createWorld(wc);
|
||||
world.set(w);
|
||||
|
||||
try {
|
||||
if (pregen.get() > 0) {
|
||||
new Pregenerator(w, pregen.get());
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
done.set(true);
|
||||
});
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
package com.volmit.iris.core.command.world;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.IrisWorlds;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
|
@ -19,8 +19,12 @@
|
||||
package com.volmit.iris.core.command.world;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.gui.Pregenerator;
|
||||
import com.volmit.iris.core.gui.PregeneratorJob;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.pregenerator.methods.HybridPregenMethod;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.plugin.MortarCommand;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -69,17 +73,17 @@ public class CommandIrisPregen extends MortarCommand {
|
||||
}
|
||||
|
||||
if (args[0].equalsIgnoreCase("stop") || args[0].equalsIgnoreCase("x")) {
|
||||
if (Pregenerator.shutdownInstance()) {
|
||||
sender.sendMessage("Stopped Pregen.");
|
||||
if (PregeneratorJob.shutdownInstance()) {
|
||||
sender.sendMessage("Stopped Pregen. Finishing last region file before shutting down...");
|
||||
} else {
|
||||
sender.sendMessage("No Active Pregens.");
|
||||
}
|
||||
return true;
|
||||
} else if (args[0].equalsIgnoreCase("pause") || args[0].equalsIgnoreCase("resume")) {
|
||||
if (Pregenerator.getInstance() != null) {
|
||||
Pregenerator.pauseResume();
|
||||
if (PregeneratorJob.getInstance() != null) {
|
||||
PregeneratorJob.pauseResume();
|
||||
|
||||
if (Pregenerator.isPaused()) {
|
||||
if (PregeneratorJob.isPaused()) {
|
||||
sender.sendMessage("Pregen Paused");
|
||||
} else {
|
||||
sender.sendMessage("Pregen Resumed");
|
||||
@ -105,7 +109,11 @@ public class CommandIrisPregen extends MortarCommand {
|
||||
}
|
||||
}
|
||||
try {
|
||||
new Pregenerator(world, getVal(args[0]) * 2);
|
||||
IrisToolbelt.pregenerate(PregenTask
|
||||
.builder()
|
||||
.center(new Position2(0, 0))
|
||||
.radius(((getVal(args[0]) >> 4) >> 5) + 1)
|
||||
.build(), world);
|
||||
} catch (NumberFormatException e) {
|
||||
Iris.reportError(e);
|
||||
sender.sendMessage("Invalid argument in command");
|
||||
@ -131,7 +139,12 @@ public class CommandIrisPregen extends MortarCommand {
|
||||
}
|
||||
World world = Bukkit.getWorld(args[1]);
|
||||
try {
|
||||
new Pregenerator(world, getVal(args[0]) * 2);
|
||||
new PregeneratorJob(PregenTask
|
||||
.builder()
|
||||
.center(new Position2(0, 0))
|
||||
.radius(((getVal(args[0]) >> 4) >> 5) + 1)
|
||||
.build(),
|
||||
new HybridPregenMethod(world, Runtime.getRuntime().availableProcessors()));
|
||||
} catch (NumberFormatException e) {
|
||||
Iris.reportError(e);
|
||||
sender.sendMessage("Invalid argument in command");
|
||||
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.command.world;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.engine.data.mca.Chunk;
|
||||
import com.volmit.iris.engine.data.mca.MCAFile;
|
||||
import com.volmit.iris.engine.data.mca.MCAUtil;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.engine.parallel.BurstExecutor;
|
||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import com.volmit.iris.util.plugin.MortarCommand;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class CommandIrisVerify extends MortarCommand {
|
||||
public CommandIrisVerify() {
|
||||
super("verifymca");
|
||||
requiresPermission(Iris.perm.studio);
|
||||
setDescription("Fix nearby chunks");
|
||||
setCategory("Studio");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTabOptions(VolmitSender sender, String[] args, KList<String> list) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(VolmitSender sender, String[] args) {
|
||||
try {
|
||||
IrisAccess a = IrisWorlds.access(sender.player().getWorld());
|
||||
File folder = a.getTarget().getWorld().worldFolder();
|
||||
File r = new File(folder, "region");
|
||||
BurstExecutor e = MultiBurst.burst.burst(r.listFiles().length);
|
||||
AtomicInteger f = new AtomicInteger(0);
|
||||
for(File i : r.listFiles())
|
||||
{
|
||||
e.queue(() -> {
|
||||
MCAFile file = null;
|
||||
try {
|
||||
file = MCAUtil.read(i);
|
||||
int rx = Integer.valueOf(i.getName().split("\\Q.\\E")[1]);
|
||||
int rz = Integer.valueOf(i.getName().split("\\Q.\\E")[2]);
|
||||
for(int j = 0; j < 32; j++)
|
||||
{
|
||||
for(int k = 0; k < 32; k++)
|
||||
{
|
||||
f.incrementAndGet();
|
||||
Chunk c = file.getChunk(j, k);
|
||||
if(c == null)
|
||||
{
|
||||
sender.sendMessage("Found Missing Chunk " + i.getName() + ", chunk #" + j + "," + k + " (see " + (((rx << 5)<<4)+(j<<4)) + "," + (((rz << 5)<<4)+(k<<4)));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ioException) {
|
||||
ioException.printStackTrace();
|
||||
sender.sendMessage("Error loading region " + i.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
e.complete();
|
||||
sender.sendMessage("Done! Checked " + f.get() + " chunks");
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
sender.sendMessage("Not a valid Iris World (or bad argument)");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getArgsUsage() {
|
||||
return "[view-distance]";
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@
|
||||
package com.volmit.iris.core.command.world;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.IrisWorlds;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.plugin.MortarCommand;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
|
@ -19,7 +19,7 @@
|
||||
package com.volmit.iris.core.edit;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.IrisWorlds;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.engine.parallax.ParallaxAccess;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
|
@ -38,7 +38,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class IrisExplorer extends JPanel implements MouseWheelListener {
|
||||
public class NoiseExplorerGUI extends JPanel implements MouseWheelListener {
|
||||
|
||||
private static final long serialVersionUID = 2094606939770332040L;
|
||||
|
||||
@ -74,7 +74,7 @@ public class IrisExplorer extends JPanel implements MouseWheelListener {
|
||||
double t;
|
||||
double tz;
|
||||
|
||||
public IrisExplorer() {
|
||||
public NoiseExplorerGUI() {
|
||||
addMouseWheelListener(this);
|
||||
addMouseMotionListener(new MouseMotionListener() {
|
||||
@Override
|
||||
@ -237,7 +237,7 @@ public class IrisExplorer extends JPanel implements MouseWheelListener {
|
||||
|
||||
private static void createAndShowGUI(Function2<Double, Double, Double> gen, String genName) {
|
||||
JFrame frame = new JFrame("Noise Explorer: " + genName);
|
||||
IrisExplorer nv = new IrisExplorer();
|
||||
NoiseExplorerGUI nv = new NoiseExplorerGUI();
|
||||
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||
JLayeredPane pane = new JLayeredPane();
|
||||
nv.setSize(new Dimension(1440, 820));
|
||||
@ -259,7 +259,7 @@ public class IrisExplorer extends JPanel implements MouseWheelListener {
|
||||
|
||||
private static void createAndShowGUI() {
|
||||
JFrame frame = new JFrame("Noise Explorer");
|
||||
IrisExplorer nv = new IrisExplorer();
|
||||
NoiseExplorerGUI nv = new NoiseExplorerGUI();
|
||||
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||
KList<String> li = new KList<>(NoiseStyle.values()).toStringList();
|
||||
combo = new JComboBox<>(li.toArray(new String[0]));
|
||||
@ -296,7 +296,7 @@ public class IrisExplorer extends JPanel implements MouseWheelListener {
|
||||
}
|
||||
|
||||
public static void launch() {
|
||||
EventQueue.invokeLater(IrisExplorer::createAndShowGUI);
|
||||
EventQueue.invokeLater(NoiseExplorerGUI::createAndShowGUI);
|
||||
}
|
||||
|
||||
static class HandScrollListener extends MouseAdapter {
|
@ -1,639 +0,0 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.gui;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.IrisWorlds;
|
||||
import com.volmit.iris.engine.data.mca.MCAFile;
|
||||
import com.volmit.iris.engine.data.mca.NBTWorld;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.engine.parallel.BurstExecutor;
|
||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.function.Consumer2;
|
||||
import com.volmit.iris.util.function.Consumer3;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.math.ChunkPosition;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RollingSequence;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import com.volmit.iris.util.scheduling.SR;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Comparator;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@Data
|
||||
public class Pregenerator implements Listener {
|
||||
private static Pregenerator instance;
|
||||
private static final Color COLOR_ERROR = Color.decode("#E34113");
|
||||
private static final Color COLOR_MCA_PREPARE = Color.decode("#3CAAB5");
|
||||
private static final Color COLOR_MCA_RELOAD = Color.decode("#41FF61");
|
||||
private static final Color COLOR_MCA_GENERATE = Color.decode("#33FF8F");
|
||||
private static final Color COLOR_MCA_GENERATE_SLOW = Color.decode("#13BAE3");
|
||||
private static final Color COLOR_MCA_GENERATE_SLOW_ASYNC = Color.decode("#13BAE3");
|
||||
private static final Color COLOR_MCA_GENERATED = Color.decode("#33FF8F");
|
||||
private static final Color COLOR_MCA_GENERATED_MCA = Color.decode("#13E3C9");
|
||||
private static final Color COLOR_MCA_SEALED = Color.decode("#33FF8F");
|
||||
private static final Color COLOR_MCA_DEFERRED = Color.decode("#3CB57A");
|
||||
private final World world;
|
||||
private int lowestBedrock;
|
||||
private final NBTWorld directWriter;
|
||||
private final AtomicBoolean active;
|
||||
private final AtomicBoolean running;
|
||||
private final KList<ChunkPosition> errors;
|
||||
private final KList<Runnable> onComplete;
|
||||
private final ChunkPosition max;
|
||||
private final ChunkPosition min;
|
||||
private final MCAPregenGui gui;
|
||||
private final KList<ChunkPosition> mcaDefer;
|
||||
private final AtomicInteger generated;
|
||||
private final AtomicInteger generatedLast;
|
||||
private final RollingSequence perSecond;
|
||||
private final RollingSequence perMinute;
|
||||
private final AtomicInteger totalChunks;
|
||||
private final AtomicLong memory;
|
||||
private final AtomicReference<String> memoryMetric;
|
||||
private final AtomicReference<String> method;
|
||||
private final AtomicInteger vmcax;
|
||||
private final AtomicInteger vmcaz;
|
||||
private final AtomicInteger vcax;
|
||||
private final AtomicInteger vcaz;
|
||||
private final long elapsed;
|
||||
private final ChronoLatch latch;
|
||||
private IrisAccess access;
|
||||
private final KList<ChunkPosition> regionReload;
|
||||
private KList<ChunkPosition> wait = new KList<>();
|
||||
|
||||
public Pregenerator(World world, int blockSize, Runnable onComplete) {
|
||||
this(world, blockSize);
|
||||
this.onComplete.add(onComplete);
|
||||
}
|
||||
|
||||
public Pregenerator(World world, int blockSize) throws HeadlessException {
|
||||
this(world, blockSize, true);
|
||||
}
|
||||
|
||||
public Pregenerator(World world, int blockSize, boolean dogui) throws HeadlessException {
|
||||
instance();
|
||||
regionReload = new KList<>();
|
||||
latch = new ChronoLatch(5000);
|
||||
memoryMetric = new AtomicReference<>("...");
|
||||
method = new AtomicReference<>("STARTUP");
|
||||
memory = new AtomicLong(0);
|
||||
this.world = world;
|
||||
errors = new KList<>();
|
||||
vmcax = new AtomicInteger();
|
||||
vmcaz = new AtomicInteger();
|
||||
vcax = new AtomicInteger();
|
||||
vcaz = new AtomicInteger();
|
||||
perMinute = new RollingSequence(200);
|
||||
perSecond = new RollingSequence(20);
|
||||
generatedLast = new AtomicInteger(0);
|
||||
totalChunks = new AtomicInteger(0);
|
||||
generated = new AtomicInteger(0);
|
||||
mcaDefer = new KList<>();
|
||||
access = IrisWorlds.access(world);
|
||||
this.directWriter = new NBTWorld(world.getWorldFolder());
|
||||
this.running = new AtomicBoolean(true);
|
||||
this.active = new AtomicBoolean(true);
|
||||
MultiBurst burst = new MultiBurst("Iris Pregenerator", 9, Runtime.getRuntime().availableProcessors());
|
||||
int mcaSize = (((blockSize >> 4) + 2) >> 5) + 1;
|
||||
onComplete = new KList<>();
|
||||
max = new ChunkPosition(0, 0);
|
||||
min = new ChunkPosition(0, 0);
|
||||
KList<Runnable> draw = new KList<>();
|
||||
new Spiraler(mcaSize, mcaSize, (xx, zz) -> {
|
||||
min.setX(Math.min(xx << 5, min.getX()));
|
||||
min.setZ(Math.min(zz << 5, min.getZ()));
|
||||
max.setX(Math.max((xx << 5) + 31, max.getX()));
|
||||
max.setZ(Math.max((zz << 5) + 31, max.getZ()));
|
||||
totalChunks.getAndAdd(1024);
|
||||
draw.add(() -> drawMCA(xx, zz, COLOR_MCA_PREPARE));
|
||||
}).drain();
|
||||
if (access != null) {
|
||||
lowestBedrock = access.getCompound().getLowestBedrock();
|
||||
}
|
||||
gui = dogui ? (IrisSettings.get().getGui().isLocalPregenGui() && IrisSettings.get().getGui().isUseServerLaunchedGuis() ? MCAPregenGui.createAndShowGUI(this) : null) : null;
|
||||
flushWorld();
|
||||
KList<ChunkPosition> order = computeChunkOrder();
|
||||
Consumer3<Integer, Integer, Consumer2<Integer, Integer>> mcaIteration =
|
||||
(ox, oz, r) -> order.forEach((i)
|
||||
-> r.accept(i.getX() + ox, i.getZ() + oz));
|
||||
draw.forEach(Runnable::run);
|
||||
Spiraler spiraler = new Spiraler(mcaSize, mcaSize, (xx, zz) -> {
|
||||
vmcax.set(xx);
|
||||
vmcaz.set(zz);
|
||||
flushWorld();
|
||||
drawMCA(xx, zz, COLOR_MCA_PREPARE);
|
||||
if (access != null && generateMCARegion(xx, zz, burst, access, mcaIteration)) {
|
||||
flushWorld();
|
||||
}
|
||||
});
|
||||
|
||||
elapsed = M.ms();
|
||||
|
||||
new Thread(() -> {
|
||||
flushWorld();
|
||||
J.sleep(2000);
|
||||
flushWorld();
|
||||
|
||||
while (running.get() && spiraler.hasNext()) {
|
||||
if (active.get()) {
|
||||
spiraler.next();
|
||||
}
|
||||
}
|
||||
|
||||
mcaDefer.removeDuplicates();
|
||||
|
||||
while (running.get() && mcaDefer.isNotEmpty()) {
|
||||
ChunkPosition p = mcaDefer.popLast();
|
||||
vmcax.set(p.getX());
|
||||
vmcaz.set(p.getZ());
|
||||
generateDeferedMCARegion(p.getX(), p.getZ(), burst, mcaIteration);
|
||||
flushWorld();
|
||||
}
|
||||
|
||||
while (wait.isNotEmpty()) {
|
||||
J.sleep(50);
|
||||
}
|
||||
|
||||
burst.shutdownNow();
|
||||
directWriter.close();
|
||||
flushWorld();
|
||||
onComplete.forEach(Runnable::run);
|
||||
running.set(false);
|
||||
active.set(false);
|
||||
if (gui != null) {
|
||||
gui.close();
|
||||
}
|
||||
}).start();
|
||||
new Thread(() -> {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
|
||||
while (running.get() && active.get()) {
|
||||
int m = generated.get();
|
||||
int w = generatedLast.get();
|
||||
int up = m - w;
|
||||
double dur = p.getMilliseconds();
|
||||
perSecond.put((int) (up / (dur / 1000D)));
|
||||
perSecond.put((int) (up / (dur / 60000D)));
|
||||
p.reset();
|
||||
p.begin();
|
||||
updateProgress();
|
||||
generatedLast.set(m);
|
||||
J.sleep(100);
|
||||
long lmem = memory.get();
|
||||
memory.set(Runtime.getRuntime().freeMemory());
|
||||
|
||||
if (memory.get() > lmem) {
|
||||
long free = memory.get();
|
||||
long max = Runtime.getRuntime().maxMemory();
|
||||
long total = Runtime.getRuntime().totalMemory();
|
||||
long use = total - free;
|
||||
memoryMetric.set(Form.memSize(use, 2) + " (" + Form.pc((double) use / (double) max, 0) + ")");
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private boolean generateMCARegion(int x, int z, MultiBurst burst, IrisAccess access, Consumer3<Integer, Integer, Consumer2<Integer, Integer>> mcaIteration) {
|
||||
if (!Iris.instance.isMCA()) {
|
||||
generateDeferedMCARegion(x, z, burst, mcaIteration);
|
||||
return false;
|
||||
}
|
||||
|
||||
File mca = directWriter.getRegionFile(x, z);
|
||||
BurstExecutor e = burst.burst(1024);
|
||||
int mcaox = x << 5;
|
||||
int mcaoz = z << 5;
|
||||
if (isMCAWritable(x, z) && !mca.exists()) {
|
||||
method.set("Direct (Fast)");
|
||||
mcaIteration.accept(mcaox, mcaoz, (ii, jj) -> e.queue(() -> {
|
||||
draw(ii, jj, COLOR_MCA_GENERATE);
|
||||
access.directWriteChunk(world, ii, jj, directWriter);
|
||||
draw(ii, jj, COLOR_MCA_GENERATED_MCA);
|
||||
generated.getAndIncrement();
|
||||
vcax.set(ii);
|
||||
vcaz.set(jj);
|
||||
}));
|
||||
e.complete();
|
||||
//verifyMCA(x, z, burst);
|
||||
directWriter.save();
|
||||
} else {
|
||||
totalChunks.getAndAdd(1024);
|
||||
mcaDefer.add(new ChunkPosition(x, z));
|
||||
e.complete();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void verifyMCA(int x, int z, MultiBurst burst) {
|
||||
MCAFile rg = directWriter.getMCA(x, z);
|
||||
KList<Runnable> requeue = new KList<>();
|
||||
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
for(int j = 0; j < 32; j++)
|
||||
{
|
||||
com.volmit.iris.engine.data.mca.Chunk c = rg.getChunk(i, j);
|
||||
|
||||
if(c == null)
|
||||
{
|
||||
draw(((x << 5) + i), ((z << 5) + j), COLOR_ERROR);
|
||||
int finalI = i;
|
||||
int finalJ = j;
|
||||
requeue.add(() -> {
|
||||
draw(((x << 5) + finalI), ((z << 5) + finalJ), COLOR_MCA_GENERATE);
|
||||
access.directWriteChunk(world, ((x << 5) + finalI), ((z << 5) + finalJ), directWriter);
|
||||
draw(((x << 5) + finalI), ((z << 5) + finalJ), COLOR_MCA_GENERATED_MCA);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(requeue.isNotEmpty())
|
||||
{
|
||||
burst.burst(requeue);
|
||||
verifyMCA(x, z, burst);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateProgress() {
|
||||
if (!latch.flip()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String[] v = getProgress();
|
||||
Iris.info("Pregeneration " + v[0] + " | " + v[1] + " | " + v[2] + " | " + v[3]);
|
||||
}
|
||||
|
||||
private void generateDeferedMCARegion(int x, int z, MultiBurst burst, Consumer3<Integer, Integer, Consumer2<Integer, Integer>> mcaIteration) {
|
||||
int mcaox = x << 5;
|
||||
int mcaoz = z << 5;
|
||||
if (PaperLib.isPaper()) {
|
||||
method.set("PaperAsync (Slow)");
|
||||
|
||||
while (wait.size() > 16) {
|
||||
J.sleep(5);
|
||||
}
|
||||
|
||||
mcaIteration.accept(mcaox, mcaoz, (ii, jj) -> {
|
||||
ChunkPosition cx = new ChunkPosition(ii, jj);
|
||||
PaperLib.getChunkAtAsync(world, ii, jj).thenAccept((c) -> {
|
||||
draw(ii, jj, COLOR_MCA_GENERATE_SLOW_ASYNC);
|
||||
draw(ii, jj, COLOR_MCA_GENERATED);
|
||||
generated.getAndIncrement();
|
||||
vcax.set(ii);
|
||||
vcaz.set(jj);
|
||||
|
||||
synchronized (wait) {
|
||||
wait.remove(cx);
|
||||
}
|
||||
});
|
||||
|
||||
wait.add(cx);
|
||||
});
|
||||
} else {
|
||||
AtomicInteger m = new AtomicInteger();
|
||||
method.set("Spigot (Very Slow)");
|
||||
KList<Runnable> q = new KList<>();
|
||||
mcaIteration.accept(mcaox, mcaoz, (ii, jj) -> q.add(() -> {
|
||||
draw(ii, jj, COLOR_MCA_GENERATE_SLOW);
|
||||
world.getChunkAt(ii, jj).load(true);
|
||||
Chunk c = world.getChunkAt(ii, jj);
|
||||
draw(ii, jj, COLOR_MCA_GENERATED);
|
||||
m.getAndIncrement();
|
||||
generated.getAndIncrement();
|
||||
vcax.set(ii);
|
||||
vcaz.set(jj);
|
||||
}));
|
||||
ChronoLatch tick = new ChronoLatch(1000);
|
||||
new SR(0) {
|
||||
@Override
|
||||
public void run() {
|
||||
if (tick.flip()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (q.isEmpty()) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
q.pop().run();
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
while (m.get() < 1024) {
|
||||
J.sleep(25);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private KList<ChunkPosition> computeChunkOrder() {
|
||||
ChunkPosition center = new ChunkPosition(15, 15);
|
||||
KList<ChunkPosition> p = new KList<>();
|
||||
new Spiraler(33, 33, (x, z) -> {
|
||||
int xx = x + 15;
|
||||
int zz = z + 15;
|
||||
if (xx < 0 || xx > 31 || zz < 0 || zz > 31) {
|
||||
return;
|
||||
}
|
||||
|
||||
p.add(new ChunkPosition(xx, zz));
|
||||
}).drain();
|
||||
p.sort(Comparator.comparing((i) -> i.distance(center)));
|
||||
return p;
|
||||
}
|
||||
|
||||
public static Pregenerator getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static boolean shutdownInstance() {
|
||||
if (instance != null) {
|
||||
instance.shutdown();
|
||||
instance = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void pauseResume() {
|
||||
instance.active.set(!instance.active.get());
|
||||
}
|
||||
|
||||
public static boolean isPaused() {
|
||||
return instance.paused();
|
||||
}
|
||||
|
||||
private void instance() {
|
||||
if (instance != null) {
|
||||
instance.shutdown();
|
||||
}
|
||||
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
running.set(false);
|
||||
active.set(false);
|
||||
}
|
||||
|
||||
private void draw(int cx, int cz, Color color) {
|
||||
if (gui != null) {
|
||||
gui.func.accept(new ChunkPosition(cx, cz), color);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawMCA(int cx, int cz, Color color) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
for (int j = 0; j < 32; j++) {
|
||||
draw((cx << 5) + i, (cz << 5) + j, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void flushWorld() {
|
||||
if (Bukkit.isPrimaryThread()) {
|
||||
flushWorldSync();
|
||||
return;
|
||||
}
|
||||
|
||||
AtomicBoolean b = new AtomicBoolean(false);
|
||||
J.s(() -> {
|
||||
flushWorldSync();
|
||||
b.set(true);
|
||||
});
|
||||
|
||||
while (!b.get()) {
|
||||
J.sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
private void flushWorldSync() {
|
||||
for (Chunk i : world.getLoadedChunks()) {
|
||||
i.unload(true);
|
||||
}
|
||||
|
||||
world.save();
|
||||
}
|
||||
|
||||
private boolean isMCAWritable(int x, int z) {
|
||||
File mca = new File(world.getWorldFolder(), "region/r." + x + "." + z + ".mca");
|
||||
|
||||
if (mca.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Chunk i : world.getLoadedChunks()) {
|
||||
if (i.getX() >> 5 == x && i.getZ() >> 5 == z) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public String[] getProgress() {
|
||||
long eta = (long) ((totalChunks.get() - generated.get()) * ((double) (M.ms() - elapsed) / (double) generated.get()));
|
||||
|
||||
return new String[]{
|
||||
"Progress: " + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (" + Form.pc((double) generated.get() / (double) totalChunks.get(), 0) + ")",
|
||||
"ETA: " + Form.duration(eta, 0),
|
||||
"Chunks/s: " + Form.f((int) perSecond.getAverage()) + " (" + Form.f((int)perSecond.getMax()) + " Peak)",
|
||||
"Chunks/min: " + Form.f((int) perMinute.getAverage())+ " (" + Form.f((int)perMinute.getMax()) + " Peak)",
|
||||
"Memory: " + memoryMetric.get(),
|
||||
"Cursor: " + "MCA(" + vmcax.get() + ", " + vmcaz.get() + ") @ (" + vcax.get() + ", " + vcaz.get() + ")",
|
||||
"Gen Mode: " + method.get(),
|
||||
};
|
||||
}
|
||||
|
||||
public boolean paused() {
|
||||
return !active.get();
|
||||
}
|
||||
|
||||
public static class MCAPregenGui extends JPanel implements KeyListener {
|
||||
private Pregenerator job;
|
||||
private static final long serialVersionUID = 2094606939770332040L;
|
||||
private final KList<Runnable> order = new KList<>();
|
||||
private final int res = 512;
|
||||
Graphics2D bg;
|
||||
private ReentrantLock l;
|
||||
private final BufferedImage image = new BufferedImage(res, res, BufferedImage.TYPE_INT_RGB);
|
||||
private Consumer2<ChunkPosition, Color> func;
|
||||
private JFrame frame;
|
||||
|
||||
public MCAPregenGui() {
|
||||
|
||||
}
|
||||
|
||||
public void paint(int x, int z, Color c) {
|
||||
func.accept(new ChunkPosition(x, z), c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics gx) {
|
||||
Graphics2D g = (Graphics2D) gx;
|
||||
bg = (Graphics2D) image.getGraphics();
|
||||
|
||||
l.lock();
|
||||
while (order.isNotEmpty()) {
|
||||
try {
|
||||
order.pop().run();
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
|
||||
}
|
||||
}
|
||||
l.unlock();
|
||||
|
||||
g.drawImage(image, 0, 0, getParent().getWidth(), getParent().getHeight(), (img, infoflags, x, y, width, height) -> true);
|
||||
|
||||
g.setColor(Color.WHITE);
|
||||
g.setFont(new Font("Hevetica", Font.BOLD, 28));
|
||||
String[] prog = job.getProgress();
|
||||
int h = g.getFontMetrics().getHeight() + 5;
|
||||
int hh = 20;
|
||||
|
||||
if (job.paused()) {
|
||||
g.drawString("PAUSED", 20, hh += h);
|
||||
|
||||
g.drawString("Press P to Resume", 20, hh += h);
|
||||
} else {
|
||||
for (String i : prog) {
|
||||
g.drawString(i, 20, hh += h);
|
||||
}
|
||||
|
||||
g.drawString("Press P to Pause", 20, hh += h);
|
||||
}
|
||||
|
||||
J.sleep(IrisSettings.get().getGui().isMaximumPregenGuiFPS() ? 4 : 250);
|
||||
repaint();
|
||||
}
|
||||
|
||||
private void draw(ChunkPosition p, Color c, Graphics2D bg) {
|
||||
double pw = M.lerpInverse(job.getMin().getX(), job.getMax().getX(), p.getX());
|
||||
double ph = M.lerpInverse(job.getMin().getZ(), job.getMax().getZ(), p.getZ());
|
||||
double pwa = M.lerpInverse(job.getMin().getX(), job.getMax().getX(), p.getX() + 1);
|
||||
double pha = M.lerpInverse(job.getMin().getZ(), job.getMax().getZ(), p.getZ() + 1);
|
||||
int x = (int) M.lerp(0, res, pw);
|
||||
int z = (int) M.lerp(0, res, ph);
|
||||
int xa = (int) M.lerp(0, res, pwa);
|
||||
int za = (int) M.lerp(0, res, pha);
|
||||
bg.setColor(c);
|
||||
bg.fillRect(x, z, xa - x, za - z);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static MCAPregenGui createAndShowGUI(Pregenerator j) throws HeadlessException {
|
||||
JFrame frame;
|
||||
frame = new JFrame("Pregen View");
|
||||
MCAPregenGui nv = new MCAPregenGui();
|
||||
frame.addKeyListener(nv);
|
||||
nv.l = new ReentrantLock();
|
||||
nv.frame = frame;
|
||||
nv.job = j;
|
||||
nv.func = (c, b) ->
|
||||
{
|
||||
if (b.equals(Color.pink) && c.equals(new ChunkPosition(Integer.MAX_VALUE, Integer.MAX_VALUE))) {
|
||||
frame.hide();
|
||||
}
|
||||
nv.l.lock();
|
||||
nv.order.add(() -> nv.draw(c, b, nv.bg));
|
||||
nv.l.unlock();
|
||||
};
|
||||
frame.add(nv);
|
||||
frame.setSize(1000, 1000);
|
||||
frame.setVisible(true);
|
||||
File file = Iris.getCached("Iris Icon", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/icon.png");
|
||||
|
||||
if (file != null) {
|
||||
try {
|
||||
frame.setIconImage(ImageIO.read(file));
|
||||
} catch (IOException ignored) {
|
||||
Iris.reportError(ignored);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nv;
|
||||
}
|
||||
|
||||
public static void launch(Pregenerator g) {
|
||||
J.a(() ->
|
||||
{
|
||||
createAndShowGUI(g);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_P) {
|
||||
Pregenerator.pauseResume();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
frame.setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
389
src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java
Normal file
389
src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java
Normal file
@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.gui;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.IrisPregenerator;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.function.Consumer2;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PregeneratorJob implements PregenListener {
|
||||
public static PregeneratorJob instance;
|
||||
private static final Color COLOR_EXISTS = parseColor("#4d7d5b");
|
||||
private static final Color COLOR_GENERATING = parseColor("#0062ff");
|
||||
private static final Color COLOR_NETWORK = parseColor("#a863c2");
|
||||
private static final Color COLOR_NETWORK_GENERATING = parseColor("#836b8c");
|
||||
private static final Color COLOR_GENERATED = parseColor("#34eb93");
|
||||
private JFrame frame;
|
||||
private final PregenTask task;
|
||||
private boolean saving;
|
||||
private KList<Consumer<Double>> onProgress = new KList<>();
|
||||
private KList<Runnable> whenDone = new KList<>();
|
||||
private final IrisPregenerator pregenerator;
|
||||
private PregenRenderer renderer;
|
||||
private String[] info;
|
||||
private Position2 min;
|
||||
private Position2 max;
|
||||
|
||||
public PregeneratorJob(PregenTask task, PregeneratorMethod method) {
|
||||
instance = this;
|
||||
saving = false;
|
||||
info = new String[]{"Initializing..."};
|
||||
this.task = task;
|
||||
this.pregenerator = new IrisPregenerator(task, method, this);
|
||||
max = new Position2(0, 0);
|
||||
min = new Position2(0, 0);
|
||||
KList<Runnable> draw = new KList<>();
|
||||
task.iterateRegions((xx, zz) -> {
|
||||
min.setX(Math.min(xx << 5, min.getX()));
|
||||
min.setZ(Math.min(zz << 5, min.getZ()));
|
||||
max.setX(Math.max((xx << 5) + 31, max.getX()));
|
||||
max.setZ(Math.max((zz << 5) + 31, max.getZ()));
|
||||
});
|
||||
|
||||
if (IrisSettings.get().getGui().isUseServerLaunchedGuis()) {
|
||||
open();
|
||||
}
|
||||
|
||||
J.a(this.pregenerator::start, 20);
|
||||
}
|
||||
|
||||
public PregeneratorJob onProgress(Consumer<Double> c) {
|
||||
onProgress.add(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PregeneratorJob whenDone(Runnable r) {
|
||||
whenDone.add(r);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static boolean shutdownInstance() {
|
||||
if (instance == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
J.a(() -> instance.pregenerator.close());
|
||||
return true;
|
||||
}
|
||||
|
||||
public static PregeneratorJob getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static void pauseResume() {
|
||||
if (instance == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPaused()) {
|
||||
instance.pregenerator.resume();
|
||||
} else {
|
||||
instance.pregenerator.pause();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPaused() {
|
||||
if (instance == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return instance.paused();
|
||||
}
|
||||
|
||||
public void drawRegion(int x, int z, Color color) {
|
||||
J.a(() -> {
|
||||
PregenTask.iterateRegion(x, z, (xx, zz) -> {
|
||||
draw(xx, zz, color);
|
||||
J.sleep(3);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public void draw(int x, int z, Color color) {
|
||||
try {
|
||||
if (renderer != null && frame != null && frame.isVisible()) {
|
||||
renderer.func.accept(new Position2(x, z), color);
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
J.a(() -> {
|
||||
pregenerator.close();
|
||||
close();
|
||||
instance = null;
|
||||
});
|
||||
}
|
||||
|
||||
public void close() {
|
||||
J.a(() -> {
|
||||
try {
|
||||
J.sleep(3000);
|
||||
frame.setVisible(false);
|
||||
} catch (Throwable e) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void open() {
|
||||
J.a(() -> {
|
||||
try {
|
||||
frame = new JFrame("Pregen View");
|
||||
renderer = new PregenRenderer();
|
||||
frame.addKeyListener(renderer);
|
||||
renderer.l = new ReentrantLock();
|
||||
renderer.frame = frame;
|
||||
renderer.job = this;
|
||||
renderer.func = (c, b) ->
|
||||
{
|
||||
renderer.l.lock();
|
||||
renderer.order.add(() -> renderer.draw(c, b, renderer.bg));
|
||||
renderer.l.unlock();
|
||||
};
|
||||
frame.add(renderer);
|
||||
frame.setSize(1000, 1000);
|
||||
frame.setVisible(true);
|
||||
} catch (Throwable e) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) {
|
||||
info = new String[]{
|
||||
(paused() ? "PAUSED" : (saving ? "Saving... " : "Generating")) + " " + Form.f(generated) + " of " + Form.f(totalChunks) + " (" + Form.pc(percent, 0) + " Complete)",
|
||||
"Speed: " + Form.f(chunksPerSecond, 0) + " Chunks/s, " + Form.f(regionsPerMinute, 1) + " Regions/m, " + Form.f(chunksPerMinute, 0) + " Chunks/m",
|
||||
Form.duration(eta, 2) + " Remaining " + " (" + Form.duration(elapsed, 2) + " Elapsed)",
|
||||
"Generation Method: " + method,
|
||||
};
|
||||
|
||||
for (Consumer<Double> i : onProgress) {
|
||||
i.accept(percent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkGenerating(int x, int z) {
|
||||
draw(x, z, COLOR_GENERATING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkGenerated(int x, int z) {
|
||||
draw(x, z, COLOR_GENERATED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionGenerated(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionGenerating(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionSkipped(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkStarted(int x, int z) {
|
||||
drawRegion(x, z, COLOR_NETWORK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkFailed(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkReclaim(int revert) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkGeneratedChunk(int x, int z) {
|
||||
draw(x, z, COLOR_NETWORK_GENERATING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkDownloaded(int x, int z) {
|
||||
drawRegion(x, z, COLOR_NETWORK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
close();
|
||||
instance = null;
|
||||
whenDone.forEach(Runnable::run);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaving() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkExistsInRegionGen(int x, int z) {
|
||||
draw(x, z, COLOR_EXISTS);
|
||||
}
|
||||
|
||||
private Position2 getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
private Position2 getMin() {
|
||||
return min;
|
||||
}
|
||||
|
||||
private boolean paused() {
|
||||
return pregenerator.paused();
|
||||
}
|
||||
|
||||
private String[] getProgress() {
|
||||
return info;
|
||||
}
|
||||
|
||||
public static class PregenRenderer extends JPanel implements KeyListener {
|
||||
private PregeneratorJob job;
|
||||
private static final long serialVersionUID = 2094606939770332040L;
|
||||
private final KList<Runnable> order = new KList<>();
|
||||
private final int res = 512;
|
||||
Graphics2D bg;
|
||||
private ReentrantLock l;
|
||||
private final BufferedImage image = new BufferedImage(res, res, BufferedImage.TYPE_INT_RGB);
|
||||
private Consumer2<Position2, Color> func;
|
||||
private JFrame frame;
|
||||
|
||||
public PregenRenderer() {
|
||||
|
||||
}
|
||||
|
||||
public void paint(int x, int z, Color c) {
|
||||
func.accept(new Position2(x, z), c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics gx) {
|
||||
Graphics2D g = (Graphics2D) gx;
|
||||
bg = (Graphics2D) image.getGraphics();
|
||||
l.lock();
|
||||
|
||||
while (order.isNotEmpty()) {
|
||||
try {
|
||||
order.pop().run();
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
l.unlock();
|
||||
g.drawImage(image, 0, 0, getParent().getWidth(), getParent().getHeight(), (img, infoflags, x, y, width, height) -> true);
|
||||
g.setColor(Color.WHITE);
|
||||
g.setFont(new Font("Hevetica", Font.BOLD, 28));
|
||||
String[] prog = job.getProgress();
|
||||
int h = g.getFontMetrics().getHeight() + 5;
|
||||
int hh = 20;
|
||||
|
||||
if (job.paused()) {
|
||||
g.drawString("PAUSED", 20, hh += h);
|
||||
|
||||
g.drawString("Press P to Resume", 20, hh += h);
|
||||
} else {
|
||||
for (String i : prog) {
|
||||
g.drawString(i, 20, hh += h);
|
||||
}
|
||||
|
||||
g.drawString("Press P to Pause", 20, hh += h);
|
||||
}
|
||||
|
||||
J.sleep(IrisSettings.get().getGui().isMaximumPregenGuiFPS() ? 4 : 250);
|
||||
repaint();
|
||||
}
|
||||
|
||||
private void draw(Position2 p, Color c, Graphics2D bg) {
|
||||
double pw = M.lerpInverse(job.getMin().getX(), job.getMax().getX(), p.getX());
|
||||
double ph = M.lerpInverse(job.getMin().getZ(), job.getMax().getZ(), p.getZ());
|
||||
double pwa = M.lerpInverse(job.getMin().getX(), job.getMax().getX(), p.getX() + 1);
|
||||
double pha = M.lerpInverse(job.getMin().getZ(), job.getMax().getZ(), p.getZ() + 1);
|
||||
int x = (int) M.lerp(0, res, pw);
|
||||
int z = (int) M.lerp(0, res, ph);
|
||||
int xa = (int) M.lerp(0, res, pwa);
|
||||
int za = (int) M.lerp(0, res, pha);
|
||||
bg.setColor(c);
|
||||
bg.fillRect(x, z, xa - x, za - z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_P) {
|
||||
PregeneratorJob.pauseResume();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
frame.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static Color parseColor(String c) {
|
||||
String v = (c.startsWith("#") ? c : "#" + c).trim();
|
||||
try {
|
||||
return Color.decode(v);
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.error("Error Parsing 'color', (" + c + ")");
|
||||
}
|
||||
|
||||
return Color.RED;
|
||||
}
|
||||
}
|
@ -19,11 +19,14 @@
|
||||
package com.volmit.iris.core.gui;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.gui.components.IrisRenderer;
|
||||
import com.volmit.iris.core.gui.components.RenderType;
|
||||
import com.volmit.iris.engine.IrisComplex;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.engine.object.common.IrisWorld;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
@ -36,7 +39,6 @@ import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.O;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -54,7 +56,7 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class IrisVision extends JPanel implements MouseWheelListener, KeyListener, MouseMotionListener, MouseInputListener {
|
||||
public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener, MouseMotionListener, MouseInputListener {
|
||||
private static final long serialVersionUID = 2094606939770332040L;
|
||||
|
||||
private RenderType currentType = RenderType.BIOME;
|
||||
@ -70,7 +72,7 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene
|
||||
private boolean alt = false;
|
||||
private int posX = 0;
|
||||
private IrisRenderer renderer;
|
||||
private World world;
|
||||
private IrisWorld world;
|
||||
private double velocity = 0;
|
||||
private int lowq = 12;
|
||||
private int posZ = 0;
|
||||
@ -128,7 +130,7 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene
|
||||
});
|
||||
private BufferedImage texture;
|
||||
|
||||
public IrisVision(JFrame frame) {
|
||||
public VisionGUI(JFrame frame) {
|
||||
m.set(8);
|
||||
rs.put(1);
|
||||
addMouseWheelListener(this);
|
||||
@ -142,6 +144,13 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene
|
||||
help = false;
|
||||
}
|
||||
});
|
||||
frame.addWindowListener(new java.awt.event.WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
|
||||
e.shutdown();
|
||||
eh.shutdown();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -726,9 +735,9 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene
|
||||
}
|
||||
}
|
||||
|
||||
private static void createAndShowGUI(Engine r, int s, World world) {
|
||||
private static void createAndShowGUI(Engine r, int s, IrisWorld world) {
|
||||
JFrame frame = new JFrame("Vision");
|
||||
IrisVision nv = new IrisVision(frame);
|
||||
VisionGUI nv = new VisionGUI(frame);
|
||||
nv.world = world;
|
||||
nv.engine = r;
|
||||
nv.renderer = new IrisRenderer(r);
|
@ -16,11 +16,10 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.gui;
|
||||
package com.volmit.iris.core.gui.components;
|
||||
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.interpolation.IrisInterpolation;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
@ -60,8 +59,4 @@ public class IrisRenderer {
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
public void set(double worldX, double worldZ) {
|
||||
renderer.getWorld().getBlockAt((int) worldX, 20, (int) worldZ).setType(Material.DIAMOND_BLOCK);
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.gui;
|
||||
package com.volmit.iris.core.gui.components;
|
||||
|
||||
public enum RenderType {
|
||||
BIOME, BIOME_LAND, BIOME_SEA, REGION, CAVE_LAND, HEIGHT, OBJECT_LOAD, DECORATOR_LOAD, LAYER_LOAD
|
@ -16,7 +16,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.gui;
|
||||
package com.volmit.iris.core.gui.components;
|
||||
|
||||
import java.awt.*;
|
||||
|
@ -16,7 +16,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.gui;
|
||||
package com.volmit.iris.core.gui.components;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RollingSequence;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.Looper;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class IrisPregenerator {
|
||||
private final PregenTask task;
|
||||
private final PregeneratorMethod generator;
|
||||
private final PregenListener listener;
|
||||
private final Looper ticker;
|
||||
private final AtomicBoolean paused;
|
||||
private final AtomicBoolean shutdown;
|
||||
private final RollingSequence chunksPerSecond;
|
||||
private final RollingSequence chunksPerMinute;
|
||||
private final RollingSequence regionsPerMinute;
|
||||
private final AtomicInteger generated;
|
||||
private final AtomicInteger generatedLast;
|
||||
private final AtomicInteger generatedLastMinute;
|
||||
private final AtomicInteger totalChunks;
|
||||
private final AtomicLong startTime;
|
||||
private final ChronoLatch minuteLatch;
|
||||
private final AtomicReference<String> currentGeneratorMethod;
|
||||
private final KSet<Position2> generatedRegions;
|
||||
private final KSet<Position2> retry;
|
||||
private final KSet<Position2> net;
|
||||
|
||||
public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) {
|
||||
this.listener = listenify(listener);
|
||||
generatedRegions = new KSet<>();
|
||||
this.shutdown = new AtomicBoolean(false);
|
||||
this.paused = new AtomicBoolean(false);
|
||||
this.task = task;
|
||||
this.generator = generator;
|
||||
retry = new KSet<>();
|
||||
net = new KSet<>();
|
||||
currentGeneratorMethod = new AtomicReference<>("Void");
|
||||
minuteLatch = new ChronoLatch(60000, false);
|
||||
chunksPerSecond = new RollingSequence(10);
|
||||
chunksPerMinute = new RollingSequence(10);
|
||||
regionsPerMinute = new RollingSequence(10);
|
||||
generated = new AtomicInteger(0);
|
||||
generatedLast = new AtomicInteger(0);
|
||||
generatedLastMinute = new AtomicInteger(0);
|
||||
totalChunks = new AtomicInteger(0);
|
||||
task.iterateRegions((_a, _b) -> totalChunks.addAndGet(1024));
|
||||
startTime = new AtomicLong(M.ms());
|
||||
ticker = new Looper() {
|
||||
@Override
|
||||
protected long loop() {
|
||||
long eta = computeETA();
|
||||
int secondGenerated = generated.get() - generatedLast.get();
|
||||
generatedLast.set(generated.get());
|
||||
chunksPerSecond.put(secondGenerated);
|
||||
|
||||
if (minuteLatch.flip()) {
|
||||
int minuteGenerated = generated.get() - generatedLastMinute.get();
|
||||
generatedLastMinute.set(generated.get());
|
||||
chunksPerMinute.put(minuteGenerated);
|
||||
regionsPerMinute.put((double) minuteGenerated / 1024D);
|
||||
}
|
||||
|
||||
listener.onTick(chunksPerSecond.getAverage(), chunksPerMinute.getAverage(),
|
||||
regionsPerMinute.getAverage(),
|
||||
(double) generated.get() / (double) totalChunks.get(),
|
||||
generated.get(), totalChunks.get(),
|
||||
totalChunks.get() - generated.get(),
|
||||
eta, M.ms() - startTime.get(), currentGeneratorMethod.get());
|
||||
|
||||
return 1000;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private long computeETA() {
|
||||
return (long) ((totalChunks.get() - generated.get()) *
|
||||
((double) (M.ms() - startTime.get()) / (double) generated.get()));
|
||||
}
|
||||
|
||||
public void close() {
|
||||
shutdown.set(true);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
init();
|
||||
ticker.start();
|
||||
checkRegions();
|
||||
task.iterateRegions((x, z) -> visitRegion(x, z, true));
|
||||
task.iterateRegions((x, z) -> visitRegion(x, z, false));
|
||||
shutdown();
|
||||
}
|
||||
|
||||
private void checkRegions() {
|
||||
task.iterateRegions(this::checkRegion);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
generator.init();
|
||||
generator.save();
|
||||
}
|
||||
|
||||
private void shutdown() {
|
||||
listener.onSaving();
|
||||
generator.close();
|
||||
ticker.interrupt();
|
||||
listener.onClose();
|
||||
}
|
||||
|
||||
private void visitRegion(int x, int z, boolean regions) {
|
||||
while (paused.get() && !shutdown.get()) {
|
||||
J.sleep(50);
|
||||
}
|
||||
|
||||
if (shutdown.get()) {
|
||||
listener.onRegionSkipped(x, z);
|
||||
return;
|
||||
}
|
||||
|
||||
Position2 pos = new Position2(x, z);
|
||||
|
||||
if (generatedRegions.contains(pos)) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentGeneratorMethod.set(generator.getMethod(x, z));
|
||||
boolean hit = false;
|
||||
if (generator.supportsRegions(x, z, listener) && regions) {
|
||||
hit = true;
|
||||
listener.onRegionGenerating(x, z);
|
||||
generator.generateRegion(x, z, listener);
|
||||
} else if (!regions) {
|
||||
hit = true;
|
||||
listener.onRegionGenerating(x, z);
|
||||
PregenTask.iterateRegion(x, z, (xx, zz) -> generator.generateChunk(xx, zz, listener));
|
||||
}
|
||||
|
||||
if (hit) {
|
||||
listener.onRegionGenerated(x, z);
|
||||
listener.onSaving();
|
||||
generator.save();
|
||||
generatedRegions.add(pos);
|
||||
checkRegions();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRegion(int x, int z) {
|
||||
if (generatedRegions.contains(new Position2(x, z))) {
|
||||
return;
|
||||
}
|
||||
|
||||
generator.supportsRegions(x, z, listener);
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
paused.set(true);
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
paused.set(false);
|
||||
}
|
||||
|
||||
private PregenListener listenify(PregenListener listener) {
|
||||
return new PregenListener() {
|
||||
@Override
|
||||
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) {
|
||||
listener.onTick(chunksPerSecond, chunksPerMinute, regionsPerMinute, percent, generated, totalChunks, chunksRemaining, eta, elapsed, method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkGenerating(int x, int z) {
|
||||
listener.onChunkGenerating(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkGenerated(int x, int z) {
|
||||
listener.onChunkGenerated(x, z);
|
||||
generated.addAndGet(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionGenerated(int x, int z) {
|
||||
listener.onRegionGenerated(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionGenerating(int x, int z) {
|
||||
listener.onRegionGenerating(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionSkipped(int x, int z) {
|
||||
listener.onRegionSkipped(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkStarted(int x, int z) {
|
||||
net.add(new Position2(x, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkFailed(int x, int z) {
|
||||
retry.add(new Position2(x, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkReclaim(int revert) {
|
||||
generated.addAndGet(-revert);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkGeneratedChunk(int x, int z) {
|
||||
generated.addAndGet(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkDownloaded(int x, int z) {
|
||||
net.remove(new Position2(x, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
listener.onClose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaving() {
|
||||
listener.onSaving();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkExistsInRegionGen(int x, int z) {
|
||||
listener.onChunkExistsInRegionGen(x, z);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public boolean paused() {
|
||||
return paused.get();
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
public interface PregenListener {
|
||||
void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method);
|
||||
|
||||
void onChunkGenerating(int x, int z);
|
||||
|
||||
void onChunkGenerated(int x, int z);
|
||||
|
||||
void onRegionGenerated(int x, int z);
|
||||
|
||||
void onRegionGenerating(int x, int z);
|
||||
|
||||
void onRegionSkipped(int x, int z);
|
||||
|
||||
void onNetworkStarted(int x, int z);
|
||||
|
||||
void onNetworkFailed(int x, int z);
|
||||
|
||||
void onNetworkReclaim(int revert);
|
||||
|
||||
void onNetworkGeneratedChunk(int x, int z);
|
||||
|
||||
void onNetworkDownloaded(int x, int z);
|
||||
|
||||
void onClose();
|
||||
|
||||
void onSaving();
|
||||
|
||||
void onChunkExistsInRegionGen(int x, int z);
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.Spiraled;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
public class PregenTask {
|
||||
@Builder.Default
|
||||
private Position2 center = new Position2(0, 0);
|
||||
|
||||
@Builder.Default
|
||||
private int radius = 1;
|
||||
|
||||
private static final KList<Position2> order = computeChunkOrder();
|
||||
|
||||
public void iterateRegions(Spiraled s) {
|
||||
new Spiraler(radius * 2, radius * 2, s)
|
||||
.setOffset(center.getX(), center.getZ()).drain();
|
||||
}
|
||||
|
||||
public static void iterateRegion(int xr, int zr, Spiraled s) {
|
||||
for (Position2 i : order) {
|
||||
s.on(i.getX() + (xr << 5), i.getZ() + (zr << 5));
|
||||
}
|
||||
}
|
||||
|
||||
public void iterateAllChunks(Spiraled s) {
|
||||
new Spiraler(radius * 2, radius * 2, (x, z) -> iterateRegion(x, z, s))
|
||||
.setOffset(center.getX(), center.getZ()).drain();
|
||||
}
|
||||
|
||||
private static KList<Position2> computeChunkOrder() {
|
||||
Position2 center = new Position2(15, 15);
|
||||
KList<Position2> p = new KList<>();
|
||||
new Spiraler(33, 33, (x, z) -> {
|
||||
int xx = x + 15;
|
||||
int zz = z + 15;
|
||||
if (xx < 0 || xx > 31 || zz < 0 || zz > 31) {
|
||||
return;
|
||||
}
|
||||
|
||||
p.add(new Position2(xx, zz));
|
||||
}).drain();
|
||||
p.sort(Comparator.comparing((i) -> i.distance(center)));
|
||||
return p;
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
/**
|
||||
* Represents something that is capable of generating in chunks or regions, or both
|
||||
*/
|
||||
public interface PregeneratorMethod {
|
||||
/**
|
||||
* This is called before any generate methods are called. Setup your generator here
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* This is called after the pregenerator is done. Save your work and stop threads
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* This is called every X amount of chunks or regions. Save work,
|
||||
* but no need to save all of it. At the end, close() will still be called.
|
||||
*/
|
||||
void save();
|
||||
|
||||
/**
|
||||
* Return true if regions can be generated
|
||||
*
|
||||
* @param x the x region
|
||||
* @param z the z region
|
||||
* @return true if they can be
|
||||
*/
|
||||
boolean supportsRegions(int x, int z, PregenListener listener);
|
||||
|
||||
/**
|
||||
* Return the name of the method being used
|
||||
*
|
||||
* @param x the x region
|
||||
* @param z the z region
|
||||
* @return the name
|
||||
*/
|
||||
String getMethod(int x, int z);
|
||||
|
||||
/**
|
||||
* Called to generate a region. Execute sync, if multicore internally, wait
|
||||
* for the task to complete
|
||||
*
|
||||
* @param x the x
|
||||
* @param z the z
|
||||
* @param listener signal chunks generating & generated. Parallel capable.
|
||||
*/
|
||||
void generateRegion(int x, int z, PregenListener listener);
|
||||
|
||||
/**
|
||||
* Called to generate a chunk. You can go async so long as save will wait on the threads to finish
|
||||
*
|
||||
* @param x the x
|
||||
* @param z the z
|
||||
* @param listener
|
||||
*/
|
||||
void generateChunk(int x, int z, PregenListener listener);
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.World;
|
||||
|
||||
public class AsyncOrMedievalPregenMethod implements PregeneratorMethod {
|
||||
private final PregeneratorMethod method;
|
||||
|
||||
public AsyncOrMedievalPregenMethod(World world, int threads) {
|
||||
method = PaperLib.isPaper() ? new AsyncPregenMethod(world, threads) : new MedievalPregenMethod(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
method.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
method.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
method.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod(int x, int z) {
|
||||
return method.getMethod(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateRegion(int x, int z, PregenListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
method.generateChunk(x, z, listener);
|
||||
}
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
private final World world;
|
||||
private final MultiBurst burst;
|
||||
private final KList<CompletableFuture<?>> future;
|
||||
|
||||
public AsyncPregenMethod(World world, int threads) {
|
||||
if (!PaperLib.isPaper()) {
|
||||
throw new UnsupportedOperationException("Cannot use PaperAsync on non paper!");
|
||||
}
|
||||
|
||||
this.world = world;
|
||||
burst = new MultiBurst("Iris Async Pregenerator", IrisSettings.get().getConcurrency().getPregenThreadPriority(), threads);
|
||||
future = new KList<>(1024);
|
||||
}
|
||||
|
||||
private void unloadAndSaveAllChunks() {
|
||||
try {
|
||||
J.sfut(() -> {
|
||||
for (Chunk i : world.getLoadedChunks()) {
|
||||
i.unload(true);
|
||||
}
|
||||
world.save();
|
||||
}).get();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void completeChunk(int x, int z, PregenListener listener) {
|
||||
try {
|
||||
PaperLib.getChunkAtAsync(world, x, z, true).get();
|
||||
listener.onChunkGenerated(x, z);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForChunks() {
|
||||
for (CompletableFuture<?> i : future) {
|
||||
try {
|
||||
i.get();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
future.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
unloadAndSaveAllChunks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod(int x, int z) {
|
||||
return "Async";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
waitForChunks();
|
||||
burst.shutdownAndAwait();
|
||||
unloadAndSaveAllChunks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
waitForChunks();
|
||||
unloadAndSaveAllChunks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateRegion(int x, int z, PregenListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
if (future.size() > IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getPregenThreadCount())) {
|
||||
waitForChunks();
|
||||
}
|
||||
|
||||
listener.onChunkGenerating(x, z);
|
||||
future.add(burst.complete(() -> completeChunk(x, z, listener)));
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
|
||||
public class DummyPregenMethod implements PregeneratorMethod {
|
||||
@Override
|
||||
public void init() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod(int x, int z) {
|
||||
return "Dummy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateRegion(int x, int z, PregenListener listener) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.engine.headless.HeadlessGenerator;
|
||||
import com.volmit.iris.engine.headless.HeadlessWorld;
|
||||
import lombok.Getter;
|
||||
|
||||
public class HeadlessPregenMethod implements PregeneratorMethod {
|
||||
private final HeadlessWorld world;
|
||||
|
||||
@Getter
|
||||
private final HeadlessGenerator generator;
|
||||
|
||||
public HeadlessPregenMethod(HeadlessWorld world) {
|
||||
this(world, world.generate());
|
||||
}
|
||||
|
||||
public HeadlessPregenMethod(HeadlessWorld world, HeadlessGenerator generator) {
|
||||
this.world = world;
|
||||
this.generator = generator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
generator.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
generator.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod(int x, int z) {
|
||||
return "Headless";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateRegion(int x, int z, PregenListener listener) {
|
||||
generator.generateRegion(x, z, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.engine.headless.HeadlessWorld;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class HybridPregenMethod implements PregeneratorMethod {
|
||||
private final PregeneratorMethod headless;
|
||||
private final PregeneratorMethod inWorld;
|
||||
private final World world;
|
||||
|
||||
public HybridPregenMethod(World world, int threads) {
|
||||
this.world = world;
|
||||
headless = supportsHeadless(world)
|
||||
? new HeadlessPregenMethod(HeadlessWorld.from(world)) : new DummyPregenMethod();
|
||||
inWorld = new AsyncOrMedievalPregenMethod(world, threads);
|
||||
}
|
||||
|
||||
private boolean supportsHeadless(World world) {
|
||||
return IrisWorlds.access(world) != null && IrisSettings.get().getGenerator().isMcaPregenerator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod(int x, int z) {
|
||||
return "Hybrid<" + ((supportsRegions(x, z, null) ? headless.getMethod(x, z) : inWorld.getMethod(x, z)) + ">");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
headless.init();
|
||||
inWorld.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
headless.close();
|
||||
inWorld.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
headless.save();
|
||||
inWorld.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||
if (headless instanceof DummyPregenMethod) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean r = !new File(world.getWorldFolder(), "region/r." + x + "." + z + ".mca").exists();
|
||||
|
||||
if (!r && listener != null) {
|
||||
try {
|
||||
for (Position2 i : ((HeadlessPregenMethod) headless).getGenerator().getChunksInRegion(x, z)) {
|
||||
listener.onChunkExistsInRegionGen((x << 5) + i.getX(), (z << 5) + i.getZ());
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateRegion(int x, int z, PregenListener listener) {
|
||||
headless.generateRegion(x, z, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
inWorld.generateChunk(x, z, listener);
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class MedievalPregenMethod implements PregeneratorMethod {
|
||||
private final World world;
|
||||
private final KList<CompletableFuture<?>> futures;
|
||||
|
||||
public MedievalPregenMethod(World world) {
|
||||
this.world = world;
|
||||
futures = new KList<>();
|
||||
}
|
||||
|
||||
private void waitForChunks() {
|
||||
for (CompletableFuture<?> i : futures) {
|
||||
try {
|
||||
i.get();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
futures.clear();
|
||||
}
|
||||
|
||||
private void unloadAndSaveAllChunks() {
|
||||
waitForChunks();
|
||||
try {
|
||||
J.sfut(() -> {
|
||||
for (Chunk i : world.getLoadedChunks()) {
|
||||
i.unload(true);
|
||||
}
|
||||
world.save();
|
||||
}).get();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
unloadAndSaveAllChunks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
unloadAndSaveAllChunks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
unloadAndSaveAllChunks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateRegion(int x, int z, PregenListener listener) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod(int x, int z) {
|
||||
return "Medieval";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
if (futures.size() > IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getPregenThreadCount())) {
|
||||
waitForChunks();
|
||||
}
|
||||
|
||||
listener.onChunkGenerating(x, z);
|
||||
futures.add(J.sfut(() -> {
|
||||
world.getChunkAt(x, z);
|
||||
listener.onChunkGenerated(x, z);
|
||||
}));
|
||||
}
|
||||
}
|
@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.google.common.util.concurrent.AtomicDouble;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.core.pregenerator.syndicate.SyndicateClient;
|
||||
import com.volmit.iris.core.pregenerator.syndicate.command.*;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.Getter;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class SyndicatePregenMethod implements PregeneratorMethod {
|
||||
@Getter
|
||||
private String address;
|
||||
private String nickname;
|
||||
private int port;
|
||||
private String password;
|
||||
private IrisDimension dimension;
|
||||
private boolean ready = false;
|
||||
private File worldFolder;
|
||||
private UUID pack = UUID.randomUUID();
|
||||
private long seed;
|
||||
|
||||
public SyndicatePregenMethod(String nickname, File worldFolder, String address, int port, String password, IrisDimension dimension, long seed) {
|
||||
this.seed = seed;
|
||||
this.worldFolder = worldFolder;
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
this.password = password;
|
||||
this.dimension = dimension;
|
||||
}
|
||||
|
||||
private SyndicateClient.SyndicateClientBuilder connect() {
|
||||
return SyndicateClient.builder().address(address).port(port);
|
||||
}
|
||||
|
||||
public synchronized void setup() {
|
||||
if (ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
ready = false;
|
||||
try {
|
||||
connect().command(SyndicateInstallPack
|
||||
.builder()
|
||||
.dimension(dimension)
|
||||
.pack(pack)
|
||||
.seed(seed)
|
||||
.build())
|
||||
.output((o) -> {
|
||||
File to = new File(Iris.getTemp(), "send-" + pack.toString() + ".zip");
|
||||
ZipUtil.pack(dimension.getLoader().getDataFolder(), to);
|
||||
|
||||
try {
|
||||
IO.writeAll(to, o);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
to.deleteOnExit();
|
||||
})
|
||||
.build().go((response, data) -> {
|
||||
if (response instanceof SyndicateBusy) {
|
||||
throw new RuntimeException("Service is busy, will try later");
|
||||
}
|
||||
|
||||
ready = true;
|
||||
});
|
||||
ready = true;
|
||||
} catch (Throwable throwable) {
|
||||
if (throwable instanceof RuntimeException) {
|
||||
ready = false;
|
||||
return;
|
||||
}
|
||||
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canGenerate() {
|
||||
if (!ready) {
|
||||
J.a(this::setup);
|
||||
}
|
||||
|
||||
return ready;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
J.a(this::setup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (ready) {
|
||||
try {
|
||||
connect()
|
||||
.command(SyndicateClose
|
||||
.builder()
|
||||
.pack(pack)
|
||||
.build())
|
||||
.build()
|
||||
.go((__, __b) -> {
|
||||
});
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRegions(int x, int z, PregenListener listener) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod(int x, int z) {
|
||||
return "Syndicate<" + nickname + ">";
|
||||
}
|
||||
|
||||
private double checkProgress(int x, int z) {
|
||||
AtomicDouble progress = new AtomicDouble(-1);
|
||||
try {
|
||||
connect()
|
||||
.command(SyndicateGetProgress.builder()
|
||||
.pack(pack).build()).output((i) -> {
|
||||
}).build().go((response, o) -> {
|
||||
if (response instanceof SyndicateSendProgress) {
|
||||
if (((SyndicateSendProgress) response).isAvailable()) {
|
||||
progress.set(((SyndicateSendProgress) response).getProgress());
|
||||
File f = new File(worldFolder, "region/r." + x + "." + z + ".mca");
|
||||
try {
|
||||
f.getParentFile().mkdirs();
|
||||
IO.writeAll(f, o);
|
||||
progress.set(1000);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
|
||||
return progress.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateRegion(int x, int z, PregenListener listener) {
|
||||
if (!ready) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
try {
|
||||
connect().command(SyndicateGenerate
|
||||
.builder()
|
||||
.x(x).z(z).pack(pack)
|
||||
.build())
|
||||
.build().go((response, data) -> {
|
||||
if (response instanceof SyndicateOK) {
|
||||
listener.onNetworkStarted(x, z);
|
||||
J.a(() -> {
|
||||
double lastp = 0;
|
||||
int calls = 0;
|
||||
boolean installed = false;
|
||||
while (true) {
|
||||
J.sleep(100);
|
||||
double progress = checkProgress(x, z);
|
||||
|
||||
if (progress == 1000) {
|
||||
installed = true;
|
||||
AtomicInteger a = new AtomicInteger(calls);
|
||||
PregenTask.iterateRegion(x, z, (xx, zz) -> {
|
||||
if (a.decrementAndGet() < 0) {
|
||||
listener.onNetworkGeneratedChunk(xx, zz);
|
||||
}
|
||||
});
|
||||
calls = 1024;
|
||||
} else if (progress < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
int change = (int) Math.floor((progress - lastp) * 1024D);
|
||||
change = change == 0 ? 1 : change;
|
||||
|
||||
AtomicInteger a = new AtomicInteger(calls);
|
||||
AtomicInteger b = new AtomicInteger(change);
|
||||
PregenTask.iterateRegion(x, z, (xx, zz) -> {
|
||||
if (a.decrementAndGet() < 0) {
|
||||
if (b.decrementAndGet() >= 0) {
|
||||
listener.onNetworkGeneratedChunk(xx, zz);
|
||||
}
|
||||
}
|
||||
});
|
||||
calls += change;
|
||||
}
|
||||
|
||||
if (!installed) {
|
||||
// TODO RETRY REGION
|
||||
return;
|
||||
}
|
||||
|
||||
listener.onNetworkDownloaded(x, z);
|
||||
});
|
||||
} else if (response instanceof SyndicateInstallFirst) {
|
||||
ready = false;
|
||||
throw new RuntimeException();
|
||||
} else if (response instanceof SyndicateBusy) {
|
||||
throw new RuntimeException();
|
||||
} else {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
});
|
||||
} catch (Throwable throwable) {
|
||||
|
||||
if (throwable instanceof RuntimeException) {
|
||||
throw (RuntimeException) throwable;
|
||||
}
|
||||
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.syndicate;
|
||||
|
||||
import com.volmit.iris.core.pregenerator.syndicate.command.SyndicateCommand;
|
||||
import com.volmit.iris.util.function.Consumer2;
|
||||
import lombok.Builder;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Builder
|
||||
public class SyndicateClient {
|
||||
private String address;
|
||||
private int port;
|
||||
private SyndicateCommand command;
|
||||
private Consumer<DataOutputStream> output;
|
||||
|
||||
public void go(Consumer2<SyndicateCommand, DataInputStream> handler) throws Throwable {
|
||||
Socket socket = new Socket(address, port);
|
||||
DataInputStream i = new DataInputStream(socket.getInputStream());
|
||||
DataOutputStream o = new DataOutputStream(socket.getOutputStream());
|
||||
SyndicateCommandIO.write(command, o);
|
||||
|
||||
if (output != null) {
|
||||
output.accept(o);
|
||||
}
|
||||
|
||||
o.flush();
|
||||
handler.accept(SyndicateCommandIO.read(i), i);
|
||||
socket.close();
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.syndicate;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.volmit.iris.core.pregenerator.syndicate.command.SyndicateCommand;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class SyndicateCommandIO {
|
||||
private static final Gson gson = new Gson();
|
||||
|
||||
public static SyndicateCommand read(DataInputStream in) throws IOException, ClassNotFoundException {
|
||||
String clazz = in.readUTF();
|
||||
return (SyndicateCommand) gson.fromJson(in.readUTF(), Class.forName(clazz));
|
||||
}
|
||||
|
||||
public static void write(SyndicateCommand c, DataOutputStream out) throws IOException {
|
||||
out.writeUTF(c.getClass().getCanonicalName());
|
||||
out.writeUTF(gson.toJson(c));
|
||||
}
|
||||
}
|
@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.syndicate;
|
||||
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.syndicate.command.*;
|
||||
import com.volmit.iris.engine.headless.HeadlessGenerator;
|
||||
import com.volmit.iris.engine.headless.HeadlessWorld;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class SyndicateServer extends Thread implements PregenListener {
|
||||
private int port;
|
||||
private String password;
|
||||
private boolean busy;
|
||||
private int tc;
|
||||
private HeadlessGenerator generator;
|
||||
private ServerSocket server;
|
||||
private File cache;
|
||||
private UUID currentId = null;
|
||||
private AtomicInteger g = new AtomicInteger(0);
|
||||
private File lastGeneratedRegion = null;
|
||||
|
||||
public SyndicateServer(File cache, int port, String password, int tc) throws IOException {
|
||||
this.port = port;
|
||||
this.cache = cache;
|
||||
this.password = password;
|
||||
this.tc = tc;
|
||||
start();
|
||||
server = new ServerSocket(port);
|
||||
server.setSoTimeout(1000);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (!interrupted()) {
|
||||
try {
|
||||
Socket client = server.accept();
|
||||
DataInputStream i = new DataInputStream(client.getInputStream());
|
||||
DataOutputStream o = new DataOutputStream(client.getOutputStream());
|
||||
try {
|
||||
handle(client, i, o);
|
||||
o.flush();
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
client.close();
|
||||
} catch (SocketTimeoutException ignored) {
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handle(Socket client, DataInputStream i, DataOutputStream o) throws Throwable {
|
||||
SyndicateCommand cmd = handle(SyndicateCommandIO.read(i), i, o);
|
||||
|
||||
if (cmd != null) {
|
||||
SyndicateCommandIO.write(cmd, o);
|
||||
}
|
||||
|
||||
o.flush();
|
||||
}
|
||||
|
||||
private File getCachedDim(UUID id) {
|
||||
return new File(cache, id.toString().charAt(2) + "/" + id.toString().substring(0, 4) + "/" + id);
|
||||
}
|
||||
|
||||
private SyndicateCommand handle(SyndicateCommand command, DataInputStream i, DataOutputStream o) throws Throwable {
|
||||
if (command instanceof SyndicateInstallPack) {
|
||||
if (busy) {
|
||||
return new SyndicateBusy();
|
||||
}
|
||||
|
||||
if (generator != null) {
|
||||
generator.close();
|
||||
IO.delete(generator.getWorld().getWorld().worldFolder());
|
||||
generator = null;
|
||||
}
|
||||
|
||||
UUID id = ((SyndicateInstallPack) command).getPack();
|
||||
File cacheload = new File(cache, id.toString().charAt(2) + "/" + id.toString().substring(0, 4) + "/" + id + ".zip");
|
||||
File cachestore = getCachedDim(id);
|
||||
IO.delete(cachestore);
|
||||
int len = i.readInt();
|
||||
cacheload.getParentFile().mkdirs();
|
||||
byte[] buf = new byte[8192];
|
||||
FileOutputStream fos = new FileOutputStream(cacheload);
|
||||
IO.transfer(i, fos, buf, len);
|
||||
fos.close();
|
||||
ZipUtil.unpack(cacheload, cachestore);
|
||||
cacheload.deleteOnExit();
|
||||
HeadlessWorld w = new HeadlessWorld("turbo/" + id.toString(), ((SyndicateInstallPack) command).getDimension(), ((SyndicateInstallPack) command).getSeed());
|
||||
w.setStudio(true);
|
||||
generator = w.generate();
|
||||
return new SyndicateOK();
|
||||
}
|
||||
|
||||
if (command instanceof SyndicateGenerate) {
|
||||
if (busy) {
|
||||
return new SyndicateBusy();
|
||||
}
|
||||
|
||||
if (generator == null || !Objects.equals(currentId, ((SyndicateGenerate) command).getPack())) {
|
||||
return new SyndicateInstallFirst();
|
||||
}
|
||||
|
||||
g.set(0);
|
||||
busy = true;
|
||||
J.a(() -> {
|
||||
busy = false;
|
||||
lastGeneratedRegion = generator.generateRegionToFile(((SyndicateGenerate) command).getX(), ((SyndicateGenerate) command).getZ(), this);
|
||||
});
|
||||
return new SyndicateOK();
|
||||
}
|
||||
|
||||
if (command instanceof SyndicateClose) {
|
||||
if (generator != null && Objects.equals(currentId, ((SyndicateClose) command).getPack()) && !busy) {
|
||||
generator.close();
|
||||
IO.delete(generator.getWorld().getWorld().worldFolder());
|
||||
generator = null;
|
||||
currentId = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (command instanceof SyndicateGetProgress) {
|
||||
if (generator != null && busy && Objects.equals(currentId, ((SyndicateGetProgress) command).getPack())) {
|
||||
return SyndicateSendProgress.builder().progress((double) g.get() / 1024D).build();
|
||||
} else if (generator != null && !busy && Objects.equals(currentId, ((SyndicateGetProgress) command).getPack()) && lastGeneratedRegion != null && lastGeneratedRegion.exists()) {
|
||||
SyndicateCommandIO.write(SyndicateSendProgress
|
||||
.builder()
|
||||
.progress(1).available(true)
|
||||
.build(), o);
|
||||
o.writeLong(lastGeneratedRegion.length());
|
||||
IO.writeAll(lastGeneratedRegion, o);
|
||||
return null;
|
||||
} else if (generator == null) {
|
||||
return new SyndicateInstallFirst();
|
||||
} else {
|
||||
return new SyndicateBusy();
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Unexpected value: " + command.getClass());
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
interrupt();
|
||||
generator.close();
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkGenerating(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkGenerated(int x, int z) {
|
||||
g.incrementAndGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionGenerated(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionGenerating(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionSkipped(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkStarted(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkFailed(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkReclaim(int revert) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkGeneratedChunk(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkDownloaded(int x, int z) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaving() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkExistsInRegionGen(int x, int z) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.syndicate.command;
|
||||
|
||||
public class SyndicateBusy implements SyndicateCommand {
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.syndicate.command;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class SyndicateClose implements SyndicateCommand {
|
||||
@Builder.Default
|
||||
private UUID pack = UUID.randomUUID();
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.syndicate.command;
|
||||
|
||||
public interface SyndicateCommand {
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.syndicate.command;
|
||||
|
||||
public class SyndicateError implements SyndicateCommand {
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.syndicate.command;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class SyndicateGenerate implements SyndicateCommand {
|
||||
@Builder.Default
|
||||
private int x = 0;
|
||||
@Builder.Default
|
||||
private int z = 0;
|
||||
@Builder.Default
|
||||
private UUID pack = UUID.randomUUID();
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.syndicate.command;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SyndicateGetProgress implements SyndicateCommand {
|
||||
@Builder.Default
|
||||
private UUID pack = UUID.randomUUID();
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.syndicate.command;
|
||||
|
||||
public class SyndicateInstallFirst implements SyndicateCommand {
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.syndicate.command;
|
||||
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class SyndicateInstallPack implements SyndicateCommand {
|
||||
@Builder.Default
|
||||
private UUID pack = UUID.randomUUID();
|
||||
|
||||
@Builder.Default
|
||||
private long seed = 1337;
|
||||
|
||||
@Builder.Default
|
||||
private IrisDimension dimension = null;
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.syndicate.command;
|
||||
|
||||
public class SyndicateOK implements SyndicateCommand {
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.pregenerator.syndicate.command;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SyndicateSendProgress implements SyndicateCommand {
|
||||
@Builder.Default
|
||||
private double progress = 0;
|
||||
@Builder.Default
|
||||
private boolean available = false;
|
||||
}
|
220
src/main/java/com/volmit/iris/core/tools/IrisCreator.java
Normal file
220
src/main/java/com/volmit/iris/core/tools/IrisCreator.java
Normal file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.tools;
|
||||
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.engine.headless.HeadlessWorld;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.exceptions.IrisException;
|
||||
import com.volmit.iris.util.exceptions.MissingDimensionException;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.O;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.WorldCreator;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Makes it a lot easier to setup an engine, world, studio or whatever
|
||||
*/
|
||||
@Data
|
||||
@Accessors(fluent = true, chain = true)
|
||||
public class IrisCreator {
|
||||
/**
|
||||
* Specify an area to pregenerate during creation
|
||||
*/
|
||||
private PregenTask pregen;
|
||||
|
||||
/**
|
||||
* Specify a sender to get updates & progress info + tp when world is created.
|
||||
*/
|
||||
private VolmitSender sender;
|
||||
|
||||
/**
|
||||
* The seed to use for this generator
|
||||
*/
|
||||
private long seed = RNG.r.nextLong();
|
||||
|
||||
/**
|
||||
* The dimension to use. This can be any online dimension, or a dimension in the
|
||||
* packs folder
|
||||
*/
|
||||
private String dimension = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||
|
||||
/**
|
||||
* The name of this world.
|
||||
*/
|
||||
private String name = "irisworld";
|
||||
|
||||
/**
|
||||
* Headless mode allows Iris to generate / query engine information
|
||||
* without needing an actual world loaded. This is normally only used
|
||||
* for pregeneration purposes but it could be used for mapping.
|
||||
*/
|
||||
private boolean headless = false;
|
||||
|
||||
/**
|
||||
* Studio mode makes the engine hotloadable and uses the dimension in
|
||||
* your Iris/packs folder instead of copying the dimension files into
|
||||
* the world itself. Studio worlds are deleted when they are unloaded.
|
||||
*/
|
||||
private boolean studio = false;
|
||||
|
||||
/**
|
||||
* Create the IrisAccess (contains the world)
|
||||
*
|
||||
* @return the IrisAccess
|
||||
* @throws IrisException shit happens
|
||||
*/
|
||||
public IrisAccess create() throws IrisException {
|
||||
IrisDimension d = IrisToolbelt.getDimension(dimension());
|
||||
IrisAccess access = null;
|
||||
Consumer<Double> prog = (pxx) -> {
|
||||
double px = (headless && pregen != null) ? pxx / 2 : pxx;
|
||||
|
||||
if (pregen != null && !headless) {
|
||||
px = (px / 2) + 0.5;
|
||||
}
|
||||
|
||||
if (sender != null) {
|
||||
if (sender.isPlayer()) {
|
||||
sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generating " + Form.pc(px)));
|
||||
} else {
|
||||
sender.sendMessage("Generating " + Form.f(px, 0));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (d == null) {
|
||||
throw new MissingDimensionException("Cannot find dimension '" + dimension() + "'");
|
||||
}
|
||||
|
||||
if (headless) {
|
||||
HeadlessWorld w = new HeadlessWorld(name, d, seed, studio);
|
||||
access = w.generate().getGenerator();
|
||||
} else {
|
||||
O<Boolean> done = new O<>();
|
||||
done.set(false);
|
||||
WorldCreator wc = new IrisWorldCreator()
|
||||
.dimension(dimension)
|
||||
.name(name)
|
||||
.seed(seed)
|
||||
.studio(studio)
|
||||
.create();
|
||||
access = (IrisAccess) wc.generator();
|
||||
IrisAccess finalAccess1 = access;
|
||||
|
||||
J.a(() ->
|
||||
{
|
||||
int req = 400;
|
||||
|
||||
while (finalAccess1.getGenerated() < req && !done.get()) {
|
||||
double v = (double) finalAccess1.getGenerated() / (double) req;
|
||||
|
||||
if (pregen != null) {
|
||||
v /= 2;
|
||||
}
|
||||
|
||||
if (sender.isPlayer()) {
|
||||
sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess1.getGenerated()) + " Left)"))));
|
||||
J.sleep(50);
|
||||
} else {
|
||||
sender.sendMessage(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess1.getGenerated()) + " Left)")));
|
||||
J.sleep(1000);
|
||||
}
|
||||
|
||||
if (finalAccess1.isFailing()) {
|
||||
|
||||
sender.sendMessage("Generation Failed!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generation Complete"));
|
||||
});
|
||||
|
||||
wc.createWorld();
|
||||
done.set(true);
|
||||
}
|
||||
|
||||
if (access == null) {
|
||||
throw new IrisException("Access is null. Something bad happened.");
|
||||
}
|
||||
|
||||
IrisAccess finalAccess = access;
|
||||
Runnable loadup = () -> {
|
||||
try {
|
||||
J.sfut(() -> {
|
||||
if (headless) {
|
||||
O<Boolean> done = new O<>();
|
||||
done.set(false);
|
||||
|
||||
J.a(() ->
|
||||
{
|
||||
int req = 400;
|
||||
|
||||
while (finalAccess.getGenerated() < req && !done.get()) {
|
||||
double v = (double) finalAccess.getGenerated() / (double) req;
|
||||
v = (v / 2) + 0.5;
|
||||
|
||||
if (sender.isPlayer()) {
|
||||
sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess.getGenerated()) + " Left)"))));
|
||||
J.sleep(50);
|
||||
} else {
|
||||
sender.sendMessage(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess.getGenerated()) + " Left)")));
|
||||
J.sleep(1000);
|
||||
}
|
||||
|
||||
if (finalAccess.isFailing()) {
|
||||
|
||||
sender.sendMessage("Generation Failed!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generation Complete"));
|
||||
});
|
||||
|
||||
finalAccess.getHeadlessGenerator().getWorld().load();
|
||||
done.set(true);
|
||||
}
|
||||
}).get();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
};
|
||||
|
||||
if (pregen != null) {
|
||||
IrisToolbelt.pregenerate(pregen, access).onProgress(prog).whenDone(loadup);
|
||||
} else {
|
||||
loadup.run();
|
||||
}
|
||||
|
||||
return access;
|
||||
}
|
||||
}
|
148
src/main/java/com/volmit/iris/core/tools/IrisToolbelt.java
Normal file
148
src/main/java/com/volmit/iris/core/tools/IrisToolbelt.java
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.core.tools;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.gui.PregeneratorJob;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.core.pregenerator.methods.HeadlessPregenMethod;
|
||||
import com.volmit.iris.core.pregenerator.methods.HybridPregenMethod;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Something you really want to wear if working on Iris. Shit gets pretty hectic down there.
|
||||
* Hope you packed snacks & road sodas.
|
||||
*/
|
||||
public class IrisToolbelt {
|
||||
/**
|
||||
* Will find / download / search for the dimension or return null
|
||||
* <p>
|
||||
* - You can provide a dimenson in the packs folder by the folder name
|
||||
* - You can provide a github repo by using (assumes branch is master unless specified)
|
||||
* - GithubUsername/repository
|
||||
* - GithubUsername/repository/branch
|
||||
*
|
||||
* @param dimension the dimension id such as overworld or flat
|
||||
* @return the IrisDimension or null
|
||||
*/
|
||||
public static IrisDimension getDimension(String dimension) {
|
||||
File pack = Iris.instance.getDataFolder("packs", dimension);
|
||||
|
||||
if (!pack.exists()) {
|
||||
Iris.proj.downloadSearch(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag()), dimension, false, false);
|
||||
}
|
||||
|
||||
if (!pack.exists()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new IrisDataManager(pack).getDimensionLoader().load(dimension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a world with plenty of options
|
||||
*
|
||||
* @return the creator builder
|
||||
*/
|
||||
public static IrisCreator createWorld() {
|
||||
return new IrisCreator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given world is an Iris World (same as access(world) != null)
|
||||
*
|
||||
* @param world the world
|
||||
* @return true if it is an Iris Access world
|
||||
*/
|
||||
public static boolean isIrisWorld(World world) {
|
||||
return access(world) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Iris generator for the given world
|
||||
*
|
||||
* @param world the given world
|
||||
* @return the IrisAccess or null if it's not an Iris World
|
||||
*/
|
||||
public static IrisAccess access(World world) {
|
||||
return IrisWorlds.access(world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a pregenerator task
|
||||
*
|
||||
* @param task the scheduled task
|
||||
* @param method the method to execute the task
|
||||
* @return the pregenerator job (already started)
|
||||
*/
|
||||
public static PregeneratorJob pregenerate(PregenTask task, PregeneratorMethod method) {
|
||||
return new PregeneratorJob(task, method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a pregenerator task. If the supplied generator is headless, headless mode is used,
|
||||
* otherwise Hybrid mode is used.
|
||||
*
|
||||
* @param task the scheduled task
|
||||
* @param access the Iris Generator
|
||||
* @return the pregenerator job (already started)
|
||||
*/
|
||||
public static PregeneratorJob pregenerate(PregenTask task, IrisAccess access) {
|
||||
if (access.isHeadless()) {
|
||||
return pregenerate(task, new HeadlessPregenMethod(access.getHeadlessGenerator().getWorld(), access.getHeadlessGenerator()));
|
||||
}
|
||||
|
||||
return pregenerate(task, new HybridPregenMethod(access.getCompound().getWorld().realWorld(), IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getPregenThreadCount())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a pregenerator task. If the supplied generator is headless, headless mode is used,
|
||||
* otherwise Hybrid mode is used.
|
||||
*
|
||||
* @param task the scheduled task
|
||||
* @param world the World
|
||||
* @return the pregenerator job (already started)
|
||||
*/
|
||||
public static PregeneratorJob pregenerate(PregenTask task, World world) {
|
||||
if (isIrisWorld(world)) {
|
||||
return pregenerate(task, access(world));
|
||||
}
|
||||
|
||||
return pregenerate(task, new HybridPregenMethod(world, IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getPregenThreadCount())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Evacuate all players from the world into literally any other world.
|
||||
* If there are no other worlds, kick them! Not the best but what's mine is mine sometimes...
|
||||
*
|
||||
* @param world the world to evac
|
||||
*/
|
||||
public static void evacuate(World world) {
|
||||
IrisWorlds.evacuate(world);
|
||||
}
|
||||
}
|
@ -16,12 +16,12 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine;
|
||||
package com.volmit.iris.core.tools;
|
||||
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.engine.framework.EngineCompositeGenerator;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.fakenews.FakeWorld;
|
||||
import com.volmit.iris.engine.object.common.IrisWorld;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
|
||||
@ -78,8 +78,14 @@ public class IrisWorldCreator {
|
||||
|
||||
public WorldCreator create() {
|
||||
EngineCompositeGenerator g = new EngineCompositeGenerator(dimensionName, !studio);
|
||||
g.initialize(new FakeWorld(name, minHeight, maxHeight, seed, new File(name), findEnvironment()));
|
||||
|
||||
g.initialize(IrisWorld.builder()
|
||||
.name(name)
|
||||
.minHeight(minHeight)
|
||||
.maxHeight(maxHeight)
|
||||
.seed(seed)
|
||||
.worldFolder(new File(name))
|
||||
.environment(findEnvironment())
|
||||
.build());
|
||||
return new WorldCreator(name)
|
||||
.environment(findEnvironment())
|
||||
.generateStructures(true)
|
||||
@ -94,4 +100,9 @@ public class IrisWorldCreator {
|
||||
return dim.getEnvironment();
|
||||
}
|
||||
}
|
||||
|
||||
public IrisWorldCreator studio(boolean studio) {
|
||||
this.studio = studio;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine;
|
||||
package com.volmit.iris.core.tools;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
@ -107,15 +107,16 @@ public class IrisComplex implements DataProvider {
|
||||
}
|
||||
|
||||
public IrisComplex(Engine engine, boolean simple) {
|
||||
int cacheSize = 1024 * 128;
|
||||
this.rng = new RNG(engine.getWorld().getSeed());
|
||||
int cacheSize = 131072;
|
||||
IrisBiome emptyBiome = new IrisBiome();
|
||||
this.rng = new RNG(engine.getWorld().seed());
|
||||
this.data = engine.getData();
|
||||
double height = engine.getHeight();
|
||||
fluidHeight = engine.getDimension().getFluidHeight();
|
||||
generators = new KList<>();
|
||||
focus = engine.getFocus();
|
||||
IrisRegion focusRegion = focus != null ? findRegion(focus, engine) : null;
|
||||
RNG rng = new RNG(engine.getWorld().getSeed());
|
||||
RNG rng = new RNG(engine.getWorld().seed());
|
||||
//@builder
|
||||
engine.getDimension().getRegions().forEach((i) -> data.getRegionLoader().load(i)
|
||||
.getAllBiomes(this).forEach((b) -> b
|
||||
@ -124,7 +125,7 @@ public class IrisComplex implements DataProvider {
|
||||
overlayStream = ProceduralStream.ofDouble((x, z) -> 0D);
|
||||
engine.getDimension().getOverlayNoise().forEach((i) -> overlayStream.add((x, z) -> i.get(rng, x, z)));
|
||||
rngStream = ProceduralStream.of((x, z) -> new RNG(((x.longValue()) << 32) | (z.longValue() & 0xffffffffL))
|
||||
.nextParallelRNG(engine.getWorld().getSeed()), Interpolated.RNG);
|
||||
.nextParallelRNG(engine.getWorld().seed()), Interpolated.RNG);
|
||||
chunkRngStream = rngStream.blockToChunkCoords();
|
||||
rockStream = engine.getDimension().getRockPalette().getLayerGenerator(rng.nextParallelRNG(45), data).stream()
|
||||
.select(engine.getDimension().getRockPalette().getBlockData(data));
|
||||
@ -151,7 +152,7 @@ public class IrisComplex implements DataProvider {
|
||||
.onNull("")
|
||||
.convertCached((s) -> {
|
||||
if (s.isEmpty()) {
|
||||
return new IrisBiome();
|
||||
return emptyBiome;
|
||||
}
|
||||
|
||||
return data.getBiomeLoader().load(s)
|
||||
@ -193,12 +194,11 @@ public class IrisComplex implements DataProvider {
|
||||
.convertAware2D(this::implode).cache2D(cacheSize);
|
||||
heightStream = ProceduralStream.of((x, z) -> {
|
||||
IrisBiome b = focus != null ? focus : baseBiomeStream.get(x, z);
|
||||
return getHeight(engine, b, x, z, engine.getWorld().getSeed());
|
||||
return getHeight(engine, b, x, z, engine.getWorld().seed());
|
||||
}, Interpolated.DOUBLE).cache2D(cacheSize);
|
||||
slopeStream = heightStream.slope(3).interpolate().bilinear(3, 3).cache2D(cacheSize);
|
||||
slopeStream = heightStream.slope(3).cache2D(cacheSize);
|
||||
objectChanceStream = ProceduralStream.ofDouble((x, z) -> {
|
||||
if(engine.getDimension().hasFeatures(engine))
|
||||
{
|
||||
if (engine.getDimension().hasFeatures(engine)) {
|
||||
AtomicDouble str = new AtomicDouble(1D);
|
||||
engine.getFramework().getEngineParallax().forEachFeature(x, z, (i)
|
||||
-> str.set(Math.min(str.get(), i.getObjectChanceModifier(x, z))));
|
||||
|
@ -25,9 +25,9 @@ import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisBiomePaletteLayer;
|
||||
import com.volmit.iris.engine.object.IrisDecorator;
|
||||
import com.volmit.iris.engine.object.IrisObjectPlacement;
|
||||
import com.volmit.iris.engine.parallel.BurstExecutor;
|
||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
@ -41,8 +41,6 @@ import org.bukkit.generator.BlockPopulator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class IrisEngine extends BlockPopulator implements Engine {
|
||||
@Getter
|
||||
@ -88,7 +86,7 @@ public class IrisEngine extends BlockPopulator implements Engine {
|
||||
private double maxBiomeDecoratorDensity;
|
||||
|
||||
public IrisEngine(EngineTarget target, EngineCompound compound, int index) {
|
||||
Iris.info("Initializing Engine: " + target.getWorld().getName() + "/" + target.getDimension().getLoadKey() + " (" + target.getHeight() + " height)");
|
||||
Iris.info("Initializing Engine: " + target.getWorld().name() + "/" + target.getDimension().getLoadKey() + " (" + target.getHeight() + " height)");
|
||||
metrics = new EngineMetrics(32);
|
||||
this.target = target;
|
||||
this.framework = new IrisEngineFramework(this);
|
||||
@ -136,6 +134,7 @@ public class IrisEngine extends BlockPopulator implements Engine {
|
||||
closed = true;
|
||||
getWorldManager().close();
|
||||
getFramework().close();
|
||||
getTarget().close();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -158,21 +157,39 @@ public class IrisEngine extends BlockPopulator implements Engine {
|
||||
return z / getDimension().getTerrainZoom();
|
||||
}
|
||||
|
||||
@ChunkCoordinates
|
||||
@Override
|
||||
public void generate(int x, int z, Hunk<BlockData> vblocks, Hunk<Biome> vbiomes) {
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
BurstExecutor b = burst().burst(16);
|
||||
|
||||
// This is a very weird optimization, but it works
|
||||
// Basically we precache multicore the biome stream which effectivley
|
||||
// makes the biome stream, interpolation & noise engine run in parallel without mca
|
||||
for(int i = 0; i < vblocks.getWidth(); i++)
|
||||
{
|
||||
int finalI = i;
|
||||
b.queue(() -> {
|
||||
for(int j = 0; j < vblocks.getDepth(); j++)
|
||||
{
|
||||
getFramework().getComplex().getTrueBiomeStream().get(x+ finalI,z+j);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
b.complete();
|
||||
|
||||
switch (getDimension().getTerrainMode()) {
|
||||
case NORMAL -> {
|
||||
getFramework().getEngineParallax().generateParallaxArea(x >> 4, z >> 4);
|
||||
getFramework().getBiomeActuator().actuate(x, z, vbiomes);
|
||||
getFramework().getTerrainActuator().actuate(x, z, vblocks);
|
||||
getFramework().getBiomeActuator().actuate(x, z, vbiomes);
|
||||
getFramework().getCaveModifier().modify(x, z, vblocks);
|
||||
getFramework().getRavineModifier().modify(x, z, vblocks);
|
||||
getFramework().getPostModifier().modify(x, z, vblocks);
|
||||
getFramework().getDecorantActuator().actuate(x, z, vblocks);
|
||||
getFramework().getEngineParallax().insertParallax(x, z, vblocks);
|
||||
getFramework().getEngineParallax().insertParallax(x >> 4, z >> 4, vblocks);
|
||||
getFramework().getDepositModifier().modify(x, z, vblocks);
|
||||
}
|
||||
case ISLANDS -> {
|
||||
@ -195,6 +212,11 @@ public class IrisEngine extends BlockPopulator implements Engine {
|
||||
return getData().getBiomeLoader().load(getDimension().getFocus());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hotloading() {
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk c) {
|
||||
getWorldManager().spawnInitialEntities(c);
|
||||
|
@ -20,6 +20,7 @@ package com.volmit.iris.engine;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.EngineCompound;
|
||||
import com.volmit.iris.engine.framework.EngineData;
|
||||
@ -28,6 +29,7 @@ import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisDimensionIndex;
|
||||
import com.volmit.iris.engine.object.IrisPosition;
|
||||
import com.volmit.iris.engine.object.common.IrisWorld;
|
||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.atomics.AtomicRollingSequence;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
@ -37,7 +39,6 @@ import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@ -50,7 +51,7 @@ import java.util.List;
|
||||
|
||||
public class IrisEngineCompound implements EngineCompound {
|
||||
@Getter
|
||||
private World world;
|
||||
private IrisWorld world;
|
||||
|
||||
private final AtomicRollingSequence wallClock;
|
||||
|
||||
@ -77,10 +78,10 @@ public class IrisEngineCompound implements EngineCompound {
|
||||
@Setter
|
||||
private boolean studio;
|
||||
|
||||
public IrisEngineCompound(World world, IrisDimension rootDimension, IrisDataManager data, int maximumThreads) {
|
||||
public IrisEngineCompound(IrisWorld world, IrisDimension rootDimension, IrisDataManager data, int maximumThreads) {
|
||||
wallClock = new AtomicRollingSequence(32);
|
||||
this.rootDimension = rootDimension;
|
||||
Iris.info("Initializing Engine Composite for " + world.getName());
|
||||
Iris.info("Initializing Engine Composite for " + world.name());
|
||||
this.world = world;
|
||||
engineMetadata = EngineData.load(getEngineMetadataFile());
|
||||
engineMetadata.setDimension(rootDimension.getLoadKey());
|
||||
@ -97,7 +98,7 @@ public class IrisEngineCompound implements EngineCompound {
|
||||
} else {
|
||||
double totalWeight = 0D;
|
||||
engines = new Engine[rootDimension.getDimensionalComposite().size()];
|
||||
burster = engines.length > 1 ? new MultiBurst(engines.length) : null;
|
||||
burster = engines.length > 1 ? new MultiBurst("Iris Compound " + rootDimension.getName(), IrisSettings.get().getConcurrency().getEngineThreadPriority(), engines.length) : null;
|
||||
int threadDist = (Math.max(2, maximumThreads - engines.length)) / engines.length;
|
||||
|
||||
if ((threadDist * engines.length) + engines.length > maximumThreads) {
|
||||
@ -208,7 +209,7 @@ public class IrisEngineCompound implements EngineCompound {
|
||||
}
|
||||
|
||||
private File getEngineMetadataFile() {
|
||||
return new File(world.getWorldFolder(), "iris/engine-metadata.json");
|
||||
return new File(world.worldFolder(), "iris/engine-metadata.json");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -274,11 +275,6 @@ public class IrisEngineCompound implements EngineCompound {
|
||||
return defaultEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateWorld(World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hotload() {
|
||||
for (int i = 0; i < getSize(); i++) {
|
||||
|
@ -27,6 +27,7 @@ import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.hunk.view.BiomeGridHunkView;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import org.bukkit.block.Biome;
|
||||
@ -37,9 +38,10 @@ public class IrisBiomeActuator extends EngineAssignedActuator<Biome> {
|
||||
|
||||
public IrisBiomeActuator(Engine engine) {
|
||||
super(engine, "Biome");
|
||||
rng = new RNG(engine.getWorld().getSeed() + 243995);
|
||||
rng = new RNG(engine.getWorld().seed() + 243995);
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
private boolean injectBiome(Hunk<Biome> h, int x, int y, int z, Object bb) {
|
||||
try {
|
||||
if (h instanceof BiomeGridHunkView hh) {
|
||||
@ -59,6 +61,7 @@ public class IrisBiomeActuator extends EngineAssignedActuator<Biome> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
@Override
|
||||
public void onActuate(int x, int z, Hunk<Biome> h) {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
|
@ -24,6 +24,7 @@ import com.volmit.iris.engine.framework.EngineAssignedActuator;
|
||||
import com.volmit.iris.engine.framework.EngineDecorator;
|
||||
import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import lombok.Getter;
|
||||
@ -50,7 +51,7 @@ public class IrisDecorantActuator extends EngineAssignedActuator<BlockData> {
|
||||
public IrisDecorantActuator(Engine engine) {
|
||||
super(engine, "Decorant");
|
||||
shouldRay = shouldRayDecorate();
|
||||
this.rng = new RNG(engine.getTarget().getWorld().getSeed());
|
||||
this.rng = new RNG(engine.getTarget().getWorld().seed());
|
||||
surfaceDecorator = new IrisSurfaceDecorator(getEngine());
|
||||
ceilingDecorator = new IrisCeilingDecorator(getEngine());
|
||||
seaSurfaceDecorator = new IrisSeaSurfaceDecorator(getEngine());
|
||||
@ -58,6 +59,7 @@ public class IrisDecorantActuator extends EngineAssignedActuator<BlockData> {
|
||||
seaFloorDecorator = new IrisSeaFloorDecorator(getEngine());
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
@Override
|
||||
public void onActuate(int x, int z, Hunk<BlockData> output) {
|
||||
if (!getEngine().getDimension().isDecorate()) {
|
||||
|
@ -23,6 +23,7 @@ import com.volmit.iris.engine.framework.EngineAssignedActuator;
|
||||
import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import lombok.Getter;
|
||||
@ -45,11 +46,12 @@ public class IrisTerrainIslandActuator extends EngineAssignedActuator<BlockData>
|
||||
|
||||
public IrisTerrainIslandActuator(Engine engine) {
|
||||
super(engine, "TerrainIsland");
|
||||
rng = new RNG(engine.getWorld().getSeed());
|
||||
rng = new RNG(engine.getWorld().seed());
|
||||
carving = getDimension().isCarving() && getDimension().getCarveLayers().isNotEmpty();
|
||||
hasUnder = getDimension().getUndercarriage() != null && !getDimension().getUndercarriage().getGenerator().isFlat();
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
@Override
|
||||
public void onActuate(int x, int z, Hunk<BlockData> h) {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
|
@ -23,6 +23,7 @@ import com.volmit.iris.engine.framework.EngineAssignedActuator;
|
||||
import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import lombok.Getter;
|
||||
@ -42,11 +43,12 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData>
|
||||
|
||||
public IrisTerrainNormalActuator(Engine engine) {
|
||||
super(engine, "Terrain");
|
||||
rng = new RNG(engine.getWorld().getSeed());
|
||||
rng = new RNG(engine.getWorld().seed());
|
||||
carving = getDimension().isCarving() && getDimension().getCarveLayers().isNotEmpty();
|
||||
hasUnder = getDimension().getUndercarriage() != null && !getDimension().getUndercarriage().getGenerator().isFlat();
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
@Override
|
||||
public void onActuate(int x, int z, Hunk<BlockData> h) {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
|
@ -25,6 +25,7 @@ import com.volmit.iris.util.collection.KSet;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.type.Leaves;
|
||||
|
||||
public class B {
|
||||
private static final Material AIR_MATERIAL = Material.AIR;
|
||||
@ -103,7 +104,6 @@ public class B {
|
||||
public static BlockData getOrNull(String bdxf) {
|
||||
try {
|
||||
String bd = bdxf.trim();
|
||||
|
||||
BlockData bdx = parseBlockData(bd);
|
||||
|
||||
if (bdx == null) {
|
||||
@ -143,6 +143,12 @@ public class B {
|
||||
}
|
||||
|
||||
BlockData bx = Bukkit.createBlockData(ix);
|
||||
|
||||
if(bx instanceof Leaves)
|
||||
{
|
||||
((Leaves) bx).setPersistent(true);
|
||||
}
|
||||
|
||||
blockDataCache.put(ix, bx);
|
||||
return bx;
|
||||
} catch (Throwable e) {
|
||||
@ -151,6 +157,7 @@ public class B {
|
||||
}
|
||||
|
||||
String i = ix.toUpperCase().trim();
|
||||
i = i.equals("GRASS_PATH") ? "DIRT_PATH" : i;
|
||||
i = i.equals("WOOL") ? "WHITE_WOOL" : i;
|
||||
i = i.equals("CONCRETE") ? "WHITE_CONCRETE" : i;
|
||||
|
||||
|
@ -18,13 +18,12 @@
|
||||
|
||||
package com.volmit.iris.engine.data.chunk;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.BiomeBaseInjector;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.util.data.IrisBiomeStorage;
|
||||
import com.volmit.iris.util.fakenews.HeightedFakeWorld;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
|
||||
@ -38,8 +37,12 @@ public class LinkedTerrainChunk implements TerrainChunk {
|
||||
private ChunkData rawChunkData;
|
||||
private final BiomeGrid storage;
|
||||
|
||||
public LinkedTerrainChunk(int maxHeight) {
|
||||
this(null, maxHeight);
|
||||
public LinkedTerrainChunk(World world) {
|
||||
this(null, Bukkit.createChunkData(world));
|
||||
}
|
||||
|
||||
public LinkedTerrainChunk(World world, BiomeGrid storage) {
|
||||
this(storage, Bukkit.createChunkData(world));
|
||||
}
|
||||
|
||||
public LinkedTerrainChunk(BiomeGrid storage, ChunkData data) {
|
||||
@ -48,23 +51,6 @@ public class LinkedTerrainChunk implements TerrainChunk {
|
||||
biome3D = storage != null ? null : new IrisBiomeStorage();
|
||||
}
|
||||
|
||||
public LinkedTerrainChunk(BiomeGrid storage, int maxHeight) {
|
||||
this.storage = storage;
|
||||
rawChunkData = createChunkData(maxHeight);
|
||||
biome3D = storage != null ? null : new IrisBiomeStorage();
|
||||
}
|
||||
|
||||
private ChunkData createChunkData(int maxHeight) {
|
||||
try {
|
||||
return Bukkit.createChunkData(new HeightedFakeWorld(maxHeight));
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeBaseInjector getBiomeBaseInjector() {
|
||||
return (x, y, z, bb) -> INMS.get().forceBiomeInto(x, y, z, bb, storage);
|
||||
|
@ -28,25 +28,17 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface TerrainChunk extends BiomeGrid, ChunkData {
|
||||
static TerrainChunk create(World world) {
|
||||
return create(world.getMaxHeight());
|
||||
}
|
||||
|
||||
static TerrainChunk create(int maxHeight) {
|
||||
return new LinkedTerrainChunk(maxHeight);
|
||||
return new LinkedTerrainChunk(world);
|
||||
}
|
||||
|
||||
static TerrainChunk create(World world, BiomeGrid grid) {
|
||||
return create(world.getMaxHeight(), grid);
|
||||
return new LinkedTerrainChunk(world, grid);
|
||||
}
|
||||
|
||||
static TerrainChunk create(ChunkData raw, BiomeGrid grid) {
|
||||
return new LinkedTerrainChunk(grid, raw);
|
||||
}
|
||||
|
||||
static TerrainChunk create(int maxHeight, BiomeGrid grid) {
|
||||
return new LinkedTerrainChunk(grid, maxHeight);
|
||||
}
|
||||
|
||||
BiomeBaseInjector getBiomeBaseInjector();
|
||||
|
||||
void setRaw(ChunkData data);
|
||||
|
@ -19,6 +19,8 @@
|
||||
package com.volmit.iris.engine.data.mca;
|
||||
|
||||
import com.volmit.iris.engine.data.nbt.tag.CompoundTag;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
@ -88,6 +90,27 @@ public class MCAFile {
|
||||
}
|
||||
}
|
||||
|
||||
public KList<Position2> samplePositions(RandomAccessFile raf) throws IOException {
|
||||
KList<Position2> p2 = new KList<>();
|
||||
chunks = new AtomicReferenceArray<>(1024);
|
||||
int x = 0;
|
||||
int z = 0;
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
x++;
|
||||
z++;
|
||||
|
||||
raf.seek(i * 4);
|
||||
int offset = raf.read() << 16;
|
||||
offset |= (raf.read() & 0xFF) << 8;
|
||||
offset |= raf.read() & 0xFF;
|
||||
if (raf.readByte() == 0) {
|
||||
continue;
|
||||
}
|
||||
p2.add(new Position2(x & 31, (z / 32) & 31));
|
||||
}
|
||||
return p2;
|
||||
}
|
||||
|
||||
public AtomicReferenceArray<Chunk> getChunks() {
|
||||
return chunks;
|
||||
}
|
||||
@ -218,8 +241,7 @@ public class MCAFile {
|
||||
return getChunk(getChunkIndex(chunkX, chunkZ));
|
||||
}
|
||||
|
||||
public boolean hasChunk(int chunkX, int chunkZ)
|
||||
{
|
||||
public boolean hasChunk(int chunkX, int chunkZ) {
|
||||
return getChunk(chunkX, chunkZ) != null;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,9 @@
|
||||
|
||||
package com.volmit.iris.engine.data.mca;
|
||||
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
@ -83,6 +86,13 @@ public final class MCAUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static KList<Position2> sampleChunkPositions(File file) throws IOException {
|
||||
MCAFile mcaFile = newMCAFile(file);
|
||||
try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {
|
||||
return mcaFile.samplePositions(raf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link MCAUtil#write(MCAFile, File, boolean)} without changing the timestamps.
|
||||
*
|
||||
|
@ -24,21 +24,20 @@ import com.volmit.iris.engine.cache.Cache;
|
||||
import com.volmit.iris.engine.data.B;
|
||||
import com.volmit.iris.engine.data.nbt.tag.CompoundTag;
|
||||
import com.volmit.iris.engine.data.nbt.tag.StringTag;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.scheduling.IrisLock;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class NBTWorld {
|
||||
private static final BlockData AIR = B.get("AIR");
|
||||
@ -50,8 +49,7 @@ public class NBTWorld {
|
||||
private final File worldFolder;
|
||||
private final ExecutorService saveQueue;
|
||||
|
||||
public NBTWorld(File worldFolder)
|
||||
{
|
||||
public NBTWorld(File worldFolder) {
|
||||
this.worldFolder = worldFolder;
|
||||
this.loadedRegions = new KMap<>();
|
||||
this.lastUse = new KMap<>();
|
||||
@ -63,20 +61,17 @@ public class NBTWorld {
|
||||
});
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
public void close() {
|
||||
regionLock.lock();
|
||||
|
||||
for(Long i : loadedRegions.k())
|
||||
{
|
||||
for (Long i : loadedRegions.k()) {
|
||||
queueSaveUnload(Cache.keyX(i), Cache.keyZ(i));
|
||||
}
|
||||
|
||||
regionLock.unlock();
|
||||
saveQueue.shutdown();
|
||||
try {
|
||||
while(!saveQueue.awaitTermination(3, TimeUnit.SECONDS))
|
||||
{
|
||||
while (!saveQueue.awaitTermination(3, TimeUnit.SECONDS)) {
|
||||
Iris.info("Still Waiting to save MCA Files...");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
@ -84,37 +79,43 @@ public class NBTWorld {
|
||||
}
|
||||
}
|
||||
|
||||
public void queueSaveUnload(int x, int z)
|
||||
{
|
||||
saveQueue.submit(() -> {
|
||||
MCAFile f = getMCAOrNull(x, z);
|
||||
if(f != null)
|
||||
{
|
||||
unloadRegion(x, z);
|
||||
}
|
||||
public void flushNow() {
|
||||
regionLock.lock();
|
||||
|
||||
saveRegion(x, z, f);
|
||||
});
|
||||
for (Long i : loadedRegions.k()) {
|
||||
doSaveUnload(Cache.keyX(i), Cache.keyZ(i));
|
||||
}
|
||||
|
||||
regionLock.unlock();
|
||||
}
|
||||
|
||||
public void save()
|
||||
{
|
||||
public void queueSaveUnload(int x, int z) {
|
||||
saveQueue.submit(() -> doSaveUnload(x, z));
|
||||
}
|
||||
|
||||
public void doSaveUnload(int x, int z) {
|
||||
MCAFile f = getMCAOrNull(x, z);
|
||||
if (f != null) {
|
||||
unloadRegion(x, z);
|
||||
}
|
||||
|
||||
saveRegion(x, z, f);
|
||||
}
|
||||
|
||||
public void save() {
|
||||
regionLock.lock();
|
||||
|
||||
boolean saving = true;
|
||||
|
||||
for(Long i : loadedRegions.k())
|
||||
{
|
||||
for (Long i : loadedRegions.k()) {
|
||||
int x = Cache.keyX(i);
|
||||
int z = Cache.keyZ(i);
|
||||
|
||||
if(!lastUse.containsKey(i))
|
||||
{
|
||||
if (!lastUse.containsKey(i)) {
|
||||
lastUse.put(i, M.ms());
|
||||
}
|
||||
|
||||
if(shouldUnload(x, z))
|
||||
{
|
||||
if (shouldUnload(x, z)) {
|
||||
queueSaveUnload(x, z);
|
||||
}
|
||||
}
|
||||
@ -124,13 +125,11 @@ public class NBTWorld {
|
||||
regionLock.unlock();
|
||||
}
|
||||
|
||||
public void queueSave()
|
||||
{
|
||||
public void queueSave() {
|
||||
|
||||
}
|
||||
|
||||
public synchronized void unloadRegion(int x, int z)
|
||||
{
|
||||
public synchronized void unloadRegion(int x, int z) {
|
||||
long key = Cache.key(x, z);
|
||||
regionLock.lock();
|
||||
loadedRegions.remove(key);
|
||||
@ -139,8 +138,7 @@ public class NBTWorld {
|
||||
Iris.debug("Unloaded Region " + C.GOLD + x + " " + z);
|
||||
}
|
||||
|
||||
public void saveRegion(int x, int z)
|
||||
{
|
||||
public void saveRegion(int x, int z) {
|
||||
long k = Cache.key(x, z);
|
||||
MCAFile mca = getMCAOrNull(x, z);
|
||||
try {
|
||||
@ -152,8 +150,7 @@ public class NBTWorld {
|
||||
}
|
||||
}
|
||||
|
||||
public void saveRegion(int x, int z, MCAFile mca)
|
||||
{
|
||||
public void saveRegion(int x, int z, MCAFile mca) {
|
||||
try {
|
||||
MCAUtil.write(mca, getRegionFile(x, z), true);
|
||||
Iris.debug("Saved Region " + C.GOLD + x + " " + z);
|
||||
@ -163,8 +160,7 @@ public class NBTWorld {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean shouldUnload(int x, int z)
|
||||
{
|
||||
public boolean shouldUnload(int x, int z) {
|
||||
return getIdleDuration(x, z) > 60000;
|
||||
}
|
||||
|
||||
@ -281,8 +277,7 @@ public class NBTWorld {
|
||||
return c;
|
||||
}
|
||||
|
||||
public long getIdleDuration(int x, int z)
|
||||
{
|
||||
public long getIdleDuration(int x, int z) {
|
||||
Long l = lastUse.get(Cache.key(x, z));
|
||||
|
||||
return l == null ? 0 : (M.ms() - l);
|
||||
@ -296,17 +291,8 @@ public class NBTWorld {
|
||||
MCAFile mcaf = loadedRegions.get(key);
|
||||
regionLock.unlock();
|
||||
|
||||
if(mcaf == null)
|
||||
{
|
||||
File f = getRegionFile(x, z);
|
||||
try {
|
||||
mcaf = f.exists() ? MCAUtil.read(f) : new MCAFile(x, z);
|
||||
} catch (IOException e) {
|
||||
Iris.error("Failed to properly read MCA File " + f.getPath() + " Using a blank one.");
|
||||
e.printStackTrace();
|
||||
mcaf = new MCAFile(x, z);
|
||||
}
|
||||
|
||||
if (mcaf == null) {
|
||||
mcaf = new MCAFile(x, z);
|
||||
regionLock.lock();
|
||||
loadedRegions.put(key, mcaf);
|
||||
regionLock.unlock();
|
||||
@ -320,8 +306,7 @@ public class NBTWorld {
|
||||
MCAFile ff = null;
|
||||
regionLock.lock();
|
||||
|
||||
if(loadedRegions.containsKey(key))
|
||||
{
|
||||
if (loadedRegions.containsKey(key)) {
|
||||
lastUse.put(key, M.ms());
|
||||
ff = loadedRegions.get(key);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.object.DecorationPart;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisDecorator;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
public class IrisCeilingDecorator extends IrisEngineDecorator {
|
||||
@ -31,6 +32,7 @@ public class IrisCeilingDecorator extends IrisEngineDecorator {
|
||||
super(engine, "Ceiling", DecorationPart.CEILING);
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
@Override
|
||||
public void decorate(int x, int z, int realX, int realX1, int realX_1, int realZ, int realZ1, int realZ_1, Hunk<BlockData> data, IrisBiome biome, int height, int max) {
|
||||
IrisDecorator decorator = getDecorator(biome, realX, realZ);
|
||||
|
@ -24,6 +24,7 @@ import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.object.DecorationPart;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisDecorator;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
public class IrisSeaFloorDecorator extends IrisEngineDecorator {
|
||||
@ -31,6 +32,7 @@ public class IrisSeaFloorDecorator extends IrisEngineDecorator {
|
||||
super(engine, "Sea Floor", DecorationPart.SEA_FLOOR);
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
@Override
|
||||
public void decorate(int x, int z, int realX, int realX1, int realX_1, int realZ, int realZ1, int realZ_1, Hunk<BlockData> data, IrisBiome biome, int height, int max) {
|
||||
if (height <= getDimension().getFluidHeight()) {
|
||||
|
@ -24,6 +24,7 @@ import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.object.DecorationPart;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisDecorator;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
public class IrisSeaSurfaceDecorator extends IrisEngineDecorator {
|
||||
@ -31,6 +32,7 @@ public class IrisSeaSurfaceDecorator extends IrisEngineDecorator {
|
||||
super(engine, "Sea Surface", DecorationPart.SEA_SURFACE);
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
@Override
|
||||
public void decorate(int x, int z, int realX, int realX1, int realX_1, int realZ, int realZ1, int realZ_1, Hunk<BlockData> data, IrisBiome biome, int height, int max) {
|
||||
IrisDecorator decorator = getDecorator(biome, realX, realZ);
|
||||
|
@ -24,6 +24,7 @@ import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.object.DecorationPart;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisDecorator;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
public class IrisShoreLineDecorator extends IrisEngineDecorator {
|
||||
@ -31,6 +32,7 @@ public class IrisShoreLineDecorator extends IrisEngineDecorator {
|
||||
super(engine, "Shore Line", DecorationPart.SHORE_LINE);
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
@Override
|
||||
public void decorate(int x, int z, int realX, int realX1, int realX_1, int realZ, int realZ1, int realZ_1, Hunk<BlockData> data, IrisBiome biome, int height, int max) {
|
||||
|
||||
|
@ -26,6 +26,7 @@ import com.volmit.iris.engine.object.DecorationPart;
|
||||
import com.volmit.iris.engine.object.InferredType;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisDecorator;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import org.bukkit.block.data.Bisected;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
@ -34,6 +35,7 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
|
||||
super(engine, "Surface", DecorationPart.NONE);
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
@Override
|
||||
public void decorate(int x, int z, int realX, int realX1, int realX_1, int realZ, int realZ1, int realZ_1, Hunk<BlockData> data, IrisBiome biome, int height, int max) {
|
||||
if (biome.getInferredType().equals(InferredType.SHORE) && height < getDimension().getFluidHeight()) {
|
||||
|
@ -20,13 +20,14 @@ package com.volmit.iris.engine.framework;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.core.gui.RenderType;
|
||||
import com.volmit.iris.core.gui.Renderer;
|
||||
import com.volmit.iris.core.gui.components.RenderType;
|
||||
import com.volmit.iris.core.gui.components.Renderer;
|
||||
import com.volmit.iris.engine.cache.Cache;
|
||||
import com.volmit.iris.engine.data.B;
|
||||
import com.volmit.iris.engine.data.DataProvider;
|
||||
import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.engine.object.common.IrisWorld;
|
||||
import com.volmit.iris.engine.parallax.ParallaxAccess;
|
||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
@ -37,7 +38,6 @@ import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@ -105,7 +105,7 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
|
||||
return getTarget().getData();
|
||||
}
|
||||
|
||||
default World getWorld() {
|
||||
default IrisWorld getWorld() {
|
||||
return getTarget().getWorld();
|
||||
}
|
||||
|
||||
@ -357,8 +357,12 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
|
||||
return getCompound().isStudio();
|
||||
}
|
||||
|
||||
default MultiBurst burst() {
|
||||
return getTarget().getBurster();
|
||||
}
|
||||
|
||||
default void clean() {
|
||||
MultiBurst.burst.lazy(() -> getParallax().cleanup());
|
||||
burst().lazy(() -> getParallax().cleanup());
|
||||
}
|
||||
|
||||
default IrisBiome getBiome(Location l) {
|
||||
@ -374,4 +378,6 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
|
||||
}
|
||||
|
||||
IrisBiome getFocus();
|
||||
|
||||
void hotloading();
|
||||
}
|
||||
|
@ -19,7 +19,9 @@
|
||||
package com.volmit.iris.engine.framework;
|
||||
|
||||
import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
|
||||
public interface EngineActuator<O> extends EngineComponent {
|
||||
@BlockCoordinates
|
||||
void actuate(int x, int z, Hunk<O> output);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
package com.volmit.iris.engine.framework;
|
||||
|
||||
import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
|
||||
public abstract class EngineAssignedActuator<T> extends EngineAssignedComponent implements EngineActuator<T> {
|
||||
public EngineAssignedActuator(Engine engine, String name) {
|
||||
@ -27,6 +28,7 @@ public abstract class EngineAssignedActuator<T> extends EngineAssignedComponent
|
||||
|
||||
public abstract void onActuate(int x, int z, Hunk<T> output);
|
||||
|
||||
@BlockCoordinates
|
||||
@Override
|
||||
public void actuate(int x, int z, Hunk<T> output) {
|
||||
onActuate(x, z, output);
|
||||
|
@ -69,7 +69,7 @@ public interface EngineComponent {
|
||||
}
|
||||
|
||||
default long getSeed() {
|
||||
return getTarget().getWorld().getSeed();
|
||||
return getTarget().getWorld().seed();
|
||||
}
|
||||
|
||||
default EngineFramework getFramework() {
|
||||
|
@ -23,21 +23,22 @@ import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.nms.BiomeBaseInjector;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.engine.IrisEngineCompound;
|
||||
import com.volmit.iris.engine.IrisWorlds;
|
||||
import com.volmit.iris.engine.cache.Cache;
|
||||
import com.volmit.iris.engine.data.B;
|
||||
import com.volmit.iris.engine.data.chunk.TerrainChunk;
|
||||
import com.volmit.iris.engine.data.mca.NBTWorld;
|
||||
import com.volmit.iris.engine.headless.HeadlessGenerator;
|
||||
import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisPosition;
|
||||
import com.volmit.iris.engine.object.common.IrisWorld;
|
||||
import com.volmit.iris.engine.parallel.BurstExecutor;
|
||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.fakenews.FakeWorld;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.io.ReactiveFolder;
|
||||
@ -48,7 +49,6 @@ import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import io.netty.util.internal.ConcurrentSet;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
@ -77,11 +77,11 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
||||
private final boolean production;
|
||||
private final KList<BlockPopulator> populators;
|
||||
private long mst = 0;
|
||||
private HeadlessGenerator headlessGenerator;
|
||||
private NBTWorld nbtWorld;
|
||||
private int generated = 0;
|
||||
private int lgenerated = 0;
|
||||
private final KMap<Long, PregeneratedData> chunkCache;
|
||||
private final ChronoLatch hotloadcd;
|
||||
private final AtomicBoolean fake;
|
||||
@Getter
|
||||
private double generatedPerSecond = 0;
|
||||
private final int art;
|
||||
@ -93,8 +93,6 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
||||
|
||||
public EngineCompositeGenerator(String query, boolean production) {
|
||||
super();
|
||||
chunkCache = new KMap<>();
|
||||
fake = new AtomicBoolean(true);
|
||||
hotloadcd = new ChronoLatch(3500);
|
||||
mst = M.ms();
|
||||
this.production = production;
|
||||
@ -113,6 +111,7 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hotload() {
|
||||
if (isStudio()) {
|
||||
Iris.proj.updateWorkspace();
|
||||
@ -128,12 +127,14 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
getComposite().close();
|
||||
initialized.lazySet(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (isClosed()) {
|
||||
if (getComposite() == null || isClosed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -158,14 +159,14 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized IrisDimension getDimension(World world) {
|
||||
private synchronized IrisDimension getDimension(IrisWorld world) {
|
||||
String query = dimensionQuery;
|
||||
query = Iris.linkMultiverseCore.getWorldNameType(world.getName(), query);
|
||||
query = Iris.linkMultiverseCore.getWorldNameType(world.name(), query);
|
||||
|
||||
IrisDimension dim = null;
|
||||
|
||||
if (query == null) {
|
||||
File iris = new File(world.getWorldFolder(), "iris");
|
||||
File iris = new File(world.worldFolder(), "iris");
|
||||
|
||||
if (iris.exists() && iris.isDirectory()) {
|
||||
for (File i : iris.listFiles()) {
|
||||
@ -191,7 +192,7 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
||||
}
|
||||
|
||||
if (query == null) {
|
||||
Iris.error("Cannot find iris dimension data for world: " + world.getName() + "! Assuming " + IrisSettings.get().getGenerator().getDefaultWorldType() + "!");
|
||||
Iris.error("Cannot find iris dimension data for world: " + world.name() + "! Assuming " + IrisSettings.get().getGenerator().getDefaultWorldType() + "!");
|
||||
query = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||
}
|
||||
|
||||
@ -213,8 +214,8 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
||||
dim = new IrisDataManager(getDataFolder(world)).getDimensionLoader().load(od.getLoadKey());
|
||||
|
||||
if (dim == null) {
|
||||
Iris.info("Installing Iris pack " + od.getName() + " into world " + world.getName() + "...");
|
||||
Iris.proj.installIntoWorld(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag()), od.getLoadKey(), world.getWorldFolder());
|
||||
Iris.info("Installing Iris pack " + od.getName() + " into world " + world.name() + "...");
|
||||
Iris.proj.installIntoWorld(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag()), od.getLoadKey(), world.worldFolder());
|
||||
dim = new IrisDataManager(getDataFolder(world)).getDimensionLoader().load(od.getLoadKey());
|
||||
|
||||
if (dim == null) {
|
||||
@ -294,20 +295,7 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
||||
return dim;
|
||||
}
|
||||
|
||||
public synchronized void initialize(World world) {
|
||||
if (!(world instanceof FakeWorld) && fake.get() && this.compound.get() != null) {
|
||||
fake.set(false);
|
||||
this.compound.get().updateWorld(world);
|
||||
getTarget().updateWorld(world);
|
||||
placeStrongholds(world);
|
||||
|
||||
for (int i = 0; i < getComposite().getSize(); i++) {
|
||||
getComposite().getEngine(i).getTarget().updateWorld(world);
|
||||
}
|
||||
|
||||
Iris.info("Attached Real World to Engine Target");
|
||||
}
|
||||
|
||||
public synchronized void initialize(IrisWorld world) {
|
||||
if (initialized.get()) {
|
||||
return;
|
||||
}
|
||||
@ -316,12 +304,16 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
||||
initialized.set(true);
|
||||
IrisDimension dim = getDimension(world);
|
||||
IrisDataManager data = production ? new IrisDataManager(getDataFolder(world)) : dim.getLoader().copy();
|
||||
compound.set(new IrisEngineCompound(world, dim, data, Iris.getThreadCount()));
|
||||
compound.set(new IrisEngineCompound(world, dim, data, IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getEngineThreadCount())));
|
||||
compound.get().setStudio(!production);
|
||||
populators.clear();
|
||||
populators.addAll(compound.get().getPopulators());
|
||||
hotloader = new ReactiveFolder(data.getDataFolder(), (a, c, d) -> hotload());
|
||||
dim.installDataPack(() -> data, Iris.instance.getDatapacksFolder());
|
||||
|
||||
if(isStudio())
|
||||
{
|
||||
dim.installDataPack(() -> data, Iris.instance.getDatapacksFolder());
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
@ -445,8 +437,8 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
||||
);
|
||||
}
|
||||
|
||||
private File getDataFolder(World world) {
|
||||
return new File(world.getWorldFolder(), "iris/pack");
|
||||
private File getDataFolder(IrisWorld world) {
|
||||
return new File(world.worldFolder(), "iris/pack");
|
||||
}
|
||||
|
||||
private File getDataFolder(String world) {
|
||||
@ -458,7 +450,13 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
||||
public ChunkData generateChunkData(@NotNull World world, @NotNull Random ignored, int x, int z, @NotNull BiomeGrid biome) {
|
||||
PrecisionStopwatch ps = PrecisionStopwatch.start();
|
||||
TerrainChunk tc = TerrainChunk.create(world, biome);
|
||||
generateChunkRawData(world, x, z, tc).run();
|
||||
IrisWorld ww = (getComposite() == null || getComposite().getWorld() == null) ? IrisWorld.fromWorld(world) : getComposite().getWorld();
|
||||
generateChunkRawData(ww, x, z, tc).run();
|
||||
|
||||
if (!getComposite().getWorld().hasRealWorld()) {
|
||||
getComposite().getWorld().bind(world);
|
||||
}
|
||||
|
||||
generated++;
|
||||
ps.end();
|
||||
|
||||
@ -469,23 +467,48 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
||||
return tc.getRaw();
|
||||
}
|
||||
|
||||
public void directWriteMCA(World w, int x, int z, NBTWorld writer, MultiBurst burst) {
|
||||
BurstExecutor e = burst.burst(1024);
|
||||
int mcaox = x << 5;
|
||||
int mcaoz = z << 5;
|
||||
public void assignHeadlessGenerator(HeadlessGenerator headlessGenerator) {
|
||||
this.headlessGenerator = headlessGenerator;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
int ii = i;
|
||||
for (int j = 0; j < 32; j++) {
|
||||
int jj = j;
|
||||
e.queue(() -> directWriteChunk(w, ii + mcaox, jj + mcaoz, writer));
|
||||
@Override
|
||||
public HeadlessGenerator getHeadlessGenerator() {
|
||||
return headlessGenerator;
|
||||
}
|
||||
|
||||
public void assignHeadlessNBTWriter(NBTWorld writer) {
|
||||
this.nbtWorld = writer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTWorld getHeadlessNBTWriter() {
|
||||
return nbtWorld;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst) {
|
||||
directWriteMCA(w, x, z, writer, burst, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst, PregenListener l) {
|
||||
BurstExecutor e = burst.burst(1024);
|
||||
|
||||
PregenTask.iterateRegion(x, z, (ii, jj) -> e.queue(() -> {
|
||||
if (l != null) {
|
||||
l.onChunkGenerating(ii, jj);
|
||||
}
|
||||
}
|
||||
directWriteChunk(w, ii, jj, writer);
|
||||
if (l != null) {
|
||||
l.onChunkGenerated(ii, jj);
|
||||
}
|
||||
}));
|
||||
|
||||
e.complete();
|
||||
}
|
||||
|
||||
public void directWriteChunk(World w, int x, int z, NBTWorld writer) {
|
||||
@Override
|
||||
public void directWriteChunk(IrisWorld w, int x, int z, NBTWorld writer) {
|
||||
int ox = x << 4;
|
||||
int oz = z << 4;
|
||||
com.volmit.iris.engine.data.mca.Chunk cc = writer.getChunk(x, z);
|
||||
@ -526,12 +549,12 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return w.getMinHeight();
|
||||
return w.minHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return w.getMaxHeight();
|
||||
return w.maxHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -614,50 +637,8 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
||||
}).run();
|
||||
}
|
||||
|
||||
public Chunk generatePaper(World world, int x, int z) {
|
||||
precache(world, x, z);
|
||||
Chunk c = PaperLib.getChunkAtAsync(world, x, z, true).join();
|
||||
chunkCache.remove(Cache.key(x, z));
|
||||
return c;
|
||||
}
|
||||
|
||||
public void precache(World world, int x, int z) {
|
||||
synchronized (this) {
|
||||
initialize(world);
|
||||
}
|
||||
|
||||
synchronized (chunkCache) {
|
||||
if (chunkCache.containsKey(Cache.key(x, z))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PregeneratedData data = new PregeneratedData(getComposite().getHeight() - 1);
|
||||
compound.get().generate(x * 16, z * 16, data.getBlocks(), data.getPost(), data.getBiomes());
|
||||
synchronized (chunkCache) {
|
||||
chunkCache.put(Cache.key(x, z), data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrecacheSize() {
|
||||
return chunkCache.size();
|
||||
}
|
||||
|
||||
public int getCachedChunks() {
|
||||
return chunkCache.size();
|
||||
}
|
||||
|
||||
public Runnable generateChunkRawData(World world, int x, int z, TerrainChunk tc) {
|
||||
public Runnable generateChunkRawData(IrisWorld world, int x, int z, TerrainChunk tc) {
|
||||
initialize(world);
|
||||
|
||||
synchronized (chunkCache) {
|
||||
long g = Cache.key(x, z);
|
||||
if (chunkCache.containsKey(g)) {
|
||||
return chunkCache.remove(g).inject(tc);
|
||||
}
|
||||
}
|
||||
|
||||
Hunk<BlockData> blocks = Hunk.view((ChunkData) tc);
|
||||
Hunk<Biome> biomes = Hunk.view((BiomeGrid) tc);
|
||||
Hunk<BlockData> post = Hunk.newAtomicHunk(biomes.getWidth(), biomes.getHeight(), biomes.getDepth());
|
||||
@ -783,146 +764,15 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
|
||||
// TODO: DO IT
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRegeneratedLists(int x, int z) {
|
||||
for (int i = 0; i < getComposite().getSize(); i++) {
|
||||
getComposite().getEngine(i).getParallax().delete(x, z);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void regenerate(int x, int z) {
|
||||
|
||||
clearRegeneratedLists(x, z);
|
||||
int xx = x * 16;
|
||||
int zz = z * 16;
|
||||
BiomeBaseInjector inj = (a, b, c, d) -> {
|
||||
};
|
||||
//noinspection deprecation
|
||||
generateChunkRawData(getComposite().getWorld(), x, z, new TerrainChunk() {
|
||||
@Override
|
||||
public BiomeBaseInjector getBiomeBaseInjector() {
|
||||
return inj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRaw(ChunkData data) {
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Biome getBiome(int x, int z) {
|
||||
return Biome.THE_VOID;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Biome getBiome(int x, int y, int z) {
|
||||
return Biome.THE_VOID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int z, Biome bio) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int y, int z, Biome bio) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return getComposite().getWorld().getMinHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return getComposite().getWorld().getMaxHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, BlockData blockData) {
|
||||
if (!getBlockData(x, y, z).matches(blockData)) {
|
||||
Iris.edit.set(compound.get().getWorld(), x + xx, y, z + zz, blockData);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public BlockData getBlockData(int x, int y, int z) {
|
||||
return Iris.edit.get(compound.get().getWorld(), x + xx, y, z + zz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkData getRaw() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(BiomeGrid biome) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int i, int i1, int i2, @NotNull Material material) {
|
||||
setBlock(i, i1, i2, material.createBlockData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int i, int i1, int i2, @NotNull MaterialData materialData) {
|
||||
setBlock(i, i1, i2, materialData.getItemType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRegion(int i, int i1, int i2, int i3, int i4, int i5, @NotNull Material material) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRegion(int i, int i1, int i2, int i3, int i4, int i5, @NotNull MaterialData materialData) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRegion(int i, int i1, int i2, int i3, int i4, int i5, @NotNull BlockData blockData) {
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Material getType(int i, int i1, int i2) {
|
||||
return getBlockData(i, i1, i2).getMaterial();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public MaterialData getTypeAndData(int i, int i1, int i2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getData(int i, int i1, int i2) {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
Iris.edit.flushNow();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
J.car(art);
|
||||
if (getComposite() != null) {
|
||||
getComposite().close();
|
||||
|
||||
|
||||
if (isStudio()) {
|
||||
IrisWorlds.evacuate(getComposite().getWorld());
|
||||
Bukkit.unloadWorld(getComposite().getWorld(), !isStudio());
|
||||
if (isStudio() && getComposite().getWorld().hasRealWorld()) {
|
||||
getComposite().getWorld().evacuate();
|
||||
Bukkit.unloadWorld(getComposite().getWorld().realWorld(), !isStudio());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,10 +26,10 @@ import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisPosition;
|
||||
import com.volmit.iris.engine.object.common.IrisWorld;
|
||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@ -43,7 +43,7 @@ public interface EngineCompound extends Listener, Hotloadable, DataProvider {
|
||||
|
||||
void generate(int x, int z, Hunk<BlockData> blocks, Hunk<BlockData> postblocks, Hunk<Biome> biomes);
|
||||
|
||||
World getWorld();
|
||||
IrisWorld getWorld();
|
||||
|
||||
List<IrisPosition> getStrongholdPositions();
|
||||
|
||||
@ -149,8 +149,6 @@ public interface EngineCompound extends Listener, Hotloadable, DataProvider {
|
||||
return v.v();
|
||||
}
|
||||
|
||||
void updateWorld(World world);
|
||||
|
||||
default int getLowestBedrock() {
|
||||
int f = Integer.MAX_VALUE;
|
||||
|
||||
|
@ -21,11 +21,15 @@ package com.volmit.iris.engine.framework;
|
||||
import com.volmit.iris.engine.data.B;
|
||||
import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
public interface EngineDecorator extends EngineComponent {
|
||||
|
||||
@BlockCoordinates
|
||||
void decorate(int x, int z, int realX, int realX1, int realX_1, int realZ, int realZ1, int realZ_1, Hunk<BlockData> data, IrisBiome biome, int height, int max);
|
||||
|
||||
@BlockCoordinates
|
||||
default void decorate(int x, int z, int realX, int realZ, Hunk<BlockData> data, IrisBiome biome, int height, int max) {
|
||||
decorate(x, z, realX, realX, realX, realZ, realZ, realZ, data, biome, height, max);
|
||||
}
|
||||
|
@ -19,7 +19,9 @@
|
||||
package com.volmit.iris.engine.framework;
|
||||
|
||||
import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
|
||||
public interface EngineModifier<T> extends EngineComponent {
|
||||
@BlockCoordinates
|
||||
void modify(int x, int z, Hunk<T> t);
|
||||
}
|
||||
|
@ -34,10 +34,10 @@ import com.volmit.iris.engine.object.tile.TileData;
|
||||
import com.volmit.iris.engine.parallax.ParallaxAccess;
|
||||
import com.volmit.iris.engine.parallax.ParallaxChunkMeta;
|
||||
import com.volmit.iris.engine.parallel.BurstExecutor;
|
||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.function.Consumer4;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
@ -165,14 +165,19 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer {
|
||||
});
|
||||
}
|
||||
|
||||
@ChunkCoordinates
|
||||
default void insertParallax(int x, int z, Hunk<BlockData> data) {
|
||||
if (!getEngine().getDimension().isPlaceObjects()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
ParallaxChunkMeta meta = getParallaxAccess().getMetaR(x >> 4, z >> 4);
|
||||
ParallaxChunkMeta meta = getParallaxAccess().getMetaR(x, z);
|
||||
|
||||
if (!meta.isParallaxGenerated()) {
|
||||
generateParallaxLayer(x, z, true);
|
||||
meta = getParallaxAccess().getMetaR(x >> 4, z >> 4);
|
||||
meta = getParallaxAccess().getMetaR(x, z);
|
||||
}
|
||||
|
||||
if (!meta.isObjects()) {
|
||||
@ -180,7 +185,7 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer {
|
||||
return;
|
||||
}
|
||||
|
||||
getParallaxAccess().getBlocksR(x >> 4, z >> 4).iterateSync((a, b, c, d) -> {
|
||||
getParallaxAccess().getBlocksR(x, z).iterateSync((a, b, c, d) -> {
|
||||
if (d != null) {
|
||||
data.set(a, b, c, d);
|
||||
}
|
||||
@ -199,8 +204,7 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer {
|
||||
IrisLock getFeatureLock();
|
||||
|
||||
default void forEachFeature(double x, double z, Consumer<IrisFeaturePositional> f) {
|
||||
if(!getEngine().getDimension().hasFeatures(getEngine()))
|
||||
{
|
||||
if (!getEngine().getDimension().hasFeatures(getEngine())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -229,14 +233,18 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer {
|
||||
for (j = -s; j <= s; j++) {
|
||||
ParallaxChunkMeta m = getParallaxAccess().getMetaR(i + cx, j + cz);
|
||||
|
||||
try {
|
||||
for (IrisFeaturePositional k : m.getFeatures()) {
|
||||
if (k.shouldFilter(x, z)) {
|
||||
pos.add(k);
|
||||
synchronized (m) {
|
||||
try {
|
||||
for (IrisFeaturePositional k : m.getFeatures()) {
|
||||
if (k.shouldFilter(x, z)) {
|
||||
pos.add(k);
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.error("FILTER ERROR" + " AT " + (cx + i) + " " + (j + cz));
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -261,7 +269,7 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer {
|
||||
int i, j;
|
||||
KList<Runnable> after = new KList<>();
|
||||
int bs = (int) Math.pow((s * 2) + 1, 2);
|
||||
BurstExecutor burst = MultiBurst.burst.burst(bs);
|
||||
BurstExecutor burst = getEngine().getTarget().getBurster().burst(bs);
|
||||
for (i = -s; i <= s; i++) {
|
||||
for (j = -s; j <= s; j++) {
|
||||
int xx = i + x;
|
||||
@ -271,7 +279,7 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer {
|
||||
if (!getParallaxAccess().isFeatureGenerated(xx, zz)) {
|
||||
burst.queue(() -> {
|
||||
getParallaxAccess().setFeatureGenerated(xx, zz);
|
||||
RNG rng = new RNG(Cache.key(xx, zz)).nextParallelRNG(getEngine().getTarget().getWorld().getSeed());
|
||||
RNG rng = new RNG(Cache.key(xx, zz)).nextParallelRNG(getEngine().getTarget().getWorld().seed());
|
||||
IrisRegion region = getComplex().getRegionStream().get(xxx, zzz);
|
||||
IrisBiome biome = getComplex().getTrueBiomeStream().get(xxx, zzz);
|
||||
generateParallaxFeatures(rng, xx, zz, region, biome);
|
||||
@ -283,7 +291,7 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer {
|
||||
burst.complete();
|
||||
|
||||
if (getEngine().getDimension().isPlaceObjects()) {
|
||||
burst = MultiBurst.burst.burst(bs);
|
||||
burst = getEngine().getTarget().getBurster().burst(bs);
|
||||
|
||||
for (i = -s; i <= s; i++) {
|
||||
int ii = i;
|
||||
@ -299,7 +307,7 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer {
|
||||
}
|
||||
|
||||
burst.complete();
|
||||
burst = MultiBurst.burst.burst(bs);
|
||||
burst = getEngine().getTarget().getBurster().burst(bs);
|
||||
|
||||
for (i = -s; i <= s; i++) {
|
||||
int ii = i;
|
||||
@ -312,7 +320,7 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer {
|
||||
burst.complete();
|
||||
}
|
||||
|
||||
MultiBurst.burst.burst(after);
|
||||
getEngine().getTarget().getBurster().burst(after);
|
||||
getParallaxAccess().setChunkGenerated(x, z);
|
||||
p.end();
|
||||
getEngine().getMetrics().getParallax().put(p.getMilliseconds());
|
||||
@ -325,14 +333,14 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer {
|
||||
|
||||
default KList<Runnable> generateParallaxVacuumLayer(int x, int z) {
|
||||
KList<Runnable> after = new KList<>();
|
||||
if (getParallaxAccess().isParallaxGenerated(x, z)) {
|
||||
if (getParallaxAccess().isParallaxGenerated(x >> 4, z >> 4)) {
|
||||
return after;
|
||||
}
|
||||
|
||||
if (getEngine().getDimension().isPlaceObjects()) {
|
||||
int xx = x << 4;
|
||||
int zz = z << 4;
|
||||
RNG rng = new RNG(Cache.key(x, z)).nextParallelRNG(getEngine().getTarget().getWorld().getSeed());
|
||||
RNG rng = new RNG(Cache.key(x, z)).nextParallelRNG(getEngine().getTarget().getWorld().seed());
|
||||
IrisRegion region = getComplex().getRegionStream().get(xx + 8, zz + 8);
|
||||
IrisBiome biome = getComplex().getTrueBiomeStream().get(xx + 8, zz + 8);
|
||||
after.addAll(generateParallaxJigsaw(rng, x, z, biome, region));
|
||||
@ -351,7 +359,7 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer {
|
||||
int xx = x << 4;
|
||||
int zz = z << 4;
|
||||
getParallaxAccess().setParallaxGenerated(x, z);
|
||||
RNG rng = new RNG(Cache.key(x, z)).nextParallelRNG(getEngine().getTarget().getWorld().getSeed());
|
||||
RNG rng = new RNG(Cache.key(x, z)).nextParallelRNG(getEngine().getTarget().getWorld().seed());
|
||||
IrisBiome biome = getComplex().getTrueBiomeStream().get(xx + 8, zz + 8);
|
||||
IrisRegion region = getComplex().getRegionStream().get(xx + 8, zz + 8);
|
||||
generateParallaxSurface(rng, x, z, biome, region, false);
|
||||
@ -666,7 +674,7 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer {
|
||||
}
|
||||
|
||||
Iris.verbose("Checking sizes for " + Form.f(objects.size()) + " referenced objects.");
|
||||
BurstExecutor e = MultiBurst.burst.burst(objects.size());
|
||||
BurstExecutor e = getEngine().getTarget().getBurster().burst(objects.size());
|
||||
KMap<String, BlockVector> sizeCache = new KMap<>();
|
||||
for (String i : objects) {
|
||||
e.queue(() -> {
|
||||
|
@ -19,11 +19,12 @@
|
||||
package com.volmit.iris.engine.framework;
|
||||
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.common.IrisWorld;
|
||||
import com.volmit.iris.engine.parallax.ParallaxWorld;
|
||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import lombok.Data;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@ -31,27 +32,27 @@ import java.io.File;
|
||||
public class EngineTarget {
|
||||
private final MultiBurst burster;
|
||||
private final IrisDimension dimension;
|
||||
private World world;
|
||||
private IrisWorld world;
|
||||
private final int height;
|
||||
private final IrisDataManager data;
|
||||
private final ParallaxWorld parallaxWorld;
|
||||
private final boolean inverted;
|
||||
|
||||
public EngineTarget(World world, IrisDimension dimension, IrisDataManager data, int height, boolean inverted, int threads) {
|
||||
public EngineTarget(IrisWorld world, IrisDimension dimension, IrisDataManager data, int height, boolean inverted, int threads) {
|
||||
this.world = world;
|
||||
this.height = height;
|
||||
this.dimension = dimension;
|
||||
this.data = data;
|
||||
this.parallaxWorld = new ParallaxWorld(256, new File(world.getWorldFolder(), "iris/" + dimension.getLoadKey() + "/parallax"));
|
||||
this.inverted = inverted;
|
||||
this.burster = new MultiBurst(threads);
|
||||
this.burster = new MultiBurst("Iris Engine " + dimension.getName(), IrisSettings.get().getConcurrency().getEngineThreadPriority(), threads);
|
||||
this.parallaxWorld = new ParallaxWorld(burster, 256, new File(world.worldFolder(), "iris/" + dimension.getLoadKey() + "/parallax"));
|
||||
}
|
||||
|
||||
public void updateWorld(World world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public EngineTarget(World world, IrisDimension dimension, IrisDataManager data, int height, int threads) {
|
||||
public EngineTarget(IrisWorld world, IrisDimension dimension, IrisDataManager data, int height, int threads) {
|
||||
this(world, dimension, data, height, false, threads);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
burster.shutdownAndAwait();
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
package com.volmit.iris.engine.framework;
|
||||
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.core.gui.Renderer;
|
||||
import com.volmit.iris.core.gui.components.Renderer;
|
||||
import com.volmit.iris.engine.data.DataProvider;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisObjectPlacement;
|
||||
|
@ -20,20 +20,21 @@ package com.volmit.iris.engine.framework;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.engine.IrisComplex;
|
||||
import com.volmit.iris.engine.data.DataProvider;
|
||||
import com.volmit.iris.engine.data.mca.NBTWorld;
|
||||
import com.volmit.iris.engine.headless.HeadlessGenerator;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
import com.volmit.iris.engine.object.common.IrisWorld;
|
||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@ -44,9 +45,19 @@ import java.util.function.Consumer;
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
public interface IrisAccess extends Hotloadable, DataProvider {
|
||||
|
||||
void directWriteMCA(World w, int x, int z, NBTWorld writer, MultiBurst burst);
|
||||
HeadlessGenerator getHeadlessGenerator();
|
||||
|
||||
void directWriteChunk(World w, int x, int z, NBTWorld writer);
|
||||
default boolean isHeadless() {
|
||||
return getHeadlessGenerator() != null;
|
||||
}
|
||||
|
||||
NBTWorld getHeadlessNBTWriter();
|
||||
|
||||
void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst);
|
||||
|
||||
void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst, PregenListener listener);
|
||||
|
||||
void directWriteChunk(IrisWorld w, int x, int z, NBTWorld writer);
|
||||
|
||||
int getGenerated();
|
||||
|
||||
@ -72,8 +83,6 @@ public interface IrisAccess extends Hotloadable, DataProvider {
|
||||
|
||||
void changeThreadCount(int m);
|
||||
|
||||
void regenerate(int x, int z);
|
||||
|
||||
void close();
|
||||
|
||||
boolean isClosed();
|
||||
@ -87,6 +96,11 @@ public interface IrisAccess extends Hotloadable, DataProvider {
|
||||
boolean isStudio();
|
||||
|
||||
default Location lookForBiome(IrisBiome biome, long timeout, Consumer<Integer> triesc) {
|
||||
if (!getCompound().getWorld().hasRealWorld()) {
|
||||
Iris.error("Cannot GOTO without a bound world (headless mode)");
|
||||
return null;
|
||||
}
|
||||
|
||||
IrisComplex.cacheLock.set(true);
|
||||
ChronoLatch cl = new ChronoLatch(250, false);
|
||||
long s = M.ms();
|
||||
@ -130,7 +144,7 @@ public interface IrisAccess extends Hotloadable, DataProvider {
|
||||
|
||||
if (b != null && b.getLoadKey().equals(biome.getLoadKey())) {
|
||||
found.lazySet(true);
|
||||
location.lazySet(new Location(e.getWorld(), x, e.getHeight(x, z), z));
|
||||
location.lazySet(new Location(e.getWorld().realWorld(), x, e.getHeight(x, z), z));
|
||||
}
|
||||
|
||||
tries.getAndIncrement();
|
||||
@ -167,6 +181,11 @@ public interface IrisAccess extends Hotloadable, DataProvider {
|
||||
}
|
||||
|
||||
default Location lookForRegion(IrisRegion reg, long timeout, Consumer<Integer> triesc) {
|
||||
if (!getCompound().getWorld().hasRealWorld()) {
|
||||
Iris.error("Cannot GOTO without a bound world (headless mode)");
|
||||
return null;
|
||||
}
|
||||
|
||||
IrisComplex.cacheLock.set(true);
|
||||
ChronoLatch cl = new ChronoLatch(3000, false);
|
||||
long s = M.ms();
|
||||
@ -204,7 +223,7 @@ public interface IrisAccess extends Hotloadable, DataProvider {
|
||||
|
||||
if (b != null && b.getLoadKey() != null && b.getLoadKey().equals(reg.getLoadKey())) {
|
||||
found.lazySet(true);
|
||||
location.lazySet(new Location(e.getWorld(), x, e.getHeight(x, z) + e.getMinHeight(), z));
|
||||
location.lazySet(new Location(e.getWorld().realWorld(), x, e.getHeight(x, z) + e.getMinHeight(), z));
|
||||
}
|
||||
|
||||
tries.getAndIncrement();
|
||||
@ -238,14 +257,6 @@ public interface IrisAccess extends Hotloadable, DataProvider {
|
||||
return location.get();
|
||||
}
|
||||
|
||||
void clearRegeneratedLists(int x, int z);
|
||||
|
||||
void precache(World world, int x, int z);
|
||||
|
||||
int getPrecacheSize();
|
||||
|
||||
Chunk generatePaper(World world, int cx, int cz);
|
||||
|
||||
default int getParallaxChunkCount() {
|
||||
int v = 0;
|
||||
|
||||
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.headless;
|
||||
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.engine.data.mca.MCAUtil;
|
||||
import com.volmit.iris.engine.data.mca.NBTWorld;
|
||||
import com.volmit.iris.engine.framework.EngineCompositeGenerator;
|
||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@Data
|
||||
public class HeadlessGenerator {
|
||||
private static KList<Position2> EMPTYPOINTS = new KList<>();
|
||||
private final HeadlessWorld world;
|
||||
private final EngineCompositeGenerator generator;
|
||||
private final NBTWorld writer;
|
||||
private final MultiBurst burst;
|
||||
|
||||
public HeadlessGenerator(HeadlessWorld world) {
|
||||
this.world = world;
|
||||
burst = new MultiBurst("Iris Headless Generator", 9, IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getPregenThreadCount()));
|
||||
writer = new NBTWorld(world.getWorld().worldFolder());
|
||||
generator = new EngineCompositeGenerator(world.getDimension().getLoadKey(), !world.isStudio());
|
||||
generator.assignHeadlessGenerator(this);
|
||||
generator.assignHeadlessNBTWriter(writer);
|
||||
generator.initialize(world.getWorld());
|
||||
}
|
||||
|
||||
public void generateChunk(int x, int z) {
|
||||
generator.directWriteChunk(world.getWorld(), x, z, writer);
|
||||
}
|
||||
|
||||
public void generateRegion(int x, int z) {
|
||||
generator.directWriteMCA(world.getWorld(), x, z, writer, burst);
|
||||
}
|
||||
|
||||
public void generateRegion(int x, int z, PregenListener listener) {
|
||||
generator.directWriteMCA(world.getWorld(), x, z, writer, burst, listener);
|
||||
}
|
||||
|
||||
public File generateRegionToFile(int x, int z, PregenListener listener) {
|
||||
generateRegionToFile(x, z, listener);
|
||||
flush();
|
||||
return writer.getRegionFile(x, z);
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
writer.flushNow();
|
||||
}
|
||||
|
||||
public void save() {
|
||||
writer.save();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
burst.shutdownAndAwait();
|
||||
generator.close();
|
||||
writer.close();
|
||||
}
|
||||
|
||||
public KList<Position2> getChunksInRegion(int x, int z) {
|
||||
try {
|
||||
return MCAUtil.sampleChunkPositions(writer.getRegionFile(x, z));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return EMPTYPOINTS;
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.headless;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisDataManager;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.engine.framework.EngineCompositeGenerator;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.common.IrisWorld;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@Data
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
public class HeadlessWorld {
|
||||
private final IrisDimension dimension;
|
||||
private final String worldName;
|
||||
private final IrisWorld world;
|
||||
private boolean studio = false;
|
||||
|
||||
public HeadlessWorld(String worldName, IrisDimension dimension, long seed) {
|
||||
this(worldName, dimension, seed, false);
|
||||
}
|
||||
|
||||
public HeadlessWorld(String worldName, IrisDimension dimension, long seed, boolean studio) {
|
||||
this.worldName = worldName;
|
||||
this.dimension = dimension;
|
||||
this.studio = studio;
|
||||
world = IrisWorld.builder()
|
||||
.environment(dimension.getEnvironment())
|
||||
.worldFolder(new File(worldName))
|
||||
.seed(seed)
|
||||
.maxHeight(256)
|
||||
.minHeight(0)
|
||||
.name(worldName)
|
||||
.build();
|
||||
world.worldFolder().mkdirs();
|
||||
new File(world.worldFolder(), "region").mkdirs();
|
||||
|
||||
if (!studio && !new File(world.worldFolder(), "iris").exists()) {
|
||||
Iris.proj.installIntoWorld(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag("Headless")), dimension.getLoadKey(), world.worldFolder());
|
||||
}
|
||||
}
|
||||
|
||||
public HeadlessGenerator generate() {
|
||||
return new HeadlessGenerator(this);
|
||||
}
|
||||
|
||||
public World load() {
|
||||
return new WorldCreator(worldName)
|
||||
.environment(dimension.getEnvironment())
|
||||
.seed(world.seed())
|
||||
.generator(new EngineCompositeGenerator(dimension.getLoadKey(), !studio))
|
||||
.createWorld();
|
||||
}
|
||||
|
||||
public static HeadlessWorld from(World world) {
|
||||
return new HeadlessWorld(world.getName(), IrisWorlds.access(world).getTarget().getDimension(), world.getSeed());
|
||||
}
|
||||
|
||||
public static HeadlessWorld from(String name, String dimension, long seed) {
|
||||
return new HeadlessWorld(name, IrisDataManager.loadAnyDimension(dimension), seed);
|
||||
}
|
||||
}
|
@ -865,18 +865,6 @@ public interface Hunk<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
default void enforceBounds(int x, int y, int z) {
|
||||
if (x < 0 || x >= getWidth() || y < 0 || y >= getHeight() || z < 0 || z >= getDepth()) {
|
||||
//Iris.warn(x + "," + y + "," + z + " does not fit within size " + getWidth() + "," + getHeight() + "," + getDepth() + " (0,0,0 to " + (getWidth() - 1) + "," + (getHeight() - 1) + "," + (getDepth() - 1) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
default void enforceBounds(int x, int y, int z, int w, int h, int d) {
|
||||
if (x < 0 || x >= getWidth() || y < 0 || y >= getHeight() || z < 0 || z >= getDepth() || x + w < 0 || x + w > getWidth() || y + h < 0 || y + h > getHeight() || z + d < 0 || z + d > getDepth()) {
|
||||
//Iris.warn("The hunk " + w + "," + h + "," + d + " with an offset of " + x + "," + y + "," + z + " does not fit within the parent hunk " + getWidth() + "," + getHeight() + "," + getDepth() + " (0,0,0 to " + (getWidth() - 1) + "," + (getHeight() - 1) + "," + (getDepth() - 1) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new hunk from a section of this hunk.
|
||||
*
|
||||
@ -890,7 +878,6 @@ public interface Hunk<T> {
|
||||
*/
|
||||
default ArrayHunk<T> crop(int x1, int y1, int z1, int x2, int y2, int z2) {
|
||||
ArrayHunk<T> h = new ArrayHunk<T>(x2 - x1, y2 - y1, z2 - z1);
|
||||
enforceBounds(x1, y1, z1, x2 - x1, y2 - y1, z2 - z1);
|
||||
|
||||
for (int i = x1; i < x2; i++) {
|
||||
for (int j = y1; j < y2; j++) {
|
||||
@ -916,7 +903,6 @@ public interface Hunk<T> {
|
||||
* @return the cropped view of this hunk (x2-x1, y2-y1, z2-z1)
|
||||
*/
|
||||
default Hunk<T> croppedView(int x1, int y1, int z1, int x2, int y2, int z2) {
|
||||
enforceBounds(x1, y1, z1, x2 - x1, y2 - y1, z2 - z1);
|
||||
return new HunkView<T>(this, x2 - x1, y2 - y1, z2 - z1, x1, y1, z1);
|
||||
}
|
||||
|
||||
@ -947,7 +933,6 @@ public interface Hunk<T> {
|
||||
* @param t the value to set
|
||||
*/
|
||||
default void set(int x1, int y1, int z1, int x2, int y2, int z2, T t) {
|
||||
enforceBounds(x1, y1, z1, x2 - x1, y2 - y1, z2 - z1);
|
||||
for (int i = x1; i <= x2; i++) {
|
||||
for (int j = y1; j <= y2; j++) {
|
||||
for (int k = z1; k <= z2; k++) {
|
||||
@ -1036,7 +1021,6 @@ public interface Hunk<T> {
|
||||
* @param t the value
|
||||
*/
|
||||
default void set(int x, int y, int z, T t) {
|
||||
enforceBounds(x, y, z);
|
||||
setRaw(x, y, z, t);
|
||||
}
|
||||
|
||||
@ -1089,12 +1073,10 @@ public interface Hunk<T> {
|
||||
* @return the value or null
|
||||
*/
|
||||
default T get(int x, int y, int z) {
|
||||
enforceBounds(x, y, z);
|
||||
return getRaw(x, y, z);
|
||||
}
|
||||
|
||||
default T getOr(int x, int y, int z, T t) {
|
||||
enforceBounds(x, y, z);
|
||||
T v = getRaw(x, y, z);
|
||||
|
||||
if (v == null) {
|
||||
@ -1161,8 +1143,6 @@ public interface Hunk<T> {
|
||||
* @param invertY should the inserted hunk be inverted
|
||||
*/
|
||||
default void insert(int offX, int offY, int offZ, Hunk<T> hunk, boolean invertY) {
|
||||
enforceBounds(offX, offY, offZ, hunk.getWidth(), hunk.getHeight(), hunk.getDepth());
|
||||
|
||||
for (int i = offX; i < offX + hunk.getWidth(); i++) {
|
||||
for (int j = offY; j < offY + hunk.getHeight(); j++) {
|
||||
for (int k = offZ; k < offZ + hunk.getDepth(); k++) {
|
||||
@ -1183,8 +1163,6 @@ public interface Hunk<T> {
|
||||
* @param invertY should the inserted hunk be inverted
|
||||
*/
|
||||
default void insertSoftly(int offX, int offY, int offZ, Hunk<T> hunk, boolean invertY, Predicate<T> shouldOverwrite) {
|
||||
enforceBounds(offX, offY, offZ, hunk.getWidth(), hunk.getHeight(), hunk.getDepth());
|
||||
|
||||
for (int i = offX; i < offX + hunk.getWidth(); i++) {
|
||||
for (int j = offY; j < offY + hunk.getHeight(); j++) {
|
||||
for (int k = offZ; k < offZ + hunk.getDepth(); k++) {
|
||||
|
@ -22,19 +22,17 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.object.tile.TileData;
|
||||
import com.volmit.iris.engine.parallel.BurstExecutor;
|
||||
import com.volmit.iris.engine.parallel.GridLock;
|
||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.function.Function2;
|
||||
import com.volmit.iris.util.function.Function3;
|
||||
import com.volmit.iris.util.math.ChunkPosition;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.oldnbt.ByteArrayTag;
|
||||
import com.volmit.iris.util.oldnbt.CompoundTag;
|
||||
import com.volmit.iris.util.oldnbt.Tag;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.block.TileState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
@ -42,22 +40,20 @@ import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class HunkRegionSlice<T> {
|
||||
public static final Function2<Integer, CompoundTag, HunkRegionSlice<BlockData>> BLOCKDATA = (h, c) -> new HunkRegionSlice<>(h, Hunk::newMappedHunkSynced, new BlockDataHunkIOAdapter(), c, "blockdata");
|
||||
public static final Function2<Integer, CompoundTag, HunkRegionSlice<TileData<? extends TileState>>> TILE = (h, c) -> new HunkRegionSlice<>(h, Hunk::newMappedHunkSynced, new TileDataHunkIOAdapter(), c, "tile");
|
||||
public static final Function3<Integer, CompoundTag, String, HunkRegionSlice<String>> STRING = (h, c, t) -> new HunkRegionSlice<>(h, Hunk::newMappedHunkSynced, new StringHunkIOAdapter(), c, t);
|
||||
public static final Function3<Integer, CompoundTag, String, HunkRegionSlice<Boolean>> BOOLEAN = (h, c, t) -> new HunkRegionSlice<>(h, Hunk::newMappedHunkSynced, new BooleanHunkIOAdapter(), c, t);
|
||||
public static final Function2<Integer, CompoundTag, HunkRegionSlice<BlockData>> BLOCKDATA = (h, c) -> new HunkRegionSlice<>(h, Hunk::newMappedHunk, new BlockDataHunkIOAdapter(), c, "blockdata");
|
||||
public static final Function2<Integer, CompoundTag, HunkRegionSlice<TileData<? extends TileState>>> TILE = (h, c) -> new HunkRegionSlice<>(h, Hunk::newMappedHunk, new TileDataHunkIOAdapter(), c, "tile");
|
||||
public static final Function3<Integer, CompoundTag, String, HunkRegionSlice<String>> STRING = (h, c, t) -> new HunkRegionSlice<>(h, Hunk::newMappedHunk, new StringHunkIOAdapter(), c, t);
|
||||
public static final Function3<Integer, CompoundTag, String, HunkRegionSlice<Boolean>> BOOLEAN = (h, c, t) -> new HunkRegionSlice<>(h, Hunk::newMappedHunk, new BooleanHunkIOAdapter(), c, t);
|
||||
private final Function3<Integer, Integer, Integer, Hunk<T>> factory;
|
||||
private final GridLock lock;
|
||||
private final HunkIOAdapter<T> adapter;
|
||||
private final CompoundTag compound;
|
||||
private final String key;
|
||||
private final KMap<ChunkPosition, Hunk<T>> loadedChunks;
|
||||
private final KMap<ChunkPosition, Long> lastUse;
|
||||
private final KSet<ChunkPosition> save;
|
||||
private final KMap<Position2, Hunk<T>> loadedChunks;
|
||||
private final KMap<Position2, Long> lastUse;
|
||||
private final KSet<Position2> save;
|
||||
private final int height;
|
||||
|
||||
public HunkRegionSlice(int height, Function3<Integer, Integer, Integer, Hunk<T>> factory, HunkIOAdapter<T> adapter, CompoundTag compound, String key) {
|
||||
this.lock = new GridLock(32, 32);
|
||||
this.height = height;
|
||||
this.loadedChunks = new KMap<>();
|
||||
this.factory = factory;
|
||||
@ -73,18 +69,20 @@ public class HunkRegionSlice<T> {
|
||||
if (loadedChunks.size() != lastUse.size()) {
|
||||
Iris.warn("Incorrect chunk use counts in " + key);
|
||||
|
||||
for (ChunkPosition i : lastUse.k()) {
|
||||
for (Position2 i : lastUse.k()) {
|
||||
if (!loadedChunks.containsKey(i)) {
|
||||
Iris.warn(" Missing LoadChunkKey " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ChunkPosition i : lastUse.k()) {
|
||||
for (Position2 i : lastUse.k()) {
|
||||
Long l = lastUse.get(i);
|
||||
if (l == null || M.ms() - l > t) {
|
||||
v++;
|
||||
unload(i.getX(), i.getZ());
|
||||
MultiBurst.burst.lazy(() -> {
|
||||
unload(i.getX(), i.getZ());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,30 +97,23 @@ public class HunkRegionSlice<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void save() {
|
||||
BurstExecutor e = MultiBurst.burst.burst();
|
||||
public synchronized void save(MultiBurst burst) {
|
||||
|
||||
try
|
||||
{
|
||||
for (ChunkPosition i : save.copy()) {
|
||||
try {
|
||||
for (Position2 i : save.copy()) {
|
||||
if (i == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
e.queue(() -> save(i.getX(), i.getZ()));
|
||||
save(i.getX(), i.getZ());
|
||||
|
||||
try {
|
||||
lock.withNasty(i.getX(), i.getZ(), () -> save.remove(i));
|
||||
save.remove(i);
|
||||
} catch (Throwable eer) {
|
||||
Iris.reportError(eer);
|
||||
}
|
||||
}
|
||||
|
||||
e.complete();
|
||||
}
|
||||
|
||||
catch(Throwable ee)
|
||||
{
|
||||
} catch (Throwable ee) {
|
||||
Iris.reportError(ee);
|
||||
}
|
||||
}
|
||||
@ -132,28 +123,23 @@ public class HunkRegionSlice<T> {
|
||||
}
|
||||
|
||||
public void delete(int x, int z) {
|
||||
lock.with(x, z, () -> compound.getValue().remove(key(x, z)));
|
||||
compound.getValue().remove(key(x, z));
|
||||
}
|
||||
|
||||
public Hunk<T> read(int x, int z) throws IOException {
|
||||
AtomicReference<IOException> e = new AtomicReference<>();
|
||||
Hunk<T> xt = lock.withResult(x, z, () -> {
|
||||
Tag t = compound.getValue().get(key(x, z));
|
||||
Hunk<T> xt = null;
|
||||
|
||||
if (!(t instanceof ByteArrayTag)) {
|
||||
Iris.verbose("NOT BYTE ARRAY!");
|
||||
return null;
|
||||
}
|
||||
Tag t = compound.getValue().get(key(x, z));
|
||||
|
||||
if ((t instanceof ByteArrayTag)) {
|
||||
try {
|
||||
return adapter.read(factory, (ByteArrayTag) t);
|
||||
xt = adapter.read(factory, (ByteArrayTag) t);
|
||||
} catch (IOException xe) {
|
||||
Iris.reportError(xe);
|
||||
e.set(xe);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
if (xt != null) {
|
||||
return xt;
|
||||
@ -167,12 +153,12 @@ public class HunkRegionSlice<T> {
|
||||
}
|
||||
|
||||
public void write(Hunk<T> hunk, int x, int z) throws IOException {
|
||||
lock.withIO(x, z, () -> compound.getValue().put(key(x, z), hunk.writeByteArrayTag(adapter, key(x, z))));
|
||||
compound.getValue().put(key(x, z), hunk.writeByteArrayTag(adapter, key(x, z)));
|
||||
}
|
||||
|
||||
public synchronized int unloadAll() {
|
||||
int v = 0;
|
||||
for (ChunkPosition i : loadedChunks.k()) {
|
||||
for (Position2 i : loadedChunks.k()) {
|
||||
unload(i.getX(), i.getZ());
|
||||
v++;
|
||||
}
|
||||
@ -185,7 +171,7 @@ public class HunkRegionSlice<T> {
|
||||
|
||||
public void save(Hunk<T> region, int x, int z) {
|
||||
try {
|
||||
lock.withIO(x, z, () -> write(region, x, z));
|
||||
write(region, x, z);
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
@ -193,84 +179,74 @@ public class HunkRegionSlice<T> {
|
||||
}
|
||||
|
||||
public boolean isLoaded(int x, int z) {
|
||||
return lock.withResult(x, z, () -> loadedChunks.containsKey(new ChunkPosition(x, z)));
|
||||
return loadedChunks.containsKey(new Position2(x, z));
|
||||
}
|
||||
|
||||
public void save(int x, int z) {
|
||||
lock.with(x, z, () -> {
|
||||
if (isLoaded(x, z)) {
|
||||
save(get(x, z), x, z);
|
||||
}
|
||||
});
|
||||
if (isLoaded(x, z)) {
|
||||
save(get(x, z), x, z);
|
||||
}
|
||||
}
|
||||
|
||||
public void unload(int x, int z) {
|
||||
lock.with(x, z, () -> {
|
||||
ChunkPosition key = new ChunkPosition(x, z);
|
||||
if (isLoaded(x, z)) {
|
||||
if (save.contains(key)) {
|
||||
save(x, z);
|
||||
save.remove(key);
|
||||
}
|
||||
|
||||
lastUse.remove(key);
|
||||
loadedChunks.remove(key);
|
||||
Position2 key = new Position2(x, z);
|
||||
if (isLoaded(x, z)) {
|
||||
if (save.contains(key)) {
|
||||
save(x, z);
|
||||
save.remove(key);
|
||||
}
|
||||
});
|
||||
|
||||
lastUse.remove(key);
|
||||
loadedChunks.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public Hunk<T> load(int x, int z) {
|
||||
return lock.withResult(x, z, () -> {
|
||||
if (isLoaded(x, z)) {
|
||||
return loadedChunks.get(new ChunkPosition(x, z));
|
||||
if (isLoaded(x, z)) {
|
||||
return loadedChunks.get(new Position2(x, z));
|
||||
}
|
||||
|
||||
Hunk<T> v = null;
|
||||
|
||||
if (contains(x, z)) {
|
||||
try {
|
||||
v = read(x, z);
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Hunk<T> v = null;
|
||||
if (v == null) {
|
||||
v = factory.apply(16, height, 16);
|
||||
}
|
||||
|
||||
if (contains(x, z)) {
|
||||
try {
|
||||
v = read(x, z);
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
loadedChunks.put(new Position2(x, z), v);
|
||||
|
||||
if (v == null) {
|
||||
v = factory.apply(16, height, 16);
|
||||
}
|
||||
|
||||
loadedChunks.put(new ChunkPosition(x, z), v);
|
||||
|
||||
return v;
|
||||
});
|
||||
return v;
|
||||
}
|
||||
|
||||
public Hunk<T> get(int x, int z) {
|
||||
return lock.withResult(x, z, () -> {
|
||||
ChunkPosition key = new ChunkPosition(x, z);
|
||||
Position2 key = new Position2(x, z);
|
||||
|
||||
Hunk<T> c = loadedChunks.get(key);
|
||||
Hunk<T> c = loadedChunks.get(key);
|
||||
|
||||
if (c == null) {
|
||||
c = load(x, z);
|
||||
}
|
||||
if (c == null) {
|
||||
c = load(x, z);
|
||||
}
|
||||
|
||||
lastUse.put(new ChunkPosition(x, z), M.ms());
|
||||
lastUse.put(new Position2(x, z), M.ms());
|
||||
|
||||
return c;
|
||||
});
|
||||
return c;
|
||||
}
|
||||
|
||||
public Hunk<T> getR(int x, int z) {
|
||||
return lock.withResult(x, z, () -> get(x, z).readOnly());
|
||||
return get(x, z).readOnly();
|
||||
}
|
||||
|
||||
public Hunk<T> getRW(int x, int z) {
|
||||
return lock.withResult(x, z, () -> {
|
||||
save.add(new ChunkPosition(x, z));
|
||||
return get(x, z);
|
||||
});
|
||||
save.add(new Position2(x, z));
|
||||
return get(x, z);
|
||||
}
|
||||
|
||||
private String key(int x, int z) {
|
||||
|
@ -51,7 +51,6 @@ public class ChunkDataHunkView implements Hunk<BlockData> {
|
||||
return;
|
||||
}
|
||||
|
||||
enforceBounds(x1, y1, z1, x2 - x1, y2 - y1, z2 - z1);
|
||||
chunk.setRegion(x1, y1, z1, x2, y2, z2, t);
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user