mirror of https://github.com/GeyserMC/Geyser.git
Merge remote-tracking branch 'upstream/master' into feature/cloud
# Conflicts: # bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/world/GeyserFabricWorldManager.java # bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java # bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java # bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/command/SpongeCommandSource.java # core/src/main/java/org/geysermc/geyser/level/GeyserWorldManager.java
This commit is contained in:
commit
6e4f718069
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -251,3 +251,4 @@ locales/
|
|||
/saved-refresh-tokens.json
|
||||
/custom_mappings/
|
||||
/languages/
|
||||
/custom-skulls.yml
|
|
@ -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");
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
package org.geysermc.geyser.platform.fabric.world;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo;
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
@ -147,6 +148,11 @@ public class GeyserFabricWorldManager extends GeyserWorldManager {
|
|||
BlockEntityUtils.updateBlockEntity(session, blockEntityTag, Vector3i.from(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameMode getDefaultGameMode(GeyserSession session) {
|
||||
return GameMode.byId(server.getDefaultGameType().getId());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<com.github.steveice10.opennbt.tag.builtin.CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
package org.geysermc.geyser.platform.spigot.world.manager;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import org.bukkit.Bukkit;
|
||||
|
@ -171,6 +172,11 @@ public class GeyserSpigotWorldManager extends WorldManager {
|
|||
return gameRule.getDefaultIntValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameMode getDefaultGameMode(GeyserSession session) {
|
||||
return GameMode.byId(Bukkit.getDefaultGameMode().ordinal());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) {
|
||||
|
|
|
@ -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,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,227 +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.command.CommandRegistry;
|
||||
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.util.FileUtils;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
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.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.Objects;
|
||||
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 Logger logger;
|
||||
|
||||
@Inject
|
||||
@ConfigDir(sharedRoot = false)
|
||||
private Path configPath;
|
||||
|
||||
// Available after construction lifecycle
|
||||
private GeyserSpongeConfiguration geyserConfig;
|
||||
private GeyserSpongeLogger geyserLogger;
|
||||
private GeyserImpl geyser;
|
||||
private CommandRegistry commandRegistry;
|
||||
|
||||
// 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.commandRegistry = new CommandRegistry(geyser, Objects.requireNonNull(null)); // todo: commands
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the {@link CommandRegistry} and register the commands
|
||||
*
|
||||
* @param event required to register the commands
|
||||
*/
|
||||
@Listener
|
||||
public void onRegisterCommands(@Nonnull RegisterCommandEvent<org.spongepowered.api.command.Command.Raw> event) {
|
||||
// todo: commands. sponge-cloud probably hooks into this without us needing to
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 CommandRegistry getCommandRegistry() {
|
||||
return commandRegistry;
|
||||
}
|
||||
|
||||
@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,75 +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;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@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 Optional<UUID> playerUuid() {
|
||||
if (handle.cause().root() instanceof ServerPlayer player) {
|
||||
return Optional.of(player.uniqueId());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return handle.hasPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle() {
|
||||
return handle;
|
||||
}
|
||||
}
|
|
@ -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 }
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
package org.geysermc.geyser.level;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
|
@ -160,6 +161,11 @@ public class GeyserWorldManager extends WorldManager {
|
|||
return gameRule.getDefaultIntValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameMode getDefaultGameMode(GeyserSession session) {
|
||||
return GameMode.SURVIVAL;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<@Nullable CompoundTag> getPickItemNbt(GeyserSession session, int x, int y, int z, boolean addNbtData) {
|
||||
|
|
|
@ -170,6 +170,24 @@ public abstract class WorldManager {
|
|||
session.sendCommand("gamemode " + gameMode.name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default game mode of the server
|
||||
*
|
||||
* @param session the player requesting the default game mode
|
||||
* @return the default game mode of the server, or Survival if unknown.
|
||||
*/
|
||||
public abstract GameMode getDefaultGameMode(GeyserSession session);
|
||||
|
||||
/**
|
||||
* Change the default game mode of the session's server
|
||||
*
|
||||
* @param session the player making the change
|
||||
* @param gameMode the new default game mode
|
||||
*/
|
||||
public void setDefaultGameMode(GeyserSession session, GameMode gameMode) {
|
||||
session.sendCommand("defaultgamemode " + gameMode.name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the difficulty of the Java server
|
||||
*
|
||||
|
|
|
@ -255,6 +255,11 @@ public class LoggingPacketHandler implements BedrockPacketHandler {
|
|||
return defaultHandler(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketSignal handle(RequestPermissionsPacket packet) {
|
||||
return defaultHandler(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketSignal handle(ResourcePackChunkRequestPacket packet) {
|
||||
return defaultHandler(packet);
|
||||
|
|
|
@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundDe
|
|||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundTabListPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLightUpdatePacket;
|
||||
import io.netty.channel.EventLoop;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.RequestPermissionsPacket;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.registry.loader.RegistryLoaders;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
@ -46,6 +47,7 @@ public class PacketTranslatorRegistry<T> extends AbstractMappedRegistry<Class<?
|
|||
IGNORED_PACKETS.add(ClientboundLightUpdatePacket.class); // Light is handled on Bedrock for us
|
||||
IGNORED_PACKETS.add(ClientboundTabListPacket.class); // Cant be implemented in Bedrock
|
||||
IGNORED_PACKETS.add(ClientboundDelimiterPacket.class); // Not implemented, spams logs
|
||||
IGNORED_PACKETS.add(RequestPermissionsPacket.class); // Bedrock client asks permission to switch default game mode, but we handle this ourselves
|
||||
}
|
||||
|
||||
protected PacketTranslatorRegistry() {
|
||||
|
|
|
@ -34,7 +34,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
|||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.*;
|
||||
import org.cloudburstmc.nbt.*;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582;
|
||||
import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594;
|
||||
|
@ -74,10 +73,9 @@ public final class BlockRegistryPopulator {
|
|||
|
||||
public static void populate(Stage stage) {
|
||||
switch (stage) {
|
||||
case PRE_INIT -> { nullifyBlocksNode(); }
|
||||
case PRE_INIT, POST_INIT -> { nullifyBlocksNode(); }
|
||||
case INIT_JAVA -> { registerJavaBlocks(); }
|
||||
case INIT_BEDROCK -> { registerBedrockBlocks(); }
|
||||
case POST_INIT -> { nullifyBlocksNode(); }
|
||||
default -> { throw new IllegalArgumentException("Unknown stage: " + stage); }
|
||||
}
|
||||
}
|
||||
|
@ -86,9 +84,8 @@ public final class BlockRegistryPopulator {
|
|||
* Stores the raw blocks JSON until it is no longer needed.
|
||||
*/
|
||||
private static JsonNode BLOCKS_JSON;
|
||||
private static int minCustomRuntimeID = -1;
|
||||
private static int maxCustomRuntimeID = -1;
|
||||
private static int javaBlocksSize = -1;
|
||||
private static int MIN_CUSTOM_RUNTIME_ID = -1;
|
||||
private static int JAVA_BLOCKS_SIZE = -1;
|
||||
|
||||
private static void nullifyBlocksNode() {
|
||||
BLOCKS_JSON = null;
|
||||
|
@ -224,8 +221,8 @@ public final class BlockRegistryPopulator {
|
|||
|
||||
BiFunction<String, NbtMapBuilder, String> stateMapper = blockMappers.getOrDefault(palette.getKey(), emptyMapper);
|
||||
|
||||
GeyserBedrockBlock[] javaToBedrockBlocks = new GeyserBedrockBlock[javaBlocksSize];
|
||||
GeyserBedrockBlock[] javaToVanillaBedrockBlocks = new GeyserBedrockBlock[javaBlocksSize];
|
||||
GeyserBedrockBlock[] javaToBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE];
|
||||
GeyserBedrockBlock[] javaToVanillaBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE];
|
||||
|
||||
Map<String, NbtMap> flowerPotBlocks = new Object2ObjectOpenHashMap<>();
|
||||
Map<NbtMap, BlockDefinition> itemFrames = new Object2ObjectOpenHashMap<>();
|
||||
|
@ -309,8 +306,8 @@ public final class BlockRegistryPopulator {
|
|||
Map<JavaBlockState, CustomBlockState> nonVanillaStateOverrides = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get();
|
||||
if (nonVanillaStateOverrides.size() > 0) {
|
||||
// First ensure all non vanilla runtime IDs at minimum are air in case they aren't consecutive
|
||||
Arrays.fill(javaToVanillaBedrockBlocks, minCustomRuntimeID, javaToVanillaBedrockBlocks.length, airDefinition);
|
||||
Arrays.fill(javaToBedrockBlocks, minCustomRuntimeID, javaToBedrockBlocks.length, airDefinition);
|
||||
Arrays.fill(javaToVanillaBedrockBlocks, MIN_CUSTOM_RUNTIME_ID, javaToVanillaBedrockBlocks.length, airDefinition);
|
||||
Arrays.fill(javaToBedrockBlocks, MIN_CUSTOM_RUNTIME_ID, javaToBedrockBlocks.length, airDefinition);
|
||||
|
||||
for (Map.Entry<JavaBlockState, CustomBlockState> entry : nonVanillaStateOverrides.entrySet()) {
|
||||
GeyserBedrockBlock bedrockDefinition = customBlockStateDefinitions.get(entry.getValue());
|
||||
|
@ -364,20 +361,20 @@ public final class BlockRegistryPopulator {
|
|||
throw new AssertionError("Unable to load Java block mappings", e);
|
||||
}
|
||||
|
||||
javaBlocksSize = blocksJson.size();
|
||||
JAVA_BLOCKS_SIZE = blocksJson.size();
|
||||
|
||||
if (BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().size() > 0) {
|
||||
minCustomRuntimeID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().min(Comparator.comparing(JavaBlockState::javaId)).get().javaId();
|
||||
maxCustomRuntimeID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().max(Comparator.comparing(JavaBlockState::javaId)).get().javaId();
|
||||
MIN_CUSTOM_RUNTIME_ID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().min(Comparator.comparing(JavaBlockState::javaId)).get().javaId();
|
||||
int maxCustomRuntimeID = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().keySet().stream().max(Comparator.comparing(JavaBlockState::javaId)).get().javaId();
|
||||
|
||||
if (minCustomRuntimeID < blocksJson.size()) {
|
||||
throw new RuntimeException("Non vanilla custom block state overrides runtime ID must start after the last vanilla block state (" + javaBlocksSize + ")");
|
||||
if (MIN_CUSTOM_RUNTIME_ID < blocksJson.size()) {
|
||||
throw new RuntimeException("Non vanilla custom block state overrides runtime ID must start after the last vanilla block state (" + JAVA_BLOCKS_SIZE + ")");
|
||||
}
|
||||
|
||||
javaBlocksSize = maxCustomRuntimeID + 1; // Runtime ids start at 0, so we need to add 1
|
||||
JAVA_BLOCKS_SIZE = maxCustomRuntimeID + 1; // Runtime ids start at 0, so we need to add 1
|
||||
}
|
||||
|
||||
BlockRegistries.JAVA_BLOCKS.set(new BlockMapping[javaBlocksSize]); // Set array size to number of blockstates
|
||||
BlockRegistries.JAVA_BLOCKS.set(new BlockMapping[JAVA_BLOCKS_SIZE]); // Set array size to number of blockstates
|
||||
|
||||
Deque<String> cleanIdentifiers = new ArrayDeque<>();
|
||||
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
package org.geysermc.geyser.registry.populator;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.nbt.NbtUtils;
|
||||
|
@ -124,6 +122,7 @@ public class CreativeItemRegistryPopulator {
|
|||
NbtMapBuilder builder = stateTag.toBuilder();
|
||||
builder.remove("name_hash");
|
||||
builder.remove("network_id");
|
||||
builder.remove("version");
|
||||
|
||||
blockDefinition = blockMappings.getDefinition(builder.build());
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -70,21 +70,21 @@ public class CustomBlockRegistryPopulator {
|
|||
}
|
||||
}
|
||||
|
||||
private static Set<CustomBlockData> customBlocks;
|
||||
private static Set<String> customBlockNames;
|
||||
private static Int2ObjectMap<CustomBlockState> blockStateOverrides;
|
||||
private static Map<String, CustomBlockData> customBlockItemOverrides;
|
||||
private static Map<JavaBlockState, CustomBlockState> nonVanillaBlockStateOverrides;
|
||||
private static Set<CustomBlockData> CUSTOM_BLOCKS;
|
||||
private static Set<String> CUSTOM_BLOCK_NAMES;
|
||||
private static Int2ObjectMap<CustomBlockState> BLOCK_STATE_OVERRIDES;
|
||||
private static Map<String, CustomBlockData> CUSTOM_BLOCK_ITEM_OVERRIDES;
|
||||
private static Map<JavaBlockState, CustomBlockState> NON_VANILLA_BLOCK_STATE_OVERRIDES;
|
||||
|
||||
/**
|
||||
* Initializes custom blocks defined by API
|
||||
*/
|
||||
private static void populateBedrock() {
|
||||
customBlocks = new ObjectOpenHashSet<>();
|
||||
customBlockNames = new ObjectOpenHashSet<>();
|
||||
blockStateOverrides = new Int2ObjectOpenHashMap<>();
|
||||
customBlockItemOverrides = new HashMap<>();
|
||||
nonVanillaBlockStateOverrides = new HashMap<>();
|
||||
CUSTOM_BLOCKS = new ObjectOpenHashSet<>();
|
||||
CUSTOM_BLOCK_NAMES = new ObjectOpenHashSet<>();
|
||||
BLOCK_STATE_OVERRIDES = new Int2ObjectOpenHashMap<>();
|
||||
CUSTOM_BLOCK_ITEM_OVERRIDES = new HashMap<>();
|
||||
NON_VANILLA_BLOCK_STATE_OVERRIDES = new HashMap<>();
|
||||
|
||||
GeyserImpl.getInstance().getEventBus().fire(new GeyserDefineCustomBlocksEvent() {
|
||||
@Override
|
||||
|
@ -92,13 +92,13 @@ public class CustomBlockRegistryPopulator {
|
|||
if (customBlockData.name().length() == 0) {
|
||||
throw new IllegalArgumentException("Custom block name must have at least 1 character.");
|
||||
}
|
||||
if (!customBlockNames.add(customBlockData.name())) {
|
||||
if (!CUSTOM_BLOCK_NAMES.add(customBlockData.name())) {
|
||||
throw new IllegalArgumentException("Another custom block was already registered under the name: " + customBlockData.name());
|
||||
}
|
||||
if (Character.isDigit(customBlockData.name().charAt(0))) {
|
||||
throw new IllegalArgumentException("Custom block can not start with a digit. Name: " + customBlockData.name());
|
||||
}
|
||||
customBlocks.add(customBlockData);
|
||||
CUSTOM_BLOCKS.add(customBlockData);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -107,10 +107,10 @@ public class CustomBlockRegistryPopulator {
|
|||
if (id == -1) {
|
||||
throw new IllegalArgumentException("Unknown Java block state. Identifier: " + javaIdentifier);
|
||||
}
|
||||
if (!customBlocks.contains(customBlockState.block())) {
|
||||
if (!CUSTOM_BLOCKS.contains(customBlockState.block())) {
|
||||
throw new IllegalArgumentException("Custom block is unregistered. Name: " + customBlockState.name());
|
||||
}
|
||||
CustomBlockState oldBlockState = blockStateOverrides.put(id, customBlockState);
|
||||
CustomBlockState oldBlockState = BLOCK_STATE_OVERRIDES.put(id, customBlockState);
|
||||
if (oldBlockState != null) {
|
||||
GeyserImpl.getInstance().getLogger().debug("Duplicate block state override for Java Identifier: " +
|
||||
javaIdentifier + " Old override: " + oldBlockState.name() + " New override: " + customBlockState.name());
|
||||
|
@ -119,18 +119,18 @@ public class CustomBlockRegistryPopulator {
|
|||
|
||||
@Override
|
||||
public void registerItemOverride(@NonNull String javaIdentifier, @NonNull CustomBlockData customBlockData) {
|
||||
if (!customBlocks.contains(customBlockData)) {
|
||||
if (!CUSTOM_BLOCKS.contains(customBlockData)) {
|
||||
throw new IllegalArgumentException("Custom block is unregistered. Name: " + customBlockData.name());
|
||||
}
|
||||
customBlockItemOverrides.put(javaIdentifier, customBlockData);
|
||||
CUSTOM_BLOCK_ITEM_OVERRIDES.put(javaIdentifier, customBlockData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerOverride(@NonNull JavaBlockState javaBlockState, @NonNull CustomBlockState customBlockState) {
|
||||
if (!customBlocks.contains(customBlockState.block())) {
|
||||
if (!CUSTOM_BLOCKS.contains(customBlockState.block())) {
|
||||
throw new IllegalArgumentException("Custom block is unregistered. Name: " + customBlockState.name());
|
||||
}
|
||||
nonVanillaBlockStateOverrides.put(javaBlockState, customBlockState);
|
||||
NON_VANILLA_BLOCK_STATE_OVERRIDES.put(javaBlockState, customBlockState);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -140,25 +140,25 @@ public class CustomBlockRegistryPopulator {
|
|||
*/
|
||||
private static void populateVanilla() {
|
||||
for (CustomSkull customSkull : BlockRegistries.CUSTOM_SKULLS.get().values()) {
|
||||
customBlocks.add(customSkull.getCustomBlockData());
|
||||
CUSTOM_BLOCKS.add(customSkull.getCustomBlockData());
|
||||
}
|
||||
|
||||
Map<CustomBlockData, Set<Integer>> extendedCollisionBoxes = new HashMap<>();
|
||||
Map<BoxComponent, CustomBlockData> extendedCollisionBoxSet = new HashMap<>();
|
||||
MappingsConfigReader mappingsConfigReader = new MappingsConfigReader();
|
||||
mappingsConfigReader.loadBlockMappingsFromJson((key, block) -> {
|
||||
customBlocks.add(block.data());
|
||||
CUSTOM_BLOCKS.add(block.data());
|
||||
if (block.overrideItem()) {
|
||||
customBlockItemOverrides.put(block.javaIdentifier(), block.data());
|
||||
CUSTOM_BLOCK_ITEM_OVERRIDES.put(block.javaIdentifier(), block.data());
|
||||
}
|
||||
block.states().forEach((javaIdentifier, customBlockState) -> {
|
||||
int id = BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(javaIdentifier, -1);
|
||||
blockStateOverrides.put(id, customBlockState.state());
|
||||
BLOCK_STATE_OVERRIDES.put(id, customBlockState.state());
|
||||
BoxComponent extendedCollisionBox = customBlockState.extendedCollisionBox();
|
||||
if (extendedCollisionBox != null) {
|
||||
CustomBlockData extendedCollisionBlock = extendedCollisionBoxSet.computeIfAbsent(extendedCollisionBox, box -> {
|
||||
CustomBlockData collisionBlock = createExtendedCollisionBlock(box, extendedCollisionBoxSet.size());
|
||||
customBlocks.add(collisionBlock);
|
||||
CUSTOM_BLOCKS.add(collisionBlock);
|
||||
return collisionBlock;
|
||||
});
|
||||
extendedCollisionBoxes.computeIfAbsent(extendedCollisionBlock, k -> new HashSet<>())
|
||||
|
@ -167,30 +167,40 @@ public class CustomBlockRegistryPopulator {
|
|||
});
|
||||
});
|
||||
|
||||
BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.set(blockStateOverrides);
|
||||
GeyserImpl.getInstance().getLogger().info("Registered " + blockStateOverrides.size() + " custom block overrides.");
|
||||
BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.set(BLOCK_STATE_OVERRIDES);
|
||||
if (BLOCK_STATE_OVERRIDES.size() != 0) {
|
||||
GeyserImpl.getInstance().getLogger().info("Registered " + BLOCK_STATE_OVERRIDES.size() + " custom block overrides.");
|
||||
}
|
||||
|
||||
BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.set(customBlockItemOverrides);
|
||||
GeyserImpl.getInstance().getLogger().info("Registered " + customBlockItemOverrides.size() + " custom block item overrides.");
|
||||
BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.set(CUSTOM_BLOCK_ITEM_OVERRIDES);
|
||||
if (CUSTOM_BLOCK_ITEM_OVERRIDES.size() != 0) {
|
||||
GeyserImpl.getInstance().getLogger().info("Registered " + CUSTOM_BLOCK_ITEM_OVERRIDES.size() + " custom block item overrides.");
|
||||
}
|
||||
|
||||
BlockRegistries.EXTENDED_COLLISION_BOXES.set(extendedCollisionBoxes);
|
||||
GeyserImpl.getInstance().getLogger().info("Registered " + extendedCollisionBoxes.size() + " custom block extended collision boxes.");
|
||||
if (extendedCollisionBoxes.size() != 0) {
|
||||
GeyserImpl.getInstance().getLogger().info("Registered " + extendedCollisionBoxes.size() + " custom block extended collision boxes.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all non-vanilla custom blocks defined by API
|
||||
*/
|
||||
private static void populateNonVanilla() {
|
||||
BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.set(nonVanillaBlockStateOverrides);
|
||||
GeyserImpl.getInstance().getLogger().info("Registered " + nonVanillaBlockStateOverrides.size() + " non-vanilla block overrides.");
|
||||
BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.set(NON_VANILLA_BLOCK_STATE_OVERRIDES);
|
||||
if (NON_VANILLA_BLOCK_STATE_OVERRIDES.size() != 0) {
|
||||
GeyserImpl.getInstance().getLogger().info("Registered " + NON_VANILLA_BLOCK_STATE_OVERRIDES.size() + " non-vanilla block overrides.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all bedrock custom blocks defined in previous stages
|
||||
*/
|
||||
private static void registration() {
|
||||
BlockRegistries.CUSTOM_BLOCKS.set(customBlocks.toArray(new CustomBlockData[0]));
|
||||
GeyserImpl.getInstance().getLogger().info("Registered " + customBlocks.size() + " custom blocks.");
|
||||
BlockRegistries.CUSTOM_BLOCKS.set(CUSTOM_BLOCKS.toArray(new CustomBlockData[0]));
|
||||
if (CUSTOM_BLOCKS.size() != 0) {
|
||||
GeyserImpl.getInstance().getLogger().info("Registered " + CUSTOM_BLOCKS.size() + " custom blocks.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -129,7 +129,9 @@ public class CustomSkullRegistryPopulator {
|
|||
}
|
||||
});
|
||||
|
||||
GeyserImpl.getInstance().getLogger().info("Registered " + BlockRegistries.CUSTOM_SKULLS.get().size() + " custom skulls as custom blocks.");
|
||||
if (BlockRegistries.CUSTOM_SKULLS.get().size() != 0) {
|
||||
GeyserImpl.getInstance().getLogger().info("Registered " + BlockRegistries.CUSTOM_SKULLS.get().size() + " custom skulls as custom blocks.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,12 +34,10 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
|||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import it.unimi.dsi.fastutil.objects.*;
|
||||
import org.geysermc.geyser.Constants;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.nbt.NbtType;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v589.Bedrock_v589;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v594.Bedrock_v594;
|
||||
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
|
||||
|
@ -48,6 +46,7 @@ import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
|
|||
import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
import org.geysermc.geyser.Constants;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.block.custom.CustomBlockData;
|
||||
|
@ -58,10 +57,10 @@ import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
|||
import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
|
||||
import org.geysermc.geyser.inventory.item.StoredItemMappings;
|
||||
import org.geysermc.geyser.item.GeyserCustomMappingData;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.registry.type.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
@ -356,7 +355,7 @@ public class ItemRegistryPopulator {
|
|||
|
||||
boolean valid = true;
|
||||
for (Map.Entry<String, Object> nbtEntry : requiredBlockStates.entrySet()) {
|
||||
if (states.getOrDefault(nbtEntry.getKey(), null) == null || !states.get(nbtEntry.getKey()).equals(nbtEntry.getValue())) {
|
||||
if (!Objects.equals(states.get(nbtEntry.getKey()), nbtEntry.getValue())) {
|
||||
// A required block state doesn't match - this one is not valid
|
||||
valid = false;
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 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.translator.protocol.bedrock.entity.player;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetDefaultGameTypePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetPlayerGameTypePacket;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.util.EntityUtils;
|
||||
|
||||
@Translator(packet = SetDefaultGameTypePacket.class)
|
||||
public class BedrockSetDefaultGameTypeTranslator extends PacketTranslator<SetDefaultGameTypePacket> {
|
||||
|
||||
/**
|
||||
* Sets the default game mode for the server via the Bedrock client's "world" menu (given sufficient permissions).
|
||||
*/
|
||||
@Override
|
||||
public void translate(GeyserSession session, SetDefaultGameTypePacket packet) {
|
||||
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
|
||||
session.getGeyser().getWorldManager().setDefaultGameMode(session, GameMode.byId(packet.getGamemode()));
|
||||
}
|
||||
// Stop the client from updating their own Gamemode without telling the server
|
||||
// Can occur when client Gamemode is set to "default", and default game mode is changed.
|
||||
SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket();
|
||||
playerGameTypePacket.setGamemode(EntityUtils.toBedrockGamemode(session.getGameMode()).ordinal());
|
||||
session.sendUpstreamPacket(playerGameTypePacket);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2023 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
|
||||
|
@ -23,54 +23,26 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.platform.sponge;
|
||||
package org.geysermc.geyser.translator.protocol.bedrock.entity.player;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetDifficultyPacket;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class GeyserSpongeLogger implements GeyserLogger {
|
||||
private final Logger logger;
|
||||
@Getter @Setter
|
||||
private boolean debug;
|
||||
@Translator(packet = SetDifficultyPacket.class)
|
||||
public class BedrockSetDifficultyTranslator extends PacketTranslator<SetDifficultyPacket> {
|
||||
|
||||
/**
|
||||
* Sets the Java server's difficulty via the Bedrock client's "world" menu (given sufficient permissions).
|
||||
*/
|
||||
@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);
|
||||
public void translate(GeyserSession session, SetDifficultyPacket packet) {
|
||||
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
|
||||
if (packet.getDifficulty() != session.getWorldCache().getDifficulty().ordinal()) {
|
||||
session.getGeyser().getWorldManager().setDifficulty(session, Difficulty.from(packet.getDifficulty()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,23 +25,43 @@
|
|||
|
||||
package org.geysermc.geyser.translator.protocol.bedrock.entity.player;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetPlayerGameTypePacket;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.util.EntityUtils;
|
||||
|
||||
/**
|
||||
* In vanilla Bedrock, if you have operator status, this sets the player's gamemode without confirmation from the server.
|
||||
* Since we have a custom server option to request the gamemode, we just reset the gamemode and ignore this.
|
||||
* With operator status, the Gamemode change is sent to the Java server, if it is not present, the gamemode is not changed.
|
||||
*/
|
||||
@Translator(packet = SetPlayerGameTypePacket.class)
|
||||
public class BedrockSetPlayerGameTypeTranslator extends PacketTranslator<SetPlayerGameTypePacket> {
|
||||
|
||||
/**
|
||||
* Sets client game mode for the server via the Bedrock client's "world" menu (given sufficient permissions).
|
||||
*/
|
||||
@Override
|
||||
public void translate(GeyserSession session, SetPlayerGameTypePacket packet) {
|
||||
// no
|
||||
SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket();
|
||||
playerGameTypePacket.setGamemode(session.getGameMode().ordinal());
|
||||
session.sendUpstreamPacket(playerGameTypePacket);
|
||||
// yes, if you are OP
|
||||
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
|
||||
if (packet.getGamemode() != session.getGameMode().ordinal()) {
|
||||
// Bedrock has more Gamemodes than Java, leading to cases 5 (for "default") and 6 (for "spectator") being sent
|
||||
// https://github.com/CloudburstMC/Protocol/blob/3.0/bedrock-codec/src/main/java/org/cloudburstmc/protocol/bedrock/data/GameType.java
|
||||
GameMode gameMode = switch (packet.getGamemode()) {
|
||||
case 1 -> GameMode.CREATIVE;
|
||||
case 2 -> GameMode.ADVENTURE;
|
||||
case 5 -> session.getGeyser().getWorldManager().getDefaultGameMode(session);
|
||||
case 6 -> GameMode.SPECTATOR;
|
||||
default -> GameMode.SURVIVAL;
|
||||
};
|
||||
session.getGeyser().getWorldManager().setPlayerGameMode(session, gameMode);
|
||||
}
|
||||
} else {
|
||||
SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket();
|
||||
playerGameTypePacket.setGamemode(EntityUtils.toBedrockGamemode(session.getGameMode()).ordinal());
|
||||
session.sendUpstreamPacket(playerGameTypePacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSy
|
|||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.TextPacket;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
|
@ -55,7 +56,11 @@ public class JavaSystemChatTranslator extends PacketTranslator<ClientboundSystem
|
|||
textPacket.setType(packet.isOverlay() ? TextPacket.Type.JUKEBOX_POPUP : TextPacket.Type.SYSTEM);
|
||||
|
||||
textPacket.setNeedsTranslation(false);
|
||||
textPacket.setMessage(MessageTranslator.convertMessage(packet.getContent(), session.locale()));
|
||||
if (packet.isOverlay()) {
|
||||
textPacket.setMessage(ChatColor.WHITE + MessageTranslator.convertMessage(packet.getContent(), session.locale()));
|
||||
} else {
|
||||
textPacket.setMessage(MessageTranslator.convertMessage(packet.getContent(), session.locale()));
|
||||
}
|
||||
|
||||
if (session.isSentSpawnPacket()) {
|
||||
session.sendUpstreamPacket(textPacket);
|
||||
|
|
|
@ -73,7 +73,8 @@ public class JavaOpenScreenTranslator extends PacketTranslator<ClientboundOpenSc
|
|||
if (openInventory != null) {
|
||||
// If the window type is the same, don't close.
|
||||
// In rare cases, inventories can do funny things where it keeps the same window type up but change the contents.
|
||||
if (openInventory.getContainerType() != packet.getType()) {
|
||||
// Or, inventory names can change (useful for JsonUI). In these cases, we need to close the old inventory.
|
||||
if (openInventory.getContainerType() != packet.getType() || !openInventory.getTitle().equals(name)) {
|
||||
// Sometimes the server can double-open an inventory with the same ID - don't confirm in that instance.
|
||||
InventoryUtils.closeInventory(session, openInventory.getJavaId(), openInventory.getJavaId() != packet.getContainerId());
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
package org.geysermc.geyser.translator.protocol.java.title;
|
||||
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.title.ClientboundSetActionBarTextPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.TextPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetTitlePacket;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
|
@ -44,14 +44,11 @@ public class JavaSetActionBarTextTranslator extends PacketTranslator<Clientbound
|
|||
text = MessageTranslator.convertMessage(packet.getText(), session.locale());
|
||||
}
|
||||
|
||||
// Type seems wrong, but is intentional to avoid collisions with armor/remaining air bars
|
||||
TextPacket textPacket = new TextPacket();
|
||||
textPacket.setType(TextPacket.Type.JUKEBOX_POPUP);
|
||||
textPacket.setNeedsTranslation(false);
|
||||
textPacket.setSourceName("");
|
||||
textPacket.setMessage(text);
|
||||
textPacket.setXuid("");
|
||||
textPacket.setPlatformChatId("");
|
||||
session.sendUpstreamPacket(textPacket);
|
||||
SetTitlePacket titlePacket = new SetTitlePacket();
|
||||
titlePacket.setType(SetTitlePacket.Type.ACTIONBAR);
|
||||
titlePacket.setText(text);
|
||||
titlePacket.setXuid("");
|
||||
titlePacket.setPlatformOnlineId("");
|
||||
session.sendUpstreamPacket(titlePacket);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
package org.geysermc.geyser.util;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
|
||||
import org.geysermc.cumulus.component.DropdownComponent;
|
||||
import org.geysermc.cumulus.form.CustomForm;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
|
@ -77,23 +75,6 @@ public class SettingsUtils {
|
|||
}
|
||||
}
|
||||
|
||||
boolean canModifyServer = session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server");
|
||||
if (canModifyServer) {
|
||||
builder.label("geyser.settings.title.server");
|
||||
|
||||
DropdownComponent.Builder gamemodeDropdown = DropdownComponent.builder("%createWorldScreen.gameMode.personal");
|
||||
for (GameMode gamemode : GameMode.values()) {
|
||||
gamemodeDropdown.option("selectWorld.gameMode." + gamemode.name().toLowerCase(), session.getGameMode() == gamemode);
|
||||
}
|
||||
builder.dropdown(gamemodeDropdown);
|
||||
|
||||
DropdownComponent.Builder difficultyDropdown = DropdownComponent.builder("%options.difficulty");
|
||||
for (Difficulty difficulty : Difficulty.values()) {
|
||||
difficultyDropdown.option("%options.difficulty." + difficulty.name().toLowerCase(), session.getWorldCache().getDifficulty() == difficulty);
|
||||
}
|
||||
builder.dropdown(difficultyDropdown);
|
||||
}
|
||||
|
||||
boolean showGamerules = session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.gamerules");
|
||||
if (showGamerules) {
|
||||
builder.label("geyser.settings.title.game_rules")
|
||||
|
@ -128,18 +109,6 @@ public class SettingsUtils {
|
|||
}
|
||||
}
|
||||
|
||||
if (canModifyServer) {
|
||||
GameMode gameMode = GameMode.values()[(int) response.next()];
|
||||
if (gameMode != null && gameMode != session.getGameMode()) {
|
||||
session.getGeyser().getWorldManager().setPlayerGameMode(session, gameMode);
|
||||
}
|
||||
|
||||
Difficulty difficulty = Difficulty.values()[(int) response.next()];
|
||||
if (difficulty != null && difficulty != session.getWorldCache().getDifficulty()) {
|
||||
session.getGeyser().getWorldManager().setDifficulty(session, difficulty);
|
||||
}
|
||||
}
|
||||
|
||||
if (showGamerules) {
|
||||
for (GameRule gamerule : GameRule.VALUES) {
|
||||
if (Boolean.class.equals(gamerule.getType())) {
|
||||
|
|
|
@ -28,7 +28,6 @@ cloud = "1.8.3"
|
|||
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"
|
||||
|
@ -95,7 +94,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")
|
Loading…
Reference in New Issue