Merge remote-tracking branch 'origin/master' into ver/6.0.0

# Conflicts:
#	build.gradle.kts
#	common/src/main/java/com/dfsek/terra/api/TerraPlugin.java
#	common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java
#	common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java
#	common/src/main/java/com/dfsek/terra/profiler/Profiler.java
#	common/src/main/java/com/dfsek/terra/profiler/ProfilerImpl.java
#	common/src/main/java/com/dfsek/terra/registry/OpenRegistry.java
#	common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator3D.java
#	common/src/main/java/com/dfsek/terra/world/population/FloraPopulator.java
#	common/src/main/java/com/dfsek/terra/world/population/OrePopulator.java
#	common/src/main/java/com/dfsek/terra/world/population/StructurePopulator.java
#	common/src/main/java/com/dfsek/terra/world/population/TreePopulator.java
#	common/src/test/java/biome/DistributionTest.java
#	common/src/test/java/biome/ImageTest.java
#	platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/PopulationManager.java
#	platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java
#	platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/FabricTree.java
This commit is contained in:
dfsek
2021-05-09 22:20:47 -07:00
162 changed files with 4123 additions and 1179 deletions

View File

@@ -1,16 +1,100 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.block.Axis;
import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.block.data.Bisected;
import com.dfsek.terra.api.platform.block.data.Slab;
import com.dfsek.terra.api.platform.block.data.Stairs;
import com.dfsek.terra.api.platform.block.state.Container;
import com.dfsek.terra.api.platform.block.state.MobSpawner;
import com.dfsek.terra.api.platform.block.state.Sign;
import com.dfsek.terra.fabric.block.FabricBlockData;
import com.dfsek.terra.fabric.block.data.FabricDirectional;
import com.dfsek.terra.fabric.block.data.FabricMultipleFacing;
import com.dfsek.terra.fabric.block.data.FabricOrientable;
import com.dfsek.terra.fabric.block.data.FabricRotatable;
import com.dfsek.terra.fabric.block.data.FabricSlab;
import com.dfsek.terra.fabric.block.data.FabricStairs;
import com.dfsek.terra.fabric.block.data.FabricWaterlogged;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.LootableContainerBlockEntity;
import net.minecraft.block.entity.MobSpawnerBlockEntity;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.block.enums.BlockHalf;
import net.minecraft.block.enums.SlabType;
import net.minecraft.block.enums.StairShape;
import net.minecraft.state.property.Properties;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.WorldAccess;
import java.util.Arrays;
public final class FabricAdapter {
public static BlockPos adapt(Vector3 v) {
return new BlockPos(v.getBlockX(), v.getBlockY(), v.getBlockZ());
}
public static Vector3 adapt(BlockPos pos) {
return new Vector3(pos.getX(), pos.getY(), pos.getZ());
}
public static FabricBlockData adapt(BlockState state) {
if(state.contains(Properties.STAIR_SHAPE)) return new FabricStairs(state);
if(state.contains(Properties.SLAB_TYPE)) return new FabricSlab(state);
if(state.contains(Properties.AXIS)) return new FabricOrientable(state, Properties.AXIS);
if(state.contains(Properties.HORIZONTAL_AXIS)) return new FabricOrientable(state, Properties.HORIZONTAL_AXIS);
if(state.contains(Properties.ROTATION)) return new FabricRotatable(state);
if(state.contains(Properties.FACING)) return new FabricDirectional(state, Properties.FACING);
if(state.contains(Properties.HOPPER_FACING)) return new FabricDirectional(state, Properties.HOPPER_FACING);
if(state.contains(Properties.HORIZONTAL_FACING)) return new FabricDirectional(state, Properties.HORIZONTAL_FACING);
if(state.getProperties().containsAll(Arrays.asList(Properties.NORTH, Properties.SOUTH, Properties.EAST, Properties.WEST)))
return new FabricMultipleFacing(state);
if(state.contains(Properties.WATERLOGGED)) return new FabricWaterlogged(state);
return new FabricBlockData(state);
}
public static Direction adapt(BlockFace face) {
switch(face) {
case NORTH:
return Direction.NORTH;
case WEST:
return Direction.WEST;
case SOUTH:
return Direction.SOUTH;
case EAST:
return Direction.EAST;
case UP:
return Direction.UP;
case DOWN:
return Direction.DOWN;
default:
throw new IllegalArgumentException("Illegal direction: " + face);
}
}
public static com.dfsek.terra.api.platform.block.state.BlockState adapt(com.dfsek.terra.api.platform.block.Block block) {
WorldAccess worldAccess = (WorldAccess) block.getLocation().getWorld();
BlockEntity entity = worldAccess.getBlockEntity(adapt(block.getLocation().toVector()));
if(entity instanceof SignBlockEntity) {
return (Sign) entity;
} else if(entity instanceof MobSpawnerBlockEntity) {
return (MobSpawner) entity;
} else if(entity instanceof LootableContainerBlockEntity) {
return (Container) entity;
}
return null;
}
public final class FabricEnumAdapter {
public static Stairs.Shape adapt(StairShape shape) {
switch(shape) {
case OUTER_RIGHT:
@@ -99,25 +183,6 @@ public final class FabricEnumAdapter {
}
}
public static Direction adapt(BlockFace face) {
switch(face) {
case SOUTH:
return Direction.SOUTH;
case NORTH:
return Direction.NORTH;
case EAST:
return Direction.EAST;
case WEST:
return Direction.WEST;
case UP:
return Direction.UP;
case DOWN:
return Direction.DOWN;
default:
throw new IllegalArgumentException();
}
}
public static SlabType adapt(Slab.Type type) {
switch(type) {
case DOUBLE:

View File

@@ -18,6 +18,7 @@ import com.dfsek.terra.api.event.annotations.Priority;
import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.platform.CommandSender;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.platform.handle.ItemHandle;
import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.platform.world.Tree;
@@ -48,12 +49,22 @@ import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator;
import com.dfsek.terra.fabric.world.generator.FabricChunkGeneratorWrapper;
import com.dfsek.terra.profiler.Profiler;
import com.dfsek.terra.profiler.ProfilerImpl;
import com.dfsek.terra.fabric.handle.FabricItemHandle;
import com.dfsek.terra.fabric.handle.FabricWorldHandle;
import com.dfsek.terra.fabric.mixin.access.BiomeEffectsAccessor;
import com.dfsek.terra.fabric.mixin.access.GeneratorTypeAccessor;
import com.dfsek.terra.fabric.generation.TerraBiomeSource;
import com.dfsek.terra.fabric.generation.PopulatorFeature;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.profiler.Profiler;
import com.dfsek.terra.profiler.ProfilerImpl;
import com.dfsek.terra.registry.exception.DuplicateEntryException;
import com.dfsek.terra.registry.master.AddonRegistry;
import com.dfsek.terra.registry.master.ConfigRegistry;
import com.dfsek.terra.world.TerraWorld;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
@@ -77,7 +88,6 @@ import net.minecraft.world.gen.decorator.Decorator;
import net.minecraft.world.gen.decorator.NopeDecoratorConfig;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.ConfiguredFeatures;
import net.minecraft.world.gen.feature.DefaultBiomeFeatures;
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import net.minecraft.world.gen.feature.FeatureConfig;
import net.minecraft.world.gen.surfacebuilder.SurfaceBuilder;
@@ -158,10 +168,16 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
public TerraWorld getWorld(World world) {
return worldMap.computeIfAbsent(world.getSeed(), w -> {
logger.info("Loading world " + w);
return new TerraWorld(world, ((FabricChunkGeneratorWrapper) ((FabricChunkGenerator) world.getGenerator()).getHandle()).getPack(), this);
return new TerraWorld(world, ((FabricChunkGeneratorWrapper) world.getGenerator()).getPack(), this);
});
}
public TerraWorld getWorld(long seed) {
TerraWorld world = worldMap.get(seed);
if(world == null) throw new IllegalArgumentException("No world exists with seed " + seed);
return world;
}
@Override
public Logger logger() {
return logger;
@@ -243,41 +259,37 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
genericLoaders.register(registry);
registry
.registerLoader(BlockData.class, (t, o, l) -> worldHandle.createBlockData((String) o))
.registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> new FabricBiome(biomeFixer.translate((String) o)));
.registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> biomeFixer.translate((String) o));
}
private Biome createBiome(BiomeBuilder biome) {
SpawnSettings.Builder spawnSettings = new SpawnSettings.Builder();
DefaultBiomeFeatures.addFarmAnimals(spawnSettings);
DefaultBiomeFeatures.addMonsters(spawnSettings, 95, 5, 100);
BiomeTemplate template = biome.getTemplate();
Map<String, Integer> colors = template.getColors();
Biome vanilla = ((FabricBiome) new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0)).getHandle();
Biome vanilla = (Biome) (new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0)).getHandle();
GenerationSettings.Builder generationSettings = new GenerationSettings.Builder();
generationSettings.surfaceBuilder(SurfaceBuilder.DEFAULT.withConfig(new TernarySurfaceConfig(Blocks.GRASS_BLOCK.getDefaultState(), Blocks.DIRT.getDefaultState(), Blocks.GRAVEL.getDefaultState()))); // It needs a surfacebuilder, even though we dont use it.
generationSettings.feature(GenerationStep.Feature.VEGETAL_DECORATION, POPULATOR_CONFIGURED_FEATURE);
BiomeEffectsAccessor accessor = (BiomeEffectsAccessor) vanilla.getEffects();
BiomeEffects.Builder effects = new BiomeEffects.Builder()
.waterColor(colors.getOrDefault("water", vanilla.getEffects().waterColor))
.waterFogColor(colors.getOrDefault("water-fog", vanilla.getEffects().waterFogColor))
.fogColor(colors.getOrDefault("fog", vanilla.getEffects().fogColor))
.skyColor(colors.getOrDefault("sky", vanilla.getEffects().skyColor))
.grassColorModifier(vanilla.getEffects().grassColorModifier);
.waterColor(colors.getOrDefault("water", accessor.getWaterColor()))
.waterFogColor(colors.getOrDefault("water-fog", accessor.getWaterFogColor()))
.fogColor(colors.getOrDefault("fog", accessor.getFogColor()))
.skyColor(colors.getOrDefault("sky", accessor.getSkyColor()))
.grassColorModifier(accessor.getGrassColorModifier());
if(colors.containsKey("grass")) {
effects.grassColor(colors.get("grass"));
} else {
vanilla.getEffects().grassColor.ifPresent(effects::grassColor);
accessor.getGrassColor().ifPresent(effects::grassColor);
}
vanilla.getEffects().foliageColor.ifPresent(effects::foliageColor);
if(colors.containsKey("foliage")) {
effects.foliageColor(colors.get("foliage"));
} else {
vanilla.getEffects().foliageColor.ifPresent(effects::foliageColor);
accessor.getFoliageColor().ifPresent(effects::foliageColor);
}
return new Biome.Builder()
@@ -288,7 +300,7 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
.temperature(vanilla.getTemperature())
.downfall(vanilla.getDownfall())
.effects(effects.build())
.spawnSettings(spawnSettings.build())
.spawnSettings(vanilla.getSpawnSettings())
.generationSettings(generationSettings.build())
.build();
}
@@ -330,7 +342,7 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
};
//noinspection ConstantConditions
((GeneratorTypeAccessor) generatorType).setTranslationKey(new LiteralText("Terra:" + pack.getTemplate().getID()));
GeneratorTypeAccessor.getVALUES().add(generatorType);
GeneratorTypeAccessor.getValues().add(generatorType);
});
}
@@ -362,7 +374,11 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
private RequiredArgumentBuilder<ServerCommandSource, String> assemble(RequiredArgumentBuilder<ServerCommandSource, String> in, CommandManager manager) {
return in.suggests((context, builder) -> {
List<String> args = parseCommand(context.getInput());
CommandSender sender = FabricAdapter.adapt(context.getSource());
CommandSender sender = (CommandSender) context.getSource();
try {
sender = (Entity) context.getSource().getEntityOrThrow();
} catch(CommandSyntaxException ignore) {
}
try {
manager.tabComplete(args.remove(0), sender, args).forEach(builder::suggest);
} catch(CommandException e) {
@@ -371,8 +387,13 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
return builder.buildFuture();
}).executes(context -> {
List<String> args = parseCommand(context.getInput());
CommandSender sender = (CommandSender) context.getSource();
try {
manager.execute(args.remove(0), FabricAdapter.adapt(context.getSource()), args);
sender = (Entity) context.getSource().getEntityOrThrow();
} catch(CommandSyntaxException ignore) {
}
try {
manager.execute(args.remove(0), sender, args);
} catch(CommandException e) {
context.getSource().sendError(new LiteralText(e.getMessage()));
}
@@ -443,7 +464,7 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
private void injectTree(CheckedRegistry<Tree> registry, String id, ConfiguredFeature<?, ?> tree) {
try {
registry.add(id, new FabricTree(tree));
registry.add(id, (Tree) tree);
} catch(DuplicateEntryException ignore) {
}
}

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.fabric.world.block;
package com.dfsek.terra.fabric.block;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.Block;
@@ -6,9 +6,8 @@ import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.block.BlockType;
import com.dfsek.terra.api.platform.block.state.BlockState;
import com.dfsek.terra.fabric.world.FabricAdapter;
import com.dfsek.terra.fabric.world.block.state.FabricBlockState;
import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.fabric.FabricAdapter;
import net.minecraft.block.FluidBlock;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.WorldAccess;
@@ -35,7 +34,7 @@ public class FabricBlock implements Block {
@Override
public BlockState getState() {
return FabricBlockState.newInstance(this);
return FabricAdapter.adapt(this);
}
@Override
@@ -51,7 +50,7 @@ public class FabricBlock implements Block {
@Override
public Location getLocation() {
return FabricAdapter.adapt(delegate.position).toLocation(new FabricWorldAccess(delegate.worldAccess));
return FabricAdapter.adapt(delegate.position).toLocation((World) delegate.worldAccess);
}
@Override

View File

@@ -1,11 +1,10 @@
package com.dfsek.terra.fabric.world.block;
package com.dfsek.terra.fabric.block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.BlockType;
import com.dfsek.terra.fabric.world.FabricAdapter;
import com.dfsek.terra.fabric.mixin.access.StateAccessor;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.state.State;
import net.minecraft.util.registry.Registry;
import java.util.stream.Collectors;
@@ -19,7 +18,7 @@ public class FabricBlockData implements BlockData {
@Override
public BlockType getBlockType() {
return FabricAdapter.adapt(delegate.getBlock());
return (BlockType) delegate.getBlock();
}
@Override
@@ -41,7 +40,7 @@ public class FabricBlockData implements BlockData {
StringBuilder data = new StringBuilder(Registry.BLOCK.getId(delegate.getBlock()).toString());
if(!delegate.getEntries().isEmpty()) {
data.append('[');
data.append(delegate.getEntries().entrySet().stream().map(State.PROPERTY_MAP_PRINTER).collect(Collectors.joining(",")));
data.append(delegate.getEntries().entrySet().stream().map(StateAccessor.getPropertyMapPrinter()).collect(Collectors.joining(",")));
data.append(']');
}
return data.toString();

View File

@@ -1,7 +1,7 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.data.AnaloguePowerable;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import com.dfsek.terra.fabric.block.FabricBlockData;
import net.minecraft.block.BlockState;
/**

View File

@@ -1,9 +1,9 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.block.data.Directional;
import com.dfsek.terra.fabric.world.FabricAdapter;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import com.dfsek.terra.fabric.FabricAdapter;
import com.dfsek.terra.fabric.block.FabricBlockData;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.DirectionProperty;

View File

@@ -1,8 +1,8 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.block.data.MultipleFacing;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import com.dfsek.terra.fabric.block.FabricBlockData;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Properties;

View File

@@ -1,8 +1,9 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.Axis;
import com.dfsek.terra.api.platform.block.data.Orientable;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import com.dfsek.terra.fabric.FabricAdapter;
import com.dfsek.terra.fabric.block.FabricBlockData;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.EnumProperty;
import net.minecraft.util.math.Direction;
@@ -26,11 +27,11 @@ public class FabricOrientable extends FabricBlockData implements Orientable {
@Override
public Axis getAxis() {
return FabricEnumAdapter.adapt(getHandle().get(property));
return FabricAdapter.adapt(getHandle().get(property));
}
@Override
public void setAxis(Axis axis) {
delegate = delegate.with(property, FabricEnumAdapter.adapt(axis));
delegate = delegate.with(property, FabricAdapter.adapt(axis));
}
}

View File

@@ -1,8 +1,8 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.block.data.Rotatable;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import com.dfsek.terra.fabric.block.FabricBlockData;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Properties;

View File

@@ -1,6 +1,7 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.data.Slab;
import com.dfsek.terra.fabric.FabricAdapter;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Properties;
@@ -11,11 +12,11 @@ public class FabricSlab extends FabricWaterlogged implements Slab {
@Override
public Type getType() {
return FabricEnumAdapter.adapt(delegate.get(Properties.SLAB_TYPE));
return FabricAdapter.adapt(delegate.get(Properties.SLAB_TYPE));
}
@Override
public void setType(Type type) {
delegate = delegate.with(Properties.SLAB_TYPE, FabricEnumAdapter.adapt(type));
delegate = delegate.with(Properties.SLAB_TYPE, FabricAdapter.adapt(type));
}
}

View File

@@ -1,7 +1,8 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.block.data.Stairs;
import com.dfsek.terra.fabric.FabricAdapter;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Properties;
@@ -12,31 +13,31 @@ public class FabricStairs extends FabricWaterlogged implements Stairs {
@Override
public Shape getShape() {
return FabricEnumAdapter.adapt(getHandle().get(Properties.STAIR_SHAPE));
return FabricAdapter.adapt(getHandle().get(Properties.STAIR_SHAPE));
}
@Override
public void setShape(Shape shape) {
super.delegate = getHandle().with(Properties.STAIR_SHAPE, FabricEnumAdapter.adapt(shape));
super.delegate = getHandle().with(Properties.STAIR_SHAPE, FabricAdapter.adapt(shape));
}
@Override
public Half getHalf() {
return FabricEnumAdapter.adapt(getHandle().get(Properties.BLOCK_HALF));
return FabricAdapter.adapt(getHandle().get(Properties.BLOCK_HALF));
}
@Override
public void setHalf(Half half) {
super.delegate = getHandle().with(Properties.BLOCK_HALF, FabricEnumAdapter.adapt(half));
super.delegate = getHandle().with(Properties.BLOCK_HALF, FabricAdapter.adapt(half));
}
@Override
public BlockFace getFacing() {
return FabricEnumAdapter.adapt(getHandle().get(Properties.HORIZONTAL_FACING));
return FabricAdapter.adapt(getHandle().get(Properties.HORIZONTAL_FACING));
}
@Override
public void setFacing(BlockFace facing) {
super.delegate = getHandle().with(Properties.HORIZONTAL_FACING, FabricEnumAdapter.adapt(facing));
super.delegate = getHandle().with(Properties.HORIZONTAL_FACING, FabricAdapter.adapt(facing));
}
}

View File

@@ -1,7 +1,7 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.data.Waterlogged;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import com.dfsek.terra.fabric.block.FabricBlockData;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Properties;

View File

@@ -1,7 +0,0 @@
package com.dfsek.terra.fabric.command;
public class FabricCommandAdapter {
public static void register() {
}
}

View File

@@ -1,17 +0,0 @@
package com.dfsek.terra.fabric.command;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class StringListArgumentType implements ArgumentType<List<String>> {
@Override
public List<String> parse(StringReader reader) {
final String text = reader.getRemaining();
reader.setCursor(reader.getTotalLength());
return new ArrayList<>(Arrays.asList(text.split(" ")));
}
}

View File

@@ -1,25 +1,29 @@
package com.dfsek.terra.fabric.world.generator;
package com.dfsek.terra.fabric.generation;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.generator.ChunkData;
import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.api.world.locate.AsyncStructureFinder;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.fabric.FabricAdapter;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.world.TerraBiomeSource;
import com.dfsek.terra.fabric.world.handles.world.FabricSeededWorldAccess;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D;
import com.dfsek.terra.world.population.CavePopulator;
import com.dfsek.terra.world.population.FloraPopulator;
import com.dfsek.terra.world.population.OrePopulator;
import com.dfsek.terra.world.population.StructurePopulator;
import com.dfsek.terra.world.population.TreePopulator;
import com.dfsek.terra.world.generation.math.samplers.Sampler;
import com.dfsek.terra.world.population.items.TerraStructure;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.jafama.FastMath;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.structure.StructureManager;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.BlockView;
import net.minecraft.world.ChunkRegion;
import net.minecraft.world.Heightmap;
@@ -31,6 +35,12 @@ import net.minecraft.world.gen.StructureAccessor;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.gen.chunk.StructuresConfig;
import net.minecraft.world.gen.chunk.VerticalBlockSample;
import net.minecraft.world.gen.feature.StructureFeature;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class FabricChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper {
private final long seed;
@@ -77,6 +87,28 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener
}
@Nullable
@Override
public BlockPos locateStructure(ServerWorld world, StructureFeature<?> feature, BlockPos center, int radius, boolean skipExistingChunks) {
String name = Objects.requireNonNull(Registry.STRUCTURE_FEATURE.getId(feature)).toString();
TerraWorld terraWorld = TerraFabricPlugin.getInstance().getWorld((World) world);
TerraStructure located = pack.getStructure(pack.getTemplate().getLocatable().get(name));
if(located != null) {
CompletableFuture<BlockPos> result = new CompletableFuture<>();
AsyncStructureFinder finder = new AsyncStructureFinder(terraWorld.getBiomeProvider(), located, FabricAdapter.adapt(center).toLocation((World) world), 0, 500, location -> {
result.complete(FabricAdapter.adapt(location));
}, TerraFabricPlugin.getInstance());
finder.run(); // Do this synchronously.
try {
return result.get();
} catch(InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
TerraFabricPlugin.getInstance().logger().warning("No overrides are defined for \"" + name + "\"");
return null;
}
@Override
public void generateFeatures(ChunkRegion region, StructureAccessor accessor) {
super.generateFeatures(region, accessor);
@@ -84,8 +116,7 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener
@Override
public void populateNoise(WorldAccess world, StructureAccessor accessor, Chunk chunk) {
FabricSeededWorldAccess worldAccess = new FabricSeededWorldAccess(world, seed, this);
delegate.generateChunkData(worldAccess, new FastRandom(), chunk.getPos().x, chunk.getPos().z, new FabricChunkData(chunk));
delegate.generateChunkData((World) world, new FastRandom(), chunk.getPos().x, chunk.getPos().z, (ChunkData) chunk);
}
@Override
@@ -107,7 +138,18 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener
@Override
public int getHeight(int x, int z, Heightmap.Type heightmapType) {
return 0;
TerraWorld world = TerraFabricPlugin.getInstance().getWorld(seed);
Sampler sampler = world.getConfig().getSamplerCache().getChunk(FastMath.floorDiv(x, 16), FastMath.floorDiv(z, 16));
int cx = FastMath.floorMod(x, 16);
int cz = FastMath.floorMod(z, 16);
int height = world.getWorld().getMaxHeight();
while (height >= 0 && sampler.sample(cx, height - 1, cz) < 0) {
height--;
}
return height;
}
@Override

View File

@@ -1,10 +1,8 @@
package com.dfsek.terra.fabric.world.features;
package com.dfsek.terra.fabric.generation;
import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator;
import com.dfsek.terra.fabric.world.generator.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.world.handles.FabricWorld;
import com.dfsek.terra.fabric.world.handles.chunk.FabricChunkWorldAccess;
import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.mojang.serialization.Codec;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.StructureWorldAccess;
@@ -25,9 +23,7 @@ public class PopulatorFeature extends Feature<DefaultFeatureConfig> {
@Override
public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) {
FabricChunkGeneratorWrapper gen = (FabricChunkGeneratorWrapper) chunkGenerator;
FabricChunkWorldAccess chunk = new FabricChunkWorldAccess(world, pos.getX() >> 4, pos.getZ() >> 4);
FabricWorld world1 = new FabricWorld(world.toServerWorld(), new FabricChunkGenerator(chunkGenerator));
gen.getHandle().getPopulators().forEach(populator -> populator.populate(world1, chunk));
gen.getHandle().getPopulators().forEach(populator -> populator.populate((World) world, (Chunk) world));
return true;
}
}

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.fabric.world;
package com.dfsek.terra.fabric.generation;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;

View File

@@ -1,9 +1,8 @@
package com.dfsek.terra.fabric.inventory;
package com.dfsek.terra.fabric.handle;
import com.dfsek.terra.api.platform.handle.ItemHandle;
import com.dfsek.terra.api.platform.inventory.Item;
import com.dfsek.terra.api.platform.inventory.item.Enchantment;
import com.dfsek.terra.fabric.world.FabricAdapter;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.command.argument.ItemStackArgumentType;
@@ -18,7 +17,7 @@ public class FabricItemHandle implements ItemHandle {
@Override
public Item createItem(String data) {
try {
return FabricAdapter.adapt(new ItemStackArgumentType().parse(new StringReader(data)).getItem());
return (Item) new ItemStackArgumentType().parse(new StringReader(data)).getItem();
} catch(CommandSyntaxException e) {
throw new IllegalArgumentException("Invalid item data \"" + data + "\"", e);
}
@@ -26,11 +25,11 @@ public class FabricItemHandle implements ItemHandle {
@Override
public Enchantment getEnchantment(String id) {
return FabricAdapter.adapt(Registry.ENCHANTMENT.get(Identifier.tryParse(id)));
return (Enchantment) (Registry.ENCHANTMENT.get(Identifier.tryParse(id)));
}
@Override
public Set<Enchantment> getEnchantments() {
return Registry.ENCHANTMENT.stream().map(FabricAdapter::adapt).collect(Collectors.toSet());
return Registry.ENCHANTMENT.stream().map(enchantment -> (Enchantment) enchantment).collect(Collectors.toSet());
}
}

View File

@@ -1,8 +1,9 @@
package com.dfsek.terra.fabric.world;
package com.dfsek.terra.fabric.handle;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import com.dfsek.terra.fabric.FabricAdapter;
import com.dfsek.terra.fabric.block.FabricBlockData;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.block.BlockState;
@@ -30,6 +31,6 @@ public class FabricWorldHandle implements WorldHandle {
public EntityType getEntity(String id) {
Identifier identifier = Identifier.tryParse(id);
if(identifier == null) identifier = Identifier.tryParse("minecraft:" + id.toLowerCase(Locale.ROOT));
return FabricAdapter.adapt(Registry.ENTITY_TYPE.get(identifier));
return (EntityType) Registry.ENTITY_TYPE.get(identifier);
}
}

View File

@@ -1,41 +0,0 @@
package com.dfsek.terra.fabric.inventory;
import com.dfsek.terra.api.platform.inventory.ItemStack;
import com.dfsek.terra.api.platform.inventory.item.Enchantment;
import com.dfsek.terra.fabric.world.FabricAdapter;
import net.minecraft.util.registry.Registry;
import java.util.Objects;
public class FabricEnchantment implements Enchantment {
private final net.minecraft.enchantment.Enchantment enchantment;
public FabricEnchantment(net.minecraft.enchantment.Enchantment enchantment) {
this.enchantment = enchantment;
}
@Override
public net.minecraft.enchantment.Enchantment getHandle() {
return enchantment;
}
@Override
public boolean canEnchantItem(ItemStack itemStack) {
return enchantment.isAcceptableItem(FabricAdapter.adapt(itemStack));
}
@Override
public String getID() {
return Objects.requireNonNull(Registry.ENCHANTMENT.getId(enchantment)).toString();
}
@Override
public boolean conflictsWith(Enchantment other) {
return !enchantment.canCombine(FabricAdapter.adapt(other));
}
@Override
public int getMaxLevel() {
return enchantment.getMaxLevel();
}
}

View File

@@ -1,35 +0,0 @@
package com.dfsek.terra.fabric.inventory;
import com.dfsek.terra.api.platform.inventory.Inventory;
import com.dfsek.terra.api.platform.inventory.ItemStack;
import com.dfsek.terra.fabric.world.FabricAdapter;
import net.minecraft.item.Items;
public class FabricInventory implements Inventory {
private final net.minecraft.inventory.Inventory delegate;
public FabricInventory(net.minecraft.inventory.Inventory delegate) {
this.delegate = delegate;
}
@Override
public net.minecraft.inventory.Inventory getHandle() {
return delegate;
}
@Override
public int getSize() {
return delegate.size();
}
@Override
public ItemStack getItem(int slot) {
net.minecraft.item.ItemStack itemStack = delegate.getStack(slot);
return itemStack.getItem() == Items.AIR ? null : FabricAdapter.adapt(itemStack);
}
@Override
public void setItem(int slot, ItemStack newStack) {
delegate.setStack(slot, FabricAdapter.adapt(newStack));
}
}

View File

@@ -1,27 +0,0 @@
package com.dfsek.terra.fabric.inventory;
import com.dfsek.terra.api.platform.inventory.Item;
import com.dfsek.terra.api.platform.inventory.ItemStack;
public class FabricItem implements Item {
private final net.minecraft.item.Item delegate;
public FabricItem(net.minecraft.item.Item delegate) {
this.delegate = delegate;
}
@Override
public net.minecraft.item.Item getHandle() {
return delegate;
}
@Override
public ItemStack newItemStack(int amount) {
return new FabricItemStack(new net.minecraft.item.ItemStack(delegate, amount));
}
@Override
public double getMaxDurability() {
return delegate.getMaxDamage();
}
}

View File

@@ -1,46 +0,0 @@
package com.dfsek.terra.fabric.inventory;
import com.dfsek.terra.api.platform.inventory.Item;
import com.dfsek.terra.api.platform.inventory.ItemStack;
import com.dfsek.terra.api.platform.inventory.item.ItemMeta;
import com.dfsek.terra.fabric.inventory.meta.FabricDamageable;
import com.dfsek.terra.fabric.inventory.meta.FabricItemMeta;
public class FabricItemStack implements ItemStack {
private net.minecraft.item.ItemStack delegate;
public FabricItemStack(net.minecraft.item.ItemStack delegate) {
this.delegate = delegate;
}
@Override
public int getAmount() {
return delegate.getCount();
}
@Override
public void setAmount(int i) {
delegate.setCount(i);
}
@Override
public Item getType() {
return new FabricItem(delegate.getItem());
}
@Override
public ItemMeta getItemMeta() {
if(delegate.isDamageable()) return new FabricDamageable(delegate.copy());
return new FabricItemMeta(delegate.copy());
}
@Override
public void setItemMeta(ItemMeta meta) {
this.delegate = ((FabricItemMeta) meta).getHandle();
}
@Override
public net.minecraft.item.ItemStack getHandle() {
return delegate;
}
}

View File

@@ -1,25 +0,0 @@
package com.dfsek.terra.fabric.inventory.meta;
import com.dfsek.terra.api.platform.inventory.item.Damageable;
import net.minecraft.item.ItemStack;
public class FabricDamageable extends FabricItemMeta implements Damageable {
public FabricDamageable(ItemStack delegate) {
super(delegate);
}
@Override
public int getDamage() {
return delegate.getDamage();
}
@Override
public void setDamage(int damage) {
delegate.setDamage(damage);
}
@Override
public boolean hasDamage() {
return delegate.isDamageable();
}
}

View File

@@ -1,42 +0,0 @@
package com.dfsek.terra.fabric.inventory.meta;
import com.dfsek.terra.api.platform.inventory.item.Enchantment;
import com.dfsek.terra.api.platform.inventory.item.ItemMeta;
import com.dfsek.terra.fabric.world.FabricAdapter;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.registry.Registry;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class FabricItemMeta implements ItemMeta {
protected final ItemStack delegate;
public FabricItemMeta(ItemStack delegate) {
this.delegate = delegate;
}
@Override
public ItemStack getHandle() {
return delegate;
}
@Override
public Map<Enchantment, Integer> getEnchantments() {
if(!delegate.hasEnchantments()) return Collections.emptyMap();
Map<Enchantment, Integer> map = new HashMap<>();
delegate.getEnchantments().forEach(enchantment -> {
CompoundTag eTag = (CompoundTag) enchantment;
map.put(FabricAdapter.adapt(Registry.ENCHANTMENT.get(eTag.getInt("id"))), eTag.getInt("lvl"));
});
return map;
}
@Override
public void addEnchantment(Enchantment enchantment, int level) {
delegate.addEnchantment(FabricAdapter.adapt(enchantment), level);
}
}

View File

@@ -2,8 +2,8 @@ package com.dfsek.terra.fabric.mixin;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.world.TerraBiomeSource;
import com.dfsek.terra.fabric.world.generator.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.generation.TerraBiomeSource;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.google.common.base.MoreObjects;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.util.registry.Registry;
@@ -13,16 +13,17 @@ import net.minecraft.world.dimension.DimensionOptions;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.GeneratorOptions;
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Properties;
import java.util.Random;
// Mixins commented out until loom fixes multi-project builds.
//@Mixin(GeneratorOptions.class)
public class MixinGeneratorOptions {
//@Inject(method = "fromProperties(Lnet/minecraft/util/registry/DynamicRegistryManager;Ljava/util/Properties;)Lnet/minecraft/world/gen/GeneratorOptions;", at = @At("HEAD"), cancellable = true)
@Mixin(GeneratorOptions.class)
public abstract class GeneratorOptionsMixin {
@Inject(method = "fromProperties(Lnet/minecraft/util/registry/DynamicRegistryManager;Ljava/util/Properties;)Lnet/minecraft/world/gen/GeneratorOptions;", at = @At("HEAD"), cancellable = true)
private static void fromProperties(DynamicRegistryManager dynamicRegistryManager, Properties properties, CallbackInfoReturnable<GeneratorOptions> cir) {
if(properties.get("level-type") == null) {
return;

View File

@@ -0,0 +1,31 @@
package com.dfsek.terra.fabric.mixin.access;
import net.minecraft.world.biome.BiomeEffects;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.Optional;
@Mixin(BiomeEffects.class)
public interface BiomeEffectsAccessor {
@Accessor("fogColor")
int getFogColor();
@Accessor("waterColor")
int getWaterColor();
@Accessor("waterFogColor")
int getWaterFogColor();
@Accessor("skyColor")
int getSkyColor();
@Accessor("foliageColor")
Optional<Integer> getFoliageColor();
@Accessor("grassColor")
Optional<Integer> getGrassColor();
@Accessor("grassColorModifier")
BiomeEffects.GrassColorModifier getGrassColorModifier();
}

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.fabric.mixin;
package com.dfsek.terra.fabric.mixin.access;
import net.minecraft.client.world.GeneratorType;
import net.minecraft.text.Text;
@@ -10,12 +10,12 @@ import java.util.List;
@Mixin(GeneratorType.class)
public interface GeneratorTypeAccessor {
@Accessor
static List<GeneratorType> getVALUES() {
@Accessor("VALUES")
static List<GeneratorType> getValues() {
throw new UnsupportedOperationException();
}
@Mutable
@Accessor
@Accessor("translationKey")
void setTranslationKey(Text translationKey);
}

View File

@@ -0,0 +1,12 @@
package com.dfsek.terra.fabric.mixin.access;
import net.minecraft.util.Identifier;
import net.minecraft.world.MobSpawnerLogic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(MobSpawnerLogic.class)
public interface MobSpawnerLogicAccessor {
@Invoker("getEntityId")
Identifier callGetEntityId();
}

View File

@@ -0,0 +1,17 @@
package com.dfsek.terra.fabric.mixin.access;
import net.minecraft.state.State;
import net.minecraft.state.property.Property;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.Map;
import java.util.function.Function;
@Mixin(State.class)
public interface StateAccessor {
@Accessor("PROPERTY_MAP_PRINTER")
static Function<Map.Entry<Property<?>, Comparable<?>>, String> getPropertyMapPrinter() {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,14 @@
package com.dfsek.terra.fabric.mixin.implementations;
import net.minecraft.world.biome.Biome;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(Biome.class)
@Implements(@Interface(iface = com.dfsek.terra.api.platform.world.Biome.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class BiomeMixin {
public Object terra$getHandle() {
return this;
}
}

View File

@@ -0,0 +1,14 @@
package com.dfsek.terra.fabric.mixin.implementations;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(ChunkGenerator.class)
@Implements(@Interface(iface = com.dfsek.terra.api.platform.world.generator.ChunkGenerator.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ChunkGeneratorMixin {
public Object terra$getHandle() {
return this;
}
}

View File

@@ -0,0 +1,42 @@
package com.dfsek.terra.fabric.mixin.implementations;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.profiler.ProfileFrame;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.world.StructureWorldAccess;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Locale;
import java.util.Random;
@Mixin(ConfiguredFeature.class)
@Implements(@Interface(iface = Tree.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ConfiguredFeatureMixin {
@Shadow
public abstract boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos);
@SuppressWarnings({"ConstantConditions", "try"})
public boolean terra$plant(Location l, Random r) {
String id = BuiltinRegistries.CONFIGURED_FEATURE.getId((ConfiguredFeature<?, ?>) (Object) this).toString();
try(ProfileFrame ignore = TerraFabricPlugin.getInstance().getProfiler().profile("fabric_tree:" + id.toLowerCase(Locale.ROOT))) {
StructureWorldAccess fabricWorldAccess = ((StructureWorldAccess) l.getWorld());
ChunkGenerator generatorWrapper = (ChunkGenerator) l.getWorld().getGenerator();
return generate(fabricWorldAccess, generatorWrapper, r, new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()));
}
}
public MaterialSet terra$getSpawnable() {
return MaterialSet.get(TerraFabricPlugin.getInstance().getWorldHandle().createBlockData("minecraft:grass_block"),
TerraFabricPlugin.getInstance().getWorldHandle().createBlockData("minecraft:podzol"),
TerraFabricPlugin.getInstance().getWorldHandle().createBlockData("minecraft:mycelium"));
}
}

View File

@@ -0,0 +1,60 @@
package com.dfsek.terra.fabric.mixin.implementations.block;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.state.BlockState;
import com.dfsek.terra.fabric.FabricAdapter;
import com.dfsek.terra.fabric.block.FabricBlock;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(BlockEntity.class)
@Implements(@Interface(iface = BlockState.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class BlockEntityMixin {
@Shadow
protected BlockPos pos;
@Shadow
@Nullable
protected World world;
@Shadow
public abstract net.minecraft.block.BlockState getCachedState();
@Shadow
public abstract boolean hasWorld();
public Object terra$getHandle() {
return this;
}
public Block terra$getBlock() {
return new FabricBlock(pos, world);
}
public int terra$getX() {
return pos.getX();
}
public int terra$getY() {
return pos.getY();
}
public int terra$getZ() {
return pos.getZ();
}
public BlockData terra$getBlockData() {
return FabricAdapter.adapt(getCachedState());
}
public boolean terra$update(boolean applyPhysics) {
if(hasWorld()) world.getChunk(pos).setBlockEntity(pos, (BlockEntity) (Object) this);
return true;
}
}

View File

@@ -0,0 +1,36 @@
package com.dfsek.terra.fabric.mixin.implementations.block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.BlockType;
import com.dfsek.terra.fabric.FabricAdapter;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(Block.class)
@Implements(@Interface(iface = BlockType.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class BlockMixin {
@Shadow
private BlockState defaultState;
public Object terra$getHandle() {
return this;
}
public BlockData terra$getDefaultData() {
return FabricAdapter.adapt(defaultState);
}
public boolean terra$isSolid() {
return defaultState.isOpaque();
}
@SuppressWarnings("ConstantConditions")
public boolean terra$isWater() {
return ((Object) this) == Blocks.WATER;
}
}

View File

@@ -0,0 +1,21 @@
package com.dfsek.terra.fabric.mixin.implementations.block.state;
import com.dfsek.terra.api.platform.block.state.Container;
import com.dfsek.terra.api.platform.inventory.Inventory;
import com.dfsek.terra.fabric.mixin.implementations.block.BlockEntityMixin;
import net.minecraft.block.entity.LootableContainerBlockEntity;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(LootableContainerBlockEntity.class)
@Implements(@Interface(iface = Container.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class LootableContainerBlockEntityMixin extends BlockEntityMixin {
public Inventory terra$getInventory() {
return (Inventory) this;
}
public Object terra$getHandle() {
return this;
}
}

View File

@@ -0,0 +1,119 @@
package com.dfsek.terra.fabric.mixin.implementations.block.state;
import com.dfsek.terra.api.platform.block.state.MobSpawner;
import com.dfsek.terra.api.platform.block.state.SerialState;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.mixin.access.MobSpawnerLogicAccessor;
import net.minecraft.block.entity.MobSpawnerBlockEntity;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.MobSpawnerLogic;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(MobSpawnerBlockEntity.class)
@Implements(@Interface(iface = MobSpawner.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class MobSpawnerBlockEntityMixin {
@Shadow
public abstract MobSpawnerLogic getLogic();
public EntityType terra$getSpawnedType() {
return (EntityType) Registry.ENTITY_TYPE.get(((MobSpawnerLogicAccessor) getLogic()).callGetEntityId());
}
public void terra$setSpawnedType(@NotNull EntityType creatureType) {
getLogic().setEntityId((net.minecraft.entity.EntityType<?>) creatureType);
}
public int terra$getDelay() {
return 0;
}
public void terra$setDelay(int delay) {
}
public int terra$getMinSpawnDelay() {
return 0;
}
public void terra$setMinSpawnDelay(int delay) {
}
public int terra$getMaxSpawnDelay() {
return 0;
}
public void terra$setMaxSpawnDelay(int delay) {
}
public int terra$getSpawnCount() {
return 0;
}
public void terra$setSpawnCount(int spawnCount) {
}
public int terra$getMaxNearbyEntities() {
return 0;
}
public void terra$setMaxNearbyEntities(int maxNearbyEntities) {
}
public int terra$getRequiredPlayerRange() {
return 0;
}
public void terra$setRequiredPlayerRange(int requiredPlayerRange) {
}
public int terra$getSpawnRange() {
return 0;
}
public void terra$setSpawnRange(int spawnRange) {
}
public void terra$applyState(String state) {
SerialState.parse(state).forEach((k, v) -> {
switch(k) {
case "type":
terra$setSpawnedType(TerraFabricPlugin.getInstance().getWorldHandle().getEntity(v));
return;
case "delay":
terra$setDelay(Integer.parseInt(v));
return;
case "min_delay":
terra$setMinSpawnDelay(Integer.parseInt(v));
return;
case "max_delay":
terra$setMaxSpawnDelay(Integer.parseInt(v));
return;
case "spawn_count":
terra$setSpawnCount(Integer.parseInt(v));
return;
case "spawn_range":
terra$setSpawnRange(Integer.parseInt(v));
return;
case "max_nearby":
terra$setMaxNearbyEntities(Integer.parseInt(v));
return;
case "required_player_range":
terra$setRequiredPlayerRange(Integer.parseInt(v));
return;
default:
throw new IllegalArgumentException("Invalid property: " + k);
}
});
}
}

View File

@@ -0,0 +1,47 @@
package com.dfsek.terra.fabric.mixin.implementations.block.state;
import com.dfsek.terra.api.platform.block.state.SerialState;
import com.dfsek.terra.api.platform.block.state.Sign;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(SignBlockEntity.class)
@Implements(@Interface(iface = Sign.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class SignBlockEntityMixin {
@Shadow
public abstract void setTextOnRow(int row, Text text);
@Shadow
@Final
private Text[] text;
public @NotNull String[] terra$getLines() {
String[] lines = new String[text.length];
for(int i = 0; i < text.length; i++) {
lines[i] = text[i].asString();
}
return lines;
}
public @NotNull String terra$getLine(int index) throws IndexOutOfBoundsException {
return text[index].asString();
}
public void terra$setLine(int index, @NotNull String line) throws IndexOutOfBoundsException {
setTextOnRow(index, new LiteralText(line));
}
public void terra$applyState(String state) {
SerialState.parse(state).forEach((k, v) -> {
if(!k.startsWith("text")) throw new IllegalArgumentException("Invalid property: " + k);
terra$setLine(Integer.parseInt(k.substring(4)), v);
});
}
}

View File

@@ -0,0 +1,57 @@
package com.dfsek.terra.fabric.mixin.implementations.chunk;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.fabric.block.FabricBlock;
import com.dfsek.terra.fabric.block.FabricBlockData;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ChunkRegion;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ChunkRegion.class)
@Implements(@Interface(iface = Chunk.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ChunkRegionMixin {
@Final
@Shadow
private int centerChunkX;
@Final
@Shadow
private int centerChunkZ;
public int terra$getX() {
return centerChunkX;
}
public int terra$getZ() {
return centerChunkZ;
}
public World terra$getWorld() {
return (World) this;
}
public Block terra$getBlock(int x, int y, int z) {
BlockPos pos = new BlockPos(x + (centerChunkX << 4), y, z + (centerChunkZ << 4));
return new FabricBlock(pos, (ChunkRegion) (Object) this);
}
public @NotNull BlockData terra$getBlockData(int x, int y, int z) {
return terra$getBlock(x, y, z).getBlockData();
}
public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) {
((ChunkRegion) (Object) this).setBlockState(new BlockPos(x + (centerChunkX << 4), y, z + (centerChunkZ << 4)), ((FabricBlockData) blockData).getHandle(), 0);
}
public Object terra$getHandle() {
return this;
}
}

View File

@@ -0,0 +1,53 @@
package com.dfsek.terra.fabric.mixin.implementations.chunk;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.fabric.block.FabricBlock;
import com.dfsek.terra.fabric.block.FabricBlockData;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.WorldChunk;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(WorldChunk.class)
@Implements(@Interface(iface = Chunk.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class WorldChunkMixin {
@Final
@Shadow
private net.minecraft.world.World world;
public int terra$getX() {
return ((net.minecraft.world.chunk.Chunk) this).getPos().x;
}
public int terra$getZ() {
return ((net.minecraft.world.chunk.Chunk) this).getPos().z;
}
public World terra$getWorld() {
return (World) world;
}
public Block terra$getBlock(int x, int y, int z) {
BlockPos pos = new BlockPos(x + (terra$getX() << 4), y, z + (terra$getZ() << 4));
return new FabricBlock(pos, world);
}
public @NotNull BlockData terra$getBlockData(int x, int y, int z) {
return terra$getBlock(x, y, z).getBlockData();
}
public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) {
((net.minecraft.world.chunk.Chunk) this).setBlockState(new BlockPos(x, y, z), ((FabricBlockData) blockData).getHandle(), false);
}
public Object terra$getHandle() {
return this;
}
}

View File

@@ -0,0 +1,36 @@
package com.dfsek.terra.fabric.mixin.implementations.chunk.data;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.generator.ChunkData;
import com.dfsek.terra.fabric.block.FabricBlockData;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.ProtoChunk;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ProtoChunk.class)
@Implements(@Interface(iface = ChunkData.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ProtoChunkMixin {
@Shadow
public abstract BlockState getBlockState(BlockPos pos);
public @NotNull BlockData terra$getBlockData(int x, int y, int z) {
return new FabricBlockData(getBlockState(new BlockPos(x, y, z)));
}
public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) {
((net.minecraft.world.chunk.Chunk) this).setBlockState(new BlockPos(x, y, z), ((FabricBlockData) blockData).getHandle(), false);
}
public Object terra$getHandle() {
return this;
}
public int terra$getMaxHeight() {
return 255; // TODO: 1.17 - Implement dynamic height.
}
}

View File

@@ -0,0 +1,51 @@
package com.dfsek.terra.fabric.mixin.implementations.entity;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.fabric.FabricAdapter;
import net.minecraft.entity.Entity;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.UUID;
@Mixin(Entity.class)
@Implements(@Interface(iface = com.dfsek.terra.api.platform.entity.Entity.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class EntityMixin {
@Shadow
public net.minecraft.world.World world;
@Shadow
private BlockPos blockPos;
@Shadow
public abstract void teleport(double destX, double destY, double destZ);
@Shadow
public abstract void sendSystemMessage(Text message, UUID senderUuid);
public Object terra$getHandle() {
return this;
}
public Location terra$getLocation() {
return new Location((World) world, FabricAdapter.adapt(blockPos));
}
public void terra$setLocation(Location location) {
teleport(location.getX(), location.getY(), location.getZ());
}
public World terra$getWorld() {
return (World) world;
}
public void terra$sendMessage(String message) {
sendSystemMessage(new LiteralText(message), UUID.randomUUID()); // TODO: look into how this actually works and make it less jank
}
}

View File

@@ -0,0 +1,14 @@
package com.dfsek.terra.fabric.mixin.implementations.entity;
import net.minecraft.entity.EntityType;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(EntityType.class)
@Implements(@Interface(iface = com.dfsek.terra.api.platform.entity.EntityType.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class EntityTypeMixin {
public Object terra$getHandle() {
return this;
}
}

View File

@@ -0,0 +1,13 @@
package com.dfsek.terra.fabric.mixin.implementations.entity;
import com.dfsek.terra.api.platform.entity.Player;
import net.minecraft.entity.player.PlayerEntity;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(PlayerEntity.class)
@Implements(@Interface(iface = Player.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class PlayerEntityMixin extends EntityMixin {
}

View File

@@ -0,0 +1,25 @@
package com.dfsek.terra.fabric.mixin.implementations.entity;
import com.dfsek.terra.api.platform.CommandSender;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ServerCommandSource.class)
@Implements(@Interface(iface = CommandSender.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ServerCommandSourceMixin {
@Shadow
public abstract void sendFeedback(Text message, boolean broadcastToOps);
public void terra$sendMessage(String message) {
sendFeedback(new LiteralText(message), true);
}
public Object terra$getHandle() {
return this;
}
}

View File

@@ -0,0 +1,32 @@
package com.dfsek.terra.fabric.mixin.implementations.inventory;
import com.dfsek.terra.api.platform.inventory.Inventory;
import com.dfsek.terra.api.platform.inventory.ItemStack;
import net.minecraft.block.entity.LockableContainerBlockEntity;
import net.minecraft.item.Items;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(LockableContainerBlockEntity.class)
@Implements(@Interface(iface = Inventory.class, prefix = "terra$", remap = Interface.Remap.NONE))
public class LockableContainerBlockEntityMixin {
public Object terra$getHandle() {
return this;
}
public int terra$getSize() {
return ((LockableContainerBlockEntity) (Object) this).size();
}
@SuppressWarnings("ConstantConditions")
public ItemStack terra$getItem(int slot) {
net.minecraft.item.ItemStack itemStack = ((LockableContainerBlockEntity) (Object) this).getStack(slot);
return itemStack.getItem() == Items.AIR ? null : (ItemStack) (Object) itemStack;
}
@SuppressWarnings("ConstantConditions")
public void terra$setItem(int slot, ItemStack newStack) {
((LockableContainerBlockEntity) (Object) this).setStack(slot, (net.minecraft.item.ItemStack) (Object) newStack);
}
}

View File

@@ -0,0 +1,28 @@
package com.dfsek.terra.fabric.mixin.implementations.inventory.item;
import com.dfsek.terra.api.platform.inventory.ItemStack;
import net.minecraft.item.Item;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(Item.class)
@Implements(@Interface(iface = com.dfsek.terra.api.platform.inventory.Item.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ItemMixin {
@Shadow
public abstract int getMaxDamage();
public Object terra$getHandle() {
return this;
}
@SuppressWarnings("ConstantConditions")
public ItemStack terra$newItemStack(int amount) {
return (ItemStack) (Object) new net.minecraft.item.ItemStack((Item) (Object) this, amount);
}
public double terra$getMaxDurability() {
return getMaxDamage();
}
}

View File

@@ -0,0 +1,61 @@
package com.dfsek.terra.fabric.mixin.implementations.inventory.item;
import com.dfsek.terra.api.platform.inventory.Item;
import com.dfsek.terra.api.platform.inventory.item.ItemMeta;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Intrinsic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ItemStack.class)
@Implements(@Interface(iface = com.dfsek.terra.api.platform.inventory.ItemStack.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ItemStackMixin {
@Shadow
public abstract int getCount();
@Shadow
public abstract void setCount(int count);
@Shadow
public abstract net.minecraft.item.Item getItem();
@Shadow
public abstract boolean isDamageable();
@Shadow
public abstract void setTag(@Nullable CompoundTag tag);
public int terra$getAmount() {
return getCount();
}
public void terra$setAmount(int i) {
setCount(i);
}
public Item terra$getType() {
return (Item) getItem();
}
public ItemMeta terra$getItemMeta() {
return (ItemMeta) this;
}
@SuppressWarnings("ConstantConditions")
public void terra$setItemMeta(ItemMeta meta) {
setTag(((ItemStack) (Object) meta).getTag());
}
public Object terra$getHandle() {
return this;
}
@Intrinsic
public boolean terra$isDamageable() {
return isDamageable();
}
}

View File

@@ -0,0 +1,38 @@
package com.dfsek.terra.fabric.mixin.implementations.inventory.meta;
import com.dfsek.terra.api.platform.inventory.ItemStack;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.util.registry.Registry;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Objects;
@Mixin(Enchantment.class)
@Implements(@Interface(iface = com.dfsek.terra.api.platform.inventory.item.Enchantment.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class EnchantmentMixin {
@Shadow
public abstract boolean isAcceptableItem(net.minecraft.item.ItemStack stack);
@Shadow
public abstract boolean canCombine(Enchantment other);
public Object terra$getHandle() {
return this;
}
@SuppressWarnings("ConstantConditions")
public boolean terra$canEnchantItem(ItemStack itemStack) {
return isAcceptableItem((net.minecraft.item.ItemStack) (Object) itemStack);
}
public String terra$getID() {
return Objects.requireNonNull(Registry.ENCHANTMENT.getId((Enchantment) (Object) this)).toString();
}
public boolean terra$conflictsWith(com.dfsek.terra.api.platform.inventory.item.Enchantment other) {
return !canCombine((Enchantment) other);
}
}

View File

@@ -0,0 +1,36 @@
package com.dfsek.terra.fabric.mixin.implementations.inventory.meta;
import com.dfsek.terra.api.platform.inventory.item.Damageable;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Intrinsic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ItemStack.class)
@Implements(@Interface(iface = Damageable.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ItemStackDamageableMixin {
@Shadow
public abstract boolean isDamaged();
@Shadow
public abstract int getDamage();
@Shadow
public abstract void setDamage(int damage);
public boolean terra$hasDamage() {
return isDamaged();
}
@Intrinsic
public void terra$setDamage(int damage) {
setDamage(damage);
}
@Intrinsic
public int terra$getDamage() {
return getDamage();
}
}

View File

@@ -0,0 +1,50 @@
package com.dfsek.terra.fabric.mixin.implementations.inventory.meta;
import com.dfsek.terra.api.platform.inventory.item.Enchantment;
import com.dfsek.terra.api.platform.inventory.item.ItemMeta;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.util.registry.Registry;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Intrinsic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@Mixin(ItemStack.class)
@Implements(@Interface(iface = ItemMeta.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ItemStackMetaMixin {
@Shadow
public abstract boolean hasEnchantments();
@Shadow
public abstract ListTag getEnchantments();
@Shadow
public abstract void addEnchantment(net.minecraft.enchantment.Enchantment enchantment, int level);
public Object terra$getHandle() {
return this;
}
@Intrinsic(displace = true)
public Map<Enchantment, Integer> terra$getEnchantments() {
if(!hasEnchantments()) return Collections.emptyMap();
Map<Enchantment, Integer> map = new HashMap<>();
getEnchantments().forEach(enchantment -> {
CompoundTag eTag = (CompoundTag) enchantment;
map.put((Enchantment) Registry.ENCHANTMENT.get(eTag.getInt("id")), eTag.getInt("lvl"));
});
return map;
}
public void terra$addEnchantment(Enchantment enchantment, int level) {
addEnchantment((net.minecraft.enchantment.Enchantment) enchantment, level);
}
}

View File

@@ -0,0 +1,5 @@
/**
* Mixins in this package implement Terra
* interfaces in Minecraft classes.
*/
package com.dfsek.terra.fabric.mixin.implementations;

View File

@@ -0,0 +1,109 @@
package com.dfsek.terra.fabric.mixin.implementations.world;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.generator.ChunkGenerator;
import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.fabric.block.FabricBlock;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ChunkRegion;
import net.minecraft.world.ServerWorldAccess;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Intrinsic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ChunkRegion.class)
@Implements(@Interface(iface = World.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ChunkRegionMixin {
@Shadow
@Final
private ServerWorld world;
@Shadow
@Final
private long seed;
public int terra$getMaxHeight() {
return ((ChunkRegion) (Object) this).getDimensionHeight();
}
@SuppressWarnings("deprecation")
public ChunkGenerator terra$getGenerator() {
return (ChunkGenerator) ((ChunkRegion) (Object) this).toServerWorld().getChunkManager().getChunkGenerator();
}
public Chunk terra$getChunkAt(int x, int z) {
return (Chunk) ((ChunkRegion) (Object) this).getChunk(x, z);
}
public Block terra$getBlockAt(int x, int y, int z) {
return new FabricBlock(new BlockPos(x, y, z), ((ChunkRegion) (Object) this));
}
@SuppressWarnings("deprecation")
public Entity terra$spawnEntity(Location location, EntityType entityType) {
net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType<?>) entityType).create(((ChunkRegion) (Object) this).toServerWorld());
entity.setPos(location.getX(), location.getY(), location.getZ());
((ChunkRegion) (Object) this).spawnEntity(entity);
return (Entity) entity;
}
@Intrinsic
public long terra$getSeed() {
return seed;
}
public int terra$getMinHeight() {
return 0;
}
public Object terra$getHandle() {
return this;
}
public boolean terra$isTerraWorld() {
return terra$getGenerator() instanceof GeneratorWrapper;
}
public TerraChunkGenerator terra$getTerraGenerator() {
return ((FabricChunkGeneratorWrapper) terra$getGenerator()).getHandle();
}
/**
* We need regions delegating to the same world
* to have the same hashcode. This
* minimizes cache misses.
* <p>
* This is sort of jank, but shouldn't(tm)
* break any other mods, unless they're doing
* something they really shouldn't, since
* ChunkRegions are not supposed to persist.
*/
@Override
public int hashCode() {
return world.hashCode();
}
/**
* Overridden in the same manner as {@link #hashCode()}
*
* @param other Another object
* @return Whether this world is the same as other.
* @see #hashCode()
*/
@Override
public boolean equals(Object other) {
if(!(other instanceof ServerWorldAccess)) return false;
return world.equals(((ServerWorldAccess) other).toServerWorld());
}
}

View File

@@ -0,0 +1,86 @@
package com.dfsek.terra.fabric.mixin.implementations.world;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.generator.ChunkGenerator;
import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.fabric.block.FabricBlock;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ServerWorldAccess;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Intrinsic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ServerWorld.class)
@Implements(@Interface(iface = World.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ServerWorldMixin {
@Shadow
public abstract long getSeed();
public int terra$getMaxHeight() {
return ((ServerWorld) (Object) this).getDimensionHeight();
}
public ChunkGenerator terra$getGenerator() {
return (ChunkGenerator) ((ServerWorld) (Object) this).getChunkManager().getChunkGenerator();
}
public Chunk terra$getChunkAt(int x, int z) {
return (Chunk) ((ServerWorld) (Object) this).getChunk(x, z);
}
public Block terra$getBlockAt(int x, int y, int z) {
return new FabricBlock(new BlockPos(x, y, z), ((ServerWorld) (Object) this));
}
public Entity terra$spawnEntity(Location location, EntityType entityType) {
net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType<?>) entityType).create(((ServerWorld) (Object) this));
entity.setPos(location.getX(), location.getY(), location.getZ());
((ServerWorld) (Object) this).spawnEntity(entity);
return (Entity) entity;
}
@Intrinsic
public long terra$getSeed() {
return getSeed();
}
public int terra$getMinHeight() {
return 0;
}
public Object terra$getHandle() {
return this;
}
public boolean terra$isTerraWorld() {
return terra$getGenerator() instanceof GeneratorWrapper;
}
public TerraChunkGenerator terra$getTerraGenerator() {
return ((FabricChunkGeneratorWrapper) terra$getGenerator()).getHandle();
}
/**
* Overridden in the same manner as {@link ChunkRegionMixin#hashCode()}
*
* @param other Another object
* @return Whether this world is the same as other.
* @see ChunkRegionMixin#hashCode()
*/
@SuppressWarnings("ConstantConditions")
@Override
public boolean equals(Object other) {
if(!(other instanceof ServerWorldAccess)) return false;
return (ServerWorldAccess) this == (((ServerWorldAccess) other).toServerWorld());
}
}

View File

@@ -1,127 +0,0 @@
package com.dfsek.terra.fabric.world;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.CommandSender;
import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.block.BlockType;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.platform.inventory.item.Enchantment;
import com.dfsek.terra.fabric.inventory.FabricEnchantment;
import com.dfsek.terra.fabric.inventory.FabricItem;
import com.dfsek.terra.fabric.inventory.FabricItemStack;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import com.dfsek.terra.fabric.world.block.FabricBlockType;
import com.dfsek.terra.fabric.world.block.data.FabricDirectional;
import com.dfsek.terra.fabric.world.block.data.FabricMultipleFacing;
import com.dfsek.terra.fabric.world.block.data.FabricOrientable;
import com.dfsek.terra.fabric.world.block.data.FabricRotatable;
import com.dfsek.terra.fabric.world.block.data.FabricSlab;
import com.dfsek.terra.fabric.world.block.data.FabricStairs;
import com.dfsek.terra.fabric.world.block.data.FabricWaterlogged;
import com.dfsek.terra.fabric.world.entity.FabricCommandSender;
import com.dfsek.terra.fabric.world.entity.FabricEntityType;
import com.dfsek.terra.fabric.world.entity.FabricPlayer;
import com.dfsek.terra.fabric.world.handles.world.FabricWorldHandle;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.state.property.Properties;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.WorldAccess;
import java.util.Arrays;
public final class FabricAdapter {
public static BlockPos adapt(Vector3 v) {
return new BlockPos(v.getBlockX(), v.getBlockY(), v.getBlockZ());
}
public static Vector3 adapt(BlockPos pos) {
return new Vector3(pos.getX(), pos.getY(), pos.getZ());
}
public static FabricBlockData adapt(BlockState state) {
if(state.contains(Properties.STAIR_SHAPE)) return new FabricStairs(state);
if(state.contains(Properties.SLAB_TYPE)) return new FabricSlab(state);
if(state.contains(Properties.AXIS)) return new FabricOrientable(state, Properties.AXIS);
if(state.contains(Properties.HORIZONTAL_AXIS)) return new FabricOrientable(state, Properties.HORIZONTAL_AXIS);
if(state.contains(Properties.ROTATION)) return new FabricRotatable(state);
if(state.contains(Properties.FACING)) return new FabricDirectional(state, Properties.FACING);
if(state.contains(Properties.HOPPER_FACING)) return new FabricDirectional(state, Properties.HOPPER_FACING);
if(state.contains(Properties.HORIZONTAL_FACING)) return new FabricDirectional(state, Properties.HORIZONTAL_FACING);
if(state.getProperties().containsAll(Arrays.asList(Properties.NORTH, Properties.SOUTH, Properties.EAST, Properties.WEST)))
return new FabricMultipleFacing(state);
if(state.contains(Properties.WATERLOGGED)) return new FabricWaterlogged(state);
return new FabricBlockData(state);
}
public static CommandSender adapt(ServerCommandSource serverCommandSource) {
if(serverCommandSource.getEntity() instanceof PlayerEntity) return new FabricPlayer((PlayerEntity) serverCommandSource.getEntity());
return new FabricCommandSender(serverCommandSource);
}
public static Direction adapt(BlockFace face) {
switch(face) {
case NORTH:
return Direction.NORTH;
case WEST:
return Direction.WEST;
case SOUTH:
return Direction.SOUTH;
case EAST:
return Direction.EAST;
case UP:
return Direction.UP;
case DOWN:
return Direction.DOWN;
default:
throw new IllegalArgumentException("Illegal direction: " + face);
}
}
public static BlockType adapt(Block block) {
return new FabricBlockType(block);
}
public static EntityType adapt(net.minecraft.entity.EntityType<?> entityType) {
return new FabricEntityType(entityType);
}
public static net.minecraft.entity.EntityType<? extends Entity> adapt(EntityType entityType) {
return ((FabricEntityType) entityType).getHandle();
}
public static ItemStack adapt(com.dfsek.terra.api.platform.inventory.ItemStack itemStack) {
return ((FabricItemStack) itemStack).getHandle();
}
public static com.dfsek.terra.api.platform.inventory.ItemStack adapt(ItemStack itemStack) {
return new FabricItemStack(itemStack);
}
public static com.dfsek.terra.api.platform.inventory.Item adapt(Item item) {
return new FabricItem(item);
}
public static Enchantment adapt(net.minecraft.enchantment.Enchantment enchantment) {
return new FabricEnchantment(enchantment);
}
public static net.minecraft.enchantment.Enchantment adapt(Enchantment enchantment) {
return ((FabricEnchantment) enchantment).getHandle();
}
public WorldAccess adapt(FabricWorldHandle worldHandle) {
return worldHandle.getWorld();
}
}

View File

@@ -1,17 +0,0 @@
package com.dfsek.terra.fabric.world;
import com.dfsek.terra.api.platform.world.Biome;
public class FabricBiome implements Biome {
private final net.minecraft.world.biome.Biome delegate;
public FabricBiome(net.minecraft.world.biome.Biome delegate) {
this.delegate = delegate;
}
@Override
public net.minecraft.world.biome.Biome getHandle() {
return delegate;
}
}

View File

@@ -1,40 +0,0 @@
package com.dfsek.terra.fabric.world;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator;
import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess;
import com.dfsek.terra.profiler.ProfileFrame;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.StructureWorldAccess;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import java.util.Locale;
import java.util.Random;
public class FabricTree implements Tree {
private final ConfiguredFeature<?, ?> delegate;
public FabricTree(ConfiguredFeature<?, ?> delegate) {
this.delegate = delegate;
}
@Override
public boolean plant(Location l, Random r) {
try(ProfileFrame ignore = TerraFabricPlugin.getInstance().getProfiler().profile("fabric_tree:" + delegate.toString().toLowerCase(Locale.ROOT))) {
FabricWorldAccess fabricWorldAccess = ((FabricWorldAccess) l.getWorld());
ChunkGenerator generatorWrapper = ((FabricChunkGenerator) fabricWorldAccess.getGenerator()).getHandle();
return delegate.generate((StructureWorldAccess) fabricWorldAccess.getHandle(), generatorWrapper, r, new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()));
}
}
@Override
public MaterialSet getSpawnable() {
return MaterialSet.get(TerraFabricPlugin.getInstance().getWorldHandle().createBlockData("minecraft:grass_block"),
TerraFabricPlugin.getInstance().getWorldHandle().createBlockData("minecraft:podzol"),
TerraFabricPlugin.getInstance().getWorldHandle().createBlockData("minecraft:mycelium"));
}
}

View File

@@ -1,46 +0,0 @@
package com.dfsek.terra.fabric.world.block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.BlockType;
import com.dfsek.terra.fabric.world.FabricAdapter;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
public class FabricBlockType implements BlockType {
private final Block delegate;
public FabricBlockType(Block delegate) {
this.delegate = delegate;
}
@Override
public Block getHandle() {
return delegate;
}
@Override
public BlockData getDefaultData() {
return FabricAdapter.adapt(delegate.getDefaultState());
}
@Override
public boolean isSolid() {
return delegate.getDefaultState().isOpaque();
}
@Override
public boolean isWater() {
return delegate == Blocks.WATER;
}
@Override
public int hashCode() {
return delegate.hashCode();
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof FabricBlockType)) return false;
return ((FabricBlockType) obj).delegate == delegate;
}
}

View File

@@ -1,73 +0,0 @@
package com.dfsek.terra.fabric.world.block.state;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.state.BlockState;
import com.dfsek.terra.fabric.world.FabricAdapter;
import com.dfsek.terra.fabric.world.block.FabricBlock;
import com.dfsek.terra.fabric.world.handles.world.FabricWorldHandle;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.LootableContainerBlockEntity;
import net.minecraft.block.entity.MobSpawnerBlockEntity;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.world.WorldAccess;
public class FabricBlockState implements BlockState {
protected final BlockEntity blockEntity;
private final WorldAccess worldAccess;
public FabricBlockState(BlockEntity blockEntity, WorldAccess worldAccess) {
this.blockEntity = blockEntity;
this.worldAccess = worldAccess;
}
public static FabricBlockState newInstance(Block block) {
WorldAccess worldAccess = ((FabricWorldHandle) block.getLocation().getWorld()).getWorld();
BlockEntity entity = worldAccess.getBlockEntity(FabricAdapter.adapt(block.getLocation().toVector()));
if(entity instanceof SignBlockEntity) {
return new FabricSign((SignBlockEntity) entity, worldAccess);
} else if(entity instanceof MobSpawnerBlockEntity) {
return new FabricMobSpawner((MobSpawnerBlockEntity) entity, worldAccess);
} else if(entity instanceof LootableContainerBlockEntity) {
return new FabricContainer((LootableContainerBlockEntity) entity, worldAccess);
}
return null;
}
@Override
public BlockEntity getHandle() {
return blockEntity;
}
@Override
public Block getBlock() {
return new FabricBlock(blockEntity.getPos(), blockEntity.getWorld());
}
@Override
public int getX() {
return blockEntity.getPos().getX();
}
@Override
public int getY() {
return blockEntity.getPos().getY();
}
@Override
public int getZ() {
return blockEntity.getPos().getZ();
}
@Override
public BlockData getBlockData() {
return FabricAdapter.adapt(blockEntity.getCachedState());
}
@Override
public boolean update(boolean applyPhysics) {
worldAccess.getChunk(blockEntity.getPos()).setBlockEntity(blockEntity.getPos(), blockEntity);
return true;
}
}

View File

@@ -1,18 +0,0 @@
package com.dfsek.terra.fabric.world.block.state;
import com.dfsek.terra.api.platform.block.state.Container;
import com.dfsek.terra.api.platform.inventory.Inventory;
import com.dfsek.terra.fabric.inventory.FabricInventory;
import net.minecraft.block.entity.LootableContainerBlockEntity;
import net.minecraft.world.WorldAccess;
public class FabricContainer extends FabricBlockState implements Container {
public FabricContainer(LootableContainerBlockEntity blockEntity, WorldAccess worldAccess) {
super(blockEntity, worldAccess);
}
@Override
public Inventory getInventory() {
return new FabricInventory(((LootableContainerBlockEntity) blockEntity));
}
}

View File

@@ -1,133 +0,0 @@
package com.dfsek.terra.fabric.world.block.state;
import com.dfsek.terra.api.platform.block.state.MobSpawner;
import com.dfsek.terra.api.platform.block.state.SerialState;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.dfsek.terra.fabric.world.FabricAdapter;
import net.minecraft.block.entity.MobSpawnerBlockEntity;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.WorldAccess;
import org.jetbrains.annotations.NotNull;
public class FabricMobSpawner extends FabricBlockState implements MobSpawner { // TODO: finish implementation / refactor API because bukkit doesnt expose most of the stuff spawners can do
public FabricMobSpawner(MobSpawnerBlockEntity blockEntity, WorldAccess worldAccess) {
super(blockEntity, worldAccess);
}
@Override
public EntityType getSpawnedType() {
return FabricAdapter.adapt(Registry.ENTITY_TYPE.get(((MobSpawnerBlockEntity) blockEntity).getLogic().getEntityId()));
}
@Override
public void setSpawnedType(@NotNull EntityType creatureType) {
((MobSpawnerBlockEntity) blockEntity).getLogic().setEntityId(FabricAdapter.adapt(creatureType));
}
@Override
public int getDelay() {
return 0;
}
@Override
public void setDelay(int delay) {
}
@Override
public int getMinSpawnDelay() {
return 0;
}
@Override
public void setMinSpawnDelay(int delay) {
}
@Override
public int getMaxSpawnDelay() {
return 0;
}
@Override
public void setMaxSpawnDelay(int delay) {
}
@Override
public int getSpawnCount() {
return 0;
}
@Override
public void setSpawnCount(int spawnCount) {
}
@Override
public int getMaxNearbyEntities() {
return 0;
}
@Override
public void setMaxNearbyEntities(int maxNearbyEntities) {
}
@Override
public int getRequiredPlayerRange() {
return 0;
}
@Override
public void setRequiredPlayerRange(int requiredPlayerRange) {
}
@Override
public int getSpawnRange() {
return 0;
}
@Override
public void setSpawnRange(int spawnRange) {
}
@Override
public void applyState(String state) {
SerialState.parse(state).forEach((k, v) -> {
switch(k) {
case "type":
setSpawnedType(TerraFabricPlugin.getInstance().getWorldHandle().getEntity(v));
return;
case "delay":
setDelay(Integer.parseInt(v));
return;
case "min_delay":
setMinSpawnDelay(Integer.parseInt(v));
return;
case "max_delay":
setMaxSpawnDelay(Integer.parseInt(v));
return;
case "spawn_count":
setSpawnCount(Integer.parseInt(v));
return;
case "spawn_range":
setSpawnRange(Integer.parseInt(v));
return;
case "max_nearby":
setMaxNearbyEntities(Integer.parseInt(v));
return;
case "required_player_range":
setRequiredPlayerRange(Integer.parseInt(v));
return;
default:
throw new IllegalArgumentException("Invalid property: " + k);
}
});
}
}

View File

@@ -1,44 +0,0 @@
package com.dfsek.terra.fabric.world.block.state;
import com.dfsek.terra.api.platform.block.state.SerialState;
import com.dfsek.terra.api.platform.block.state.Sign;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.text.LiteralText;
import net.minecraft.world.WorldAccess;
import org.jetbrains.annotations.NotNull;
public class FabricSign extends FabricBlockState implements Sign {
public FabricSign(SignBlockEntity blockEntity, WorldAccess worldAccess) {
super(blockEntity, worldAccess);
}
@Override
public @NotNull String[] getLines() {
SignBlockEntity sign = (SignBlockEntity) blockEntity;
return new String[] {
sign.getTextOnRow(0).asString(),
sign.getTextOnRow(1).asString(),
sign.getTextOnRow(2).asString(),
sign.getTextOnRow(3).asString()
};
}
@Override
public @NotNull String getLine(int index) throws IndexOutOfBoundsException {
return ((SignBlockEntity) blockEntity).getTextOnRow(index).asString();
}
@Override
public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException {
((SignBlockEntity) blockEntity).setTextOnRow(index, new LiteralText(line));
}
@Override
public void applyState(String state) {
SerialState.parse(state).forEach((k, v) -> {
if(!k.startsWith("text")) throw new IllegalArgumentException("Invalid property: " + k);
setLine(Integer.parseInt(k.substring(4)), v);
});
}
}

View File

@@ -1,23 +0,0 @@
package com.dfsek.terra.fabric.world.entity;
import com.dfsek.terra.api.platform.CommandSender;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.LiteralText;
public class FabricCommandSender implements CommandSender {
private final ServerCommandSource delegate;
public FabricCommandSender(ServerCommandSource delegate) {
this.delegate = delegate;
}
@Override
public void sendMessage(String message) {
delegate.sendFeedback(new LiteralText(message), true);
}
@Override
public Object getHandle() {
return delegate;
}
}

View File

@@ -1,43 +0,0 @@
package com.dfsek.terra.fabric.world.entity;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.fabric.world.FabricAdapter;
import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess;
import com.dfsek.terra.fabric.world.handles.world.FabricWorldHandle;
import net.minecraft.server.world.ServerWorld;
public class FabricEntity implements Entity {
private final net.minecraft.entity.Entity delegate;
public FabricEntity(net.minecraft.entity.Entity delegate) {
this.delegate = delegate;
}
@Override
public void sendMessage(String message) {
}
@Override
public Object getHandle() {
return null;
}
@Override
public Location getLocation() {
return new Location(new FabricWorldAccess(delegate.world), FabricAdapter.adapt(delegate.getBlockPos()));
}
@Override
public void setLocation(Location location) {
delegate.teleport(location.getX(), location.getY(), location.getZ());
delegate.moveToWorld((ServerWorld) ((FabricWorldHandle) location).getWorld());
}
@Override
public World getWorld() {
return new FabricWorldAccess(delegate.world);
}
}

View File

@@ -1,16 +0,0 @@
package com.dfsek.terra.fabric.world.entity;
import com.dfsek.terra.api.platform.entity.EntityType;
public class FabricEntityType implements EntityType {
private final net.minecraft.entity.EntityType<?> type;
public FabricEntityType(net.minecraft.entity.EntityType<?> type) {
this.type = type;
}
@Override
public net.minecraft.entity.EntityType<?> getHandle() {
return type;
}
}

View File

@@ -1,42 +0,0 @@
package com.dfsek.terra.fabric.world.entity;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.entity.Player;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.fabric.world.FabricAdapter;
import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.LiteralText;
public class FabricPlayer implements Player {
private final PlayerEntity delegate;
public FabricPlayer(PlayerEntity delegate) {
this.delegate = delegate;
}
@Override
public void sendMessage(String message) {
delegate.sendMessage(new LiteralText(message), false);
}
@Override
public Object getHandle() {
return delegate;
}
@Override
public Location getLocation() {
return FabricAdapter.adapt(delegate.getBlockPos()).toLocation(new FabricWorldAccess(delegate.world));
}
@Override
public World getWorld() {
return new FabricWorldAccess(delegate.world);
}
@Override
public void setLocation(Location location) {
delegate.teleport(location.getX(), location.getY(), location.getZ());
}
}

View File

@@ -1,36 +0,0 @@
package com.dfsek.terra.fabric.world.generator;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.generator.ChunkData;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.Chunk;
import org.jetbrains.annotations.NotNull;
public class FabricChunkData implements ChunkData {
private final Chunk handle;
public FabricChunkData(Chunk handle) {
this.handle = handle;
}
@Override
public Chunk getHandle() {
return handle;
}
@Override
public int getMaxHeight() {
return handle.getHeight();
}
@Override
public void setBlock(int x, int y, int z, @NotNull BlockData blockData) {
handle.setBlockState(new BlockPos(x, y, z), ((FabricBlockData) blockData).getHandle(), false);
}
@Override
public @NotNull BlockData getBlockData(int x, int y, int z) {
return new FabricBlockData(handle.getBlockState(new BlockPos(x, y, z)));
}
}

View File

@@ -1,16 +0,0 @@
package com.dfsek.terra.fabric.world.generator;
import com.dfsek.terra.api.platform.world.generator.ChunkGenerator;
public class FabricChunkGenerator implements ChunkGenerator {
private final net.minecraft.world.gen.chunk.ChunkGenerator delegate;
public FabricChunkGenerator(net.minecraft.world.gen.chunk.ChunkGenerator delegate) {
this.delegate = delegate;
}
@Override
public net.minecraft.world.gen.chunk.ChunkGenerator getHandle() {
return delegate;
}
}

View File

@@ -1,128 +0,0 @@
package com.dfsek.terra.fabric.world.handles;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.generator.ChunkGenerator;
import com.dfsek.terra.fabric.world.FabricAdapter;
import com.dfsek.terra.fabric.world.block.FabricBlock;
import com.dfsek.terra.fabric.world.entity.FabricEntity;
import com.dfsek.terra.fabric.world.handles.chunk.FabricChunk;
import com.dfsek.terra.fabric.world.handles.world.FabricWorldHandle;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ServerWorldAccess;
import net.minecraft.world.WorldAccess;
import java.io.File;
import java.util.UUID;
public class FabricWorld implements World, FabricWorldHandle {
private final Handle delegate;
public FabricWorld(ServerWorld world, ChunkGenerator generator) {
this.delegate = new Handle(world, generator);
}
@Override
public long getSeed() {
return delegate.world.getSeed();
}
@Override
public int getMaxHeight() {
return delegate.world.getHeight();
}
@Override
public ChunkGenerator getGenerator() {
return delegate.generator;
}
@Override
public String getName() {
return delegate.world.worldProperties.getLevelName();
}
@Override
public UUID getUID() {
return null;
}
@Override
public boolean isChunkGenerated(int x, int z) {
return false;
}
@Override
public Chunk getChunkAt(int x, int z) {
return new FabricChunk(delegate.world.getChunk(x, z));
}
@Override
public File getWorldFolder() {
return null;
}
@Override
public Block getBlockAt(int x, int y, int z) {
BlockPos pos = new BlockPos(x, y, z);
return new FabricBlock(pos, delegate.world);
}
@Override
public int hashCode() {
return ((ServerWorldAccess) delegate.world).toServerWorld().hashCode();
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof FabricWorld)) return false;
return ((ServerWorldAccess) ((FabricWorld) obj).delegate.world).toServerWorld().equals(((ServerWorldAccess) delegate.world).toServerWorld());
}
@Override
public Entity spawnEntity(Location location, EntityType entityType) {
net.minecraft.entity.Entity entity = FabricAdapter.adapt(entityType).create(delegate.world);
entity.setPos(location.getX(), location.getY(), location.getZ());
delegate.world.spawnEntity(entity);
return new FabricEntity(entity);
}
@Override
public int getMinHeight() {
return 0;
}
@Override
public Handle getHandle() {
return null;
}
@Override
public WorldAccess getWorld() {
return delegate.getWorld();
}
public static final class Handle {
private final ServerWorld world;
private final ChunkGenerator generator;
private Handle(ServerWorld world, ChunkGenerator generator) {
this.world = world;
this.generator = generator;
}
public ChunkGenerator getGenerator() {
return generator;
}
public ServerWorld getWorld() {
return world;
}
}
}

View File

@@ -1,52 +0,0 @@
package com.dfsek.terra.fabric.world.handles.chunk;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import net.minecraft.util.math.BlockPos;
import org.jetbrains.annotations.NotNull;
public class FabricChunk implements Chunk {
private final net.minecraft.world.chunk.Chunk chunk;
public FabricChunk(net.minecraft.world.chunk.Chunk chunk) {
this.chunk = chunk;
}
@Override
public int getX() {
return chunk.getPos().x;
}
@Override
public int getZ() {
return chunk.getPos().z;
}
@Override
public World getWorld() {
return null;
}
@Override
public Block getBlock(int x, int y, int z) {
return null;
}
@Override
public net.minecraft.world.chunk.Chunk getHandle() {
return chunk;
}
@Override
public void setBlock(int x, int y, int z, @NotNull BlockData blockData) {
chunk.setBlockState(new BlockPos(x, y, z), ((FabricBlockData) blockData).getHandle(), false);
}
@Override
public @NotNull BlockData getBlockData(int x, int y, int z) {
return getBlock(x, y, z).getBlockData();
}
}

View File

@@ -1,60 +0,0 @@
package com.dfsek.terra.fabric.world.handles.chunk;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.fabric.world.block.FabricBlock;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.WorldAccess;
import org.jetbrains.annotations.NotNull;
public class FabricChunkWorldAccess implements Chunk {
private final WorldAccess chunkRegion;
private final int x;
private final int z;
public FabricChunkWorldAccess(WorldAccess chunkRegion, int x, int z) {
this.chunkRegion = chunkRegion;
this.x = x << 4;
this.z = z << 4;
}
@Override
public int getX() {
return x >> 4;
}
@Override
public int getZ() {
return z >> 4;
}
@Override
public World getWorld() {
return new FabricWorldAccess(chunkRegion);
}
@Override
public Block getBlock(int x, int y, int z) {
BlockPos pos = new BlockPos(x + this.x, y, z + this.z);
return new FabricBlock(pos, chunkRegion);
}
@Override
public WorldAccess getHandle() {
return chunkRegion;
}
@Override
public void setBlock(int x, int y, int z, @NotNull BlockData blockData) {
chunkRegion.setBlockState(new BlockPos(x + this.x, y, z + this.z), ((FabricBlockData) blockData).getHandle(), 0);
}
@Override
public @NotNull BlockData getBlockData(int x, int y, int z) {
return getBlock(x, y, z).getBlockData();
}
}

View File

@@ -1,133 +0,0 @@
package com.dfsek.terra.fabric.world.handles.world;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.generator.ChunkGenerator;
import com.dfsek.terra.fabric.world.FabricAdapter;
import com.dfsek.terra.fabric.world.block.FabricBlock;
import com.dfsek.terra.fabric.world.entity.FabricEntity;
import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ServerWorldAccess;
import net.minecraft.world.WorldAccess;
import java.io.File;
import java.util.UUID;
public class FabricSeededWorldAccess implements World, FabricWorldHandle {
private final Handle handle;
public FabricSeededWorldAccess(WorldAccess access, long seed, net.minecraft.world.gen.chunk.ChunkGenerator generator) {
this.handle = new Handle(access, seed, generator);
}
@Override
public long getSeed() {
return handle.getSeed();
}
@Override
public int getMaxHeight() {
return handle.getWorldAccess().getDimensionHeight();
}
@Override
public ChunkGenerator getGenerator() {
return new FabricChunkGenerator(handle.getGenerator());
}
@Override
public String getName() {
return handle.toString(); // TODO: implementation
}
@Override
public UUID getUID() {
return UUID.randomUUID(); // TODO: implementation
}
@Override
public boolean isChunkGenerated(int x, int z) {
return false;
}
@Override
public Chunk getChunkAt(int x, int z) {
return null;
}
@Override
public File getWorldFolder() {
return null;
}
@Override
public Block getBlockAt(int x, int y, int z) {
BlockPos pos = new BlockPos(x, y, z);
return new FabricBlock(pos, handle.worldAccess);
}
@Override
public Entity spawnEntity(Location location, EntityType entityType) {
net.minecraft.entity.Entity entity = FabricAdapter.adapt(entityType).create((ServerWorld) handle.worldAccess);
entity.setPos(location.getX(), location.getY(), location.getZ());
handle.worldAccess.spawnEntity(entity);
return new FabricEntity(entity);
}
@Override
public int getMinHeight() {
return 0;
}
@Override
public int hashCode() {
return ((ServerWorldAccess) handle.worldAccess).toServerWorld().hashCode();
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof FabricSeededWorldAccess)) return false;
return ((ServerWorldAccess) ((FabricSeededWorldAccess) obj).handle.worldAccess).toServerWorld().equals(((ServerWorldAccess) handle.worldAccess).toServerWorld());
}
@Override
public Handle getHandle() {
return handle;
}
@Override
public WorldAccess getWorld() {
return handle.worldAccess;
}
public static class Handle {
private final WorldAccess worldAccess;
private final long seed;
private final net.minecraft.world.gen.chunk.ChunkGenerator generator;
public Handle(WorldAccess worldAccess, long seed, net.minecraft.world.gen.chunk.ChunkGenerator generator) {
this.worldAccess = worldAccess;
this.seed = seed;
this.generator = generator;
}
public net.minecraft.world.gen.chunk.ChunkGenerator getGenerator() {
return generator;
}
public long getSeed() {
return seed;
}
public WorldAccess getWorldAccess() {
return worldAccess;
}
}
}

