3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-12-26 00:00:41 +01:00

Merge pull request #3334 from GeyserMC/platform/fabric

Merge Fabric support
Dieser Commit ist enthalten in:
Camotoy 2022-10-17 23:23:33 -04:00 committet von GitHub
Commit 733d41a29c
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 4AEE18F83AFDEB23
28 geänderte Dateien mit 1383 neuen und 10 gelöschten Zeilen

Datei anzeigen

@ -19,6 +19,13 @@ jobs:
uses: snickerbockers/submodules-init@v4
- name: Build with Gradle
run: ./gradlew build
- name: Archive artifacts (Geyser Fabric)
uses: actions/upload-artifact@v2
if: success()
with:
name: Geyser Fabric
path: bootstrap/fabric/build/libs/Geyser-Fabric.jar
- name: Archive artifacts (Geyser Standalone)
uses: actions/upload-artifact@v2
if: success()

2
Jenkinsfile vendored
Datei anzeigen

@ -20,7 +20,7 @@ pipeline {
}
post {
success {
archiveArtifacts artifacts: 'bootstrap/**/build/libs/*.jar', excludes: 'bootstrap/**/build/libs/*-sources.jar,bootstrap/**/build/libs/*-unshaded.jar', fingerprint: true
archiveArtifacts artifacts: 'bootstrap/**/build/libs/Geyser-*.jar', fingerprint: true
}
}
}

Datei anzeigen

@ -0,0 +1,77 @@
plugins {
id("fabric-loom") version "1.0-SNAPSHOT"
id("maven-publish")
id("com.github.johnrengelman.shadow")
id("java")
}
java {
targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_17
}
dependencies {
//to change the versions see the gradle.properties file
minecraft(libs.fabric.minecraft)
mappings(libs.fabric.yarn) { artifact { classifier = "v2" } }
modImplementation(libs.fabric.loader)
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation(libs.fabric.api)
// PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs.
// You may need to force-disable transitiveness on them.
api(projects.core)
shadow(projects.core) {
exclude(group = "com.google.guava", module = "guava")
exclude(group = "com.google.code.gson", module = "gson")
exclude(group = "org.slf4j")
exclude(group = "com.nukkitx.fastutil")
exclude(group = "io.netty.incubator")
}
}
repositories {
mavenLocal()
maven("https://repo.opencollab.dev/maven-releases/")
maven("https://repo.opencollab.dev/maven-snapshots/")
maven("https://jitpack.io")
maven("https://oss.sonatype.org/content/repositories/snapshots/")
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
application {
mainClass.set("org.geysermc.geyser.platform.fabric.GeyserFabricMain")
}
tasks {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this task, sources will not be generated.
sourcesJar {
archiveClassifier.set("sources")
from(sourceSets.main.get().allSource)
}
shadowJar {
// Mirrors the example fabric project, otherwise tons of dependencies are shaded that shouldn't be
configurations = listOf(project.configurations.shadow.get())
// The remapped shadowJar is the final desired Geyser-Fabric.jar
archiveVersion.set(project.version.toString())
archiveClassifier.set("shaded")
relocate("org.objectweb.asm", "org.geysermc.relocate.asm")
relocate("org.yaml", "org.geysermc.relocate.yaml") // https://github.com/CardboardPowered/cardboard/issues/139
relocate("com.fasterxml.jackson", "org.geysermc.relocate.jackson")
relocate("net.kyori", "org.geysermc.relocate.kyori")
}
remapJar {
dependsOn(shadowJar)
inputFile.set(shadowJar.get().archiveFile)
archiveBaseName.set("Geyser-Fabric")
archiveClassifier.set("")
archiveVersion.set("")
}
}

Datei anzeigen

@ -0,0 +1,51 @@
/*
* 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.fabric;
import com.fasterxml.jackson.annotation.JsonIgnore;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import org.geysermc.geyser.FloodgateKeyLoader;
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
import java.nio.file.Path;
public class GeyserFabricConfiguration extends GeyserJacksonConfiguration {
@JsonIgnore
private Path floodgateKeyPath;
public void loadFloodgate(GeyserFabricMod geyser, ModContainer floodgate) {
Path geyserDataFolder = geyser.getConfigFolder();
Path floodgateDataFolder = floodgate != null ? FabricLoader.getInstance().getConfigDir().resolve("floodgate") : null;
floodgateKeyPath = FloodgateKeyLoader.getKeyPath(this, floodgateDataFolder, geyserDataFolder, geyser.getGeyserLogger());
}
@Override
public Path getFloodgateKeyPath() {
return floodgateKeyPath;
}
}

Datei anzeigen

@ -0,0 +1,89 @@
/*
* 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.fabric;
import net.fabricmc.api.EnvType;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.server.MinecraftServer;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.text.AsteriskSerializer;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("unused") // The way that the dump renders makes them used
public class GeyserFabricDumpInfo extends BootstrapDumpInfo {
private String platformVersion = null;
private final EnvType environmentType;
private final String serverIP;
private final int serverPort;
private final List<ModInfo> mods;
public GeyserFabricDumpInfo(MinecraftServer server) {
super();
for (ModContainer modContainer : FabricLoader.getInstance().getAllMods()) {
if (modContainer.getMetadata().getId().equals("fabricloader")) {
this.platformVersion = modContainer.getMetadata().getVersion().getFriendlyString();
break;
}
}
this.environmentType = FabricLoader.getInstance().getEnvironmentType();
if (AsteriskSerializer.showSensitive || (server.getServerIp() == null || server.getServerIp().equals("") || server.getServerIp().equals("0.0.0.0"))) {
this.serverIP = server.getServerIp();
} else {
this.serverIP = "***";
}
this.serverPort = server.getServerPort();
this.mods = new ArrayList<>();
for (ModContainer mod : FabricLoader.getInstance().getAllMods()) {
this.mods.add(new ModInfo(mod));
}
}
public String getPlatformVersion() {
return platformVersion;
}
public EnvType getEnvironmentType() {
return environmentType;
}
public String getServerIP() {
return this.serverIP;
}
public int getServerPort() {
return this.serverPort;
}
public List<ModInfo> getMods() {
return this.mods;
}
}

Datei anzeigen

@ -0,0 +1,88 @@
/*
* 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.fabric;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.geysermc.geyser.GeyserLogger;
public class GeyserFabricLogger implements GeyserLogger {
private final Logger logger = LogManager.getLogger("geyser-fabric");
private boolean debug;
public GeyserFabricLogger(boolean isDebug) {
debug = isDebug;
}
@Override
public void severe(String message) {
logger.fatal(message);
}
@Override
public void severe(String message, Throwable error) {
logger.fatal(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) {
logger.info(message);
}
}
@Override
public void setDebug(boolean debug) {
this.debug = debug;
}
@Override
public boolean isDebug() {
return debug;
}
}

Datei anzeigen

@ -0,0 +1,45 @@
/*
* 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.fabric;
import org.geysermc.geyser.GeyserMain;
public class GeyserFabricMain extends GeyserMain {
public static void main(String[] args) {
new GeyserFabricMain().displayMessage();
}
@Override
public String getPluginType() {
return "Fabric";
}
@Override
public String getPluginFolder() {
return "mods";
}
}

Datei anzeigen

@ -0,0 +1,301 @@
/*
* 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.fabric;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.ServerCommandSource;
import org.apache.logging.log4j.LogManager;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.GeyserLogger;
import org.geysermc.geyser.api.command.Command;
import org.geysermc.geyser.api.network.AuthType;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandManager;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.configuration.GeyserConfiguration;
import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
import org.geysermc.geyser.util.FileUtils;
import org.geysermc.geyser.platform.fabric.command.GeyserFabricCommandExecutor;
import org.geysermc.geyser.platform.fabric.command.GeyserFabricCommandManager;
import org.geysermc.geyser.platform.fabric.world.GeyserFabricWorldManager;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.*;
public class GeyserFabricMod implements ModInitializer, GeyserBootstrap {
private static GeyserFabricMod instance;
private boolean reloading;
private GeyserImpl connector;
private ModContainer mod;
private Path dataFolder;
private MinecraftServer server;
/**
* Commands that don't require any permission level to ran
*/
private List<String> playerCommands;
private final List<GeyserFabricCommandExecutor> commandExecutors = new ArrayList<>();
private GeyserFabricCommandManager geyserCommandManager;
private GeyserFabricConfiguration geyserConfig;
private GeyserFabricLogger geyserLogger;
private IGeyserPingPassthrough geyserPingPassthrough;
private WorldManager geyserWorldManager;
@Override
public void onInitialize() {
instance = this;
mod = FabricLoader.getInstance().getModContainer("geyser-fabric").orElseThrow();
this.onEnable();
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER) {
// Set as an event so we can get the proper IP and port if needed
ServerLifecycleEvents.SERVER_STARTED.register(this::startGeyser);
}
}
@Override
public void onEnable() {
dataFolder = FabricLoader.getInstance().getConfigDir().resolve("Geyser-Fabric");
if (!dataFolder.toFile().exists()) {
//noinspection ResultOfMethodCallIgnored
dataFolder.toFile().mkdir();
}
// Init dataFolder first as local language overrides call getConfigFolder()
GeyserLocale.init(this);
try {
File configFile = FileUtils.fileOrCopiedFromResource(dataFolder.resolve("config.yml").toFile(), "config.yml",
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserFabricConfiguration.class);
File permissionsFile = fileOrCopiedFromResource(dataFolder.resolve("permissions.yml").toFile(), "permissions.yml");
this.playerCommands = Arrays.asList(FileUtils.loadConfig(permissionsFile, GeyserFabricPermissions.class).getCommands());
} catch (IOException ex) {
LogManager.getLogger("geyser-fabric").error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
ex.printStackTrace();
return;
}
this.geyserLogger = new GeyserFabricLogger(geyserConfig.isDebugMode());
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
if (server == null) {
// Server has yet to start
// Register onDisable so players are properly kicked
ServerLifecycleEvents.SERVER_STOPPING.register((server) -> onDisable());
} else {
// Server has started and this is a reload
startGeyser(this.server);
reloading = false;
}
}
/**
* Initialize core Geyser.
* A function, as it needs to be called in different places depending on if Geyser is being reloaded or not.
*
* @param server The minecraft server.
*/
public void startGeyser(MinecraftServer server) {
this.server = server;
if (this.geyserConfig.getRemote().address().equalsIgnoreCase("auto")) {
this.geyserConfig.setAutoconfiguredRemote(true);
String ip = server.getServerIp();
int port = ((GeyserServerPortGetter) server).geyser$getServerPort();
if (ip != null && !ip.isEmpty() && !ip.equals("0.0.0.0")) {
this.geyserConfig.getRemote().setAddress(ip);
}
this.geyserConfig.getRemote().setPort(port);
}
if (geyserConfig.getBedrock().isCloneRemotePort()) {
geyserConfig.getBedrock().setPort(geyserConfig.getRemote().port());
}
Optional<ModContainer> floodgate = FabricLoader.getInstance().getModContainer("floodgate");
boolean floodgatePresent = floodgate.isPresent();
if (geyserConfig.getRemote().authType() == AuthType.FLOODGATE && !floodgatePresent) {
geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.disabling"));
return;
} else if (geyserConfig.isAutoconfiguredRemote() && floodgatePresent) {
// Floodgate installed means that the user wants Floodgate authentication
geyserLogger.debug("Auto-setting to Floodgate authentication.");
geyserConfig.getRemote().setAuthType(AuthType.FLOODGATE);
}
geyserConfig.loadFloodgate(this, floodgate.orElse(null));
this.connector = GeyserImpl.load(PlatformType.FABRIC, this);
GeyserImpl.start(); // shrug
this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(connector);
this.geyserCommandManager = new GeyserFabricCommandManager(connector);
this.geyserCommandManager.init();
this.geyserWorldManager = new GeyserFabricWorldManager(server);
// Start command building
// Set just "geyser" as the help command
GeyserFabricCommandExecutor helpExecutor = new GeyserFabricCommandExecutor(connector,
(GeyserCommand) connector.commandManager().getCommands().get("help"), !playerCommands.contains("help"));
commandExecutors.add(helpExecutor);
LiteralArgumentBuilder<ServerCommandSource> builder = net.minecraft.server.command.CommandManager.literal("geyser").executes(helpExecutor);
// Register all subcommands as valid
for (Map.Entry<String, Command> command : connector.commandManager().getCommands().entrySet()) {
GeyserFabricCommandExecutor executor = new GeyserFabricCommandExecutor(connector, (GeyserCommand) command.getValue(),
!playerCommands.contains(command.getKey()));
commandExecutors.add(executor);
builder.then(net.minecraft.server.command.CommandManager.literal(command.getKey()).executes(executor));
}
server.getCommandManager().getDispatcher().register(builder);
}
@Override
public void onDisable() {
if (connector != null) {
connector.shutdown();
connector = null;
}
if (!reloading) {
this.server = null;
}
}
@Override
public GeyserConfiguration getGeyserConfig() {
return geyserConfig;
}
@Override
public GeyserLogger getGeyserLogger() {
return geyserLogger;
}
@Override
public GeyserCommandManager getGeyserCommandManager() {
return geyserCommandManager;
}
@Override
public IGeyserPingPassthrough getGeyserPingPassthrough() {
return geyserPingPassthrough;
}
@Override
public WorldManager getWorldManager() {
return geyserWorldManager;
}
@Override
public Path getConfigFolder() {
return dataFolder;
}
@Override
public BootstrapDumpInfo getDumpInfo() {
return new GeyserFabricDumpInfo(server);
}
@Override
public String getMinecraftServerVersion() {
return this.server.getVersion();
}
@Nullable
@Override
public InputStream getResourceOrNull(String resource) {
// We need to handle this differently, because Fabric shares the classloader across multiple mods
Path path = this.mod.getPath(resource);
try {
return path.getFileSystem()
.provider()
.newInputStream(path);
} catch (IOException e) {
return null;
}
}
public void setReloading(boolean reloading) {
this.reloading = reloading;
}
private File fileOrCopiedFromResource(File file, String name) throws IOException {
if (!file.exists()) {
//noinspection ResultOfMethodCallIgnored
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
InputStream input = getResource(name);
byte[] bytes = new byte[input.available()];
//noinspection ResultOfMethodCallIgnored
input.read(bytes);
for(char c : new String(bytes).toCharArray()) {
fos.write(c);
}
fos.flush();
input.close();
fos.close();
}
return file;
}
public List<GeyserFabricCommandExecutor> getCommandExecutors() {
return commandExecutors;
}
public static GeyserFabricMod getInstance() {
return instance;
}
}

