Downgrade gradle to 8.14.3, remove fabric support, update README.md
This commit is contained in:
1 parent
49742a9ddc
commit
3ae1e32813
96 files changed
+126
-4241
No files matched your search
@@ -1,5 +1,5 @@
|
||||
<div align="center">
|
||||
<h1>GrimAC</h1>
|
||||
<h1>GrimAC (LightningGrim Fork)</h1>
|
||||
|
||||
<div>
|
||||
<a href="https://github.com/GrimAnticheat/Grim/actions/workflows/gradle-publish.yml">
|
||||
@@ -23,15 +23,15 @@ It currently supports minecraft versions 1.8–1.21. Geyser players are fully ex
|
||||
This project is considered feature-complete for the 2.0 (open-source) branch. If you would like a bug fix or enhancement and cannot sponsor the work, pull requests are welcome.
|
||||
A premium version is planned, which will offer additional subscription-based paid checks, such as heuristics.
|
||||
|
||||
## Downloads
|
||||
## Changes over Grim:
|
||||
|
||||
- Latest updates:
|
||||
- **[Modrinth](https://modrinth.com/plugin/grimac)** *(recommended)*
|
||||
- GitHub
|
||||
artifacts: [Bukkit](https://nightly.link/GrimAnticheat/Grim/workflows/gradle-publish/2.0/grimac-bukkit.zip), [Fabric](https://nightly.link/GrimAnticheat/Grim/workflows/gradle-publish/2.0/grimac-fabric.zip) *(bleeding edge)*
|
||||
- Major releases only:
|
||||
- ~~[Hangar](https://hangar.papermc.io/GrimAnticheat/GrimAnticheat)~~
|
||||
- ~~[SpigotMC](https://www.spigotmc.org/resources/grim-anticheat.99923/)~~
|
||||
- WallHit - checks for hitting through walls
|
||||
- EntityPierce - checks for hitting through other entities
|
||||
- Bukkit Event Piston Optimizations
|
||||
- Optimized Hitbox/Collision Boxes
|
||||
- Optimized Reach calculations
|
||||
- Checks for PacketOrder (patches lots of noslow, autoblocks, etc...)
|
||||
- Checks for Inventory interactions (prevents using crafting slots as extra storage, moving while having inventory open, etc...)
|
||||
|
||||
## Resources
|
||||
|
||||
@@ -40,17 +40,11 @@ A premium version is planned, which will offer additional subscription-based pai
|
||||
- For community support and project discussion join our [Discord](https://discord.grim.ac).
|
||||
|
||||
|
||||
## Pull Requests
|
||||
|
||||
See [Contributing](CONTRIBUTING.md) for more information about contributing and what our guidelines
|
||||
are.
|
||||
|
||||
|
||||
## Requirements & Installation
|
||||
|
||||
- Java 17 or higher. *For more details
|
||||
see [Updating-to-Java-17](https://github.com/GrimAnticheat/Grim/wiki/Updating-to-Java-17).*
|
||||
- A Spigot, Paper, Folia, or Fabric server environment. *For more details
|
||||
- A Spigot, Paper, or Folia, server environment. *For more details
|
||||
see [Supported-environments](https://github.com/GrimAnticheat/Grim/wiki/Supported-environments).*
|
||||
- If you use Geyser, place Floodgate on the backend server so grim can exempt bedrock players. Grim
|
||||
cannot access the Floodgate API if it is on the proxy.
|
||||
@@ -67,7 +61,7 @@ information.
|
||||
|
||||
1. `git clone https://github.com/Axionize/LightningGrim`
|
||||
2. `cd LightningGrim`
|
||||
3. `./gradlew build`
|
||||
3. `./gradlew build clean eclipse --warning-mode all`
|
||||
4. The final jars will compile into the `<platform>/build/libs` folders
|
||||
|
||||
## Grim Supremacy
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
* Logic in: buildSrc/versioning/BuildConfig.kt & VersionUtil.kt
|
||||
*/
|
||||
|
||||
plugins {
|
||||
base
|
||||
}
|
||||
|
||||
import org.gradle.api.tasks.Copy
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
import versioning.BuildConfig
|
||||
import versioning.VersionUtil
|
||||
|
||||
@@ -47,3 +53,15 @@ subprojects {
|
||||
options.isIncremental = true
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register<Copy>("copyBukkitJarToRoot") {
|
||||
dependsOn(":bukkit:shadowJar")
|
||||
from(project(":bukkit").layout.buildDirectory.dir("libs"))
|
||||
include("LightningGrim-bukkit-*.jar")
|
||||
into(layout.buildDirectory.dir("libs"))
|
||||
}
|
||||
|
||||
tasks.named("build") {
|
||||
dependsOn("copyBukkitJarToRoot")
|
||||
}
|
||||
|
||||
@@ -66,7 +66,6 @@ tasks {
|
||||
listOf(
|
||||
"bungee.yml",
|
||||
"velocity-plugin.json",
|
||||
"fabric.mod.json",
|
||||
"grimac.properties"
|
||||
)
|
||||
) {
|
||||
|
||||
@@ -76,7 +76,6 @@ repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.paper.api)
|
||||
compileOnly(libs.placeholderapi)
|
||||
@@ -185,12 +184,11 @@ bukkit {
|
||||
"Shows lists of specific data"
|
||||
default = Permission.Default.FALSE
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
publishing.publications.create<MavenPublication>("maven") {
|
||||
artifact(tasks["shadowJar"])
|
||||
artifact(tasks.named("shadowJar"))
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import versioning.BuildConfig
|
||||
|
||||
plugins {
|
||||
eclipse
|
||||
`maven-publish`
|
||||
grim.`base-conventions`
|
||||
}
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
import versioning.BuildConfig
|
||||
|
||||
val minecraft_version: String by project
|
||||
val yarn_mappings: String by project
|
||||
val fabric_version: String by project
|
||||
|
||||
plugins {
|
||||
`maven-publish`
|
||||
alias(libs.plugins.fabric.loom)
|
||||
grim.`base-conventions`
|
||||
grim.`jij-conventions`
|
||||
}
|
||||
|
||||
dependencies {
|
||||
minecraft("com.mojang:minecraft:$minecraft_version")
|
||||
mappings(loom.officialMojangMappings())
|
||||
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", fabric_version))
|
||||
|
||||
modImplementation("me.lucko:fabric-permissions-api:0.3.1")
|
||||
|
||||
modImplementation(libs.cloud.fabric)
|
||||
modImplementation(libs.fabric.loader)
|
||||
if (BuildConfig.shadePE) {
|
||||
modImplementation(libs.packetevents.fabric)
|
||||
} else {
|
||||
compileOnly(libs.packetevents.fabric)
|
||||
}
|
||||
compileOnly("org.slf4j:slf4j-api:2.0.17")
|
||||
compileOnly("org.apache.logging.log4j:log4j-api:2.24.3")
|
||||
|
||||
modApi(libs.packetevents.fabric)
|
||||
}
|
||||
|
||||
// The configurations below will only apply to :fabric and its submodules, not its siblings or the root project
|
||||
allprojects {
|
||||
apply(plugin = "fabric-loom")
|
||||
apply(plugin = "grim.base-conventions")
|
||||
apply(plugin = "maven-publish")
|
||||
|
||||
repositories {
|
||||
if (BuildConfig.mavenLocalOverride) {
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://maven.fabricmc.net/")
|
||||
}
|
||||
filter {
|
||||
includeGroup("net.fabricmc")
|
||||
includeGroup("net.fabricmc.fabric-api")
|
||||
}
|
||||
}
|
||||
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://repo.grim.ac/snapshots") // Grim API & PacketEvents
|
||||
}
|
||||
filter {
|
||||
includeGroup("ac.grim.grimac")
|
||||
includeGroup("com.github.retrooper")
|
||||
}
|
||||
}
|
||||
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://jitpack.io") { // Conditional Mixin
|
||||
mavenContent { releasesOnly() }
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeGroup("com.github.Fallen-Breath.conditional-mixin")
|
||||
}
|
||||
}
|
||||
|
||||
exclusiveContent {
|
||||
// The repository URL is determined by the project's name
|
||||
if (project.name == "mc1161") {
|
||||
// For the 1.16.1 subproject, the old snapshot is on the Grim repo
|
||||
forRepository {
|
||||
maven("https://repo.grim.ac/snapshots")
|
||||
}
|
||||
} else {
|
||||
// For all other subprojects, the releases are on Maven Central
|
||||
forRepository {
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
// This filter applies to whichever repository was chosen above
|
||||
filter {
|
||||
includeGroup("me.lucko")
|
||||
}
|
||||
}
|
||||
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://repo.viaversion.com") { // ViaVersion
|
||||
mavenContent { releasesOnly() }
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeGroup("com.viaversion")
|
||||
}
|
||||
}
|
||||
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://nexus.scarsz.me/content/repositories/releases") { // Configuralize
|
||||
mavenContent { releasesOnly() }
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeGroup("github.scarsz")
|
||||
}
|
||||
}
|
||||
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://repo.opencollab.dev/maven-releases/") { // Cumulus (for Floodgate)
|
||||
mavenContent { releasesOnly() }
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeGroup("org.geysermc.api")
|
||||
}
|
||||
}
|
||||
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven("https://repo.opencollab.dev/maven-snapshots/") { // Floodgate
|
||||
mavenContent { snapshotsOnly() }
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeGroup("org.geysermc.floodgate")
|
||||
includeGroup("org.geysermc.cumulus")
|
||||
includeModule("org.geysermc", "common")
|
||||
includeModule("org.geysermc", "geyser-parent")
|
||||
}
|
||||
}
|
||||
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
loom {
|
||||
accessWidenerPath = file("src/main/resources/grimac.accesswidener")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// I hate this syntax, is there an alternative to make modCompileOnly(libs.package.name) work?
|
||||
val libsx = rootProject.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||
// Use the libs extension from the root project
|
||||
modImplementation(libsx.findLibrary("cloud-fabric").get()) {
|
||||
exclude(group = "net.fabricmc.fabric-api")
|
||||
}
|
||||
modImplementation(libsx.findLibrary("fabric-loader").get())
|
||||
|
||||
implementation(project(":common"))
|
||||
}
|
||||
|
||||
publishing.publications.create<MavenPublication>("maven") {
|
||||
artifact(tasks["remapJar"])
|
||||
}
|
||||
|
||||
tasks {
|
||||
remapJar {
|
||||
archiveBaseName = "${rootProject.name}-fabric${if (project.name != "fabric") "-${project.name}" else ""}"
|
||||
archiveVersion = rootProject.version as String
|
||||
}
|
||||
|
||||
remapSourcesJar {
|
||||
archiveVersion = rootProject.version as String
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subprojects {
|
||||
dependencies {
|
||||
// configuration = "namedElements" required when depending on another loom project
|
||||
implementation(project(":fabric", configuration = "namedElements"))
|
||||
}
|
||||
}
|
||||
|
||||
subprojects.forEach {
|
||||
tasks.named("remapJar").configure {
|
||||
dependsOn("${it.path}:remapJar")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.remapJar.configure {
|
||||
subprojects.forEach { subproject ->
|
||||
subproject.tasks.matching { it.name == "remapJar" }.configureEach {
|
||||
nestedJars.from(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
# Done to increase the memory available to gradle.
|
||||
org.gradle.jvmargs=-Xmx2G
|
||||
org.gradle.parallel=true
|
||||
# Fabric Properties
|
||||
# check these on https://fabricmc.net/develop
|
||||
minecraft_version=1.16.1
|
||||
yarn_mappings=1.16.1+build.21
|
||||
loader_version=0.16.13
|
||||
|
||||
# Fabric API
|
||||
fabric_version=0.42.0+1.16
|
||||
@@ -1,11 +0,0 @@
|
||||
dependencies {
|
||||
minecraft("com.mojang:minecraft:1.16.1")
|
||||
mappings(loom.officialMojangMappings())
|
||||
|
||||
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", "0.42.0+1.16"))
|
||||
modImplementation("me.lucko:fabric-permissions-api:0.1-SNAPSHOT")
|
||||
}
|
||||
|
||||
loom {
|
||||
accessWidenerPath = file("src/main/resources/grimac.accesswidener")
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1161;
|
||||
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.platform.fabric.AbstractFabricPlatformServer;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
|
||||
public class Fabric1140PlatformServer extends AbstractFabricPlatformServer {
|
||||
|
||||
@Override
|
||||
public void dispatchCommand(Sender sender, String command) {
|
||||
CommandSourceStack commandSource = GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().reverse(sender);
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER.getCommands().performCommand(commandSource, command);
|
||||
}
|
||||
|
||||
// TODO (Cross-platform) implement proper bukkit equivalent for getting TPS over time
|
||||
@Override
|
||||
public double getTPS() {
|
||||
return Math.min(1000.0 / GrimACFabricLoaderPlugin.FABRIC_SERVER.getAverageTickTime(), 20.0);
|
||||
}
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1161;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.AbstractFabricPlatformServer;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.command.FabricPlayerSelectorParser;
|
||||
import ac.grim.grimac.platform.fabric.manager.FabricParserDescriptorFactory;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.command.Fabric1161PlayerSelectorAdapter;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.entity.Fabric1161GrimEntity;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.player.Fabric1161PlatformInventory;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.player.Fabric1161PlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.util.convert.Fabric1140ConversionUtil;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.util.convert.Fabric1161MessageUtil;
|
||||
import ac.grim.grimac.platform.fabric.player.FabricPlatformPlayerFactory;
|
||||
import ac.grim.grimac.platform.fabric.utils.convert.IFabricConversionUtil;
|
||||
import ac.grim.grimac.platform.fabric.utils.message.IFabricMessageUtil;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
|
||||
public class GrimACFabric1161LoaderPlugin extends GrimACFabricLoaderPlugin {
|
||||
|
||||
public GrimACFabric1161LoaderPlugin() {
|
||||
this(
|
||||
new FabricPlatformPlayerFactory(
|
||||
Fabric1161PlatformPlayer::new,
|
||||
Fabric1161GrimEntity::new,
|
||||
Fabric1161PlatformInventory::new
|
||||
),
|
||||
new Fabric1140PlatformServer(),
|
||||
new Fabric1161MessageUtil(),
|
||||
new Fabric1140ConversionUtil()
|
||||
);
|
||||
}
|
||||
|
||||
protected GrimACFabric1161LoaderPlugin(
|
||||
FabricPlatformPlayerFactory playerFactory,
|
||||
AbstractFabricPlatformServer platformServer,
|
||||
IFabricMessageUtil fabricMessageUtil,
|
||||
IFabricConversionUtil fabricConversionUtil
|
||||
) {
|
||||
super(
|
||||
new FabricParserDescriptorFactory(new FabricPlayerSelectorParser<>(Fabric1161PlayerSelectorAdapter::new)),
|
||||
playerFactory,
|
||||
platformServer,
|
||||
fabricMessageUtil,
|
||||
fabricConversionUtil
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerVersion getNativeVersion() {
|
||||
return ServerVersion.V_1_16_1;
|
||||
}
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1161.command;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.platform.api.command.PlayerSelector;
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.platform.fabric.sender.FabricSenderFactory;
|
||||
import org.incendo.cloud.minecraft.modded.data.SinglePlayerSelector;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class Fabric1161PlayerSelectorAdapter implements PlayerSelector {
|
||||
protected final SinglePlayerSelector fabricSelector;
|
||||
|
||||
public Fabric1161PlayerSelectorAdapter(SinglePlayerSelector fabricSelector) {
|
||||
this.fabricSelector = fabricSelector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getSinglePlayer() {
|
||||
return ((FabricSenderFactory) GrimAPI.INSTANCE.getSenderFactory()).map(fabricSelector.single().createCommandSourceStack());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Sender> getPlayers() {
|
||||
return Collections.singletonList(getSinglePlayer()); // Assuming your ServerPlayer can be cast to Player
|
||||
}
|
||||
|
||||
@Override
|
||||
public String inputString() {
|
||||
return fabricSelector.inputString();
|
||||
}
|
||||
}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1161.entity;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.entity.AbstractFabricGrimEntity;
|
||||
import ac.grim.grimac.platform.fabric.utils.thread.FabricFutureUtil;
|
||||
import ac.grim.grimac.utils.math.Location;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
|
||||
public class Fabric1161GrimEntity extends AbstractFabricGrimEntity {
|
||||
|
||||
public Fabric1161GrimEntity(Entity entity) {
|
||||
super(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> teleportAsync(Location location) {
|
||||
return FabricFutureUtil.supplySync(() -> {
|
||||
if (entity.getCommandSenderWorld() instanceof ServerLevel) {
|
||||
entity.teleportToWithTicket(
|
||||
location.getX(),
|
||||
location.getY(),
|
||||
location.getZ()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDead() {
|
||||
return entity instanceof LivingEntity living ? living.isDeadOrDying() : entity.removed;
|
||||
}
|
||||
}
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1161.player;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.player.AbstractFabricPlatformInventory;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.InventoryMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class Fabric1161PlatformInventory extends AbstractFabricPlatformInventory {
|
||||
public Fabric1161PlatformInventory(ServerPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
// TODO
|
||||
// I don't understand why we do this on Bukkit, so I'm replicating the behaviour without high-level understanding of purpose
|
||||
// This method is only used to check if the inventory matches one of the following
|
||||
// private static final Set<String> SUPPORTED_INVENTORIES = new HashSet<>(
|
||||
// Arrays.asList("CHEST", "DISPENSER", "DROPPER", "PLAYER", "ENDER_CHEST", "SHULKER_BOX", "BARREL", "CRAFTING", "CREATIVE")
|
||||
// );
|
||||
// And is slated to be replaced by packet based behaviour, this should do for now
|
||||
@Override
|
||||
public String getOpenInventoryKey() {
|
||||
AbstractContainerMenu handler = fabricPlayer.containerMenu;
|
||||
MenuType<?> type = getSafeType(handler);
|
||||
|
||||
// Handle null types (player crafting and creative)
|
||||
if (type == null) {
|
||||
// 4x4 CRAFTING -> CRAFTING
|
||||
if (handler instanceof InventoryMenu) {
|
||||
return "CRAFTING";
|
||||
// Not sure if creative mode check here is correct
|
||||
} else if (this.isPlayerCreative()) {
|
||||
return "CREATIVE";
|
||||
}
|
||||
}
|
||||
|
||||
// should we handle crafters here also??
|
||||
// CRAFTING -> CRAFTING
|
||||
if (type == MenuType.CRAFTING) {
|
||||
return "CRAFTING";
|
||||
// PLAYER -> PLAYER
|
||||
} else if (type == MenuType.GENERIC_9x4) {
|
||||
return "PLAYER";
|
||||
// CHEST, ENDER_CHEST, or BARREL -> CHEST
|
||||
} else if (type == MenuType.GENERIC_9x3) {
|
||||
return "CHEST";
|
||||
// DISPENSER, DROPPER -> DISPENSER
|
||||
} else if (type == MenuType.GENERIC_3x3) {
|
||||
return "DISPENSER";
|
||||
} else {
|
||||
// Registry handles:
|
||||
// SHULKER_BOX -> SHULKER_BOX
|
||||
// CRAFTIING -> CRAFTING
|
||||
|
||||
ResourceLocation registryKey = this.getScreenID(type);
|
||||
if (registryKey != null) {
|
||||
return registryKey.getPath();
|
||||
}
|
||||
|
||||
return handler.getClass().getSimpleName(); // Default fallback
|
||||
}
|
||||
}
|
||||
|
||||
protected ResourceLocation getScreenID(MenuType<?> type) {
|
||||
return Registry.MENU.getKey(type);
|
||||
}
|
||||
|
||||
protected boolean isPlayerCreative() {
|
||||
return fabricPlayer.isCreative();
|
||||
}
|
||||
|
||||
protected @Nullable MenuType<?> getSafeType(AbstractContainerMenu handler) {
|
||||
try {
|
||||
return handler.getType();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1161.player;
|
||||
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.player.AbstractFabricPlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.utils.thread.FabricFutureUtil;
|
||||
import ac.grim.grimac.utils.math.Location;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
||||
public class Fabric1161PlatformPlayer extends AbstractFabricPlatformPlayer {
|
||||
public Fabric1161PlatformPlayer(ServerPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getSender() {
|
||||
return GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().map(entity.createCommandSourceStack());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> teleportAsync(Location location) {
|
||||
return FabricFutureUtil.supplySync(() -> {
|
||||
fabricPlayer.teleportTo(
|
||||
(ServerLevel) location.getWorld(),
|
||||
location.getX(),
|
||||
location.getY(),
|
||||
location.getZ(),
|
||||
location.getYaw(),
|
||||
location.getPitch()
|
||||
);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1161.util.convert;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.utils.convert.IFabricConversionUtil;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import io.github.retrooper.packetevents.adventure.serializer.gson.GsonComponentSerializer;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.PooledByteBufAllocator;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
public class Fabric1140ConversionUtil implements IFabricConversionUtil {
|
||||
public ItemStack fromFabricItemStack(net.minecraft.world.item.ItemStack fabricStack) {
|
||||
if (fabricStack.isEmpty()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
ByteBuf buffer = PooledByteBufAllocator.DEFAULT.buffer();
|
||||
try {
|
||||
FriendlyByteBuf packetByteBuf = new FriendlyByteBuf(buffer);
|
||||
packetByteBuf.writeItem(fabricStack);
|
||||
PacketWrapper<?> wrapper = PacketWrapper.createUniversalPacketWrapper(buffer);
|
||||
return wrapper.readItemStack();
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("Failed to encode ItemStack: {}" + fabricStack, e);
|
||||
return ItemStack.EMPTY;
|
||||
} finally {
|
||||
ByteBufHelper.release(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public net.minecraft.network.chat.Component toNativeText(Component component) {
|
||||
return net.minecraft.network.chat.Component.Serializer.fromJson(GsonComponentSerializer.gson().serializeToTree(component));
|
||||
}
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1161.util.convert;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.utils.message.IFabricMessageUtil;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
|
||||
public class Fabric1161MessageUtil implements IFabricMessageUtil {
|
||||
@Override
|
||||
public Component textLiteral(String message) {
|
||||
return new TextComponent(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(CommandSourceStack target, Component message, boolean overlay) {
|
||||
target.sendSuccess(message, overlay);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "grimac-mc1161",
|
||||
"version": "${version}",
|
||||
"name": "GrimAC for 1.16.1",
|
||||
"description": "Libre simulation anticheat designed for 1.21 with 1.8-1.21 support, powered by PacketEvents 2.0.",
|
||||
"authors": [
|
||||
"GrimAC"
|
||||
],
|
||||
"license": "GPLv3",
|
||||
"environment": "server",
|
||||
"entrypoints": {
|
||||
"grimMainLoad": [
|
||||
"ac.grim.grimac.platform.fabric.mc1161.GrimACFabric1161LoaderPlugin"
|
||||
]
|
||||
},
|
||||
"accessWidener": "grimac.accesswidener",
|
||||
"depends": {
|
||||
"fabricloader": "\u003e\u003d0.16",
|
||||
"minecraft": ">=1.16.1",
|
||||
"fabric-resource-loader-v0": "*"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
accessWidener v2 named
|
||||
accessible field net/minecraft/server/level/ServerLevel serverLevelData Lnet/minecraft/world/level/storage/ServerLevelData;
|
||||
accessible field net/minecraft/commands/CommandSourceStack source Lnet/minecraft/commands/CommandSource;
|
||||
@@ -1,8 +0,0 @@
|
||||
dependencies {
|
||||
minecraft("com.mojang:minecraft:1.17.1")
|
||||
mappings(loom.officialMojangMappings())
|
||||
compileOnly(project(":fabric:mc1161", configuration = "namedElements"))
|
||||
|
||||
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", "0.46.1+1.17"))
|
||||
modImplementation("me.lucko:fabric-permissions-api:0.3.1")
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1171;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.Fabric1140PlatformServer;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class Fabric1171PlatformServer extends Fabric1140PlatformServer {
|
||||
@Override
|
||||
public @Nullable GameProfile getProfileByName(String name) {
|
||||
Optional<GameProfile> gameProfile = GrimACFabricLoaderPlugin.FABRIC_SERVER.getProfileCache().get(name);
|
||||
return gameProfile.orElse(null);
|
||||
}
|
||||
}
|
||||
-57
@@ -1,57 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1171;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.AbstractFabricPlatformServer;
|
||||
import ac.grim.grimac.platform.api.manager.CommandAdapter;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.command.FabricPlayerSelectorParser;
|
||||
import ac.grim.grimac.platform.fabric.manager.FabricParserDescriptorFactory;
|
||||
import ac.grim.grimac.platform.fabric.mc1171.player.Fabric1170PlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.Fabric1140PlatformServer;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.command.Fabric1161PlayerSelectorAdapter;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.player.Fabric1161PlatformInventory;
|
||||
import ac.grim.grimac.platform.fabric.mc1171.entity.Fabric1170GrimEntity;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.util.convert.Fabric1140ConversionUtil;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.util.convert.Fabric1161MessageUtil;
|
||||
import ac.grim.grimac.platform.fabric.player.FabricPlatformPlayerFactory;
|
||||
import ac.grim.grimac.platform.fabric.utils.convert.IFabricConversionUtil;
|
||||
import ac.grim.grimac.platform.fabric.utils.message.IFabricMessageUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
|
||||
public class GrimACFabric1170LoaderPlugin extends GrimACFabricLoaderPlugin {
|
||||
|
||||
public GrimACFabric1170LoaderPlugin() {
|
||||
this( new FabricParserDescriptorFactory(
|
||||
new FabricPlayerSelectorParser<>(Fabric1161PlayerSelectorAdapter::new)
|
||||
),
|
||||
new FabricPlatformPlayerFactory(
|
||||
Fabric1170PlatformPlayer::new,
|
||||
Fabric1170GrimEntity::new,
|
||||
Fabric1161PlatformInventory::new
|
||||
),
|
||||
PacketEvents.getAPI().getServerManager().getVersion().isNewerThan(ServerVersion.V_1_17)
|
||||
? new Fabric1171PlatformServer() : new Fabric1140PlatformServer(),
|
||||
new Fabric1161MessageUtil(),
|
||||
new Fabric1140ConversionUtil()
|
||||
);
|
||||
}
|
||||
|
||||
protected GrimACFabric1170LoaderPlugin(CommandAdapter parserDescriptorFactory,
|
||||
FabricPlatformPlayerFactory playerFactory,
|
||||
AbstractFabricPlatformServer platformServer,
|
||||
IFabricMessageUtil fabricMessageUtil,
|
||||
IFabricConversionUtil fabricConversionUtil) {
|
||||
super(
|
||||
parserDescriptorFactory,
|
||||
playerFactory,
|
||||
platformServer,
|
||||
fabricMessageUtil,
|
||||
fabricConversionUtil
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerVersion getNativeVersion() {
|
||||
return ServerVersion.V_1_17_1;
|
||||
}
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1171.entity;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.mc1161.entity.Fabric1161GrimEntity;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
|
||||
public class Fabric1170GrimEntity extends Fabric1161GrimEntity {
|
||||
|
||||
public Fabric1170GrimEntity(Entity entity) {
|
||||
super(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDead() {
|
||||
return this.entity instanceof LivingEntity living ? living.isDeadOrDying() : this.entity.isRemoved();
|
||||
}
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1171.player;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.mc1161.player.Fabric1161PlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.utils.convert.FabricConversionUtil;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
||||
public class Fabric1170PlatformPlayer extends Fabric1161PlatformPlayer {
|
||||
public Fabric1170PlatformPlayer(ServerPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGameMode(GameMode gameMode) {
|
||||
fabricPlayer.setGameMode(FabricConversionUtil.toFabricGameMode(gameMode));
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "grimac-mc1171",
|
||||
"version": "${version}",
|
||||
"name": "GrimAC for 1.17+ built against 1.17.1",
|
||||
"description": "Libre simulation anticheat designed for 1.21 with 1.8-1.21 support, powered by PacketEvents 2.0.",
|
||||
"authors": [
|
||||
"GrimAC"
|
||||
],
|
||||
"license": "GPLv3",
|
||||
"environment": "server",
|
||||
"entrypoints": {
|
||||
"grimMainLoad": [
|
||||
"ac.grim.grimac.platform.fabric.mc1171.GrimACFabric1170LoaderPlugin"
|
||||
]
|
||||
},
|
||||
"accessWidener": "grimac.accesswidener",
|
||||
"depends": {
|
||||
"minecraft": ">=1.17",
|
||||
"fabric-lifecycle-events-v1": "*"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
accessWidener v2 named
|
||||
accessible field net/minecraft/server/level/ServerLevel serverLevelData Lnet/minecraft/world/level/storage/ServerLevelData;
|
||||
accessible field net/minecraft/commands/CommandSourceStack source Lnet/minecraft/commands/CommandSource;
|
||||
@@ -1,13 +0,0 @@
|
||||
dependencies {
|
||||
minecraft("com.mojang:minecraft:1.19.4")
|
||||
mappings(loom.officialMojangMappings())
|
||||
compileOnly(project(":fabric:mc1161", configuration = "namedElements"))
|
||||
compileOnly(project(":fabric:mc1171", configuration = "namedElements"))
|
||||
|
||||
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", "0.87.2+1.19.4"))
|
||||
modImplementation("me.lucko:fabric-permissions-api:0.3.1")
|
||||
}
|
||||
|
||||
tasks.compileJava {
|
||||
options.release.set(17)
|
||||
}
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1194;
|
||||
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.mc1171.Fabric1171PlatformServer;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
|
||||
public class Fabric1190PlatformServer extends Fabric1171PlatformServer {
|
||||
@Override
|
||||
public void dispatchCommand(Sender sender, String command) {
|
||||
CommandSourceStack commandSource = GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().reverse(sender);
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER.getCommands().performPrefixedCommand(commandSource, command);
|
||||
}
|
||||
}
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1194;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.AbstractFabricPlatformServer;
|
||||
import ac.grim.grimac.platform.api.manager.CommandAdapter;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.command.Fabric1161PlayerSelectorAdapter;
|
||||
import ac.grim.grimac.platform.fabric.command.FabricPlayerSelectorParser;
|
||||
import ac.grim.grimac.platform.fabric.manager.FabricParserDescriptorFactory;
|
||||
import ac.grim.grimac.platform.fabric.mc1171.GrimACFabric1170LoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.mc1171.player.Fabric1170PlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.mc1194.convert.Fabric1190MessageUtil;
|
||||
import ac.grim.grimac.platform.fabric.mc1194.entity.Fabric1194GrimEntity;
|
||||
import ac.grim.grimac.platform.fabric.mc1194.player.Fabric1193PlatformInventory;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.player.Fabric1161PlatformInventory;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.util.convert.Fabric1140ConversionUtil;
|
||||
import ac.grim.grimac.platform.fabric.player.FabricPlatformPlayerFactory;
|
||||
import ac.grim.grimac.platform.fabric.utils.convert.IFabricConversionUtil;
|
||||
import ac.grim.grimac.platform.fabric.utils.message.IFabricMessageUtil;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
|
||||
public class GrimACFabric1190LoaderPlugin extends GrimACFabric1170LoaderPlugin {
|
||||
|
||||
public GrimACFabric1190LoaderPlugin() {
|
||||
this(
|
||||
new FabricParserDescriptorFactory(
|
||||
new FabricPlayerSelectorParser<>(Fabric1161PlayerSelectorAdapter::new)
|
||||
),
|
||||
new FabricPlatformPlayerFactory(
|
||||
Fabric1170PlatformPlayer::new,
|
||||
Fabric1194GrimEntity::new,
|
||||
PacketEvents.getAPI().getServerManager().getVersion().isNewerThan(ServerVersion.V_1_19_2)
|
||||
? Fabric1193PlatformInventory::new : Fabric1161PlatformInventory::new
|
||||
),
|
||||
new Fabric1190PlatformServer(),
|
||||
new Fabric1190MessageUtil(),
|
||||
new Fabric1140ConversionUtil()
|
||||
);
|
||||
}
|
||||
|
||||
protected GrimACFabric1190LoaderPlugin(
|
||||
CommandAdapter parserDescriptorFactory,
|
||||
FabricPlatformPlayerFactory platformPlayerFactory,
|
||||
AbstractFabricPlatformServer platformServer,
|
||||
IFabricMessageUtil fabricMessageUtil,
|
||||
IFabricConversionUtil fabricConversionUtil) {
|
||||
super(parserDescriptorFactory, platformPlayerFactory, platformServer, fabricMessageUtil, fabricConversionUtil);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerVersion getNativeVersion() {
|
||||
return ServerVersion.V_1_19_4;
|
||||
}
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1194.convert;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.mc1161.util.convert.Fabric1161MessageUtil;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
public class Fabric1190MessageUtil extends Fabric1161MessageUtil {
|
||||
@Override
|
||||
public Component textLiteral(String message) {
|
||||
return Component.literal(message);
|
||||
}
|
||||
}
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1194.entity;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.mc1171.entity.Fabric1170GrimEntity;
|
||||
import ac.grim.grimac.platform.fabric.utils.thread.FabricFutureUtil;
|
||||
import ac.grim.grimac.utils.math.Location;
|
||||
import java.util.EnumSet;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.RelativeMovement;
|
||||
|
||||
public class Fabric1194GrimEntity extends Fabric1170GrimEntity {
|
||||
|
||||
public Fabric1194GrimEntity(Entity entity) {
|
||||
super(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> teleportAsync(Location location) {
|
||||
return FabricFutureUtil.supplySync(() -> {
|
||||
if (entity.getLevel() instanceof ServerLevel) {
|
||||
entity.teleportTo(
|
||||
(ServerLevel) location.getWorld(),
|
||||
location.getX(),
|
||||
location.getY(),
|
||||
location.getZ(),
|
||||
EnumSet.noneOf(RelativeMovement.class), // todo change to match paper? Do they do this?
|
||||
location.getYaw(),
|
||||
location.getPitch()
|
||||
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1194.player;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.mc1161.player.Fabric1161PlatformInventory;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
|
||||
public class Fabric1193PlatformInventory extends Fabric1161PlatformInventory {
|
||||
public Fabric1193PlatformInventory(ServerPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResourceLocation getScreenID(MenuType<?> type) {
|
||||
return BuiltInRegistries.MENU.getKey(type);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "grimac-mc1194",
|
||||
"version": "${version}",
|
||||
"name": "GrimAC for 1.19+ built against 1.19.4",
|
||||
"description": "Libre simulation anticheat designed for 1.21 with 1.8-1.21 support, powered by PacketEvents 2.0.",
|
||||
"authors": [
|
||||
"GrimAC"
|
||||
],
|
||||
"license": "GPLv3",
|
||||
"environment": "server",
|
||||
"entrypoints": {
|
||||
"grimMainLoad": [
|
||||
"ac.grim.grimac.platform.fabric.mc1194.GrimACFabric1190LoaderPlugin"
|
||||
]
|
||||
},
|
||||
"accessWidener": "grimac.accesswidener",
|
||||
"depends": {
|
||||
"minecraft": ">=1.19",
|
||||
"fabric-lifecycle-events-v1": "*"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
accessWidener v2 named
|
||||
accessible field net/minecraft/server/level/ServerLevel serverLevelData Lnet/minecraft/world/level/storage/ServerLevelData;
|
||||
accessible field net/minecraft/commands/CommandSourceStack source Lnet/minecraft/commands/CommandSource;
|
||||
@@ -1,10 +0,0 @@
|
||||
dependencies {
|
||||
minecraft("com.mojang:minecraft:1.20.5")
|
||||
mappings(loom.officialMojangMappings())
|
||||
compileOnly(project(":fabric:mc1161", configuration = "namedElements"))
|
||||
compileOnly(project(":fabric:mc1171", configuration = "namedElements"))
|
||||
compileOnly(project(":fabric:mc1194", configuration = "namedElements"))
|
||||
|
||||
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", "0.97.8+1.20.5"))
|
||||
modImplementation("me.lucko:fabric-permissions-api:0.3.1")
|
||||
}
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1205;
|
||||
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.mc1194.Fabric1190PlatformServer;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
|
||||
public class Fabric1203PlatformServer extends Fabric1190PlatformServer {
|
||||
|
||||
// TODO (Cross-platform) implement proper bukkit equivalent for getting TPS over time
|
||||
@Override
|
||||
public double getTPS() {
|
||||
return Math.min(1000.0 / GrimACFabricLoaderPlugin.FABRIC_SERVER.getCurrentSmoothedTickTime(), GrimACFabricLoaderPlugin.FABRIC_SERVER.tickRateManager().tickrate());
|
||||
}
|
||||
|
||||
// Return type changed from int -> void in 1.20.3
|
||||
@Override
|
||||
public void dispatchCommand(Sender sender, String command) {
|
||||
CommandSourceStack commandSource = GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().reverse(sender);
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER.getCommands().performPrefixedCommand(commandSource, command);
|
||||
}
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1205;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.command.FabricPlayerSelectorParser;
|
||||
import ac.grim.grimac.platform.fabric.manager.FabricParserDescriptorFactory;
|
||||
import ac.grim.grimac.platform.fabric.mc1171.player.Fabric1170PlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.mc1194.Fabric1190PlatformServer;
|
||||
import ac.grim.grimac.platform.fabric.mc1194.GrimACFabric1190LoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.mc1194.player.Fabric1193PlatformInventory;
|
||||
import ac.grim.grimac.platform.fabric.mc1205.convert.Fabric1200MessageUtil;
|
||||
import ac.grim.grimac.platform.fabric.mc1205.convert.Fabric1205ConversionUtil;
|
||||
import ac.grim.grimac.platform.fabric.mc1194.entity.Fabric1194GrimEntity;
|
||||
import ac.grim.grimac.platform.fabric.mc1205.player.Fabric1202PlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.command.Fabric1161PlayerSelectorAdapter;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.util.convert.Fabric1140ConversionUtil;
|
||||
import ac.grim.grimac.platform.fabric.player.FabricPlatformPlayerFactory;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import io.github.retrooper.packetevents.factory.fabric.FabricPacketEventsAPI;
|
||||
|
||||
public class GrimACFabric1200LoaderPlugin extends GrimACFabric1190LoaderPlugin {
|
||||
|
||||
public GrimACFabric1200LoaderPlugin() {
|
||||
super(
|
||||
new FabricParserDescriptorFactory(
|
||||
new FabricPlayerSelectorParser<>(Fabric1161PlayerSelectorAdapter::new)
|
||||
),
|
||||
new FabricPlatformPlayerFactory(
|
||||
FabricPacketEventsAPI.getServerAPI().getServerManager().getVersion().isNewerThan(ServerVersion.V_1_20_1)
|
||||
? Fabric1202PlatformPlayer::new : Fabric1170PlatformPlayer::new,
|
||||
Fabric1194GrimEntity::new,
|
||||
Fabric1193PlatformInventory::new
|
||||
),
|
||||
FabricPacketEventsAPI.getServerAPI().getServerManager().getVersion().isNewerThan(ServerVersion.V_1_20_2)
|
||||
? new Fabric1203PlatformServer() : new Fabric1190PlatformServer(),
|
||||
new Fabric1200MessageUtil(),
|
||||
FabricPacketEventsAPI.getServerAPI().getServerManager().getVersion().isNewerThan(ServerVersion.V_1_20_4)
|
||||
? new Fabric1205ConversionUtil() : new Fabric1140ConversionUtil()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerVersion getNativeVersion() {
|
||||
return ServerVersion.V_1_20_5;
|
||||
}
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1205.convert;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.mc1194.convert.Fabric1190MessageUtil;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
public class Fabric1200MessageUtil extends Fabric1190MessageUtil {
|
||||
@Override
|
||||
public void sendMessage(CommandSourceStack target, Component message, boolean overlay) {
|
||||
target.sendSuccess(() -> message, overlay);
|
||||
}
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1205.convert;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.utils.convert.IFabricConversionUtil;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import io.github.retrooper.packetevents.adventure.serializer.gson.GsonComponentSerializer;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.PooledByteBufAllocator;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
|
||||
public class Fabric1205ConversionUtil implements IFabricConversionUtil {
|
||||
public ItemStack fromFabricItemStack(net.minecraft.world.item.ItemStack fabricStack) {
|
||||
if (fabricStack.isEmpty()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
// Allocate a ByteBuf
|
||||
ByteBuf buffer = PooledByteBufAllocator.DEFAULT.buffer();
|
||||
try {
|
||||
// Obtain the DynamicRegistryManager (you need to provide this from your context)
|
||||
RegistryAccess registryManager = GrimACFabricLoaderPlugin.FABRIC_SERVER.registryAccess(); // Replace with actual method to get registry manager
|
||||
|
||||
// Create a RegistryByteBuf
|
||||
RegistryFriendlyByteBuf registryByteBuf = new RegistryFriendlyByteBuf(buffer, registryManager);
|
||||
|
||||
// Encode the ItemStack using the appropriate PacketCodec
|
||||
net.minecraft.world.item.ItemStack.STREAM_CODEC.encode(registryByteBuf, fabricStack);
|
||||
|
||||
// Create a PacketWrapper to read the ItemStack back (if needed)
|
||||
PacketWrapper<?> wrapper = PacketWrapper.createUniversalPacketWrapper(buffer);
|
||||
return wrapper.readItemStack();
|
||||
} catch (Exception e) {
|
||||
// Handle encoding errors
|
||||
LogUtil.error("Failed to encode ItemStack: {}" + fabricStack, e);
|
||||
return ItemStack.EMPTY;
|
||||
} finally {
|
||||
// Release the ByteBuf to prevent memory leaks
|
||||
ByteBufHelper.release(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO proper registry support?
|
||||
public net.minecraft.network.chat.Component toNativeText(Component component) {
|
||||
return net.minecraft.network.chat.Component.Serializer.fromJson(GsonComponentSerializer.gson().serializeToTree(component), RegistryAccess.EMPTY);
|
||||
}
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1205.player;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.mc1171.player.Fabric1170PlatformPlayer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
||||
public class Fabric1202PlatformPlayer extends Fabric1170PlatformPlayer {
|
||||
public Fabric1202PlatformPlayer(ServerPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void kickPlayer(String textReason) {
|
||||
fabricPlayer.connection.disconnect(GrimACFabricLoaderPlugin.LOADER.getFabricMessageUtils().textLiteral(textReason));
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "grimac-mc1205",
|
||||
"version": "${version}",
|
||||
"name": "GrimAC for 1.20+ built against 1.20.5",
|
||||
"description": "Libre simulation anticheat designed for 1.21 with 1.8-1.21 support, powered by PacketEvents 2.0.",
|
||||
"authors": [
|
||||
"GrimAC"
|
||||
],
|
||||
"license": "GPLv3",
|
||||
"environment": "server",
|
||||
"entrypoints": {
|
||||
"grimMainLoad": [
|
||||
"ac.grim.grimac.platform.fabric.mc1205.GrimACFabric1200LoaderPlugin"
|
||||
]
|
||||
},
|
||||
"accessWidener": "grimac.accesswidener",
|
||||
"depends": {
|
||||
"minecraft": ">=1.20",
|
||||
"fabric-lifecycle-events-v1": "*"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
accessWidener v2 named
|
||||
accessible field net/minecraft/server/level/ServerLevel serverLevelData Lnet/minecraft/world/level/storage/ServerLevelData;
|
||||
accessible field net/minecraft/commands/CommandSourceStack source Lnet/minecraft/commands/CommandSource;
|
||||
@@ -1,17 +0,0 @@
|
||||
dependencies {
|
||||
minecraft("com.mojang:minecraft:1.21.6")
|
||||
mappings(loom.officialMojangMappings())
|
||||
compileOnly(project(":fabric:mc1161", configuration = "namedElements"))
|
||||
compileOnly(project(":fabric:mc1171", configuration = "namedElements"))
|
||||
compileOnly(project(":fabric:mc1194", configuration = "namedElements"))
|
||||
compileOnly(project(":fabric:mc1205", configuration = "namedElements"))
|
||||
|
||||
modImplementation(fabricApi.module("fabric-lifecycle-events-v1", "0.128.1+1.21.6"))
|
||||
modImplementation("me.lucko:fabric-permissions-api:0.4.0")
|
||||
include("me.lucko:fabric-permissions-api:0.4.0")
|
||||
}
|
||||
|
||||
|
||||
tasks.compileJava {
|
||||
options.release.set(21)
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1216;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.mc1216.command.Fabric1212PlayerSelectorAdapter;
|
||||
import ac.grim.grimac.platform.fabric.command.FabricPlayerSelectorParser;
|
||||
import ac.grim.grimac.platform.fabric.manager.FabricParserDescriptorFactory;
|
||||
import ac.grim.grimac.platform.fabric.mc1194.GrimACFabric1190LoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.mc1194.entity.Fabric1194GrimEntity;
|
||||
import ac.grim.grimac.platform.fabric.mc1194.player.Fabric1193PlatformInventory;
|
||||
import ac.grim.grimac.platform.fabric.mc1205.Fabric1203PlatformServer;
|
||||
import ac.grim.grimac.platform.fabric.mc1205.convert.Fabric1200MessageUtil;
|
||||
import ac.grim.grimac.platform.fabric.mc1205.convert.Fabric1205ConversionUtil;
|
||||
import ac.grim.grimac.platform.fabric.mc1216.convert.Fabric1216ConversionUtil;
|
||||
import ac.grim.grimac.platform.fabric.mc1216.player.Fabric1212PlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.mc1216.player.Fabric1215PlatformInventory;
|
||||
import ac.grim.grimac.platform.fabric.player.FabricPlatformPlayerFactory;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
|
||||
public class GrimACFabric1212LoaderPlugin extends GrimACFabric1190LoaderPlugin {
|
||||
|
||||
public GrimACFabric1212LoaderPlugin() {
|
||||
super(
|
||||
new FabricParserDescriptorFactory(
|
||||
new FabricPlayerSelectorParser<>(Fabric1212PlayerSelectorAdapter::new)
|
||||
),
|
||||
new FabricPlatformPlayerFactory(
|
||||
Fabric1212PlatformPlayer::new,
|
||||
Fabric1194GrimEntity::new,
|
||||
PacketEvents.getAPI().getServerManager().getVersion().isNewerThan(ServerVersion.V_1_21_4)
|
||||
? Fabric1215PlatformInventory::new : Fabric1193PlatformInventory::new
|
||||
),
|
||||
new Fabric1203PlatformServer(),
|
||||
new Fabric1200MessageUtil(),
|
||||
PacketEvents.getAPI().getServerManager().getVersion().isNewerThan(ServerVersion.V_1_21_5)
|
||||
? new Fabric1216ConversionUtil() : new Fabric1205ConversionUtil()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerVersion getNativeVersion() {
|
||||
return ServerVersion.V_1_21_6;
|
||||
}
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1216.command;
|
||||
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.mc1161.command.Fabric1161PlayerSelectorAdapter;
|
||||
import org.incendo.cloud.minecraft.modded.data.SinglePlayerSelector;
|
||||
|
||||
public class Fabric1212PlayerSelectorAdapter extends Fabric1161PlayerSelectorAdapter {
|
||||
|
||||
public Fabric1212PlayerSelectorAdapter(SinglePlayerSelector fabricSelector) {
|
||||
super(fabricSelector);
|
||||
}
|
||||
|
||||
// 1.21.2 .getCommandSource() moves from entity to player
|
||||
@Override
|
||||
public Sender getSinglePlayer() {
|
||||
return GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().map(fabricSelector.single().createCommandSourceStack());
|
||||
}
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1216.convert;
|
||||
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import io.github.retrooper.packetevents.adventure.serializer.gson.GsonComponentSerializer;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.network.chat.ComponentSerialization;
|
||||
|
||||
public class Fabric1216ConversionUtil extends ac.grim.grimac.platform.fabric.mc1205.convert.Fabric1205ConversionUtil {
|
||||
|
||||
@Override
|
||||
public net.minecraft.network.chat.Component toNativeText(Component component) {
|
||||
return ComponentSerialization.CODEC.decode(
|
||||
RegistryAccess.EMPTY.createSerializationContext(JsonOps.INSTANCE),
|
||||
GsonComponentSerializer.gson().serializeToTree(component)
|
||||
).getOrThrow(IllegalArgumentException::new).getFirst();
|
||||
}
|
||||
}
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1216.player;
|
||||
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.mc1205.player.Fabric1202PlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.utils.thread.FabricFutureUtil;
|
||||
import ac.grim.grimac.utils.math.Location;
|
||||
import java.util.EnumSet;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.Relative;
|
||||
|
||||
public class Fabric1212PlatformPlayer extends Fabric1202PlatformPlayer {
|
||||
public Fabric1212PlatformPlayer(ServerPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getSender() {
|
||||
return GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().map(fabricPlayer.createCommandSourceStack());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> teleportAsync(Location location) {
|
||||
return FabricFutureUtil.supplySync(() -> {
|
||||
fabricPlayer.teleportTo(
|
||||
(ServerLevel) location.getWorld(),
|
||||
location.getX(),
|
||||
location.getY(),
|
||||
location.getZ(),
|
||||
EnumSet.noneOf(Relative.class), // todo change to match paper? Do they do this?
|
||||
location.getYaw(),
|
||||
location.getPitch(),
|
||||
true
|
||||
);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mc1216.player;
|
||||
|
||||
import ac.grim.grimac.platform.fabric.mc1194.player.Fabric1193PlatformInventory;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
|
||||
public class Fabric1215PlatformInventory extends Fabric1193PlatformInventory {
|
||||
public Fabric1215PlatformInventory(ServerPlayer player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResourceLocation getScreenID(MenuType<?> type) {
|
||||
return BuiltInRegistries.MENU.getKey(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPlayerCreative() {
|
||||
return fabricPlayer.isCreative();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "grimac-mc1215",
|
||||
"version": "${version}",
|
||||
"name": "GrimAC for 1.21.2+ built against 1.21.5",
|
||||
"description": "Libre simulation anticheat designed for 1.21 with 1.8-1.21 support, powered by PacketEvents 2.0.",
|
||||
"authors": [
|
||||
"GrimAC"
|
||||
],
|
||||
"license": "GPLv3",
|
||||
"environment": "server",
|
||||
"entrypoints": {
|
||||
"grimMainLoad": [
|
||||
"ac.grim.grimac.platform.fabric.mc1216.GrimACFabric1212LoaderPlugin"
|
||||
]
|
||||
},
|
||||
"accessWidener": "grimac.accesswidener",
|
||||
"depends": {
|
||||
"minecraft": ">=1.21.2",
|
||||
"fabric-lifecycle-events-v1": "*"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
accessWidener v2 named
|
||||
accessible field net/minecraft/server/level/ServerLevel serverLevelData Lnet/minecraft/world/level/storage/ServerLevelData;
|
||||
accessible field net/minecraft/commands/CommandSourceStack source Lnet/minecraft/commands/CommandSource;
|
||||
@@ -1,33 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric;
|
||||
|
||||
import ac.grim.grimac.platform.api.PlatformServer;
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class AbstractFabricPlatformServer implements PlatformServer {
|
||||
|
||||
@Override
|
||||
public String getPlatformImplementationString() {
|
||||
// Return the Fabric server version
|
||||
return "Fabric " + FabricLoader.getInstance().getModContainer("fabricloader").orElseThrow().getMetadata().getVersion().getFriendlyString() + " (MC: " + GrimACFabricLoaderPlugin.FABRIC_SERVER.getServerVersion() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sender getConsoleSender() {
|
||||
CommandSourceStack consoleSource = GrimACFabricLoaderPlugin.FABRIC_SERVER.createCommandSourceStack();
|
||||
return GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory().map(consoleSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerOutgoingPluginChannel(String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GameProfile getProfileByName(String name) {
|
||||
return GrimACFabricLoaderPlugin.FABRIC_SERVER.getProfileCache().get(name);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric;
|
||||
|
||||
import ac.grim.grimac.platform.api.PlatformPlugin;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class FabricPlatformPlugin implements PlatformPlugin {
|
||||
private final @NotNull ModContainer modContainer;
|
||||
|
||||
@Contract(pure = true)
|
||||
public FabricPlatformPlugin(@NotNull ModContainer modContainer) {
|
||||
this.modContainer = Objects.requireNonNull(modContainer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
// Fabric mods are always "enabled" if loaded, as there's no explicit enable/disable state
|
||||
// You can add custom logic if needed (e.g., check mod configuration)
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
// Get the mod ID (unique identifier)
|
||||
return modContainer.getMetadata().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
// Get the mod version from metadata
|
||||
return modContainer.getMetadata().getVersion().getFriendlyString();
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.manager.init.start.CommandRegister;
|
||||
import ac.grim.grimac.platform.fabric.initables.FabricBStats;
|
||||
import ac.grim.grimac.platform.fabric.initables.FabricTickEndEvent;
|
||||
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.entrypoint.PreLaunchEntrypoint;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GrimACFabricEntryPoint implements PreLaunchEntrypoint, ModInitializer {
|
||||
@Override
|
||||
public void onPreLaunch() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
FabricLoader loader = FabricLoader.getInstance();
|
||||
String chainLoadEntryPointName = "grimMainLoad";
|
||||
|
||||
// Collect grimMainLoad entrypoints and sort by version
|
||||
List<GrimACFabricLoaderPlugin> mainChainLoadEntryPoints = loader.getEntrypoints(chainLoadEntryPointName, GrimACFabricLoaderPlugin.class);
|
||||
mainChainLoadEntryPoints.sort((a, b) -> b.getNativeVersion().getProtocolVersion() - a.getNativeVersion().getProtocolVersion());
|
||||
|
||||
// Get entrypoint for newest sub-version and execute it
|
||||
GrimACFabricLoaderPlugin platformLoader = mainChainLoadEntryPoints.get(0);
|
||||
GrimACFabricLoaderPlugin.LOADER = platformLoader;
|
||||
|
||||
// On Fabric we have to register commands earlier, and cannot register them when server is no longer null
|
||||
GrimAPI.INSTANCE.load(
|
||||
platformLoader,
|
||||
new FabricBStats(),
|
||||
new FabricTickEndEvent()
|
||||
);
|
||||
|
||||
CommandRegister.registerCommands(platformLoader.getCommandManager());
|
||||
|
||||
ServerLifecycleEvents.SERVER_STARTING.register(server -> {
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER = server;
|
||||
GrimAPI.INSTANCE.start();
|
||||
});
|
||||
|
||||
ServerLifecycleEvents.SERVER_STOPPING.register((server) -> {
|
||||
GrimAPI.INSTANCE.stop();
|
||||
platformLoader.getScheduler().shutdown();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.GrimAPIProvider;
|
||||
import ac.grim.grimac.api.plugin.GrimPlugin;
|
||||
import ac.grim.grimac.events.GrimExtensionManager;
|
||||
import ac.grim.grimac.platform.api.PlatformLoader;
|
||||
import ac.grim.grimac.platform.api.manager.*;
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.platform.api.sender.SenderFactory;
|
||||
import ac.grim.grimac.platform.fabric.manager.*;
|
||||
import ac.grim.grimac.platform.fabric.player.FabricPlatformPlayerFactory;
|
||||
import ac.grim.grimac.platform.fabric.resolver.FabricResolverRegistrar;
|
||||
import ac.grim.grimac.platform.fabric.scheduler.FabricPlatformScheduler;
|
||||
import ac.grim.grimac.platform.fabric.sender.FabricSenderFactory;
|
||||
import ac.grim.grimac.platform.fabric.utils.convert.IFabricConversionUtil;
|
||||
import ac.grim.grimac.platform.fabric.utils.message.IFabricMessageUtil;
|
||||
import ac.grim.grimac.utils.lazy.LazyHolder;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.PacketEventsAPI;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.incendo.cloud.CommandManager;
|
||||
import org.incendo.cloud.execution.ExecutionCoordinator;
|
||||
import org.incendo.cloud.fabric.FabricServerCommandManager;
|
||||
|
||||
public abstract class GrimACFabricLoaderPlugin implements PlatformLoader {
|
||||
public static MinecraftServer FABRIC_SERVER;
|
||||
public static GrimACFabricLoaderPlugin LOADER;
|
||||
|
||||
protected final LazyHolder<FabricPlatformScheduler> scheduler = LazyHolder.simple(FabricPlatformScheduler::new);
|
||||
// Since we JiJ PacketEvents and depend on it on Fabric, we can always just get the API instance since it loads firsts
|
||||
protected final PacketEventsAPI<?> packetEvents = PacketEvents.getAPI();
|
||||
protected final LazyHolder<FabricSenderFactory> senderFactory = LazyHolder.simple(FabricSenderFactory::new);
|
||||
protected final LazyHolder<CommandManager<Sender>> commandManager = LazyHolder.simple(this::createCommandManager);
|
||||
protected final LazyHolder<ItemResetHandler> itemResetHandler = LazyHolder.simple(FabricItemResetHandler::new);
|
||||
protected final GrimPlugin plugin;
|
||||
@Getter
|
||||
protected final PlatformPluginManager pluginManager = new FabricPlatformPluginManager();
|
||||
@Getter
|
||||
protected final MessagePlaceHolderManager messagePlaceHolderManager = new FabricMessagePlaceHolderManager();
|
||||
protected final LazyHolder<FabricPermissionRegistrationManager> fabricPermissionRegistrationManager = LazyHolder.simple(FabricPermissionRegistrationManager::new);
|
||||
|
||||
protected final CommandAdapter parserFactory;
|
||||
protected final FabricPlatformPlayerFactory playerFactory;
|
||||
protected final AbstractFabricPlatformServer platformServer;
|
||||
@Getter
|
||||
protected final IFabricConversionUtil fabricConversionUtil;
|
||||
protected final IFabricMessageUtil fabricMessageUtil;
|
||||
|
||||
public GrimACFabricLoaderPlugin(
|
||||
CommandAdapter parserDescriptorFactory,
|
||||
FabricPlatformPlayerFactory playerFactory,
|
||||
AbstractFabricPlatformServer platformServer,
|
||||
IFabricMessageUtil fabricMessageUtil,
|
||||
IFabricConversionUtil fabricConversionUtil
|
||||
) {
|
||||
this.parserFactory = parserDescriptorFactory;
|
||||
this.playerFactory = playerFactory;
|
||||
this.platformServer = platformServer;
|
||||
this.fabricMessageUtil = fabricMessageUtil;
|
||||
this.fabricConversionUtil = fabricConversionUtil;
|
||||
|
||||
GrimExtensionManager extensionManager = GrimAPI.INSTANCE.getExtensionManager();
|
||||
new FabricResolverRegistrar(extensionManager).registerAll();
|
||||
plugin = extensionManager.getPlugin("GrimAC");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricPlatformScheduler getScheduler() {
|
||||
return scheduler.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketEventsAPI<?> getPacketEvents() {
|
||||
return packetEvents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandManager<Sender> getCommandManager() {
|
||||
return commandManager.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemResetHandler getItemResetHandler() {
|
||||
return itemResetHandler.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SenderFactory<CommandSourceStack> getSenderFactory() {
|
||||
return senderFactory.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GrimPlugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerAPIService() {
|
||||
GrimAPIProvider.init(GrimAPI.INSTANCE.getExternalAPI());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionRegistrationManager getPermissionManager() {
|
||||
return fabricPermissionRegistrationManager.get();
|
||||
}
|
||||
|
||||
private CommandManager<Sender> createCommandManager() {
|
||||
return new FabricServerCommandManager<>(
|
||||
ExecutionCoordinator.simpleCoordinator(),
|
||||
senderFactory.get()
|
||||
);
|
||||
}
|
||||
|
||||
public FabricSenderFactory getFabricSenderFactory() {
|
||||
return senderFactory.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandAdapter getCommandAdapter() {
|
||||
return parserFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricPlatformPlayerFactory getPlatformPlayerFactory() {
|
||||
return playerFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractFabricPlatformServer getPlatformServer() {
|
||||
return platformServer;
|
||||
}
|
||||
|
||||
public IFabricMessageUtil getFabricMessageUtils() {
|
||||
return fabricMessageUtil;
|
||||
}
|
||||
|
||||
public abstract ServerVersion getNativeVersion();
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.command;
|
||||
|
||||
import ac.grim.grimac.platform.api.command.AbstractPlayerSelectorParser;
|
||||
import ac.grim.grimac.platform.api.command.PlayerSelector;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.minecraft.modded.data.SinglePlayerSelector;
|
||||
import org.incendo.cloud.minecraft.modded.parser.VanillaArgumentParsers;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class FabricPlayerSelectorParser<C> extends AbstractPlayerSelectorParser<C> {
|
||||
|
||||
private final Function<SinglePlayerSelector, PlayerSelector> selectorSupplier;
|
||||
|
||||
@Override
|
||||
public ParserDescriptor<C, PlayerSelector> descriptor() {
|
||||
return createDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ParserDescriptor<C, ?> getPlatformSpecificDescriptor() {
|
||||
return VanillaArgumentParsers.singlePlayerSelectorParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CompletableFuture<PlayerSelector> adaptToCommonSelector(CommandContext<C> context, Object platformSpecificSelector) {
|
||||
return CompletableFuture.completedFuture(
|
||||
selectorSupplier.apply((SinglePlayerSelector) platformSpecificSelector)
|
||||
);
|
||||
}
|
||||
}
|
||||
-66
@@ -1,66 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.entity;
|
||||
|
||||
import ac.grim.grimac.platform.api.entity.GrimEntity;
|
||||
import ac.grim.grimac.platform.api.world.PlatformWorld;
|
||||
import ac.grim.grimac.utils.math.Location;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
||||
public abstract class AbstractFabricGrimEntity implements GrimEntity {
|
||||
|
||||
protected final Entity entity;
|
||||
|
||||
public AbstractFabricGrimEntity(Entity entity) {
|
||||
this.entity = Objects.requireNonNull(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return entity.getUUID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eject() {
|
||||
if (entity.isVehicle()) {
|
||||
entity.ejectPassengers();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Entity getNative() {
|
||||
return this.entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformWorld getWorld() {
|
||||
return (PlatformWorld) entity.level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return new Location(
|
||||
this.getWorld(),
|
||||
this.entity.getX(),
|
||||
this.entity.getY(),
|
||||
this.entity.getZ(),
|
||||
this.entity.getViewYRot(1.0F),
|
||||
this.entity.getViewXRot(1.0F)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double distanceSquared(double oX, double oY, double oZ) {
|
||||
double x = this.entity.getX();
|
||||
double y = this.entity.getY();
|
||||
double z = this.entity.getZ();
|
||||
double distX = (x - oX) * (x - oX);
|
||||
double distY = (y - oY) * (y - oY);
|
||||
double distZ = (z - oZ) * (z - oZ);
|
||||
return distX + distY + distZ;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.initables;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.manager.init.start.StartableInitable;
|
||||
import ac.grim.grimac.manager.init.stop.StoppableInitable;
|
||||
import ac.grim.grimac.platform.fabric.utils.metrics.MetricsFabric;
|
||||
import ac.grim.grimac.utils.anticheat.Constants;
|
||||
|
||||
public class FabricBStats implements StartableInitable, StoppableInitable {
|
||||
|
||||
private MetricsFabric metricsFabric;
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
try {
|
||||
metricsFabric = new MetricsFabric(GrimAPI.INSTANCE.getGrimPlugin(), Constants.BSTATS_PLUGIN_ID);
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
if (metricsFabric != null)
|
||||
metricsFabric.shutdown();
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.initables;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.manager.init.start.AbstractTickEndEvent;
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
public class FabricTickEndEvent extends AbstractTickEndEvent {
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (!super.shouldInjectEndTick()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Register the end-of-tick callback
|
||||
ServerTickEvents.END_SERVER_TICK.register(this::onEndServerTick);
|
||||
}
|
||||
|
||||
private void onEndServerTick(MinecraftServer server) {
|
||||
tickAllPlayers();
|
||||
}
|
||||
|
||||
private void tickAllPlayers() {
|
||||
for (GrimPlayer player : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
|
||||
if (player.disableGrim) continue;
|
||||
super.onEndOfTick(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.manager;
|
||||
|
||||
import ac.grim.grimac.platform.api.manager.ItemResetHandler;
|
||||
import ac.grim.grimac.platform.api.player.PlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.utils.convert.FabricConversionUtil;
|
||||
import com.github.retrooper.packetevents.protocol.player.InteractionHand;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class FabricItemResetHandler implements ItemResetHandler {
|
||||
@Override
|
||||
public void resetItemUsage(@Nullable PlatformPlayer player) {
|
||||
if (player != null) {
|
||||
((ServerPlayer) player.getNative()).stopUsingItem();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable InteractionHand getItemUsageHand(@Nullable PlatformPlayer platformPlayer) {
|
||||
if (platformPlayer == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ServerPlayer player = (ServerPlayer) platformPlayer.getNative();
|
||||
return player.isUsingItem() ? FabricConversionUtil.fromFabricHand(player.getUsedItemHand()) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUsingItem(@Nullable PlatformPlayer player) {
|
||||
return player != null && ((ServerPlayer) player.getNative()).isUsingItem();
|
||||
}
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.manager;
|
||||
|
||||
import ac.grim.grimac.platform.api.manager.MessagePlaceHolderManager;
|
||||
import ac.grim.grimac.platform.api.player.PlatformPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class FabricMessagePlaceHolderManager implements MessagePlaceHolderManager {
|
||||
|
||||
// PlaceHolderAPI doesn't exist on Fabric and no chosen replacement for the platform yet
|
||||
@Override
|
||||
public @NotNull String replacePlaceholders(@Nullable PlatformPlayer player, @NotNull String string) {
|
||||
return string;
|
||||
}
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.manager;
|
||||
|
||||
import ac.grim.grimac.platform.api.command.PlayerSelector;
|
||||
import ac.grim.grimac.platform.api.manager.CommandAdapter;
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.command.FabricPlayerSelectorParser;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.incendo.cloud.parser.ParserDescriptor;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.incendo.cloud.suggestion.SuggestionProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class FabricParserDescriptorFactory implements CommandAdapter {
|
||||
|
||||
private final FabricPlayerSelectorParser<Sender> fabricPlayerSelectorParser;
|
||||
|
||||
@Override
|
||||
public ParserDescriptor<Sender, PlayerSelector> singlePlayerSelectorParser() {
|
||||
return fabricPlayerSelectorParser.descriptor();
|
||||
}
|
||||
|
||||
// TODO (Cross-platform) brigadier style & better suggestions
|
||||
@Override
|
||||
public SuggestionProvider<Sender> onlinePlayerSuggestions() {
|
||||
return (context, input) -> {
|
||||
List<Suggestion> suggestions = new ArrayList<>();
|
||||
|
||||
// TODO Support Vanish mods?
|
||||
for (ServerPlayer player : GrimACFabricLoaderPlugin.FABRIC_SERVER.getPlayerList().getPlayers()) {
|
||||
suggestions.add(Suggestion.suggestion(player.getName().getString()));
|
||||
}
|
||||
|
||||
return CompletableFuture.completedFuture(suggestions);
|
||||
};
|
||||
}
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.manager;
|
||||
|
||||
import ac.grim.grimac.platform.api.manager.PermissionRegistrationManager;
|
||||
import ac.grim.grimac.platform.api.permissions.PermissionDefaultValue;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.sender.FabricSenderFactory;
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
|
||||
public class FabricPermissionRegistrationManager implements PermissionRegistrationManager {
|
||||
|
||||
private final FabricSenderFactory fabricSenderFactory = GrimACFabricLoaderPlugin.LOADER.getFabricSenderFactory();
|
||||
|
||||
public FabricPermissionRegistrationManager() {
|
||||
registerPermission("grim.exempt", PermissionDefaultValue.FALSE);
|
||||
registerPermission("grim.nosetback", PermissionDefaultValue.FALSE);
|
||||
registerPermission("grim.nomodifypacket", PermissionDefaultValue.FALSE);
|
||||
registerPermission("grim.nosetback", PermissionDefaultValue.FALSE);
|
||||
registerPermission("grim.alerts.enable-on-join", PermissionDefaultValue.FALSE);
|
||||
registerPermission("grim.verbose.enable-on-join", PermissionDefaultValue.FALSE);
|
||||
registerPermission("grim.brand.enable-on-join", PermissionDefaultValue.FALSE);
|
||||
registerPermission("grim.alerts.enable-on-join.silent", PermissionDefaultValue.FALSE);
|
||||
registerPermission("grim.verbose.enable-on-join.silent", PermissionDefaultValue.FALSE);
|
||||
registerPermission("grim.brand.enable-on-join.silent", PermissionDefaultValue.FALSE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPermission(String name, PermissionDefaultValue defaultValue) {
|
||||
fabricSenderFactory.registerPermissionDefault(name, defaultValue);
|
||||
Permissions.check(GrimACFabricLoaderPlugin.FABRIC_SERVER.createCommandSourceStack(), name);
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.manager;
|
||||
|
||||
import ac.grim.grimac.platform.api.PlatformPlugin;
|
||||
import ac.grim.grimac.platform.api.manager.PlatformPluginManager;
|
||||
import ac.grim.grimac.platform.fabric.FabricPlatformPlugin;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
public class FabricPlatformPluginManager implements PlatformPluginManager {
|
||||
|
||||
@Override
|
||||
public PlatformPlugin[] getPlugins() {
|
||||
// Get all loaded mods from Fabric Loader
|
||||
Collection<ModContainer> mods = FabricLoader.getInstance().getAllMods();
|
||||
PlatformPlugin[] plugins = new PlatformPlugin[mods.size()];
|
||||
int i = 0;
|
||||
for (ModContainer mod : mods) {
|
||||
plugins[i++] = new FabricPlatformPlugin(mod);
|
||||
}
|
||||
return plugins;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformPlugin getPlugin(String pluginName) {
|
||||
// Look up a mod by its ID
|
||||
Optional<ModContainer> mod = FabricLoader.getInstance().getModContainer(pluginName);
|
||||
return mod.map(FabricPlatformPlugin::new).orElse(null);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mixins;
|
||||
|
||||
import ac.grim.grimac.platform.api.world.PlatformChunk;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import org.spongepowered.asm.mixin.Implements;
|
||||
import org.spongepowered.asm.mixin.Interface;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
@Mixin(LevelChunk.class)
|
||||
@Implements(@Interface(iface = PlatformChunk.class, prefix = "grimac$"))
|
||||
abstract class LevelChunkMixin {
|
||||
public int grimac$getBlockID(int x, int y, int z) {
|
||||
LevelChunk chunk = (LevelChunk) (Object) this;
|
||||
return Block.getId(chunk.getBlockState(new BlockPos(
|
||||
chunk.getPos().getMinBlockX() + x,
|
||||
y,
|
||||
chunk.getPos().getMinBlockZ() + z
|
||||
)));
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mixins;
|
||||
|
||||
import ac.grim.grimac.platform.api.world.PlatformChunk;
|
||||
import ac.grim.grimac.platform.api.world.PlatformWorld;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.*;
|
||||
|
||||
import java.util.UUID;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.storage.ServerLevelData;
|
||||
|
||||
@Mixin(ServerLevel.class)
|
||||
@Implements(@Interface(iface = PlatformWorld.class, prefix = "grimac$"))
|
||||
abstract class ServerLevelMixin implements LevelAccessor {
|
||||
@Shadow public @Final ServerLevelData serverLevelData;
|
||||
|
||||
public boolean grimac$isChunkLoaded(int chunkX, int chunkZ) {
|
||||
return hasChunk(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
public WrappedBlockState grimac$getBlockAt(int x, int y, int z) {
|
||||
return WrappedBlockState.getByGlobalId(
|
||||
Block.getId(getBlockState(new BlockPos(x, y, z)))
|
||||
);
|
||||
}
|
||||
|
||||
public String grimac$getName() {
|
||||
return serverLevelData.getLevelName();
|
||||
}
|
||||
|
||||
public @Nullable UUID grimac$getUID() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public PlatformChunk grimac$getChunkAt(int currChunkX, int currChunkZ) {
|
||||
return (PlatformChunk) getChunk(currChunkX, currChunkZ);
|
||||
}
|
||||
|
||||
public boolean grimac$isLoaded() {
|
||||
return GrimACFabricLoaderPlugin.FABRIC_SERVER.getLevel(getLevel().dimension()) != null;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.mixins;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.platform.fabric.player.FabricPlatformPlayerFactory;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
// Works from 1.14 - latest (1.21.5)
|
||||
@Mixin(ServerPlayer.class)
|
||||
abstract class ServerPlayerMixin {
|
||||
@Inject(method = "restoreFrom", at = @At("TAIL"))
|
||||
private void onRestoreFrom(ServerPlayer oldPlayer, boolean alive, CallbackInfo ci) {
|
||||
((FabricPlatformPlayerFactory) GrimAPI.INSTANCE.getPlatformPlayerFactory()).replaceNativePlayer(oldPlayer.getUUID(), (ServerPlayer) (Object) this);
|
||||
}
|
||||
}
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.player;
|
||||
|
||||
import ac.grim.grimac.platform.api.player.PlatformInventory;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.utils.convert.IFabricConversionUtil;
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
|
||||
|
||||
public abstract class AbstractFabricPlatformInventory implements PlatformInventory {
|
||||
|
||||
private static final IFabricConversionUtil fabricConversionUtil = GrimACFabricLoaderPlugin.LOADER.getFabricConversionUtil();
|
||||
protected ServerPlayer fabricPlayer;
|
||||
protected Inventory inventory;
|
||||
|
||||
public AbstractFabricPlatformInventory(ServerPlayer player) {
|
||||
this.fabricPlayer = player;
|
||||
this.inventory = player.inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemInHand() {
|
||||
return fabricConversionUtil.fromFabricItemStack(inventory.getSelected());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemInOffHand() {
|
||||
return fabricConversionUtil.fromFabricItemStack(inventory.getItem(40));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStack(int bukkitSlot, int vanillaSlot) {
|
||||
return fabricConversionUtil.fromFabricItemStack(inventory.getItem(bukkitSlot));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getHelmet() {
|
||||
return fabricConversionUtil.fromFabricItemStack(inventory.getItem(39));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getChestplate() {
|
||||
return fabricConversionUtil.fromFabricItemStack(inventory.getItem(38));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getLeggings() {
|
||||
return fabricConversionUtil.fromFabricItemStack(inventory.getItem(37));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getBoots() {
|
||||
return fabricConversionUtil.fromFabricItemStack(inventory.getItem(36));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack[] getContents() {
|
||||
ItemStack[] items = new ItemStack[inventory.getContainerSize()];
|
||||
for (int i = 0; i < inventory.getContainerSize(); i++) {
|
||||
items[i] = fabricConversionUtil.fromFabricItemStack(inventory.getItem(i));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
-160
@@ -1,160 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.player;
|
||||
|
||||
import ac.grim.grimac.platform.api.entity.GrimEntity;
|
||||
import ac.grim.grimac.platform.api.player.PlatformInventory;
|
||||
import ac.grim.grimac.platform.api.player.PlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.entity.AbstractFabricGrimEntity;
|
||||
import ac.grim.grimac.platform.fabric.utils.convert.FabricConversionUtil;
|
||||
import ac.grim.grimac.utils.common.arguments.CommonGrimArguments;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class AbstractFabricPlatformPlayer extends AbstractFabricGrimEntity implements PlatformPlayer {
|
||||
protected ServerPlayer fabricPlayer;
|
||||
protected final AbstractFabricPlatformInventory inventory;
|
||||
private final @Nullable User user;
|
||||
|
||||
public AbstractFabricPlatformPlayer(ServerPlayer player) {
|
||||
super(player);
|
||||
this.fabricPlayer = player;
|
||||
this.inventory = GrimACFabricLoaderPlugin.LOADER.getPlatformPlayerFactory().getPlatformInventory(player);
|
||||
if (CommonGrimArguments.USE_CHAT_FAST_BYPASS.value()) {
|
||||
Object channel = PacketEvents.getAPI().getProtocolManager().getChannel(fabricPlayer.getUUID());
|
||||
this.user = PacketEvents.getAPI().getProtocolManager().getUser(channel);
|
||||
} else {
|
||||
this.user = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void kickPlayer(String textReason) {
|
||||
fabricPlayer.connection.disconnect(GrimACFabricLoaderPlugin.LOADER.getFabricMessageUtils().textLiteral(textReason));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSneaking() {
|
||||
return fabricPlayer.isShiftKeyDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSneaking(boolean isSneaking) {
|
||||
fabricPlayer.setShiftKeyDown(isSneaking);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return getSender().hasPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission, boolean defaultIfUnset) {
|
||||
return getSender().hasPermission(permission, defaultIfUnset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
if (CommonGrimArguments.USE_CHAT_FAST_BYPASS.value() && user != null) {
|
||||
user.sendMessage(message);
|
||||
} else {
|
||||
fabricPlayer.displayClientMessage(GrimACFabricLoaderPlugin.LOADER.getFabricMessageUtils().textLiteral(message), false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(Component message) {
|
||||
if (CommonGrimArguments.USE_CHAT_FAST_BYPASS.value() && user != null) {
|
||||
user.sendMessage(message);
|
||||
} else {
|
||||
fabricPlayer.displayClientMessage(GrimACFabricLoaderPlugin.LOADER.getFabricConversionUtil().toNativeText(message), false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return !fabricPlayer.hasDisconnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return fabricPlayer.getName().getString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateInventory() {
|
||||
fabricPlayer.containerMenu.broadcastChanges();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3d getPosition() {
|
||||
return new Vector3d(fabricPlayer.getX(), fabricPlayer.getY(), fabricPlayer.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformInventory getInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GrimEntity getVehicle() {
|
||||
Entity vehicle = fabricPlayer.getVehicle();
|
||||
return vehicle != null ? GrimACFabricLoaderPlugin.LOADER.getPlatformPlayerFactory().getPlatformEntity(vehicle) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameMode getGameMode() {
|
||||
return FabricConversionUtil.fromFabricGameMode(fabricPlayer.gameMode.getGameModeForPlayer());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGameMode(GameMode gameMode) {
|
||||
fabricPlayer.setGameMode(FabricConversionUtil.toFabricGameMode(gameMode));
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return fabricPlayer.getUUID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExternalPlayer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPluginMessage(String channelName, byte[] byteArray) {
|
||||
// You might want to use Fabric's networking system here
|
||||
// CustomPayloadS2CPacket packet = new CustomPayloadS2CPacket(
|
||||
// Identifier.of(channelName),
|
||||
// new PacketByteBuf(Unpooled.wrappedBuffer(byteArray))
|
||||
// );
|
||||
// fabricPlayer.networkHandler.sendPacket(packet);
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceNativePlayer(Object nativePlayerObject) {
|
||||
this.inventory.fabricPlayer = (ServerPlayer) nativePlayerObject;
|
||||
this.inventory.inventory = ((ServerPlayer) nativePlayerObject).inventory;
|
||||
this.fabricPlayer = (ServerPlayer) nativePlayerObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ServerPlayer getNative() {
|
||||
return this.fabricPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDead() {
|
||||
return fabricPlayer.isDeadOrDying();
|
||||
}
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.player;
|
||||
|
||||
import ac.grim.grimac.platform.api.player.OfflinePlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public class FabricOfflinePlatformPlayer implements OfflinePlatformPlayer {
|
||||
private final @NotNull UUID uniqueId;
|
||||
private final @NotNull String name;
|
||||
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return GrimACFabricLoaderPlugin.FABRIC_SERVER.getPlayerList().getPlayer(uniqueId) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof OfflinePlatformPlayer player && this.getUniqueId().equals(player.getUniqueId());
|
||||
}
|
||||
}
|
||||
-99
@@ -1,99 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.player;
|
||||
|
||||
import ac.grim.grimac.platform.api.entity.GrimEntity;
|
||||
import ac.grim.grimac.platform.api.player.AbstractPlatformPlayerFactory;
|
||||
import ac.grim.grimac.platform.api.player.OfflinePlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class FabricPlatformPlayerFactory extends AbstractPlatformPlayerFactory<ServerPlayer> {
|
||||
|
||||
private final Map<UUID, OfflinePlatformPlayer> offlinePlatformPlayerCache = new HashMap<>();
|
||||
private final Function<ServerPlayer, AbstractFabricPlatformPlayer> getPlayerFunction;
|
||||
private final Function<Entity, GrimEntity> getEntityFunction;
|
||||
private final Function<ServerPlayer, AbstractFabricPlatformInventory> getPlayerInventoryFunction;
|
||||
|
||||
@Override
|
||||
protected ServerPlayer getNativePlayer(@NotNull UUID uuid) {
|
||||
return GrimACFabricLoaderPlugin.FABRIC_SERVER.getPlayerList().getPlayer(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ServerPlayer getNativePlayer(@NotNull String name) {
|
||||
return GrimACFabricLoaderPlugin.FABRIC_SERVER.getPlayerList().getPlayerByName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractFabricPlatformPlayer createPlatformPlayer(@NotNull ServerPlayer nativePlayer) {
|
||||
return getPlayerFunction.apply(nativePlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UUID getPlayerUUID(@NotNull ServerPlayer nativePlayer) {
|
||||
return nativePlayer.getUUID();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<ServerPlayer> getNativeOnlinePlayers() {
|
||||
// Get the list of online players from the server
|
||||
return GrimACFabricLoaderPlugin.FABRIC_SERVER.getPlayerList().getPlayers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflinePlatformPlayer getOfflineFromUUID(@NotNull UUID uuid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflinePlatformPlayer getOfflineFromName(@NotNull String name) {
|
||||
OfflinePlatformPlayer result = this.getFromName(name);
|
||||
if (result == null) {
|
||||
GameProfile profile = null;
|
||||
// Only fetch an online UUID in online mode
|
||||
// TODO (cross-platform) add a config option for "offline-mode" servers with online-mode behind a proxy
|
||||
if (GrimACFabricLoaderPlugin.FABRIC_SERVER.usesAuthentication()) {
|
||||
// THIS CAN BLOCK THE CALLING THREAD!
|
||||
profile = GrimACFabricLoaderPlugin.LOADER.getPlatformServer().getProfileByName(name);
|
||||
}
|
||||
|
||||
result = this.getOfflinePlayer(profile != null
|
||||
// Use the GameProfile even when we get a UUID so we ensure we still have a name
|
||||
? profile
|
||||
// Make an OfflinePlayer using an offline mode UUID since the name has no profile
|
||||
: new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8)), name)
|
||||
);
|
||||
} else {
|
||||
this.offlinePlatformPlayerCache.remove(result.getUniqueId());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public OfflinePlatformPlayer getOfflinePlayer(GameProfile profile) {
|
||||
OfflinePlatformPlayer player = new FabricOfflinePlatformPlayer(profile.getId(), profile.getName());
|
||||
this.offlinePlatformPlayerCache.put(profile.getId(), player);
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceNativePlayer(@NotNull UUID uuid, @NotNull ServerPlayer serverPlayerEntity) {
|
||||
super.cache.getPlayer(uuid).replaceNativePlayer(serverPlayerEntity);
|
||||
}
|
||||
|
||||
public AbstractFabricPlatformInventory getPlatformInventory(ServerPlayer serverPlayerEntity) {
|
||||
return getPlayerInventoryFunction.apply(serverPlayerEntity);
|
||||
}
|
||||
|
||||
public GrimEntity getPlatformEntity(Entity entity) {
|
||||
return getEntityFunction.apply(entity);
|
||||
}
|
||||
}
|
||||
-185
@@ -1,185 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.resolver;
|
||||
|
||||
import ac.grim.grimac.api.plugin.BasicGrimPlugin;
|
||||
import ac.grim.grimac.api.plugin.GrimPlugin;
|
||||
import ac.grim.grimac.events.GrimExtensionManager;
|
||||
import ac.grim.grimac.platform.fabric.utils.message.JULoggerFactory;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.fabricmc.api.*;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import net.fabricmc.loader.api.entrypoint.EntrypointContainer;
|
||||
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint;
|
||||
import net.fabricmc.loader.api.metadata.Person;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Manages the registration of Fabric-specific resolvers with the GrimExtensionManager.
|
||||
* This class is designed to be instantiated once during plugin startup.
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public final class FabricResolverRegistrar {
|
||||
|
||||
private final GrimExtensionManager extensionManager;
|
||||
|
||||
// Cache to ensure we only create one GrimPlugin wrapper per Fabric ModContainer.
|
||||
private final Map<ModContainer, GrimPlugin> modContainerCache = new ConcurrentHashMap<>();
|
||||
private final Map<Class<?>, GrimPlugin> classCache = new ConcurrentHashMap<>();
|
||||
private final Map<Object, GrimPlugin> entrypointCache = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Registers all the Fabric-specific resolvers in order of performance (fastest to slowest).
|
||||
*/
|
||||
public void registerAll() {
|
||||
extensionManager.setFailureHandler(this::createFailureException);
|
||||
extensionManager.registerResolver(this::resolveModContainer);
|
||||
extensionManager.registerResolver(this::resolveStringId);
|
||||
extensionManager.registerResolver(this::resolveEntrypointInstance);
|
||||
extensionManager.registerResolver(this::resolveClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a shared, reusable function to handle the core logic of
|
||||
* converting a Fabric ModContainer to a GrimPlugin wrapper.
|
||||
*/
|
||||
private GrimPlugin resolveMod(ModContainer modContainer) {
|
||||
return modContainerCache.computeIfAbsent(modContainer, container -> {
|
||||
net.fabricmc.loader.api.metadata.ModMetadata metadata = container.getMetadata();
|
||||
String folderName = metadata.getId().equals("grimac") ? metadata.getName() : metadata.getId();
|
||||
return new BasicGrimPlugin(
|
||||
JULoggerFactory.createLogger(metadata.getName()),
|
||||
new File(FabricLoader.getInstance().getConfigDir().toFile(), folderName),
|
||||
metadata.getVersion().getFriendlyString(),
|
||||
metadata.getDescription(),
|
||||
metadata.getAuthors().stream().map(Person::getName).collect(Collectors.toList())
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolver #0: Direct ModContainer (fastest)
|
||||
*/
|
||||
private GrimPlugin resolveModContainer(Object context) {
|
||||
return (context instanceof ModContainer mc) ? resolveMod(mc) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolver #1: String Mod ID (very fast)
|
||||
*/
|
||||
private GrimPlugin resolveStringId(Object context) {
|
||||
if (context instanceof String modId) {
|
||||
// Mod IDs are enforced to always be fully lowercase
|
||||
return FabricLoader.getInstance().getModContainer(modId.toLowerCase(Locale.ROOT))
|
||||
.map(this::resolveMod)
|
||||
.orElse(null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolver #2: Mod Entrypoint Instance (slower, but cached)
|
||||
*/
|
||||
private GrimPlugin resolveEntrypointInstance(Object context) {
|
||||
// We only care about potential entrypoint instances
|
||||
if (context instanceof ModInitializer || context instanceof PreLaunchEntrypoint || context instanceof ClientModInitializer || context instanceof DedicatedServerModInitializer) {
|
||||
return entrypointCache.computeIfAbsent(context, this::findEntrypoint);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private GrimPlugin findEntrypoint(Object key) {
|
||||
GrimPlugin result;
|
||||
if ((result = findEntrypoint(key, ModInitializer.class, "main")) != null) return result;
|
||||
if ((result = findEntrypoint(key, PreLaunchEntrypoint.class, "preLaunch")) != null) return result;
|
||||
if ((result = findEntrypoint(key, ClientModInitializer.class, "client")) != null) return result;
|
||||
if ((result = findEntrypoint(key, DedicatedServerModInitializer.class, "server")) != null) return result;
|
||||
return null;
|
||||
}
|
||||
|
||||
private <T> GrimPlugin findEntrypoint(Object context, Class<T> entrypointClass, String entrypointKey) {
|
||||
if (entrypointClass.isInstance(context)) {
|
||||
for (EntrypointContainer<T> container : FabricLoader.getInstance().getEntrypointContainers(entrypointKey, entrypointClass)) {
|
||||
if (container.getEntrypoint() == context) {
|
||||
return resolveMod(container.getProvider());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolver #3: Class object (slowest - involves I/O, but cached)
|
||||
*/
|
||||
private GrimPlugin resolveClass(Object context) {
|
||||
if (context instanceof Class<?> clazz) {
|
||||
return classCache.computeIfAbsent(clazz, this::findClassProvider);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private GrimPlugin findClassProvider(Class<?> c) {
|
||||
try {
|
||||
// 1. Get the path to the physical JAR/directory the class was loaded from.
|
||||
// This is our ground truth.
|
||||
java.security.CodeSource codeSource = c.getProtectionDomain().getCodeSource();
|
||||
if (codeSource == null) return null;
|
||||
java.net.URL sourceUrl = codeSource.getLocation();
|
||||
if (sourceUrl == null) return null;
|
||||
Path sourcePath = Paths.get(sourceUrl.toURI());
|
||||
|
||||
// 2. Iterate through all mods and check if the class's source path
|
||||
// matches the physical path of the mod's container.
|
||||
for (ModContainer modContainer : FabricLoader.getInstance().getAllMods()) {
|
||||
for (Path modRootPath : modContainer.getRootPaths()) {
|
||||
URI modUri = modRootPath.toUri();
|
||||
Path modPhysicalPath = null;
|
||||
|
||||
// 3. Determine the mod's physical path based on its URI scheme.
|
||||
if ("file".equals(modUri.getScheme())) {
|
||||
modPhysicalPath = modRootPath;
|
||||
} else if ("jar".equals(modUri.getScheme())) {
|
||||
String schemeSpecificPart = modUri.getSchemeSpecificPart();
|
||||
int separatorIndex = schemeSpecificPart.indexOf("!/");
|
||||
if (separatorIndex != -1) {
|
||||
String jarUriString = schemeSpecificPart.substring(0, separatorIndex);
|
||||
modPhysicalPath = Paths.get(new URI(jarUriString));
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Perform the reliable file comparison.
|
||||
if (modPhysicalPath != null && Files.isSameFile(modPhysicalPath, sourcePath)) {
|
||||
return resolveMod(modContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (URISyntaxException | IOException | NullPointerException e) {
|
||||
// Fail gracefully.
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private RuntimeException createFailureException(Object failedContext) {
|
||||
String message = """
|
||||
Failed to resolve GrimPlugin context from the provided object of type '%s'.
|
||||
|
||||
Please ensure you are passing one of the following:
|
||||
- The main instance of your mod (e.g., 'this' from your ModInitializer class).
|
||||
- The mod ID as a String (e.g., "my-mod-id").
|
||||
- Any Class from your mod's JAR file (e.g., MyListener.class).
|
||||
- A pre-existing GrimPlugin instance.
|
||||
""".formatted(failedContext.getClass().getName());
|
||||
return new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.scheduler;
|
||||
|
||||
import ac.grim.grimac.api.plugin.GrimPlugin;
|
||||
import ac.grim.grimac.platform.api.scheduler.AsyncScheduler;
|
||||
import ac.grim.grimac.platform.api.scheduler.PlatformScheduler;
|
||||
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class FabricAsyncScheduler implements AsyncScheduler {
|
||||
private final Map<Thread, InternalAsyncTask> asyncTasks = new HashMap<>();
|
||||
private final GrimPlugin plugin;
|
||||
|
||||
record InternalAsyncTask(GrimPlugin plugin, Runnable runnable) {}
|
||||
|
||||
public FabricAsyncScheduler(GrimPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runNow(@NotNull GrimPlugin plugin, @NotNull Runnable task) {
|
||||
Thread thread = new Thread(task);
|
||||
Runnable cancellationTask = () -> {
|
||||
thread.interrupt();
|
||||
asyncTasks.remove(thread);
|
||||
};
|
||||
asyncTasks.put(thread, new InternalAsyncTask(plugin, cancellationTask));
|
||||
thread.start();
|
||||
return new FabricTaskHandle(cancellationTask, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runDelayed(@NotNull GrimPlugin plugin, @NotNull Runnable task, long delay, @NotNull TimeUnit timeUnit) {
|
||||
long delayMillis = timeUnit.toMillis(delay);
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
Thread.sleep(delayMillis);
|
||||
task.run();
|
||||
} catch (InterruptedException e) {
|
||||
// Handle interruption
|
||||
}
|
||||
});
|
||||
Runnable cancellationTask = () -> {
|
||||
thread.interrupt();
|
||||
asyncTasks.remove(thread);
|
||||
};
|
||||
asyncTasks.put(thread, new InternalAsyncTask(plugin, cancellationTask));
|
||||
thread.start();
|
||||
return new FabricTaskHandle(cancellationTask, false); // false for async
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull Runnable task, long delay, long period, @NotNull TimeUnit timeUnit) {
|
||||
long delayMillis = timeUnit.toMillis(delay);
|
||||
long periodMillis = timeUnit.toMillis(period);
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
Thread.sleep(delayMillis);
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
task.run();
|
||||
Thread.sleep(periodMillis);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// Handle interruption
|
||||
}
|
||||
});
|
||||
Runnable cancellationTask = () -> {
|
||||
thread.interrupt();
|
||||
asyncTasks.remove(thread);
|
||||
};
|
||||
asyncTasks.put(thread, new InternalAsyncTask(plugin, cancellationTask));
|
||||
thread.start();
|
||||
return new FabricTaskHandle(cancellationTask, false); // false for async
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull Runnable task, long initialDelayTicks, long periodTicks) {
|
||||
return runAtFixedRate(plugin, task,
|
||||
PlatformScheduler.convertTicksToTime(initialDelayTicks, TimeUnit.MILLISECONDS),
|
||||
PlatformScheduler.convertTicksToTime(periodTicks, TimeUnit.MILLISECONDS),
|
||||
TimeUnit.MILLISECONDS); // Convert ticks to milliseconds
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(@NotNull GrimPlugin plugin) {
|
||||
// Cancel tasks only for the specified plugin
|
||||
Iterator<Map.Entry<Thread, InternalAsyncTask>> iterator = asyncTasks.entrySet().iterator();
|
||||
List<Runnable> cancellationTasks = new ArrayList<>();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<Thread, InternalAsyncTask> entry = iterator.next();
|
||||
if (entry.getValue().plugin().equals(plugin)) {
|
||||
cancellationTasks.add(entry.getValue().runnable());
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
for (Runnable cancellationTask : cancellationTasks) {
|
||||
cancellationTask.run();
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelAll() {
|
||||
List<Runnable> cancellationTasks = asyncTasks.values().stream()
|
||||
.map(InternalAsyncTask::runnable)
|
||||
.toList();
|
||||
asyncTasks.clear();
|
||||
|
||||
for (Runnable cancellationTask : cancellationTasks) {
|
||||
cancellationTask.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
-85
@@ -1,85 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.scheduler;
|
||||
|
||||
import ac.grim.grimac.api.plugin.GrimPlugin;
|
||||
import ac.grim.grimac.platform.api.entity.GrimEntity;
|
||||
import ac.grim.grimac.platform.api.scheduler.EntityScheduler;
|
||||
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class FabricEntityScheduler implements EntityScheduler {
|
||||
// TODO (Cross-platform) (Threading) try to make this not Concurrent
|
||||
private final Map<FabricPlatformScheduler.ScheduledTask, Runnable> taskMap = new ConcurrentHashMap<>();
|
||||
private final GrimPlugin plugin;
|
||||
|
||||
public FabricEntityScheduler(GrimPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
ServerTickEvents.END_SERVER_TICK.register(this::handleTasks);
|
||||
}
|
||||
|
||||
private void handleTasks(MinecraftServer server) {
|
||||
FabricPlatformScheduler.handleSyncTasks(taskMap, server, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull GrimEntity entity, @NotNull GrimPlugin plugin, @NotNull Runnable run, @Nullable Runnable retired, long delay) {
|
||||
runDelayed(entity, plugin, run, retired, delay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle run(@NotNull GrimEntity entity, @NotNull GrimPlugin plugin, @NotNull Runnable task, @Nullable Runnable retired) {
|
||||
return runDelayed(entity, plugin, task, retired, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runDelayed(@NotNull GrimEntity entity, @NotNull GrimPlugin plugin, @NotNull Runnable task, @Nullable Runnable retired, long delayTicks) {
|
||||
FabricPlatformScheduler.ScheduledTask scheduledTask = new FabricPlatformScheduler.ScheduledTask(
|
||||
() -> {
|
||||
task.run();
|
||||
if (retired != null && entity.isDead()) {
|
||||
retired.run();
|
||||
}
|
||||
},
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER.getTickCount() + delayTicks,
|
||||
0,
|
||||
false,
|
||||
plugin
|
||||
);
|
||||
Runnable cancellationTask = () -> taskMap.remove(scheduledTask);
|
||||
taskMap.put(scheduledTask, cancellationTask);
|
||||
return new FabricTaskHandle(cancellationTask, true); // true for sync
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runAtFixedRate(@NotNull GrimEntity entity, @NotNull GrimPlugin plugin, @NotNull Runnable task, @Nullable Runnable retired, long initialDelayTicks, long periodTicks) {
|
||||
FabricPlatformScheduler.ScheduledTask scheduledTask = new FabricPlatformScheduler.ScheduledTask(
|
||||
() -> {
|
||||
task.run();
|
||||
if (retired != null && entity.isDead()) {
|
||||
retired.run();
|
||||
}
|
||||
},
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER.getTickCount() + initialDelayTicks,
|
||||
periodTicks,
|
||||
true,
|
||||
plugin
|
||||
);
|
||||
Runnable cancellationTask = () -> taskMap.remove(scheduledTask);
|
||||
taskMap.put(scheduledTask, cancellationTask);
|
||||
return new FabricTaskHandle(cancellationTask, true); // true for sync
|
||||
}
|
||||
|
||||
public void cancel(@NotNull GrimPlugin plugin) {
|
||||
FabricPlatformScheduler.cancelPluginTasks(taskMap, plugin);
|
||||
}
|
||||
|
||||
public void cancelAll() {
|
||||
FabricPlatformScheduler.cancelAllTasks(taskMap);
|
||||
}
|
||||
}
|
||||
-76
@@ -1,76 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.scheduler;
|
||||
|
||||
import ac.grim.grimac.api.plugin.GrimPlugin;
|
||||
import ac.grim.grimac.platform.api.scheduler.GlobalRegionScheduler;
|
||||
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class FabricGlobalRegionScheduler implements GlobalRegionScheduler {
|
||||
// TODO (Cross-platform) (Threading) try to make this not Concurrent
|
||||
private final Map<FabricPlatformScheduler.ScheduledTask, Runnable> taskMap = new ConcurrentHashMap<>();
|
||||
private final GrimPlugin plugin;
|
||||
|
||||
public FabricGlobalRegionScheduler(GrimPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
// Register the task handler to run on server tick
|
||||
ServerTickEvents.END_SERVER_TICK.register(this::handleTasks);
|
||||
}
|
||||
|
||||
private void handleTasks(MinecraftServer server) {
|
||||
FabricPlatformScheduler.handleSyncTasks(taskMap, server, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull GrimPlugin plugin, @NotNull Runnable run) {
|
||||
run(plugin, run);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle run(@NotNull GrimPlugin plugin, @NotNull Runnable task) {
|
||||
return runDelayed(plugin, task, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runDelayed(@NotNull GrimPlugin plugin, @NotNull Runnable task, long delay) {
|
||||
FabricPlatformScheduler.ScheduledTask scheduledTask = new FabricPlatformScheduler.ScheduledTask(
|
||||
task,
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER.getTickCount() + delay,
|
||||
0,
|
||||
false,
|
||||
plugin
|
||||
);
|
||||
Runnable cancellationTask = () -> taskMap.remove(scheduledTask);
|
||||
taskMap.put(scheduledTask, cancellationTask);
|
||||
return new FabricTaskHandle(cancellationTask, true); // true for sync
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull Runnable task, long initialDelayTicks, long periodTicks) {
|
||||
FabricPlatformScheduler.ScheduledTask scheduledTask = new FabricPlatformScheduler.ScheduledTask(
|
||||
task,
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER.getTickCount() + initialDelayTicks,
|
||||
periodTicks,
|
||||
true,
|
||||
plugin
|
||||
);
|
||||
Runnable cancellationTask = () -> taskMap.remove(scheduledTask);
|
||||
taskMap.put(scheduledTask, cancellationTask);
|
||||
return new FabricTaskHandle(cancellationTask, true); // true for sync
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(@NotNull GrimPlugin plugin) {
|
||||
FabricPlatformScheduler.cancelPluginTasks(taskMap, plugin);
|
||||
}
|
||||
|
||||
// New method to cancel all tasks
|
||||
public void cancelAll() {
|
||||
FabricPlatformScheduler.cancelAllTasks(taskMap);
|
||||
}
|
||||
}
|
||||
-133
@@ -1,133 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.scheduler;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.plugin.GrimPlugin;
|
||||
import ac.grim.grimac.platform.api.scheduler.*;
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class FabricPlatformScheduler implements PlatformScheduler {
|
||||
private final FabricAsyncScheduler asyncScheduler;
|
||||
private final FabricGlobalRegionScheduler globalRegionScheduler;
|
||||
private final FabricEntityScheduler entityScheduler;
|
||||
private final FabricRegionScheduler regionScheduler;
|
||||
|
||||
public FabricPlatformScheduler() {
|
||||
GrimPlugin plugin = GrimAPI.INSTANCE.getGrimPlugin();
|
||||
this.asyncScheduler = new FabricAsyncScheduler(plugin);
|
||||
this.globalRegionScheduler = new FabricGlobalRegionScheduler(plugin);
|
||||
this.entityScheduler = new FabricEntityScheduler(plugin);
|
||||
this.regionScheduler = new FabricRegionScheduler(plugin);
|
||||
}
|
||||
|
||||
// Shared method to handle synchronous tasks
|
||||
// Add this to FabricPlatformScheduler.java
|
||||
public static final ThreadLocal<Boolean> EXECUTING_TASK = ThreadLocal.withInitial(() -> false);
|
||||
|
||||
protected static void handleSyncTasks(Map<ScheduledTask, Runnable> taskMap, MinecraftServer server, GrimPlugin plugin) {
|
||||
Iterator<ScheduledTask> iterator = taskMap.keySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
ScheduledTask task = iterator.next();
|
||||
if (server.getTickCount() >= task.nextRunTick) {
|
||||
try {
|
||||
EXECUTING_TASK.set(true);
|
||||
task.task.run();
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("Error executing scheduled task ", e);
|
||||
} finally {
|
||||
EXECUTING_TASK.set(false);
|
||||
}
|
||||
|
||||
if (task.isPeriodic) {
|
||||
task.nextRunTick = server.getTickCount() + task.period;
|
||||
} else {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel tasks for a specific plugin
|
||||
protected static void cancelPluginTasks(Map<ScheduledTask, Runnable> taskMap, GrimPlugin plugin) {
|
||||
Iterator<Map.Entry<ScheduledTask, Runnable>> iterator = taskMap.entrySet().iterator();
|
||||
List<Runnable> cancellationTasks = new ArrayList<>();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<ScheduledTask, Runnable> entry = iterator.next();
|
||||
if (entry.getKey().plugin.equals(plugin)) {
|
||||
cancellationTasks.add(entry.getValue());
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
for (Runnable cancellationTask : cancellationTasks) {
|
||||
cancellationTask.run();
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel all tasks (renamed from cancelAllTasks)
|
||||
protected static void cancelAllTasks(Map<?, Runnable> taskMap) {
|
||||
List<Runnable> cancellationTasks = new ArrayList<>(taskMap.values());
|
||||
taskMap.clear();
|
||||
for (Runnable cancellationTask : cancellationTasks) {
|
||||
cancellationTask.run();
|
||||
}
|
||||
}
|
||||
|
||||
protected static void scheduleTask(Map<ScheduledTask, Runnable> taskMap, GrimPlugin plugin, Runnable task, long initialDelayTicks, long periodTicks, boolean isPeriodic) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull AsyncScheduler getAsyncScheduler() {
|
||||
return asyncScheduler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull GlobalRegionScheduler getGlobalRegionScheduler() {
|
||||
return globalRegionScheduler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntityScheduler getEntityScheduler() {
|
||||
return entityScheduler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull RegionScheduler getRegionScheduler() {
|
||||
return regionScheduler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down all schedulers and cancels all pending tasks.
|
||||
* This method should be called when the server is shutting down.
|
||||
*/
|
||||
public void shutdown() {
|
||||
asyncScheduler.cancelAll();
|
||||
globalRegionScheduler.cancelAll();
|
||||
entityScheduler.cancelAll();
|
||||
regionScheduler.cancelAll();
|
||||
}
|
||||
|
||||
protected static class ScheduledTask {
|
||||
final Runnable task;
|
||||
final long period;
|
||||
final boolean isPeriodic;
|
||||
final GrimPlugin plugin; // Add plugin reference
|
||||
long nextRunTick;
|
||||
|
||||
ScheduledTask(Runnable task, long nextRunTick, long period, boolean isPeriodic, GrimPlugin plugin) {
|
||||
this.task = task;
|
||||
this.nextRunTick = nextRunTick;
|
||||
this.period = period;
|
||||
this.isPeriodic = isPeriodic;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
}
|
||||
}
|
||||
-94
@@ -1,94 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.scheduler;
|
||||
|
||||
import ac.grim.grimac.api.plugin.GrimPlugin;
|
||||
import ac.grim.grimac.platform.api.scheduler.RegionScheduler;
|
||||
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
|
||||
import ac.grim.grimac.platform.api.world.PlatformWorld;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.utils.math.Location;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class FabricRegionScheduler implements RegionScheduler {
|
||||
// TODO (Cross-platform) (Threading) try to make this not Concurrent
|
||||
private final Map<FabricPlatformScheduler.ScheduledTask, Runnable> taskMap = new ConcurrentHashMap<>();
|
||||
private final GrimPlugin plugin;
|
||||
|
||||
public FabricRegionScheduler(GrimPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
ServerTickEvents.END_SERVER_TICK.register(this::handleTasks);
|
||||
}
|
||||
|
||||
private void handleTasks(MinecraftServer server) {
|
||||
FabricPlatformScheduler.handleSyncTasks(taskMap, server, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull GrimPlugin plugin, @NotNull PlatformWorld world, int chunkX, int chunkZ, @NotNull Runnable run) {
|
||||
run(plugin, world, chunkX, chunkZ, run);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull GrimPlugin plugin, @NotNull Location location, @NotNull Runnable run) {
|
||||
execute(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, run);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle run(@NotNull GrimPlugin plugin, @NotNull PlatformWorld world, int chunkX, int chunkZ, @NotNull Runnable task) {
|
||||
return runDelayed(plugin, world, chunkX, chunkZ, task, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle run(@NotNull GrimPlugin plugin, @NotNull Location location, @NotNull Runnable task) {
|
||||
return run(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runDelayed(@NotNull GrimPlugin plugin, @NotNull PlatformWorld world, int chunkX, int chunkZ, @NotNull Runnable task, long delayTicks) {
|
||||
FabricPlatformScheduler.ScheduledTask scheduledTask = new FabricPlatformScheduler.ScheduledTask(
|
||||
task,
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER.getTickCount() + delayTicks,
|
||||
0,
|
||||
false,
|
||||
plugin
|
||||
);
|
||||
Runnable cancellationTask = () -> taskMap.remove(scheduledTask);
|
||||
taskMap.put(scheduledTask, cancellationTask);
|
||||
return new FabricTaskHandle(cancellationTask, true);
|
||||
}
|
||||
@Override
|
||||
public TaskHandle runDelayed(@NotNull GrimPlugin plugin, @NotNull Location location, @NotNull Runnable task, long delayTicks) {
|
||||
return runDelayed(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task, delayTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull PlatformWorld world, int chunkX, int chunkZ, @NotNull Runnable task, long initialDelayTicks, long periodTicks) {
|
||||
FabricPlatformScheduler.ScheduledTask scheduledTask = new FabricPlatformScheduler.ScheduledTask(
|
||||
task,
|
||||
GrimACFabricLoaderPlugin.FABRIC_SERVER.getTickCount() + initialDelayTicks,
|
||||
periodTicks,
|
||||
true,
|
||||
plugin
|
||||
);
|
||||
Runnable cancellationTask = () -> taskMap.remove(scheduledTask);
|
||||
taskMap.put(scheduledTask, cancellationTask);
|
||||
return new FabricTaskHandle(cancellationTask, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull Location location, @NotNull Runnable task, long initialDelayTicks, long periodTicks) {
|
||||
return runAtFixedRate(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task, initialDelayTicks, periodTicks);
|
||||
}
|
||||
|
||||
public void cancel(@NotNull GrimPlugin plugin) {
|
||||
FabricPlatformScheduler.cancelPluginTasks(taskMap, plugin);
|
||||
}
|
||||
|
||||
public void cancelAll() {
|
||||
FabricPlatformScheduler.cancelAllTasks(taskMap);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.scheduler;
|
||||
|
||||
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
|
||||
import lombok.Getter;
|
||||
|
||||
public class FabricTaskHandle implements TaskHandle {
|
||||
private final Runnable cancellationTask;
|
||||
@Getter
|
||||
private boolean cancelled;
|
||||
@Getter
|
||||
private final boolean sync;
|
||||
|
||||
public FabricTaskHandle(Runnable cancellationTask) {
|
||||
this.cancellationTask = cancellationTask;
|
||||
this.sync = false;
|
||||
}
|
||||
|
||||
public FabricTaskHandle(Runnable cancellationTask, boolean sync) {
|
||||
this.cancellationTask = cancellationTask;
|
||||
this.sync = sync;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
this.cancellationTask.run();
|
||||
this.cancelled = true;
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.sender;
|
||||
|
||||
import ac.grim.grimac.platform.api.permissions.PermissionDefaultValue;
|
||||
import ac.grim.grimac.platform.api.sender.Sender;
|
||||
import ac.grim.grimac.platform.api.sender.SenderFactory;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.utils.message.IFabricMessageUtil;
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
import net.fabricmc.fabric.api.util.TriState;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.commands.CommandSource;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.rcon.RconConsoleSource;
|
||||
import org.incendo.cloud.SenderMapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class FabricSenderFactory extends SenderFactory<CommandSourceStack> implements SenderMapper<CommandSourceStack, Sender> {
|
||||
|
||||
private final Map<String, PermissionDefaultValue> permissionDefaults = new HashMap<>();
|
||||
private static final IFabricMessageUtil fabricMessageUtils = GrimACFabricLoaderPlugin.LOADER.getFabricMessageUtils();
|
||||
|
||||
@Override
|
||||
protected UUID getUniqueId(CommandSourceStack commandSource) {
|
||||
if (commandSource.getEntity() != null) {
|
||||
return commandSource.getEntity().getUUID();
|
||||
}
|
||||
return Sender.CONSOLE_UUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getName(CommandSourceStack commandSource) {
|
||||
String name = commandSource.getTextName();
|
||||
if (commandSource.getEntity() != null && name.equals("Server")) {
|
||||
return Sender.CONSOLE_NAME;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sendMessage(CommandSourceStack sender, String message) {
|
||||
fabricMessageUtils.sendMessage(sender, fabricMessageUtils.textLiteral(message), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sendMessage(CommandSourceStack sender, Component message) {
|
||||
fabricMessageUtils.sendMessage(sender, GrimACFabricLoaderPlugin.LOADER.getFabricConversionUtil().toNativeText(message), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasPermission(CommandSourceStack commandSource, String node) {
|
||||
TriState permissionValue = Permissions.getPermissionValue(commandSource, node);
|
||||
if (permissionValue != TriState.DEFAULT) {
|
||||
return permissionValue.get();
|
||||
}
|
||||
|
||||
// Check registered default value
|
||||
PermissionDefaultValue defaultValue = permissionDefaults.get(node);
|
||||
if (defaultValue == null) {
|
||||
return permissionValue.get(); // Fallback to provided default if unset
|
||||
}
|
||||
|
||||
return switch (defaultValue) {
|
||||
case TRUE -> true;
|
||||
case FALSE -> false;
|
||||
case OP -> commandSource.hasPermission(GrimACFabricLoaderPlugin.FABRIC_SERVER.getOperatorUserPermissionLevel());
|
||||
case NOT_OP -> !commandSource.hasPermission(GrimACFabricLoaderPlugin.FABRIC_SERVER.getOperatorUserPermissionLevel());
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasPermission(CommandSourceStack commandSource, String node, boolean defaultIfUnset) {
|
||||
return Permissions.check(commandSource, node, defaultIfUnset);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performCommand(CommandSourceStack sender, String command) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isConsole(CommandSourceStack sender) {
|
||||
CommandSource output = sender.source;
|
||||
return output == sender.getServer() || // Console
|
||||
output.getClass() == RconConsoleSource.class || // Rcon
|
||||
(output == CommandSource.NULL && sender.getTextName().isEmpty()); // Functions
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPlayer(CommandSourceStack sender) {
|
||||
return sender.getEntity() instanceof ServerPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Sender map(@NotNull CommandSourceStack base) {
|
||||
return this.wrap(base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CommandSourceStack reverse(@NotNull Sender mapped) {
|
||||
return this.unwrap(mapped);
|
||||
}
|
||||
|
||||
public void registerPermissionDefault(String permission, PermissionDefaultValue defaultValue) {
|
||||
permissionDefaults.put(permission, defaultValue);
|
||||
}
|
||||
}
|
||||
-89
@@ -1,89 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.utils.convert;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.protocol.player.InteractionHand;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public abstract class FabricConversionUtil implements IFabricConversionUtil {
|
||||
|
||||
private IFabricConversionUtil fabricConversionUtilSupplier;
|
||||
|
||||
private final Function<net.minecraft.world.item.ItemStack, ItemStack> itemStackMapperFunction = (fabricStack) -> {
|
||||
// if (fabricStack.isEmpty()) {
|
||||
// return ItemStack.EMPTY;
|
||||
// }
|
||||
//
|
||||
// // Allocate a ByteBuf
|
||||
// ByteBuf buffer = PooledByteBufAllocator.DEFAULT.buffer();
|
||||
// try {
|
||||
// // Obtain the DynamicRegistryManager (you need to provide this from your context)
|
||||
// DynamicRegistryManager registryManager = GrimACFabricLoaderPlugin.FABRIC_SERVER.getRegistryManager(); // Replace with actual method to get registry manager
|
||||
//
|
||||
// // Create a RegistryByteBuf
|
||||
// RegistryByteBuf registryByteBuf = new RegistryByteBuf(buffer, registryManager);
|
||||
//
|
||||
// // Encode the ItemStack using the appropriate PacketCodec
|
||||
// net.minecraft.item.ItemStack.PACKET_CODEC.encode(registryByteBuf, fabricStack);
|
||||
//
|
||||
// // Create a PacketWrapper to read the ItemStack back (if needed)
|
||||
// PacketWrapper<?> wrapper = PacketWrapper.createUniversalPacketWrapper(buffer);
|
||||
// return wrapper.readItemStack();
|
||||
// } catch (Exception e) {
|
||||
// // Handle encoding errors
|
||||
// LogUtil.error("Failed to encode ItemStack: {}" + fabricStack, e);
|
||||
// return ItemStack.EMPTY;
|
||||
// } finally {
|
||||
// // Release the ByteBuf to prevent memory leaks
|
||||
// ByteBufHelper.release(buffer);
|
||||
// }
|
||||
throw new UnsupportedOperationException();
|
||||
};
|
||||
private final Function<Component, net.minecraft.network.chat.Component> nativeTextMapperFunction = (component) -> {
|
||||
throw new UnsupportedOperationException();
|
||||
// Text.Serialization.fromJsonTree(GsonComponentSerializer.gson().serializeToTree(component), DynamicRegistryManager.EMPTY);
|
||||
};
|
||||
//
|
||||
|
||||
public ItemStack fromFabricItemStack(net.minecraft.world.item.ItemStack fabricStack) {
|
||||
// return itemStackMapperFunction.apply(fabricStack);
|
||||
return fabricConversionUtilSupplier.fromFabricItemStack(fabricStack);
|
||||
}
|
||||
|
||||
public net.minecraft.network.chat.Component toNativeText(Component component) {
|
||||
// return nativeTextMapperFunction.apply(component);
|
||||
return fabricConversionUtilSupplier.toNativeText(component);
|
||||
}
|
||||
|
||||
public static GameType toFabricGameMode(GameMode gameMode) {
|
||||
return switch (gameMode) {
|
||||
case CREATIVE -> GameType.CREATIVE;
|
||||
case SURVIVAL -> GameType.SURVIVAL;
|
||||
case ADVENTURE -> GameType.ADVENTURE;
|
||||
case SPECTATOR -> GameType.SPECTATOR;
|
||||
};
|
||||
}
|
||||
|
||||
public static GameMode fromFabricGameMode(GameType fabricGameMode) {
|
||||
return switch (fabricGameMode) {
|
||||
case CREATIVE -> GameMode.CREATIVE;
|
||||
case SURVIVAL -> GameMode.SURVIVAL;
|
||||
case ADVENTURE -> GameMode.ADVENTURE;
|
||||
case SPECTATOR -> GameMode.SPECTATOR;
|
||||
default -> throw new IllegalArgumentException("Unknown Fabric GameMode: " + fabricGameMode);
|
||||
};
|
||||
}
|
||||
|
||||
@Contract(value = "null -> null; !null -> !null", pure = true)
|
||||
public static @Nullable InteractionHand fromFabricHand(@Nullable net.minecraft.world.InteractionHand hand) {
|
||||
return hand == null ? null : switch (hand) {
|
||||
case OFF_HAND -> InteractionHand.OFF_HAND;
|
||||
case MAIN_HAND -> InteractionHand.MAIN_HAND;
|
||||
};
|
||||
}
|
||||
}
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.utils.convert;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public interface IFabricConversionUtil {
|
||||
ItemStack fromFabricItemStack(net.minecraft.world.item.ItemStack fabricStack);
|
||||
net.minecraft.network.chat.Component toNativeText(Component component);
|
||||
}
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.utils.message;
|
||||
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
public interface IFabricMessageUtil {
|
||||
Component textLiteral(String message);
|
||||
void sendMessage(CommandSourceStack target, Component message, boolean overlay);
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.utils.message;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class JULoggerFactory {
|
||||
public static Logger createLogger(String name) {
|
||||
try {
|
||||
return new Slf4jBackedJULogger(name);
|
||||
} catch (NoClassDefFoundError | Exception ignored) {
|
||||
}
|
||||
try {
|
||||
return new Log4jBackedJULogger(name);
|
||||
} catch (NoClassDefFoundError | Exception ignored) {
|
||||
}
|
||||
|
||||
return Logger.getLogger(name);
|
||||
}
|
||||
}
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.utils.message;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class Log4jBackedJULogger extends Logger {
|
||||
private final org.apache.logging.log4j.Logger log4jLogger;
|
||||
|
||||
protected Log4jBackedJULogger(String name) {
|
||||
super(name, null);
|
||||
this.log4jLogger = org.apache.logging.log4j.LogManager.getLogger(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Level level, String msg) {
|
||||
if (level == Level.SEVERE) {
|
||||
log4jLogger.error(msg);
|
||||
} else if (level == Level.WARNING) {
|
||||
log4jLogger.warn(msg);
|
||||
} else if (level == Level.INFO) {
|
||||
log4jLogger.info(msg);
|
||||
} else if (level == Level.CONFIG || level == Level.FINE) {
|
||||
log4jLogger.debug(msg);
|
||||
} else if (level == Level.FINER || level == Level.FINEST) {
|
||||
log4jLogger.trace(msg);
|
||||
} else {
|
||||
log4jLogger.info(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Level level, String msg, Throwable thrown) {
|
||||
if (level == Level.SEVERE) {
|
||||
log4jLogger.error(msg, thrown);
|
||||
} else if (level == Level.WARNING) {
|
||||
log4jLogger.warn(msg, thrown);
|
||||
} else if (level == Level.INFO) {
|
||||
log4jLogger.info(msg, thrown);
|
||||
} else if (level == Level.CONFIG || level == Level.FINE) {
|
||||
log4jLogger.debug(msg, thrown);
|
||||
} else if (level == Level.FINER || level == Level.FINEST) {
|
||||
log4jLogger.trace(msg, thrown);
|
||||
} else {
|
||||
log4jLogger.info(msg, thrown);
|
||||
}
|
||||
}
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.utils.message;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.MarkerFactory;
|
||||
|
||||
public class Slf4jBackedJULogger extends Logger {
|
||||
private final org.slf4j.Logger slf4jLogger;
|
||||
private static final Marker MARKER = MarkerFactory.getMarker("JUL");
|
||||
|
||||
public Slf4jBackedJULogger(String name) {
|
||||
super(name, null);
|
||||
this.slf4jLogger = LoggerFactory.getLogger(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Level level, String msg) {
|
||||
if (level == Level.SEVERE) {
|
||||
slf4jLogger.error(MARKER, msg);
|
||||
} else if (level == Level.WARNING) {
|
||||
slf4jLogger.warn(MARKER, msg);
|
||||
} else if (level == Level.INFO) {
|
||||
slf4jLogger.info(MARKER, msg);
|
||||
} else if (level == Level.CONFIG || level == Level.FINE) {
|
||||
slf4jLogger.debug(MARKER, msg);
|
||||
} else if (level == Level.FINER || level == Level.FINEST) {
|
||||
slf4jLogger.trace(MARKER, msg);
|
||||
} else {
|
||||
slf4jLogger.info(MARKER, msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Level level, String msg, Throwable thrown) {
|
||||
if (level.equals(Level.SEVERE)) {
|
||||
slf4jLogger.error(MARKER, msg, thrown);
|
||||
} else if (level.equals(Level.WARNING)) {
|
||||
slf4jLogger.warn(MARKER, msg, thrown);
|
||||
} else if (level.equals(Level.INFO)) {
|
||||
slf4jLogger.info(MARKER, msg, thrown);
|
||||
} else if (level.equals(Level.CONFIG) || level.equals(Level.FINE)) {
|
||||
slf4jLogger.debug(MARKER, msg, thrown);
|
||||
} else if (level.equals(Level.FINER) || level.equals(Level.FINEST)) {
|
||||
slf4jLogger.trace(MARKER, msg, thrown);
|
||||
} else {
|
||||
slf4jLogger.info(MARKER, msg, thrown);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.utils.metrics;
|
||||
|
||||
import ac.grim.grimac.utils.anticheat.LogUtil;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BStatsConfig {
|
||||
private static final String HEADER = """
|
||||
# bStats (https://bStats.org) collects some basic information for plugin authors, like how
|
||||
# many people use their plugin and their total player count. It's recommended to keep bStats
|
||||
# enabled, but if you're not comfortable with this, you can turn this setting off. There is no
|
||||
# performance penalty associated with having metrics enabled, and data sent to bStats is fully
|
||||
# anonymous.
|
||||
""";
|
||||
|
||||
public static Config loadConfig() {
|
||||
File bStatsFolder = new File(FabricLoader.getInstance().getConfigDir().toString(), "bStats");
|
||||
File configFile = new File(bStatsFolder, "config.yml");
|
||||
|
||||
DumperOptions options = new DumperOptions();
|
||||
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
options.setPrettyFlow(true);
|
||||
Yaml yaml = new Yaml(options);
|
||||
|
||||
Map<String, Object> data;
|
||||
Config config = new Config();
|
||||
|
||||
try {
|
||||
if (!configFile.exists()) {
|
||||
bStatsFolder.mkdirs();
|
||||
|
||||
// Create default config
|
||||
data = new LinkedHashMap<>();
|
||||
data.put("enabled", true);
|
||||
data.put("serverUuid", UUID.randomUUID().toString());
|
||||
data.put("logFailedRequests", false);
|
||||
data.put("logSentData", false);
|
||||
data.put("logResponseStatusText", false);
|
||||
|
||||
// Write config with header
|
||||
try (Writer writer = new OutputStreamWriter(new FileOutputStream(configFile), StandardCharsets.UTF_8)) {
|
||||
writer.write(HEADER);
|
||||
yaml.dump(data, writer);
|
||||
}
|
||||
} else {
|
||||
// Load existing config
|
||||
data = yaml.load(new FileInputStream(configFile));
|
||||
if (data == null) {
|
||||
data = new LinkedHashMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
// Map the data to Config object
|
||||
config.enabled = getBoolean(data, "enabled", true);
|
||||
config.serverUuid = getString(data, "serverUuid", UUID.randomUUID().toString());
|
||||
config.logFailedRequests = getBoolean(data, "logFailedRequests", false);
|
||||
config.logSentData = getBoolean(data, "logSentData", false);
|
||||
config.logResponseStatusText = getBoolean(data, "logResponseStatusText", false);
|
||||
|
||||
} catch (IOException e) {
|
||||
LogUtil.error("Failed to load bStats config. Using default values.", e);
|
||||
// Fallback to default values
|
||||
config.enabled = true;
|
||||
config.serverUuid = UUID.randomUUID().toString();
|
||||
config.logFailedRequests = false;
|
||||
config.logSentData = false;
|
||||
config.logResponseStatusText = false;
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
private static boolean getBoolean(Map<String, Object> map, String key, boolean defaultValue) {
|
||||
Object value = map.get(key);
|
||||
return value instanceof Boolean ? (Boolean) value : defaultValue;
|
||||
}
|
||||
|
||||
private static String getString(Map<String, Object> map, String key, String defaultValue) {
|
||||
Object value = map.get(key);
|
||||
return value instanceof String ? (String) value : defaultValue;
|
||||
}
|
||||
|
||||
// Your existing Config class
|
||||
public static class Config {
|
||||
public boolean enabled = true;
|
||||
public String serverUuid;
|
||||
public boolean logFailedRequests = false;
|
||||
public boolean logSentData = false;
|
||||
public boolean logResponseStatusText = false;
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.utils.metrics;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public abstract class CustomChart {
|
||||
|
||||
private final String chartId;
|
||||
|
||||
protected CustomChart(String chartId) {
|
||||
if (chartId == null) {
|
||||
throw new IllegalArgumentException("chartId must not be null");
|
||||
}
|
||||
this.chartId = chartId;
|
||||
}
|
||||
|
||||
public JsonObjectBuilder.JsonObject getRequestJsonObject(
|
||||
BiConsumer<String, Throwable> errorLogger, boolean logErrors) {
|
||||
JsonObjectBuilder builder = new JsonObjectBuilder();
|
||||
builder.appendField("chartId", chartId);
|
||||
try {
|
||||
JsonObjectBuilder.JsonObject data = getChartData();
|
||||
if (data == null) {
|
||||
// If the data is null we don't send the chart.
|
||||
return null;
|
||||
}
|
||||
builder.appendField("data", data);
|
||||
} catch (Throwable t) {
|
||||
if (logErrors) {
|
||||
errorLogger.accept("Failed to get data for custom chart with id " + chartId, t);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
protected abstract JsonObjectBuilder.JsonObject getChartData() throws Exception;
|
||||
}
|
||||
-210
@@ -1,210 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.utils.metrics;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* An extremely simple JSON builder.
|
||||
*
|
||||
* <p>While this class is neither feature-rich nor the most performant one, it's sufficient enough
|
||||
* for its use-case.
|
||||
*/
|
||||
public class JsonObjectBuilder {
|
||||
|
||||
private StringBuilder builder = new StringBuilder();
|
||||
|
||||
private boolean hasAtLeastOneField = false;
|
||||
|
||||
public JsonObjectBuilder() {
|
||||
builder.append("{");
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes the given string like stated in <a href="https://www.ietf.org/rfc/rfc4627.txt">https://www.ietf.org/rfc/rfc4627.txt</a>.
|
||||
*
|
||||
* <p>This method escapes only the necessary characters '"', '\'. and '\u0000' - '\u001F'.
|
||||
* Compact escapes are not used (e.g., '\n' is escaped as "\u000a" and not as "\n").
|
||||
*
|
||||
* @param value The value to escape.
|
||||
* @return The escaped value.
|
||||
*/
|
||||
private static String escape(String value) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < value.length(); i++) {
|
||||
char c = value.charAt(i);
|
||||
if (c == '"') {
|
||||
builder.append("\\\"");
|
||||
} else if (c == '\\') {
|
||||
builder.append("\\\\");
|
||||
} else if (c <= '\u000F') {
|
||||
builder.append("\\u000").append(Integer.toHexString(c));
|
||||
} else if (c <= '\u001F') {
|
||||
builder.append("\\u00").append(Integer.toHexString(c));
|
||||
} else {
|
||||
builder.append(c);
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a null field to the JSON.
|
||||
*
|
||||
* @param key The key of the field.
|
||||
* @return A reference to this object.
|
||||
*/
|
||||
public JsonObjectBuilder appendNull(String key) {
|
||||
appendFieldUnescaped(key, "null");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a string field to the JSON.
|
||||
*
|
||||
* @param key The key of the field.
|
||||
* @param value The value of the field.
|
||||
* @return A reference to this object.
|
||||
*/
|
||||
public JsonObjectBuilder appendField(String key, String value) {
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException("JSON value must not be null");
|
||||
}
|
||||
appendFieldUnescaped(key, "\"" + escape(value) + "\"");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends an integer field to the JSON.
|
||||
*
|
||||
* @param key The key of the field.
|
||||
* @param value The value of the field.
|
||||
* @return A reference to this object.
|
||||
*/
|
||||
public JsonObjectBuilder appendField(String key, int value) {
|
||||
appendFieldUnescaped(key, String.valueOf(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends an object to the JSON.
|
||||
*
|
||||
* @param key The key of the field.
|
||||
* @param object The object.
|
||||
* @return A reference to this object.
|
||||
*/
|
||||
public JsonObjectBuilder appendField(String key, JsonObject object) {
|
||||
if (object == null) {
|
||||
throw new IllegalArgumentException("JSON object must not be null");
|
||||
}
|
||||
appendFieldUnescaped(key, object.toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a string array to the JSON.
|
||||
*
|
||||
* @param key The key of the field.
|
||||
* @param values The string array.
|
||||
* @return A reference to this object.
|
||||
*/
|
||||
public JsonObjectBuilder appendField(String key, String[] values) {
|
||||
if (values == null) {
|
||||
throw new IllegalArgumentException("JSON values must not be null");
|
||||
}
|
||||
String escapedValues =
|
||||
Arrays.stream(values)
|
||||
.map(value -> "\"" + escape(value) + "\"")
|
||||
.collect(Collectors.joining(","));
|
||||
appendFieldUnescaped(key, "[" + escapedValues + "]");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends an integer array to the JSON.
|
||||
*
|
||||
* @param key The key of the field.
|
||||
* @param values The integer array.
|
||||
* @return A reference to this object.
|
||||
*/
|
||||
public JsonObjectBuilder appendField(String key, int[] values) {
|
||||
if (values == null) {
|
||||
throw new IllegalArgumentException("JSON values must not be null");
|
||||
}
|
||||
String escapedValues =
|
||||
Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(","));
|
||||
appendFieldUnescaped(key, "[" + escapedValues + "]");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends an object array to the JSON.
|
||||
*
|
||||
* @param key The key of the field.
|
||||
* @param values The integer array.
|
||||
* @return A reference to this object.
|
||||
*/
|
||||
public JsonObjectBuilder appendField(String key, JsonObject[] values) {
|
||||
if (values == null) {
|
||||
throw new IllegalArgumentException("JSON values must not be null");
|
||||
}
|
||||
String escapedValues =
|
||||
Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(","));
|
||||
appendFieldUnescaped(key, "[" + escapedValues + "]");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a field to the object.
|
||||
*
|
||||
* @param key The key of the field.
|
||||
* @param escapedValue The escaped value of the field.
|
||||
*/
|
||||
private void appendFieldUnescaped(String key, String escapedValue) {
|
||||
if (builder == null) {
|
||||
throw new IllegalStateException("JSON has already been built");
|
||||
}
|
||||
if (key == null) {
|
||||
throw new IllegalArgumentException("JSON key must not be null");
|
||||
}
|
||||
if (hasAtLeastOneField) {
|
||||
builder.append(",");
|
||||
}
|
||||
builder.append("\"").append(escape(key)).append("\":").append(escapedValue);
|
||||
hasAtLeastOneField = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the JSON string and invalidates this builder.
|
||||
*
|
||||
* @return The built JSON string.
|
||||
*/
|
||||
public JsonObject build() {
|
||||
if (builder == null) {
|
||||
throw new IllegalStateException("JSON has already been built");
|
||||
}
|
||||
JsonObject object = new JsonObject(builder.append("}").toString());
|
||||
builder = null;
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* A super simple representation of a JSON object.
|
||||
*
|
||||
* <p>This class only exists to make methods of the {@link JsonObjectBuilder} type-safe and not
|
||||
* allow a raw string inputs for methods like {@link JsonObjectBuilder#appendField(String,
|
||||
* JsonObject)}.
|
||||
*/
|
||||
public static class JsonObject {
|
||||
|
||||
private final String value;
|
||||
|
||||
private JsonObject(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.utils.metrics;
|
||||
|
||||
public interface Metrics {
|
||||
|
||||
void shutdown();
|
||||
}
|
||||
@@ -1,278 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.utils.metrics;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
public class MetricsBase {
|
||||
|
||||
/**
|
||||
* The version of the Metrics class.
|
||||
*/
|
||||
public static final String METRICS_VERSION = "3.1.0";
|
||||
|
||||
private static final String REPORT_URL = "https://bStats.org/api/v2/data/%s";
|
||||
|
||||
private final ScheduledExecutorService scheduler;
|
||||
|
||||
private final String platform;
|
||||
|
||||
private final String serverUuid;
|
||||
|
||||
private final int serviceId;
|
||||
|
||||
private final Consumer<JsonObjectBuilder> appendPlatformDataConsumer;
|
||||
|
||||
private final Consumer<JsonObjectBuilder> appendServiceDataConsumer;
|
||||
|
||||
private final Consumer<Runnable> submitTaskConsumer;
|
||||
|
||||
private final Supplier<Boolean> checkServiceEnabledSupplier;
|
||||
|
||||
private final BiConsumer<String, Throwable> errorLogger;
|
||||
|
||||
private final Consumer<String> infoLogger;
|
||||
|
||||
private final boolean logErrors;
|
||||
|
||||
private final boolean logSentData;
|
||||
|
||||
private final boolean logResponseStatusText;
|
||||
|
||||
private final Set<CustomChart> customCharts = new HashSet<>();
|
||||
|
||||
private final boolean enabled;
|
||||
|
||||
/**
|
||||
* Creates a new MetricsBase class instance.
|
||||
*
|
||||
* @param platform The platform of the service.
|
||||
* @param serviceId The id of the service.
|
||||
* @param serverUuid The server uuid.
|
||||
* @param enabled Whether or not data sending is enabled.
|
||||
* @param appendPlatformDataConsumer A consumer that receives a {@code JsonObjectBuilder} and
|
||||
* appends all platform-specific data.
|
||||
* @param appendServiceDataConsumer A consumer that receives a {@code JsonObjectBuilder} and
|
||||
* appends all service-specific data.
|
||||
* @param submitTaskConsumer A consumer that takes a runnable with the submit task. This can be
|
||||
* used to delegate the data collection to a another thread to prevent errors caused by
|
||||
* concurrency. Can be {@code null}.
|
||||
* @param checkServiceEnabledSupplier A supplier to check if the service is still enabled.
|
||||
* @param errorLogger A consumer that accepts log message and an error.
|
||||
* @param infoLogger A consumer that accepts info log messages.
|
||||
* @param logErrors Whether or not errors should be logged.
|
||||
* @param logSentData Whether or not the sent data should be logged.
|
||||
* @param logResponseStatusText Whether or not the response status text should be logged.
|
||||
* @param skipRelocateCheck Whether or not the relocate check should be skipped.
|
||||
*/
|
||||
public MetricsBase(
|
||||
String platform,
|
||||
String serverUuid,
|
||||
int serviceId,
|
||||
boolean enabled,
|
||||
Consumer<JsonObjectBuilder> appendPlatformDataConsumer,
|
||||
Consumer<JsonObjectBuilder> appendServiceDataConsumer,
|
||||
Consumer<Runnable> submitTaskConsumer,
|
||||
Supplier<Boolean> checkServiceEnabledSupplier,
|
||||
BiConsumer<String, Throwable> errorLogger,
|
||||
Consumer<String> infoLogger,
|
||||
boolean logErrors,
|
||||
boolean logSentData,
|
||||
boolean logResponseStatusText,
|
||||
boolean skipRelocateCheck) {
|
||||
this.scheduler = getScheduledThreadPoolExecutor();
|
||||
this.platform = platform;
|
||||
this.serverUuid = serverUuid;
|
||||
this.serviceId = serviceId;
|
||||
this.enabled = enabled;
|
||||
this.appendPlatformDataConsumer = appendPlatformDataConsumer;
|
||||
this.appendServiceDataConsumer = appendServiceDataConsumer;
|
||||
this.submitTaskConsumer = submitTaskConsumer;
|
||||
this.checkServiceEnabledSupplier = checkServiceEnabledSupplier;
|
||||
this.errorLogger = errorLogger;
|
||||
this.infoLogger = infoLogger;
|
||||
this.logErrors = logErrors;
|
||||
this.logSentData = logSentData;
|
||||
this.logResponseStatusText = logResponseStatusText;
|
||||
if (!skipRelocateCheck) {
|
||||
checkRelocation();
|
||||
}
|
||||
if (enabled) {
|
||||
// WARNING: Removing the option to opt-out will get your plugin banned from
|
||||
// bStats
|
||||
startSubmitting();
|
||||
}
|
||||
}
|
||||
|
||||
private static @NotNull ScheduledThreadPoolExecutor getScheduledThreadPoolExecutor() {
|
||||
ScheduledThreadPoolExecutor scheduler =
|
||||
new ScheduledThreadPoolExecutor(
|
||||
1,
|
||||
task -> {
|
||||
Thread thread = new Thread(task, "bStats-Metrics");
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
});
|
||||
// We want delayed tasks (non-periodic) that will execute in the future to be
|
||||
// cancelled when the scheduler is shutdown.
|
||||
// Otherwise, we risk preventing the server from shutting down even when
|
||||
// MetricsBase#shutdown() is called
|
||||
scheduler.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gzips the given string.
|
||||
*
|
||||
* @param str The string to gzip.
|
||||
* @return The gzipped string.
|
||||
*/
|
||||
private static byte[] compress(final String str) throws IOException {
|
||||
if (str == null) {
|
||||
return null;
|
||||
}
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) {
|
||||
gzip.write(str.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
|
||||
public void addCustomChart(CustomChart chart) {
|
||||
this.customCharts.add(chart);
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
scheduler.shutdown();
|
||||
}
|
||||
|
||||
private void startSubmitting() {
|
||||
final Runnable submitTask =
|
||||
() -> {
|
||||
if (!enabled || !checkServiceEnabledSupplier.get()) {
|
||||
// Submitting data or service is disabled
|
||||
scheduler.shutdown();
|
||||
return;
|
||||
}
|
||||
if (submitTaskConsumer != null) {
|
||||
submitTaskConsumer.accept(this::submitData);
|
||||
} else {
|
||||
this.submitData();
|
||||
}
|
||||
};
|
||||
// Many servers tend to restart at a fixed time at xx:00 which causes an uneven
|
||||
// distribution of requests on the
|
||||
// bStats backend. To circumvent this problem, we introduce some randomness into
|
||||
// the initial and second delay.
|
||||
// WARNING: You must not modify and part of this Metrics class, including the
|
||||
// submit delay or frequency!
|
||||
// WARNING: Modifying this code will get your plugin banned on bStats. Just
|
||||
// don't do it!
|
||||
long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3));
|
||||
long secondDelay = (long) (1000 * 60 * (Math.random() * 30));
|
||||
scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS);
|
||||
scheduler.scheduleAtFixedRate(
|
||||
submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private void submitData() {
|
||||
final JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder();
|
||||
appendPlatformDataConsumer.accept(baseJsonBuilder);
|
||||
final JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder();
|
||||
appendServiceDataConsumer.accept(serviceJsonBuilder);
|
||||
JsonObjectBuilder.JsonObject[] chartData =
|
||||
customCharts.stream()
|
||||
.map(customChart -> customChart.getRequestJsonObject(errorLogger, logErrors))
|
||||
.filter(Objects::nonNull)
|
||||
.toArray(JsonObjectBuilder.JsonObject[]::new);
|
||||
serviceJsonBuilder.appendField("id", serviceId);
|
||||
serviceJsonBuilder.appendField("customCharts", chartData);
|
||||
baseJsonBuilder.appendField("service", serviceJsonBuilder.build());
|
||||
baseJsonBuilder.appendField("serverUUID", serverUuid);
|
||||
baseJsonBuilder.appendField("metricsVersion", METRICS_VERSION);
|
||||
JsonObjectBuilder.JsonObject data = baseJsonBuilder.build();
|
||||
scheduler.execute(
|
||||
() -> {
|
||||
try {
|
||||
// Send the data
|
||||
sendData(data);
|
||||
} catch (Exception e) {
|
||||
// Something went wrong! :(
|
||||
if (logErrors) {
|
||||
errorLogger.accept("Could not submit bStats metrics data", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void sendData(JsonObjectBuilder.JsonObject data) throws Exception {
|
||||
if (logSentData) {
|
||||
infoLogger.accept("Sent bStats metrics data: " + data.toString());
|
||||
}
|
||||
String url = String.format(REPORT_URL, platform);
|
||||
HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();
|
||||
// Compress the data to save bandwidth
|
||||
byte[] compressedData = compress(data.toString());
|
||||
connection.setRequestMethod("POST");
|
||||
connection.addRequestProperty("Accept", "application/json");
|
||||
connection.addRequestProperty("Connection", "close");
|
||||
connection.addRequestProperty("Content-Encoding", "gzip");
|
||||
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setRequestProperty("User-Agent", "Metrics-Service/1");
|
||||
connection.setDoOutput(true);
|
||||
try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
|
||||
outputStream.write(compressedData);
|
||||
}
|
||||
StringBuilder builder = new StringBuilder();
|
||||
try (BufferedReader bufferedReader =
|
||||
new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
|
||||
String line;
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
builder.append(line);
|
||||
}
|
||||
}
|
||||
if (logResponseStatusText) {
|
||||
infoLogger.accept("Sent data to bStats and received response: " + builder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the class was properly relocated.
|
||||
*/
|
||||
private void checkRelocation() {
|
||||
// You can use the property to disable the check in your test environment
|
||||
if (System.getProperty("bstats.relocatecheck") == null
|
||||
|| !System.getProperty("bstats.relocatecheck").equals("false")) {
|
||||
// Maven's Relocate is clever and changes strings, too. So we have to use this
|
||||
// little "trick" ... :D
|
||||
final String defaultPackage =
|
||||
new String(new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's'});
|
||||
final String examplePackage =
|
||||
new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
|
||||
// We want to make sure no one just copy & pastes the example and uses the wrong
|
||||
// package names
|
||||
if (MetricsBase.class.getPackage().getName().startsWith(defaultPackage)
|
||||
|| MetricsBase.class.getPackage().getName().startsWith(examplePackage)) {
|
||||
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.utils.metrics;
|
||||
|
||||
/*
|
||||
* This Metrics class was auto-generated and can be copied into your project if you are
|
||||
* not using a build tool like Gradle or Maven for dependency management.
|
||||
*
|
||||
* IMPORTANT: You are not allowed to modify this class, except changing the package.
|
||||
*
|
||||
* Disallowed modifications include but are not limited to:
|
||||
* - Remove the option for users to opt-out
|
||||
* - Change the frequency for data submission
|
||||
* - Obfuscate the code (every obfuscator should allow you to make an exception for specific files)
|
||||
* - Reformat the code (if you use a linter, add an exception)
|
||||
*
|
||||
* Violations will result in a ban of your plugin and account from bStats.
|
||||
*/
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.api.plugin.GrimPlugin;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class MetricsFabric implements Metrics {
|
||||
|
||||
private final MetricsBase metricsBase;
|
||||
|
||||
/**
|
||||
* Creates a new Metrics instance.
|
||||
*
|
||||
* @param serviceId The id of the service. It can be found at <a
|
||||
* href="https://bstats.org/what-is-my-plugin-id">What is my plugin id?</a>
|
||||
*/
|
||||
public MetricsFabric(GrimPlugin plugin, int serviceId) {
|
||||
// Get the config file
|
||||
BStatsConfig.Config config = BStatsConfig.loadConfig();
|
||||
|
||||
// Load the data
|
||||
boolean enabled = config.enabled;
|
||||
String serverUUID = config.serverUuid;
|
||||
boolean logErrors = config.logFailedRequests;
|
||||
boolean logSentData = config.logSentData;
|
||||
boolean logResponseStatusText = config.logResponseStatusText;
|
||||
|
||||
metricsBase =
|
||||
new // See https://github.com/Bastian/bstats-metrics/pull/126
|
||||
// See https://github.com/Bastian/bstats-metrics/pull/126
|
||||
// See https://github.com/Bastian/bstats-metrics/pull/126
|
||||
// See https://github.com/Bastian/bstats-metrics/pull/126
|
||||
// See https://github.com/Bastian/bstats-metrics/pull/126
|
||||
// See https://github.com/Bastian/bstats-metrics/pull/126
|
||||
// See https://github.com/Bastian/bstats-metrics/pull/126
|
||||
MetricsBase(
|
||||
"fabric",
|
||||
serverUUID,
|
||||
serviceId,
|
||||
enabled,
|
||||
this::appendPlatformData,
|
||||
this::appendServiceData,
|
||||
submitDataTask -> GrimAPI.INSTANCE.getScheduler().getAsyncScheduler().runNow(plugin, submitDataTask),
|
||||
() -> true,
|
||||
(message, error) -> plugin.getLogger().log(Level.WARNING, message, error),
|
||||
(message) -> plugin.getLogger().log(Level.INFO, message),
|
||||
logErrors,
|
||||
logSentData,
|
||||
logResponseStatusText,
|
||||
false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down the underlying scheduler service.
|
||||
*/
|
||||
public void shutdown() {
|
||||
metricsBase.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a custom chart.
|
||||
*
|
||||
* @param chart The chart to add.
|
||||
*/
|
||||
public void addCustomChart(CustomChart chart) {
|
||||
metricsBase.addCustomChart(chart);
|
||||
}
|
||||
|
||||
private void appendPlatformData(JsonObjectBuilder builder) {
|
||||
builder.appendField("playerAmount", getPlayerAmount());
|
||||
builder.appendField("onlineMode", GrimACFabricLoaderPlugin.FABRIC_SERVER.usesAuthentication() ? 0 : 1);
|
||||
builder.appendField("bukkitVersion", GrimAPI.INSTANCE.getPlatformServer().getPlatformImplementationString());
|
||||
builder.appendField("bukkitName", "Fabric");
|
||||
builder.appendField("javaVersion", System.getProperty("java.version"));
|
||||
builder.appendField("osName", System.getProperty("os.name"));
|
||||
builder.appendField("osArch", System.getProperty("os.arch"));
|
||||
builder.appendField("osVersion", System.getProperty("os.version"));
|
||||
builder.appendField("coreCount", Runtime.getRuntime().availableProcessors());
|
||||
}
|
||||
|
||||
private void appendServiceData(JsonObjectBuilder builder) {
|
||||
builder.appendField("pluginVersion", FabricLoader.getInstance().getModContainer("grimac").get().getMetadata().getVersion().getFriendlyString());
|
||||
}
|
||||
|
||||
private int getPlayerAmount() {
|
||||
if (GrimACFabricLoaderPlugin.FABRIC_SERVER.isRunning()) {
|
||||
return GrimACFabricLoaderPlugin.FABRIC_SERVER.getPlayerCount();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
package ac.grim.grimac.platform.fabric.utils.thread;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class FabricFutureUtil {
|
||||
public static <U> CompletableFuture<U> supplySync(Supplier<U> entityTeleportSupplier) {
|
||||
CompletableFuture<U> ret = new CompletableFuture<>();
|
||||
GrimAPI.INSTANCE.getScheduler().getGlobalRegionScheduler().run(GrimAPI.INSTANCE.getGrimPlugin(),
|
||||
() -> ret.complete(entityTeleportSupplier.get()));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "grimac",
|
||||
"version": "${version}",
|
||||
"name": "GrimAC",
|
||||
"description": "Libre simulation anticheat designed for 1.21 with 1.8-1.21 support, powered by PacketEvents 2.0.",
|
||||
"authors": [
|
||||
"GrimAC"
|
||||
],
|
||||
"license": "GPLv3",
|
||||
"environment": "server",
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"ac.grim.grimac.platform.fabric.GrimACFabricEntryPoint"
|
||||
],
|
||||
"preLaunch": [
|
||||
"ac.grim.grimac.platform.fabric.GrimACFabricEntryPoint"
|
||||
]
|
||||
},
|
||||
"mixins": [
|
||||
"grimac.mixins.json"
|
||||
],
|
||||
"accessWidener": "grimac.accesswidener",
|
||||
"depends": {
|
||||
"fabricloader": "\u003e\u003d0.16",
|
||||
"fabric-lifecycle-events-v1": "*",
|
||||
"cloud": "*",
|
||||
"packetevents": "*"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
accessWidener v2 named
|
||||
accessible field net/minecraft/server/level/ServerLevel serverLevelData Lnet/minecraft/world/level/storage/ServerLevelData;
|
||||
accessible field net/minecraft/commands/CommandSourceStack source Lnet/minecraft/commands/CommandSource;
|
||||
accessible field net/minecraft/world/entity/player/Player inventory Lnet/minecraft/world/entity/player/Inventory;
|
||||
accessible field net/minecraft/world/entity/Entity level Lnet/minecraft/world/level/Level; # Required in newer versions, even though public in older ones
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8",
|
||||
"package": "ac.grim.grimac.platform.fabric.mixins",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"mixins": [
|
||||
"LevelChunkMixin",
|
||||
"ServerLevelMixin",
|
||||
"ServerPlayerMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
Vendored
+93
-93
@@ -1,93 +1,93 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
+1
-21
@@ -12,20 +12,6 @@ dependencyResolutionManagement {
|
||||
|
||||
pluginManagement {
|
||||
repositories {
|
||||
// For the Fabric Loom plugin
|
||||
exclusiveContent {
|
||||
forRepository {
|
||||
maven {
|
||||
name = "FabricMC"
|
||||
url = uri("https://maven.fabricmc.net/")
|
||||
}
|
||||
}
|
||||
filter {
|
||||
includeModule("fabric-loom", "fabric-loom.gradle.plugin")
|
||||
includeGroupByRegex("net.fabricmc.*")
|
||||
}
|
||||
}
|
||||
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
@@ -60,12 +46,6 @@ if (gradle.startParameter.isBuildScan) {
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "grimac"
|
||||
rootProject.name = "LightningGrim"
|
||||
include("common")
|
||||
include("bukkit")
|
||||
include("fabric")
|
||||
include(":fabric:mc1161")
|
||||
include(":fabric:mc1171")
|
||||
include(":fabric:mc1194")
|
||||
include(":fabric:mc1205")
|
||||
include(":fabric:mc1216")
|
||||
Reference in new issue
Block a user