Skip to content

Commit

Permalink
Add Fabric 1.21 support
Browse files Browse the repository at this point in the history
  • Loading branch information
MrMicky-FR committed Feb 15, 2025
1 parent b85ce31 commit 197f8ac
Show file tree
Hide file tree
Showing 10 changed files with 433 additions and 1 deletion.
9 changes: 8 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:

strategy:
matrix:
java-version: [ 17 ]
java-version: [ 21 ]

steps:
- name: Checkout repository
Expand Down Expand Up @@ -46,3 +46,10 @@ jobs:
name: AzLink-Legacy
path: universal-legacy/build/libs/AzLink-Legacy-*.jar
overwrite: true

- name: Upload AzLink-Fabric.jar
uses: actions/upload-artifact@v4
with:
name: AzLink-Fabric
path: fabric/build/libs/AzLink-Fabric-*.jar
overwrite: true
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public enum PlatformType {
BUNGEE("BungeeCord"),
SPONGE("Sponge"),
VELOCITY("Velocity"),
FABRIC("Fabric"),
NUKKIT("Nukkit");

private final String name;
Expand Down
59 changes: 59 additions & 0 deletions fabric/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
plugins {
id 'fabric-loom' version '1.2.7'
id 'com.github.johnrengelman.shadow' version '8.1.1'
}

java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}

ext {
minecraft_version = '1.21.1'
yarn_mappings = '1.21.1+build.3'
loader_version = '0.16.7'
fabric_version = '0.106.0+1.21.1'
}

dependencies {
implementation project(':azlink-common')
implementation 'net.kyori:adventure-api:4.12.0'
implementation 'net.kyori:adventure-text-serializer-gson:4.14.0'
implementation 'net.kyori:adventure-text-serializer-legacy:4.14.0'
minecraft "com.mojang:minecraft:${project.ext.minecraft_version}"
mappings "net.fabricmc:yarn:${project.ext.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.ext.loader_version}"
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.ext.fabric_version}"
}

loom {
runtimeOnlyLog4j = true
}

processResources {
filesMatching('**/*.json') {
expand 'version': project.version
}
}

shadowJar {
dependencies {
exclude 'net.fabricmc:.*'
include dependency('com.azuriom:.*')
include dependency('net.kyori:.*')
}

relocate 'net.kyori', 'com.azuriom.azlink.libs'
}

remapJar {
dependsOn tasks.shadowJar
mustRunAfter tasks.shadowJar
inputFile = shadowJar.archiveFile
addNestedDependencies = true
archiveFileName = "AzLink-Fabric-${project.version}-${project.ext.minecraft_version}.jar"
}

artifacts {
archives remapJar
}
152 changes: 152 additions & 0 deletions fabric/src/main/java/com/azuriom/azlink/fabric/AzLinkFabricMod.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package com.azuriom.azlink.fabric;

import com.azuriom.azlink.common.AzLinkPlatform;
import com.azuriom.azlink.common.AzLinkPlugin;
import com.azuriom.azlink.common.command.CommandSender;
import com.azuriom.azlink.common.data.WorldData;
import com.azuriom.azlink.common.logger.LoggerAdapter;
import com.azuriom.azlink.common.logger.Slf4jLoggerAdapter;
import com.azuriom.azlink.common.platform.PlatformInfo;
import com.azuriom.azlink.common.platform.PlatformType;
import com.azuriom.azlink.common.scheduler.JavaSchedulerAdapter;
import com.azuriom.azlink.common.scheduler.SchedulerAdapter;
import com.azuriom.azlink.common.tasks.TpsTask;
import com.azuriom.azlink.fabric.command.FabricCommandExecutor;
import com.azuriom.azlink.fabric.command.FabricPlayer;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import net.fabricmc.api.DedicatedServerModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.file.Path;
import java.util.Optional;
import java.util.stream.Stream;