Datei anzeigen

@ -0,0 +1,50 @@
/*
* 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.fabric;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* A class outline of the permissions.yml file
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class GeyserFabricPermissions {
/**
* The minimum permission level a command source must have in order for it to run commands that are restricted
*/
@JsonIgnore
public static final int RESTRICTED_MIN_LEVEL = 2;
@JsonProperty("commands")
private String[] commands;
public String[] getCommands() {
return this.commands;
}
}

Datei anzeigen

@ -0,0 +1,48 @@
/*
* 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.fabric;
import net.minecraft.server.MinecraftServer;
/**
* Represents a getter to the server port in the dedicated server and in the integrated server.
*/
public interface GeyserServerPortGetter {
/**
* Returns the server port.
*
* <ul>
* <li>If it's a dedicated server, it will return the server port specified in the {@code server.properties} file.</li>
* <li>If it's an integrated server, it will return the LAN port if opened, else -1.</li>
* </ul>
*
* The reason is that {@link MinecraftServer#getServerPort()} doesn't return the LAN port if it's the integrated server,
* and changing the behavior of this method via a mixin should be avoided as it could have unexpected consequences.
*
* @return The server port.
*/
int geyser$getServerPort();
}

Datei anzeigen

@ -0,0 +1,66 @@
/*
* 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.fabric;
import net.fabricmc.loader.api.ModContainer;
import java.util.ArrayList;
import java.util.List;
/**
* A wrapper for Fabric mod information to be presented in a Geyser dump
*/
public class ModInfo {
private final String name;
private final String id;
private final String version;
private final List<String> authors;
public ModInfo(ModContainer mod) {
this.name = mod.getMetadata().getName();
this.id = mod.getMetadata().getId();
this.authors = new ArrayList<>();
mod.getMetadata().getAuthors().forEach((person) -> this.authors.add(person.getName()));
this.version = mod.getMetadata().getVersion().getFriendlyString();
}
public String getName() {
return this.name;
}
public String getId() {
return this.id;
}
public String getVersion() {
return this.version;
}
public List<String> getAuthors() {
return this.authors;
}
}

