Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-24 15:20:25 +01:00
Ursprung
c67d50c13e
Commit
f78e6dd7e7
7
.github/workflows/build.yml
vendored
7
.github/workflows/build.yml
vendored
@ -65,13 +65,6 @@ jobs:
|
||||
name: Geyser BungeeCord
|
||||
path: bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser Sponge)
|
||||
uses: actions/upload-artifact@v3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser Sponge
|
||||
path: bootstrap/sponge/build/libs/Geyser-Sponge.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser Velocity)
|
||||
uses: actions/upload-artifact@v3
|
||||
if: success()
|
||||
|
7
.github/workflows/pullrequest.yml
vendored
7
.github/workflows/pullrequest.yml
vendored
@ -80,13 +80,6 @@ jobs:
|
||||
name: Geyser BungeeCord
|
||||
path: geyser/bootstrap/bungeecord/build/libs/Geyser-BungeeCord.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser Sponge)
|
||||
uses: actions/upload-artifact@v3
|
||||
if: success()
|
||||
with:
|
||||
name: Geyser Sponge
|
||||
path: geyser/bootstrap/sponge/build/libs/Geyser-Sponge.jar
|
||||
if-no-files-found: error
|
||||
- name: Archive artifacts (Geyser Velocity)
|
||||
uses: actions/upload-artifact@v3
|
||||
if: success()
|
||||
|
@ -29,10 +29,14 @@ package org.geysermc.geyser.api.util;
|
||||
* Represents the platform Geyser is running on.
|
||||
*/
|
||||
public record PlatformType(String platformName) {
|
||||
|
||||
@Deprecated
|
||||
public static final PlatformType ANDROID = new PlatformType("Android");
|
||||
public static final PlatformType BUNGEECORD = new PlatformType("BungeeCord");
|
||||
public static final PlatformType FABRIC = new PlatformType("Fabric");
|
||||
public static final PlatformType SPIGOT = new PlatformType("Spigot");
|
||||
|
||||
@Deprecated
|
||||
public static final PlatformType SPONGE = new PlatformType("Sponge");
|
||||
public static final PlatformType STANDALONE = new PlatformType("Standalone");
|
||||
public static final PlatformType VELOCITY = new PlatformType("Velocity");
|
||||
|
@ -1,38 +0,0 @@
|
||||
dependencies {
|
||||
api(projects.core)
|
||||
}
|
||||
|
||||
platformRelocate("com.fasterxml.jackson")
|
||||
platformRelocate("io.netty")
|
||||
platformRelocate("it.unimi.dsi.fastutil")
|
||||
platformRelocate("com.google.common")
|
||||
platformRelocate("com.google.guava")
|
||||
platformRelocate("net.kyori.adventure.text.serializer.gson.legacyimpl")
|
||||
platformRelocate("net.kyori.adventure.nbt")
|
||||
|
||||
// These dependencies are already present on the platform
|
||||
provided(libs.sponge.api)
|
||||
|
||||
application {
|
||||
mainClass.set("org.geysermc.geyser.platform.sponge.GeyserSpongeMain")
|
||||
}
|
||||
|
||||
tasks.withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar> {
|
||||
archiveBaseName.set("Geyser-Sponge")
|
||||
|
||||
dependencies {
|
||||
exclude(dependency("com.google.code.gson:.*"))
|
||||
exclude(dependency("org.yaml:.*"))
|
||||
exclude(dependency("org.slf4j:.*"))
|
||||
exclude(dependency("org.ow2.asm:.*"))
|
||||
|
||||
// Exclude all Kyori dependencies except the legacy NBT serializer and NBT
|
||||
exclude(dependency("net.kyori:adventure-api:.*"))
|
||||
exclude(dependency("net.kyori:examination-api:.*"))
|
||||
exclude(dependency("net.kyori:examination-string:.*"))
|
||||
exclude(dependency("net.kyori:adventure-text-serializer-gson:.*"))
|
||||
exclude(dependency("net.kyori:adventure-text-serializer-legacy:.*"))
|
||||
exclude(dependency("net.kyori:adventure-text-serializer-plain:.*"))
|
||||
exclude(dependency("net.kyori:adventure-key:.*"))
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.sponge;
|
||||
|
||||
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public final class GeyserSpongeConfiguration extends GeyserJacksonConfiguration {
|
||||
@Override
|
||||
public Path getFloodgateKeyPath() {
|
||||
return null; //floodgate isn't available for Sponge
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.sponge;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.text.AsteriskSerializer;
|
||||
import org.spongepowered.api.Platform;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.plugin.PluginContainer;
|
||||
import org.spongepowered.plugin.metadata.PluginMetadata;
|
||||
import org.spongepowered.plugin.metadata.model.PluginContributor;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
public class GeyserSpongeDumpInfo extends BootstrapDumpInfo {
|
||||
private final String platformName;
|
||||
private final String platformVersion;
|
||||
private final boolean onlineMode;
|
||||
|
||||
@AsteriskSerializer.Asterisk(isIp = true)
|
||||
private final String serverIP;
|
||||
private final int serverPort;
|
||||
private final List<PluginInfo> plugins;
|
||||
|
||||
GeyserSpongeDumpInfo() {
|
||||
PluginContainer container = Sponge.platform().container(Platform.Component.IMPLEMENTATION);
|
||||
PluginMetadata platformMeta = container.metadata();
|
||||
this.platformName = platformMeta.name().orElse("unknown");
|
||||
this.platformVersion = platformMeta.version().getQualifier();
|
||||
this.onlineMode = Sponge.server().isOnlineModeEnabled();
|
||||
Optional<InetSocketAddress> socketAddress = Sponge.server().boundAddress();
|
||||
this.serverIP = socketAddress.map(InetSocketAddress::getHostString).orElse("unknown");
|
||||
this.serverPort = socketAddress.map(InetSocketAddress::getPort).orElse(-1);
|
||||
this.plugins = new ArrayList<>();
|
||||
|
||||
for (PluginContainer plugin : Sponge.pluginManager().plugins()) {
|
||||
PluginMetadata meta = plugin.metadata();
|
||||
List<String> contributors = meta.contributors().stream().map(PluginContributor::name).collect(Collectors.toList());
|
||||
this.plugins.add(new PluginInfo(true, meta.name().orElse("unknown"), meta.version().toString(), meta.entrypoint(), contributors));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.sponge;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class GeyserSpongeLogger implements GeyserLogger {
|
||||
private final Logger logger;
|
||||
@Getter @Setter
|
||||
private boolean debug;
|
||||
|
||||
@Override
|
||||
public void severe(String message) {
|
||||
logger.error(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void severe(String message, Throwable error) {
|
||||
logger.error(message, error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message) {
|
||||
logger.error(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message, Throwable error) {
|
||||
logger.error(message, error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(String message) {
|
||||
logger.warn(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String message) {
|
||||
logger.info(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String message) {
|
||||
if (debug) {
|
||||
info(message);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.sponge;
|
||||
|
||||
import org.geysermc.geyser.GeyserMain;
|
||||
|
||||
public class GeyserSpongeMain extends GeyserMain {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new GeyserSpongeMain().displayMessage();
|
||||
}
|
||||
|
||||
public String getPluginType() {
|
||||
return "Sponge";
|
||||
}
|
||||
|
||||
public String getPluginFolder() {
|
||||
return "mods";
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.sponge;
|
||||
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
import org.geysermc.geyser.ping.GeyserPingInfo;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.spongepowered.api.MinecraftVersion;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.event.Cause;
|
||||
import org.spongepowered.api.event.EventContext;
|
||||
import org.spongepowered.api.event.SpongeEventFactory;
|
||||
import org.spongepowered.api.event.server.ClientPingServerEvent;
|
||||
import org.spongepowered.api.network.status.StatusClient;
|
||||
import org.spongepowered.api.profile.GameProfile;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Optional;
|
||||
|
||||
public class GeyserSpongePingPassthrough implements IGeyserPingPassthrough {
|
||||
|
||||
private static final Cause CAUSE = Cause.of(EventContext.empty(), Sponge.server());
|
||||
|
||||
private static Method SpongeStatusResponse_create;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Override
|
||||
public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) {
|
||||
// come on Sponge, this is in commons, why not expose it :(
|
||||
ClientPingServerEvent event;
|
||||
try {
|
||||
if (SpongeStatusResponse_create == null) {
|
||||
Class SpongeStatusResponse = Class.forName("org.spongepowered.common.network.status.SpongeStatusResponse");
|
||||
Class MinecraftServer = Class.forName("net.minecraft.server.MinecraftServer");
|
||||
SpongeStatusResponse_create = SpongeStatusResponse.getDeclaredMethod("create", MinecraftServer);
|
||||
}
|
||||
|
||||
Object response = SpongeStatusResponse_create.invoke(null, Sponge.server());
|
||||
event = SpongeEventFactory.createClientPingServerEvent(CAUSE, new GeyserStatusClient(inetSocketAddress), (ClientPingServerEvent.Response) response);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
Sponge.eventManager().post(event);
|
||||
GeyserPingInfo geyserPingInfo = new GeyserPingInfo(
|
||||
MessageTranslator.convertMessage(event.response().description()),
|
||||
new GeyserPingInfo.Players(
|
||||
event.response().players().orElseThrow(IllegalStateException::new).max(),
|
||||
event.response().players().orElseThrow(IllegalStateException::new).online()
|
||||
),
|
||||
new GeyserPingInfo.Version(
|
||||
event.response().version().name(),
|
||||
GameProtocol.getJavaProtocolVersion()) // thanks for also not exposing this sponge
|
||||
);
|
||||
event.response().players().ifPresent(players -> players.profiles().stream()
|
||||
.map(GameProfile::name)
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.forEach(geyserPingInfo.getPlayerList()::add)
|
||||
);
|
||||
|
||||
return geyserPingInfo;
|
||||
}
|
||||
|
||||
private record GeyserStatusClient(InetSocketAddress remote) implements StatusClient {
|
||||
|
||||
@Override
|
||||
public InetSocketAddress address() {
|
||||
return this.remote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MinecraftVersion version() {
|
||||
return Sponge.platform().minecraftVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<InetSocketAddress> virtualHost() {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,247 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.sponge;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.geysermc.geyser.api.util.PlatformType;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.command.Command;
|
||||
import org.geysermc.geyser.api.extension.Extension;
|
||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.platform.sponge.command.GeyserSpongeCommandManager;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.platform.sponge.command.GeyserSpongeCommandExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spongepowered.api.Server;
|
||||
import org.spongepowered.api.Sponge;
|
||||
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.RegisterCommandEvent;
|
||||
import org.spongepowered.api.event.lifecycle.StartedEngineEvent;
|
||||
import org.spongepowered.api.event.lifecycle.StoppingEngineEvent;
|
||||
import org.spongepowered.plugin.PluginContainer;
|
||||
import org.spongepowered.plugin.builtin.jvm.Plugin;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Plugin(value = "geyser")
|
||||
public class GeyserSpongePlugin implements GeyserBootstrap {
|
||||
|
||||
/**
|
||||
* True if the plugin should be in a disabled state.
|
||||
* This exists because you can't unregister or disable plugins in Sponge
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
@Inject
|
||||
private PluginContainer pluginContainer;
|
||||
|
||||
@Inject
|
||||
private Logger logger;
|
||||
|
||||
@Inject
|
||||
@ConfigDir(sharedRoot = false)
|
||||
private Path configPath;
|
||||
|
||||
// Available after construction lifecycle
|
||||
private GeyserSpongeConfiguration geyserConfig;
|
||||
private GeyserSpongeLogger geyserLogger;
|
||||
private GeyserImpl geyser;
|
||||
private GeyserSpongeCommandManager geyserCommandManager; // Commands are only registered after command registration lifecycle
|
||||
|
||||
// Available after StartedEngine lifecycle
|
||||
private IGeyserPingPassthrough geyserSpongePingPassthrough;
|
||||
|
||||
|
||||
/**
|
||||
* Only to be used for reloading
|
||||
*/
|
||||
@Override
|
||||
public void onEnable() {
|
||||
enabled = true;
|
||||
onConstruction(null);
|
||||
// new commands cannot be registered, and geyser's command manager does not need be reloaded
|
||||
onStartedEngine(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
enabled = false;
|
||||
if (geyser != null) {
|
||||
geyser.shutdown();
|
||||
geyser = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the configuration, logger, and command manager. command manager will only be filled with commands once
|
||||
* the connector is started, but it allows us to register events in sponge.
|
||||
*
|
||||
* @param event Not used.
|
||||
*/
|
||||
@Listener
|
||||
public void onConstruction(@Nullable ConstructPluginEvent event) {
|
||||
GeyserLocale.init(this);
|
||||
|
||||
File configDir = configPath.toFile();
|
||||
if (!configDir.exists()) {
|
||||
configDir.mkdirs();
|
||||
}
|
||||
|
||||
File configFile;
|
||||
try {
|
||||
configFile = FileUtils.fileOrCopiedFromResource(new File(configDir, "config.yml"), "config.yml",
|
||||
(file) -> file.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||
|
||||
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpongeConfiguration.class);
|
||||
} catch (IOException ex) {
|
||||
logger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"));
|
||||
ex.printStackTrace();
|
||||
onDisable();
|
||||
return;
|
||||
}
|
||||
|
||||
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
||||
this.geyserLogger = new GeyserSpongeLogger(logger, geyserConfig.isDebugMode());
|
||||
|
||||
this.geyser = GeyserImpl.load(PlatformType.SPONGE, this);
|
||||
|
||||
this.geyserCommandManager = new GeyserSpongeCommandManager(geyser);
|
||||
this.geyserCommandManager.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the {@link GeyserSpongeCommandManager} and register the commands
|
||||
*
|
||||
* @param event required to register the commands
|
||||
*/
|
||||
@Listener
|
||||
public void onRegisterCommands(@Nonnull RegisterCommandEvent<org.spongepowered.api.command.Command.Raw> event) {
|
||||
if (enabled) {
|
||||
event.register(this.pluginContainer, new GeyserSpongeCommandExecutor(geyser, geyserCommandManager.getCommands()), "geyser");
|
||||
|
||||
for (Map.Entry<Extension, Map<String, Command>> entry : this.geyserCommandManager.extensionCommands().entrySet()) {
|
||||
Map<String, Command> commands = entry.getValue();
|
||||
if (commands.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
event.register(this.pluginContainer, new GeyserSpongeCommandExecutor(this.geyser, commands), entry.getKey().description().id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the config properly if remote address is auto. Start connector and ping passthrough, and register subcommands of /geyser
|
||||
*
|
||||
* @param event not required
|
||||
*/
|
||||
@Listener
|
||||
public void onStartedEngine(@Nullable StartedEngineEvent<Server> event) {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
GeyserImpl.start();
|
||||
|
||||
if (geyserConfig.isLegacyPingPassthrough()) {
|
||||
this.geyserSpongePingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||
} else {
|
||||
this.geyserSpongePingPassthrough = new GeyserSpongePingPassthrough();
|
||||
}
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onEngineStopping(StoppingEngineEvent<Server> event) {
|
||||
onDisable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserSpongeConfiguration getGeyserConfig() {
|
||||
return geyserConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserSpongeLogger getGeyserLogger() {
|
||||
return geyserLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeyserCommandManager getGeyserCommandManager() {
|
||||
return geyserCommandManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGeyserPingPassthrough getGeyserPingPassthrough() {
|
||||
return geyserSpongePingPassthrough;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getConfigFolder() {
|
||||
return configPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BootstrapDumpInfo getDumpInfo() {
|
||||
return new GeyserSpongeDumpInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMinecraftServerVersion() {
|
||||
return Sponge.platform().minecraftVersion().name();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getServerBindAddress() {
|
||||
return Sponge.server().boundAddress().map(InetSocketAddress::getHostString).orElse("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getServerPort() {
|
||||
return Sponge.server().boundAddress().stream().mapToInt(InetSocketAddress::getPort).findFirst().orElse(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testFloodgatePluginPresent() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.sponge.command;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.command.Command;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.command.GeyserCommandExecutor;
|
||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spongepowered.api.command.CommandCause;
|
||||
import org.spongepowered.api.command.CommandCompletion;
|
||||
import org.spongepowered.api.command.CommandResult;
|
||||
import org.spongepowered.api.command.parameter.ArgumentReader;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class GeyserSpongeCommandExecutor extends GeyserCommandExecutor implements org.spongepowered.api.command.Command.Raw {
|
||||
|
||||
public GeyserSpongeCommandExecutor(GeyserImpl geyser, Map<String, Command> commands) {
|
||||
super(geyser, commands);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult process(CommandCause cause, ArgumentReader.Mutable arguments) {
|
||||
GeyserCommandSource commandSource = new SpongeCommandSource(cause);
|
||||
GeyserSession session = getGeyserSession(commandSource);
|
||||
|
||||
String[] args = arguments.input().split(" ");
|
||||
// This split operation results in an array of length 1, containing a zero length string, if the input string is empty
|
||||
if (args.length > 0 && !args[0].isEmpty()) {
|
||||
GeyserCommand command = getCommand(args[0]);
|
||||
if (command != null) {
|
||||
if (!cause.hasPermission(command.permission())) {
|
||||
cause.audience().sendMessage(Component.text(GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.permission_fail")).color(NamedTextColor.RED));
|
||||
return CommandResult.success();
|
||||
}
|
||||
if (command.isBedrockOnly() && session == null) {
|
||||
cause.audience().sendMessage(Component.text(GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.bedrock_only")).color(NamedTextColor.RED));
|
||||
return CommandResult.success();
|
||||
}
|
||||
command.execute(session, commandSource, args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]);
|
||||
} else {
|
||||
cause.audience().sendMessage(Component.text(GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.not_found")).color(NamedTextColor.RED));
|
||||
}
|
||||
} else {
|
||||
getCommand("help").execute(session, commandSource, new String[0]);
|
||||
}
|
||||
return CommandResult.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommandCompletion> complete(CommandCause cause, ArgumentReader.Mutable arguments) {
|
||||
if (arguments.input().split(" ").length == 1) {
|
||||
return tabComplete(new SpongeCommandSource(cause)).stream().map(CommandCompletion::of).collect(Collectors.toList());
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(CommandCause cause) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Component> shortDescription(CommandCause cause) {
|
||||
return Optional.of(Component.text("The main command for Geyser."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Component> extendedDescription(CommandCause cause) {
|
||||
return shortDescription(cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Component> help(@NotNull CommandCause cause) {
|
||||
return Optional.of(Component.text("/geyser help"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component usage(CommandCause cause) {
|
||||
return Component.text("/geyser help");
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.sponge.command;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.command.CommandCause;
|
||||
import org.spongepowered.api.command.manager.CommandMapping;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class GeyserSpongeCommandManager extends GeyserCommandManager {
|
||||
|
||||
public GeyserSpongeCommandManager(GeyserImpl geyser) {
|
||||
super(geyser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description(String command) {
|
||||
if (!Sponge.isServerAvailable()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Note: The command manager may be replaced at any point during the game lifecycle
|
||||
return Sponge.server().commandManager().commandMapping(command)
|
||||
.map(this::description)
|
||||
.map(Optional::get)
|
||||
.map(MessageTranslator::convertMessage)
|
||||
.orElse("");
|
||||
}
|
||||
|
||||
public Optional<Component> description(CommandMapping mapping) {
|
||||
return mapping.registrar().shortDescription(CommandCause.create(), mapping);
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.sponge.command;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||
import org.spongepowered.api.command.CommandCause;
|
||||
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class SpongeCommandSource implements GeyserCommandSource {
|
||||
|
||||
private final CommandCause handle;
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return handle.friendlyIdentifier().orElse(handle.identifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(@NonNull String message) {
|
||||
handle.audience().sendMessage(LegacyComponentSerializer.legacySection().deserialize(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConsole() {
|
||||
return !(handle.cause().root() instanceof ServerPlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return handle.hasPermission(permission);
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
{
|
||||
"loader": {
|
||||
"name": "java_plain",
|
||||
"version": "1.0"
|
||||
},
|
||||
"license": "MIT",
|
||||
"plugins": [
|
||||
{
|
||||
"id": "${id}",
|
||||
"name": "${name}-Sponge",
|
||||
"version": "${version}",
|
||||
"entrypoint": "org.geysermc.geyser.platform.sponge.GeyserSpongePlugin",
|
||||
"description": "${description}",
|
||||
"links": {
|
||||
"homepage": "${url}"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "${author}"
|
||||
}
|
||||
],
|
||||
"dependencies": [
|
||||
{
|
||||
"id": "spongeapi",
|
||||
"version": "8.0.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "Geyser for Sponge",
|
||||
"pack_format": 6
|
||||
}
|
||||
}
|
@ -22,8 +22,8 @@ indra {
|
||||
|
||||
tasks {
|
||||
processResources {
|
||||
// Spigot, BungeeCord, Velocity, Sponge, Fabric
|
||||
filesMatching(listOf("plugin.yml", "bungee.yml", "velocity-plugin.json", "META-INF/sponge_plugins.json", "fabric.mod.json")) {
|
||||
// Spigot, BungeeCord, Velocity, Fabric
|
||||
filesMatching(listOf("plugin.yml", "bungee.yml", "velocity-plugin.json", "fabric.mod.json")) {
|
||||
expand(
|
||||
"id" to "geyser",
|
||||
"name" to "Geyser",
|
||||
|
@ -20,7 +20,6 @@ val platforms = setOf(
|
||||
projects.fabric,
|
||||
projects.bungeecord,
|
||||
projects.spigot,
|
||||
projects.sponge,
|
||||
projects.standalone,
|
||||
projects.velocity
|
||||
).map { it.dependencyProject }
|
||||
|
@ -27,7 +27,6 @@ adapters = "1.9-SNAPSHOT"
|
||||
commodore = "2.2"
|
||||
bungeecord = "a7c6ede"
|
||||
velocity = "3.1.1"
|
||||
sponge = "8.0.0"
|
||||
fabric-minecraft = "1.20"
|
||||
fabric-loader = "0.14.21"
|
||||
fabric-api = "0.83.0+1.20"
|
||||
@ -89,7 +88,6 @@ junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "ju
|
||||
mcauthlib = { group = "com.github.GeyserMC", name = "MCAuthLib", version.ref = "mcauthlib" }
|
||||
mcprotocollib = { group = "com.github.steveice10", name = "mcprotocollib", version.ref = "mcprotocollib" }
|
||||
raknet = { group = "org.cloudburstmc.netty", name = "netty-transport-raknet", version.ref = "raknet" }
|
||||
sponge-api = { group = "org.spongepowered", name = "spongeapi", version.ref = "sponge" }
|
||||
terminalconsoleappender = { group = "net.minecrell", name = "terminalconsoleappender", version.ref = "terminalconsoleappender" }
|
||||
velocity-api = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" }
|
||||
viaversion = { group = "com.viaversion", name = "viaversion", version.ref = "viaversion" }
|
||||
|
@ -32,9 +32,6 @@ dependencyResolutionManagement {
|
||||
name = "viaversion"
|
||||
}
|
||||
|
||||
// Sponge
|
||||
maven("https://repo.spongepowered.org/repository/maven-public/")
|
||||
|
||||
maven("https://jitpack.io") {
|
||||
content { includeGroupByRegex("com\\.github\\..*") }
|
||||
}
|
||||
@ -65,7 +62,6 @@ include(":api")
|
||||
include(":bungeecord")
|
||||
include(":fabric")
|
||||
include(":spigot")
|
||||
include(":sponge")
|
||||
include(":standalone")
|
||||
include(":velocity")
|
||||
include(":common")
|
||||
@ -75,6 +71,5 @@ include(":core")
|
||||
project(":bungeecord").projectDir = file("bootstrap/bungeecord")
|
||||
project(":fabric").projectDir = file("bootstrap/fabric")
|
||||
project(":spigot").projectDir = file("bootstrap/spigot")
|
||||
project(":sponge").projectDir = file("bootstrap/sponge")
|
||||
project(":standalone").projectDir = file("bootstrap/standalone")
|
||||
project(":velocity").projectDir = file("bootstrap/velocity")
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren