Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f8bf11660
|
||
|
|
f8dcf33fcb
|
||
|
|
116976d8e8 | ||
|
|
800a4fa743 | ||
|
|
3124d52e3b | ||
|
|
b973781649 | ||
|
|
107bb79474 | ||
|
|
f35cb20714 | ||
|
|
aab04df0b6 | ||
|
|
eda3874ba7 | ||
|
|
609fea09f6 |
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 @@
|
||||
.gitea/CODEOWNERS linguist-detectable=false
|
||||
@@ -0,0 +1,3 @@
|
||||
# Pull requests request review from the eligible staff team(s).
|
||||
# One approval from either an Admin or Developer satisfies branch protection.
|
||||
* @trueog/Admins @trueog/Developers
|
||||
@@ -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>
|
||||
+46
-24
@@ -1,17 +1,21 @@
|
||||
import java.io.ByteArrayOutputStream
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
import org.gradle.api.tasks.Sync
|
||||
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.9" 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 +24,7 @@ subprojects {
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(17))
|
||||
}
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
@@ -32,49 +34,69 @@ subprojects {
|
||||
options.release = 17
|
||||
options.compilerArgs.add("-Xlint:none")
|
||||
}
|
||||
jar {
|
||||
|
||||
withType<AbstractArchiveTask> {
|
||||
isPreserveFileTimestamps = false
|
||||
isReproducibleFileOrder = true
|
||||
}
|
||||
|
||||
named<Jar>("jar") {
|
||||
archiveClassifier.set("noshade")
|
||||
}
|
||||
shadowJar {
|
||||
|
||||
named<ShadowJar>("shadowJar") {
|
||||
archiveClassifier.set("")
|
||||
archiveFileName.set("${project.property("artifactName")}-${project.version}.jar")
|
||||
isEnableRelocation = true
|
||||
relocationPrefix = "${project.group}.${rootProject.name.lowercase()}.shadow"
|
||||
}
|
||||
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"])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named<Jar>("jar") {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
val pluginArtifact by tasks.registering(Sync::class) {
|
||||
dependsOn(":Chunky-bukkit:shadowJar")
|
||||
from(project(":Chunky-bukkit").tasks.named("shadowJar"))
|
||||
into(layout.buildDirectory.dir("libs"))
|
||||
}
|
||||
|
||||
tasks.named("build") {
|
||||
dependsOn(pluginArtifact)
|
||||
}
|
||||
|
||||
fun commitsSinceLastTag(): String {
|
||||
val tagDescription = ByteArrayOutputStream()
|
||||
exec {
|
||||
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]
|
||||
}
|
||||
+15
-8
@@ -1,18 +1,23 @@
|
||||
plugins {
|
||||
id("com.gradleup.shadow")
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://repo.purpurmc.org/snapshots")
|
||||
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
maven("https://jitpack.io")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(group = "org.spigotmc", name = "spigot-api", version = "1.20.4-R0.1-SNAPSHOT")
|
||||
compileOnly(group = "org.purpurmc.purpur", name = "purpur-api", version = "1.19.4-R0.1-SNAPSHOT")
|
||||
compileOnly(group = "com.github.Puremin0rez", name = "WorldBorder", version = "1.19") {
|
||||
isTransitive = false
|
||||
}
|
||||
implementation(group = "org.bstats", name = "bstats-bukkit", version = "3.0.2")
|
||||
implementation(project(":chunky-common"))
|
||||
implementation(project(":chunky-paper"))
|
||||
implementation(project(":chunky-folia"))
|
||||
implementation(project(":Chunky-common"))
|
||||
implementation(project(":Chunky-paper"))
|
||||
implementation(project(":Chunky-folia"))
|
||||
}
|
||||
|
||||
tasks {
|
||||
@@ -28,11 +33,13 @@ tasks {
|
||||
}
|
||||
}
|
||||
shadowJar {
|
||||
archiveClassifier.set("")
|
||||
isEnableRelocation = false
|
||||
minimize {
|
||||
exclude(project(":chunky-common"))
|
||||
exclude(project(":chunky-paper"))
|
||||
exclude(project(":chunky-folia"))
|
||||
exclude(project(":Chunky-common"))
|
||||
exclude(project(":Chunky-paper"))
|
||||
exclude(project(":Chunky-folia"))
|
||||
}
|
||||
relocate("org.bstats", "${project.group}.${rootProject.name}.lib.bstats")
|
||||
relocate("org.bstats", "${project.group}.${rootProject.name.lowercase()}.lib.bstats")
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
# Chunky Configuration
|
||||
# https://github.com/pop4959/Chunky/wiki/Configuration
|
||||
|
||||
version: 2
|
||||
language: en
|
||||
continue-on-restart: false
|
||||
continue-on-restart: true
|
||||
force-load-existing-chunks: false
|
||||
silent: false
|
||||
update-interval: 1
|
||||
@@ -2,7 +2,7 @@ dependencies {
|
||||
compileOnly(group = "com.google.code.gson", name = "gson", version = "2.8.9")
|
||||
testImplementation(group = "junit", name = "junit", version = "4.13.2")
|
||||
testImplementation(group = "com.google.code.gson", name = "gson", version = "2.8.9")
|
||||
implementation(project(":chunky-nbt"))
|
||||
implementation(project(":Chunky-nbt"))
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
Vendored
BIN
Binary file not shown.
+2
-1
@@ -1,6 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -15,6 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -55,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -83,7 +85,8 @@ done
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
@@ -111,7 +114,7 @@ case "$( uname )" in #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
@@ -130,10 +133,13 @@ location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
@@ -141,7 +147,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
@@ -149,7 +155,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
@@ -198,16 +204,16 @@ fi
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
|
||||
Vendored
+94
-92
@@ -1,92 +1,94 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
+1
-5
@@ -7,7 +7,7 @@ pluginManagement {
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "chunky"
|
||||
rootProject.name = "Chunky"
|
||||
|
||||
sequenceOf(
|
||||
"nbt",
|
||||
@@ -15,10 +15,6 @@ sequenceOf(
|
||||
"paper",
|
||||
"folia",
|
||||
"bukkit",
|
||||
"fabric",
|
||||
"forge",
|
||||
"neoforge",
|
||||
"sponge"
|
||||
).forEach {
|
||||
include("${rootProject.name}-$it")
|
||||
project(":${rootProject.name}-$it").projectDir = file(it)
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
import org.spongepowered.gradle.plugin.config.PluginLoaders
|
||||
import org.spongepowered.plugin.metadata.model.PluginDependency
|
||||
|
||||
plugins {
|
||||
id("org.spongepowered.gradle.plugin") version "2.2.0"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":chunky-common"))
|
||||
}
|
||||
|
||||
sponge {
|
||||
apiVersion("8.1.0")
|
||||
loader {
|
||||
name(PluginLoaders.JAVA_PLAIN)
|
||||
version("1.0")
|
||||
}
|
||||
license("GPL-3.0")
|
||||
plugin(rootProject.name) {
|
||||
displayName("${project.property("artifactName")}")
|
||||
version("${project.version}")
|
||||
entrypoint("${project.group}.${rootProject.name}.ChunkySponge")
|
||||
description("${project.property("description")}")
|
||||
links {
|
||||
homepage("${project.property("github")}")
|
||||
source("${project.property("github")}")
|
||||
issues("${project.property("github")}/issues")
|
||||
}
|
||||
contributor("${project.property("author")}") {
|
||||
description("Lead Developer")
|
||||
}
|
||||
dependency("spongeapi") {
|
||||
loadOrder(PluginDependency.LoadOrder.AFTER)
|
||||
optional(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,352 +0,0 @@
|
||||
package org.popcraft.chunky;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.popcraft.chunky.command.CommandArguments;
|
||||
import org.popcraft.chunky.command.CommandLiteral;
|
||||
import org.popcraft.chunky.command.suggestion.SuggestionProviders;
|
||||
import org.popcraft.chunky.platform.SpongeConfig;
|
||||
import org.popcraft.chunky.platform.SpongeSender;
|
||||
import org.popcraft.chunky.platform.SpongeServer;
|
||||
import org.spongepowered.api.Game;
|
||||
import org.spongepowered.api.ResourceKey;
|
||||
import org.spongepowered.api.Server;
|
||||
import org.spongepowered.api.command.Command;
|
||||
import org.spongepowered.api.command.CommandResult;
|
||||
import org.spongepowered.api.command.parameter.CommandContext;
|
||||
import org.spongepowered.api.command.parameter.Parameter;
|
||||
import org.spongepowered.api.config.ConfigDir;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.lifecycle.ConstructPluginEvent;
|
||||
import org.spongepowered.api.event.lifecycle.LoadedGameEvent;
|
||||
import org.spongepowered.api.event.lifecycle.RegisterCommandEvent;
|
||||
import org.spongepowered.api.event.lifecycle.StoppingEngineEvent;
|
||||
import org.spongepowered.api.world.server.ServerWorld;
|
||||
import org.spongepowered.plugin.PluginContainer;
|
||||
import org.spongepowered.plugin.builtin.jvm.Plugin;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Plugin("chunky")
|
||||
public class ChunkySponge {
|
||||
private Chunky chunky;
|
||||
private PluginContainer container;
|
||||
private Logger logger;
|
||||
@Inject
|
||||
private Game game;
|
||||
@Inject
|
||||
@ConfigDir(sharedRoot = false)
|
||||
private Path configPath;
|
||||
|
||||
@Listener
|
||||
public void onConstructPlugin(final ConstructPluginEvent event) {
|
||||
this.container = event.plugin();
|
||||
this.logger = event.plugin().logger();
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onLoadedGame(final LoadedGameEvent event) {
|
||||
this.chunky = new Chunky(new SpongeServer(this), new SpongeConfig(this));
|
||||
if (chunky.getConfig().getContinueOnRestart()) {
|
||||
chunky.getCommands().get(CommandLiteral.CONTINUE).execute(chunky.getServer().getConsole(), CommandArguments.empty());
|
||||
}
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onServerStopping(final StoppingEngineEvent<Server> event) {
|
||||
if (chunky != null) {
|
||||
chunky.disable();
|
||||
}
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onRegisterCommand(final RegisterCommandEvent<Command.Parameterized> event) {
|
||||
final Command.Parameterized cancelCommand = Command.builder()
|
||||
.permission("chunky.command.cancel")
|
||||
.addParameters(Parameter.world().key(CommandLiteral.WORLD).terminal().build())
|
||||
.terminal(true)
|
||||
.executor(ctx -> {
|
||||
final List<String> args = new ArrayList<>();
|
||||
ctx.one(Parameter.key(CommandLiteral.WORLD, ServerWorld.class)).map(ServerWorld::key).map(ResourceKey::asString).ifPresent(args::add);
|
||||
executeSpongeCommand(ctx, CommandLiteral.CANCEL, args);
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized centerCommand = Command.builder()
|
||||
.permission("chunky.command.center")
|
||||
.addParameters(
|
||||
Parameter.string().key(CommandLiteral.X).terminal().build(),
|
||||
Parameter.string().key(CommandLiteral.Z).terminal().build()
|
||||
)
|
||||
.terminal(true)
|
||||
.executor(ctx -> {
|
||||
final List<String> args = new ArrayList<>();
|
||||
ctx.one(Parameter.key(CommandLiteral.X, String.class)).ifPresent(args::add);
|
||||
ctx.one(Parameter.key(CommandLiteral.Z, String.class)).ifPresent(args::add);
|
||||
executeSpongeCommand(ctx, CommandLiteral.CENTER, args);
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized confirmCommand = Command.builder()
|
||||
.permission("chunky.command.confirm")
|
||||
.executor(ctx -> {
|
||||
executeSpongeCommand(ctx, CommandLiteral.CONFIRM, List.of());
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized continueCommand = Command.builder()
|
||||
.permission("chunky.command.continue")
|
||||
.addParameters(Parameter.world().key(CommandLiteral.WORLD).terminal().build())
|
||||
.terminal(true)
|
||||
.executor(ctx -> {
|
||||
final List<String> args = new ArrayList<>();
|
||||
ctx.one(Parameter.key(CommandLiteral.WORLD, ServerWorld.class)).map(ServerWorld::key).map(ResourceKey::asString).ifPresent(args::add);
|
||||
executeSpongeCommand(ctx, CommandLiteral.CONTINUE, args);
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized cornersCommand = Command.builder()
|
||||
.permission("chunky.command.corners")
|
||||
.addParameters(
|
||||
Parameter.string().key(CommandLiteral.X1).build(),
|
||||
Parameter.string().key(CommandLiteral.Z1).build(),
|
||||
Parameter.string().key(CommandLiteral.X2).build(),
|
||||
Parameter.string().key(CommandLiteral.Z2).build()
|
||||
)
|
||||
.executor(ctx -> {
|
||||
final List<String> args = new ArrayList<>();
|
||||
args.add(ctx.requireOne(Parameter.key(CommandLiteral.X1, String.class)));
|
||||
args.add(ctx.requireOne(Parameter.key(CommandLiteral.Z1, String.class)));
|
||||
args.add(ctx.requireOne(Parameter.key(CommandLiteral.X2, String.class)));
|
||||
args.add(ctx.requireOne(Parameter.key(CommandLiteral.Z2, String.class)));
|
||||
executeSpongeCommand(ctx, CommandLiteral.CORNERS, args);
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized helpCommand = Command.builder()
|
||||
.permission("chunky.command.help")
|
||||
.addParameters(Parameter.integerNumber().key(CommandLiteral.PAGE).terminal().build())
|
||||
.terminal(true)
|
||||
.executor(ctx -> {
|
||||
final List<String> args = new ArrayList<>();
|
||||
ctx.one(Parameter.key(CommandLiteral.PAGE, Integer.class)).map(String::valueOf).ifPresent(args::add);
|
||||
executeSpongeCommand(ctx, CommandLiteral.HELP, args);
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized patternCommand = Command.builder()
|
||||
.permission("chunky.command.pattern")
|
||||
.addParameters(
|
||||
Parameter.string().key(CommandLiteral.PATTERN).completer(SuggestionProviders.PATTERNS).terminal().build(),
|
||||
Parameter.string().key(CommandLiteral.VALUE).terminal().build()
|
||||
)
|
||||
.executor(ctx -> {
|
||||
final List<String> args = new ArrayList<>();
|
||||
args.add(ctx.requireOne(Parameter.key(CommandLiteral.PATTERN, String.class)));
|
||||
ctx.one(Parameter.key(CommandLiteral.VALUE, String.class)).ifPresent(args::add);
|
||||
executeSpongeCommand(ctx, CommandLiteral.PATTERN, args);
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized pauseCommand = Command.builder()
|
||||
.permission("chunky.command.pause")
|
||||
.addParameters(Parameter.world().key(CommandLiteral.WORLD).terminal().build())
|
||||
.terminal(true)
|
||||
.executor(ctx -> {
|
||||
final List<String> args = new ArrayList<>();
|
||||
ctx.one(Parameter.key(CommandLiteral.WORLD, ServerWorld.class)).map(ServerWorld::key).map(ResourceKey::asString).ifPresent(args::add);
|
||||
executeSpongeCommand(ctx, CommandLiteral.PAUSE, args);
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized progressCommand = Command.builder()
|
||||
.permission("chunky.command.progress")
|
||||
.executor(ctx -> {
|
||||
executeSpongeCommand(ctx, CommandLiteral.PROGRESS, List.of());
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized quietCommand = Command.builder()
|
||||
.permission("chunky.command.quiet")
|
||||
.addParameters(Parameter.integerNumber().key(CommandLiteral.INTERVAL).build())
|
||||
.executor(ctx -> {
|
||||
final List<String> args = new ArrayList<>();
|
||||
args.add(String.valueOf(ctx.requireOne(Parameter.key(CommandLiteral.INTERVAL, Integer.class))));
|
||||
executeSpongeCommand(ctx, CommandLiteral.QUIET, args);
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized radiusCommand = Command.builder()
|
||||
.permission("chunky.command.radius")
|
||||
.addParameters(
|
||||
Parameter.string().key(CommandLiteral.RADIUS_X).terminal().build(),
|
||||
Parameter.string().key(CommandLiteral.RADIUS_Z).terminal().build()
|
||||
)
|
||||
.executor(ctx -> {
|
||||
final List<String> args = new ArrayList<>();
|
||||
args.add(ctx.requireOne(Parameter.key(CommandLiteral.RADIUS_X, String.class)));
|
||||
ctx.one(Parameter.key(CommandLiteral.RADIUS_Z, String.class)).ifPresent(args::add);
|
||||
executeSpongeCommand(ctx, CommandLiteral.RADIUS, args);
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized reloadCommand = Command.builder()
|
||||
.permission("chunky.command.reload")
|
||||
.addParameters(Parameter.string().key(CommandLiteral.TYPE).terminal().build())
|
||||
.terminal(true)
|
||||
.executor(ctx -> {
|
||||
final List<String> args = new ArrayList<>();
|
||||
ctx.one(Parameter.key(CommandLiteral.TYPE, String.class)).ifPresent(args::add);
|
||||
executeSpongeCommand(ctx, CommandLiteral.RELOAD, args);
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized selectionCommand = Command.builder()
|
||||
.permission("chunky.command.selection")
|
||||
.executor(ctx -> {
|
||||
executeSpongeCommand(ctx, CommandLiteral.SELECTION, List.of());
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized shapeCommand = Command.builder()
|
||||
.permission("chunky.command.shape")
|
||||
.addParameters(Parameter.string().key(CommandLiteral.SHAPE).completer(SuggestionProviders.SHAPES).build())
|
||||
.executor(ctx -> {
|
||||
final List<String> args = new ArrayList<>();
|
||||
args.add(ctx.requireOne(Parameter.key(CommandLiteral.SHAPE, String.class)));
|
||||
executeSpongeCommand(ctx, CommandLiteral.SHAPE, args);
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized silentCommand = Command.builder()
|
||||
.permission("chunky.command.silent")
|
||||
.executor(ctx -> {
|
||||
executeSpongeCommand(ctx, CommandLiteral.SILENT, List.of());
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized spawnCommand = Command.builder()
|
||||
.permission("chunky.command.spawn")
|
||||
.executor(ctx -> {
|
||||
executeSpongeCommand(ctx, CommandLiteral.SPAWN, List.of());
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized startCommand = Command.builder()
|
||||
.permission("chunky.command.start")
|
||||
.addParameters(
|
||||
Parameter.world().key(CommandLiteral.WORLD).terminal().build(),
|
||||
Parameter.string().key(CommandLiteral.SHAPE).terminal().completer(SuggestionProviders.SHAPES).build(),
|
||||
Parameter.string().key(CommandLiteral.X).terminal().build(),
|
||||
Parameter.string().key(CommandLiteral.Z).terminal().build(),
|
||||
Parameter.string().key(CommandLiteral.RADIUS_X).terminal().build(),
|
||||
Parameter.string().key(CommandLiteral.RADIUS_Z).terminal().build()
|
||||
)
|
||||
.terminal(true)
|
||||
.executor(ctx -> {
|
||||
final List<String> args = new ArrayList<>();
|
||||
ctx.one(Parameter.key(CommandLiteral.WORLD, ServerWorld.class)).map(ServerWorld::key).map(ResourceKey::asString).ifPresent(args::add);
|
||||
ctx.one(Parameter.key(CommandLiteral.SHAPE, String.class)).ifPresent(args::add);
|
||||
ctx.one(Parameter.key(CommandLiteral.X, String.class)).ifPresent(args::add);
|
||||
ctx.one(Parameter.key(CommandLiteral.Z, String.class)).ifPresent(args::add);
|
||||
ctx.one(Parameter.key(CommandLiteral.RADIUS_X, String.class)).ifPresent(args::add);
|
||||
ctx.one(Parameter.key(CommandLiteral.RADIUS_Z, String.class)).ifPresent(args::add);
|
||||
executeSpongeCommand(ctx, CommandLiteral.START, args);
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized trimCommand = Command.builder()
|
||||
.permission("chunky.command.trim")
|
||||
.addParameters(
|
||||
Parameter.world().key(CommandLiteral.WORLD).terminal().build(),
|
||||
Parameter.string().key(CommandLiteral.SHAPE).terminal().completer(SuggestionProviders.SHAPES).build(),
|
||||
Parameter.string().key(CommandLiteral.X).terminal().build(),
|
||||
Parameter.string().key(CommandLiteral.Z).terminal().build(),
|
||||
Parameter.string().key(CommandLiteral.RADIUS_X).terminal().build(),
|
||||
Parameter.string().key(CommandLiteral.RADIUS_Z).terminal().build()
|
||||
)
|
||||
.terminal(true)
|
||||
.executor(ctx -> {
|
||||
final List<String> args = new ArrayList<>();
|
||||
ctx.one(Parameter.key(CommandLiteral.WORLD, ServerWorld.class)).map(ServerWorld::key).map(ResourceKey::asString).ifPresent(args::add);
|
||||
ctx.one(Parameter.key(CommandLiteral.SHAPE, String.class)).ifPresent(args::add);
|
||||
ctx.one(Parameter.key(CommandLiteral.X, String.class)).ifPresent(args::add);
|
||||
ctx.one(Parameter.key(CommandLiteral.Z, String.class)).ifPresent(args::add);
|
||||
ctx.one(Parameter.key(CommandLiteral.RADIUS_X, String.class)).ifPresent(args::add);
|
||||
ctx.one(Parameter.key(CommandLiteral.RADIUS_Z, String.class)).ifPresent(args::add);
|
||||
executeSpongeCommand(ctx, CommandLiteral.TRIM, args);
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized worldborderCommand = Command.builder()
|
||||
.permission("chunky.command.worldborder")
|
||||
.executor(ctx -> {
|
||||
executeSpongeCommand(ctx, CommandLiteral.WORLDBORDER, List.of());
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
final Command.Parameterized worldCommand = Command.builder()
|
||||
.permission("chunky.command.world")
|
||||
.addParameters(Parameter.world().key(CommandLiteral.WORLD).build())
|
||||
.executor(ctx -> {
|
||||
final List<String> args = new ArrayList<>();
|
||||
ctx.one(Parameter.key(CommandLiteral.WORLD, ServerWorld.class)).map(ServerWorld::key).map(ResourceKey::asString).ifPresent(args::add);
|
||||
executeSpongeCommand(ctx, CommandLiteral.WORLD, args);
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build();
|
||||
event.register(this.container, Command.builder()
|
||||
.permission("chunky.command.base")
|
||||
.addChild(cancelCommand, CommandLiteral.CANCEL)
|
||||
.addChild(centerCommand, CommandLiteral.CENTER)
|
||||
.addChild(confirmCommand, CommandLiteral.CONFIRM)
|
||||
.addChild(continueCommand, CommandLiteral.CONTINUE)
|
||||
.addChild(cornersCommand, CommandLiteral.CORNERS)
|
||||
.addChild(helpCommand, CommandLiteral.HELP)
|
||||
.addChild(patternCommand, CommandLiteral.PATTERN)
|
||||
.addChild(pauseCommand, CommandLiteral.PAUSE)
|
||||
.addChild(progressCommand, CommandLiteral.PROGRESS)
|
||||
.addChild(quietCommand, CommandLiteral.QUIET)
|
||||
.addChild(radiusCommand, CommandLiteral.RADIUS)
|
||||
.addChild(reloadCommand, CommandLiteral.RELOAD)
|
||||
.addChild(selectionCommand, CommandLiteral.SELECTION)
|
||||
.addChild(shapeCommand, CommandLiteral.SHAPE)
|
||||
.addChild(silentCommand, CommandLiteral.SILENT)
|
||||
.addChild(spawnCommand, CommandLiteral.SPAWN)
|
||||
.addChild(startCommand, CommandLiteral.START)
|
||||
.addChild(trimCommand, CommandLiteral.TRIM)
|
||||
.addChild(worldborderCommand, CommandLiteral.WORLDBORDER)
|
||||
.addChild(worldCommand, CommandLiteral.WORLD)
|
||||
.executor(ctx -> {
|
||||
executeSpongeCommand(ctx, CommandLiteral.HELP, List.of());
|
||||
return CommandResult.success();
|
||||
})
|
||||
.build(), CommandLiteral.CHUNKY);
|
||||
}
|
||||
|
||||
private void executeSpongeCommand(final CommandContext ctx, final String command, final List<String> args) {
|
||||
chunky.getCommands().get(command).execute(new SpongeSender(ctx.cause().root()), CommandArguments.of(args));
|
||||
}
|
||||
|
||||
public Chunky getChunky() {
|
||||
return chunky;
|
||||
}
|
||||
|
||||
public PluginContainer getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
public Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
public Game getGame() {
|
||||
return game;
|
||||
}
|
||||
|
||||
public Path getConfigPath() {
|
||||
return configPath;
|
||||
}
|
||||
}
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
package org.popcraft.chunky.command.suggestion;
|
||||
|
||||
import org.popcraft.chunky.iterator.PatternType;
|
||||
import org.spongepowered.api.command.CommandCompletion;
|
||||
import org.spongepowered.api.command.parameter.CommandContext;
|
||||
import org.spongepowered.api.command.parameter.managed.ValueCompleter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PatternSuggestionProvider implements ValueCompleter {
|
||||
@Override
|
||||
public List<CommandCompletion> complete(final CommandContext context, final String currentInput) {
|
||||
final List<CommandCompletion> completions = new ArrayList<>();
|
||||
PatternType.ALL.forEach(pattern -> {
|
||||
if (pattern.contains(currentInput.toLowerCase())) {
|
||||
completions.add(CommandCompletion.of(pattern));
|
||||
}
|
||||
});
|
||||
return completions;
|
||||
}
|
||||
}
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
package org.popcraft.chunky.command.suggestion;
|
||||
|
||||
import org.popcraft.chunky.shape.ShapeType;
|
||||
import org.spongepowered.api.command.CommandCompletion;
|
||||
import org.spongepowered.api.command.parameter.CommandContext;
|
||||
import org.spongepowered.api.command.parameter.managed.ValueCompleter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ShapeSuggestionProvider implements ValueCompleter {
|
||||
@Override
|
||||
public List<CommandCompletion> complete(final CommandContext context, final String currentInput) {
|
||||
final List<CommandCompletion> completions = new ArrayList<>();
|
||||
ShapeType.all().forEach(pattern -> {
|
||||
if (pattern.contains(currentInput.toLowerCase())) {
|
||||
completions.add(CommandCompletion.of(pattern));
|
||||
}
|
||||
});
|
||||
return completions;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package org.popcraft.chunky.command.suggestion;
|
||||
|
||||
public final class SuggestionProviders {
|
||||
public static final PatternSuggestionProvider PATTERNS;
|
||||
public static final ShapeSuggestionProvider SHAPES;
|
||||
|
||||
static {
|
||||
PATTERNS = new PatternSuggestionProvider();
|
||||
SHAPES = new ShapeSuggestionProvider();
|
||||
}
|
||||
|
||||
private SuggestionProviders() {
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package org.popcraft.chunky.platform;
|
||||
|
||||
import org.popcraft.chunky.platform.util.Vector2;
|
||||
import org.popcraft.chunky.shape.ShapeType;
|
||||
import org.spongepowered.api.world.server.ServerWorld;
|
||||
import org.spongepowered.math.vector.Vector2d;
|
||||
|
||||
public class SpongeBorder implements Border {
|
||||
private final ServerWorld serverWorld;
|
||||
|
||||
public SpongeBorder(final ServerWorld serverWorld) {
|
||||
this.serverWorld = serverWorld;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector2 getCenter() {
|
||||
final Vector2d center = serverWorld.border().center();
|
||||
return Vector2.of(center.x(), center.y());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getRadiusX() {
|
||||
return serverWorld.border().diameter() / 2d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getRadiusZ() {
|
||||
return serverWorld.border().diameter() / 2d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShape() {
|
||||
return ShapeType.SQUARE;
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
package org.popcraft.chunky.platform;
|
||||
|
||||
import org.popcraft.chunky.ChunkySponge;
|
||||
import org.popcraft.chunky.util.Input;
|
||||
import org.popcraft.chunky.util.Translator;
|
||||
import org.spongepowered.configurate.CommentedConfigurationNode;
|
||||
import org.spongepowered.configurate.hocon.HoconConfigurationLoader;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class SpongeConfig implements Config {
|
||||
private static final String CONFIG_FILE = "main.conf";
|
||||
private static final String ROOT_CONFIG_NODE = "config";
|
||||
private final ChunkySponge plugin;
|
||||
private final HoconConfigurationLoader configLoader;
|
||||
private CommentedConfigurationNode rootNode;
|
||||
|
||||
public SpongeConfig(final ChunkySponge plugin) {
|
||||
this.plugin = plugin;
|
||||
final Path defaultConfigPath = plugin.getConfigPath();
|
||||
try {
|
||||
Files.createDirectories(defaultConfigPath);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
final Path defaultConfigFile = new File(defaultConfigPath.toFile(), CONFIG_FILE).toPath();
|
||||
this.configLoader = HoconConfigurationLoader.builder()
|
||||
.path(defaultConfigFile)
|
||||
.build();
|
||||
try {
|
||||
this.rootNode = configLoader.load();
|
||||
} catch (IOException e) {
|
||||
this.rootNode = configLoader.createNode();
|
||||
e.printStackTrace();
|
||||
}
|
||||
final URL defaults = getClass().getClassLoader().getResource(CONFIG_FILE);
|
||||
if (defaults != null) {
|
||||
final HoconConfigurationLoader defaultConfigLoader = HoconConfigurationLoader.builder()
|
||||
.url(defaults)
|
||||
.build();
|
||||
try {
|
||||
final CommentedConfigurationNode defaultRootNode = defaultConfigLoader.load();
|
||||
rootNode.mergeFrom(defaultRootNode);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
configLoader.save(rootNode);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Translator.setLanguage(getLanguage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getDirectory() {
|
||||
return plugin.getConfigPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return this.rootNode == null ? 0 : this.rootNode.node(ROOT_CONFIG_NODE, "version").getInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLanguage() {
|
||||
if (this.rootNode == null) {
|
||||
return "en";
|
||||
}
|
||||
return Input.checkLanguage(this.rootNode.node(ROOT_CONFIG_NODE, "language").getString("en"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getContinueOnRestart() {
|
||||
return this.rootNode != null && this.rootNode.node(ROOT_CONFIG_NODE, "continue-on-restart").getBoolean(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForceLoadExistingChunks() {
|
||||
return this.rootNode != null && this.rootNode.node(ROOT_CONFIG_NODE, "force-load-existing-chunks").getBoolean(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSilent() {
|
||||
return this.rootNode != null && this.rootNode.node(ROOT_CONFIG_NODE, "silent").getBoolean(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSilent(final boolean silent) {
|
||||
if (this.rootNode != null) {
|
||||
try {
|
||||
this.rootNode.node(ROOT_CONFIG_NODE, "silent").set(silent);
|
||||
} catch (SerializationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUpdateInterval() {
|
||||
return this.rootNode == null ? 1 : this.rootNode.node(ROOT_CONFIG_NODE, "update-interval").getInt(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUpdateInterval(final int updateInterval) {
|
||||
if (this.rootNode != null) {
|
||||
try {
|
||||
this.rootNode.node(ROOT_CONFIG_NODE, "update-interval").set(updateInterval);
|
||||
} catch (SerializationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
try {
|
||||
this.rootNode = configLoader.load();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package org.popcraft.chunky.platform;
|
||||
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.popcraft.chunky.platform.util.Location;
|
||||
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
|
||||
import org.spongepowered.api.world.server.ServerLocation;
|
||||
import org.spongepowered.math.vector.Vector3d;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.popcraft.chunky.util.Translator.translateKey;
|
||||
|
||||
public class SpongePlayer extends SpongeSender implements Player {
|
||||
private final ServerPlayer player;
|
||||
|
||||
public SpongePlayer(final ServerPlayer player) {
|
||||
super(player);
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayer() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return player.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return new SpongeWorld(player.serverLocation().world());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
final ServerLocation loc = player.serverLocation();
|
||||
final Vector3d rot = player.rotation();
|
||||
return new Location(getWorld(), loc.x(), loc.y(), loc.z(), rot.floorX(), rot.floorY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return player.uniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teleport(final Location location) {
|
||||
player.setLocation(ServerLocation.of(((SpongeWorld) location.getWorld()).getWorld(), location.getX(), location.getY(), location.getZ()));
|
||||
player.setRotation(Vector3d.from(location.getYaw(), location.getPitch(), 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionBar(final String key) {
|
||||
player.sendActionBar(LegacyComponentSerializer.legacyAmpersand().deserialize(translateKey(key, false)));
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package org.popcraft.chunky.platform;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.identity.Identity;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.popcraft.chunky.platform.util.Location;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.entity.living.player.User;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
import org.spongepowered.api.world.DefaultWorldKeys;
|
||||
import org.spongepowered.api.world.server.WorldManager;
|
||||
|
||||
import static org.popcraft.chunky.util.Translator.translateKey;
|
||||
|
||||
public class SpongeSender implements Sender {
|
||||
private final Object source;
|
||||
|
||||
public SpongeSender(final Object source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayer() {
|
||||
return source instanceof Player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return source instanceof final User user ? user.name() : "Console";
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
final WorldManager worldManager = Sponge.game().server().worldManager();
|
||||
return new SpongeWorld(worldManager.world(DefaultWorldKeys.DEFAULT).orElseThrow(IllegalStateException::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return new Location(getWorld(), 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final String permission) {
|
||||
return source instanceof final Subject subject && subject.hasPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(final String key, final boolean prefixed, final Object... args) {
|
||||
if (source instanceof final Audience audience) {
|
||||
audience.sendMessage(Identity.nil(), LegacyComponentSerializer.legacyAmpersand().deserialize(translateKey(key, prefixed, args)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package org.popcraft.chunky.platform;
|
||||
|
||||
import org.popcraft.chunky.ChunkySponge;
|
||||
import org.popcraft.chunky.integration.Integration;
|
||||
import org.spongepowered.api.ResourceKey;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class SpongeServer implements Server {
|
||||
private static final int MAX_WORLD_SIZE = 29999984;
|
||||
private final ChunkySponge plugin;
|
||||
private final Map<String, Integration> integrations;
|
||||
|
||||
public SpongeServer(final ChunkySponge plugin) {
|
||||
this.plugin = plugin;
|
||||
this.integrations = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Integration> getIntegrations() {
|
||||
return integrations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<World> getWorld(final String name) {
|
||||
return plugin.getGame().server().worldManager().world(ResourceKey.resolve(name)).map(SpongeWorld::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<World> getWorlds() {
|
||||
final List<World> worlds = new ArrayList<>();
|
||||
plugin.getGame().server().worldManager().worlds().forEach(world -> worlds.add(new SpongeWorld(world)));
|
||||
return worlds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxWorldSize() {
|
||||
return MAX_WORLD_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsole() {
|
||||
return new SpongeSender(plugin.getGame().systemSubject());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Player> getPlayers() {
|
||||
final Collection<Player> players = new ArrayList<>();
|
||||
plugin.getGame().server().onlinePlayers().forEach(player -> players.add(new SpongePlayer(player)));
|
||||
return players;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Player> getPlayer(final String name) {
|
||||
return plugin.getGame().server().player(name).map(SpongePlayer::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Config getConfig() {
|
||||
return plugin.getChunky().getConfig();
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
package org.popcraft.chunky.platform;
|
||||
|
||||
import net.kyori.adventure.key.InvalidKeyException;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.sound.Sound;
|
||||
import org.popcraft.chunky.platform.util.Location;
|
||||
import org.spongepowered.api.ResourceKey;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.effect.particle.ParticleEffect;
|
||||
import org.spongepowered.api.registry.RegistryKey;
|
||||
import org.spongepowered.api.registry.RegistryTypes;
|
||||
import org.spongepowered.api.world.server.ServerWorld;
|
||||
import org.spongepowered.math.vector.Vector3d;
|
||||
import org.spongepowered.math.vector.Vector3i;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class SpongeWorld implements World {
|
||||
private final ServerWorld world;
|
||||
private final Border worldBorder;
|
||||
|
||||
public SpongeWorld(final ServerWorld world) {
|
||||
this.world = world;
|
||||
this.worldBorder = new SpongeBorder(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return world.key().asString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> isChunkGenerated(final int x, final int z) {
|
||||
return CompletableFuture.completedFuture(world.hasChunk(x, 0, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> getChunkAtAsync(final int x, final int z) {
|
||||
return CompletableFuture.allOf(CompletableFuture.completedFuture(world.loadChunk(x, 0, z, true)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return world.uniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSeaLevel() {
|
||||
return world.seaLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getSpawn() {
|
||||
final Vector3i spawn = world.properties().spawnPosition();
|
||||
return new Location(this, spawn.x(), spawn.y(), spawn.z(), 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Border getWorldBorder() {
|
||||
return worldBorder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getElevation(final int x, final int z) {
|
||||
return world.highestYAt(x, z) + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxElevation() {
|
||||
return world.maximumHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playEffect(final Player player, final String effect) {
|
||||
final Location location = player.getLocation();
|
||||
final Vector3d vector = Vector3d.from(location.getX(), location.getY(), location.getZ());
|
||||
RegistryKey.of(RegistryTypes.PARTICLE_TYPE, ResourceKey.resolve(effect)).asDefaultedReference(Sponge::game).find().ifPresent(particleType -> world.spawnParticles(ParticleEffect.builder().type(particleType).build(), vector));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(final Player player, final String sound) {
|
||||
final Key soundKey;
|
||||
try {
|
||||
//noinspection PatternValidation
|
||||
soundKey = Key.key(sound);
|
||||
} catch (final InvalidKeyException e) {
|
||||
return;
|
||||
}
|
||||
final Location location = player.getLocation();
|
||||
world.playSound(Sound.sound(soundKey, Sound.Source.MASTER, 2f, 1f), location.getX(), location.getY(), location.getZ());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Path> getDirectory(final String name) {
|
||||
if (name == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
final Path regionDirectory = world.directory().resolve(name);
|
||||
return Files.exists(regionDirectory) ? Optional.of(regionDirectory) : Optional.empty();
|
||||
}
|
||||
|
||||
public ServerWorld getWorld() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
# Chunky Configuration
|
||||
# https://github.com/pop4959/Chunky/wiki/Configuration
|
||||
config {
|
||||
continue-on-restart=false
|
||||
force-load-existing-chunks=false
|
||||
language=en
|
||||
silent=false
|
||||
update-interval=1
|
||||
version=2
|
||||
}
|
||||
Reference in new issue
Block a user