Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-26 16:12:46 +01:00
Merge pull request #3334 from GeyserMC/platform/fabric
Merge Fabric support
Dieser Commit ist enthalten in:
Commit
733d41a29c
7
.github/workflows/pullrequest.yml
vendored
7
.github/workflows/pullrequest.yml
vendored
@ -19,6 +19,13 @@ jobs:
|
|||||||
uses: snickerbockers/submodules-init@v4
|
uses: snickerbockers/submodules-init@v4
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew build
|
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)
|
- name: Archive artifacts (Geyser Standalone)
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
if: success()
|
if: success()
|
||||||
|
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
@ -20,7 +20,7 @@ pipeline {
|
|||||||
}
|
}
|
||||||
post {
|
post {
|
||||||
success {
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
77
bootstrap/fabric/build.gradle.kts
Normale Datei
77
bootstrap/fabric/build.gradle.kts
Normale Datei
@ -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("")
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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";
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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 "";
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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
bootstrap/fabric/src/main/resources/assets/geyser-fabric/icon.png
Normale Datei
BIN
bootstrap/fabric/src/main/resources/assets/geyser-fabric/icon.png
Normale Datei
Binäre Datei nicht angezeigt.
Nachher Breite: | Höhe: | Größe: 113 KiB |
30
bootstrap/fabric/src/main/resources/fabric.mod.json
Normale Datei
30
bootstrap/fabric/src/main/resources/fabric.mod.json
Normale Datei
@ -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"
|
||||||
|
}
|
||||||
|
}
|
14
bootstrap/fabric/src/main/resources/geyser-fabric.mixins.json
Normale Datei
14
bootstrap/fabric/src/main/resources/geyser-fabric.mixins.json
Normale Datei
@ -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
|
||||||
|
}
|
||||||
|
}
|
13
bootstrap/fabric/src/main/resources/permissions.yml
Normale Datei
13
bootstrap/fabric/src/main/resources/permissions.yml
Normale Datei
@ -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
|
@ -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 {
|
dependencies {
|
||||||
api(projects.core)
|
api(projects.core)
|
||||||
|
|
||||||
@ -34,7 +29,7 @@ platformRelocate("me.lucko.commodore")
|
|||||||
platformRelocate("io.netty.channel.kqueue")
|
platformRelocate("io.netty.channel.kqueue")
|
||||||
|
|
||||||
// These dependencies are already present on the platform
|
// These dependencies are already present on the platform
|
||||||
provided("com.viaversion", "viaversion", viaVersion)
|
provided(libs.viaversion)
|
||||||
|
|
||||||
application {
|
application {
|
||||||
mainClass.set("org.geysermc.geyser.platform.spigot.GeyserSpigotMain")
|
mainClass.set("org.geysermc.geyser.platform.spigot.GeyserSpigotMain")
|
||||||
|
@ -6,12 +6,17 @@ plugins {
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
|
maven("https://repo.opencollab.dev/maven-snapshots")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("net.kyori", "indra-common", "2.0.6")
|
implementation("net.kyori", "indra-common", "2.0.6")
|
||||||
implementation("org.jfrog.buildinfo", "build-info-extractor-gradle", "4.26.1")
|
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> {
|
tasks.withType<KotlinCompile> {
|
||||||
|
@ -9,7 +9,8 @@ dependencies {
|
|||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
processResources {
|
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(
|
expand(
|
||||||
"id" to "geyser",
|
"id" to "geyser",
|
||||||
"name" to "Geyser",
|
"name" to "Geyser",
|
||||||
|
@ -15,6 +15,7 @@ allprojects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val platforms = setOf(
|
val platforms = setOf(
|
||||||
|
projects.fabric,
|
||||||
projects.bungeecord,
|
projects.bungeecord,
|
||||||
projects.spigot,
|
projects.spigot,
|
||||||
projects.sponge,
|
projects.sponge,
|
||||||
|
@ -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
|
group=org.geysermc
|
||||||
version=2.1.0-SNAPSHOT
|
version=2.1.0-SNAPSHOT
|
||||||
|
|
||||||
|
@ -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-api = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" }
|
||||||
paper-mojangapi = { group = "io.papermc.paper", name = "paper-mojangapi", 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" }
|
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" }
|
bungeecord-proxy = { group = "com.github.SpigotMC.BungeeCord", name = "bungeecord-proxy", version.ref = "bungeecord" }
|
||||||
checker-qual = { group = "org.checkerframework", name = "checker-qual", version.ref = "checkerframework" }
|
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" }
|
sponge-api = { group = "org.spongepowered", name = "spongeapi", version.ref = "sponge" }
|
||||||
terminalconsoleappender = { group = "net.minecrell", name = "terminalconsoleappender", version.ref = "terminalconsoleappender" }
|
terminalconsoleappender = { group = "net.minecrell", name = "terminalconsoleappender", version.ref = "terminalconsoleappender" }
|
||||||
velocity-api = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" }
|
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" }
|
websocket = { group = "org.java-websocket", name = "Java-WebSocket", version.ref = "websocket" }
|
||||||
|
|
||||||
[bundles]
|
[bundles]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
||||||
|
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
// repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
repositories {
|
repositories {
|
||||||
// Floodgate, Cumulus etc.
|
// Floodgate, Cumulus etc.
|
||||||
maven("https://repo.opencollab.dev/main")
|
maven("https://repo.opencollab.dev/main")
|
||||||
@ -47,6 +47,8 @@ dependencyResolutionManagement {
|
|||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
|
maven("https://maven.fabricmc.net/")
|
||||||
|
maven("https://repo.opencollab.dev/maven-snapshots")
|
||||||
}
|
}
|
||||||
plugins {
|
plugins {
|
||||||
id("net.kyori.blossom") version "1.2.0"
|
id("net.kyori.blossom") version "1.2.0"
|
||||||
@ -62,6 +64,7 @@ include(":ap")
|
|||||||
include(":api")
|
include(":api")
|
||||||
include(":geyser-api")
|
include(":geyser-api")
|
||||||
include(":bungeecord")
|
include(":bungeecord")
|
||||||
|
include(":fabric")
|
||||||
include(":spigot")
|
include(":spigot")
|
||||||
include(":sponge")
|
include(":sponge")
|
||||||
include(":standalone")
|
include(":standalone")
|
||||||
@ -73,6 +76,7 @@ include(":core")
|
|||||||
project(":api").projectDir = file("api/base")
|
project(":api").projectDir = file("api/base")
|
||||||
project(":geyser-api").projectDir = file("api/geyser")
|
project(":geyser-api").projectDir = file("api/geyser")
|
||||||
project(":bungeecord").projectDir = file("bootstrap/bungeecord")
|
project(":bungeecord").projectDir = file("bootstrap/bungeecord")
|
||||||
|
project(":fabric").projectDir = file("bootstrap/fabric")
|
||||||
project(":spigot").projectDir = file("bootstrap/spigot")
|
project(":spigot").projectDir = file("bootstrap/spigot")
|
||||||
project(":sponge").projectDir = file("bootstrap/sponge")
|
project(":sponge").projectDir = file("bootstrap/sponge")
|
||||||
project(":standalone").projectDir = file("bootstrap/standalone")
|
project(":standalone").projectDir = file("bootstrap/standalone")
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren