mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-02-16 02:20:57 +00:00
Merge branch 'master' into dev/7.0-2
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
## Resource files
|
||||
|
||||
Current mapping version: je 1.21 to be 1.21.30
|
||||
Current mapping version: je 1.21.4 to be 1.21.50
|
||||
|
||||
- `mapping/biomes.json` obtain from GeyserMC/mappings.
|
||||
- `mapping/items.json` obtain from GeyserMC/mappings.
|
||||
|
||||
@@ -46,7 +46,7 @@ public class AllayPlatform extends AbstractPlatform {
|
||||
var dimension = wrapper.getAllayWorldGenerator().getDimension();
|
||||
TerraAllayPlugin.INSTANCE.getPluginLogger().info(
|
||||
"Replaced pack in chunk generator for world {}",
|
||||
dimension.getWorld().getWorldData().getName() + ":" + dimension.getDimensionInfo().dimensionId()
|
||||
dimension.getWorld().getWorldData().getDisplayName() + ":" + dimension.getDimensionInfo().dimensionId()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -73,7 +73,7 @@ public final class Mapping {
|
||||
|
||||
public static Map<String, String> getJeBlockDefaultProperties(String jeBlockIdentifier) {
|
||||
Map<String, String> defaultProperties = JE_BLOCK_DEFAULT_PROPERTIES.get(jeBlockIdentifier);
|
||||
if( defaultProperties == null) {
|
||||
if(defaultProperties == null) {
|
||||
TerraAllayPlugin.INSTANCE.getPluginLogger().warn("Failed to find default properties for {}", jeBlockIdentifier);
|
||||
return Map.of();
|
||||
}
|
||||
@@ -85,8 +85,8 @@ public final class Mapping {
|
||||
}
|
||||
|
||||
private static boolean initBiomeMapping() {
|
||||
try (InputStream stream = Mapping.class.getClassLoader().getResourceAsStream("mapping/biomes.json")) {
|
||||
if (stream == null) {
|
||||
try(InputStream stream = Mapping.class.getClassLoader().getResourceAsStream("mapping/biomes.json")) {
|
||||
if(stream == null) {
|
||||
TerraAllayPlugin.INSTANCE.getPluginLogger().error("biomes mapping not found");
|
||||
return false;
|
||||
}
|
||||
@@ -100,12 +100,12 @@ public final class Mapping {
|
||||
}
|
||||
|
||||
private static boolean initItemMapping() {
|
||||
try (InputStream stream = Mapping.class.getClassLoader().getResourceAsStream("mapping/items.json")) {
|
||||
if (stream == null) {
|
||||
try(InputStream stream = Mapping.class.getClassLoader().getResourceAsStream("mapping/items.json")) {
|
||||
if(stream == null) {
|
||||
TerraAllayPlugin.INSTANCE.getPluginLogger().error("items mapping not found");
|
||||
return false;
|
||||
}
|
||||
Set<Entry<String, Map<String, Object>>> mappings = JSONUtils.from(stream, new TypeToken<Map<String, Map<String, Object>>>(){}).entrySet();
|
||||
Set<Entry<String, Map<String, Object>>> mappings = JSONUtils.from(stream, new TypeToken<Map<String, Map<String, Object>>>() {}).entrySet();
|
||||
mappings.forEach(mapping -> {
|
||||
ItemType<?> item = ItemTypeSafeGetter
|
||||
.name((String) mapping.getValue().get("bedrock_identifier"))
|
||||
@@ -121,13 +121,13 @@ public final class Mapping {
|
||||
}
|
||||
|
||||
private static boolean initBlockStateMapping() {
|
||||
try (InputStream stream = Mapping.class.getClassLoader().getResourceAsStream("mapping/blocks.json")) {
|
||||
if (stream == null) {
|
||||
try(InputStream stream = Mapping.class.getClassLoader().getResourceAsStream("mapping/blocks.json")) {
|
||||
if(stream == null) {
|
||||
TerraAllayPlugin.INSTANCE.getPluginLogger().error("blocks mapping not found");
|
||||
return false;
|
||||
}
|
||||
// noinspection unchecked
|
||||
List<Map<String, Map<String, Object>>> mappings = (List<Map<String, Map<String, Object>>>) JSONUtils.from(stream, new TypeToken<Map<String, Object>>(){}).get("mappings");
|
||||
List<Map<String, Map<String, Object>>> mappings = (List<Map<String, Map<String, Object>>>) JSONUtils.from(stream, new TypeToken<Map<String, Object>>() {}).get("mappings");
|
||||
mappings.forEach(mapping -> {
|
||||
JeBlockState jeState = createJeBlockState(mapping.get("java_state"));
|
||||
BlockState beState = createBeBlockState(mapping.get("bedrock_state"));
|
||||
@@ -141,12 +141,12 @@ public final class Mapping {
|
||||
}
|
||||
|
||||
private static boolean initJeBlockDefaultProperties() {
|
||||
try (InputStream stream = Mapping.class.getClassLoader().getResourceAsStream("je_block_default_states.json")) {
|
||||
if (stream == null) {
|
||||
try(InputStream stream = Mapping.class.getClassLoader().getResourceAsStream("je_block_default_states.json")) {
|
||||
if(stream == null) {
|
||||
TerraAllayPlugin.INSTANCE.getPluginLogger().error("je_block_default_states.json not found");
|
||||
return false;
|
||||
}
|
||||
Map<String, Map<String, String>> states = JSONUtils.from(stream, new TypeToken<Map<String, Map<String, String>>>(){});
|
||||
Map<String, Map<String, String>> states = JSONUtils.from(stream, new TypeToken<>() {});
|
||||
for(Entry<String, Map<String, String>> entry : states.entrySet()) {
|
||||
String identifier = entry.getKey();
|
||||
Map<String, String> properties = entry.getValue();
|
||||
@@ -161,7 +161,7 @@ public final class Mapping {
|
||||
private static BlockState createBeBlockState(Map<String, Object> data) {
|
||||
Getter getter = BlockStateSafeGetter
|
||||
.name("minecraft:" + data.get("bedrock_identifier"));
|
||||
if (data.containsKey("state")) {
|
||||
if(data.containsKey("state")) {
|
||||
// noinspection unchecked
|
||||
convertValueType((Map<String, Object>) data.get("state")).forEach(getter::property);
|
||||
}
|
||||
@@ -170,8 +170,8 @@ public final class Mapping {
|
||||
|
||||
private static Map<String, Object> convertValueType(Map<String, Object> data) {
|
||||
TreeMap<String, Object> result = new TreeMap<>();
|
||||
for (Entry<String, Object> entry : data.entrySet()) {
|
||||
if (entry.getValue() instanceof Number number) {
|
||||
for(Entry<String, Object> entry : data.entrySet()) {
|
||||
if(entry.getValue() instanceof Number number) {
|
||||
// Convert double to int because the number in json is double
|
||||
result.put(entry.getKey(), number.intValue());
|
||||
} else {
|
||||
|
||||
@@ -40,9 +40,8 @@ public class TerraAllayPlugin extends Plugin {
|
||||
AllayGeneratorWrapper wrapper = new AllayGeneratorWrapper(preset);
|
||||
AllayPlatform.GENERATOR_WRAPPERS.add(wrapper);
|
||||
return wrapper.getAllayWorldGenerator();
|
||||
} catch (IllegalArgumentException e) {
|
||||
TerraAllayPlugin.INSTANCE.getPluginLogger().error("Fail to create world generator with preset: {}", preset);
|
||||
TerraAllayPlugin.INSTANCE.getPluginLogger().error("Reason: {}", e.getMessage());
|
||||
} catch(IllegalArgumentException e) {
|
||||
TerraAllayPlugin.INSTANCE.getPluginLogger().error("Fail to create world generator with preset: {}", preset, e);
|
||||
return Registries.WORLD_GENERATOR_FACTORIES.get("FLAT").apply("");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@ public record AllayBlockType(BlockType<?> allayBlockType) implements com.dfsek.t
|
||||
|
||||
@Override
|
||||
public boolean isSolid() {
|
||||
return allayBlockType.getMaterial().isSolid();
|
||||
return allayBlockType.getDefaultState().getBlockStateData().isSolid();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,8 +21,7 @@ public record AllayChunk(ServerWorld world, Chunk allayChunk) implements com.dfs
|
||||
public void setBlock(int x, int y, int z, BlockState data, boolean physics) {
|
||||
AllayBlockState allayBlockState = (AllayBlockState) data;
|
||||
allayChunk.setBlockState(x, y, z, allayBlockState.allayBlockState());
|
||||
boolean containsWater = allayBlockState.containsWater() || allayChunk.getBlockState(x, y, z).getBlockType().hasBlockTag(BlockTags.WATER);
|
||||
if (containsWater) {
|
||||
if (allayBlockState.containsWater() || allayChunk.getBlockState(x, y, z).getBlockType().hasBlockTag(BlockTags.WATER)) {
|
||||
allayChunk.setBlockState(x, y, z, WATER, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,7 @@ public record AllayProtoChunk(UnsafeChunk allayChunk) implements ProtoChunk {
|
||||
public void setBlock(int x, int y, int z, @NotNull BlockState blockState) {
|
||||
AllayBlockState allayBlockState = (AllayBlockState) blockState;
|
||||
allayChunk.setBlockState(x, y, z, allayBlockState.allayBlockState());
|
||||
boolean containsWater = allayBlockState.containsWater() || allayChunk.getBlockState(x, y, z).getBlockType().hasBlockTag(BlockTags.WATER);
|
||||
if (containsWater) {
|
||||
if(allayBlockState.containsWater() || allayChunk.getBlockState(x, y, z).getBlockType().hasBlockTag(BlockTags.WATER)) {
|
||||
allayChunk.setBlockState(x, y, z, WATER, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,10 +41,11 @@ public record AllayProtoWorld(AllayServerWorld allayServerWorld, OtherChunkAcces
|
||||
|
||||
@Override
|
||||
public void setBlockState(int x, int y, int z, BlockState data, boolean physics) {
|
||||
AllayBlockState allayBlockState = (AllayBlockState)data;
|
||||
boolean containsWater = allayBlockState.containsWater() || context.getBlockState(x, y, z).getBlockType().hasBlockTag(BlockTags.WATER);
|
||||
AllayBlockState allayBlockState = (AllayBlockState) data;
|
||||
context.setBlockState(x, y, z, allayBlockState.allayBlockState());
|
||||
if (containsWater) context.setBlockState(x, y, z, WATER, 1);
|
||||
if(allayBlockState.containsWater() || context.getBlockState(x, y, z).getBlockType().hasBlockTag(BlockTags.WATER)) {
|
||||
context.setBlockState(x, y, z, WATER, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.dfsek.terra.allay.delegate;
|
||||
|
||||
import org.allaymc.api.block.property.type.BlockPropertyTypes;
|
||||
import org.allaymc.api.block.type.BlockTypes;
|
||||
import org.allaymc.api.world.Dimension;
|
||||
|
||||
import com.dfsek.terra.allay.Mapping;
|
||||
@@ -21,12 +19,9 @@ import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||
* @author daoge_cmd
|
||||
*/
|
||||
public record AllayServerWorld(AllayGeneratorWrapper allayGeneratorWrapper, Dimension allayDimension) implements ServerWorld {
|
||||
|
||||
private static final org.allaymc.api.block.type.BlockState WATER = BlockTypes.WATER.ofState(BlockPropertyTypes.LIQUID_DEPTH.createValue(0));
|
||||
|
||||
@Override
|
||||
public Chunk getChunkAt(int x, int z) {
|
||||
return new AllayChunk(this, allayDimension.getChunkService().getChunk(x ,z));
|
||||
return new AllayChunk(this, allayDimension.getChunkService().getChunk(x, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +1,197 @@
|
||||
{ "minecraft:badlands": { "bedrock_id": 37 }, "minecraft:bamboo_jungle": { "bedrock_id": 48 }, "minecraft:basalt_deltas": { "bedrock_id": 181 }, "minecraft:beach": { "bedrock_id": 16 }, "minecraft:birch_forest": { "bedrock_id": 27 }, "minecraft:cherry_grove": { "bedrock_id": 192 }, "minecraft:cold_ocean": { "bedrock_id": 44 }, "minecraft:crimson_forest": { "bedrock_id": 179 }, "minecraft:dark_forest": { "bedrock_id": 29 }, "minecraft:deep_cold_ocean": { "bedrock_id": 45 }, "minecraft:deep_dark": { "bedrock_id": 190 }, "minecraft:deep_frozen_ocean": { "bedrock_id": 47 }, "minecraft:deep_lukewarm_ocean": { "bedrock_id": 43 }, "minecraft:deep_ocean": { "bedrock_id": 24 }, "minecraft:desert": { "bedrock_id": 2 }, "minecraft:dripstone_caves": { "bedrock_id": 188 }, "minecraft:end_barrens": { "bedrock_id": 9 }, "minecraft:end_highlands": { "bedrock_id": 9 }, "minecraft:end_midlands": { "bedrock_id": 9 }, "minecraft:eroded_badlands": { "bedrock_id": 165 }, "minecraft:flower_forest": { "bedrock_id": 132 }, "minecraft:forest": { "bedrock_id": 4 }, "minecraft:frozen_ocean": { "bedrock_id": 46 }, "minecraft:frozen_peaks": { "bedrock_id": 183 }, "minecraft:frozen_river": { "bedrock_id": 11 }, "minecraft:grove": { "bedrock_id": 185 }, "minecraft:ice_spikes": { "bedrock_id": 140 }, "minecraft:jagged_peaks": { "bedrock_id": 182 }, "minecraft:jungle": { "bedrock_id": 21 }, "minecraft:lukewarm_ocean": { "bedrock_id": 42 }, "minecraft:lush_caves": { "bedrock_id": 187 }, "minecraft:mangrove_swamp": { "bedrock_id": 191 }, "minecraft:meadow": { "bedrock_id": 186 }, "minecraft:mushroom_fields": { "bedrock_id": 14 }, "minecraft:nether_wastes": { "bedrock_id": 8 }, "minecraft:ocean": { "bedrock_id": 0 }, "minecraft:old_growth_birch_forest": { "bedrock_id": 155 }, "minecraft:old_growth_pine_taiga": { "bedrock_id": 32 }, "minecraft:old_growth_spruce_taiga": { "bedrock_id": 160 }, "minecraft:plains": { "bedrock_id": 1 }, "minecraft:river": { "bedrock_id": 7 }, "minecraft:savanna": { "bedrock_id": 35 }, "minecraft:savanna_plateau": { "bedrock_id": 36 }, "minecraft:small_end_islands": { "bedrock_id": 9 }, "minecraft:snowy_beach": { "bedrock_id": 26 }, "minecraft:snowy_plains": { "bedrock_id": 12 }, "minecraft:snowy_slopes": { "bedrock_id": 184 }, "minecraft:snowy_taiga": { "bedrock_id": 30 }, "minecraft:soul_sand_valley": { "bedrock_id": 178 }, "minecraft:sparse_jungle": { "bedrock_id": 23 }, "minecraft:stony_peaks": { "bedrock_id": 189 }, "minecraft:stony_shore": { "bedrock_id": 25 }, "minecraft:sunflower_plains": { "bedrock_id": 129 }, "minecraft:swamp": { "bedrock_id": 6 }, "minecraft:taiga": { "bedrock_id": 5 }, "minecraft:the_end": { "bedrock_id": 9 }, "minecraft:the_void": { "bedrock_id": 7 }, "minecraft:warm_ocean": { "bedrock_id": 40 }, "minecraft:warped_forest": { "bedrock_id": 180 }, "minecraft:windswept_forest": { "bedrock_id": 34 }, "minecraft:windswept_gravelly_hills": { "bedrock_id": 131 }, "minecraft:windswept_hills": { "bedrock_id": 3 }, "minecraft:windswept_savanna": { "bedrock_id": 163 }, "minecraft:wooded_badlands": { "bedrock_id": 38 } }
|
||||
{
|
||||
"minecraft:badlands": {
|
||||
"bedrock_id": 37
|
||||
},
|
||||
"minecraft:bamboo_jungle": {
|
||||
"bedrock_id": 48
|
||||
},
|
||||
"minecraft:basalt_deltas": {
|
||||
"bedrock_id": 181
|
||||
},
|
||||
"minecraft:beach": {
|
||||
"bedrock_id": 16
|
||||
},
|
||||
"minecraft:birch_forest": {
|
||||
"bedrock_id": 27
|
||||
},
|
||||
"minecraft:cherry_grove": {
|
||||
"bedrock_id": 192
|
||||
},
|
||||
"minecraft:cold_ocean": {
|
||||
"bedrock_id": 44
|
||||
},
|
||||
"minecraft:crimson_forest": {
|
||||
"bedrock_id": 179
|
||||
},
|
||||
"minecraft:dark_forest": {
|
||||
"bedrock_id": 29
|
||||
},
|
||||
"minecraft:deep_cold_ocean": {
|
||||
"bedrock_id": 45
|
||||
},
|
||||
"minecraft:deep_dark": {
|
||||
"bedrock_id": 190
|
||||
},
|
||||
"minecraft:deep_frozen_ocean": {
|
||||
"bedrock_id": 47
|
||||
},
|
||||
"minecraft:deep_lukewarm_ocean": {
|
||||
"bedrock_id": 43
|
||||
},
|
||||
"minecraft:deep_ocean": {
|
||||
"bedrock_id": 24
|
||||
},
|
||||
"minecraft:desert": {
|
||||
"bedrock_id": 2
|
||||
},
|
||||
"minecraft:dripstone_caves": {
|
||||
"bedrock_id": 188
|
||||
},
|
||||
"minecraft:end_barrens": {
|
||||
"bedrock_id": 9
|
||||
},
|
||||
"minecraft:end_highlands": {
|
||||
"bedrock_id": 9
|
||||
},
|
||||
"minecraft:end_midlands": {
|
||||
"bedrock_id": 9
|
||||
},
|
||||
"minecraft:eroded_badlands": {
|
||||
"bedrock_id": 165
|
||||
},
|
||||
"minecraft:flower_forest": {
|
||||
"bedrock_id": 132
|
||||
},
|
||||
"minecraft:forest": {
|
||||
"bedrock_id": 4
|
||||
},
|
||||
"minecraft:frozen_ocean": {
|
||||
"bedrock_id": 46
|
||||
},
|
||||
"minecraft:frozen_peaks": {
|
||||
"bedrock_id": 183
|
||||
},
|
||||
"minecraft:frozen_river": {
|
||||
"bedrock_id": 11
|
||||
},
|
||||
"minecraft:grove": {
|
||||
"bedrock_id": 185
|
||||
},
|
||||
"minecraft:ice_spikes": {
|
||||
"bedrock_id": 140
|
||||
},
|
||||
"minecraft:jagged_peaks": {
|
||||
"bedrock_id": 182
|
||||
},
|
||||
"minecraft:jungle": {
|
||||
"bedrock_id": 21
|
||||
},
|
||||
"minecraft:lukewarm_ocean": {
|
||||
"bedrock_id": 42
|
||||
},
|
||||
"minecraft:lush_caves": {
|
||||
"bedrock_id": 187
|
||||
},
|
||||
"minecraft:mangrove_swamp": {
|
||||
"bedrock_id": 191
|
||||
},
|
||||
"minecraft:meadow": {
|
||||
"bedrock_id": 186
|
||||
},
|
||||
"minecraft:mushroom_fields": {
|
||||
"bedrock_id": 14
|
||||
},
|
||||
"minecraft:nether_wastes": {
|
||||
"bedrock_id": 8
|
||||
},
|
||||
"minecraft:ocean": {
|
||||
"bedrock_id": 0
|
||||
},
|
||||
"minecraft:old_growth_birch_forest": {
|
||||
"bedrock_id": 155
|
||||
},
|
||||
"minecraft:old_growth_pine_taiga": {
|
||||
"bedrock_id": 32
|
||||
},
|
||||
"minecraft:old_growth_spruce_taiga": {
|
||||
"bedrock_id": 160
|
||||
},
|
||||
"minecraft:pale_garden": {
|
||||
"bedrock_id": 62
|
||||
},
|
||||
"minecraft:plains": {
|
||||
"bedrock_id": 1
|
||||
},
|
||||
"minecraft:river": {
|
||||
"bedrock_id": 7
|
||||
},
|
||||
"minecraft:savanna": {
|
||||
"bedrock_id": 35
|
||||
},
|
||||
"minecraft:savanna_plateau": {
|
||||
"bedrock_id": 36
|
||||
},
|
||||
"minecraft:small_end_islands": {
|
||||
"bedrock_id": 9
|
||||
},
|
||||
"minecraft:snowy_beach": {
|
||||
"bedrock_id": 26
|
||||
},
|
||||
"minecraft:snowy_plains": {
|
||||
"bedrock_id": 12
|
||||
},
|
||||
"minecraft:snowy_slopes": {
|
||||
"bedrock_id": 184
|
||||
},
|
||||
"minecraft:snowy_taiga": {
|
||||
"bedrock_id": 30
|
||||
},
|
||||
"minecraft:soul_sand_valley": {
|
||||
"bedrock_id": 178
|
||||
},
|
||||
"minecraft:sparse_jungle": {
|
||||
"bedrock_id": 23
|
||||
},
|
||||
"minecraft:stony_peaks": {
|
||||
"bedrock_id": 189
|
||||
},
|
||||
"minecraft:stony_shore": {
|
||||
"bedrock_id": 25
|
||||
},
|
||||
"minecraft:sunflower_plains": {
|
||||
"bedrock_id": 129
|
||||
},
|
||||
"minecraft:swamp": {
|
||||
"bedrock_id": 6
|
||||
},
|
||||
"minecraft:taiga": {
|
||||
"bedrock_id": 5
|
||||
},
|
||||
"minecraft:the_end": {
|
||||
"bedrock_id": 9
|
||||
},
|
||||
"minecraft:the_void": {
|
||||
"bedrock_id": 7
|
||||
},
|
||||
"minecraft:warm_ocean": {
|
||||
"bedrock_id": 40
|
||||
},
|
||||
"minecraft:warped_forest": {
|
||||
"bedrock_id": 180
|
||||
},
|
||||
"minecraft:windswept_forest": {
|
||||
"bedrock_id": 34
|
||||
},
|
||||
"minecraft:windswept_gravelly_hills": {
|
||||
"bedrock_id": 131
|
||||
},
|
||||
"minecraft:windswept_hills": {
|
||||
"bedrock_id": 3
|
||||
},
|
||||
"minecraft:windswept_savanna": {
|
||||
"bedrock_id": 163
|
||||
},
|
||||
"minecraft:wooded_badlands": {
|
||||
"bedrock_id": 38
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,7 +1,17 @@
|
||||
{
|
||||
"entrance": "com.dfsek.terra.allay.TerraAllayPlugin",
|
||||
"name": "Terra",
|
||||
"authors": ["daoge_cmd", "dfsek", "duplexsystem", "Astrash", "solonovamax", "Sancires", "Aureus", "RogueShade"],
|
||||
"authors": [
|
||||
"daoge_cmd",
|
||||
"IWareQ",
|
||||
"dfsek",
|
||||
"duplexsystem",
|
||||
"Astrash",
|
||||
"solonovamax",
|
||||
"Sancires",
|
||||
"Aureus",
|
||||
"RogueShade"
|
||||
],
|
||||
"version": "@VERSION@",
|
||||
"description": "@DESCRIPTION@",
|
||||
"website": "@WIKI@"
|
||||
|
||||
@@ -54,6 +54,9 @@ public interface Initializer {
|
||||
private static Initializer constructInitializer() {
|
||||
try {
|
||||
String packageVersion = NMS;
|
||||
if (NMS.equals("v1_21_4")) {
|
||||
packageVersion = "v1_21_3";
|
||||
}
|
||||
|
||||
Class<?> initializerClass = Class.forName(TERRA_PACKAGE + "." + packageVersion + ".NMSInitializer");
|
||||
try {
|
||||
|
||||
@@ -2,12 +2,12 @@ package com.dfsek.terra.bukkit.nms.v1_21_3;
|
||||
|
||||
import com.dfsek.terra.bukkit.nms.v1_21_3.config.VanillaBiomeProperties;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Holder.Reference;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.core.HolderSet.Named;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.RegistrationInfo;
|
||||
import net.minecraft.core.WritableRegistry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -19,8 +19,11 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
|
||||
import com.dfsek.terra.registry.master.ConfigRegistry;
|
||||
@@ -34,10 +37,12 @@ public class AwfulBukkitHacks {
|
||||
public static void registerBiomes(ConfigRegistry configRegistry) {
|
||||
try {
|
||||
LOGGER.info("Hacking biome registry...");
|
||||
WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) RegistryFetcher.biomeRegistry();
|
||||
MappedRegistry<Biome> biomeRegistry = (MappedRegistry<Biome>) RegistryFetcher.biomeRegistry();
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, false);
|
||||
// Unfreeze the biome registry to allow modification
|
||||
Reflection.MAPPED_REGISTRY.setFrozen(biomeRegistry, false);
|
||||
|
||||
// Register the terra biomes to the registry
|
||||
configRegistry.forEach(pack -> pack.getRegistry(com.dfsek.terra.api.world.biome.Biome.class).forEach((key, biome) -> {
|
||||
try {
|
||||
BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome();
|
||||
@@ -67,7 +72,7 @@ public class AwfulBukkitHacks {
|
||||
}
|
||||
}));
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen((MappedRegistry<?>) biomeRegistry, true); // freeze registry again :)
|
||||
Reflection.MAPPED_REGISTRY.setFrozen(biomeRegistry, true); // freeze registry again :)
|
||||
|
||||
LOGGER.info("Doing tag garbage....");
|
||||
Map<TagKey<Biome>, List<Holder<Biome>>> collect = biomeRegistry
|
||||
@@ -95,12 +100,51 @@ public class AwfulBukkitHacks {
|
||||
() -> LOGGER.error("No such biome: {}", tb))),
|
||||
() -> LOGGER.error("No vanilla biome: {}", vb)));
|
||||
|
||||
((MappedRegistry<Biome>) biomeRegistry).bindAllTagsToEmpty();
|
||||
ImmutableMap.copyOf(collect).forEach(biomeRegistry::bindTag);
|
||||
resetTags(biomeRegistry);
|
||||
bindTags(biomeRegistry, collect);
|
||||
|
||||
} catch(SecurityException | IllegalArgumentException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> void bindTags(MappedRegistry<T> registry, Map<TagKey<T>, List<Holder<T>>> tagEntries) {
|
||||
Map<Holder.Reference<T>, List<TagKey<T>>> map = new IdentityHashMap<>();
|
||||
Reflection.MAPPED_REGISTRY.getByKey(registry).values().forEach(entry -> map.put(entry, new ArrayList<>()));
|
||||
tagEntries.forEach((tag, entries) -> {
|
||||
for (Holder<T> holder : entries) {
|
||||
// if (!holder.canSerializeIn(registry.asLookup())) {
|
||||
// throw new IllegalStateException("Can't create named set " + tag + " containing value " + holder + " from outside registry " + this);
|
||||
// }
|
||||
|
||||
if (!(holder instanceof Holder.Reference<T> reference)) {
|
||||
throw new IllegalStateException("Found direct holder " + holder + " value in tag " + tag);
|
||||
}
|
||||
|
||||
map.get(reference).add(tag);
|
||||
}
|
||||
});
|
||||
// Set<TagKey<T>> set = Sets.difference(registry.tags.keySet(), tagEntries.keySet());
|
||||
// if (!set.isEmpty()) {
|
||||
// LOGGER.warn(
|
||||
// "Not all defined tags for registry {} are present in data pack: {}",
|
||||
// registry.key(),
|
||||
// set.stream().map(tag -> tag.location().toString()).sorted().collect(Collectors.joining(", "))
|
||||
// );
|
||||
// }
|
||||
|
||||
Map<TagKey<T>, HolderSet.Named<T>> map2 = new IdentityHashMap<>(registry.getTags().collect(Collectors.toMap(
|
||||
Named::key,
|
||||
(named) -> named
|
||||
)));
|
||||
tagEntries.forEach((tag, entries) -> Reflection.HOLDER_SET.invokeBind(map2.computeIfAbsent(tag, key -> Reflection.MAPPED_REGISTRY.invokeCreateTag(registry, key)), entries));
|
||||
map.forEach(Reflection.HOLDER_REFERENCE::invokeBindTags);
|
||||
Reflection.MAPPED_REGISTRY.setAllTags(registry, Reflection.MAPPED_REGISTRY_TAG_SET.invokeFromMap(map2));
|
||||
}
|
||||
|
||||
private static void resetTags(MappedRegistry<?> registry) {
|
||||
registry.getTags().forEach(entryList -> Reflection.HOLDER_SET.invokeBind(entryList, List.of()));
|
||||
Reflection.MAPPED_REGISTRY.getByKey(registry).values().forEach(entry -> Reflection.HOLDER_REFERENCE.invokeBindTags(entry, Set.of()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,21 @@ public class NMSBiomeInjector {
|
||||
.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor()))
|
||||
.waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor()))
|
||||
.skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor()))
|
||||
.grassColorModifier(Objects.requireNonNullElse(vanillaBiomeProperties.getGrassColorModifier(), vanilla.getSpecialEffects().getGrassColorModifier()))
|
||||
.grassColorOverride(Objects.requireNonNullElse(vanillaBiomeProperties.getGrassColor(), vanilla.getSpecialEffects().getGrassColorOverride().orElseGet(() -> Reflection.BIOME.invokeGrassColorFromTexture(vanilla))))
|
||||
.foliageColorOverride(Objects.requireNonNullElse(vanillaBiomeProperties.getFoliageColor(), vanilla.getFoliageColor()));
|
||||
.grassColorModifier(Objects.requireNonNullElse(vanillaBiomeProperties.getGrassColorModifier(), vanilla.getSpecialEffects().getGrassColorModifier()));
|
||||
// .grassColorOverride(Objects.requireNonNullElse(vanillaBiomeProperties.getGrassColor(), vanilla.getSpecialEffects().getGrassColorOverride().orElseGet(() -> Reflection.BIOME.invokeGrassColorFromTexture(vanilla))))
|
||||
// .foliageColorOverride(Objects.requireNonNullElse(vanillaBiomeProperties.getFoliageColor(), vanilla.getFoliageColor()));
|
||||
|
||||
if(vanillaBiomeProperties.getGrassColor() == null) {
|
||||
vanilla.getSpecialEffects().getGrassColorOverride().ifPresent(effects::grassColorOverride);
|
||||
} else {
|
||||
effects.grassColorOverride(vanillaBiomeProperties.getGrassColor());
|
||||
}
|
||||
|
||||
if(vanillaBiomeProperties.getFoliageColor() == null) {
|
||||
vanilla.getSpecialEffects().getFoliageColorOverride().ifPresent(effects::foliageColorOverride);
|
||||
} else {
|
||||
effects.foliageColorOverride(vanillaBiomeProperties.getFoliageColor());
|
||||
}
|
||||
|
||||
if(vanillaBiomeProperties.getParticleConfig() == null) {
|
||||
vanilla.getSpecialEffects().getAmbientParticleSettings().ifPresent(effects::ambientParticle);
|
||||
|
||||
@@ -4,7 +4,9 @@ import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Holder.Reference;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.StructureManager;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
@@ -15,19 +17,24 @@ import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldGetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldSetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.MethodName;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.Static;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class Reflection {
|
||||
public static final MappedRegistryProxy MAPPED_REGISTRY;
|
||||
public static final MappedRegistryTagSetProxy MAPPED_REGISTRY_TAG_SET;
|
||||
public static final StructureManagerProxy STRUCTURE_MANAGER;
|
||||
|
||||
public static final ReferenceProxy REFERENCE;
|
||||
|
||||
|
||||
public static final ChunkMapProxy CHUNKMAP;
|
||||
public static final HolderSetProxy HOLDER_SET;
|
||||
public static final HolderReferenceProxy HOLDER_REFERENCE;
|
||||
public static final HolderSetNamedProxy HOLDER_SET;
|
||||
public static final BiomeProxy BIOME;
|
||||
|
||||
static {
|
||||
@@ -36,18 +43,36 @@ public class Reflection {
|
||||
Reflection.class.getClassLoader());
|
||||
|
||||
MAPPED_REGISTRY = reflectionProxyFactory.reflectionProxy(MappedRegistryProxy.class);
|
||||
MAPPED_REGISTRY_TAG_SET = reflectionProxyFactory.reflectionProxy(MappedRegistryTagSetProxy.class);
|
||||
STRUCTURE_MANAGER = reflectionProxyFactory.reflectionProxy(StructureManagerProxy.class);
|
||||
REFERENCE = reflectionProxyFactory.reflectionProxy(ReferenceProxy.class);
|
||||
CHUNKMAP = reflectionProxyFactory.reflectionProxy(ChunkMapProxy.class);
|
||||
HOLDER_SET = reflectionProxyFactory.reflectionProxy(HolderSetProxy.class);
|
||||
HOLDER_REFERENCE = reflectionProxyFactory.reflectionProxy(HolderReferenceProxy.class);
|
||||
HOLDER_SET = reflectionProxyFactory.reflectionProxy(HolderSetNamedProxy.class);
|
||||
BIOME = reflectionProxyFactory.reflectionProxy(BiomeProxy.class);
|
||||
}
|
||||
|
||||
|
||||
@Proxies(MappedRegistry.class)
|
||||
public interface MappedRegistryProxy {
|
||||
@FieldGetter("byKey")
|
||||
<T> Map<ResourceKey<T>, Reference<T>> getByKey(MappedRegistry<T> instance);
|
||||
|
||||
@FieldSetter("allTags")
|
||||
<T> void setAllTags(MappedRegistry<T> instance, Object obj);
|
||||
|
||||
@FieldSetter("frozen")
|
||||
void setFrozen(MappedRegistry<?> instance, boolean frozen);
|
||||
|
||||
@MethodName("createTag")
|
||||
<T> HolderSet.Named<T> invokeCreateTag(MappedRegistry<T> instance, TagKey<T> tag);
|
||||
}
|
||||
|
||||
@Proxies(className = "net.minecraft.core.MappedRegistry$TagSet")
|
||||
public interface MappedRegistryTagSetProxy {
|
||||
@MethodName("fromMap")
|
||||
@Static
|
||||
<T> Object invokeFromMap(Map<TagKey<T>, HolderSet.Named<T>> map);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +87,9 @@ public class Reflection {
|
||||
public interface ReferenceProxy {
|
||||
@MethodName("bindValue")
|
||||
<T> void invokeBindValue(Reference<T> instance, T value);
|
||||
|
||||
@MethodName("bindTags")
|
||||
<T> void invokeBindTags(Reference<T> instance, Collection<TagKey<T>> tags);
|
||||
}
|
||||
|
||||
@Proxies(ChunkMap.class)
|
||||
@@ -73,10 +101,19 @@ public class Reflection {
|
||||
void setWorldGenContext(ChunkMap instance, WorldGenContext worldGenContext);
|
||||
}
|
||||
|
||||
@Proxies(HolderSet.class)
|
||||
public interface HolderSetProxy {
|
||||
@Proxies(Holder.Reference.class)
|
||||
public interface HolderReferenceProxy {
|
||||
@MethodName("bindTags")
|
||||
<T> void invokeBindTags(Holder.Reference<T> instance, Collection<TagKey<T>> tags);
|
||||
}
|
||||
|
||||
@Proxies(HolderSet.Named.class)
|
||||
public interface HolderSetNamedProxy {
|
||||
@MethodName("bind")
|
||||
<T> void invokeBind(HolderSet.Named<T> instance, List<Holder<T>> entries);
|
||||
|
||||
@MethodName("contents")
|
||||
<T> List<Holder<T>> invokeContents(HolderSet<T> instance);
|
||||
<T> List<Holder<T>> invokeContents(HolderSet.Named<T> instance);
|
||||
}
|
||||
|
||||
@Proxies(Biome.class)
|
||||
|
||||
@@ -3,22 +3,16 @@ package com.dfsek.terra.bukkit.nms.v1_21_3;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
|
||||
|
||||
public class RegistryFetcher {
|
||||
private static <T> Registry<T> getRegistry(ResourceKey<Registry<T>> key) {
|
||||
CraftServer craftserver = (CraftServer) Bukkit.getServer();
|
||||
DedicatedServer dedicatedserver = craftserver.getServer();
|
||||
return dedicatedserver
|
||||
return MinecraftServer.getServer()
|
||||
.registryAccess()
|
||||
.get(key)
|
||||
.orElseThrow()
|
||||
.value();
|
||||
.lookupOrThrow(key);
|
||||
}
|
||||
|
||||
public static Registry<Biome> biomeRegistry() {
|
||||
|
||||
@@ -32,9 +32,9 @@
|
||||
"terra.common.mixins.json"
|
||||
],
|
||||
"depends": {
|
||||
"fabricloader": ">=0.16.7",
|
||||
"fabricloader": ">=0.16.10",
|
||||
"java": ">=21",
|
||||
"minecraft": ">=1.21.3",
|
||||
"minecraft": ">=1.21.4",
|
||||
"fabric": "*"
|
||||
}
|
||||
}
|
||||
11
platforms/minestom/build.gradle.kts
Normal file
11
platforms/minestom/build.gradle.kts
Normal file
@@ -0,0 +1,11 @@
|
||||
dependencies {
|
||||
shadedApi(project(":common:implementation:base"))
|
||||
shadedApi("com.github.ben-manes.caffeine", "caffeine", Versions.Libraries.caffeine)
|
||||
shadedImplementation("com.google.guava", "guava", Versions.Libraries.Internal.guava)
|
||||
|
||||
compileOnly("net.minestom", "minestom-snapshots", Versions.Minestom.minestom)
|
||||
}
|
||||
|
||||
tasks.named("jar") {
|
||||
finalizedBy("installAddonsIntoDefaultJar")
|
||||
}
|
||||
28
platforms/minestom/example/build.gradle.kts
Normal file
28
platforms/minestom/example/build.gradle.kts
Normal file
@@ -0,0 +1,28 @@
|
||||
plugins {
|
||||
application
|
||||
}
|
||||
|
||||
val javaMainClass = "com.dfsek.terra.minestom.TerraMinestomExample"
|
||||
|
||||
dependencies {
|
||||
shadedApi(project(":platforms:minestom"))
|
||||
|
||||
implementation("net.minestom", "minestom-snapshots", Versions.Minestom.minestom)
|
||||
implementation("org.slf4j", "slf4j-simple", Versions.Libraries.slf4j)
|
||||
}
|
||||
|
||||
tasks.withType<Jar> {
|
||||
entryCompression = ZipEntryCompression.STORED
|
||||
manifest {
|
||||
attributes(
|
||||
"Main-Class" to javaMainClass,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass.set(javaMainClass)
|
||||
}
|
||||
|
||||
tasks.getByName("run").setProperty("workingDir", file("./run"))
|
||||
addonDir(project.file("./run/terra/addons"), tasks.named("run").get())
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.dfsek.terra.minestom;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.command.builder.Command;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.entity.GameMode;
|
||||
import net.minestom.server.event.player.AsyncPlayerConfigurationEvent;
|
||||
import net.minestom.server.event.player.PlayerSpawnEvent;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.LightingChunk;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.dfsek.terra.minestom.world.TerraMinestomWorld;
|
||||
import com.dfsek.terra.minestom.world.TerraMinestomWorldBuilder;
|
||||
|
||||
|
||||
public class TerraMinestomExample {
|
||||
private static final Logger logger = LoggerFactory.getLogger(TerraMinestomExample.class);
|
||||
private final MinecraftServer server = MinecraftServer.init();
|
||||
private Instance instance;
|
||||
private TerraMinestomWorld world;
|
||||
|
||||
public void createNewInstance() {
|
||||
instance = MinecraftServer.getInstanceManager().createInstanceContainer();
|
||||
instance.setChunkSupplier(LightingChunk::new);
|
||||
}
|
||||
|
||||
public void attachTerra() {
|
||||
world = TerraMinestomWorldBuilder.from(instance)
|
||||
.defaultPack()
|
||||
.attach();
|
||||
}
|
||||
|
||||
private void sendProgressBar(int current, int max) {
|
||||
String left = "#".repeat((int) ((((float) current) / max) * 20));
|
||||
String right = ".".repeat(20 - left.length());
|
||||
int percent = (int) (((float) current) / max * 100);
|
||||
String percentString = percent + "%";
|
||||
percentString = " ".repeat(4 - percentString.length()) + percentString;
|
||||
String message = percentString + " |" + left + right + "| " + current + "/" + max;
|
||||
logger.info(message);
|
||||
}
|
||||
|
||||
public void preloadWorldAndMeasure() {
|
||||
int radius = 12;
|
||||
int chunksLoading = (radius * 2 + 1) * (radius * 2 + 1);
|
||||
AtomicInteger chunksLeft = new AtomicInteger(chunksLoading);
|
||||
|
||||
long start = System.nanoTime();
|
||||
for(int x = -radius; x <= radius; x++) {
|
||||
for(int z = -radius; z <= radius; z++) {
|
||||
instance.loadChunk(x, z).thenAccept(chunk -> {
|
||||
int left = chunksLeft.decrementAndGet();
|
||||
if(left == 0) {
|
||||
long end = System.nanoTime();
|
||||
sendProgressBar(chunksLoading - left, chunksLoading);
|
||||
double chunksPerSecond = chunksLoading / ((end - start) / 1000000000.0);
|
||||
logger.info(
|
||||
"Preloaded {} chunks in world in {}ms. That's {} Chunks/s",
|
||||
chunksLoading,
|
||||
(end - start) / 1000000.0,
|
||||
chunksPerSecond
|
||||
);
|
||||
|
||||
world.displayStats();
|
||||
} else if(left % 60 == 0) {
|
||||
sendProgressBar(chunksLoading - left, chunksLoading);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addListeners() {
|
||||
MinecraftServer.getGlobalEventHandler().addListener(AsyncPlayerConfigurationEvent.class, event -> {
|
||||
event.setSpawningInstance(instance);
|
||||
event.getPlayer().setRespawnPoint(new Pos(0.0, 100.0, 0.0));
|
||||
});
|
||||
|
||||
MinecraftServer.getGlobalEventHandler().addListener(PlayerSpawnEvent.class, event -> {
|
||||
event.getPlayer().setGameMode(GameMode.SPECTATOR);
|
||||
});
|
||||
}
|
||||
|
||||
public void addScheduler() {
|
||||
MinecraftServer.getSchedulerManager().buildTask(() -> world.displayStats())
|
||||
.repeat(Duration.ofSeconds(10))
|
||||
.schedule();
|
||||
}
|
||||
|
||||
public void addCommands() {
|
||||
MinecraftServer.getCommandManager().register(new RegenerateCommand());
|
||||
}
|
||||
|
||||
public void bind() {
|
||||
logger.info("Starting server on port 25565");
|
||||
server.start("localhost", 25565);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
TerraMinestomExample example = new TerraMinestomExample();
|
||||
example.createNewInstance();
|
||||
example.attachTerra();
|
||||
example.preloadWorldAndMeasure();
|
||||
example.addScheduler();
|
||||
example.addListeners();
|
||||
example.addCommands();
|
||||
example.bind();
|
||||
}
|
||||
|
||||
public class RegenerateCommand extends Command {
|
||||
public RegenerateCommand() {
|
||||
super("regenerate");
|
||||
setDefaultExecutor((sender, context) -> regenerate());
|
||||
}
|
||||
|
||||
private void regenerate() {
|
||||
instance.sendMessage(Component.text("Regenerating world"));
|
||||
createNewInstance();
|
||||
attachTerra();
|
||||
preloadWorldAndMeasure();
|
||||
MinecraftServer.getConnectionManager().getOnlinePlayers().forEach(player ->
|
||||
player.setInstance(instance, new Pos(0, 100, 0))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.dfsek.terra.minestom;
|
||||
|
||||
import com.dfsek.terra.api.util.vector.Vector3;
|
||||
|
||||
import net.minestom.server.coordinate.Point;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
|
||||
|
||||
public class MinestomAdapter {
|
||||
public static Vector3 adapt(Point point) {
|
||||
return Vector3.of(point.x(), point.y(), point.z());
|
||||
}
|
||||
|
||||
public static Pos adapt(Vector3 vector) {
|
||||
return new Pos(vector.getX(), vector.getY(), vector.getZ());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.dfsek.terra.minestom;
|
||||
|
||||
import com.dfsek.tectonic.api.TypeRegistry;
|
||||
import com.dfsek.tectonic.api.loader.type.TypeLoader;
|
||||
import com.dfsek.terra.AbstractPlatform;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
|
||||
import com.dfsek.terra.api.handle.ItemHandle;
|
||||
import com.dfsek.terra.api.handle.WorldHandle;
|
||||
import com.dfsek.terra.api.world.biome.PlatformBiome;
|
||||
import com.dfsek.terra.minestom.biome.MinestomBiomeLoader;
|
||||
import com.dfsek.terra.minestom.entity.MinestomEntityType;
|
||||
import com.dfsek.terra.minestom.item.MinestomItemHandle;
|
||||
import com.dfsek.terra.minestom.world.MinestomChunkGeneratorWrapper;
|
||||
import com.dfsek.terra.minestom.world.MinestomWorldHandle;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
public final class MinestomPlatform extends AbstractPlatform {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MinestomPlatform.class);
|
||||
private static MinestomPlatform INSTANCE = null;
|
||||
private final MinestomWorldHandle worldHandle = new MinestomWorldHandle();
|
||||
private final MinestomItemHandle itemHandle = new MinestomItemHandle();
|
||||
|
||||
private MinestomPlatform() {
|
||||
load();
|
||||
getEventManager().callEvent(new PlatformInitializationEvent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(TypeRegistry registry) {
|
||||
super.register(registry);
|
||||
registry
|
||||
.registerLoader(PlatformBiome.class, new MinestomBiomeLoader())
|
||||
.registerLoader(EntityType.class, (TypeLoader<EntityType>) (annotatedType, o, configLoader, depthTracker) -> new MinestomEntityType((String) o))
|
||||
.registerLoader(BlockState.class, (TypeLoader<BlockState>) (annotatedType, o, configLoader, depthTracker) -> worldHandle.createBlockState((String) o));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reload() {
|
||||
getTerraConfig().load(this);
|
||||
getRawConfigRegistry().clear();
|
||||
boolean succeed = getRawConfigRegistry().loadAll(this);
|
||||
|
||||
MinecraftServer.getInstanceManager().getInstances().forEach(world -> {
|
||||
if(world.generator() instanceof MinestomChunkGeneratorWrapper wrapper) {
|
||||
getConfigRegistry().get(wrapper.getPack().getRegistryKey()).ifPresent(pack -> {
|
||||
wrapper.setPack(pack);
|
||||
LOGGER.info("Replaced pack in chunk generator for instance {}", world.getUniqueId());
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return succeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull WorldHandle getWorldHandle() {
|
||||
return worldHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemHandle getItemHandle() {
|
||||
return itemHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String platformName() {
|
||||
return "Minestom";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull File getDataFolder() {
|
||||
String pathName = System.getProperty("terra.datafolder");
|
||||
if (pathName == null) pathName = "./terra/";
|
||||
File file = new File(pathName);
|
||||
if(!file.exists()) file.mkdirs();
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
public static MinestomPlatform getInstance() {
|
||||
if(INSTANCE == null) {
|
||||
INSTANCE = new MinestomPlatform();
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.dfsek.terra.minestom.api;
|
||||
|
||||
import com.dfsek.terra.api.block.entity.BlockEntity;
|
||||
|
||||
import net.minestom.server.coordinate.BlockVec;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a factory interface for creating instances of BlockEntity
|
||||
* at a specified BlockVec position. This is not implemented directly because
|
||||
* Minestom does not define a way to build block entities out of the box.
|
||||
*/
|
||||
public interface BlockEntityFactory {
|
||||
@Nullable BlockEntity createBlockEntity(BlockVec position);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.dfsek.terra.minestom.api;
|
||||
|
||||
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
|
||||
|
||||
/**
|
||||
* Allows adding AI to generated entities using custom entity types
|
||||
*/
|
||||
public interface EntityFactory {
|
||||
Entity createEntity(EntityType type);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.dfsek.terra.minestom.biome;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.PlatformBiome;
|
||||
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
|
||||
|
||||
public class MinestomBiome implements PlatformBiome {
|
||||
private final Biome biome;
|
||||
|
||||
public MinestomBiome(Biome biome) { this.biome = biome; }
|
||||
|
||||
@Override
|
||||
public Biome getHandle() {
|
||||
return biome;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.dfsek.terra.minestom.biome;
|
||||
|
||||
import com.dfsek.tectonic.api.depth.DepthTracker;
|
||||
import com.dfsek.tectonic.api.exception.LoadException;
|
||||
import com.dfsek.tectonic.api.loader.ConfigLoader;
|
||||
import com.dfsek.tectonic.api.loader.type.TypeLoader;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.PlatformBiome;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.AnnotatedType;
|
||||
|
||||
|
||||
public class MinestomBiomeLoader implements TypeLoader<PlatformBiome> {
|
||||
private final DynamicRegistry<Biome> biomeRegistry = MinecraftServer.getBiomeRegistry();
|
||||
|
||||
@Override
|
||||
public PlatformBiome load(@NotNull AnnotatedType annotatedType, @NotNull Object o, @NotNull ConfigLoader configLoader,
|
||||
DepthTracker depthTracker) throws LoadException {
|
||||
String id = (String) o;
|
||||
NamespaceID biomeID = NamespaceID.from(id);
|
||||
Biome biome = biomeRegistry.get(biomeID);
|
||||
if(biome == null) throw new LoadException("Biome %s does not exist in registry".formatted(id), depthTracker);
|
||||
return new MinestomBiome(biome);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.dfsek.terra.minestom.block;
|
||||
|
||||
import com.dfsek.terra.api.block.entity.BlockEntity;
|
||||
import com.dfsek.terra.minestom.api.BlockEntityFactory;
|
||||
|
||||
import net.minestom.server.coordinate.BlockVec;
|
||||
|
||||
|
||||
public class DefaultBlockEntityFactory implements BlockEntityFactory {
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockVec position) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.dfsek.terra.minestom.block;
|
||||
|
||||
import com.dfsek.terra.api.block.BlockType;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.block.state.properties.Property;
|
||||
|
||||
import net.minestom.server.instance.block.Block;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
public class MinestomBlockState implements BlockState {
|
||||
private final Block block;
|
||||
|
||||
public MinestomBlockState(Block block) {
|
||||
if(block == null) {
|
||||
this.block = Block.AIR;
|
||||
} else {
|
||||
this.block = block;
|
||||
}
|
||||
}
|
||||
|
||||
public MinestomBlockState(String data) {
|
||||
if(!data.contains("[")) {
|
||||
block = Block.fromNamespaceId(data);
|
||||
return;
|
||||
}
|
||||
|
||||
String[] split = data.split("\\[");
|
||||
String namespaceId = split[0];
|
||||
String properties = split[1].substring(0, split[1].length() - 1);
|
||||
Block block = Block.fromNamespaceId(namespaceId);
|
||||
HashMap<String, String> propertiesMap = new HashMap<>();
|
||||
|
||||
for(String property : properties.split(",")) {
|
||||
String[] kv = property.split("=");
|
||||
propertiesMap.put(kv[0].strip(), kv[1].strip());
|
||||
}
|
||||
|
||||
assert block != null;
|
||||
this.block = block.withProperties(propertiesMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(BlockState other) {
|
||||
return ((MinestomBlockState) other).block.compare(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Comparable<T>> boolean has(Property<T> property) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Comparable<T>> T get(Property<T> property) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Comparable<T>> BlockState set(Property<T> property, T value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockType getBlockType() {
|
||||
return new MinestomBlockType(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsString(boolean properties) {
|
||||
String name = block.namespace().asString();
|
||||
if(!properties || block.properties().isEmpty()) {
|
||||
return name;
|
||||
}
|
||||
|
||||
name += "[" + block.properties().entrySet().stream().map(entry -> entry.getKey() + "=" + entry.getValue()).collect(
|
||||
Collectors.joining(",")) + "]";
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAir() {
|
||||
return block.isAir();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(block.id());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.dfsek.terra.minestom.block;
|
||||
|
||||
import com.dfsek.terra.api.block.BlockType;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
|
||||
import net.minestom.server.instance.block.Block;
|
||||
|
||||
|
||||
public class MinestomBlockType implements BlockType {
|
||||
private final Block block;
|
||||
|
||||
public MinestomBlockType(Block block) {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getDefaultState() {
|
||||
return new MinestomBlockState(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid() {
|
||||
return block.isSolid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWater() {
|
||||
return block.isLiquid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return block.id();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(obj instanceof MinestomBlockType other) {
|
||||
return block.id() == other.block.id();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.dfsek.terra.minestom.chunk;
|
||||
|
||||
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.generation.ProtoChunk;
|
||||
import com.dfsek.terra.minestom.block.MinestomBlockState;
|
||||
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.generator.UnitModifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public class CachedChunk implements ProtoChunk {
|
||||
private final int minHeight;
|
||||
private final int maxHeight;
|
||||
private final Block[][][] blocks;
|
||||
|
||||
public CachedChunk(int minHeight, int maxHeight) {
|
||||
this.minHeight = minHeight;
|
||||
this.maxHeight = maxHeight;
|
||||
this.blocks = new Block[16][maxHeight - minHeight + 1][16];
|
||||
|
||||
for(int x = 0; x < 16; x++) {
|
||||
for(int z = 0; z < 16; z++) {
|
||||
for(int y = 0; y < maxHeight - minHeight + 1; y++) {
|
||||
blocks[x][y][z] = Block.AIR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void writeRelative(UnitModifier modifier) {
|
||||
modifier.setAllRelative((x, y, z) -> blocks[x][y][z]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, @NotNull BlockState blockState) {
|
||||
Block block = (Block) blockState.getHandle();
|
||||
if(block == null) return;
|
||||
blocks[x][y - minHeight][z] = block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getBlock(int x, int y, int z) {
|
||||
return new MinestomBlockState(blocks[x][y - minHeight][z]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return maxHeight;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.dfsek.terra.minestom.chunk;
|
||||
|
||||
import com.dfsek.terra.api.util.generic.pair.Pair;
|
||||
|
||||
import com.dfsek.terra.api.world.ServerWorld;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.github.benmanes.caffeine.cache.stats.CacheStats;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class GeneratedChunkCache {
|
||||
private static final Logger log = LoggerFactory.getLogger(GeneratedChunkCache.class);
|
||||
private final LoadingCache<Pair<Integer, Integer>, CachedChunk> cache;
|
||||
private final DimensionType dimensionType;
|
||||
private final ChunkGenerator generator;
|
||||
private final ServerWorld world;
|
||||
private final BiomeProvider biomeProvider;
|
||||
|
||||
public GeneratedChunkCache(DimensionType dimensionType, ChunkGenerator generator, ServerWorld world) {
|
||||
this.dimensionType = dimensionType;
|
||||
this.generator = generator;
|
||||
this.world = world;
|
||||
this.biomeProvider = world.getBiomeProvider();
|
||||
this.cache = Caffeine.newBuilder().maximumSize(128).recordStats().build(
|
||||
(Pair<Integer, Integer> key) -> generateChunk(key.getLeft(), key.getRight()));
|
||||
}
|
||||
|
||||
private CachedChunk generateChunk(int x, int z) {
|
||||
CachedChunk chunk = new CachedChunk(dimensionType.minY(), dimensionType.maxY());
|
||||
generator.generateChunkData(chunk, world, biomeProvider, x, z);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public void displayStats() {
|
||||
CacheStats stats = cache.stats();
|
||||
log.info("Avg load time: {}ms | Hit rate: {}% | Load Count: {}", stats.averageLoadPenalty(), stats.hitRate() * 100,
|
||||
stats.loadCount());
|
||||
}
|
||||
|
||||
public CachedChunk at(int x, int z) {
|
||||
return cache.get(Pair.of(x, z));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.dfsek.terra.minestom.chunk;
|
||||
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.world.ServerWorld;
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
|
||||
import com.dfsek.terra.minestom.block.MinestomBlockState;
|
||||
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public class TerraMinestomChunk implements Chunk {
|
||||
private net.minestom.server.instance.Chunk delegate;
|
||||
private final ServerWorld world;
|
||||
|
||||
public TerraMinestomChunk(net.minestom.server.instance.Chunk delegate, ServerWorld world) {
|
||||
this.delegate = delegate;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, BlockState data, boolean physics) {
|
||||
delegate.setBlock(x, y, z, (Block) data.getHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getBlock(int x, int y, int z) {
|
||||
return new MinestomBlockState(delegate.getBlock(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getX() {
|
||||
return delegate.getChunkX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZ() {
|
||||
return delegate.getChunkZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerWorld getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.dfsek.terra.minestom.entity;
|
||||
|
||||
import com.dfsek.terra.minestom.api.EntityFactory;
|
||||
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
|
||||
|
||||
public class DefaultEntityFactory implements EntityFactory {
|
||||
@Override
|
||||
public Entity createEntity(EntityType type) {
|
||||
return new Entity(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.dfsek.terra.minestom.entity;
|
||||
|
||||
import com.dfsek.terra.api.entity.Entity;
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.api.util.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.ServerWorld;
|
||||
import com.dfsek.terra.minestom.world.TerraMinestomWorld;
|
||||
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
|
||||
|
||||
public class DeferredMinestomEntity implements Entity {
|
||||
private final EntityType type;
|
||||
private double x;
|
||||
private double y;
|
||||
private double z;
|
||||
private TerraMinestomWorld world;
|
||||
|
||||
public DeferredMinestomEntity(double x, double y, double z, EntityType type, TerraMinestomWorld world) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.type = type;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 position() {
|
||||
return Vector3.of(x, y, z);
|
||||
}
|
||||
|
||||
public Pos pos() {
|
||||
return new Pos(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void position(Vector3 position) {
|
||||
x = position.getX();
|
||||
y = position.getY();
|
||||
z = position.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void world(ServerWorld world) {
|
||||
this.world = (TerraMinestomWorld) world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerWorld world() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void spawn() {
|
||||
int chunkX = (int) x >> 4;
|
||||
int chunkZ = (int) z >> 4;
|
||||
|
||||
if(!world.getHandle().isChunkLoaded(chunkX, chunkZ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MinestomEntity.spawn(x, y, z, type, world);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.dfsek.terra.minestom.entity;
|
||||
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.api.util.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.ServerWorld;
|
||||
|
||||
import com.dfsek.terra.minestom.MinestomAdapter;
|
||||
import com.dfsek.terra.minestom.world.TerraMinestomWorld;
|
||||
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.instance.Instance;
|
||||
|
||||
|
||||
public class MinestomEntity implements com.dfsek.terra.api.entity.Entity {
|
||||
private final Entity delegate;
|
||||
private final TerraMinestomWorld world;
|
||||
|
||||
public MinestomEntity(Entity delegate, TerraMinestomWorld world) {
|
||||
this.delegate = delegate;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 position() {
|
||||
return MinestomAdapter.adapt(delegate.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void position(Vector3 position) {
|
||||
delegate.teleport(MinestomAdapter.adapt(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void world(ServerWorld world) {
|
||||
delegate.setInstance(((TerraMinestomWorld) world).getHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerWorld world() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
public static MinestomEntity spawn(double x, double y, double z, EntityType type, TerraMinestomWorld world) {
|
||||
Instance instance = world.getHandle();
|
||||
Entity entity = world.getEntityFactory().createEntity(((MinestomEntityType) type).getHandle());
|
||||
entity.setInstance(instance, new Pos(x, y, z));
|
||||
return new MinestomEntity(entity, world);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.dfsek.terra.minestom.entity;
|
||||
|
||||
|
||||
import net.minestom.server.entity.EntityType;
|
||||
|
||||
|
||||
public class MinestomEntityType implements com.dfsek.terra.api.entity.EntityType {
|
||||
private final EntityType delegate;
|
||||
|
||||
public MinestomEntityType(String id) {
|
||||
delegate = EntityType.fromNamespaceId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityType getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.dfsek.terra.minestom.item;
|
||||
|
||||
import com.dfsek.terra.api.inventory.ItemStack;
|
||||
import com.dfsek.terra.api.inventory.item.Enchantment;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class MinestomEnchantment implements Enchantment {
|
||||
private final net.minestom.server.item.enchant.Enchantment delegate;
|
||||
private final String id;
|
||||
|
||||
public MinestomEnchantment(net.minestom.server.item.enchant.Enchantment delegate) {
|
||||
this.delegate = delegate;
|
||||
id = Objects.requireNonNull(delegate.registry()).raw();
|
||||
}
|
||||
|
||||
public MinestomEnchantment(String id) {
|
||||
this.delegate = MinecraftServer.getEnchantmentRegistry().get(NamespaceID.from(id));
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canEnchantItem(ItemStack itemStack) {
|
||||
return delegate.supportedItems().contains((Material) itemStack.getType().getHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean conflictsWith(Enchantment other) {
|
||||
return delegate.exclusiveSet().contains(NamespaceID.from(((MinestomEnchantment) other).id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxLevel() {
|
||||
return delegate.maxLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.minestom.server.item.enchant.Enchantment getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.dfsek.terra.minestom.item;
|
||||
|
||||
import com.dfsek.terra.api.handle.ItemHandle;
|
||||
import com.dfsek.terra.api.inventory.Item;
|
||||
import com.dfsek.terra.api.inventory.item.Enchantment;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
public class MinestomItemHandle implements ItemHandle {
|
||||
@Override
|
||||
public Item createItem(String data) {
|
||||
return new MinestomMaterial(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enchantment getEnchantment(String id) {
|
||||
return new MinestomEnchantment(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Enchantment> getEnchantments() {
|
||||
return MinecraftServer.getEnchantmentRegistry().values().stream().map(MinestomEnchantment::new).collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.dfsek.terra.minestom.item;
|
||||
|
||||
import com.dfsek.terra.api.inventory.item.Enchantment;
|
||||
import com.dfsek.terra.api.inventory.item.ItemMeta;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class MinestomItemMeta implements ItemMeta {
|
||||
private final HashMap<Enchantment, Integer> enchantments;
|
||||
|
||||
public MinestomItemMeta(HashMap<Enchantment, Integer> enchantments) {
|
||||
this.enchantments = enchantments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEnchantment(Enchantment enchantment, int level) {
|
||||
enchantments.put(enchantment, level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Enchantment, Integer> getEnchantments() {
|
||||
return enchantments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return enchantments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.dfsek.terra.minestom.item;
|
||||
|
||||
import com.dfsek.terra.api.inventory.Item;
|
||||
|
||||
import com.dfsek.terra.api.inventory.item.Enchantment;
|
||||
import com.dfsek.terra.api.inventory.item.ItemMeta;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.item.ItemComponent;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.component.EnchantmentList;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.registry.DynamicRegistry.Key;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class MinestomItemStack implements com.dfsek.terra.api.inventory.ItemStack {
|
||||
private ItemStack base;
|
||||
|
||||
public MinestomItemStack(net.minestom.server.item.@NotNull ItemStack base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAmount() {
|
||||
return base.amount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAmount(int i) {
|
||||
base = base.withAmount(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getType() {
|
||||
return new MinestomMaterial(base.material());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemMeta getItemMeta() {
|
||||
HashMap<Enchantment, Integer> enchantments = new HashMap<>();
|
||||
EnchantmentList enchantmentList = base.get(ItemComponent.ENCHANTMENTS);
|
||||
if(enchantmentList != null) {
|
||||
enchantmentList.enchantments().forEach((enchantmentKey, integer) -> {
|
||||
enchantments.put(
|
||||
new MinestomEnchantment(Objects.requireNonNull(MinecraftServer.getEnchantmentRegistry().get(enchantmentKey))), integer);
|
||||
});
|
||||
}
|
||||
return new MinestomItemMeta(enchantments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemMeta(ItemMeta meta) {
|
||||
HashMap<Key<net.minestom.server.item.enchant.Enchantment>, Integer> enchantments = new HashMap<>();
|
||||
DynamicRegistry<net.minestom.server.item.enchant.Enchantment> registry = MinecraftServer.getEnchantmentRegistry();
|
||||
meta.getEnchantments().forEach((key, value) -> {
|
||||
MinestomEnchantment enchantment = (MinestomEnchantment) key;
|
||||
enchantments.put(registry.getKey(enchantment.getHandle()), value);
|
||||
});
|
||||
|
||||
EnchantmentList list = new EnchantmentList(enchantments);
|
||||
base = base.with(ItemComponent.ENCHANTMENTS, list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.dfsek.terra.minestom.item;
|
||||
|
||||
import com.dfsek.terra.api.inventory.Item;
|
||||
import com.dfsek.terra.api.inventory.ItemStack;
|
||||
|
||||
import net.minestom.server.item.Material;
|
||||
|
||||
|
||||
public class MinestomMaterial implements Item {
|
||||
private final Material delegate;
|
||||
|
||||
public MinestomMaterial(Material delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public MinestomMaterial(String id) {
|
||||
this.delegate = Material.fromNamespaceId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack newItemStack(int amount) {
|
||||
return new MinestomItemStack(net.minestom.server.item.ItemStack.builder(delegate).amount(amount).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMaxDurability() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material getHandle() {
|
||||
return delegate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.dfsek.terra.minestom.world;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
|
||||
import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper;
|
||||
import com.dfsek.terra.minestom.chunk.CachedChunk;
|
||||
import com.dfsek.terra.minestom.chunk.GeneratedChunkCache;
|
||||
|
||||
import net.minestom.server.coordinate.Point;
|
||||
import net.minestom.server.instance.generator.GenerationUnit;
|
||||
import net.minestom.server.instance.generator.Generator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public class MinestomChunkGeneratorWrapper implements Generator, GeneratorWrapper {
|
||||
private final GeneratedChunkCache cache;
|
||||
private ChunkGenerator generator;
|
||||
private final TerraMinestomWorld world;
|
||||
private ConfigPack pack;
|
||||
|
||||
public MinestomChunkGeneratorWrapper(ChunkGenerator generator, TerraMinestomWorld world, ConfigPack pack) {
|
||||
this.generator = generator;
|
||||
this.world = world;
|
||||
this.pack = pack;
|
||||
this.cache = new GeneratedChunkCache(world.getDimensionType(), generator, world);
|
||||
}
|
||||
|
||||
public ChunkGenerator getGenerator() {
|
||||
return generator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(@NotNull GenerationUnit unit) {
|
||||
Point start = unit.absoluteStart();
|
||||
int x = start.chunkX();
|
||||
int z = start.chunkZ();
|
||||
CachedChunk chunk = cache.at(x, z);
|
||||
chunk.writeRelative(unit.modifier());
|
||||
|
||||
unit.fork(setter -> {
|
||||
MinestomProtoWorld protoWorld = new MinestomProtoWorld(cache, x, z, world, setter);
|
||||
|
||||
for(GenerationStage stage : world.getPack().getStages()) {
|
||||
stage.populate(protoWorld);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public ConfigPack getPack() {
|
||||
return pack;
|
||||
}
|
||||
|
||||
public void setPack(ConfigPack pack) {
|
||||
this.pack = pack;
|
||||
this.generator = pack.getGeneratorProvider().newInstance(pack);
|
||||
}
|
||||
|
||||
public void displayStats() {
|
||||
cache.displayStats();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getHandle() {
|
||||
return generator;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.dfsek.terra.minestom.world;
|
||||
|
||||
import com.dfsek.terra.api.block.entity.BlockEntity;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.entity.Entity;
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.api.world.ServerWorld;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
|
||||
import com.dfsek.terra.minestom.chunk.CachedChunk;
|
||||
import com.dfsek.terra.minestom.chunk.GeneratedChunkCache;
|
||||
|
||||
import com.dfsek.terra.minestom.entity.DeferredMinestomEntity;
|
||||
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.block.Block.Setter;
|
||||
|
||||
|
||||
public class MinestomProtoWorld implements ProtoWorld {
|
||||
private final GeneratedChunkCache cache;
|
||||
private final int x;
|
||||
private final int z;
|
||||
private final TerraMinestomWorld world;
|
||||
private final Setter modifier;
|
||||
|
||||
public MinestomProtoWorld(GeneratedChunkCache cache, int x, int z, TerraMinestomWorld world, Setter modifier) {
|
||||
this.cache = cache;
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.world = world;
|
||||
this.modifier = modifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int centerChunkX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int centerChunkZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerWorld getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockState(int x, int y, int z, BlockState data, boolean physics) {
|
||||
modifier.setBlock(x, y, z, (Block) data.getHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
|
||||
TerraMinestomWorld world = this.world;
|
||||
DeferredMinestomEntity entity = new DeferredMinestomEntity(x, y, z, entityType, world);
|
||||
world.enqueue(entity.pos(), (chunk) -> entity.spawn());
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(int x, int y, int z) {
|
||||
int chunkX = x >> 4;
|
||||
int chunkZ = z >> 4;
|
||||
CachedChunk chunk = cache.at(chunkX, chunkZ);
|
||||
return chunk.getBlock(x & 15, y, z & 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(int x, int y, int z) {
|
||||
return world.getBlockEntity(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getGenerator() {
|
||||
return world.getGenerator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeProvider getBiomeProvider() {
|
||||
return world.getBiomeProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigPack getPack() {
|
||||
return world.getPack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSeed() {
|
||||
return world.getSeed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return world.getMaxHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return world.getMinHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.dfsek.terra.minestom.world;
|
||||
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.api.handle.WorldHandle;
|
||||
|
||||
import com.dfsek.terra.minestom.block.MinestomBlockState;
|
||||
import com.dfsek.terra.minestom.entity.MinestomEntityType;
|
||||
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public class MinestomWorldHandle implements WorldHandle {
|
||||
private static final MinestomBlockState AIR = new MinestomBlockState(Block.AIR);
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState createBlockState(@NotNull String data) {
|
||||
return new MinestomBlockState(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState air() {
|
||||
return AIR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntityType getEntity(@NotNull String id) {
|
||||
return new MinestomEntityType(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package com.dfsek.terra.minestom.world;
|
||||
|
||||
import com.dfsek.terra.api.block.entity.BlockEntity;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.entity.Entity;
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.api.world.ServerWorld;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||
|
||||
import com.dfsek.terra.api.world.info.WorldProperties;
|
||||
|
||||
import com.dfsek.terra.minestom.api.BlockEntityFactory;
|
||||
import com.dfsek.terra.minestom.api.EntityFactory;
|
||||
import com.dfsek.terra.minestom.block.MinestomBlockState;
|
||||
import com.dfsek.terra.minestom.entity.MinestomEntity;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.coordinate.BlockVec;
|
||||
import net.minestom.server.coordinate.Point;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
|
||||
private final Instance instance;
|
||||
private final ConfigPack pack;
|
||||
private final long seed;
|
||||
private final DimensionType dimensionType;
|
||||
private final MinestomChunkGeneratorWrapper wrapper;
|
||||
private final EntityFactory entityFactory;
|
||||
private final BlockEntityFactory blockEntityFactory;
|
||||
|
||||
public TerraMinestomWorld(Instance instance, ConfigPack pack, long seed, EntityFactory entityFactory,
|
||||
BlockEntityFactory blockEntityFactory) {
|
||||
this.instance = instance;
|
||||
this.pack = pack;
|
||||
this.seed = seed;
|
||||
|
||||
this.dimensionType = MinecraftServer.getDimensionTypeRegistry().get(instance.getDimensionType());
|
||||
this.blockEntityFactory = blockEntityFactory;
|
||||
|
||||
this.wrapper = new MinestomChunkGeneratorWrapper(pack.getGeneratorProvider().newInstance(pack), this, pack);
|
||||
this.entityFactory = entityFactory;
|
||||
|
||||
instance.setGenerator(this.wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunkAt(int x, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockState(int x, int y, int z, BlockState data, boolean physics) {
|
||||
instance.setBlock(x, y, z, (Block) data.getHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
|
||||
return MinestomEntity.spawn(x, y, z, entityType, this);
|
||||
}
|
||||
|
||||
public void displayStats() {
|
||||
wrapper.displayStats();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(int x, int y, int z) {
|
||||
return new MinestomBlockState(instance.getBlock(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(int x, int y, int z) {
|
||||
return blockEntityFactory.createBlockEntity(new BlockVec(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getGenerator() {
|
||||
return wrapper.getGenerator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeProvider getBiomeProvider() {
|
||||
return pack.getBiomeProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigPack getPack() {
|
||||
return pack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSeed() {
|
||||
return seed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return dimensionType.maxY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return dimensionType.minY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instance getHandle() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public DimensionType getDimensionType() {
|
||||
return dimensionType;
|
||||
}
|
||||
|
||||
public EntityFactory getEntityFactory() {
|
||||
return entityFactory;
|
||||
}
|
||||
|
||||
public void enqueue(Point position, Consumer<net.minestom.server.instance.Chunk> action) {
|
||||
instance.loadChunk(position.chunkX(), position.chunkZ()).thenAccept(action);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.dfsek.terra.minestom.world;
|
||||
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
|
||||
import com.dfsek.terra.api.registry.CheckedRegistry;
|
||||
|
||||
import com.dfsek.terra.minestom.MinestomPlatform;
|
||||
import com.dfsek.terra.minestom.api.BlockEntityFactory;
|
||||
import com.dfsek.terra.minestom.api.EntityFactory;
|
||||
import com.dfsek.terra.minestom.block.DefaultBlockEntityFactory;
|
||||
import com.dfsek.terra.minestom.entity.DefaultEntityFactory;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.instance.Instance;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
||||
public class TerraMinestomWorldBuilder {
|
||||
private final Instance instance;
|
||||
private ConfigPack pack;
|
||||
private long seed = new Random().nextLong();
|
||||
private EntityFactory entityFactory = new DefaultEntityFactory();
|
||||
private BlockEntityFactory blockEntityFactory = new DefaultBlockEntityFactory();
|
||||
|
||||
private TerraMinestomWorldBuilder(Instance instance) { this.instance = instance; }
|
||||
|
||||
public static TerraMinestomWorldBuilder from(Instance instance) {
|
||||
return new TerraMinestomWorldBuilder(instance);
|
||||
}
|
||||
|
||||
public static TerraMinestomWorldBuilder builder() {
|
||||
return new TerraMinestomWorldBuilder(MinecraftServer.getInstanceManager().createInstanceContainer());
|
||||
}
|
||||
|
||||
public TerraMinestomWorldBuilder pack(ConfigPack pack) {
|
||||
this.pack = pack;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TerraMinestomWorldBuilder packById(String id) {
|
||||
this.pack = MinestomPlatform.getInstance().getConfigRegistry().getByID(id).orElseThrow();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public TerraMinestomWorldBuilder findPack(Function<CheckedRegistry<ConfigPack>, ConfigPack> fn) {
|
||||
this.pack = fn.apply(MinestomPlatform.getInstance().getConfigRegistry());
|
||||
return this;
|
||||
}
|
||||
|
||||
public TerraMinestomWorldBuilder defaultPack() {
|
||||
return this.packById("OVERWORLD");
|
||||
}
|
||||
|
||||
public TerraMinestomWorldBuilder seed(long seed) {
|
||||
this.seed = seed;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TerraMinestomWorldBuilder entityFactory(EntityFactory factory) {
|
||||
this.entityFactory = factory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TerraMinestomWorldBuilder blockEntityFactory(BlockEntityFactory factory) {
|
||||
this.blockEntityFactory = factory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TerraMinestomWorld attach() {
|
||||
return new TerraMinestomWorld(instance, pack, seed, entityFactory, blockEntityFactory);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user