Remove unneeded subprojects
This commit is contained in:
1 parent
609fea09f6
commit
eda3874ba7
59 files changed
+51
-2838
No files matched your search
@@ -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>
|
||||
@@ -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
@@ -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]
|
||||
}
|
||||
|
||||
@@ -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/")
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
-28
@@ -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();
|
||||
}
|
||||
}
|
||||
-28
@@ -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() {
|
||||
}
|
||||
}
|
||||
-30
@@ -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();
|
||||
}
|
||||
}
|
||||
-33
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
-86
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 +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;
|
||||
}
|
||||
}
|
||||
-28
@@ -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();
|
||||
}
|
||||
}
|
||||
-28
@@ -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() {
|
||||
}
|
||||
}
|
||||
-30
@@ -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();
|
||||
}
|
||||
}
|
||||
-33
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
-87
@@ -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 |
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "chunky resources",
|
||||
"pack_format": 8
|
||||
}
|
||||
}
|
||||
@@ -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 +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;
|
||||
}
|
||||
}
|
||||
-28
@@ -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();
|
||||
}
|
||||
}
|
||||
-28
@@ -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();
|
||||
}
|
||||
}
|
||||
-19
@@ -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() {
|
||||
}
|
||||
}
|
||||
-30
@@ -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();
|
||||
}
|
||||
}
|
||||
-33
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
-87
@@ -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 |
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "chunky resources",
|
||||
"pack_format": 8
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,6 @@ sequenceOf(
|
||||
"paper",
|
||||
"folia",
|
||||
"bukkit",
|
||||
"fabric",
|
||||
"forge",
|
||||
"neoforge",
|
||||
).forEach {
|
||||
include("${rootProject.name}-$it")
|
||||
project(":${rootProject.name}-$it").projectDir = file(it)
|
||||
|
||||
Reference in new issue
Block a user