Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ae12cff
feat: add Forge 1.20.1 platform module
Sep 20, 2026
1271d21
ci: trigger workflow
Sep 20, 2026
d4cc6d5
ci: trigger build
Sep 20, 2026
603faac
ci: retrigger build
Sep 20, 2026
1365ad6
ci: force trigger
Sep 20, 2026
d9c3767
ci: add workflow_dispatch trigger to gradle workflow
Sep 20, 2026
bdd13e8
fix(common): add missing stub classes for compilation
Sep 20, 2026
4cf79f3
ci: trigger build after adding missing classes
Sep 20, 2026
14cbff4
fix(common): add missing stubs for compilation
Sep 20, 2026
e4f1890
fix(common): move resource stubs to cparticle.force, add binding inte…
Sep 20, 2026
1d25662
fix(common): fix package for resource stubs, add inheritance
Sep 20, 2026
79a965f
fix(common): make CParticleForceResource open for extension
Sep 20, 2026
e629a55
fix(common): add missing IrisRenderState methods for Java mixin
Sep 20, 2026
5cb0482
fix(common): match CooIrisRenderState signatures to Java mixin
Sep 20, 2026
ea37b33
fix(common): create missing FinalPassRendererAccessor mixin, fix Iris…
Sep 20, 2026
43ecccb
fix(neoforge): remove duplicate network files already in common
Sep 20, 2026
913435f
fix: remove CustomPacketPayload from common interfaces and implement …
Sep 20, 2026
b25fd39
fix: continue removing MC 1.20.5+ APIs from Forge module
Sep 20, 2026
4a5a84d
fix: complete Forge MC 1.20.1 API compatibility pass
Sep 20, 2026
efdf270
fix: configure Forge Gradle plugin resolution for CI
Sep 20, 2026
06fd62b
fix: resolve Forge Gradle plugin in settings.gradle pluginManagement
Sep 20, 2026
c740751
fix: resolve Forge Gradle plugin and task configuration issues
Sep 20, 2026
0e9589b
fix: use correct ForgeGradle version and Minecraft version for 1.20.1
Sep 20, 2026
0455f62
fix: configure ForgeGradle 5.2.5 via buildscript block
Sep 21, 2026
79c5b61
fix: resolve Gradle exclusiveContent restriction for Forge plugin
Sep 21, 2026
3afb4e1
fix: upgrade ForgeGradle to 6.0.24 for Gradle 8.x compatibility
Sep 21, 2026
fec7099
fix: update Forge build.gradle for 1.20.1 compatibility
Sep 21, 2026
44e08a6
fix: try minecraft_version property in Forge build.gradle
Sep 21, 2026
b5cd9e6
fix: revert to ForgeGradle 5.2.5 for 1.20.1 support
Sep 21, 2026
6e05303
fix: use buildscript + apply plugin for ForgeGradle 5.2.5
Sep 21, 2026
cc68dfe
fix: try ForgeGradle 5.1.0 for 1.20.1
Sep 21, 2026
87a6659
fix: try method call syntax for minecraft version
Sep 21, 2026
b8ca033
fix: replace additionalRuntimeClasspath with runtimeOnly
Sep 21, 2026
94f7d33
fix: add explicit minecraft and forge dependencies
Sep 21, 2026
47fb8cb
fix: try ForgeGradle 5.1.44 for 1.20.1
Sep 21, 2026
e2a3fc8
fix: downgrade Gradle to 8.1 for ForgeGradle 5.1.x compatibility
Sep 21, 2026
106cc44
fix: try ForgeGradle 6.0.24 with buildscript approach
Sep 21, 2026
84ad069
fix: reorder buildscript block and fix sourceWithCommon task
Sep 21, 2026
4d2a173
fix: handle missing sourcesJar task in root build.gradle
Sep 21, 2026
e83c718
fix: try ForgeGradle 5.1.50
Sep 21, 2026
9f16736
fix: 整体降级到 Java 17 + Gradle 8.1 以兼容 ForgeGradle 5.1.x
Sep 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches: [ "**" ]
pull_request:
workflow_dispatch:

permissions:
contents: read
Expand All @@ -27,7 +28,7 @@ jobs:
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
java-version: "17"
cache: gradle

