Merge remote-tracking branch 'origin/master'

This commit is contained in:
Zoë Gidiere 2025-07-10 19:42:38 -06:00
commit c658d1a81b
10 changed files with 138 additions and 63 deletions

View File

@ -21,8 +21,6 @@ import com.dfsek.tectonic.api.TypeRegistry;
import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.terra.bukkit.nms.Initializer;
import io.papermc.paper.registry.RegistryAccess;
import io.papermc.paper.registry.RegistryKey;
import org.bukkit.Bukkit;
@ -33,10 +31,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.List;
import com.dfsek.terra.AbstractPlatform;
import com.dfsek.terra.api.addon.BaseAddon;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.handle.ItemHandle;
import com.dfsek.terra.api.handle.WorldHandle;
@ -99,11 +95,6 @@ public class PlatformImpl extends AbstractPlatform {
plugin.getGlobalRegionScheduler().run(plugin, task -> runnable.run());
}
@Override
protected Iterable<BaseAddon> platformAddon() {
return List.of(Initializer.nmsAddon(this));
}
@Override
public @NotNull WorldHandle getWorldHandle() {
return handle;
@ -133,7 +124,7 @@ public class PlatformImpl extends AbstractPlatform {
}
private BukkitPlatformBiome parseBiome(String id, DepthTracker depthTracker) throws LoadException {
protected BukkitPlatformBiome parseBiome(String id, DepthTracker depthTracker) throws LoadException {
NamespacedKey key = NamespacedKey.fromString(id);
if(key == null || !key.namespace().equals("minecraft")) throw new LoadException("Invalid biome identifier " + id, depthTracker);
return new BukkitPlatformBiome(RegistryAccess.registryAccess().getRegistry(RegistryKey.BIOME).getOrThrow(key));

View File

@ -51,7 +51,7 @@ import com.dfsek.terra.bukkit.world.BukkitAdapter;
public class TerraBukkitPlugin extends JavaPlugin {
private static final Logger logger = LoggerFactory.getLogger(TerraBukkitPlugin.class);
private final PlatformImpl platform = new PlatformImpl(this);
private PlatformImpl platform;
private final Map<String, com.dfsek.terra.api.world.chunk.generation.ChunkGenerator> generatorMap = new HashMap<>();
private AsyncScheduler asyncScheduler = this.getServer().getAsyncScheduler();
@ -64,13 +64,14 @@ public class TerraBukkitPlugin extends JavaPlugin {
return;
}
platform.getEventManager().callEvent(new PlatformInitializationEvent());
if(!Initializer.init(platform)) {
platform = Initializer.init(this);
if(platform == null) {
Bukkit.getPluginManager().disablePlugin(this);
return;
}
platform.getEventManager().callEvent(new PlatformInitializationEvent());
try {
LegacyPaperCommandManager<CommandSender> commandManager = getCommandSenderPaperCommandManager();

View File

@ -1,6 +1,6 @@
package com.dfsek.terra.bukkit.nms;
import com.dfsek.terra.bukkit.BukkitAddon;
import com.dfsek.terra.bukkit.TerraBukkitPlugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -13,13 +13,11 @@ public interface Initializer {
String NMS = VersionUtil.getMinecraftVersionInfo().toString().replace(".", "_");
String TERRA_PACKAGE = Initializer.class.getPackageName();
static boolean init(PlatformImpl platform) {
static PlatformImpl init(TerraBukkitPlugin plugin) {
Logger logger = LoggerFactory.getLogger(Initializer.class);
Initializer initializer = constructInitializer();
if(initializer != null) {
initializer.initialize(platform);
} else {
PlatformImpl platform = constructPlatform(plugin);
if (platform == null) {
logger.error("NMS bindings for version {} do not exist. Support for this version is limited.", NMS);
logger.error("This is usually due to running Terra on an unsupported Minecraft version.");
String bypassKey = "IKnowThereAreNoNMSBindingsFor" + NMS + "ButIWillProceedAnyway";
@ -27,7 +25,7 @@ public interface Initializer {
logger.error("Because of this **TERRA HAS BEEN DISABLED**.");
logger.error("Do not come ask us why it is not working.");
logger.error("If you wish to proceed anyways, you can add the JVM System Property \"{}\" to enable the plugin.", bypassKey);
return false;
return null;
} else {
logger.error("");
logger.error("");
@ -43,24 +41,21 @@ public interface Initializer {
}
}
return true;
return platform;
}
static BukkitAddon nmsAddon(PlatformImpl platform) {
Initializer initializer = constructInitializer();
return initializer != null ? initializer.getNMSAddon(platform) : new BukkitAddon(platform);
}
private static Initializer constructInitializer() {
private static PlatformImpl constructPlatform(TerraBukkitPlugin plugin) {
try {
String packageVersion = NMS;
if (NMS.equals("v1_21_5") || NMS.equals("v1_21_6")) {
packageVersion = "v1_21_7";
}
Class<?> initializerClass = Class.forName(TERRA_PACKAGE + "." + packageVersion + ".NMSInitializer");
Class<?> platformClass = Class.forName(TERRA_PACKAGE + "." + packageVersion + ".NMSPlatform");
try {
return (Initializer) initializerClass.getConstructor().newInstance();
return (PlatformImpl) platformClass
.getConstructor(TerraBukkitPlugin.class)
.newInstance(plugin);
} catch(ReflectiveOperationException e) {
throw new RuntimeException("Error initializing NMS bindings. Report this to Terra.", e);
}
@ -68,8 +63,4 @@ public interface Initializer {
return null;
}
}
void initialize(PlatformImpl plugin);
BukkitAddon getNMSAddon(PlatformImpl plugin);
}

View File

@ -14,6 +14,7 @@ import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.entity.npc.VillagerType;
import net.minecraft.world.level.biome.Biome;
import org.bukkit.NamespacedKey;
import org.slf4j.Logger;
@ -24,6 +25,7 @@ import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@ -48,6 +50,7 @@ public class AwfulBukkitHacks {
configRegistry.forEach(pack -> pack.getRegistry(com.dfsek.terra.api.world.biome.Biome.class).forEach((key, biome) -> {
try {
BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome();
NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey();
ResourceLocation vanillaMinecraftKey = ResourceLocation.fromNamespaceAndPath(vanillaBukkitKey.getNamespace(),
vanillaBukkitKey.getKey());
@ -66,6 +69,12 @@ public class AwfulBukkitHacks {
platformBiome.getContext().put(new BukkitBiomeInfo(delegateBukkitKey));
platformBiome.getContext().put(new NMSBiomeInfo(delegateKey));
Map<ResourceKey<Biome>, ResourceKey<VillagerType>> villagerMap = Reflection.VILLAGER_TYPE.getByBiome();
villagerMap.put(delegateKey,
Objects.requireNonNullElse(vanillaBiomeProperties.getVillagerType(),
villagerMap.getOrDefault(delegateKey, VillagerType.PLAINS)));
terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.location());
LOGGER.debug("Registered biome: " + delegateKey);

View File

@ -1,22 +0,0 @@
package com.dfsek.terra.bukkit.nms.v1_21_7;
import com.dfsek.terra.bukkit.BukkitAddon;
import org.bukkit.Bukkit;
import com.dfsek.terra.bukkit.PlatformImpl;
import com.dfsek.terra.bukkit.nms.Initializer;
public class NMSInitializer implements Initializer {
@Override
public void initialize(PlatformImpl platform) {
AwfulBukkitHacks.registerBiomes(platform.getRawConfigRegistry());
Bukkit.getPluginManager().registerEvents(new NMSInjectListener(), platform.getPlugin());
}
@Override
public BukkitAddon getNMSAddon(PlatformImpl plugin) {
return new NMSAddon(plugin);
}
}

View File

@ -0,0 +1,93 @@
package com.dfsek.terra.bukkit.nms.v1_21_7;
import com.dfsek.tectonic.api.TypeRegistry;
import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.terra.api.addon.BaseAddon;
import com.dfsek.terra.api.world.biome.PlatformBiome;
import com.dfsek.terra.bukkit.PlatformImpl;
import com.dfsek.terra.bukkit.TerraBukkitPlugin;
import com.dfsek.terra.bukkit.nms.v1_21_7.config.BiomeAdditionsSoundTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_7.config.BiomeMoodSoundTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_7.config.BiomeParticleConfigTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_7.config.EntityTypeTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_7.config.MusicSoundTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_7.config.SoundEventTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_7.config.SpawnCostConfig;
import com.dfsek.terra.bukkit.nms.v1_21_7.config.SpawnEntryConfig;
import com.dfsek.terra.bukkit.nms.v1_21_7.config.SpawnSettingsTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_7.config.SpawnTypeConfig;
import com.dfsek.terra.bukkit.nms.v1_21_7.config.VillagerTypeTemplate;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.Music;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.entity.npc.VillagerType;
import net.minecraft.world.level.biome.AmbientAdditionsSettings;
import net.minecraft.world.level.biome.AmbientMoodSettings;
import net.minecraft.world.level.biome.AmbientParticleSettings;
import net.minecraft.world.level.biome.Biome.Precipitation;
import net.minecraft.world.level.biome.Biome.TemperatureModifier;
import net.minecraft.world.level.biome.BiomeSpecialEffects.GrassColorModifier;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData;
import org.bukkit.Bukkit;
import java.util.List;
import java.util.Locale;
public class NMSPlatform extends PlatformImpl {
public NMSPlatform(TerraBukkitPlugin plugin) {
super(plugin);
AwfulBukkitHacks.registerBiomes(this.getRawConfigRegistry());
Bukkit.getPluginManager().registerEvents(new NMSInjectListener(), plugin);
}
@Override
public void register(TypeRegistry registry) {
super.register(registry);
registry.registerLoader(PlatformBiome.class, (type, o, loader, depthTracker) -> parseBiome((String) o, depthTracker))
.registerLoader(ResourceLocation.class, (type, o, loader, depthTracker) -> {
ResourceLocation identifier = ResourceLocation.tryParse((String) o);
if(identifier == null)
throw new LoadException("Invalid identifier: " + o, depthTracker);
return identifier;
})
.registerLoader(Precipitation.class, (type, o, loader, depthTracker) -> Precipitation.valueOf(((String) o).toUpperCase(
Locale.ROOT)))
.registerLoader(GrassColorModifier.class,
(type, o, loader, depthTracker) -> GrassColorModifier.valueOf(((String) o).toUpperCase(
Locale.ROOT)))
.registerLoader(GrassColorModifier.class,
(type, o, loader, depthTracker) -> TemperatureModifier.valueOf(((String) o).toUpperCase(
Locale.ROOT)))
.registerLoader(MobCategory.class, (type, o, loader, depthTracker) -> MobCategory.valueOf((String) o))
.registerLoader(AmbientParticleSettings.class, BiomeParticleConfigTemplate::new)
.registerLoader(SoundEvent.class, SoundEventTemplate::new)
.registerLoader(AmbientMoodSettings.class, BiomeMoodSoundTemplate::new)
.registerLoader(AmbientAdditionsSettings.class, BiomeAdditionsSoundTemplate::new)
.registerLoader(Music.class, MusicSoundTemplate::new)
.registerLoader(EntityType.class, EntityTypeTemplate::new)
.registerLoader(SpawnCostConfig.class, SpawnCostConfig::new)
.registerLoader(SpawnEntryConfig.class, SpawnEntryConfig::new)
.registerLoader(SpawnTypeConfig.class, SpawnTypeConfig::new)
.registerLoader(MobSpawnSettings.class, SpawnSettingsTemplate::new)
.registerLoader(VillagerType.class, VillagerTypeTemplate::new);
}
@Override
protected Iterable<BaseAddon> platformAddon() {
return List.of(new NMSAddon(this));
}
}

View File

@ -7,6 +7,7 @@ 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.entity.npc.VillagerType;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.biome.Biome;
@ -36,6 +37,7 @@ public class Reflection {
public static final HolderReferenceProxy HOLDER_REFERENCE;
public static final HolderSetNamedProxy HOLDER_SET;
public static final BiomeProxy BIOME;
public static final VillagerTypeProxy VILLAGER_TYPE;
static {
ReflectionRemapper reflectionRemapper = ReflectionRemapper.forReobfMappingsInPaperJar();
@ -50,6 +52,7 @@ public class Reflection {
HOLDER_REFERENCE = reflectionProxyFactory.reflectionProxy(HolderReferenceProxy.class);
HOLDER_SET = reflectionProxyFactory.reflectionProxy(HolderSetNamedProxy.class);
BIOME = reflectionProxyFactory.reflectionProxy(BiomeProxy.class);
VILLAGER_TYPE = reflectionProxyFactory.reflectionProxy(VillagerTypeProxy.class);
}
@ -121,4 +124,11 @@ public class Reflection {
@MethodName("getGrassColorFromTexture")
int invokeGrassColorFromTexture(Biome instance);
}
@Proxies(VillagerType.class)
public interface VillagerTypeProxy {
@Static
@FieldGetter("BY_BIOME")
Map<ResourceKey<Biome>, ResourceKey<VillagerType>> getByBiome();
}
}

View File

@ -18,11 +18,11 @@ public class BiomeParticleConfigTemplate implements ObjectTemplate<AmbientPartic
@Value("probability")
@Default
private Integer probability = null;
private Float probability = 0.1f;
@Override
public AmbientParticleSettings get() {
if(particle == null || probability == null) {
if(particle == null) {
return null;
}

View File

@ -6,6 +6,7 @@ import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.terra.api.properties.Properties;
import net.minecraft.resources.ResourceKey;
import net.minecraft.sounds.Music;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.entity.npc.VillagerType;
@ -96,7 +97,7 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties {
@Value("villager-type")
@Default
private VillagerType villagerType = null;
private ResourceKey<VillagerType> villagerType = null;
public Integer getFogColor() {
return fogColor;
@ -174,7 +175,7 @@ public class VanillaBiomeProperties implements ConfigTemplate, Properties {
return spawnSettings;
}
public VillagerType getVillagerType() {
public ResourceKey<VillagerType> getVillagerType() {
return villagerType;
}
}

View File

@ -4,17 +4,18 @@ import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.npc.VillagerType;
public class VillagerTypeTemplate implements ObjectTemplate<VillagerType> {
public class VillagerTypeTemplate implements ObjectTemplate<ResourceKey<VillagerType>> {
@Value("id")
@Default
private ResourceLocation id = null;
@Override
public VillagerType get() {
return BuiltInRegistries.VILLAGER_TYPE.get(id).orElseThrow().value();
public ResourceKey<VillagerType> get() {
return ResourceKey.create(BuiltInRegistries.VILLAGER_TYPE.key(), id);
}
}