Datei anzeigen

@ -0,0 +1,76 @@
/*
* 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.fabric.command;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.platform.fabric.GeyserFabricMod;
import org.geysermc.geyser.text.ChatColor;
public class FabricCommandSender implements GeyserCommandSource {
private final ServerCommandSource source;
public FabricCommandSender(ServerCommandSource source) {
this.source = source;
}
@Override
public String name() {
return source.getName();
}
@Override
public void sendMessage(String message) {
if (source.getEntity() instanceof ServerPlayerEntity) {
((ServerPlayerEntity) source.getEntity()).sendMessage(Text.literal(message), false);
} else {
GeyserImpl.getInstance().getLogger().info(ChatColor.toANSI(message + ChatColor.RESET));
}
}
@Override
public boolean isConsole() {
return !(source.getEntity() instanceof ServerPlayerEntity);
}
@Override
public boolean hasPermission(String s) {
// Mostly copied from fabric's world manager since the method there takes a GeyserSession
// Workaround for our commands because fabric doesn't have native permissions
for (GeyserFabricCommandExecutor executor : GeyserFabricMod.getInstance().getCommandExecutors()) {
if (executor.getCommand().permission().equals(s)) {
return executor.canRun(source);
}
}
return false;
}
}

Datei anzeigen

@ -0,0 +1,97 @@
/*
* 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.fabric.command;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.server.command.ServerCommandSource;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandExecutor;
import org.geysermc.geyser.platform.fabric.GeyserFabricMod;
import org.geysermc.geyser.platform.fabric.GeyserFabricPermissions;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.GeyserLocale;
import java.util.Collections;
public class GeyserFabricCommandExecutor extends GeyserCommandExecutor implements Command<ServerCommandSource> {
private final GeyserCommand command;
/**
* Whether the command requires an OP permission level of 2 or greater
*/
private final boolean requiresPermission;
public GeyserFabricCommandExecutor(GeyserImpl connector, GeyserCommand command, boolean requiresPermission) {
super(connector, Collections.singletonMap(command.name(), command));
this.command = command;
this.requiresPermission = requiresPermission;
}
/**
* Determine whether or not a command source is allowed to run a given executor.
*
* @param source The command source attempting to run the command
* @return True if the command source is allowed to
*/
public boolean canRun(ServerCommandSource source) {
return !requiresPermission() || source.hasPermissionLevel(GeyserFabricPermissions.RESTRICTED_MIN_LEVEL);
}
@Override
public int run(CommandContext context) {
ServerCommandSource source = (ServerCommandSource) context.getSource();
FabricCommandSender sender = new FabricCommandSender(source);
GeyserSession session = getGeyserSession(sender);
if (!canRun(source)) {
sender.sendMessage(GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.permission_fail"));
return 0;
}
if (this.command.name().equals("reload")) {
GeyserFabricMod.getInstance().setReloading(true);
}
if (command.isBedrockOnly() && session == null) {
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", sender.locale()));
return 0;
}
command.execute(session, sender, new String[0]);
return 0;
}
public GeyserCommand getCommand() {
return command;
}
/**
* Returns whether the command requires permission level of {@link GeyserFabricPermissions#RESTRICTED_MIN_LEVEL} or higher to be ran
*/
public boolean requiresPermission() {
return requiresPermission;
}
}

