From db1a194e1f3b1c8eeae75a06837f1d05859cbade Mon Sep 17 00:00:00 2001
From: TT432 <2437315224@qq.com>
Date: Sat, 14 Sep 2024 22:59:53 +0800
Subject: [PATCH] :sparkles: rpc
---
README.md | 21 ++-
build.gradle | 15 +-
gradle.properties | 2 +-
src/main/java/io/github/tt432/chin/Chin.java | 6 +
.../io/github/tt432/chin/rpc/api/Rpc.java | 47 +++++++
.../tt432/chin/rpc/api/RpcSourceRegister.java | 51 +++++++
.../tt432/chin/rpc/api/RpcSourceType.java | 25 ++++
.../github/tt432/chin/rpc/impl/RpcAspect.java | 41 ++++++
.../tt432/chin/rpc/impl/RpcManager.java | 132 ++++++++++++++++++
.../chin/rpc/impl/RpcMethodIdMapPacket.java | 36 +++++
.../chin/rpc/impl/RpcNetworkHandler.java | 52 +++++++
.../tt432/chin/rpc/impl/RpcNetworkPacket.java | 51 +++++++
.../github/tt432/chin/util/ChinNetworks.java | 31 ++++
.../resources/META-INF/neoforge.mods.toml | 4 +-
src/main/resources/chin.mixins.json | 14 ++
15 files changed, 523 insertions(+), 5 deletions(-)
create mode 100644 src/main/java/io/github/tt432/chin/rpc/api/Rpc.java
create mode 100644 src/main/java/io/github/tt432/chin/rpc/api/RpcSourceRegister.java
create mode 100644 src/main/java/io/github/tt432/chin/rpc/api/RpcSourceType.java
create mode 100644 src/main/java/io/github/tt432/chin/rpc/impl/RpcAspect.java
create mode 100644 src/main/java/io/github/tt432/chin/rpc/impl/RpcManager.java
create mode 100644 src/main/java/io/github/tt432/chin/rpc/impl/RpcMethodIdMapPacket.java
create mode 100644 src/main/java/io/github/tt432/chin/rpc/impl/RpcNetworkHandler.java
create mode 100644 src/main/java/io/github/tt432/chin/rpc/impl/RpcNetworkPacket.java
create mode 100644 src/main/java/io/github/tt432/chin/util/ChinNetworks.java
create mode 100644 src/main/resources/chin.mixins.json
diff --git a/README.md b/README.md
index 1fff8c5..1d3071b 100644
--- a/README.md
+++ b/README.md
@@ -18,4 +18,23 @@ Tuple - a heterogeneous list
TupleCodec - Codec for Tuple
-ChinExtraCodecs - util class for Codec
\ No newline at end of file
+ChinExtraCodecs - util class for Codec
+
+### Rpc
+
+Chin's rpc using [AspectJ](https://eclipse.dev/aspectj/).
+
+build.gradle:
+
+```groovy
+plugins {
+ // ...
+ id "io.freefair.aspectj.post-compile-weaving" version aspectj_gradle_plugin_version
+}
+
+dependencies {
+ // ...
+ implementation("org.aspectj:aspectjrt:{aspectj_version}")
+ aspect implementation("io.github.tt432:chin:{chin_version}")
+}
+```
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index ba235a4..192f435 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,8 +3,10 @@ plugins {
id 'eclipse'
id 'idea'
id 'maven-publish'
- id 'net.neoforged.gradle.userdev' version '7.0.145'
+ id 'net.neoforged.gradle.userdev' version '7.0.163'
id 'signing'
+ id "io.freefair.lombok" version "8.6"
+ id "io.freefair.aspectj.post-compile-weaving" version "8.10"
}
tasks.named('wrapper', Wrapper).configure {
@@ -33,6 +35,11 @@ java.toolchain.languageVersion = JavaLanguageVersion.of(21)
//minecraft.accessTransformers.file rootProject.file('src/main/resources/META-INF/accesstransformer.cfg')
//minecraft.accessTransformers.entry public net.minecraft.client.Minecraft textureManager # textureManager
+configurations {
+ libraries {}
+ implementation.extendsFrom libraries
+}
+
// Default run configurations.
// These can be tweaked, removed, or duplicated as needed.
runs {
@@ -51,6 +58,10 @@ runs {
systemProperty 'forge.logging.console.level', 'debug'
modSource project.sourceSets.main
+
+ dependencies {
+ runtime project.configurations.libraries
+ }
}
client {
@@ -114,6 +125,8 @@ dependencies {
testImplementation "org.junit.jupiter:junit-jupiter:5.10.3"
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
+
+ jarJar(libraries("org.aspectj:aspectjrt:1.9.21.1"))
}
// This block of code expands all declared replace properties in the specified resource targets.
diff --git a/gradle.properties b/gradle.properties
index 7d4f38f..154437c 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -32,7 +32,7 @@ mod_name=Chin
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=MIT
# The mod version. See https://semver.org/
-mod_version=1.0.1
+mod_version=21.0.1
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
diff --git a/src/main/java/io/github/tt432/chin/Chin.java b/src/main/java/io/github/tt432/chin/Chin.java
index e64efb1..1d903f7 100644
--- a/src/main/java/io/github/tt432/chin/Chin.java
+++ b/src/main/java/io/github/tt432/chin/Chin.java
@@ -1,5 +1,7 @@
package io.github.tt432.chin;
+import io.github.tt432.chin.rpc.api.RpcSourceRegister;
+import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.common.Mod;
/**
@@ -8,4 +10,8 @@
@Mod(Chin.MOD_ID)
public class Chin {
public static final String MOD_ID = "chin";
+
+ public Chin(IEventBus bus) {
+ RpcSourceRegister.CHIN_DEFERRED_REGISTER.register(bus);
+ }
}
diff --git a/src/main/java/io/github/tt432/chin/rpc/api/Rpc.java b/src/main/java/io/github/tt432/chin/rpc/api/Rpc.java
new file mode 100644
index 0000000..c847634
--- /dev/null
+++ b/src/main/java/io/github/tt432/chin/rpc/api/Rpc.java
@@ -0,0 +1,47 @@
+package io.github.tt432.chin.rpc.api;
+
+import io.github.tt432.chin.rpc.impl.RpcAspect;
+import net.neoforged.api.distmarker.Dist;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * example:
+ *
{@code
+ * class MyBlockEntity extends BlockEntity {
+ * @Rpc(CLIENT)
+ * public void clickClick() {
+ * // do something
+ * }
+ * }
+ * }
+ *
+ * the method will send RpcNetworkPacket to server. equals:
+ *
+ * {@code
+ * class MyBlockEntity extends BlockEntity {
+ * public void clickClick() {
+ * if (isClientSide()) {
+ * // send packet
+ * } else {
+ * // do something
+ * }
+ * }
+ * }
+ * }
+ *
+ * @author TT432
+ * @see RpcAspect
+ * @see RpcSourceRegister
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Rpc {
+ /**
+ * @return sender side
+ */
+ Dist value();
+}
diff --git a/src/main/java/io/github/tt432/chin/rpc/api/RpcSourceRegister.java b/src/main/java/io/github/tt432/chin/rpc/api/RpcSourceRegister.java
new file mode 100644
index 0000000..672bfce
--- /dev/null
+++ b/src/main/java/io/github/tt432/chin/rpc/api/RpcSourceRegister.java
@@ -0,0 +1,51 @@
+package io.github.tt432.chin.rpc.api;
+
+import io.github.tt432.chin.Chin;
+import io.github.tt432.chin.util.ChinNetworks;
+import lombok.experimental.UtilityClass;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.Registry;
+import net.minecraft.resources.ResourceKey;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.block.entity.BlockEntity;
+import net.neoforged.bus.api.SubscribeEvent;
+import net.neoforged.fml.common.EventBusSubscriber;
+import net.neoforged.neoforge.registries.DeferredHolder;
+import net.neoforged.neoforge.registries.DeferredRegister;
+import net.neoforged.neoforge.registries.NewRegistryEvent;
+import net.neoforged.neoforge.registries.RegistryBuilder;
+
+/**
+ * @author TT432
+ */
+@UtilityClass
+@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD)
+public class RpcSourceRegister {
+ public final ResourceKey>> RPC_SOURCE_TYPE_KEY =
+ ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(Chin.MOD_ID, "rpc_source_type"));
+ public final Registry> REGISTRY = new RegistryBuilder<>(RPC_SOURCE_TYPE_KEY).sync(true).create();
+
+ public final DeferredRegister> CHIN_DEFERRED_REGISTER = DeferredRegister.create(RPC_SOURCE_TYPE_KEY, Chin.MOD_ID);
+
+ public final DeferredHolder, RpcSourceType> BLOCK_ENTITY =
+ CHIN_DEFERRED_REGISTER.register("block_entity", () -> new RpcSourceType<>(
+ BlockEntity.class,
+ be -> be.getBlockPos().asLong(),
+ (ctx, id) -> {
+ BlockPos pos = BlockPos.of(id);
+ Level level = ChinNetworks.getLevel(ctx);
+
+ if (level.isLoaded(pos)) {
+ return level.getBlockEntity(pos);
+ }
+
+ return null;
+ }
+ ));
+
+ @SubscribeEvent
+ public void onEvent(NewRegistryEvent event) {
+ event.register(REGISTRY);
+ }
+}
diff --git a/src/main/java/io/github/tt432/chin/rpc/api/RpcSourceType.java b/src/main/java/io/github/tt432/chin/rpc/api/RpcSourceType.java
new file mode 100644
index 0000000..8d91983
--- /dev/null
+++ b/src/main/java/io/github/tt432/chin/rpc/api/RpcSourceType.java
@@ -0,0 +1,25 @@
+package io.github.tt432.chin.rpc.api;
+
+import net.neoforged.neoforge.network.handling.IPayloadContext;
+
+import javax.annotation.Nullable;
+
+/**
+ * @author TT432
+ */
+public record RpcSourceType(
+ Class clazz,
+ IdGetter idGetter,
+ ObjectGetter objectGetter
+) {
+ @FunctionalInterface
+ public interface IdGetter {
+ long getId(T object);
+ }
+
+ @FunctionalInterface
+ public interface ObjectGetter {
+ @Nullable
+ T getObject(IPayloadContext context, long id);
+ }
+}
diff --git a/src/main/java/io/github/tt432/chin/rpc/impl/RpcAspect.java b/src/main/java/io/github/tt432/chin/rpc/impl/RpcAspect.java
new file mode 100644
index 0000000..c96b9ca
--- /dev/null
+++ b/src/main/java/io/github/tt432/chin/rpc/impl/RpcAspect.java
@@ -0,0 +1,41 @@
+package io.github.tt432.chin.rpc.impl;
+
+import io.github.tt432.chin.rpc.api.Rpc;
+import io.github.tt432.chin.util.ChinNetworks;
+import net.neoforged.neoforge.network.PacketDistributor;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+
+/**
+ * @author TT432
+ */
+@Aspect
+public class RpcAspect {
+ @Pointcut("@annotation(rpc) && args() && target(target)")
+ public void rpcPointcut(Rpc rpc, Object target) {
+ }
+
+ @Around("rpcPointcut(rpc, target)")
+ public Object processRpc(Rpc rpc, Object target, ProceedingJoinPoint joinPoint) throws Throwable {
+ if (rpc.value().isClient() == ChinNetworks.isClientSide()) {
+ RpcNetworkPacket