# 可选:更安全,防止 wrapper 被篡改(不想要可删)
Expand Down
10 changes: 6 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,13 @@ subprojects {
inputs.file "../gradle.properties"
}
afterEvaluate {
tasks.named("sourcesJar") {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
def sourcesJar = tasks.findByName("sourcesJar")
if (sourcesJar != null) {
sourcesJar.duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
tasks.named("jar") {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
def jarTask = tasks.findByName("jar")
if (jarTask != null) {
jarTask.duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package cn.coostack.cooparticlesapi.mixin.compat.iris;

import net.irisshaders.iris.gl.framebuffer.GlFramebuffer;
import net.irisshaders.iris.pipeline.FinalPassRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(FinalPassRenderer.class)
public interface FinalPassRendererAccessor {
@Accessor
GlFramebuffer getColorHolder();
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package cn.coostack.cooparticlesapi.annotations.codec

interface CommonStreamCodec<T> {
fun decode(buf: Any): T
fun encode(buf: Any, value: T)
companion object {
fun <T> of(dec: (Any) -> T, enc: (Any, T) -> Unit): CommonStreamCodec<T> =
object : CommonStreamCodec<T> {
override fun decode(buf: Any): T = dec(buf)
override fun encode(buf: Any, value: T) = enc(buf, value)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package cn.coostack.cooparticlesapi.compat.iris

import kotlin.jvm.JvmStatic
import net.irisshaders.iris.gl.framebuffer.GlFramebuffer
import net.irisshaders.iris.targets.DepthTexture
import net.irisshaders.iris.targets.RenderTargets

object CooIrisRenderState {
@JvmStatic
fun beginFrame() {}

@JvmStatic
fun captureSceneDepth(depthTextureId: Int, width: Int, height: Int) {}

@JvmStatic
fun captureTerrainDepth(textureId: Int, width: Int, height: Int) {}

@JvmStatic
fun captureNoHandDepth(textureId: Int, width: Int, height: Int) {}

@JvmStatic
fun captureFinalColor(colorAttachment0: Any?, framebufferId: Int, width: Int, height: Int) {}

@JvmStatic
fun clear() {}

@JvmStatic
fun clearFinalColor() {}

@JvmStatic
fun snapshot(): IrisSnapshot = EmptySnapshot

object EmptySnapshot : IrisSnapshot {
override fun terrainDepthTextureId(): Int = 0
override fun terrainDepthWidth(): Int = 0
override fun terrainDepthHeight(): Int = 0
override fun sceneDepthTextureId(): Int = 0
override fun sceneDepthWidth(): Int = 0
override fun sceneDepthHeight(): Int = 0
override fun noHandDepthTextureId(): Int = 0
override fun noHandDepthWidth(): Int = 0
override fun noHandDepthHeight(): Int = 0
override fun finalColorTextureId(): Int = 0
override fun finalColorWidth(): Int = 0
override fun finalColorHeight(): Int = 0
override fun finalColorFramebufferId(): Int = 0
}
}

interface IrisSnapshot {
fun terrainDepthTextureId(): Int
fun terrainDepthWidth(): Int
fun terrainDepthHeight(): Int
fun sceneDepthTextureId(): Int
fun sceneDepthWidth(): Int
fun sceneDepthHeight(): Int
fun noHandDepthTextureId(): Int
fun noHandDepthWidth(): Int
fun noHandDepthHeight(): Int
fun finalColorTextureId(): Int
fun finalColorWidth(): Int
fun finalColorHeight(): Int
fun finalColorFramebufferId(): Int
}
Original file line number Diff line number Diff line change
Expand Up @@ -417,16 +417,18 @@ object CParticleEmitterBridge {
val base = index * ForceCommand.STRIDE
when (val force = command.force) {
is CParticleForce.Texture -> {
val slot = textureSlots.getOrPut(force.resource) {
resources.add(force.resource)
val resource = force.resource
val slot = textureSlots.getOrPut(resource) {
resources.add(resource)
textureSlots.size
}
command.pack(packed, base, origin, slot)
}

is CParticleForce.FluidFlow -> {
val slot = fluidSlots.getOrPut(force.resource) {
resources.add(force.resource)
val resource = force.resource
val slot = fluidSlots.getOrPut(resource) {
resources.add(resource)
fluidSlots.size
}
command.pack(packed, base, origin, slot)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package cn.coostack.cooparticlesapi.cparticle.force

class CParticleFluidResource(id: String) : CParticleForceResource(id), CParticleFluidBinding {
override fun sampleFluid(x: Double, y: Double, z: Double, out: FloatArray) {}
fun bindCompute(index: Int) {}
fun resetCompute() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package cn.coostack.cooparticlesapi.cparticle.force

open class CParticleForceResource(val id: String) {
override fun equals(other: Any?): Boolean = other is CParticleForceResource && other.id == id
override fun hashCode(): Int = id.hashCode()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package cn.coostack.cooparticlesapi.cparticle.force

object CParticleForceResourceRegistry {
private val bindings = mutableMapOf<CParticleForceResource, Any>()
fun bind(resource: CParticleForceResource, binding: Any) {
bindings[resource] = binding
}
fun clearResolvedBindings() {
bindings.clear()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package cn.coostack.cooparticlesapi.cparticle.force

interface CParticleTextureBinding {
fun sampleTexture(x: Double, y: Double, z: Double, out: FloatArray)
}

interface CParticleFluidBinding {
fun sampleFluid(x: Double, y: Double, z: Double, out: FloatArray)
}

class CParticleForceResourceTable {
companion object {
const val MAX_TEXTURE_RESOURCES: Int = 16
}
fun resolve(resource: CParticleForceResource): Any? = null
fun slotFor(resource: CParticleTextureResource): Int = -1
fun slotFor(resource: CParticleFluidResource): Int = -1
fun textureBinding(slot: Int): CParticleTextureBinding = NullTextureBinding
fun fluidBinding(slot: Int): CParticleFluidBinding = NullFluidBinding
fun textureBindings(): List<CParticleTextureResource> = emptyList()
fun fluidBindings(): List<CParticleFluidResource> = emptyList()
fun clear() {}
}

private object NullTextureBinding : CParticleTextureBinding {
override fun sampleTexture(x: Double, y: Double, z: Double, out: FloatArray) {}
}

private object NullFluidBinding : CParticleFluidBinding {
override fun sampleFluid(x: Double, y: Double, z: Double, out: FloatArray) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package cn.coostack.cooparticlesapi.cparticle.force

class CParticleTextureResource(id: String) : CParticleForceResource(id), CParticleTextureBinding {
override fun sampleTexture(x: Double, y: Double, z: Double, out: FloatArray) {}
fun bindCompute(index: Int) {}
fun resetCompute() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import cn.coostack.cooparticlesapi.cparticle.CParticleCapabilities
import cn.coostack.cooparticlesapi.cparticle.collision.CParticleBlockCollisionGrid
import cn.coostack.cooparticlesapi.cparticle.force.CParticleForceResourceTable
import cn.coostack.cooparticlesapi.cparticle.force.CParticleForce
import cn.coostack.cooparticlesapi.cparticle.force.CParticleTextureResource
import cn.coostack.cooparticlesapi.cparticle.force.CParticleFluidResource
import cn.coostack.cooparticlesapi.cparticle.force.ForceCommand
import cn.coostack.cooparticlesapi.renderer.shader.AdvancedShaderProgramBuilder
import cn.coostack.cooparticlesapi.renderer.shader.ShaderProgramRegistry
Expand Down Expand Up @@ -180,8 +182,8 @@ object CParticleGpuSimulator {
"[cparticle] ${if (useLegacy) "legacy Force" else "Force Command"} GPU compute program 无效,拒绝回退 CPU"
}

val textureBindings = if (useLegacy) emptyList() else system.forceResourceTable.textureBindings()
val fluidBindings = if (useLegacy) emptyList() else system.forceResourceTable.fluidBindings()
val textureBindings = if (useLegacy) emptyList<CParticleTextureResource>() else system.forceResourceTable.textureBindings()
val fluidBindings = if (useLegacy) emptyList<CParticleFluidResource>() else system.forceResourceTable.fluidBindings()
var dispatched = false
try {
compute.useOnContext {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package cn.coostack.cooparticlesapi.cparticle.storage

class CParticleCommandGlBuffer {
val initialized: Boolean get() = false
fun init() {}
fun upload(data: FloatArray, count: Int) {}
fun release() {}
fun dispose() {}
fun bindShaderStorage(binding: Int) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ package cn.coostack.cooparticlesapi.data.holder
import cn.coostack.cooparticlesapi.CooParticlesConstants
import cn.coostack.cooparticlesapi.annotations.CooAutoRegister
import cn.coostack.cooparticlesapi.annotations.codec.CodecHelper
import cn.coostack.cooparticlesapi.annotations.codec.CommonStreamCodec
import cn.coostack.cooparticlesapi.network.packet.server.PacketDataHolderS2C
import cn.coostack.cooparticlesapi.reflect.CooAPIScanner
import cn.coostack.cooparticlesapi.reflect.SimpleClassInfo
import net.minecraft.network.codec.StreamCodec
import net.minecraft.world.entity.Entity
import java.util.concurrent.ConcurrentHashMap

object DataHolderManager {
val entities = ConcurrentHashMap<Entity, DataHolder>()
private val registeredTypes = ConcurrentHashMap<String, StreamCodec<*, *>>()
private val registeredTypes = ConcurrentHashMap<String, CommonStreamCodec<*>>()

fun getOrCreate(entity: Entity): DataHolder {
return entities.getOrPut(entity) { DataHolder(entity) }
Expand All @@ -33,11 +33,11 @@ object DataHolderManager {
registeredTypes[randomInstance::class.java.name] = codec
}

fun register(type: Class<*>, codec: StreamCodec<*, *>) {
fun register(type: Class<*>, codec: CommonStreamCodec<*>) {
registeredTypes[type.name] = codec
}

fun getCodecFromID(id: String): StreamCodec<*, *>? {
fun getCodecFromID(id: String): CommonStreamCodec<*>? {
return registeredTypes[id] ?: CodecHelper.supposedTypes[id]
}

Expand All @@ -63,7 +63,7 @@ object DataHolderManager {
register(instance)
}

private fun findCodec(instance: Any): StreamCodec<*, *> {
private fun findCodec(instance: Any): CommonStreamCodec<*> {
val codec = CodecHelper.supposedTypes[instance::class.java.name]
return codec
?: throw IllegalStateException("DataHolder codec not registered for type: ${instance::class.java.name}")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package cn.coostack.cooparticlesapi.network.packet.api

interface CommonCodec<T> {
fun encode(buf: PacketByteBuf, value: T)
fun decode(buf: PacketByteBuf): T
companion object {
fun <T> of(enc: (PacketByteBuf, T) -> Unit, dec: (PacketByteBuf) -> T): CommonCodec<T> =
object : CommonCodec<T> {
override fun encode(buf: PacketByteBuf, value: T) = enc(buf, value)
override fun decode(buf: PacketByteBuf): T = dec(buf)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import cn.coostack.cooparticlesapi.network.packet.api.envelope.CooPacketEnvelope
import cn.coostack.cooparticlesapi.performance.PerformanceStatusNetworkEndpoint
import cn.coostack.cooparticlesapi.performance.PerformanceStatusNetworkMetrics
import cn.coostack.cooparticlesapi.platform.CooParticlesServices
import net.minecraft.network.protocol.common.custom.CustomPacketPayload
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import java.util.UUID
Expand Down Expand Up @@ -332,7 +331,7 @@ object CooServerPacketManager {
CooParticlesConstants.logger.error("CooPacket 编码失败: ${packet::class.java.name}", e)
return false
}
val envelope: CustomPacketPayload = CooPacketEnvelopeS2C(
val envelope = CooPacketEnvelopeS2C(
kindId = kind.id,
packetId = packet.id(),
correlationId = correlationId,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package cn.coostack.cooparticlesapi.network.packet.api

interface PacketByteBuf {
fun writeUtf(value: String)
fun writeResourceLocation(value: Any?)
fun writeInt(value: Int)
fun writeFloat(value: Float)
fun writeDouble(value: Double)
fun writeLong(value: Long)
fun writeBoolean(value: Boolean)
fun readUtf(): String
fun readResourceLocation(): Any?
fun readInt(): Int
fun readFloat(): Float
fun readDouble(): Double
fun readLong(): Long
fun readBoolean(): Boolean
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
package cn.coostack.cooparticlesapi.platform

import net.minecraft.network.protocol.common.custom.CustomPacketPayload
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.level.ChunkPos

interface ClientNetworking {

fun send(packet: CustomPacketPayload)


fun send(packet: cn.coostack.cooparticlesapi.network.packet.api.CooPacket)
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
package cn.coostack.cooparticlesapi.platform

import net.minecraft.network.protocol.common.custom.CustomPacketPayload
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.level.ChunkPos

interface ServerNetworking {
fun send(packet: CustomPacketPayload, to: ServerPlayer)
fun sendAllPlayers(packet: CustomPacketPayload)
fun sendToPlayersTrackingChunk(world: ServerLevel, chunk: ChunkPos, packet: CustomPacketPayload)
fun send(packet: cn.coostack.cooparticlesapi.network.packet.api.CooPacket, to: ServerPlayer)
fun sendAllPlayers(packet: cn.coostack.cooparticlesapi.network.packet.api.CooPacket)
fun sendToPlayersTrackingChunk(world: ServerLevel, chunk: ChunkPos, packet: cn.coostack.cooparticlesapi.network.packet.api.CooPacket)

/**
* 把数据包发送给指定世界 (维度) 内的所有玩家
*/
fun sendToWorld(world: ServerLevel, packet: CustomPacketPayload) {
fun sendToWorld(world: ServerLevel, packet: cn.coostack.cooparticlesapi.network.packet.api.CooPacket) {
world.players().forEach { send(packet, it) }
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package cn.coostack.cooparticlesapi.platform.network

import net.minecraft.network.protocol.common.custom.CustomPacketPayload
import net.minecraft.server.MinecraftServer
import net.minecraft.world.entity.player.Player

interface ServerContext {
fun player(): Player
fun server(): MinecraftServer
fun reply(packet: CustomPacketPayload)
fun reply(packet: cn.coostack.cooparticlesapi.network.packet.api.CooPacket)
}
Loading