Fabric Parity Worldgen

This commit is contained in:
Brian Neumann-Fopiano
2026-06-12 01:36:34 -04:00
parent 26d9115904
commit 2bac948edb
34 changed files with 3915 additions and 34 deletions
@@ -339,9 +339,13 @@ final class DecoratorCore {
static PlatformBlockState fixFacesForHunk(PlatformBlockState b, Hunk<PlatformBlockState> hunk, int rX, int rZ,
int x, int y, int z, EngineMantle mantle) {
if (!BUKKIT_PRESENT || !B.isVineBlock(b)) {
if (!B.isVineBlock(b)) {
return b;
}
if (!BUKKIT_PRESENT) {
DecoratorPlatformHooks.FaceFixer fixer = DecoratorPlatformHooks.faceFixer();
return fixer == null ? b : fixer.fixFaces(b, hunk, rX, rZ, x, y, z, mantle);
}
BlockData rawB = (BlockData) b.nativeHandle();
BlockData cloned = rawB.clone();
MultipleFacing data = (MultipleFacing) cloned;
@@ -392,7 +396,8 @@ final class DecoratorCore {
static boolean canGoOn(PlatformBlockState decorator, PlatformBlockState surface) {
if (!BUKKIT_PRESENT) {
return B.isSolid(surface);
DecoratorPlatformHooks.SurfaceSturdiness sturdiness = DecoratorPlatformHooks.surfaceSturdiness();
return sturdiness == null ? B.isSolid(surface) : sturdiness.canGoOn(surface);
}
return ((BlockData) surface.nativeHandle()).isFaceSturdy(BlockFace.UP, BlockSupport.FULL);
}
@@ -0,0 +1,52 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2026 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 art.arcane.iris.engine.decorator;
import art.arcane.iris.engine.mantle.EngineMantle;
import art.arcane.iris.spi.PlatformBlockState;
import art.arcane.iris.util.project.hunk.Hunk;
public final class DecoratorPlatformHooks {
private static volatile FaceFixer FACE_FIXER = null;
private static volatile SurfaceSturdiness SURFACE_STURDINESS = null;
private DecoratorPlatformHooks() {
}
public interface FaceFixer {
PlatformBlockState fixFaces(PlatformBlockState state, Hunk<PlatformBlockState> hunk, int rX, int rZ, int x, int y, int z, EngineMantle mantle);
}
public interface SurfaceSturdiness {
boolean canGoOn(PlatformBlockState surface);
}
public static void bind(FaceFixer faceFixer, SurfaceSturdiness surfaceSturdiness) {
FACE_FIXER = faceFixer;
SURFACE_STURDINESS = surfaceSturdiness;
}
static FaceFixer faceFixer() {
return FACE_FIXER;
}
static SurfaceSturdiness surfaceSturdiness() {
return SURFACE_STURDINESS;
}
}
@@ -137,9 +137,9 @@ public final class StructureAssembler {
cb.getPosition().getY() - center.getY(),
cb.getPosition().getZ() - center.getZ());
IrisPosition rcr = rot.rotate(cr, 0, 0, 0);
int wcx = c.wx + c.facing.toVector().getBlockX();
int wcy = c.wy + c.facing.toVector().getBlockY();
int wcz = c.wz + c.facing.toVector().getBlockZ();
int wcx = c.wx + c.facing.x();
int wcy = c.wy + c.facing.y();
int wcz = c.wz + c.facing.z();
int px = wcx - rcr.getX();
int py = wcy - rcr.getY();
int pz = wcz - rcr.getZ();
@@ -7,12 +7,21 @@ import org.bukkit.block.data.BlockData;
import java.util.function.Function;
final class BlockDataMergeSupport {
public final class BlockDataMergeSupport {
private static final boolean BUKKIT_PRESENT = detectBukkit();
private static volatile StateMerger FALLBACK_MERGER = null;
private BlockDataMergeSupport() {
}
public interface StateMerger {
PlatformBlockState merge(PlatformBlockState base, PlatformBlockState update);
}
public static void bindFallbackMerger(StateMerger merger) {
FALLBACK_MERGER = merger;
}
private static boolean detectBukkit() {
try {
Class.forName("org.bukkit.Bukkit", false, BlockDataMergeSupport.class.getClassLoader());
@@ -24,7 +33,8 @@ final class BlockDataMergeSupport {
static PlatformBlockState merge(PlatformBlockState base, PlatformBlockState update) {
if (!BUKKIT_PRESENT) {
return mergeByKey(base, update);
StateMerger merger = FALLBACK_MERGER;
return merger == null ? mergeByKey(base, update) : merger.merge(base, update);
}
BlockData merged = merge((BlockData) base.nativeHandle(), (BlockData) update.nativeHandle(), BukkitBlockResolution::get);
return merged == null ? null : BukkitBlockState.of(merged);
@@ -26,7 +26,6 @@ import art.arcane.iris.core.loader.IrisRegistrant;
import art.arcane.iris.engine.data.cache.AtomicCache;
import art.arcane.iris.engine.object.annotations.*;
import art.arcane.iris.platform.bukkit.BukkitBlockState;
import art.arcane.iris.platform.bukkit.BukkitPlatform;
import art.arcane.iris.spi.IrisLogging;
import art.arcane.iris.spi.PlatformBlockState;
import art.arcane.volmlib.util.collection.KList;
@@ -39,8 +38,6 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import java.util.Map;
@@ -201,8 +198,11 @@ public class IrisBlockData extends IrisRegistrant {
public TileData tryGetTile(IrisData data) {
//TODO Do like a registry thing with the tile data registry. Also update the parsing of data to include **block** entities.
Material type = ((BlockData) getBlockData(data).nativeHandle()).getMaterial();
if (type == Material.SPAWNER && this.data.containsKey("entitySpawn")) {
PlatformBlockState state = getBlockData(data);
String stateKey = state.key();
int bracket = stateKey.indexOf('[');
String blockKey = bracket >= 0 ? stateKey.substring(0, bracket) : stateKey;
if (blockKey.equals("minecraft:spawner") && this.data.containsKey("entitySpawn")) {
String id = (String) this.data.get("entitySpawn");
if (tileData == null) tileData = new KMap<>();
KMap<String, Object> spawnData = (KMap<String, Object>) tileData.computeIfAbsent("SpawnData", k -> new KMap<>());
@@ -210,9 +210,9 @@ public class IrisBlockData extends IrisRegistrant {
entity.putIfAbsent("id", Identifier.fromString(id).toString());
}
if (!BukkitPlatform.hasTile(type) || tileData == null || tileData.isEmpty())
if (tileData == null || tileData.isEmpty() || !state.hasTileEntity())
return null;
return new TileData(type, this.tileData);
return TileData.of(state, this.tileData);
}
private String keyify(String dat) {
@@ -48,6 +48,15 @@ import java.util.Map;
@Data
public class IrisObjectRotation {
private static final boolean BUKKIT_PRESENT = detectBukkit();
private static volatile StateRotator FALLBACK_ROTATOR = null;
public interface StateRotator {
PlatformBlockState rotate(IrisObjectRotation rotation, PlatformBlockState state, int spinx, int spiny, int spinz);
}
public static void bindFallbackRotator(StateRotator rotator) {
FALLBACK_ROTATOR = rotator;
}
private static boolean detectBukkit() {
try {
@@ -278,7 +287,8 @@ public class IrisObjectRotation {
}
if (!BUKKIT_PRESENT) {
return state;
StateRotator rotator = FALLBACK_ROTATOR;
return rotator == null ? state : rotator.rotate(this, state, spinx, spiny, spinz);
}
BlockData raw = ((BlockData) state.nativeHandle()).clone();
@@ -19,6 +19,7 @@
package art.arcane.iris.engine.object;
import art.arcane.iris.spi.IrisLogging;
import art.arcane.iris.spi.PlatformBlockState;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.Strictness;
@@ -43,6 +44,25 @@ import java.io.IOException;
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class TileData implements Cloneable {
private static final Gson gson = new GsonBuilder().disableHtmlEscaping().setStrictness(Strictness.LENIENT).create();
private static final boolean BUKKIT_PRESENT = detectBukkit();
private static volatile TileReader FALLBACK_READER = null;
public interface TileReader {
TileData read(DataInputStream in) throws IOException;
}
public static void bindFallbackReader(TileReader reader) {
FALLBACK_READER = reader;
}
private static boolean detectBukkit() {
try {
Class.forName("org.bukkit.Bukkit", false, TileData.class.getClassLoader());
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
@NonNull
private Material material;
@@ -67,7 +87,24 @@ public class TileData implements Cloneable {
return new TileData().fromBukkit(block);
}
public static TileData of(PlatformBlockState state, KMap<String, Object> properties) {
if (!BUKKIT_PRESENT) {
return null;
}
Object handle = state.nativeHandle();
if (!(handle instanceof BlockData blockData)) {
return null;
}
return new TileData(blockData.getMaterial(), properties);
}
public static TileData read(DataInputStream in) throws IOException {
if (!BUKKIT_PRESENT) {
TileReader reader = FALLBACK_READER;
if (reader != null) {
return reader.read(in);
}
}
if (!in.markSupported())
throw new IOException("Mark not supported");
in.mark(Integer.MAX_VALUE);