Datei anzeigen

@ -0,0 +1,41 @@
/*
* 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.fabric.command;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommandManager;
public class GeyserFabricCommandManager extends GeyserCommandManager {
public GeyserFabricCommandManager(GeyserImpl connector) {
super(connector);
}
@Override
public String description(String command) {
return "";
}
}

Datei anzeigen

@ -0,0 +1,70 @@
/*
* 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.fabric.mixin.client;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.text.Text;
import net.minecraft.world.GameMode;
import org.geysermc.geyser.platform.fabric.GeyserFabricMod;
import org.geysermc.geyser.platform.fabric.GeyserServerPortGetter;
import org.geysermc.geyser.text.GeyserLocale;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Environment(EnvType.CLIENT)
@Mixin(IntegratedServer.class)
public class IntegratedServerMixin implements GeyserServerPortGetter {
@Shadow
private int lanPort;
@Shadow @Final private MinecraftClient client;
@Inject(method = "openToLan", at = @At("RETURN"))
private void onOpenToLan(GameMode gameMode, boolean cheatsAllowed, int port, CallbackInfoReturnable<Boolean> cir) {
if (cir.getReturnValueZ()) {
// If the LAN is opened, starts Geyser.
GeyserFabricMod.getInstance().startGeyser((MinecraftServer) (Object) this);
// Ensure player locale has been loaded, in case it's different from Java system language
GeyserLocale.loadGeyserLocale(this.client.options.language);
// Give indication that Geyser is loaded
this.client.player.sendMessage(Text.literal(GeyserLocale.getPlayerLocaleString("geyser.core.start",
this.client.options.language, "localhost", String.valueOf(this.lanPort))), false);
}
}
@Override
public int geyser$getServerPort() {
return this.lanPort;
}
}

Datei anzeigen

@ -0,0 +1,51 @@
/*
* 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.fabric.mixin.server;
import com.mojang.datafixers.DataFixer;
import net.minecraft.resource.ResourcePackManager;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.SaveLoader;
import net.minecraft.server.WorldGenerationProgressListenerFactory;
import net.minecraft.server.dedicated.MinecraftDedicatedServer;
import net.minecraft.util.ApiServices;
import net.minecraft.world.level.storage.LevelStorage;
import org.geysermc.geyser.platform.fabric.GeyserServerPortGetter;
import org.spongepowered.asm.mixin.Mixin;
import java.net.Proxy;
@Mixin(MinecraftDedicatedServer.class)
public abstract class MinecraftDedicatedServerMixin extends MinecraftServer implements GeyserServerPortGetter {
public MinecraftDedicatedServerMixin(Thread serverThread, LevelStorage.Session session, ResourcePackManager dataPackManager, SaveLoader saveLoader, Proxy proxy, DataFixer dataFixer, ApiServices apiServices, WorldGenerationProgressListenerFactory worldGenerationProgressListenerFactory) {
super(serverThread, session, dataPackManager, saveLoader, proxy, dataFixer, apiServices, worldGenerationProgressListenerFactory);
}
@Override
public int geyser$getServerPort() {
return this.getServerPort();
}
}

Datei anzeigen

@ -0,0 +1,140 @@
/*
* 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.fabric.world;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.LecternBlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.WritableBookItem;
import net.minecraft.item.WrittenBookItem;
import net.minecraft.nbt.NbtList;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.math.BlockPos;
import org.geysermc.geyser.level.GeyserWorldManager;
import org.geysermc.geyser.platform.fabric.GeyserFabricMod;
import org.geysermc.geyser.platform.fabric.command.GeyserFabricCommandExecutor;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.LecternInventoryTranslator;
import org.geysermc.geyser.util.BlockEntityUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class GeyserFabricWorldManager extends GeyserWorldManager {
private final MinecraftServer server;
public GeyserFabricWorldManager(MinecraftServer server) {
this.server = server;
}
@Override
public boolean shouldExpectLecternHandled() {
return true;
}
@Override
public NbtMap getLecternDataAt(GeyserSession session, int x, int y, int z, boolean isChunkLoad) {
Runnable lecternGet = () -> {
// Mostly a reimplementation of Spigot lectern support
PlayerEntity player = getPlayer(session);
if (player != null) {
BlockEntity blockEntity = player.world.getBlockEntity(new BlockPos(x, y, z));
if (!(blockEntity instanceof LecternBlockEntity lectern)) {
return;
}
if (!lectern.hasBook()) {
if (!isChunkLoad) {
BlockEntityUtils.updateBlockEntity(session, LecternInventoryTranslator.getBaseLecternTag(x, y, z, 0).build(), Vector3i.from(x, y, z));
}
return;
}
ItemStack book = lectern.getBook();
int pageCount = WrittenBookItem.getPageCount(book);
boolean hasBookPages = pageCount > 0;
NbtMapBuilder lecternTag = LecternInventoryTranslator.getBaseLecternTag(x, y, z, hasBookPages ? pageCount : 1);
lecternTag.putInt("page", lectern.getCurrentPage() / 2);
NbtMapBuilder bookTag = NbtMap.builder()
.putByte("Count", (byte) book.getCount())
.putShort("Damage", (short) 0)
.putString("Name", "minecraft:writable_book");
List<NbtMap> pages = new ArrayList<>(hasBookPages ? pageCount : 1);
if (hasBookPages && WritableBookItem.isValid(book.getNbt())) {
NbtList listTag = book.getNbt().getList("pages", 8);
for (int i = 0; i < listTag.size(); i++) {
String page = listTag.getString(i);
NbtMapBuilder pageBuilder = NbtMap.builder()
.putString("photoname", "")
.putString("text", page);
pages.add(pageBuilder.build());
}
} else {
// Empty page
NbtMapBuilder pageBuilder = NbtMap.builder()
.putString("photoname", "")
.putString("text", "");
pages.add(pageBuilder.build());
}
bookTag.putCompound("tag", NbtMap.builder().putList("pages", NbtType.COMPOUND, pages).build());
lecternTag.putCompound("book", bookTag.build());
NbtMap blockEntityTag = lecternTag.build();
BlockEntityUtils.updateBlockEntity(session, blockEntityTag, Vector3i.from(x, y, z));
}
};
if (isChunkLoad) {
// Hacky hacks to allow lectern loading to be delayed
session.scheduleInEventLoop(() -> server.execute(lecternGet), 1, TimeUnit.SECONDS);
} else {
server.execute(lecternGet);
}
return LecternInventoryTranslator.getBaseLecternTag(x, y, z, 0).build();
}
@Override
public boolean hasPermission(GeyserSession session, String permission) {
// Workaround for our commands because fabric doesn't have native permissions
for (GeyserFabricCommandExecutor executor : GeyserFabricMod.getInstance().getCommandExecutors()) {
if (executor.getCommand().permission().equals(permission)) {
return executor.canRun(getPlayer(session).getCommandSource());
}
}
return false;
}
private PlayerEntity getPlayer(GeyserSession session) {
return server.getPlayerManager().getPlayer(session.getPlayerEntity().getUuid());
}
}

Binäre Datei nicht angezeigt.

Nachher

Breite:  |  Höhe:  |  Größe: 113 KiB

Datei anzeigen

@ -0,0 +1,30 @@
{
"schemaVersion": 1,
"id": "${id}-fabric",
"version": "${version}",
"name": "${name}-Fabric",
"description": "A bridge/proxy allowing you to connect to Minecraft: Java Edition servers with Minecraft: Bedrock Edition. ",
"authors": [
"${author}"
],
"contact": {
"website": "${url}",
"repo": "https://github.com/GeyserMC/Geyser-Fabric"
},
"license": "MIT",
"icon": "assets/geyser-fabric/icon.png",
"environment": "*",
"entrypoints": {
"main": [
"org.geysermc.geyser.platform.fabric.GeyserFabricMod"
]
},
"mixins": [
"geyser-fabric.mixins.json"
],
"depends": {
"fabricloader": ">=0.14.8",
"fabric": "*",
"minecraft": ">=1.19"
}
}

Datei anzeigen

@ -0,0 +1,14 @@
{
"required": true,
"package": "org.geysermc.geyser.platform.fabric.mixin",
"compatibilityLevel": "JAVA_16",
"client": [
"client.IntegratedServerMixin"
],
"server": [
"server.MinecraftDedicatedServerMixin"
],
"injectors": {
"defaultRequire": 1
}
}

Datei anzeigen

@ -0,0 +1,13 @@
# Uncomment any commands that you wish to be run by clients
# Commented commands require an OP permission of 2 or greater
commands:
- help
- advancements
- statistics
- settings
- offhand
- tooltips
# - list
# - reload
# - version
# - dump

Datei anzeigen

@ -1,8 +1,3 @@
val paperVersion = "1.19-R0.1-SNAPSHOT"
val viaVersion = "4.0.0"
val adaptersVersion = "1.5-SNAPSHOT"
val commodoreVersion = "2.2"
dependencies {
api(projects.core)
@ -34,7 +29,7 @@ platformRelocate("me.lucko.commodore")
platformRelocate("io.netty.channel.kqueue")
// These dependencies are already present on the platform
provided("com.viaversion", "viaversion", viaVersion)
provided(libs.viaversion)
application {
mainClass.set("org.geysermc.geyser.platform.spigot.GeyserSpigotMain")

Datei anzeigen

@ -6,12 +6,17 @@ plugins {
repositories {
gradlePluginPortal()
maven("https://repo.opencollab.dev/maven-snapshots")
}
dependencies {
implementation("net.kyori", "indra-common", "2.0.6")
implementation("org.jfrog.buildinfo", "build-info-extractor-gradle", "4.26.1")
implementation("gradle.plugin.com.github.johnrengelman", "shadow", "7.1.1")
implementation("com.github.johnrengelman", "shadow", "7.1.3-SNAPSHOT")
// Within the gradle plugin classpath, there is a version conflict between loom and some other
// plugin for databind. This fixes it: minimum 2.13.2 is required by loom.
implementation("com.fasterxml.jackson.core:jackson-databind:2.13.3")
}
tasks.withType<KotlinCompile> {

Datei anzeigen

@ -9,7 +9,8 @@ dependencies {
tasks {
processResources {
filesMatching(listOf("plugin.yml", "bungee.yml", "velocity-plugin.json", "META-INF/sponge_plugins.json")) {
// Spigot, BungeeCord, Velocity, Sponge, Fabric
filesMatching(listOf("plugin.yml", "bungee.yml", "velocity-plugin.json", "META-INF/sponge_plugins.json", "fabric.mod.json")) {
expand(
"id" to "geyser",
"name" to "Geyser",

Datei anzeigen

@ -15,6 +15,7 @@ allprojects {
}
val platforms = setOf(
projects.fabric,
projects.bungeecord,
projects.spigot,
projects.sponge,

Datei anzeigen

@ -1,3 +1,9 @@
# Gradle settings
org.gradle.jvmargs=-Xmx4G
org.gradle.configureondemand=true
org.gradle.caching=true
org.gradle.parallel=true
group=org.geysermc
version=2.1.0-SNAPSHOT

Datei anzeigen

@ -62,6 +62,12 @@ jline-reader = { group = "org.jline", name = "jline-reader", version.ref = "jlin
paper-api = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" }
paper-mojangapi = { group = "io.papermc.paper", name = "paper-mojangapi", version.ref = "paper" }
# check these on https://modmuss50.me/fabric.html
fabric-minecraft = { group = "com.mojang", name = "minecraft", version = "1.19.1" }
fabric-yarn = { group = "net.fabricmc", name = "yarn", version = "1.19.1+build.1" }
fabric-loader = { group = "net.fabricmc", name = "fabric-loader", version = "0.14.8" }
fabric-api = { group = "net.fabricmc.fabric-api", name = "fabric-api", version = "0.58.5+1.19.1" }
adapters-spigot = { group = "org.geysermc.geyser.adapters", name = "spigot-all", version.ref = "adapters" }
bungeecord-proxy = { group = "com.github.SpigotMC.BungeeCord", name = "bungeecord-proxy", version.ref = "bungeecord" }
checker-qual = { group = "org.checkerframework", name = "checker-qual", version.ref = "checkerframework" }
@ -79,6 +85,7 @@ raknet = { group = "com.nukkitx.network", name = "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" }
websocket = { group = "org.java-websocket", name = "Java-WebSocket", version.ref = "websocket" }
[bundles]

Datei anzeigen

@ -1,7 +1,7 @@
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
// repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
// Floodgate, Cumulus etc.
maven("https://repo.opencollab.dev/main")
@ -47,6 +47,8 @@ dependencyResolutionManagement {
pluginManagement {
repositories {
gradlePluginPortal()
maven("https://maven.fabricmc.net/")
maven("https://repo.opencollab.dev/maven-snapshots")
}
plugins {
id("net.kyori.blossom") version "1.2.0"
@ -62,6 +64,7 @@ include(":ap")
include(":api")
include(":geyser-api")
include(":bungeecord")
include(":fabric")
include(":spigot")
include(":sponge")
include(":standalone")
@ -73,6 +76,7 @@ include(":core")
project(":api").projectDir = file("api/base")
project(":geyser-api").projectDir = file("api/geyser")
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")