Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ build
eclipse
run
run-data

app.js
19 changes: 6 additions & 13 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ plugins {
id 'eclipse'
id 'idea'
id 'maven-publish'
id 'net.neoforged.moddev' version '2.0.88'
id 'net.neoforged.moddev' version '2.0.140'
}

version = mod_version
Expand All @@ -28,10 +28,7 @@ neoForge {
mappingsVersion = project.parchment_mappings_version
minecraftVersion = project.parchment_minecraft_version
}

accessTransformers {
file('src/main/resources/META-INF/accesstransformer.cfg')
}
validateAccessTransformers = true

runs {
client {
Expand All @@ -46,12 +43,6 @@ neoForge {
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
}

data {
data()

programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
}

configureEach {
systemProperty 'forge.logging.markers', 'REGISTRIES'
systemProperty 'particlestorm.debug', 'true'
Expand All @@ -61,7 +52,9 @@ neoForge {
// 忽略无效指令,避免有的人没安装 JetBrain Runtime 无法启动游戏
"-XX:+IgnoreUnrecognizedVMOptions",
// 启用 JetBrain Runtime 热重载功能
"-XX:+AllowEnhancedClassRedefinition"
"-XX:+AllowEnhancedClassRedefinition",
// 并发修改检测
//"-javaagent:mods/CMESuckMyDuck-1.0.5.jar=net/minecraft/util/ClassInstanceMultiMap;byClass;Map;nonstatic"
])
if (isRunningInIdea) {
systemProperty "terminal.jline", "true"
Expand Down Expand Up @@ -94,7 +87,7 @@ repositories {

dependencies {
compileOnly "software.bernie.geckolib:geckolib-neoforge-${minecraft_version}:${geckolib_version}"
// localRuntime "software.bernie.geckolib:geckolib-neoforge-${minecraft_version}:${geckolib_version}"
localRuntime "software.bernie.geckolib:geckolib-neoforge-${minecraft_version}:${geckolib_version}"
}

tasks.withType(ProcessResources).configureEach {
Expand Down
10 changes: 5 additions & 5 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ minecraft_version=1.21.1
# as they do not follow standard versioning conventions.
minecraft_version_range=[1.21.1,1.22)
# The Neo version must agree with the Minecraft version to get a valid artifact
neo_version=21.1.170
neo_version=21.1.219
# The Neo version range can use any version of Neo as bounds
neo_version_range=[21,)
# The loader version range can only use the major version of FML as bounds
Expand All @@ -31,7 +31,7 @@ mod_name=ParticleStorm
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=LGPL-3.0
# The mod version. See https://semver.org/
mod_version=1.1.4
mod_version=1.3.0
# 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
Expand All @@ -41,9 +41,9 @@ mod_authors=Westernat
# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list.
mod_description=Uses a Bedrock Edition JSON format for particle effects.

geckolib_version=4.8.2
geckolib_version=4.8.4

#systemProp.http.proxyHost=localhost
#systemProp.http.proxyPort=7890
#systemProp.http.proxyPort=7897
#systemProp.https.proxyHost=localhost
#systemProp.https.proxyPort=7890
#systemProp.https.proxyPort=7897
150 changes: 103 additions & 47 deletions src/main/java/org/mesdag/particlestorm/PSGameClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,39 @@
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.ShaderInstance;
import net.minecraft.client.renderer.debug.DebugRenderer;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.util.Mth;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModLoader;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.event.config.ModConfigEvent;
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
import net.neoforged.neoforge.client.event.ClientTickEvent;
import net.neoforged.neoforge.client.event.EntityRenderersEvent;
import net.neoforged.neoforge.client.event.RegisterClientReloadListenersEvent;
import net.neoforged.neoforge.client.event.RenderLevelStageEvent;
import net.neoforged.neoforge.common.NeoForge;
import org.mesdag.particlestorm.api.IComponent;
import org.mesdag.particlestorm.api.IEventNode;
import net.neoforged.neoforge.client.event.*;
import org.jetbrains.annotations.ApiStatus;
import org.mesdag.particlestorm.api.*;
import org.mesdag.particlestorm.api.geckolib.GeckoLibHelper;
import org.mesdag.particlestorm.data.component.*;
import org.mesdag.particlestorm.data.event.*;
import org.mesdag.particlestorm.particle.MolangParticleLoader;
import org.mesdag.particlestorm.particle.MolangParticleEngine;
import org.mesdag.particlestorm.particle.MolangParticleInstance;
import org.mesdag.particlestorm.particle.ParticleEmitter;

@EventBusSubscriber(modid = ParticleStorm.MODID, bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
import java.io.IOException;
import java.util.Queue;

@EventBusSubscriber(modid = ParticleStorm.MODID, value = Dist.CLIENT)
public final class PSGameClient {
public static final MolangParticleLoader LOADER = new MolangParticleLoader();
@Deprecated(forRemoval = true, since = "1.3.0")
@ApiStatus.ScheduledForRemoval(inVersion = "1.4.0")
public static final MolangParticleEngine LOADER = MolangParticleEngine.INSTANCE;
public static final ParticleRenderType PARTICLE_ADD = new ParticleRenderType() {
@Override
public BufferBuilder begin(Tesselator tesselator, TextureManager textureManager) {
RenderSystem.enableDepthTest();
Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer();
RenderSystem.depthMask(false);
RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_PARTICLES);
RenderSystem.enableBlend();
Expand All @@ -51,6 +54,32 @@ public String toString() {
return "PARTICLE_ADD";
}
};
public static final ParticleRenderType PARTICLE_BLEND = new ParticleRenderType() {
@Override
public BufferBuilder begin(Tesselator tesselator, TextureManager textureManager) {
RenderSystem.enableDepthTest();
RenderSystem.depthMask(false);
RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_PARTICLES);
RenderSystem.enableBlend();
RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
return tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.PARTICLE);
}

public String toString() {
return "PARTICLE_BLEND";
}
};

private static ShaderInstance particleNoDiscard;

public static ShaderInstance getParticleNoDiscardShader() {
return particleNoDiscard;
}

@SubscribeEvent
public static void registerShaders(RegisterShadersEvent event) throws IOException {
event.registerShader(new ShaderInstance(event.getResourceProvider(), ParticleStorm.asResource("particle_no_discard"), DefaultVertexFormat.PARTICLE), instance -> particleNoDiscard = instance);
}

@SubscribeEvent
public static void registerRenderers(EntityRenderersEvent.RegisterRenderers event) {
Expand All @@ -60,63 +89,77 @@ public static void registerRenderers(EntityRenderersEvent.RegisterRenderers even
}

@SubscribeEvent
public static void clientSetup(FMLClientSetupEvent event) {
event.enqueueWork(() -> {
public static void modConfig$Loading(ModConfigEvent.Loading event) {
if (ParticleStorm.MODID.equals(event.getConfig().getModId())) {
PSClientConfigs.onLoad();
NeoForge.EVENT_BUS.addListener(PSGameClient::tick);
NeoForge.EVENT_BUS.addListener(PSGameClient::renderLevelStage);
});
}
}

@SubscribeEvent
public static void modConfig$Reloading(ModConfigEvent.Reloading event) {
if (event.getConfig().getModId().equals(ParticleStorm.MODID)) {
if (ParticleStorm.MODID.equals(event.getConfig().getModId())) {
PSClientConfigs.onLoad();
}
}

private static void tick(ClientTickEvent.Pre event) {
@SubscribeEvent
public static void clientNetwork$LoggingOut(ClientPlayerNetworkEvent.LoggingOut event) {
MolangParticleEngine.INSTANCE.removeAll();
}

@SubscribeEvent
public static void tick(ClientTickEvent.Pre event) {
Minecraft minecraft = Minecraft.getInstance();
LocalPlayer localPlayer = minecraft.player;
if (localPlayer == null) {
LOADER.removeAll();
} else if (!minecraft.isPaused() && localPlayer.level().tickRateManager().runsNormally()) {
LOADER.tick(localPlayer);
LocalPlayer player = minecraft.player;
if (player != null && !minecraft.isPaused() && player.clientLevel.tickRateManager().runsNormally()) {
MolangParticleEngine.INSTANCE.tick(minecraft, player);
}
}

private static void renderLevelStage(RenderLevelStageEvent event) {
@SubscribeEvent
public static void renderLevelStage(RenderLevelStageEvent event) {
if (event.getStage() != RenderLevelStageEvent.Stage.AFTER_PARTICLES) return;
if (!PSClientConfigs.showEmitterOutline) return;
Minecraft minecraft = Minecraft.getInstance();
if (event.getStage() == RenderLevelStageEvent.Stage.AFTER_PARTICLES && minecraft.getEntityRenderDispatcher().shouldRenderHitBoxes()) {
float partialTicks = event.getPartialTick().getGameTimeDeltaPartialTick(true);
PoseStack poseStack = event.getPoseStack();
MultiBufferSource.BufferSource bufferSource = minecraft.renderBuffers().bufferSource();
for (ParticleEmitter emitter : LOADER.getEmitters()) {
double x = Mth.lerp(partialTicks, emitter.posO.x, emitter.pos.x);
double y = Mth.lerp(partialTicks, emitter.posO.y, emitter.pos.y);
double z = Mth.lerp(partialTicks, emitter.posO.z, emitter.pos.z);
DebugRenderer.renderFloatingText(poseStack, bufferSource, emitter.particleId.toString(), x, y + 0.5, z, 0xFFFFFF);
DebugRenderer.renderFloatingText(poseStack, bufferSource, "id: " + emitter.id, x, y + 0.3, z, 0xFFFFFF);
int maxNum = minecraft.particleEngine.trackedParticleCounts.getInt(emitter.particleGroup);
DebugRenderer.renderFloatingText(poseStack, bufferSource, "particles: " + maxNum, x, y + 0.1, z, maxNum >= emitter.particleGroup.getLimit() ? 0xFF0000 : 0xFFFFFF);
Camera camera = event.getCamera();
double d0 = camera.getPosition().x;
double d1 = camera.getPosition().y;
double d2 = camera.getPosition().z;
poseStack.pushPose();
poseStack.translate(x - d0, y - d1, z - d2);
LevelRenderer.renderLineBox(poseStack, bufferSource.getBuffer(RenderType.lines()), -0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0, 1, 0, 1);
poseStack.popPose();
}
if (!minecraft.getEntityRenderDispatcher().shouldRenderHitBoxes()) return;
PoseStack poseStack = event.getPoseStack();
MultiBufferSource.BufferSource bufferSource = minecraft.renderBuffers().bufferSource();
Camera camera = event.getCamera();
double camX = camera.getPosition().x;
double camY = camera.getPosition().y;
double camZ = camera.getPosition().z;
float partialTick = event.getPartialTick().getGameTimeDeltaPartialTick(true);
var iterator = MolangParticleEngine.INSTANCE.getEmitters();
while (iterator.hasNext()) {
ParticleEmitter emitter = iterator.next().getValue();
if (emitter.hideOutline) continue;
double x = Mth.lerp(partialTick, emitter.posO.x, emitter.getX());
double y = Mth.lerp(partialTick, emitter.posO.y, emitter.getY());
double z = Mth.lerp(partialTick, emitter.posO.z, emitter.getZ());
DebugRenderer.renderFloatingText(poseStack, bufferSource, emitter.particleId.toString(), x, y + 0.5, z, 0xFFFFFF);
DebugRenderer.renderFloatingText(poseStack, bufferSource, "id: " + emitter.id, x, y + 0.3, z, 0xFFFFFF);
Queue<IMolangParticleInstance> queue = MolangParticleEngine.INSTANCE.getParticlesForEmitter(emitter);
int count = queue == null ? 0 : queue.size();
DebugRenderer.renderFloatingText(poseStack, bufferSource, "particles: " + count, x, y + 0.1, z, count >= emitter.particleGroup.getLimit() ? 0xFF0000 : 0xFFFFFF);
poseStack.pushPose();
poseStack.translate(x - camX, y - camY, z - camZ);
LevelRenderer.renderLineBox(poseStack, bufferSource.getBuffer(RenderType.lines()), -0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0, 1, 0, 1);
poseStack.popPose();
}
}

@SubscribeEvent
public static void reload(RegisterClientReloadListenersEvent event) {
registerComponents();
registerEventNodes();
event.registerReloadListener(LOADER);
event.registerReloadListener(MolangParticleEngine.INSTANCE);
}

@SubscribeEvent
public static void registerCustomParticleType(RegisterCustomParticleTypeEvent event) {
event.registerWithSprites(ParticleStorm.MOLANG, (emitter, particlePreset, level, x, y, z, sprites) ->
new MolangParticleInstance(particlePreset, level, x, y, z, sprites)
);
}

private static void registerComponents() {
Expand All @@ -140,7 +183,7 @@ private static void registerComponents() {

IComponent.register("particle_initial_speed", ParticleInitialSpeed.CODEC);
IComponent.register("particle_initial_spin", ParticleInitialSpin.CODEC);
IComponent.register("particle_initialization", ParticleInitialization.CODEC);
IComponent.register(ParticleInitialization.ID, ParticleInitialization.CODEC);

IComponent.register(ParticleMotionDynamic.ID, ParticleMotionDynamic.CODEC);
IComponent.register("particle_motion_parametric", ParticleMotionParametric.CODEC);
Expand All @@ -155,6 +198,8 @@ private static void registerComponents() {
IComponent.register("particle_kill_plane", ParticleLifetimeKillPlane.CODEC);
IComponent.register("particle_expire_if_in_blocks", ParticleExpireIfInBlocks.CODEC);
IComponent.register("particle_expire_if_not_in_blocks", ParticleExpireIfNotInBlocks.CODEC);

ModLoader.postEvent(new RegisterCustomComponentEvent());
}

private static void registerEventNodes() {
Expand All @@ -165,5 +210,16 @@ private static void registerEventNodes() {
IEventNode.register("sound_effect", SoundEffect.CODEC.codec());
IEventNode.register("expression", NodeMolangExp.CODEC);
IEventNode.register("log", EventLog.CODEC);

ModLoader.postEvent(new RegisterCustomEventNodeEvent());
}

@SubscribeEvent
public static void fmlClientSetup(FMLClientSetupEvent event) {
event.enqueueWork(() -> {
if (ParticleStorm.GECKOLIB_LOADED) {
GeckoLibHelper.postEvent();
}
});
}
}
17 changes: 0 additions & 17 deletions src/main/java/org/mesdag/particlestorm/PSModClient.java

This file was deleted.

17 changes: 10 additions & 7 deletions src/main/java/org/mesdag/particlestorm/ParticleStorm.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
import net.neoforged.neoforge.network.PacketDistributor;
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
import net.neoforged.neoforge.network.registration.PayloadRegistrar;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
import org.mesdag.particlestorm.api.geckolib.GeckoLibHelper;
Expand All @@ -42,7 +41,10 @@
public final class ParticleStorm {
public static final String MODID = "particlestorm";
public static final Logger LOGGER = LoggerFactory.getLogger("ParticleStorm");
public static final boolean DEBUG = Boolean.getBoolean("particlestorm.debug") && LoadingModList.get().getModFileById("geckolib") != null;
public static final boolean GECKOLIB_LOADED = LoadingModList.get().getModFileById("geckolib") != null;
public static final boolean SODIUM_LOADED = LoadingModList.get().getModFileById("sodium") != null;
public static final boolean IRIS_LOADED = LoadingModList.get().getModFileById("iris") != null;
public static final boolean DEBUG = Boolean.getBoolean("particlestorm.debug") && GECKOLIB_LOADED;

private static final DeferredRegister<ParticleType<?>> REGISTER = DeferredRegister.create(BuiltInRegistries.PARTICLE_TYPE, MODID);
public static final DeferredHolder<ParticleType<?>, ParticleType<MolangParticleOption>> MOLANG = registerParticleType(REGISTER, "molang");
Expand All @@ -61,11 +63,12 @@ public ParticleStorm(IEventBus bus, ModContainer container) {
}

private static void registerPayloadHandlers(RegisterPayloadHandlersEvent event) {
PayloadRegistrar registrar = event.registrar("1");
registrar.playToClient(EmitterCreationPacketS2C.TYPE, EmitterCreationPacketS2C.STREAM_CODEC, EmitterCreationPacketS2C::handle);
registrar.playToClient(EmitterAttachPacketS2C.TYPE, EmitterAttachPacketS2C.STREAM_CODEC, EmitterAttachPacketS2C::handle);
registrar.playBidirectional(EmitterRemovalPacket.TYPE, EmitterRemovalPacket.STREAM_CODEC, EmitterRemovalPacket::handle);
registrar.playBidirectional(EmitterSynchronizePacket.TYPE, EmitterSynchronizePacket.STREAM_CODEC, EmitterSynchronizePacket::handle);
event.registrar("1")
.playToClient(EmitterCreationPacketS2C.TYPE, EmitterCreationPacketS2C.STREAM_CODEC, EmitterCreationPacketS2C::handle)
.playToClient(EmitterAttachPacketS2C.TYPE, EmitterAttachPacketS2C.STREAM_CODEC, EmitterAttachPacketS2C::handle)
.playBidirectional(EmitterRemovalPacket.TYPE, EmitterRemovalPacket.STREAM_CODEC, EmitterRemovalPacket::handle)
.playBidirectional(EmitterSynchronizePacket.TYPE, EmitterSynchronizePacket.STREAM_CODEC, EmitterSynchronizePacket::handle)
;
}

private static void registerCommands(RegisterCommandsEvent event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import org.mesdag.particlestorm.particle.ParticleEmitter;

public interface IEmitterComponent extends IComponent {
default void update(ParticleEmitter entity) {}
default void update(ParticleEmitter emitter) {}

default void apply(ParticleEmitter entity) {}
default void apply(ParticleEmitter emitter) {}

default boolean requireUpdate() {
return false;
Expand Down
Loading
Loading