Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Fabric support #23

Merged
merged 8 commits into from
Jun 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 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: [8, 11, 17]
java-version: [ 17 ]

steps:
- name: Checkout repository
Expand Down Expand Up @@ -44,3 +44,9 @@ jobs:
with:
name: AzLink-Legacy
path: universal-legacy/build/libs/AzLink-Legacy-*.jar

- name: Upload AzLink-Fabric.jar
uses: actions/upload-artifact@v3
with:
name: AzLink-Fabric
path: fabric/build/libs/AzLink-Fabric-*.jar
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ This plugin currently supports the following platforms:
* [Sponge](https://www.spongepowered.org/)
* [Velocity](https://velocitypowered.com/)
* [Nukkit](https://cloudburstmc.org/articles/)
* [FabricMC](https://fabricmc.net/)

## Setup

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
allprojects {
group 'com.azuriom'
version '1.2.1'
version '1.3.0'
}

subprojects {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public AuthMeIntegration(AzLinkBukkitPlugin plugin) {

this.plugin.getLoggerAdapter().info("AuthMe integration enabled.");

this.plugin.getServer().getScheduler().runTask(this.plugin, () -> {
this.plugin.getPlugin().getScheduler().executeSync(() -> {
try {
Field field = AuthMeApi.class.getDeclaredField("dataSource");
field.setAccessible(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public Executor asyncExecutor() {
}

@Override
public CancellableTask executeAsyncLater(Runnable runnable, long delay, TimeUnit unit) {
public CancellableTask scheduleAsyncLater(Runnable runnable, long delay, TimeUnit unit) {
ScheduledTask task = this.plugin.getProxy()
.getScheduler()
.schedule(this.plugin, runnable, delay, unit);
Expand All @@ -47,7 +47,7 @@ public CancellableTask executeAsyncLater(Runnable runnable, long delay, TimeUnit
}

@Override
public CancellableTask executeAsyncRepeating(Runnable runnable, long delay, long interval, TimeUnit unit) {
public CancellableTask scheduleAsyncRepeating(Runnable runnable, long delay, long interval, TimeUnit unit) {
ScheduledTask task = this.plugin.getProxy()
.getScheduler()
.schedule(this.plugin, runnable, delay, interval, unit);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public void init() {
long startDelay = Duration.between(LocalDateTime.now(), start).toMillis();
long repeatDelay = TimeUnit.MINUTES.toMillis(1);

getScheduler().executeAsyncRepeating(this.fetcherTask, startDelay, repeatDelay, TimeUnit.MILLISECONDS);
getScheduler().scheduleAsyncRepeating(this.fetcherTask, startDelay, repeatDelay, TimeUnit.MILLISECONDS);

if (!this.config.isValid()) {
getLogger().warn("Invalid configuration, please use '/azlink' to setup the plugin.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class AzLinkCommand {
private static final List<String> COMPLETIONS = Arrays.asList("status", "setup", "fetch", "money", "port");
private static final List<String> MONEY_ACTIONS = Arrays.asList("add", "remove", "set");

private final AzLinkPlugin plugin;
protected final AzLinkPlugin plugin;

public AzLinkCommand(AzLinkPlugin plugin) {
this.plugin = plugin;
Expand Down
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
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,16 @@ public class JavaSchedulerAdapter implements SchedulerAdapter {
private final Executor syncExecutor;
private final Executor asyncExecutor;

public JavaSchedulerAdapter(Executor syncExecutor) {
this(createScheduler(), syncExecutor);
}

public JavaSchedulerAdapter(Executor syncExecutor, Executor asyncExecutor) {
this(Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder()
.name("azlink-scheduler")
.daemon()), syncExecutor, asyncExecutor);
this(createScheduler(), syncExecutor, asyncExecutor);
}

public JavaSchedulerAdapter(ScheduledExecutorService scheduler, Executor syncExecutor) {
this(scheduler, syncExecutor, scheduler);
}

public JavaSchedulerAdapter(ScheduledExecutorService scheduler, Executor syncExecutor, Executor asyncExecutor) {
Expand All @@ -35,12 +41,12 @@ public Executor asyncExecutor() {
}

@Override
public CancellableTask executeAsyncLater(Runnable runnable, long delay, TimeUnit unit) {
public CancellableTask scheduleAsyncLater(Runnable runnable, long delay, TimeUnit unit) {
return new CancellableFuture(this.scheduler.schedule(runnable, delay, unit));
}

@Override
public CancellableTask executeAsyncRepeating(Runnable runnable, long delay, long interval, TimeUnit unit) {
public CancellableTask scheduleAsyncRepeating(Runnable runnable, long delay, long interval, TimeUnit unit) {
return new CancellableFuture(this.scheduler.scheduleAtFixedRate(runnable, delay, interval, unit));
}

Expand All @@ -51,6 +57,12 @@ public void shutdown() throws Exception {
this.scheduler.awaitTermination(5, TimeUnit.SECONDS);
}

private static ScheduledExecutorService createScheduler() {
return Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder()
.name("azlink-scheduler")
.daemon());
}

private static class CancellableFuture implements CancellableTask {

private final Future<?> future;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ default void executeAsync(Runnable runnable) {

Executor asyncExecutor();

CancellableTask executeAsyncLater(Runnable runnable, long delay, TimeUnit unit);
CancellableTask scheduleAsyncLater(Runnable runnable, long delay, TimeUnit unit);

CancellableTask executeAsyncRepeating(Runnable runnable, long delay, long interval, TimeUnit unit);
CancellableTask scheduleAsyncRepeating(Runnable runnable, long delay, long interval, TimeUnit unit);

default void shutdown() throws Exception {

Expand Down
57 changes: 57 additions & 0 deletions fabric/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
plugins {
id 'fabric-loom' version '1.1-SNAPSHOT'
id 'com.github.johnrengelman.shadow' version '8.1.1'
}

sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17

ext {
minecraft_version = '1.20'
yarn_mappings = '1.20+build.1'
loader_version = '0.14.21'
fabric_version = '0.83.0+1.20'
}

repositories {
maven { url 'https://repo.spongepowered.org/repository/maven-public/' }
}

dependencies {
implementation project(':azlink-common')
implementation 'net.kyori:adventure-api:4.12.0'
implementation 'net.kyori:adventure-text-serializer-gson:4.12.0'
implementation 'net.kyori:adventure-text-serializer-legacy:4.12.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}"
}

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();
}
}
Loading