Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/gradle-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ jobs:

steps:
- uses: actions/checkout@v4.2.2
- name: Set up JDK 21
- name: Set up JDK 25
uses: actions/setup-java@v4.7.1
with:
java-version: '21'
java-version: '25'
distribution: 'temurin'
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
Expand Down
2 changes: 1 addition & 1 deletion buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ dependencies {
//TODO Allow pulling from Versions.kt
implementation("com.gradleup.shadow", "shadow-gradle-plugin", "8.3.9")

implementation("io.papermc.paperweight.userdev", "io.papermc.paperweight.userdev.gradle.plugin", "2.0.0-beta.18")
implementation("io.papermc.paperweight.userdev", "io.papermc.paperweight.userdev.gradle.plugin", "2.0.0-beta.21")
implementation("org.ow2.asm", "asm", "9.9")
implementation("org.ow2.asm", "asm-tree", "9.9")
implementation("com.dfsek.tectonic", "common", "4.3.1")
Expand Down
11 changes: 3 additions & 8 deletions buildSrc/src/main/kotlin/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,14 @@ var isPrerelease = false


fun Project.getGitHash(): String {
val stdout = ByteArrayOutputStream()
exec {
return providers.exec {
commandLine = mutableListOf("git", "rev-parse", "--short", "HEAD")
standardOutput = stdout
}
return stdout.toString().trim()
}.standardOutput.asText.get().trim()
}

fun Project.gitClone(name: String) {
val stdout = ByteArrayOutputStream()
exec {
providers.exec {
commandLine = mutableListOf("git", "clone", name)
standardOutput = stdout
}
}

Expand Down
10 changes: 5 additions & 5 deletions buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,16 @@ object Versions {
// }

object Bukkit {
const val minecraft = "1.21.10"
const val minecraft = "26.1.2"
const val nms = "$minecraft-R0.1"
const val paperBuild = "$nms-20251012.013929-7"
const val paperBuild = "26.1.2.build.60-stable"
const val paper = paperBuild
const val paperLib = "1.0.8"
const val reflectionRemapper = "0.1.3"
const val paperDevBundle = paperBuild
const val runPaper = "2.3.1"
const val paperWeight = "2.0.0-beta.19"
const val cloud = "2.0.0-beta.12"
const val runPaper = "3.0.2"
const val paperWeight = "2.0.0-beta.21"
const val cloud = "2.0.0-beta.15"
const val multiverse = "5.3.0"
}

Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=845952a9d6afa783db70bb3b0effaae45ae5542ca2bb7929619e8af49cb634cf
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
4 changes: 4 additions & 0 deletions platforms/bukkit/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ dependencies {
shaded("xyz.jpenilla", "reflection-remapper", Versions.Bukkit.reflectionRemapper)
}

tasks.withType<JavaCompile>().configureEach {
options.release = 25
}

tasks {
shadowJar {
relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib")
Expand Down
3 changes: 3 additions & 0 deletions platforms/bukkit/common/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
repositories {

}
tasks.withType<JavaCompile>().configureEach {
options.release = 25
}

dependencies {
shadedApi(project(":common:implementation:base"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@


public interface NMSInitializer {
List<String> SUPPORTED_VERSIONS = List.of("v1.21.9", "v1.21.10");
List<String> SUPPORTED_VERSIONS = List.of("v26.1.2");
String MINECRAFT_VERSION = VersionUtil.getMinecraftVersionInfo().toString();
String TERRA_PACKAGE = NMSInitializer.class.getPackageName();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -29,6 +30,9 @@
import com.dfsek.terra.bukkit.util.BukkitUtils;
import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


public class BukkitWorldHandle implements WorldHandle {
private static final Logger logger = LoggerFactory.getLogger(BukkitWorldHandle.class);
Expand All @@ -40,9 +44,19 @@ public BukkitWorldHandle() {

@Override
public synchronized @NotNull BlockState createBlockState(@NotNull String data) {
org.bukkit.block.data.BlockData bukkitData = Bukkit.createBlockData(
data); // somehow bukkit managed to make this not thread safe! :)
return BukkitBlockState.newInstance(bukkitData);
try {
org.bukkit.block.data.BlockData bukkitData = Bukkit.createBlockData(data); // somehow bukkit managed to make this not thread safe! :)
return BukkitBlockState.newInstance(bukkitData);
} catch (Exception ignored) {
try {
Class<?> hacks = Class.forName("com.dfsek.terra.bukkit.nms.AwfulBukkitHacks");
Method method = hacks.getMethod("createBlockState", String.class);
Object result = method.invoke(null, data);
return BukkitBlockState.newInstance((BlockData) result);
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new IllegalArgumentException("Invalid block state data: " + data);
}
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ public static EntityType getEntityType(String id) {
if(!id.startsWith("minecraft:")) throw new IllegalArgumentException("Invalid entity identifier " + id);
String entityID = id.toUpperCase(Locale.ROOT).substring(10);

// TODO: remove this
// the default end seems to use this, this should be removed otherwise
// or replaced by a proper entity & NBT loader
if (entityID.contains("END_CRYSTAL")) {
entityID = "END_CRYSTAL";
}

return new BukkitEntityType(switch(entityID) {
case "END_CRYSTAL" -> org.bukkit.entity.EntityType.END_CRYSTAL;
case "ENDER_CRYSTAL" -> throw new IllegalArgumentException(
Expand Down
4 changes: 4 additions & 0 deletions platforms/bukkit/nms/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ plugins {
id("io.papermc.paperweight.userdev")
}

tasks.withType<JavaCompile>().configureEach {
options.release = 25
}

dependencies {
api(project(":platforms:bukkit:common"))
paperweight.paperDevBundle(Versions.Bukkit.paperDevBundle)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
package com.dfsek.terra.bukkit.nms;

import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.commands.arguments.blocks.BlockStateParser;
import net.minecraft.commands.arguments.blocks.BlockStateParser.BlockResult;
import net.minecraft.core.Holder;
import net.minecraft.core.Holder.Reference;
import net.minecraft.core.HolderSet;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.HolderSet.Named;
import net.minecraft.core.MappedRegistry;
import net.minecraft.core.RegistrationInfo;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.tags.TagKey;
import net.minecraft.world.entity.npc.VillagerType;
import net.minecraft.world.entity.npc.villager.VillagerType;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -34,7 +45,7 @@
public class AwfulBukkitHacks {
private static final Logger LOGGER = LoggerFactory.getLogger(AwfulBukkitHacks.class);

private static final Map<ResourceLocation, List<ResourceLocation>> terraBiomeMap = new HashMap<>();
private static final Map<Identifier, List<Identifier>> terraBiomeMap = new HashMap<>();

public static void registerBiomes(ConfigRegistry configRegistry) {
try {
Expand All @@ -50,15 +61,15 @@ public static void registerBiomes(ConfigRegistry configRegistry) {
BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome();

NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey();
ResourceLocation vanillaMinecraftKey = ResourceLocation.fromNamespaceAndPath(vanillaBukkitKey.getNamespace(),
Identifier vanillaMinecraftKey = Identifier.fromNamespaceAndPath(vanillaBukkitKey.getNamespace(),
vanillaBukkitKey.getKey());

VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class);

Biome platform = NMSBiomeInjector.createBiome(biomeRegistry.get(vanillaMinecraftKey).orElseThrow().value(),
vanillaBiomeProperties);

ResourceLocation delegateMinecraftKey = ResourceLocation.fromNamespaceAndPath("terra",
Identifier delegateMinecraftKey = Identifier.fromNamespaceAndPath("terra",
NMSBiomeInjector.createBiomeID(pack, key));
NamespacedKey delegateBukkitKey = NamespacedKey.fromString(delegateMinecraftKey.toString());
ResourceKey<Biome> delegateKey = ResourceKey.create(Registries.BIOME, delegateMinecraftKey);
Expand All @@ -75,7 +86,7 @@ public static void registerBiomes(ConfigRegistry configRegistry) {
Objects.requireNonNullElse(vanillaBiomeProperties.getVillagerType(),
villagerMap.getOrDefault(delegateKey, VillagerType.PLAINS)));

terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.location());
terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.identifier());

LOGGER.debug("Registered biome: " + delegateKey);
} catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
Expand All @@ -100,8 +111,8 @@ public static void registerBiomes(ConfigRegistry configRegistry) {
tb -> NMSBiomeInjector.getEntry(biomeRegistry, tb).ifPresentOrElse(
terra -> {
LOGGER.debug("{} (vanilla for {}): {}",
vanilla.unwrapKey().orElseThrow().location(),
terra.unwrapKey().orElseThrow().location(),
vanilla.unwrapKey().orElseThrow().identifier(),
terra.unwrapKey().orElseThrow().identifier(),
vanilla.tags().toList());
vanilla.tags()
.forEach(tag -> collect
Expand All @@ -120,7 +131,7 @@ public static void registerBiomes(ConfigRegistry configRegistry) {
}

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<>();
Map<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) {
Expand All @@ -145,7 +156,7 @@ private static <T> void bindTags(MappedRegistry<T> registry, Map<TagKey<T>, List
// );
// }

Map<TagKey<T>, HolderSet.Named<T>> map2 = new IdentityHashMap<>(registry.getTags().collect(Collectors.toMap(
Map<TagKey<T>, Named<T>> map2 = new IdentityHashMap<>(registry.getTags().collect(Collectors.toMap(
Named::key,
(named) -> named
)));
Expand All @@ -160,5 +171,14 @@ private static void resetTags(MappedRegistry<?> registry) {
Reflection.MAPPED_REGISTRY.getByKey(registry).values().forEach(
entry -> Reflection.HOLDER_REFERENCE.invokeBindTags(entry, Set.of()));
}

// used by BukkitWorldHandle
public static BlockData createBlockState(@NotNull String data) throws CommandSyntaxException {
MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer();
HolderLookup.Provider lookup = server.registryAccess();
final HolderLookup<Block> blocks = lookup.lookupOrThrow(Registries.BLOCK);
BlockResult result = BlockStateParser.parseForBlock(blocks, new StringReader(data), true);
return CraftBlockData.createData(result.blockState());
}
}

Loading
Loading