diff --git a/build.gradle b/build.gradle
index 5c741c4cb..4979add35 100644
--- a/build.gradle
+++ b/build.gradle
@@ -137,6 +137,7 @@ allprojects {
//implementation 'org.bytedeco:javacpp:1.5.10'
//implementation 'org.bytedeco:cuda-platform:12.3-8.9-1.5.10'
compileOnly 'io.lumine:Mythic-Dist:5.2.1'
+ compileOnly 'io.lumine:MythicCrucible-Dist:2.0.0'
// Dynamically Loaded
compileOnly 'io.timeandspace:smoothie-map:2.0.2'
diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandJigsaw.java b/core/src/main/java/com/volmit/iris/core/commands/CommandJigsaw.java
index 710184027..3022b866c 100644
--- a/core/src/main/java/com/volmit/iris/core/commands/CommandJigsaw.java
+++ b/core/src/main/java/com/volmit/iris/core/commands/CommandJigsaw.java
@@ -60,7 +60,7 @@ public class CommandJigsaw implements DecreeExecutor {
try {
var world = world();
WorldObjectPlacer placer = new WorldObjectPlacer(world);
- PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation().add(0, world.getMinHeight(), 0)), new RNG());
+ PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation().add(0, world.getMinHeight(), 0)), new RNG(), true);
VolmitSender sender = sender();
sender.sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
ps.place(placer, failed -> sender.sendMessage(failed ? C.GREEN + "Placed the structure!" : C.RED + "Failed to place the structure!"));
diff --git a/core/src/main/java/com/volmit/iris/core/link/MythicCrucibleDataProvider.java b/core/src/main/java/com/volmit/iris/core/link/MythicCrucibleDataProvider.java
new file mode 100644
index 000000000..8f3e6969f
--- /dev/null
+++ b/core/src/main/java/com/volmit/iris/core/link/MythicCrucibleDataProvider.java
@@ -0,0 +1,166 @@
+/*
+ * Iris is a World Generator for Minecraft Bukkit Servers
+ * Copyright (c) 2022 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 .
+ */
+
+package com.volmit.iris.core.link;
+
+import com.volmit.iris.Iris;
+import com.volmit.iris.core.nms.INMS;
+import com.volmit.iris.core.nms.container.BiomeColor;
+import com.volmit.iris.core.service.ExternalDataSVC;
+import com.volmit.iris.engine.data.cache.Cache;
+import com.volmit.iris.engine.framework.Engine;
+import com.volmit.iris.util.collection.KList;
+import com.volmit.iris.util.collection.KMap;
+import com.volmit.iris.util.data.B;
+import com.volmit.iris.util.data.IrisBlockData;
+import com.volmit.iris.util.math.RNG;
+import io.lumine.mythic.bukkit.BukkitAdapter;
+import io.lumine.mythic.bukkit.utils.serialize.Chroma;
+import io.lumine.mythiccrucible.MythicCrucible;
+import io.lumine.mythiccrucible.items.CrucibleItem;
+import io.lumine.mythiccrucible.items.ItemManager;
+import io.lumine.mythiccrucible.items.blocks.CustomBlockItemContext;
+import io.lumine.mythiccrucible.items.furniture.FurnitureItemContext;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.block.data.BlockData;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.MissingResourceException;
+import java.util.Optional;
+
+public class MythicCrucibleDataProvider extends ExternalDataProvider {
+
+ private ItemManager itemManager;
+
+ public MythicCrucibleDataProvider() {
+ super("MythicCrucible");
+ }
+
+ @Override
+ public void init() {
+ Iris.info("Setting up MythicCrucible Link...");
+ try {
+ this.itemManager = MythicCrucible.inst().getItemManager();
+ } catch (Exception e) {
+ Iris.error("Failed to set up MythicCrucible Link: Unable to fetch MythicCrucible instance!");
+ }
+ }
+
+ @Override
+ public BlockData getBlockData(Identifier blockId, KMap state) throws MissingResourceException {
+ CrucibleItem crucibleItem = this.itemManager.getItem(blockId.key())
+ .orElseThrow(() -> new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key()));
+ CustomBlockItemContext blockItemContext = crucibleItem.getBlockData();
+ FurnitureItemContext furnitureItemContext = crucibleItem.getFurnitureData();
+ if (furnitureItemContext != null) {
+ return new IrisBlockData(B.getAir(), ExternalDataSVC.buildState(blockId, state));
+ } else if (blockItemContext != null) {
+ return blockItemContext.getBlockData();
+ }
+ throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
+ }
+
+ @Override
+ public ItemStack getItemStack(Identifier itemId, KMap customNbt) throws MissingResourceException {
+ Optional opt = this.itemManager.getItem(itemId.key());
+ return BukkitAdapter.adapt(opt.orElseThrow(() ->
+ new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()))
+ .getMythicItem()
+ .generateItemStack(1));
+ }
+
+ @Override
+ public Identifier[] getBlockTypes() {
+ KList names = new KList<>();
+ for (CrucibleItem item : this.itemManager.getItems()) {
+ if (item.getBlockData() == null) continue;
+ try {
+ Identifier key = new Identifier("crucible", item.getInternalName());
+ if (getBlockData(key) != null) {
+ Iris.info("getBlockTypes: Block loaded '" + item.getInternalName() + "'");
+ names.add(key);
+ }
+ } catch (MissingResourceException ignored) {}
+ }
+ return names.toArray(new Identifier[0]);
+ }
+
+ @Override
+ public Identifier[] getItemTypes() {
+ KList names = new KList<>();
+ for (CrucibleItem item : this.itemManager.getItems()) {
+ try {
+ Identifier key = new Identifier("crucible", item.getInternalName());
+ if (getItemStack(key) != null) {
+ Iris.info("getItemTypes: Item loaded '" + item.getInternalName() + "'");
+ names.add(key);
+ }
+ } catch (MissingResourceException ignored) {}
+ }
+ return names.toArray(new Identifier[0]);
+ }
+
+ @Override
+ public void processUpdate(Engine engine, Block block, Identifier blockId) {
+ var pair = ExternalDataSVC.parseState(blockId);
+ var state = pair.getB();
+ blockId = pair.getA();
+
+ Optional item = itemManager.getItem(blockId.key());
+ if (item.isEmpty()) return;
+ FurnitureItemContext furniture = item.get().getFurnitureData();
+ if (furniture == null) return;
+
+ float yaw = 0;
+ BlockFace face = BlockFace.NORTH;
+ long seed = engine.getSeedManager().getSeed() + Cache.key(block.getX(), block.getZ()) + block.getY();
+ RNG rng = new RNG(seed);
+ if ("true".equals(state.get("randomYaw"))) {
+ yaw = rng.f(0, 360);
+ } else if (state.containsKey("yaw")) {
+ yaw = Float.parseFloat(state.get("yaw"));
+ }
+ if ("true".equals(state.get("randomFace"))) {
+ BlockFace[] faces = BlockFace.values();
+ face = faces[rng.i(0, faces.length - 1)];
+ } else if (state.containsKey("face")) {
+ face = BlockFace.valueOf(state.get("face").toUpperCase());
+ }
+ if (face == BlockFace.SELF) {
+ face = BlockFace.NORTH;
+ }
+
+ BiomeColor type = null;
+ Chroma color = null;
+ try {
+ type = BiomeColor.valueOf(state.get("matchBiome").toUpperCase());
+ } catch (NullPointerException | IllegalArgumentException ignored) {}
+ if (type != null) {
+ var biomeColor = INMS.get().getBiomeColor(block.getLocation(), type);
+ if (biomeColor == null) return;
+ color = Chroma.of(biomeColor.getRGB());
+ }
+ furniture.place(block, face, yaw, color);
+ }
+
+ @Override
+ public boolean isValidProvider(Identifier key, boolean isItem) {
+ return key.namespace().equalsIgnoreCase("crucible");
+ }
+}
diff --git a/core/src/main/java/com/volmit/iris/core/service/ExternalDataSVC.java b/core/src/main/java/com/volmit/iris/core/service/ExternalDataSVC.java
index 4c31f2312..6992c8be3 100644
--- a/core/src/main/java/com/volmit/iris/core/service/ExternalDataSVC.java
+++ b/core/src/main/java/com/volmit/iris/core/service/ExternalDataSVC.java
@@ -50,6 +50,10 @@ public class ExternalDataSVC implements IrisService {
if (Bukkit.getPluginManager().getPlugin("Oraxen") != null) {
Iris.info("Oraxen found, loading OraxenDataProvider...");
}
+ providers.add(new MythicCrucibleDataProvider());
+ if (Bukkit.getPluginManager().getPlugin("MythicCrucible") != null) {
+ Iris.info("MythicCrucible found, loading MythicCrucibleDataProvider...");
+ }
providers.add(new ItemAdderDataProvider());
if (Bukkit.getPluginManager().getPlugin("ItemAdder") != null) {
Iris.info("ItemAdder found, loading ItemAdderDataProvider...");
diff --git a/core/src/main/java/com/volmit/iris/engine/jigsaw/PlannedStructure.java b/core/src/main/java/com/volmit/iris/engine/jigsaw/PlannedStructure.java
index 09c819478..cca5a100a 100644
--- a/core/src/main/java/com/volmit/iris/engine/jigsaw/PlannedStructure.java
+++ b/core/src/main/java/com/volmit/iris/engine/jigsaw/PlannedStructure.java
@@ -51,16 +51,18 @@ public class PlannedStructure {
private IrisPosition position;
private IrisData data;
private RNG rng;
+ private boolean forcePlace;
private boolean verbose;
private boolean terminating;
- public PlannedStructure(IrisJigsawStructure structure, IrisPosition position, RNG rng) {
+ public PlannedStructure(IrisJigsawStructure structure, IrisPosition position, RNG rng, boolean forcePlace) {
terminating = false;
verbose = true;
this.pieces = new KList<>();
this.structure = structure;
this.position = position;
this.rng = rng;
+ this.forcePlace = forcePlace;
this.data = structure.getLoader();
generateStartPiece();
@@ -109,6 +111,9 @@ public class PlannedStructure {
} else {
options.setMode(i.getPiece().getPlaceMode());
}
+ if (forcePlace) {
+ options.setForcePlace(true);
+ }
IrisObject v = i.getObject();
int sx = (v.getW() / 2);
diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java
index 17e192c19..ac091e346 100644
--- a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java
+++ b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java
@@ -66,7 +66,7 @@ public class MantleJigsawComponent extends IrisMantleComponent {
for (Position2 pos : poss) {
if (x == pos.getX() >> 4 && z == pos.getZ() >> 4) {
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(getDimension().getStronghold());
- place(writer, pos.toIris(), structure, new RNG(seed));
+ place(writer, pos.toIris(), structure, new RNG(seed), true);
return;
}
}
@@ -92,7 +92,7 @@ public class MantleJigsawComponent extends IrisMantleComponent {
RNG rng = new RNG(seed);
IrisPosition position = new IrisPosition((x << 4) + rng.nextInt(15), 0, (z << 4) + rng.nextInt(15));
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(i.getStructure());
- return place(writer, position, structure, rng);
+ return place(writer, position, structure, rng, false);
}
@ChunkCoordinates
@@ -161,8 +161,8 @@ public class MantleJigsawComponent extends IrisMantleComponent {
}
@BlockCoordinates
- private boolean place(MantleWriter writer, IrisPosition position, IrisJigsawStructure structure, RNG rng) {
- return new PlannedStructure(structure, position, rng).place(writer, getMantle(), writer.getEngine());
+ private boolean place(MantleWriter writer, IrisPosition position, IrisJigsawStructure structure, RNG rng, boolean forcePlace) {
+ return new PlannedStructure(structure, position, rng, forcePlace).place(writer, getMantle(), writer.getEngine());
}
private long jigsaw() {
diff --git a/core/src/main/java/com/volmit/iris/engine/object/LegacyTileData.java b/core/src/main/java/com/volmit/iris/engine/object/LegacyTileData.java
index ac8728ebe..5820fc064 100644
--- a/core/src/main/java/com/volmit/iris/engine/object/LegacyTileData.java
+++ b/core/src/main/java/com/volmit/iris/engine/object/LegacyTileData.java
@@ -1,14 +1,19 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.util.collection.KList;
+import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.scheduling.J;
import lombok.EqualsAndHashCode;
+import lombok.NonNull;
import lombok.ToString;
import org.apache.commons.io.function.IOFunction;
import org.bukkit.DyeColor;
+import org.bukkit.Material;
+import org.bukkit.Tag;
import org.bukkit.block.*;
import org.bukkit.block.banner.Pattern;
import org.bukkit.block.banner.PatternType;
+import org.bukkit.block.data.BlockData;
import org.bukkit.entity.EntityType;
import java.io.DataInputStream;
@@ -34,6 +39,21 @@ public class LegacyTileData extends TileData {
handler = factory.apply(in);
}
+ @Override
+ public @NonNull KMap getProperties() {
+ return new KMap<>();
+ }
+
+ @Override
+ public @NonNull Material getMaterial() {
+ return handler.getMaterial();
+ }
+
+ @Override
+ public boolean isApplicable(BlockData data) {
+ return handler.isApplicable(data);
+ }
+
@Override
public void toBukkit(Block block) {
J.s(() -> handler.toBukkit(block));
@@ -51,6 +71,8 @@ public class LegacyTileData extends TileData {
}
private interface Handler {
+ Material getMaterial();
+ boolean isApplicable(BlockData data);
void toBinary(DataOutputStream out) throws IOException;
void toBukkit(Block block);
}
@@ -72,6 +94,16 @@ public class LegacyTileData extends TileData {
dyeColor = DyeColor.values()[in.readByte()];
}
+ @Override
+ public Material getMaterial() {
+ return Material.OAK_SIGN;
+ }
+
+ @Override
+ public boolean isApplicable(BlockData data) {
+ return Tag.ALL_SIGNS.isTagged(data.getMaterial());
+ }
+
@Override
public void toBinary(DataOutputStream out) throws IOException {
out.writeUTF(line1);
@@ -101,6 +133,16 @@ public class LegacyTileData extends TileData {
type = EntityType.values()[in.readShort()];
}
+ @Override
+ public Material getMaterial() {
+ return Material.SPAWNER;
+ }
+
+ @Override
+ public boolean isApplicable(BlockData data) {
+ return data.getMaterial() == Material.SPAWNER;
+ }
+
@Override
public void toBinary(DataOutputStream out) throws IOException {
out.writeShort(type.ordinal());
@@ -130,6 +172,16 @@ public class LegacyTileData extends TileData {
}
}
+ @Override
+ public Material getMaterial() {
+ return Material.WHITE_BANNER;
+ }
+
+ @Override
+ public boolean isApplicable(BlockData data) {
+ return Tag.BANNERS.isTagged(data.getMaterial());
+ }
+
@Override
public void toBinary(DataOutputStream out) throws IOException {
out.writeByte(baseColor.ordinal());