Remove unneeded subprojects

This commit is contained in:
NotAlexNoyle committed 2025-06-11 15:31:36 -04:00
1 parent 609fea09f6
commit eda3874ba7
59 files changed
+51 -2838

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="output" path="bin/default"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17/"/>
</classpath>
+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Chunky</name>
<comment>Pre-generates chunks, quickly, efficiently, and safely</comment>
<projects/>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments/>
</buildCommand>
</buildSpec>
<linkedResources/>
<filteredResources/>
</projectDescription>
+25 -24
View File
@@ -1,17 +1,20 @@
import java.io.ByteArrayOutputStream
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.tasks.bundling.Jar
plugins {
eclipse
id("java-library")
id("maven-publish")
id("com.github.johnrengelman.shadow") version "8.1.1"
id("com.gradleup.shadow") version "8.3.6" apply false
}
subprojects {
plugins.apply("java-library")
plugins.apply("maven-publish")
plugins.apply("com.github.johnrengelman.shadow")
plugins.apply("com.gradleup.shadow")
group = "${project.property("group")}"
group = project.property("group") as String
version = "${project.property("version")}.${commitsSinceLastTag()}"
repositories {
@@ -20,9 +23,7 @@ subprojects {
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
withSourcesJar()
}
@@ -32,37 +33,38 @@ subprojects {
options.release = 17
options.compilerArgs.add("-Xlint:none")
}
jar {
named<Jar>("jar") {
archiveClassifier.set("noshade")
}
shadowJar {
named<ShadowJar>("shadowJar") {
archiveClassifier.set("")
archiveFileName.set("${project.property("artifactName")}-${project.version}.jar")
}
build {
dependsOn(shadowJar)
named("build") {
dependsOn("shadowJar")
}
}
publishing {
repositories {
if (project.hasProperty("mavenUsername") && project.hasProperty("mavenPassword")) {
if (hasProperty("mavenUsername") && hasProperty("mavenPassword")) {
maven {
credentials {
username = "${project.property("mavenUsername")}"
password = "${project.property("mavenPassword")}"
username = project.property("mavenUsername") as String
password = project.property("mavenPassword") as String
}
url = uri("https://repo.codemc.io/repository/maven-releases/")
}
}
}
publications {
create<MavenPublication>("maven") {
groupId = "${project.group}"
artifactId = project.name
version = "${project.version}"
from(components["java"])
}
publications.create<MavenPublication>("maven") {
groupId = project.group.toString()
artifactId = project.name
version = project.version.toString()
from(components["java"])
}
}
}
@@ -73,8 +75,7 @@ fun commitsSinceLastTag(): String {
commandLine("git", "describe", "--tags")
standardOutput = tagDescription
}
if (tagDescription.toString().indexOf('-') < 0) {
return "0"
}
return tagDescription.toString().split('-')[1]
val desc = tagDescription.toString().trim()
return if ('-' !in desc) "0" else desc.split('-')[1]
}
+4
View File
@@ -1,3 +1,7 @@
plugins {
id("com.gradleup.shadow")
}
repositories {
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
maven("https://repo.papermc.io/repository/maven-public/")
-39
View File
@@ -1,39 +0,0 @@
plugins {
id("dev.architectury.loom") version "1.5-SNAPSHOT"
}
val shade: Configuration by configurations.creating
dependencies {
minecraft(group = "com.mojang", name = "minecraft", version = "1.20")
mappings(group = "net.fabricmc", name = "yarn", version = "1.20+build.1", classifier = "v2")
modImplementation(group = "net.fabricmc", name = "fabric-loader", version = "0.14.21")
modImplementation(group = "net.fabricmc.fabric-api", name = "fabric-api", version = "0.83.0+1.20")
modCompileOnly(group = "me.lucko", name = "fabric-permissions-api", version = "0.2-SNAPSHOT")
implementation(project(":Chunky-common"))
shade(project(":Chunky-common"))
}
tasks {
processResources {
filesMatching("fabric.mod.json") {
expand(
"id" to rootProject.name,
"version" to project.version,
"name" to project.property("artifactName"),
"description" to project.property("description"),
"author" to project.property("author"),
"github" to project.property("github")
)
}
}
shadowJar {
configurations = listOf(shade)
archiveClassifier.set("dev")
archiveFileName.set(null as String?)
}
remapJar {
inputFile.set(shadowJar.get().archiveFile)
archiveFileName.set("${project.property("artifactName")}-${project.version}.jar")
}
}
@@ -1,174 +0,0 @@
package org.popcraft.chunky;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.entity.boss.ServerBossBar;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;
import org.popcraft.chunky.command.ChunkyCommand;
import org.popcraft.chunky.command.CommandArguments;
import org.popcraft.chunky.command.CommandLiteral;
import org.popcraft.chunky.command.suggestion.SuggestionProviders;
import org.popcraft.chunky.event.task.GenerationTaskFinishEvent;
import org.popcraft.chunky.event.task.GenerationTaskUpdateEvent;
import org.popcraft.chunky.listeners.bossbar.BossBarTaskFinishListener;
import org.popcraft.chunky.listeners.bossbar.BossBarTaskUpdateListener;
import org.popcraft.chunky.platform.FabricPlayer;
import org.popcraft.chunky.platform.FabricSender;
import org.popcraft.chunky.platform.FabricServer;
import org.popcraft.chunky.platform.Sender;
import org.popcraft.chunky.platform.impl.GsonConfig;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static com.mojang.brigadier.arguments.StringArgumentType.string;
import static com.mojang.brigadier.arguments.StringArgumentType.word;
import static net.minecraft.command.argument.DimensionArgumentType.dimension;
import static net.minecraft.command.argument.EntityArgumentType.player;
import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal;
public class ChunkyFabric implements ModInitializer {
private Chunky chunky;
private final Map<Identifier, ServerBossBar> bossBars = new ConcurrentHashMap<>();
@Override
public void onInitialize() {
ServerLifecycleEvents.SERVER_STARTED.register(minecraftServer -> {
final Path configPath = FabricLoader.getInstance().getConfigDir().resolve("chunky/config.json");
this.chunky = new Chunky(new FabricServer(this, minecraftServer), new GsonConfig(configPath));
if (chunky.getConfig().getContinueOnRestart()) {
chunky.getCommands().get(CommandLiteral.CONTINUE).execute(chunky.getServer().getConsole(), CommandArguments.empty());
}
chunky.getEventBus().subscribe(GenerationTaskUpdateEvent.class, new BossBarTaskUpdateListener(bossBars));
chunky.getEventBus().subscribe(GenerationTaskFinishEvent.class, new BossBarTaskFinishListener(bossBars));
FabricLoader.getInstance().getEntrypointContainers("chunky", ModInitializer.class)
.forEach(entryPoint -> entryPoint.getEntrypoint().onInitialize());
});
ServerLifecycleEvents.SERVER_STOPPING.register(minecraftServer -> {
if (chunky != null) {
chunky.disable();
}
});
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
final LiteralArgumentBuilder<ServerCommandSource> command = literal(CommandLiteral.CHUNKY)
.requires(serverCommandSource -> {
if (serverCommandSource.getServer().isSingleplayer()) {
return true;
}
return new FabricSender(serverCommandSource).hasPermission("chunky.command", true);
})
.executes(context -> {
final Sender sender;
if (context.getSource().getEntity() instanceof final ServerPlayerEntity player) {
sender = new FabricPlayer(player);
} else {
sender = new FabricSender(context.getSource());
}
final Map<String, ChunkyCommand> commands = chunky.getCommands();
final String input = context.getInput().substring(context.getLastChild().getNodes().get(0).getRange().getStart());
final String[] tokens = input.split(" ");
final String subCommand = tokens.length > 1 && commands.containsKey(tokens[1]) ? tokens[1] : CommandLiteral.HELP;
final CommandArguments arguments = tokens.length > 2 ? CommandArguments.of(Arrays.copyOfRange(tokens, 2, tokens.length)) : CommandArguments.empty();
commands.get(subCommand).execute(sender, arguments);
return Command.SINGLE_SUCCESS;
});
registerArguments(command, literal(CommandLiteral.CANCEL),
argument(CommandLiteral.WORLD, dimension()));
registerArguments(command, literal(CommandLiteral.CENTER),
argument(CommandLiteral.X, word()),
argument(CommandLiteral.Z, word()));
registerArguments(command, literal(CommandLiteral.CONFIRM));
registerArguments(command, literal(CommandLiteral.CONTINUE),
argument(CommandLiteral.WORLD, dimension()));
registerArguments(command, literal(CommandLiteral.CORNERS),
argument(CommandLiteral.X1, word()),
argument(CommandLiteral.Z1, word()),
argument(CommandLiteral.X2, word()),
argument(CommandLiteral.Z2, word()));
registerArguments(command, literal(CommandLiteral.HELP),
argument(CommandLiteral.PAGE, integer()));
registerArguments(command, literal(CommandLiteral.PATTERN),
argument(CommandLiteral.PATTERN, string()).suggests(SuggestionProviders.PATTERNS),
argument(CommandLiteral.VALUE, string()));
registerArguments(command, literal(CommandLiteral.PAUSE),
argument(CommandLiteral.WORLD, dimension()));
registerArguments(command, literal(CommandLiteral.PROGRESS));
registerArguments(command, literal(CommandLiteral.QUIET),
argument(CommandLiteral.INTERVAL, integer()));
registerArguments(command, literal(CommandLiteral.RADIUS),
argument(CommandLiteral.RADIUS, word()),
argument(CommandLiteral.RADIUS, word()));
registerArguments(command, literal(CommandLiteral.RELOAD),
argument(CommandLiteral.TYPE, word()));
registerArguments(command, literal(CommandLiteral.SELECTION));
registerArguments(command, literal(CommandLiteral.SHAPE),
argument(CommandLiteral.SHAPE, string()).suggests(SuggestionProviders.SHAPES));
registerArguments(command, literal(CommandLiteral.SILENT));
registerArguments(command, literal(CommandLiteral.SPAWN));
registerArguments(command, literal(CommandLiteral.START),
argument(CommandLiteral.WORLD, dimension()),
argument(CommandLiteral.SHAPE, string()).suggests(SuggestionProviders.SHAPES),
argument(CommandLiteral.CENTER_X, word()),
argument(CommandLiteral.CENTER_Z, word()),
argument(CommandLiteral.RADIUS_X, word()),
argument(CommandLiteral.RADIUS_Z, word()));
registerArguments(command, literal(CommandLiteral.TRIM),
argument(CommandLiteral.WORLD, dimension()),
argument(CommandLiteral.SHAPE, string()).suggests(SuggestionProviders.SHAPES),
argument(CommandLiteral.CENTER_X, word()),
argument(CommandLiteral.CENTER_Z, word()),
argument(CommandLiteral.RADIUS_X, word()),
argument(CommandLiteral.RADIUS_Z, word()),
argument(CommandLiteral.TRIM_MODE, string()).suggests(SuggestionProviders.TRIM_MODES),
argument(CommandLiteral.INHABITED, word()));
registerArguments(command, literal(CommandLiteral.WORLDBORDER));
registerArguments(command, literal(CommandLiteral.WORLD),
argument(CommandLiteral.WORLD, dimension()));
final LiteralArgumentBuilder<ServerCommandSource> borderCommand = literal(CommandLiteral.BORDER)
.requires(serverCommandSource -> chunky != null && chunky.getCommands().containsKey(CommandLiteral.BORDER))
.executes(command.getCommand());
registerArguments(borderCommand, literal(CommandLiteral.ADD),
argument(CommandLiteral.WORLD, dimension()),
argument(CommandLiteral.SHAPE, string()).suggests(SuggestionProviders.SHAPES),
argument(CommandLiteral.CENTER_X, word()),
argument(CommandLiteral.CENTER_Z, word()),
argument(CommandLiteral.RADIUS_X, word()),
argument(CommandLiteral.RADIUS_Z, word()));
registerArguments(borderCommand, literal(CommandLiteral.BYPASS),
argument(CommandLiteral.PLAYER, player()));
registerArguments(borderCommand, literal(CommandLiteral.HELP));
registerArguments(borderCommand, literal(CommandLiteral.LIST));
registerArguments(borderCommand, literal(CommandLiteral.LOAD),
argument(CommandLiteral.WORLD, dimension()));
registerArguments(borderCommand, literal(CommandLiteral.REMOVE),
argument(CommandLiteral.WORLD, dimension()));
registerArguments(borderCommand, literal(CommandLiteral.WRAP),
argument(CommandLiteral.WRAP, word()));
registerArguments(command, borderCommand);
dispatcher.register(command);
});
}
@SafeVarargs
private <S> void registerArguments(final LiteralArgumentBuilder<S> command, final ArgumentBuilder<S, ?>... arguments) {
for (int i = arguments.length - 1; i > 0; --i) {
arguments[i - 1].then(arguments[i].executes(command.getCommand()));
}
command.then(arguments[0].executes(command.getCommand()));
}
public Chunky getChunky() {
return chunky;
}
}
@@ -1,28 +0,0 @@
package org.popcraft.chunky.command.suggestion;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.server.command.ServerCommandSource;
import org.popcraft.chunky.command.CommandLiteral;
import org.popcraft.chunky.iterator.PatternType;
import java.util.concurrent.CompletableFuture;
public class PatternSuggestionProvider implements SuggestionProvider<ServerCommandSource> {
@Override
public CompletableFuture<Suggestions> getSuggestions(final CommandContext<ServerCommandSource> context, final SuggestionsBuilder builder) {
try {
final String input = context.getArgument(CommandLiteral.PATTERN, String.class);
PatternType.ALL.forEach(pattern -> {
if (pattern.contains(input.toLowerCase())) {
builder.suggest(pattern);
}
});
} catch (IllegalArgumentException e) {
PatternType.ALL.forEach(builder::suggest);
}
return builder.buildFuture();
}
}
@@ -1,28 +0,0 @@
package org.popcraft.chunky.command.suggestion;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.server.command.ServerCommandSource;
import org.popcraft.chunky.command.CommandLiteral;
import org.popcraft.chunky.shape.ShapeType;
import java.util.concurrent.CompletableFuture;
public class ShapeSuggestionProvider implements SuggestionProvider<ServerCommandSource> {
@Override
public CompletableFuture<Suggestions> getSuggestions(final CommandContext<ServerCommandSource> context, final SuggestionsBuilder builder) {
try {
final String input = context.getArgument(CommandLiteral.SHAPE, String.class);
ShapeType.all().forEach(shape -> {
if (shape.contains(input.toLowerCase())) {
builder.suggest(shape);
}
});
} catch (IllegalArgumentException e) {
ShapeType.all().forEach(builder::suggest);
}
return builder.buildFuture();
}
}
@@ -1,19 +0,0 @@
package org.popcraft.chunky.command.suggestion;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import net.minecraft.server.command.ServerCommandSource;
public final class SuggestionProviders {
public static final SuggestionProvider<ServerCommandSource> PATTERNS;
public static final SuggestionProvider<ServerCommandSource> SHAPES;
public static final SuggestionProvider<ServerCommandSource> TRIM_MODES;
static {
PATTERNS = new PatternSuggestionProvider();
SHAPES = new ShapeSuggestionProvider();
TRIM_MODES = new TrimModeSuggestionProvider();
}
private SuggestionProviders() {
}
}
@@ -1,30 +0,0 @@
package org.popcraft.chunky.command.suggestion;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.server.command.ServerCommandSource;
import org.popcraft.chunky.command.CommandLiteral;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class TrimModeSuggestionProvider implements SuggestionProvider<ServerCommandSource> {
private static final List<String> TRIM_MODES = List.of("inside", "outside");
@Override
public CompletableFuture<Suggestions> getSuggestions(final CommandContext<ServerCommandSource> context, final SuggestionsBuilder builder) {
try {
final String input = context.getArgument(CommandLiteral.TRIM_MODE, String.class);
TRIM_MODES.forEach(shape -> {
if (shape.contains(input.toLowerCase())) {
builder.suggest(shape);
}
});
} catch (IllegalArgumentException e) {
TRIM_MODES.forEach(builder::suggest);
}
return builder.buildFuture();
}
}
@@ -1,33 +0,0 @@
package org.popcraft.chunky.listeners.bossbar;
import net.minecraft.entity.boss.ServerBossBar;
import net.minecraft.util.Identifier;
import org.popcraft.chunky.GenerationTask;
import org.popcraft.chunky.event.task.GenerationTaskFinishEvent;
import org.popcraft.chunky.platform.World;
import java.util.Map;
import java.util.function.Consumer;
public class BossBarTaskFinishListener implements Consumer<GenerationTaskFinishEvent> {
private final Map<Identifier, ServerBossBar> bossBars;
public BossBarTaskFinishListener(final Map<Identifier, ServerBossBar> bossBars) {
this.bossBars = bossBars;
}
@Override
public void accept(final GenerationTaskFinishEvent event) {
final GenerationTask task = event.generationTask();
final World world = task.getSelection().world();
final Identifier worldIdentifier = Identifier.tryParse(world.getKey());
if (worldIdentifier == null) {
return;
}
final ServerBossBar bossBar = bossBars.get(worldIdentifier);
if (bossBar != null) {
bossBar.clearPlayers();
bossBars.remove(worldIdentifier);
}
}
}
@@ -1,86 +0,0 @@
package org.popcraft.chunky.listeners.bossbar;
import net.minecraft.entity.boss.BossBar;
import net.minecraft.entity.boss.ServerBossBar;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import org.popcraft.chunky.Chunky;
import org.popcraft.chunky.GenerationTask;
import org.popcraft.chunky.event.task.GenerationTaskUpdateEvent;
import org.popcraft.chunky.platform.FabricWorld;
import org.popcraft.chunky.platform.World;
import java.util.Map;
import java.util.function.Consumer;
public class BossBarTaskUpdateListener implements Consumer<GenerationTaskUpdateEvent> {
private final Map<Identifier, ServerBossBar> bossBars;
public BossBarTaskUpdateListener(final Map<Identifier, ServerBossBar> bossBars) {
this.bossBars = bossBars;
}
@Override
public void accept(final GenerationTaskUpdateEvent event) {
final GenerationTask task = event.generationTask();
final Chunky chunky = task.getChunky();
final World world = task.getSelection().world();
final Identifier worldIdentifier = Identifier.tryParse(world.getKey());
if (worldIdentifier == null || !(world instanceof final FabricWorld fabricWorld)) {
return;
}
final ServerBossBar bossBar = bossBars.computeIfAbsent(worldIdentifier, x -> createNewBossBar(worldIdentifier));
final boolean silent = chunky.getConfig().isSilent();
if (silent == bossBar.isVisible()) {
bossBar.setVisible(!silent);
}
final MinecraftServer server = fabricWorld.getServerWorld().getServer();
for (final ServerPlayerEntity player : server.getPlayerManager().getPlayerList()) {
if (player.hasPermissionLevel(2)) {
bossBar.addPlayer(player);
} else {
bossBar.removePlayer(player);
}
}
final GenerationTask.Progress progress = task.getProgress();
bossBar.setName(Text.of(String.format("%s | %s%% | %s:%s:%s",
worldIdentifier,
String.format("%.2f", progress.getPercentComplete()),
String.format("%01d", progress.getHours()),
String.format("%02d", progress.getMinutes()),
String.format("%02d", progress.getSeconds()))));
bossBar.setPercent(progress.getPercentComplete() / 100f);
if (progress.isComplete()) {
bossBar.clearPlayers();
bossBars.remove(worldIdentifier);
}
}
private ServerBossBar createNewBossBar(final Identifier worldIdentifier) {
final ServerBossBar bossBar = new ServerBossBar(
Text.of(worldIdentifier.toString()),
bossBarColor(worldIdentifier),
BossBar.Style.PROGRESS
);
bossBar.setDarkenSky(false);
bossBar.setDragonMusic(false);
bossBar.setThickenFog(false);
return bossBar;
}
private static BossBar.Color bossBarColor(Identifier worldIdentifier) {
final BossBar.Color bossBarColor;
if (net.minecraft.world.World.OVERWORLD.getValue().equals(worldIdentifier)) {
bossBarColor = BossBar.Color.GREEN;
} else if (net.minecraft.world.World.NETHER.getValue().equals(worldIdentifier)) {
bossBarColor = BossBar.Color.RED;
} else if (net.minecraft.world.World.END.getValue().equals(worldIdentifier)) {
bossBarColor = BossBar.Color.PURPLE;
} else {
bossBarColor = BossBar.Color.BLUE;
}
return bossBarColor;
}
}
@@ -1,12 +0,0 @@
package org.popcraft.chunky.mixin;
import net.minecraft.server.world.ServerChunkManager;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(ServerChunkManager.class)
public interface ServerChunkManagerMixin {
@Invoker("tick")
@SuppressWarnings({"UnusedReturnValue", "UnnecessaryInterfaceModifier"})
public boolean invokeTick();
}
@@ -1,26 +0,0 @@
package org.popcraft.chunky.mixin;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.world.ChunkHolder;
import net.minecraft.server.world.ThreadedAnvilChunkStorage;
import net.minecraft.util.math.ChunkPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
@SuppressWarnings("UnnecessaryInterfaceModifier")
@Mixin(ThreadedAnvilChunkStorage.class)
public interface ThreadedAnvilChunkStorageMixin {
@Invoker("getChunkHolder")
public ChunkHolder invokeGetChunkHolder(long pos);
@Invoker("getUpdatedChunkNbt")
public CompletableFuture<Optional<NbtCompound>> invokeGetUpdatedChunkNbt(ChunkPos pos);
@Accessor("chunksToUnload")
public Long2ObjectLinkedOpenHashMap<ChunkHolder> getChunksToUnload();
}
@@ -1,33 +0,0 @@
package org.popcraft.chunky.platform;
import net.minecraft.world.border.WorldBorder;
import org.popcraft.chunky.platform.util.Vector2;
import org.popcraft.chunky.shape.ShapeType;
public class FabricBorder implements Border {
private final WorldBorder worldBorder;
public FabricBorder(final WorldBorder worldBorder) {
this.worldBorder = worldBorder;
}
@Override
public Vector2 getCenter() {
return Vector2.of(worldBorder.getCenterX(), worldBorder.getCenterZ());
}
@Override
public double getRadiusX() {
return worldBorder.getSize() / 2d;
}
@Override
public double getRadiusZ() {
return worldBorder.getSize() / 2d;
}
@Override
public String getShape() {
return ShapeType.SQUARE;
}
}
@@ -1,62 +0,0 @@
package org.popcraft.chunky.platform;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import org.popcraft.chunky.platform.util.Location;
import java.util.UUID;
import static org.popcraft.chunky.util.Translator.translateKey;
public class FabricPlayer extends FabricSender implements Player {
private final ServerPlayerEntity player;
public FabricPlayer(final ServerPlayerEntity player) {
super(player.getCommandSource());
this.player = player;
}
@Override
public boolean isPlayer() {
return true;
}
@Override
public String getName() {
return player.getName().getString();
}
@Override
public World getWorld() {
return new FabricWorld(player.getServerWorld());
}
@Override
public Location getLocation() {
return new Location(getWorld(), player.getX(), player.getY(), player.getZ(), player.getYaw(), player.getPitch());
}
@Override
public void sendMessage(final String key, final boolean prefixed, final Object... args) {
player.sendMessage(formatColored(translateKey(key, prefixed, args)), false);
}
@Override
public UUID getUUID() {
return player.getUuid();
}
@Override
public void teleport(final Location location) {
player.teleport(((FabricWorld) location.getWorld()).getServerWorld(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
}
@Override
public void sendActionBar(final String key) {
player.sendMessage(formatColored(translateKey(key, false)), true);
}
private Text formatColored(final String message) {
return Text.of(message.replaceAll("&(?=[0-9a-fk-orA-FK-OR])", "§"));
}
}
@@ -1,76 +0,0 @@
package org.popcraft.chunky.platform;
import me.lucko.fabric.api.permissions.v0.Permissions;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.math.Position;
import net.minecraft.util.math.Vec2f;
import org.popcraft.chunky.platform.util.Location;
import static org.popcraft.chunky.util.Translator.translateKey;
public class FabricSender implements Sender {
private static final boolean HAS_PERMISSIONS;
static {
boolean hasPermissions;
try {
Class.forName("me.lucko.fabric.api.permissions.v0.Permissions");
hasPermissions = true;
} catch (ClassNotFoundException e) {
hasPermissions = false;
}
HAS_PERMISSIONS = hasPermissions;
}
private final ServerCommandSource source;
public FabricSender(final ServerCommandSource source) {
this.source = source;
}
@Override
public boolean isPlayer() {
return source.getEntity() instanceof ServerPlayerEntity;
}
@Override
public String getName() {
return source.getName();
}
@Override
public World getWorld() {
return new FabricWorld(source.getWorld());
}
@Override
public Location getLocation() {
final Position pos = source.getPosition();
final Vec2f rotation = source.getRotation();
return new Location(getWorld(), pos.getX(), pos.getY(), pos.getZ(), rotation.x, rotation.y);
}
@Override
public boolean hasPermission(final String permission) {
return hasPermission(permission, false);
}
public boolean hasPermission(final String permission, final boolean defaultOp) {
if (HAS_PERMISSIONS) {
if (defaultOp) {
return Permissions.check(source, permission, 2);
} else {
return Permissions.check(source, permission, false);
}
} else {
return source.hasPermissionLevel(2);
}
}
@Override
public void sendMessage(final String key, final boolean prefixed, final Object... args) {
source.sendFeedback(() -> Text.of(translateKey(key, prefixed, args).replaceAll("&[0-9a-fk-orA-FK-OR]", "")), false);
}
}
@@ -1,83 +0,0 @@
package org.popcraft.chunky.platform;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import org.popcraft.chunky.ChunkyFabric;
import org.popcraft.chunky.integration.Integration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
public class FabricServer implements Server {
private final ChunkyFabric plugin;
private final MinecraftServer server;
public FabricServer(final ChunkyFabric plugin, final MinecraftServer server) {
this.plugin = plugin;
this.server = server;
}
@Override
public Map<String, Integration> getIntegrations() {
return Map.of();
}
@Override
public Optional<World> getWorld(final String name) {
return Optional.ofNullable(Identifier.tryParse(name))
.map(worldIdentifier -> server.getWorld(RegistryKey.of(RegistryKeys.WORLD, worldIdentifier)))
.or(() -> {
for (final ServerWorld world : server.getWorlds()) {
if (name.equals(world.getRegistryKey().getValue().getPath())) {
return Optional.of(world);
}
}
return Optional.empty();
})
.map(FabricWorld::new);
}
@Override
public List<World> getWorlds() {
final List<World> worlds = new ArrayList<>();
server.getWorlds().forEach(world -> worlds.add(new FabricWorld(world)));
return worlds;
}
@Override
public int getMaxWorldSize() {
if (server instanceof final DedicatedServer dedicatedServer) {
return dedicatedServer.getProperties().maxWorldSize;
} else {
return server.getMaxWorldBorderRadius();
}
}
@Override
public Sender getConsole() {
return new FabricSender(server.getCommandSource());
}
@Override
public Collection<Player> getPlayers() {
return server.getPlayerManager().getPlayerList().stream().map(FabricPlayer::new).collect(Collectors.toList());
}
@Override
public Optional<Player> getPlayer(final String name) {
return Optional.ofNullable(server.getPlayerManager().getPlayer(name)).map(FabricPlayer::new);
}
@Override
public Config getConfig() {
return plugin.getChunky().getConfig();
}
}
@@ -1,194 +0,0 @@
package org.popcraft.chunky.platform;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtString;
import net.minecraft.nbt.scanner.NbtScanQuery;
import net.minecraft.nbt.scanner.SelectiveNbtCollector;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.server.world.ChunkHolder;
import net.minecraft.server.world.ChunkTicketType;
import net.minecraft.server.world.ServerChunkManager;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.server.world.ThreadedAnvilChunkStorage;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.Identifier;
import net.minecraft.util.Unit;
import net.minecraft.util.WorldSavePath;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.Heightmap;
import net.minecraft.world.chunk.ChunkStatus;
import net.minecraft.world.dimension.DimensionType;
import org.popcraft.chunky.mixin.ServerChunkManagerMixin;
import org.popcraft.chunky.mixin.ThreadedAnvilChunkStorageMixin;
import org.popcraft.chunky.platform.util.Location;
import org.popcraft.chunky.util.Input;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
public class FabricWorld implements World {
private static final int TICKING_LOAD_DURATION = Input.tryInteger(System.getProperty("chunky.tickingLoadDuration")).orElse(0);
private static final ChunkTicketType<Unit> CHUNKY = ChunkTicketType.create("chunky", (unit, unit2) -> 0);
private static final ChunkTicketType<Unit> CHUNKY_TICKING = ChunkTicketType.create("chunky_ticking", (unit, unit2) -> 0, TICKING_LOAD_DURATION * 20);
private static final boolean UPDATE_CHUNK_NBT = Boolean.getBoolean("chunky.updateChunkNbt");
private final ServerWorld serverWorld;
private final Border worldBorder;
public FabricWorld(final ServerWorld serverWorld) {
this.serverWorld = serverWorld;
this.worldBorder = new FabricBorder(serverWorld.getWorldBorder());
}
@Override
public String getName() {
return serverWorld.getRegistryKey().getValue().toString();
}
@Override
public String getKey() {
return getName();
}
@Override
public CompletableFuture<Boolean> isChunkGenerated(final int x, final int z) {
if (Thread.currentThread() != serverWorld.getServer().getThread()) {
return CompletableFuture.supplyAsync(() -> isChunkGenerated(x, z), serverWorld.getServer()).thenCompose(Function.identity());
} else {
final ChunkPos chunkPos = new ChunkPos(x, z);
final ServerChunkManager serverChunkManager = serverWorld.getChunkManager();
final ThreadedAnvilChunkStorage chunkStorage = serverChunkManager.threadedAnvilChunkStorage;
final ThreadedAnvilChunkStorageMixin chunkStorageMixin = (ThreadedAnvilChunkStorageMixin) chunkStorage;
final ChunkHolder loadedChunkHolder = chunkStorageMixin.invokeGetChunkHolder(chunkPos.toLong());
if (loadedChunkHolder != null && loadedChunkHolder.getCurrentStatus() == ChunkStatus.FULL) {
return CompletableFuture.completedFuture(true);
}
final ChunkHolder unloadedChunkHolder = chunkStorageMixin.getChunksToUnload().get(chunkPos.toLong());
if (unloadedChunkHolder != null && unloadedChunkHolder.getCurrentStatus() == ChunkStatus.FULL) {
return CompletableFuture.completedFuture(true);
}
if (UPDATE_CHUNK_NBT) {
return chunkStorageMixin.invokeGetUpdatedChunkNbt(chunkPos)
.thenApply(optionalNbt -> optionalNbt
.filter(chunkNbt -> chunkNbt.contains("Status", NbtElement.STRING_TYPE))
.map(chunkNbt -> chunkNbt.getString("Status"))
.map(status -> "minecraft:full".equals(status) || "full".equals(status))
.orElse(false));
}
final NbtScanQuery statusQuery = new NbtScanQuery(NbtString.TYPE, "Status");
final SelectiveNbtCollector statusCollector = new SelectiveNbtCollector(statusQuery);
return serverChunkManager.getChunkIoWorker().scanChunk(chunkPos, statusCollector)
.thenApply(ignored -> {
if (statusCollector.getRoot() instanceof final NbtCompound chunkNbt) {
final String status = chunkNbt.getString("Status");
return "minecraft:full".equals(status) || "full".equals(status);
}
return false;
});
}
}
@Override
public CompletableFuture<Void> getChunkAtAsync(final int x, final int z) {
if (Thread.currentThread() != serverWorld.getServer().getThread()) {
return CompletableFuture.supplyAsync(() -> getChunkAtAsync(x, z), serverWorld.getServer()).thenCompose(Function.identity());
} else {
final ChunkPos chunkPos = new ChunkPos(x, z);
final ServerChunkManager serverChunkManager = serverWorld.getChunkManager();
serverChunkManager.addTicket(CHUNKY, chunkPos, 0, Unit.INSTANCE);
if (TICKING_LOAD_DURATION > 0) {
serverChunkManager.addTicket(CHUNKY_TICKING, chunkPos, 1, Unit.INSTANCE);
}
((ServerChunkManagerMixin) serverChunkManager).invokeTick();
final ThreadedAnvilChunkStorage threadedAnvilChunkStorage = serverChunkManager.threadedAnvilChunkStorage;
final ThreadedAnvilChunkStorageMixin threadedAnvilChunkStorageMixin = (ThreadedAnvilChunkStorageMixin) threadedAnvilChunkStorage;
final ChunkHolder chunkHolder = threadedAnvilChunkStorageMixin.invokeGetChunkHolder(chunkPos.toLong());
final CompletableFuture<Void> chunkFuture = chunkHolder == null ? CompletableFuture.completedFuture(null) : CompletableFuture.allOf(chunkHolder.getChunkAt(ChunkStatus.FULL, threadedAnvilChunkStorage));
chunkFuture.whenCompleteAsync((ignored, throwable) -> serverChunkManager.removeTicket(CHUNKY, chunkPos, 0, Unit.INSTANCE), serverWorld.getServer());
return chunkFuture;
}
}
@Override
public UUID getUUID() {
throw new UnsupportedOperationException();
}
@Override
public int getSeaLevel() {
return serverWorld.getSeaLevel();
}
@Override
public Location getSpawn() {
final BlockPos pos = serverWorld.getSpawnPos();
final float angle = serverWorld.getSpawnAngle();
return new Location(this, pos.getX(), pos.getY(), pos.getZ(), angle, 0);
}
@Override
public Border getWorldBorder() {
return worldBorder;
}
@Override
public int getElevation(final int x, final int z) {
final int height = serverWorld.getChunk(x >> 4, z >> 4).sampleHeightmap(Heightmap.Type.MOTION_BLOCKING, x, z) + 1;
final int logicalHeight = serverWorld.getLogicalHeight();
if (height >= logicalHeight) {
BlockPos.Mutable pos = new BlockPos.Mutable(x, logicalHeight, z);
int air = 0;
while (pos.getY() > serverWorld.getBottomY()) {
pos = pos.move(Direction.DOWN);
final BlockState blockState = serverWorld.getBlockState(pos);
if (blockState.isSolid() && air > 1) {
return pos.getY() + 1;
}
air = blockState.isAir() ? air + 1 : 0;
}
}
return height;
}
@Override
public int getMaxElevation() {
return serverWorld.getLogicalHeight();
}
@Override
public void playEffect(final Player player, final String effect) {
final Location location = player.getLocation();
final BlockPos pos = BlockPos.ofFloored(location.getX(), location.getY(), location.getZ());
Input.tryInteger(effect).ifPresent(eventId -> serverWorld.syncWorldEvent(null, eventId, pos, 0));
}
@Override
public void playSound(final Player player, final String sound) {
final Location location = player.getLocation();
serverWorld.getServer()
.getRegistryManager()
.getOptional(RegistryKeys.SOUND_EVENT)
.flatMap(soundEventRegistry -> soundEventRegistry.getOrEmpty(Identifier.tryParse(sound)))
.ifPresent(soundEvent -> serverWorld.playSound(null, location.getX(), location.getY(), location.getZ(), soundEvent, SoundCategory.MASTER, 2f, 1f));
}
@Override
public Optional<Path> getDirectory(final String name) {
if (name == null) {
return Optional.empty();
}
final Path directory = DimensionType.getSaveDirectory(serverWorld.getRegistryKey(), serverWorld.getServer().getSavePath(WorldSavePath.ROOT)).normalize().resolve(name);
return Files.exists(directory) ? Optional.of(directory) : Optional.empty();
}
public ServerWorld getServerWorld() {
return serverWorld;
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

@@ -1,15 +0,0 @@
{
"required": true,
"minVersion": "0.8",
"package": "org.popcraft.chunky.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"ServerChunkManagerMixin",
"ThreadedAnvilChunkStorageMixin"
],
"client": [
],
"injectors": {
"defaultRequire": 1
}
}
-41
View File
@@ -1,41 +0,0 @@
{
"schemaVersion": 1,
"id": "${id}",
"version": "${version}",
"name": "${name}",
"description": "${description}",
"authors": [
"${author}"
],
"contact": {
"website": "https://www.curseforge.com/minecraft/mc-mods/chunky-pregenerator",
"homepage": "https://www.curseforge.com/minecraft/mc-mods/chunky-pregenerator",
"repo": "${github}",
"sources": "${github}",
"issues": "${github}/issues"
},
"license": "GPLv3",
"icon": "assets/chunky/icon.png",
"environment": "*",
"entrypoints": {
"main": [
"org.popcraft.chunky.ChunkyFabric"
]
},
"mixins": [
"chunky.mixins.json"
],
"depends": {
"fabricloader": ">=0.14.21",
"fabric": "*",
"minecraft": ">=1.20.0",
"java": ">=17"
},
"custom": {
"modmenu": {
"links": {
"modmenu.discord": "https://discord.gg/ZwVJukcNQG"
}
}
}
}
-48
View File
@@ -1,48 +0,0 @@
plugins {
id("dev.architectury.loom") version "1.5-SNAPSHOT"
}
val shade: Configuration by configurations.creating
dependencies {
minecraft(group = "com.mojang", name = "minecraft", version = "1.20")
mappings(loom.officialMojangMappings())
forge(group = "net.minecraftforge", name = "forge", version = "1.20-46.0.10")
implementation(project(":Chunky-common"))
shade(project(":Chunky-common"))
}
tasks {
processResources {
filesMatching("META-INF/mods.toml") {
expand(
"github" to project.property("github"),
"id" to rootProject.name,
"version" to project.version,
"name" to project.property("artifactName"),
"author" to project.property("author"),
"description" to project.property("description")
)
}
}
jar {
manifest {
attributes(
mapOf(
"Implementation-Title" to rootProject.name,
"Implementation-Version" to project.version,
"Implementation-Vendor" to project.property("author")
)
)
}
}
shadowJar {
configurations = listOf(shade)
archiveClassifier.set("dev")
archiveFileName.set(null as String?)
}
remapJar {
inputFile.set(shadowJar.get().archiveFile)
archiveFileName.set("${project.property("artifactName")}-${project.version}.jar")
}
}
-1
View File
@@ -1 +0,0 @@
loom.platform=forge
@@ -1,185 +0,0 @@
package org.popcraft.chunky;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerBossEvent;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.event.server.ServerStoppingEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.loading.FMLPaths;
import org.popcraft.chunky.command.ChunkyCommand;
import org.popcraft.chunky.command.CommandArguments;
import org.popcraft.chunky.command.CommandLiteral;
import org.popcraft.chunky.command.suggestion.SuggestionProviders;
import org.popcraft.chunky.event.task.GenerationTaskFinishEvent;
import org.popcraft.chunky.event.task.GenerationTaskUpdateEvent;
import org.popcraft.chunky.listeners.bossbar.BossBarTaskFinishListener;
import org.popcraft.chunky.listeners.bossbar.BossBarTaskUpdateListener;
import org.popcraft.chunky.platform.ForgePlayer;
import org.popcraft.chunky.platform.ForgeSender;
import org.popcraft.chunky.platform.ForgeServer;
import org.popcraft.chunky.platform.Sender;
import org.popcraft.chunky.platform.impl.GsonConfig;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static com.mojang.brigadier.arguments.StringArgumentType.string;
import static com.mojang.brigadier.arguments.StringArgumentType.word;
import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal;
import static net.minecraft.commands.arguments.DimensionArgument.dimension;
import static net.minecraft.commands.arguments.EntityArgument.player;
@Mod(ChunkyForge.MOD_ID)
public class ChunkyForge {
public static final String MOD_ID = "chunky";
private Chunky chunky;
private final Map<ResourceLocation, ServerBossEvent> bossBars = new ConcurrentHashMap<>();
public ChunkyForge() {
MinecraftForge.EVENT_BUS.register(this);
}
@SubscribeEvent
public void onServerStarting(final ServerStartingEvent event) {
final MinecraftServer server = event.getServer();
final Path configPath = FMLPaths.CONFIGDIR.get().resolve("chunky/config.json");
this.chunky = new Chunky(new ForgeServer(this, server), new GsonConfig(configPath));
if (chunky.getConfig().getContinueOnRestart()) {
chunky.getCommands().get(CommandLiteral.CONTINUE).execute(chunky.getServer().getConsole(), CommandArguments.empty());
}
chunky.getEventBus().subscribe(GenerationTaskUpdateEvent.class, new BossBarTaskUpdateListener(bossBars));
chunky.getEventBus().subscribe(GenerationTaskFinishEvent.class, new BossBarTaskFinishListener(bossBars));
}
@SubscribeEvent
public void onRegisterCommands(final RegisterCommandsEvent event) {
final LiteralArgumentBuilder<CommandSourceStack> command = literal(CommandLiteral.CHUNKY)
.requires(serverCommandSource -> {
if (serverCommandSource.getServer().isSingleplayer()) {
return true;
}
return serverCommandSource.hasPermission(2);
})
.executes(context -> {
final Sender sender;
if (context.getSource().getEntity() instanceof final ServerPlayer player) {
sender = new ForgePlayer(player);
} else {
sender = new ForgeSender(context.getSource());
}
final Map<String, ChunkyCommand> commands = chunky.getCommands();
final String input = context.getInput().substring(context.getLastChild().getNodes().get(0).getRange().getStart());
final String[] tokens = input.split(" ");
final String subCommand = tokens.length > 1 && commands.containsKey(tokens[1]) ? tokens[1] : CommandLiteral.HELP;
final CommandArguments arguments = tokens.length > 2 ? CommandArguments.of(Arrays.copyOfRange(tokens, 2, tokens.length)) : CommandArguments.empty();
commands.get(subCommand).execute(sender, arguments);
return Command.SINGLE_SUCCESS;
});
registerArguments(command, literal(CommandLiteral.CANCEL),
argument(CommandLiteral.WORLD, dimension()));
registerArguments(command, literal(CommandLiteral.CENTER),
argument(CommandLiteral.X, word()),
argument(CommandLiteral.Z, word()));
registerArguments(command, literal(CommandLiteral.CONFIRM));
registerArguments(command, literal(CommandLiteral.CONTINUE),
argument(CommandLiteral.WORLD, dimension()));
registerArguments(command, literal(CommandLiteral.CORNERS),
argument(CommandLiteral.X1, word()),
argument(CommandLiteral.Z1, word()),
argument(CommandLiteral.X2, word()),
argument(CommandLiteral.Z2, word()));
registerArguments(command, literal(CommandLiteral.HELP),
argument(CommandLiteral.PAGE, integer()));
registerArguments(command, literal(CommandLiteral.PATTERN),
argument(CommandLiteral.PATTERN, string()).suggests(SuggestionProviders.PATTERNS),
argument(CommandLiteral.VALUE, string()));
registerArguments(command, literal(CommandLiteral.PAUSE),
argument(CommandLiteral.WORLD, dimension()));
registerArguments(command, literal(CommandLiteral.PROGRESS));
registerArguments(command, literal(CommandLiteral.QUIET),
argument(CommandLiteral.INTERVAL, integer()));
registerArguments(command, literal(CommandLiteral.RADIUS),
argument(CommandLiteral.RADIUS, word()),
argument(CommandLiteral.RADIUS, word()));
registerArguments(command, literal(CommandLiteral.RELOAD),
argument(CommandLiteral.TYPE, word()));
registerArguments(command, literal(CommandLiteral.SELECTION));
registerArguments(command, literal(CommandLiteral.SHAPE),
argument(CommandLiteral.SHAPE, string()).suggests(SuggestionProviders.SHAPES));
registerArguments(command, literal(CommandLiteral.SILENT));
registerArguments(command, literal(CommandLiteral.SPAWN));
registerArguments(command, literal(CommandLiteral.START),
argument(CommandLiteral.WORLD, dimension()),
argument(CommandLiteral.SHAPE, string()).suggests(SuggestionProviders.SHAPES),
argument(CommandLiteral.CENTER_X, word()),
argument(CommandLiteral.CENTER_Z, word()),
argument(CommandLiteral.RADIUS_X, word()),
argument(CommandLiteral.RADIUS_Z, word()));
registerArguments(command, literal(CommandLiteral.TRIM),
argument(CommandLiteral.WORLD, dimension()),
argument(CommandLiteral.SHAPE, string()).suggests(SuggestionProviders.SHAPES),
argument(CommandLiteral.CENTER_X, word()),
argument(CommandLiteral.CENTER_Z, word()),
argument(CommandLiteral.RADIUS_X, word()),
argument(CommandLiteral.RADIUS_Z, word()),
argument(CommandLiteral.TRIM_MODE, string()).suggests(SuggestionProviders.TRIM_MODES),
argument(CommandLiteral.INHABITED, word()));
registerArguments(command, literal(CommandLiteral.WORLDBORDER));
registerArguments(command, literal(CommandLiteral.WORLD),
argument(CommandLiteral.WORLD, dimension()));
final LiteralArgumentBuilder<CommandSourceStack> borderCommand = literal(CommandLiteral.BORDER)
.requires(serverCommandSource -> chunky != null && chunky.getCommands().containsKey(CommandLiteral.BORDER))
.executes(command.getCommand());
registerArguments(borderCommand, literal(CommandLiteral.ADD),
argument(CommandLiteral.WORLD, dimension()),
argument(CommandLiteral.SHAPE, string()).suggests(SuggestionProviders.SHAPES),
argument(CommandLiteral.CENTER_X, word()),
argument(CommandLiteral.CENTER_Z, word()),
argument(CommandLiteral.RADIUS_X, word()),
argument(CommandLiteral.RADIUS_Z, word()));
registerArguments(borderCommand, literal(CommandLiteral.BYPASS),
argument(CommandLiteral.PLAYER, player()));
registerArguments(borderCommand, literal(CommandLiteral.HELP));
registerArguments(borderCommand, literal(CommandLiteral.LIST));
registerArguments(borderCommand, literal(CommandLiteral.LOAD),
argument(CommandLiteral.WORLD, dimension()));
registerArguments(borderCommand, literal(CommandLiteral.REMOVE),
argument(CommandLiteral.WORLD, dimension()));
registerArguments(borderCommand, literal(CommandLiteral.WRAP),
argument(CommandLiteral.WRAP, word()));
registerArguments(command, borderCommand);
event.getDispatcher().register(command);
}
@SafeVarargs
private <S> void registerArguments(final LiteralArgumentBuilder<S> command, final ArgumentBuilder<S, ?>... arguments) {
for (int i = arguments.length - 1; i > 0; --i) {
arguments[i - 1].then(arguments[i].executes(command.getCommand()));
}
command.then(arguments[0].executes(command.getCommand()));
}
@SubscribeEvent
public void onServerStopping(final ServerStoppingEvent event) {
if (chunky != null) {
chunky.disable();
}
}
public Chunky getChunky() {
return chunky;
}
}
@@ -1,28 +0,0 @@
package org.popcraft.chunky.command.suggestion;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.commands.CommandSourceStack;
import org.popcraft.chunky.command.CommandLiteral;
import org.popcraft.chunky.iterator.PatternType;
import java.util.concurrent.CompletableFuture;
public class PatternSuggestionProvider implements SuggestionProvider<CommandSourceStack> {
@Override
public CompletableFuture<Suggestions> getSuggestions(final CommandContext<CommandSourceStack> context, final SuggestionsBuilder builder) {
try {
final String input = context.getArgument(CommandLiteral.PATTERN, String.class);
PatternType.ALL.forEach(pattern -> {
if (pattern.contains(input.toLowerCase())) {
builder.suggest(pattern);
}
});
} catch (IllegalArgumentException e) {
PatternType.ALL.forEach(builder::suggest);
}
return builder.buildFuture();
}
}
@@ -1,28 +0,0 @@
package org.popcraft.chunky.command.suggestion;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.commands.CommandSourceStack;
import org.popcraft.chunky.command.CommandLiteral;
import org.popcraft.chunky.shape.ShapeType;
import java.util.concurrent.CompletableFuture;
public class ShapeSuggestionProvider implements SuggestionProvider<CommandSourceStack> {
@Override
public CompletableFuture<Suggestions> getSuggestions(final CommandContext<CommandSourceStack> context, final SuggestionsBuilder builder) {
try {
final String input = context.getArgument(CommandLiteral.SHAPE, String.class);
ShapeType.all().forEach(shape -> {
if (shape.contains(input.toLowerCase())) {
builder.suggest(shape);
}
});
} catch (IllegalArgumentException e) {
ShapeType.all().forEach(builder::suggest);
}
return builder.buildFuture();
}
}
@@ -1,19 +0,0 @@
package org.popcraft.chunky.command.suggestion;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import net.minecraft.commands.CommandSourceStack;
public final class SuggestionProviders {
public static final SuggestionProvider<CommandSourceStack> PATTERNS;
public static final SuggestionProvider<CommandSourceStack> SHAPES;
public static final SuggestionProvider<CommandSourceStack> TRIM_MODES;
static {
PATTERNS = new PatternSuggestionProvider();
SHAPES = new ShapeSuggestionProvider();
TRIM_MODES = new TrimModeSuggestionProvider();
}
private SuggestionProviders() {
}
}
@@ -1,30 +0,0 @@
package org.popcraft.chunky.command.suggestion;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.commands.CommandSourceStack;
import org.popcraft.chunky.command.CommandLiteral;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class TrimModeSuggestionProvider implements SuggestionProvider<CommandSourceStack> {
private static final List<String> TRIM_MODES = List.of("inside", "outside");
@Override
public CompletableFuture<Suggestions> getSuggestions(final CommandContext<CommandSourceStack> context, final SuggestionsBuilder builder) {
try {
final String input = context.getArgument(CommandLiteral.TRIM_MODE, String.class);
TRIM_MODES.forEach(shape -> {
if (shape.contains(input.toLowerCase())) {
builder.suggest(shape);
}
});
} catch (IllegalArgumentException e) {
TRIM_MODES.forEach(builder::suggest);
}
return builder.buildFuture();
}
}
@@ -1,33 +0,0 @@
package org.popcraft.chunky.listeners.bossbar;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerBossEvent;
import org.popcraft.chunky.GenerationTask;
import org.popcraft.chunky.event.task.GenerationTaskFinishEvent;
import org.popcraft.chunky.platform.World;
import java.util.Map;
import java.util.function.Consumer;
public class BossBarTaskFinishListener implements Consumer<GenerationTaskFinishEvent> {
private final Map<ResourceLocation, ServerBossEvent> bossBars;
public BossBarTaskFinishListener(final Map<ResourceLocation, ServerBossEvent> bossBars) {
this.bossBars = bossBars;
}
@Override
public void accept(final GenerationTaskFinishEvent event) {
final GenerationTask task = event.generationTask();
final World world = task.getSelection().world();
final ResourceLocation worldIdentifier = ResourceLocation.tryParse(world.getKey());
if (worldIdentifier == null) {
return;
}
final ServerBossEvent bossBar = bossBars.get(worldIdentifier);
if (bossBar != null) {
bossBar.removeAllPlayers();
bossBars.remove(worldIdentifier);
}
}
}
@@ -1,87 +0,0 @@
package org.popcraft.chunky.listeners.bossbar;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerBossEvent;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.BossEvent;
import net.minecraft.world.level.Level;
import org.popcraft.chunky.Chunky;
import org.popcraft.chunky.GenerationTask;
import org.popcraft.chunky.event.task.GenerationTaskUpdateEvent;
import org.popcraft.chunky.platform.ForgeWorld;
import org.popcraft.chunky.platform.World;
import java.util.Map;
import java.util.function.Consumer;
public class BossBarTaskUpdateListener implements Consumer<GenerationTaskUpdateEvent> {
private final Map<ResourceLocation, ServerBossEvent> bossBars;
public BossBarTaskUpdateListener(final Map<ResourceLocation, ServerBossEvent> bossBars) {
this.bossBars = bossBars;
}
@Override
public void accept(final GenerationTaskUpdateEvent event) {
final GenerationTask task = event.generationTask();
final Chunky chunky = task.getChunky();
final World world = task.getSelection().world();
final ResourceLocation worldIdentifier = ResourceLocation.tryParse(world.getKey());
if (worldIdentifier == null || !(world instanceof final ForgeWorld forgeWorld)) {
return;
}
final ServerBossEvent bossBar = bossBars.computeIfAbsent(worldIdentifier, x -> createNewBossBar(worldIdentifier));
final boolean silent = chunky.getConfig().isSilent();
if (silent == bossBar.isVisible()) {
bossBar.setVisible(!silent);
}
final MinecraftServer server = forgeWorld.getWorld().getServer();
for (final ServerPlayer player : server.getPlayerList().getPlayers()) {
if (player.hasPermissions(2)) {
bossBar.addPlayer(player);
} else {
bossBar.removePlayer(player);
}
}
final GenerationTask.Progress progress = task.getProgress();
bossBar.setName(Component.nullToEmpty(String.format("%s | %s%% | %s:%s:%s",
worldIdentifier,
String.format("%.2f", progress.getPercentComplete()),
String.format("%01d", progress.getHours()),
String.format("%02d", progress.getMinutes()),
String.format("%02d", progress.getSeconds()))));
bossBar.setProgress(task.getProgress().getPercentComplete() / 100f);
if (progress.isComplete()) {
bossBar.removeAllPlayers();
bossBars.remove(worldIdentifier);
}
}
private ServerBossEvent createNewBossBar(final ResourceLocation worldIdentifier) {
final ServerBossEvent bossBar = new ServerBossEvent(
Component.nullToEmpty(worldIdentifier.toString()),
bossBarColor(worldIdentifier),
BossEvent.BossBarOverlay.PROGRESS
);
bossBar.setDarkenScreen(false);
bossBar.setPlayBossMusic(false);
bossBar.setCreateWorldFog(false);
return bossBar;
}
private static BossEvent.BossBarColor bossBarColor(ResourceLocation worldIdentifier) {
final BossEvent.BossBarColor bossBarColor;
if (Level.OVERWORLD.location().equals(worldIdentifier)) {
bossBarColor = BossEvent.BossBarColor.GREEN;
} else if (Level.NETHER.location().equals(worldIdentifier)) {
bossBarColor = BossEvent.BossBarColor.RED;
} else if (Level.END.location().equals(worldIdentifier)) {
bossBarColor = BossEvent.BossBarColor.PURPLE;
} else {
bossBarColor = BossEvent.BossBarColor.BLUE;
}
return bossBarColor;
}
}
@@ -1,33 +0,0 @@
package org.popcraft.chunky.platform;
import net.minecraft.world.level.border.WorldBorder;
import org.popcraft.chunky.platform.util.Vector2;
import org.popcraft.chunky.shape.ShapeType;
public class ForgeBorder implements Border {
private final WorldBorder worldBorder;
public ForgeBorder(final WorldBorder worldBorder) {
this.worldBorder = worldBorder;
}
@Override
public Vector2 getCenter() {
return Vector2.of(worldBorder.getCenterX(), worldBorder.getCenterZ());
}
@Override
public double getRadiusX() {
return worldBorder.getSize() / 2d;
}
@Override
public double getRadiusZ() {
return worldBorder.getSize() / 2d;
}
@Override
public String getShape() {
return ShapeType.SQUARE;
}
}
@@ -1,62 +0,0 @@
package org.popcraft.chunky.platform;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import org.popcraft.chunky.platform.util.Location;
import java.util.UUID;
import static org.popcraft.chunky.util.Translator.translateKey;
public class ForgePlayer extends ForgeSender implements Player {
private final ServerPlayer player;
public ForgePlayer(final ServerPlayer player) {
super(player.createCommandSourceStack());
this.player = player;
}
@Override
public boolean isPlayer() {
return true;
}
@Override
public String getName() {
return player.getName().toString();
}
@Override
public World getWorld() {
return new ForgeWorld(player.serverLevel());
}
@Override
public Location getLocation() {
return new Location(getWorld(), player.getX(), player.getY(), player.getZ(), player.getXRot(), player.getYRot());
}
@Override
public void sendMessage(final String key, final boolean prefixed, final Object... args) {
player.sendSystemMessage(formatColored(translateKey(key, prefixed, args)));
}
@Override
public UUID getUUID() {
return player.getUUID();
}
@Override
public void teleport(final Location location) {
player.teleportTo(((ForgeWorld) location.getWorld()).getWorld(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
}
@Override
public void sendActionBar(final String key) {
player.displayClientMessage(formatColored(translateKey(key, false)), true);
}
private Component formatColored(final String message) {
return Component.nullToEmpty(message.replaceAll("&(?=[0-9a-fk-orA-FK-OR])", "§"));
}
}
@@ -1,50 +0,0 @@
package org.popcraft.chunky.platform;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3;
import org.popcraft.chunky.platform.util.Location;
import static org.popcraft.chunky.util.Translator.translateKey;
public class ForgeSender implements Sender {
private final CommandSourceStack source;
public ForgeSender(final CommandSourceStack source) {
this.source = source;
}
@Override
public boolean isPlayer() {
return source.getEntity() instanceof ServerPlayer;
}
@Override
public String getName() {
return source.getTextName();
}
@Override
public World getWorld() {
return new ForgeWorld(source.getLevel());
}
@Override
public Location getLocation() {
final Vec3 pos = source.getPosition();
final Vec2 rot = source.getRotation();
return new Location(getWorld(), pos.x(), pos.y(), pos.z(), rot.x, rot.y);
}
@Override
public boolean hasPermission(final String permission) {
return source.hasPermission(2);
}
@Override
public void sendMessage(final String key, final boolean prefixed, final Object... args) {
source.sendSuccess(() -> Component.nullToEmpty(translateKey(key, prefixed, args).replaceAll("&[0-9a-fk-orA-FK-OR]", "")), false);
}
}
@@ -1,83 +0,0 @@
package org.popcraft.chunky.platform;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.ServerInterface;
import net.minecraft.server.level.ServerLevel;
import org.popcraft.chunky.ChunkyForge;
import org.popcraft.chunky.integration.Integration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
public class ForgeServer implements Server {
private final ChunkyForge plugin;
private final MinecraftServer server;
public ForgeServer(final ChunkyForge plugin, final MinecraftServer server) {
this.plugin = plugin;
this.server = server;
}
@Override
public Map<String, Integration> getIntegrations() {
return Map.of();
}
@Override
public Optional<World> getWorld(final String name) {
return Optional.ofNullable(ResourceLocation.tryParse(name))
.map(resourceLocation -> server.getLevel(ResourceKey.create(Registries.DIMENSION, resourceLocation)))
.or(() -> {
for (final ServerLevel level : server.getAllLevels()) {
if (name.equals(level.dimension().location().getPath())) {
return Optional.of(level);
}
}
return Optional.empty();
})
.map(ForgeWorld::new);
}
@Override
public List<World> getWorlds() {
final List<World> worlds = new ArrayList<>();
server.getAllLevels().forEach(world -> worlds.add(new ForgeWorld(world)));
return worlds;
}
@Override
public int getMaxWorldSize() {
if (server instanceof final ServerInterface serverInterface) {
return serverInterface.getProperties().maxWorldSize;
} else {
return server.getAbsoluteMaxWorldSize();
}
}
@Override
public Sender getConsole() {
return new ForgeSender(server.createCommandSourceStack());
}
@Override
public Collection<Player> getPlayers() {
return server.getPlayerList().getPlayers().stream().map(ForgePlayer::new).collect(Collectors.toList());
}
@Override
public Optional<Player> getPlayer(final String name) {
return Optional.ofNullable(server.getPlayerList().getPlayerByName(name)).map(ForgePlayer::new);
}
@Override
public Config getConfig() {
return plugin.getChunky().getConfig();
}
}
@@ -1,191 +0,0 @@
package org.popcraft.chunky.platform;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.nbt.visitors.CollectFields;
import net.minecraft.nbt.visitors.FieldSelector;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.TicketType;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Unit;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.storage.LevelResource;
import org.popcraft.chunky.ChunkyForge;
import org.popcraft.chunky.platform.util.Location;
import org.popcraft.chunky.util.Input;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
public class ForgeWorld implements World {
private static final int TICKING_LOAD_DURATION = Input.tryInteger(System.getProperty("chunky.tickingLoadDuration")).orElse(0);
private static final TicketType<Unit> CHUNKY = TicketType.create(ChunkyForge.MOD_ID, (unit, unit2) -> 0);
private static final TicketType<Unit> CHUNKY_TICKING = TicketType.create("%s_ticking".formatted(ChunkyForge.MOD_ID), (unit, unit2) -> 0, TICKING_LOAD_DURATION * 20);
private static final boolean UPDATE_CHUNK_NBT = Boolean.getBoolean("chunky.updateChunkNbt");
private final ServerLevel world;
private final Border worldBorder;
public ForgeWorld(final ServerLevel world) {
this.world = world;
this.worldBorder = new ForgeBorder(world.getWorldBorder());
}
@Override
public String getName() {
return world.dimension().location().toString();
}
@Override
public String getKey() {
return getName();
}
@Override
public CompletableFuture<Boolean> isChunkGenerated(final int x, final int z) {
if (Thread.currentThread() != world.getServer().getRunningThread()) {
return CompletableFuture.supplyAsync(() -> isChunkGenerated(x, z), world.getServer()).thenCompose(Function.identity());
} else {
final ChunkPos chunkPos = new ChunkPos(x, z);
final ServerChunkCache serverChunkCache = world.getChunkSource();
final ChunkMap chunkStorage = serverChunkCache.chunkMap;
final ChunkHolder loadedChunkHolder = chunkStorage.getVisibleChunkIfPresent(chunkPos.toLong());
if (loadedChunkHolder != null && loadedChunkHolder.getLastAvailableStatus() == ChunkStatus.FULL) {
return CompletableFuture.completedFuture(true);
}
final ChunkHolder unloadedChunkHolder = chunkStorage.pendingUnloads.get(chunkPos.toLong());
if (unloadedChunkHolder != null && unloadedChunkHolder.getLastAvailableStatus() == ChunkStatus.FULL) {
return CompletableFuture.completedFuture(true);
}
if (UPDATE_CHUNK_NBT) {
return chunkStorage.readChunk(chunkPos)
.thenApply(optionalNbt -> optionalNbt
.filter(chunkNbt -> chunkNbt.contains("Status", Tag.TAG_STRING))
.map(chunkNbt -> chunkNbt.getString("Status"))
.map(status -> "minecraft:full".equals(status) || "full".equals(status))
.orElse(false));
}
final FieldSelector statusSelector = new FieldSelector(StringTag.TYPE, "Status");
final CollectFields statusCollector = new CollectFields(statusSelector);
return serverChunkCache.chunkScanner().scanChunk(chunkPos, statusCollector)
.thenApply(ignored -> {
if (statusCollector.getResult() instanceof final CompoundTag chunkNbt) {
final String status = chunkNbt.getString("Status");
return "minecraft:full".equals(status) || "full".equals(status);
}
return false;
});
}
}
@Override
public CompletableFuture<Void> getChunkAtAsync(final int x, final int z) {
if (Thread.currentThread() != world.getServer().getRunningThread()) {
return CompletableFuture.supplyAsync(() -> getChunkAtAsync(x, z), world.getServer()).thenCompose(Function.identity());
} else {
final ChunkPos chunkPos = new ChunkPos(x, z);
final ServerChunkCache serverChunkCache = world.getChunkSource();
serverChunkCache.addRegionTicket(CHUNKY, chunkPos, 0, Unit.INSTANCE);
if (TICKING_LOAD_DURATION > 0) {
serverChunkCache.addRegionTicket(CHUNKY_TICKING, chunkPos, 1, Unit.INSTANCE);
}
serverChunkCache.runDistanceManagerUpdates();
final ChunkMap chunkManager = serverChunkCache.chunkMap;
final ChunkHolder chunkHolder = chunkManager.getVisibleChunkIfPresent(chunkPos.toLong());
final CompletableFuture<Void> chunkFuture = chunkHolder == null ? CompletableFuture.completedFuture(null) : CompletableFuture.allOf(chunkHolder.getOrScheduleFuture(ChunkStatus.FULL, chunkManager));
chunkFuture.whenCompleteAsync((ignored, throwable) -> serverChunkCache.removeRegionTicket(CHUNKY, chunkPos, 0, Unit.INSTANCE), world.getServer());
return chunkFuture;
}
}
@Override
public UUID getUUID() {
throw new UnsupportedOperationException();
}
@Override
public int getSeaLevel() {
return world.getSeaLevel();
}
@Override
public Location getSpawn() {
final BlockPos pos = world.getSharedSpawnPos();
final float rot = world.getSharedSpawnAngle();
return new Location(this, pos.getX(), pos.getY(), pos.getZ(), rot, 0);
}
@Override
public Border getWorldBorder() {
return worldBorder;
}
@Override
public int getElevation(final int x, final int z) {
final int height = world.getHeight(Heightmap.Types.MOTION_BLOCKING, x, z) + 1;
final int logicalHeight = world.getLogicalHeight();
if (height >= logicalHeight) {
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(x, logicalHeight, z);
int air = 0;
while (pos.getY() > world.getMinBuildHeight()) {
pos = pos.move(Direction.DOWN);
final BlockState blockState = world.getBlockState(pos);
if (blockState.isSolid() && air > 1) {
return pos.getY() + 1;
}
air = blockState.isAir() ? air + 1 : 0;
}
}
return height;
}
@Override
public int getMaxElevation() {
return world.getLogicalHeight();
}
@Override
public void playEffect(final Player player, final String effect) {
final Location location = player.getLocation();
final BlockPos pos = BlockPos.containing(location.getX(), location.getY(), location.getZ());
Input.tryInteger(effect).ifPresent(eventId -> world.levelEvent(eventId, pos, 0));
}
@Override
public void playSound(final Player player, final String sound) {
final Location location = player.getLocation();
world.getServer()
.registryAccess()
.registry(Registries.SOUND_EVENT)
.flatMap(soundEventRegistry -> soundEventRegistry.getOptional(ResourceLocation.tryParse(sound)))
.ifPresent(soundEvent -> world.playSound(null, location.getX(), location.getY(), location.getZ(), soundEvent, SoundSource.MASTER, 2f, 1f));
}
@Override
public Optional<Path> getDirectory(final String name) {
if (name == null) {
return Optional.empty();
}
final Path directory = DimensionType.getStorageFolder(world.dimension(), world.getServer().getWorldPath(LevelResource.ROOT)).normalize().resolve(name);
return Files.exists(directory) ? Optional.of(directory) : Optional.empty();
}
public ServerLevel getWorld() {
return world;
}
}
@@ -1,6 +0,0 @@
# ChunkMap
public net.minecraft.server.level.ChunkMap m_214963_(Lnet/minecraft/world/level/ChunkPos;)Ljava/util/concurrent/CompletableFuture; # readChunk
public net.minecraft.server.level.ChunkMap m_140327_(J)Lnet/minecraft/server/level/ChunkHolder; # getVisibleChunkIfPresent
public net.minecraft.server.level.ChunkMap f_140131_ # pendingUnloads
# ServerChunkCache
public net.minecraft.server.level.ServerChunkCache m_8489_()Z # runDistanceManagerUpdates
@@ -1,24 +0,0 @@
modLoader="javafml"
loaderVersion="[38,)"
license="GNU GPLv3"
issueTrackerURL="${github}/issues"
[[mods]]
modId="${id}"
version="${version}"
displayName="${name}"
displayURL="${github}"
logoFile="icon.png"
authors="${author}"
description="${description}"
[[dependencies.chunky]]
modId="forge"
mandatory=true
versionRange="[46,)"
ordering="NONE"
side="BOTH"
[[dependencies.chunky]]
modId="minecraft"
mandatory=true
versionRange="[1.20,1.21)"
ordering="NONE"
side="BOTH"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

-6
View File
@@ -1,6 +0,0 @@
{
"pack": {
"description": "chunky resources",
"pack_format": 8
}
}
-52
View File
@@ -1,52 +0,0 @@
plugins {
id("dev.architectury.loom") version "1.5-SNAPSHOT"
}
val shade: Configuration by configurations.creating
repositories {
maven("https://maven.neoforged.net/releases/")
}
dependencies {
minecraft(group = "com.mojang", name = "minecraft", version = "1.20.2")
mappings(loom.officialMojangMappings())
neoForge(group = "net.neoforged", name = "neoforge", version = "20.2.88")
implementation(project(":Chunky-common"))
shade(project(":Chunky-common"))
}
tasks {
processResources {
filesMatching("META-INF/mods.toml") {
expand(
"github" to project.property("github"),
"id" to rootProject.name,
"version" to project.version,
"name" to project.property("artifactName"),
"author" to project.property("author"),
"description" to project.property("description")
)
}
}
jar {
manifest {
attributes(
mapOf(
"Implementation-Title" to rootProject.name,
"Implementation-Version" to project.version,
"Implementation-Vendor" to project.property("author")
)
)
}
}
shadowJar {
configurations = listOf(shade)
archiveClassifier.set("dev")
archiveFileName.set(null as String?)
}
remapJar {
inputFile.set(shadowJar.get().archiveFile)
archiveFileName.set("${project.property("artifactName")}-${project.version}.jar")
}
}
-1
View File
@@ -1 +0,0 @@
loom.platform=neoforge
@@ -1,185 +0,0 @@
package org.popcraft.chunky;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerBossEvent;
import net.minecraft.server.level.ServerPlayer;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.loading.FMLPaths;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.RegisterCommandsEvent;
import net.neoforged.neoforge.event.server.ServerStartingEvent;
import net.neoforged.neoforge.event.server.ServerStoppingEvent;
import org.popcraft.chunky.command.ChunkyCommand;
import org.popcraft.chunky.command.CommandArguments;
import org.popcraft.chunky.command.CommandLiteral;
import org.popcraft.chunky.command.suggestion.SuggestionProviders;
import org.popcraft.chunky.event.task.GenerationTaskFinishEvent;
import org.popcraft.chunky.event.task.GenerationTaskUpdateEvent;
import org.popcraft.chunky.listeners.bossbar.BossBarTaskFinishListener;
import org.popcraft.chunky.listeners.bossbar.BossBarTaskUpdateListener;
import org.popcraft.chunky.platform.NeoForgePlayer;
import org.popcraft.chunky.platform.NeoForgeSender;
import org.popcraft.chunky.platform.NeoForgeServer;
import org.popcraft.chunky.platform.Sender;
import org.popcraft.chunky.platform.impl.GsonConfig;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static com.mojang.brigadier.arguments.StringArgumentType.string;
import static com.mojang.brigadier.arguments.StringArgumentType.word;
import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal;
import static net.minecraft.commands.arguments.DimensionArgument.dimension;
import static net.minecraft.commands.arguments.EntityArgument.player;
@Mod(ChunkyNeoForge.MOD_ID)
public class ChunkyNeoForge {
public static final String MOD_ID = "chunky";
private Chunky chunky;
private final Map<ResourceLocation, ServerBossEvent> bossBars = new ConcurrentHashMap<>();
public ChunkyNeoForge() {
NeoForge.EVENT_BUS.register(this);
}
@SubscribeEvent
public void onServerStarting(final ServerStartingEvent event) {
final MinecraftServer server = event.getServer();
final Path configPath = FMLPaths.CONFIGDIR.get().resolve("chunky/config.json");
this.chunky = new Chunky(new NeoForgeServer(this, server), new GsonConfig(configPath));
if (chunky.getConfig().getContinueOnRestart()) {
chunky.getCommands().get(CommandLiteral.CONTINUE).execute(chunky.getServer().getConsole(), CommandArguments.empty());
}
chunky.getEventBus().subscribe(GenerationTaskUpdateEvent.class, new BossBarTaskUpdateListener(bossBars));
chunky.getEventBus().subscribe(GenerationTaskFinishEvent.class, new BossBarTaskFinishListener(bossBars));
}
@SubscribeEvent
public void onRegisterCommands(final RegisterCommandsEvent event) {
final LiteralArgumentBuilder<CommandSourceStack> command = literal(CommandLiteral.CHUNKY)
.requires(serverCommandSource -> {
if (serverCommandSource.getServer().isSingleplayer()) {
return true;
}
return serverCommandSource.hasPermission(2);
})
.executes(context -> {
final Sender sender;
if (context.getSource().getEntity() instanceof final ServerPlayer player) {
sender = new NeoForgePlayer(player);
} else {
sender = new NeoForgeSender(context.getSource());
}
final Map<String, ChunkyCommand> commands = chunky.getCommands();
final String input = context.getInput().substring(context.getLastChild().getNodes().get(0).getRange().getStart());
final String[] tokens = input.split(" ");
final String subCommand = tokens.length > 1 && commands.containsKey(tokens[1]) ? tokens[1] : CommandLiteral.HELP;
final CommandArguments arguments = tokens.length > 2 ? CommandArguments.of(Arrays.copyOfRange(tokens, 2, tokens.length)) : CommandArguments.empty();
commands.get(subCommand).execute(sender, arguments);
return Command.SINGLE_SUCCESS;
});
registerArguments(command, literal(CommandLiteral.CANCEL),
argument(CommandLiteral.WORLD, dimension()));
registerArguments(command, literal(CommandLiteral.CENTER),
argument(CommandLiteral.X, word()),
argument(CommandLiteral.Z, word()));
registerArguments(command, literal(CommandLiteral.CONFIRM));
registerArguments(command, literal(CommandLiteral.CONTINUE),
argument(CommandLiteral.WORLD, dimension()));
registerArguments(command, literal(CommandLiteral.CORNERS),
argument(CommandLiteral.X1, word()),
argument(CommandLiteral.Z1, word()),
argument(CommandLiteral.X2, word()),
argument(CommandLiteral.Z2, word()));
registerArguments(command, literal(CommandLiteral.HELP),
argument(CommandLiteral.PAGE, integer()));
registerArguments(command, literal(CommandLiteral.PATTERN),
argument(CommandLiteral.PATTERN, string()).suggests(SuggestionProviders.PATTERNS),
argument(CommandLiteral.VALUE, string()));
registerArguments(command, literal(CommandLiteral.PAUSE),
argument(CommandLiteral.WORLD, dimension()));
registerArguments(command, literal(CommandLiteral.PROGRESS));
registerArguments(command, literal(CommandLiteral.QUIET),
argument(CommandLiteral.INTERVAL, integer()));
registerArguments(command, literal(CommandLiteral.RADIUS),
argument(CommandLiteral.RADIUS, word()),
argument(CommandLiteral.RADIUS, word()));
registerArguments(command, literal(CommandLiteral.RELOAD),
argument(CommandLiteral.TYPE, word()));
registerArguments(command, literal(CommandLiteral.SELECTION));
registerArguments(command, literal(CommandLiteral.SHAPE),
argument(CommandLiteral.SHAPE, string()).suggests(SuggestionProviders.SHAPES));
registerArguments(command, literal(CommandLiteral.SILENT));
registerArguments(command, literal(CommandLiteral.SPAWN));
registerArguments(command, literal(CommandLiteral.START),
argument(CommandLiteral.WORLD, dimension()),
argument(CommandLiteral.SHAPE, string()).suggests(SuggestionProviders.SHAPES),
argument(CommandLiteral.CENTER_X, word()),
argument(CommandLiteral.CENTER_Z, word()),
argument(CommandLiteral.RADIUS_X, word()),
argument(CommandLiteral.RADIUS_Z, word()));
registerArguments(command, literal(CommandLiteral.TRIM),
argument(CommandLiteral.WORLD, dimension()),
argument(CommandLiteral.SHAPE, string()).suggests(SuggestionProviders.SHAPES),
argument(CommandLiteral.CENTER_X, word()),
argument(CommandLiteral.CENTER_Z, word()),
argument(CommandLiteral.RADIUS_X, word()),
argument(CommandLiteral.RADIUS_Z, word()),
argument(CommandLiteral.TRIM_MODE, string()).suggests(SuggestionProviders.TRIM_MODES),
argument(CommandLiteral.INHABITED, word()));
registerArguments(command, literal(CommandLiteral.WORLDBORDER));
registerArguments(command, literal(CommandLiteral.WORLD),
argument(CommandLiteral.WORLD, dimension()));
final LiteralArgumentBuilder<CommandSourceStack> borderCommand = literal(CommandLiteral.BORDER)
.requires(serverCommandSource -> chunky != null && chunky.getCommands().containsKey(CommandLiteral.BORDER))
.executes(command.getCommand());
registerArguments(borderCommand, literal(CommandLiteral.ADD),
argument(CommandLiteral.WORLD, dimension()),
argument(CommandLiteral.SHAPE, string()).suggests(SuggestionProviders.SHAPES),
argument(CommandLiteral.CENTER_X, word()),
argument(CommandLiteral.CENTER_Z, word()),
argument(CommandLiteral.RADIUS_X, word()),
argument(CommandLiteral.RADIUS_Z, word()));
registerArguments(borderCommand, literal(CommandLiteral.BYPASS),
argument(CommandLiteral.PLAYER, player()));
registerArguments(borderCommand, literal(CommandLiteral.HELP));
registerArguments(borderCommand, literal(CommandLiteral.LIST));
registerArguments(borderCommand, literal(CommandLiteral.LOAD),
argument(CommandLiteral.WORLD, dimension()));
registerArguments(borderCommand, literal(CommandLiteral.REMOVE),
argument(CommandLiteral.WORLD, dimension()));
registerArguments(borderCommand, literal(CommandLiteral.WRAP),
argument(CommandLiteral.WRAP, word()));
registerArguments(command, borderCommand);
event.getDispatcher().register(command);
}
@SafeVarargs
private <S> void registerArguments(final LiteralArgumentBuilder<S> command, final ArgumentBuilder<S, ?>... arguments) {
for (int i = arguments.length - 1; i > 0; --i) {
arguments[i - 1].then(arguments[i].executes(command.getCommand()));
}
command.then(arguments[0].executes(command.getCommand()));
}
@SubscribeEvent
public void onServerStopping(final ServerStoppingEvent event) {
if (chunky != null) {
chunky.disable();
}
}
public Chunky getChunky() {
return chunky;
}
}
@@ -1,28 +0,0 @@
package org.popcraft.chunky.command.suggestion;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.commands.CommandSourceStack;
import org.popcraft.chunky.command.CommandLiteral;
import org.popcraft.chunky.iterator.PatternType;
import java.util.concurrent.CompletableFuture;
public class PatternSuggestionProvider implements SuggestionProvider<CommandSourceStack> {
@Override
public CompletableFuture<Suggestions> getSuggestions(final CommandContext<CommandSourceStack> context, final SuggestionsBuilder builder) {
try {
final String input = context.getArgument(CommandLiteral.PATTERN, String.class);
PatternType.ALL.forEach(pattern -> {
if (pattern.contains(input.toLowerCase())) {
builder.suggest(pattern);
}
});
} catch (IllegalArgumentException e) {
PatternType.ALL.forEach(builder::suggest);
}
return builder.buildFuture();
}
}
@@ -1,28 +0,0 @@
package org.popcraft.chunky.command.suggestion;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.commands.CommandSourceStack;
import org.popcraft.chunky.command.CommandLiteral;
import org.popcraft.chunky.shape.ShapeType;
import java.util.concurrent.CompletableFuture;
public class ShapeSuggestionProvider implements SuggestionProvider<CommandSourceStack> {
@Override
public CompletableFuture<Suggestions> getSuggestions(final CommandContext<CommandSourceStack> context, final SuggestionsBuilder builder) {
try {
final String input = context.getArgument(CommandLiteral.SHAPE, String.class);
ShapeType.all().forEach(shape -> {
if (shape.contains(input.toLowerCase())) {
builder.suggest(shape);
}
});
} catch (IllegalArgumentException e) {
ShapeType.all().forEach(builder::suggest);
}
return builder.buildFuture();
}
}
@@ -1,19 +0,0 @@
package org.popcraft.chunky.command.suggestion;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import net.minecraft.commands.CommandSourceStack;
public final class SuggestionProviders {
public static final SuggestionProvider<CommandSourceStack> PATTERNS;
public static final SuggestionProvider<CommandSourceStack> SHAPES;
public static final SuggestionProvider<CommandSourceStack> TRIM_MODES;
static {
PATTERNS = new PatternSuggestionProvider();
SHAPES = new ShapeSuggestionProvider();
TRIM_MODES = new TrimModeSuggestionProvider();
}
private SuggestionProviders() {
}
}
@@ -1,30 +0,0 @@
package org.popcraft.chunky.command.suggestion;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.commands.CommandSourceStack;
import org.popcraft.chunky.command.CommandLiteral;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class TrimModeSuggestionProvider implements SuggestionProvider<CommandSourceStack> {
private static final List<String> TRIM_MODES = List.of("inside", "outside");
@Override
public CompletableFuture<Suggestions> getSuggestions(final CommandContext<CommandSourceStack> context, final SuggestionsBuilder builder) {
try {
final String input = context.getArgument(CommandLiteral.TRIM_MODE, String.class);
TRIM_MODES.forEach(shape -> {
if (shape.contains(input.toLowerCase())) {
builder.suggest(shape);
}
});
} catch (IllegalArgumentException e) {
TRIM_MODES.forEach(builder::suggest);
}
return builder.buildFuture();
}
}
@@ -1,33 +0,0 @@
package org.popcraft.chunky.listeners.bossbar;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerBossEvent;
import org.popcraft.chunky.GenerationTask;
import org.popcraft.chunky.event.task.GenerationTaskFinishEvent;
import org.popcraft.chunky.platform.World;
import java.util.Map;
import java.util.function.Consumer;
public class BossBarTaskFinishListener implements Consumer<GenerationTaskFinishEvent> {
private final Map<ResourceLocation, ServerBossEvent> bossBars;
public BossBarTaskFinishListener(final Map<ResourceLocation, ServerBossEvent> bossBars) {
this.bossBars = bossBars;
}
@Override
public void accept(final GenerationTaskFinishEvent event) {
final GenerationTask task = event.generationTask();
final World world = task.getSelection().world();
final ResourceLocation worldIdentifier = ResourceLocation.tryParse(world.getKey());
if (worldIdentifier == null) {
return;
}
final ServerBossEvent bossBar = bossBars.get(worldIdentifier);
if (bossBar != null) {
bossBar.removeAllPlayers();
bossBars.remove(worldIdentifier);
}
}
}
@@ -1,87 +0,0 @@
package org.popcraft.chunky.listeners.bossbar;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerBossEvent;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.BossEvent;
import net.minecraft.world.level.Level;
import org.popcraft.chunky.Chunky;
import org.popcraft.chunky.GenerationTask;
import org.popcraft.chunky.event.task.GenerationTaskUpdateEvent;
import org.popcraft.chunky.platform.NeoForgeWorld;
import org.popcraft.chunky.platform.World;
import java.util.Map;
import java.util.function.Consumer;
public class BossBarTaskUpdateListener implements Consumer<GenerationTaskUpdateEvent> {
private final Map<ResourceLocation, ServerBossEvent> bossBars;
public BossBarTaskUpdateListener(final Map<ResourceLocation, ServerBossEvent> bossBars) {
this.bossBars = bossBars;
}
@Override
public void accept(final GenerationTaskUpdateEvent event) {
final GenerationTask task = event.generationTask();
final Chunky chunky = task.getChunky();
final World world = task.getSelection().world();
final ResourceLocation worldIdentifier = ResourceLocation.tryParse(world.getKey());
if (worldIdentifier == null || !(world instanceof final NeoForgeWorld neoForgeWorld)) {
return;
}
final ServerBossEvent bossBar = bossBars.computeIfAbsent(worldIdentifier, x -> createNewBossBar(worldIdentifier));
final boolean silent = chunky.getConfig().isSilent();
if (silent == bossBar.isVisible()) {
bossBar.setVisible(!silent);
}
final MinecraftServer server = neoForgeWorld.getWorld().getServer();
for (final ServerPlayer player : server.getPlayerList().getPlayers()) {
if (player.hasPermissions(2)) {
bossBar.addPlayer(player);
} else {
bossBar.removePlayer(player);
}
}
final GenerationTask.Progress progress = task.getProgress();
bossBar.setName(Component.nullToEmpty(String.format("%s | %s%% | %s:%s:%s",
worldIdentifier,
String.format("%.2f", progress.getPercentComplete()),
String.format("%01d", progress.getHours()),
String.format("%02d", progress.getMinutes()),
String.format("%02d", progress.getSeconds()))));
bossBar.setProgress(task.getProgress().getPercentComplete() / 100f);
if (progress.isComplete()) {
bossBar.removeAllPlayers();
bossBars.remove(worldIdentifier);
}
}
private ServerBossEvent createNewBossBar(final ResourceLocation worldIdentifier) {
final ServerBossEvent bossBar = new ServerBossEvent(
Component.nullToEmpty(worldIdentifier.toString()),
bossBarColor(worldIdentifier),
BossEvent.BossBarOverlay.PROGRESS
);
bossBar.setDarkenScreen(false);
bossBar.setPlayBossMusic(false);
bossBar.setCreateWorldFog(false);
return bossBar;
}
private static BossEvent.BossBarColor bossBarColor(ResourceLocation worldIdentifier) {
final BossEvent.BossBarColor bossBarColor;
if (Level.OVERWORLD.location().equals(worldIdentifier)) {
bossBarColor = BossEvent.BossBarColor.GREEN;
} else if (Level.NETHER.location().equals(worldIdentifier)) {
bossBarColor = BossEvent.BossBarColor.RED;
} else if (Level.END.location().equals(worldIdentifier)) {
bossBarColor = BossEvent.BossBarColor.PURPLE;
} else {
bossBarColor = BossEvent.BossBarColor.BLUE;
}
return bossBarColor;
}
}
@@ -1,33 +0,0 @@
package org.popcraft.chunky.platform;
import net.minecraft.world.level.border.WorldBorder;
import org.popcraft.chunky.platform.util.Vector2;
import org.popcraft.chunky.shape.ShapeType;
public class NeoForgeBorder implements Border {
private final WorldBorder worldBorder;
public NeoForgeBorder(final WorldBorder worldBorder) {
this.worldBorder = worldBorder;
}
@Override
public Vector2 getCenter() {
return Vector2.of(worldBorder.getCenterX(), worldBorder.getCenterZ());
}
@Override
public double getRadiusX() {
return worldBorder.getSize() / 2d;
}
@Override
public double getRadiusZ() {
return worldBorder.getSize() / 2d;
}
@Override
public String getShape() {
return ShapeType.SQUARE;
}
}
@@ -1,62 +0,0 @@
package org.popcraft.chunky.platform;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import org.popcraft.chunky.platform.util.Location;
import java.util.UUID;
import static org.popcraft.chunky.util.Translator.translateKey;
public class NeoForgePlayer extends NeoForgeSender implements Player {
private final ServerPlayer player;
public NeoForgePlayer(final ServerPlayer player) {
super(player.createCommandSourceStack());
this.player = player;
}
@Override
public boolean isPlayer() {
return true;
}
@Override
public String getName() {
return player.getName().toString();
}
@Override
public World getWorld() {
return new NeoForgeWorld(player.serverLevel());
}
@Override
public Location getLocation() {
return new Location(getWorld(), player.getX(), player.getY(), player.getZ(), player.getXRot(), player.getYRot());
}
@Override
public void sendMessage(final String key, final boolean prefixed, final Object... args) {
player.sendSystemMessage(formatColored(translateKey(key, prefixed, args)));
}
@Override
public UUID getUUID() {
return player.getUUID();
}
@Override
public void teleport(final Location location) {
player.teleportTo(((NeoForgeWorld) location.getWorld()).getWorld(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
}
@Override
public void sendActionBar(final String key) {
player.displayClientMessage(formatColored(translateKey(key, false)), true);
}
private Component formatColored(final String message) {
return Component.nullToEmpty(message.replaceAll("&(?=[0-9a-fk-orA-FK-OR])", "§"));
}
}
@@ -1,50 +0,0 @@
package org.popcraft.chunky.platform;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3;
import org.popcraft.chunky.platform.util.Location;
import static org.popcraft.chunky.util.Translator.translateKey;
public class NeoForgeSender implements Sender {
private final CommandSourceStack source;
public NeoForgeSender(final CommandSourceStack source) {
this.source = source;
}
@Override
public boolean isPlayer() {
return source.getEntity() instanceof ServerPlayer;
}
@Override
public String getName() {
return source.getTextName();
}
@Override
public World getWorld() {
return new NeoForgeWorld(source.getLevel());
}
@Override
public Location getLocation() {
final Vec3 pos = source.getPosition();
final Vec2 rot = source.getRotation();
return new Location(getWorld(), pos.x(), pos.y(), pos.z(), rot.x, rot.y);
}
@Override
public boolean hasPermission(final String permission) {
return source.hasPermission(2);
}
@Override
public void sendMessage(final String key, final boolean prefixed, final Object... args) {
source.sendSuccess(() -> Component.nullToEmpty(translateKey(key, prefixed, args).replaceAll("&[0-9a-fk-orA-FK-OR]", "")), false);
}
}
@@ -1,83 +0,0 @@
package org.popcraft.chunky.platform;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.ServerInterface;
import net.minecraft.server.level.ServerLevel;
import org.popcraft.chunky.ChunkyNeoForge;
import org.popcraft.chunky.integration.Integration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
public class NeoForgeServer implements Server {
private final ChunkyNeoForge plugin;
private final MinecraftServer server;
public NeoForgeServer(final ChunkyNeoForge plugin, final MinecraftServer server) {
this.plugin = plugin;
this.server = server;
}
@Override
public Map<String, Integration> getIntegrations() {
return Map.of();
}
@Override
public Optional<World> getWorld(final String name) {
return Optional.ofNullable(ResourceLocation.tryParse(name))
.map(resourceLocation -> server.getLevel(ResourceKey.create(Registries.DIMENSION, resourceLocation)))
.or(() -> {
for (final ServerLevel level : server.getAllLevels()) {
if (name.equals(level.dimension().location().getPath())) {
return Optional.of(level);
}
}
return Optional.empty();
})
.map(NeoForgeWorld::new);
}
@Override
public List<World> getWorlds() {
final List<World> worlds = new ArrayList<>();
server.getAllLevels().forEach(world -> worlds.add(new NeoForgeWorld(world)));
return worlds;
}
@Override
public int getMaxWorldSize() {
if (server instanceof final ServerInterface serverInterface) {
return serverInterface.getProperties().maxWorldSize;
} else {
return server.getAbsoluteMaxWorldSize();
}
}
@Override
public Sender getConsole() {
return new NeoForgeSender(server.createCommandSourceStack());
}
@Override
public Collection<Player> getPlayers() {
return server.getPlayerList().getPlayers().stream().map(NeoForgePlayer::new).collect(Collectors.toList());
}
@Override
public Optional<Player> getPlayer(final String name) {
return Optional.ofNullable(server.getPlayerList().getPlayerByName(name)).map(NeoForgePlayer::new);
}
@Override
public Config getConfig() {
return plugin.getChunky().getConfig();
}
}
@@ -1,191 +0,0 @@
package org.popcraft.chunky.platform;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.nbt.visitors.CollectFields;
import net.minecraft.nbt.visitors.FieldSelector;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.TicketType;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Unit;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.storage.LevelResource;
import org.popcraft.chunky.ChunkyNeoForge;
import org.popcraft.chunky.platform.util.Location;
import org.popcraft.chunky.util.Input;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
public class NeoForgeWorld implements World {
private static final int TICKING_LOAD_DURATION = Input.tryInteger(System.getProperty("chunky.tickingLoadDuration")).orElse(0);
private static final TicketType<Unit> CHUNKY = TicketType.create(ChunkyNeoForge.MOD_ID, (unit, unit2) -> 0);
private static final TicketType<Unit> CHUNKY_TICKING = TicketType.create("%s_ticking".formatted(ChunkyNeoForge.MOD_ID), (unit, unit2) -> 0, TICKING_LOAD_DURATION * 20);
private static final boolean UPDATE_CHUNK_NBT = Boolean.getBoolean("chunky.updateChunkNbt");
private final ServerLevel world;
private final Border worldBorder;
public NeoForgeWorld(final ServerLevel world) {
this.world = world;
this.worldBorder = new NeoForgeBorder(world.getWorldBorder());
}
@Override
public String getName() {
return world.dimension().location().toString();
}
@Override
public String getKey() {
return getName();
}
@Override
public CompletableFuture<Boolean> isChunkGenerated(final int x, final int z) {
if (Thread.currentThread() != world.getServer().getRunningThread()) {
return CompletableFuture.supplyAsync(() -> isChunkGenerated(x, z), world.getServer()).thenCompose(Function.identity());
} else {
final ChunkPos chunkPos = new ChunkPos(x, z);
final ServerChunkCache serverChunkCache = world.getChunkSource();
final ChunkMap chunkStorage = serverChunkCache.chunkMap;
final ChunkHolder loadedChunkHolder = chunkStorage.getVisibleChunkIfPresent(chunkPos.toLong());
if (loadedChunkHolder != null && loadedChunkHolder.getLastAvailableStatus() == ChunkStatus.FULL) {
return CompletableFuture.completedFuture(true);
}
final ChunkHolder unloadedChunkHolder = chunkStorage.pendingUnloads.get(chunkPos.toLong());
if (unloadedChunkHolder != null && unloadedChunkHolder.getLastAvailableStatus() == ChunkStatus.FULL) {
return CompletableFuture.completedFuture(true);
}
if (UPDATE_CHUNK_NBT) {
return chunkStorage.readChunk(chunkPos)
.thenApply(optionalNbt -> optionalNbt
.filter(chunkNbt -> chunkNbt.contains("Status", Tag.TAG_STRING))
.map(chunkNbt -> chunkNbt.getString("Status"))
.map(status -> "minecraft:full".equals(status) || "full".equals(status))
.orElse(false));
}
final FieldSelector statusSelector = new FieldSelector(StringTag.TYPE, "Status");
final CollectFields statusCollector = new CollectFields(statusSelector);
return serverChunkCache.chunkScanner().scanChunk(chunkPos, statusCollector)
.thenApply(ignored -> {
if (statusCollector.getResult() instanceof final CompoundTag chunkNbt) {
final String status = chunkNbt.getString("Status");
return "minecraft:full".equals(status) || "full".equals(status);
}
return false;
});
}
}
@Override
public CompletableFuture<Void> getChunkAtAsync(final int x, final int z) {
if (Thread.currentThread() != world.getServer().getRunningThread()) {
return CompletableFuture.supplyAsync(() -> getChunkAtAsync(x, z), world.getServer()).thenCompose(Function.identity());
} else {
final ChunkPos chunkPos = new ChunkPos(x, z);
final ServerChunkCache serverChunkCache = world.getChunkSource();
serverChunkCache.addRegionTicket(CHUNKY, chunkPos, 0, Unit.INSTANCE);
if (TICKING_LOAD_DURATION > 0) {
serverChunkCache.addRegionTicket(CHUNKY_TICKING, chunkPos, 1, Unit.INSTANCE);
}
serverChunkCache.runDistanceManagerUpdates();
final ChunkMap chunkManager = serverChunkCache.chunkMap;
final ChunkHolder chunkHolder = chunkManager.getVisibleChunkIfPresent(chunkPos.toLong());
final CompletableFuture<Void> chunkFuture = chunkHolder == null ? CompletableFuture.completedFuture(null) : CompletableFuture.allOf(chunkHolder.getOrScheduleFuture(ChunkStatus.FULL, chunkManager));
chunkFuture.whenCompleteAsync((ignored, throwable) -> serverChunkCache.removeRegionTicket(CHUNKY, chunkPos, 0, Unit.INSTANCE), world.getServer());
return chunkFuture;
}
}
@Override
public UUID getUUID() {
throw new UnsupportedOperationException();
}
@Override
public int getSeaLevel() {
return world.getSeaLevel();
}
@Override
public Location getSpawn() {
final BlockPos pos = world.getSharedSpawnPos();
final float rot = world.getSharedSpawnAngle();
return new Location(this, pos.getX(), pos.getY(), pos.getZ(), rot, 0);
}
@Override
public Border getWorldBorder() {
return worldBorder;
}
@Override
public int getElevation(final int x, final int z) {
final int height = world.getHeight(Heightmap.Types.MOTION_BLOCKING, x, z) + 1;
final int logicalHeight = world.getLogicalHeight();
if (height >= logicalHeight) {
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(x, logicalHeight, z);
int air = 0;
while (pos.getY() > world.getMinBuildHeight()) {
pos = pos.move(Direction.DOWN);
final BlockState blockState = world.getBlockState(pos);
if (blockState.isSolid() && air > 1) {
return pos.getY() + 1;
}
air = blockState.isAir() ? air + 1 : 0;
}
}
return height;
}
@Override
public int getMaxElevation() {
return world.getLogicalHeight();
}
@Override
public void playEffect(final Player player, final String effect) {
final Location location = player.getLocation();
final BlockPos pos = BlockPos.containing(location.getX(), location.getY(), location.getZ());
Input.tryInteger(effect).ifPresent(eventId -> world.levelEvent(eventId, pos, 0));
}
@Override
public void playSound(final Player player, final String sound) {
final Location location = player.getLocation();
world.getServer()
.registryAccess()
.registry(Registries.SOUND_EVENT)
.flatMap(soundEventRegistry -> soundEventRegistry.getOptional(ResourceLocation.tryParse(sound)))
.ifPresent(soundEvent -> world.playSound(null, location.getX(), location.getY(), location.getZ(), soundEvent, SoundSource.MASTER, 2f, 1f));
}
@Override
public Optional<Path> getDirectory(final String name) {
if (name == null) {
return Optional.empty();
}
final Path directory = DimensionType.getStorageFolder(world.dimension(), world.getServer().getWorldPath(LevelResource.ROOT)).normalize().resolve(name);
return Files.exists(directory) ? Optional.of(directory) : Optional.empty();
}
public ServerLevel getWorld() {
return world;
}
}
@@ -1,6 +0,0 @@
# ChunkMap
public net.minecraft.server.level.ChunkMap readChunk(Lnet/minecraft/world/level/ChunkPos;)Ljava/util/concurrent/CompletableFuture;
public net.minecraft.server.level.ChunkMap getVisibleChunkIfPresent(J)Lnet/minecraft/server/level/ChunkHolder;
public net.minecraft.server.level.ChunkMap pendingUnloads
# ServerChunkCache
public net.minecraft.server.level.ServerChunkCache runDistanceManagerUpdates()Z
@@ -1,24 +0,0 @@
modLoader="javafml"
loaderVersion="[1,)"
license="GNU GPLv3"
issueTrackerURL="${github}/issues"
[[mods]]
modId="${id}"
version="${version}"
displayName="${name}"
displayURL="${github}"
logoFile="icon.png"
authors="${author}"
description="${description}"
[[dependencies.chunky]]
modId="neoforge"
mandatory=true
versionRange="[20.2,)"
ordering="NONE"
side="BOTH"
[[dependencies.chunky]]
modId="minecraft"
mandatory=true
versionRange="[1.20,1.21)"
ordering="NONE"
side="BOTH"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

-6
View File
@@ -1,6 +0,0 @@
{
"pack": {
"description": "chunky resources",
"pack_format": 8
}
}
-3
View File
@@ -15,9 +15,6 @@ sequenceOf(
"paper",
"folia",
"bukkit",
"fabric",
"forge",
"neoforge",
).forEach {
include("${rootProject.name}-$it")
project(":${rootProject.name}-$it").projectDir = file(it)