View File

@@ -1,108 +0,0 @@
package com.dfsek.terra.fabric.world.handles.world;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.generator.ChunkGenerator;
import com.dfsek.terra.fabric.world.FabricAdapter;
import com.dfsek.terra.fabric.world.block.FabricBlock;
import com.dfsek.terra.fabric.world.entity.FabricEntity;
import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ServerWorldAccess;
import net.minecraft.world.StructureWorldAccess;
import net.minecraft.world.WorldAccess;
import java.io.File;
import java.util.UUID;
public class FabricWorldAccess implements World, FabricWorldHandle {
private final WorldAccess delegate;
public FabricWorldAccess(WorldAccess delegate) {
this.delegate = delegate;
}
@Override
public long getSeed() {
return ((StructureWorldAccess) delegate).getSeed();
}
@Override
public int getMaxHeight() {
return delegate.getDimensionHeight();
}
@Override
public ChunkGenerator getGenerator() {
return new FabricChunkGenerator(((ServerWorldAccess) delegate).toServerWorld().getChunkManager().getChunkGenerator());
}
@Override
public String getName() {
return ((ServerWorldAccess) delegate).toServerWorld().worldProperties.getLevelName();
}
@Override
public UUID getUID() {
return null;
}
@Override
public boolean isChunkGenerated(int x, int z) {
return false;
}
@Override
public Chunk getChunkAt(int x, int z) {
return null;
}
@Override
public File getWorldFolder() {
return null;
}
@Override
public Block getBlockAt(int x, int y, int z) {
BlockPos pos = new BlockPos(x, y, z);
return new FabricBlock(pos, delegate);
}
@Override
public Entity spawnEntity(Location location, EntityType entityType) {
net.minecraft.entity.Entity entity = FabricAdapter.adapt(entityType).create(((ServerWorldAccess) delegate).toServerWorld());
entity.setPos(location.getX(), location.getY(), location.getZ());
delegate.spawnEntity(entity);
return new FabricEntity(entity);
}
@Override
public int getMinHeight() {
return 0;
}
@Override
public WorldAccess getHandle() {
return delegate;
}
@Override
public WorldAccess getWorld() {
return delegate;
}
@Override
public int hashCode() {
return ((ServerWorldAccess) delegate).toServerWorld().hashCode();
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof FabricWorldAccess)) return false;
return ((ServerWorldAccess) ((FabricWorldAccess) obj).delegate).toServerWorld().equals(((ServerWorldAccess) delegate).toServerWorld());
}
}