public final class AzLinkFabricMod implements AzLinkPlatform, DedicatedServerModInitializer {

private static final Logger LOGGER = LoggerFactory.getLogger("azlink");

private final LoggerAdapter logger = new Slf4jLoggerAdapter(LOGGER);
private final TpsTask tpsTask = new TpsTask();

private final ModContainer modContainer;
private final AzLinkPlugin plugin;
private SchedulerAdapter scheduler;

public AzLinkFabricMod() {
this.modContainer = FabricLoader.getInstance()
.getModContainer("azlink")
.orElseThrow(() -> new RuntimeException("Unable to get the mod container."));
this.plugin = new AzLinkPlugin(this);
}

@Override
public void onInitializeServer() {
var command = new FabricCommandExecutor<>(this.plugin);

ServerLifecycleEvents.SERVER_STARTING.register(this::onServerStart);
ServerLifecycleEvents.SERVER_STOPPING.register(this::onServerStop);
ServerTickEvents.START_SERVER_TICK.register(s -> this.tpsTask.run());

CommandRegistrationCallback.EVENT
.register((dispatcher, registry, env) -> command.register(dispatcher));
}

public void onServerStart(MinecraftServer server) {
this.scheduler = this.initScheduler();
this.plugin.init();
}

public void onServerStop(MinecraftServer server) {
if (this.plugin != null) {
this.plugin.shutdown();
}
}

@Override
public AzLinkPlugin getPlugin() {
return this.plugin;
}

@Override
public LoggerAdapter getLoggerAdapter() {
return this.logger;
}

@Override
public SchedulerAdapter getSchedulerAdapter() {
return this.scheduler;
}

@Override
public PlatformType getPlatformType() {
return PlatformType.FABRIC;
}

@Override
public PlatformInfo getPlatformInfo() {
return FabricLoader.getInstance()
.getModContainer("fabric")
.map(ModContainer::getMetadata)
.map(m -> new PlatformInfo(m.getName(), m.getVersion().getFriendlyString()))
.orElse(new PlatformInfo("unknown", "unknown"));
}

@Override
public String getPluginVersion() {
return this.modContainer.getMetadata().getVersion().getFriendlyString();
}

@Override
public Path getDataDirectory() {
return FabricLoader.getInstance().getConfigDir().resolve("AzLink");
}

@Override
public Optional<WorldData> getWorldData() {
int loadedChunks = Streams.stream(getServer().getWorlds())
.mapToInt(w -> w.getChunkManager().getLoadedChunkCount())
.sum();
int entities = Streams.stream(getServer().getWorlds())
.mapToInt(w -> Iterables.size(w.iterateEntities()))
.sum();

return Optional.of(new WorldData(this.tpsTask.getTps(), loadedChunks, entities));
}

@Override
public Stream<CommandSender> getOnlinePlayers() {
return getServer().getPlayerManager()
.getPlayerList()
.stream()
.map(FabricPlayer::new);
}

@Override
public void dispatchConsoleCommand(String command) {
ServerCommandSource source = getServer().getCommandSource();
getServer().getCommandManager().executeWithPrefix(source, command);
}

@Override
public int getMaxPlayers() {
return getServer().getMaxPlayerCount();
}

private SchedulerAdapter initScheduler() {
return new JavaSchedulerAdapter(getServer()::executeSync);
}

@SuppressWarnings("deprecation")
private MinecraftServer getServer() {
return (MinecraftServer) FabricLoader.getInstance().getGameInstance();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.azuriom.azlink.fabric.command;

import com.azuriom.azlink.common.AzLinkPlugin;
import com.azuriom.azlink.common.command.AzLinkCommand;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.server.command.ServerCommandSource;

import java.util.concurrent.CompletableFuture;

public class FabricCommandExecutor<S extends ServerCommandSource>
extends AzLinkCommand implements Command<S>, SuggestionProvider<S> {

public FabricCommandExecutor(AzLinkPlugin plugin) {
super(plugin);
}

@Override
public int run(CommandContext<S> context) {
try {
String args = getArguments(context);
FabricCommandSource source = new FabricCommandSource(context.getSource());

this.execute(source, args.split(" ", -1));
} catch (Exception e) {
this.plugin.getLogger().error("An error occurred while executing command", e);
}

return Command.SINGLE_SUCCESS;
}

@Override
public CompletableFuture<Suggestions> getSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
try {
String args = getArguments(context);
FabricCommandSource source = new FabricCommandSource(context.getSource());

this.tabComplete(source, args.split(" ", -1)).forEach(builder::suggest);
} catch (Exception e) {
this.plugin.getLogger().error("An error occurred while getting suggestions", e);
}

return builder.buildFuture();
}

public void register(CommandDispatcher<S> dispatcher) {
LiteralArgumentBuilder<S> command = LiteralArgumentBuilder.<S>literal("azlink")
.then(RequiredArgumentBuilder
.<S, String>argument("args", StringArgumentType.greedyString())
.executes(this)
.suggests(this)
)
.executes(this);

dispatcher.register(command);
}

private String getArguments(CommandContext<S> context) {
try {
return context.getArgument("args", String.class);
} catch (IllegalArgumentException e) {
return "";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.azuriom.azlink.fabric.command;

import com.azuriom.azlink.common.command.CommandSender;
import net.minecraft.entity.Entity;
import net.minecraft.server.command.ServerCommandSource;

import java.util.UUID;

public class FabricCommandSource implements CommandSender {

private final ServerCommandSource source;

public FabricCommandSource(ServerCommandSource source) {
this.source = source;
}

@Override
public String getName() {
return this.source.getName();
}

@Override
public UUID getUuid() {
Entity entity = this.source.getEntity();

return entity != null
? entity.getUuid()
: UUID.nameUUIDFromBytes(this.source.getName().getBytes());
}

@Override
public void sendMessage(String message) {
this.source.sendMessage(TextAdapter.toText(message));
}

@Override
public boolean hasPermission(String permission) {
return this.source.hasPermissionLevel(3);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.azuriom.azlink.fabric.command;

import com.azuriom.azlink.common.command.CommandSender;
import net.minecraft.server.network.ServerPlayerEntity;

import java.util.UUID;

public class FabricPlayer implements CommandSender {

private final ServerPlayerEntity player;

public FabricPlayer(ServerPlayerEntity player) {
this.player = player;
}

@Override
public String getName() {
return this.player.getName().getString();
}

@Override
public UUID getUuid() {
return this.player.getUuid();
}

@Override
public void sendMessage(String message) {
this.player.sendMessage(TextAdapter.toText(message));
}

@Override
public boolean hasPermission(String permission) {
return this.player.hasPermissionLevel(3);
}
}
Loading

0 comments on commit 197f8ac

Please sign in to comment.