View File

@@ -1,7 +0,0 @@
package com.dfsek.terra.fabric.world.handles.world;
import net.minecraft.world.WorldAccess;
public interface FabricWorldHandle {
WorldAccess getWorld();
}

View File

@@ -1,16 +0,0 @@
{
"mappings": {
"com/dfsek/terra/fabric/mixin/GeneratorTypeAccessor": {
"VALUES": "field_25052:Ljava/util/List;",
"translationKey": "field_25060:Lnet/minecraft/class_2561;"
}
},
"data": {
"named:intermediary": {
"com/dfsek/terra/fabric/mixin/GeneratorTypeAccessor": {
"VALUES": "field_25052:Ljava/util/List;",
"translationKey": "field_25060:Lnet/minecraft/class_2561;"
}
}
}
}

View File

@@ -1,19 +1,3 @@
accessWidener v1 named
extendable method net/minecraft/client/world/GeneratorType <init> (Ljava/lang/String;)V
accessible field net/minecraft/server/world/ServerWorld worldProperties Lnet/minecraft/world/level/ServerWorldProperties;
accessible method net/minecraft/world/MobSpawnerLogic getEntityId ()Lnet/minecraft/util/Identifier;
accessible field net/minecraft/state/State PROPERTY_MAP_PRINTER Ljava/util/function/Function;
accessible field net/minecraft/world/biome/BiomeEffects fogColor I
accessible field net/minecraft/world/biome/BiomeEffects waterColor I
accessible field net/minecraft/world/biome/BiomeEffects waterFogColor I
accessible field net/minecraft/world/biome/BiomeEffects skyColor I
accessible field net/minecraft/world/biome/BiomeEffects foliageColor Ljava/util/Optional;
accessible field net/minecraft/world/biome/BiomeEffects grassColor Ljava/util/Optional;
accessible field net/minecraft/world/biome/BiomeEffects grassColorModifier Lnet/minecraft/world/biome/BiomeEffects$GrassColorModifier;
extendable method net/minecraft/client/world/GeneratorType <init> (Ljava/lang/String;)V

View File

@@ -4,9 +4,36 @@
"package": "com.dfsek.terra.fabric.mixin",
"compatibilityLevel": "JAVA_8",
"mixins": [
"GeneratorOptionsMixin",
"access.BiomeEffectsAccessor",
"access.MobSpawnerLogicAccessor",
"access.StateAccessor",
"implementations.BiomeMixin",
"implementations.ChunkGeneratorMixin",
"implementations.ConfiguredFeatureMixin",
"implementations.block.BlockEntityMixin",
"implementations.block.BlockMixin",
"implementations.block.state.LootableContainerBlockEntityMixin",
"implementations.block.state.MobSpawnerBlockEntityMixin",
"implementations.block.state.SignBlockEntityMixin",
"implementations.chunk.ChunkRegionMixin",
"implementations.chunk.WorldChunkMixin",
"implementations.chunk.data.ProtoChunkMixin",
"implementations.entity.EntityMixin",
"implementations.entity.EntityTypeMixin",
"implementations.entity.PlayerEntityMixin",
"implementations.entity.ServerCommandSourceMixin",
"implementations.inventory.LockableContainerBlockEntityMixin",
"implementations.inventory.item.ItemMixin",
"implementations.inventory.item.ItemStackMixin",
"implementations.inventory.meta.EnchantmentMixin",
"implementations.inventory.meta.ItemStackDamageableMixin",
"implementations.inventory.meta.ItemStackMetaMixin",
"implementations.world.ChunkRegionMixin",
"implementations.world.ServerWorldMixin"
],
"client": [
"GeneratorTypeAccessor"
"access.GeneratorTypeAccessor"
],
"server": [],
"injectors": {