├── .gitattributes ├── .github └── workflows │ └── auto-build-publish-release.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.gradle ├── common ├── build.gradle └── src │ └── main │ ├── java │ ├── com │ │ └── lowdragmc │ │ │ └── photon │ │ │ ├── Photon.java │ │ │ ├── PhotonCommonProxy.java │ │ │ ├── PhotonNetworking.java │ │ │ ├── ServerCommands.java │ │ │ ├── client │ │ │ ├── ClientCommands.java │ │ │ ├── PhotonClientProxy.java │ │ │ ├── PhotonParticleManager.java │ │ │ ├── PhotonShaders.java │ │ │ ├── fx │ │ │ │ ├── BlockEffect.java │ │ │ │ ├── EntityEffect.java │ │ │ │ ├── FX.java │ │ │ │ ├── FXData.java │ │ │ │ ├── FXEffect.java │ │ │ │ ├── FXHelper.java │ │ │ │ ├── FXOutDated.java │ │ │ │ ├── FXProjectEffect.java │ │ │ │ ├── FXRuntime.java │ │ │ │ ├── IEffect.java │ │ │ │ └── IFXEffect.java │ │ │ ├── gameobject │ │ │ │ ├── EmptyFXObject.java │ │ │ │ ├── FXObject.java │ │ │ │ ├── IFXObject.java │ │ │ │ ├── emitter │ │ │ │ │ ├── Emitter.java │ │ │ │ │ ├── IParticleEmitter.java │ │ │ │ │ ├── ParticleQueueRenderType.java │ │ │ │ │ ├── PhotonParticleRenderType.java │ │ │ │ │ ├── beam │ │ │ │ │ │ ├── BeamConfig.java │ │ │ │ │ │ └── BeamEmitter.java │ │ │ │ │ ├── data │ │ │ │ │ │ ├── ColorBySpeedSetting.java │ │ │ │ │ │ ├── ColorOverLifetimeSetting.java │ │ │ │ │ │ ├── EmissionSetting.java │ │ │ │ │ │ ├── ForceOverLifetimeSetting.java │ │ │ │ │ │ ├── InheritVelocitySetting.java │ │ │ │ │ │ ├── LifetimeByEmitterSpeedSetting.java │ │ │ │ │ │ ├── LightOverLifetimeSetting.java │ │ │ │ │ │ ├── MaterialSetting.java │ │ │ │ │ │ ├── NoiseSetting.java │ │ │ │ │ │ ├── PhysicsSetting.java │ │ │ │ │ │ ├── RendererSetting.java │ │ │ │ │ │ ├── RotationBySpeedSetting.java │ │ │ │ │ │ ├── RotationOverLifetimeSetting.java │ │ │ │ │ │ ├── ShapeSetting.java │ │ │ │ │ │ ├── SizeBySpeedSetting.java │ │ │ │ │ │ ├── SizeOverLifetimeSetting.java │ │ │ │ │ │ ├── SubEmittersSetting.java │ │ │ │ │ │ ├── ToggleGroup.java │ │ │ │ │ │ ├── TrailsSetting.java │ │ │ │ │ │ ├── UVAnimationSetting.java │ │ │ │ │ │ ├── VelocityOverLifetimeSetting.java │ │ │ │ │ │ ├── material │ │ │ │ │ │ │ ├── BlendMode.java │ │ │ │ │ │ │ ├── BlockTextureSheetMaterial.java │ │ │ │ │ │ │ ├── CustomShaderMaterial.java │ │ │ │ │ │ │ ├── IMaterial.java │ │ │ │ │ │ │ ├── ShaderInstanceMaterial.java │ │ │ │ │ │ │ └── TextureMaterial.java │ │ │ │ │ │ ├── number │ │ │ │ │ │ │ ├── Constant.java │ │ │ │ │ │ │ ├── NumberFunction.java │ │ │ │ │ │ │ ├── NumberFunction3.java │ │ │ │ │ │ │ ├── NumberFunction3Config.java │ │ │ │ │ │ │ ├── NumberFunctionConfig.java │ │ │ │ │ │ │ ├── RandomConstant.java │ │ │ │ │ │ │ ├── color │ │ │ │ │ │ │ │ ├── Color.java │ │ │ │ │ │ │ │ ├── Gradient.java │ │ │ │ │ │ │ │ ├── GradientColorTexture.java │ │ │ │ │ │ │ │ ├── RandomColor.java │ │ │ │ │ │ │ │ ├── RandomGradient.java │ │ │ │ │ │ │ │ └── RandomGradientColorTexture.java │ │ │ │ │ │ │ └── curve │ │ │ │ │ │ │ │ ├── Curve.java │ │ │ │ │ │ │ │ ├── CurveConfig.java │ │ │ │ │ │ │ │ ├── CurveLineWidget.java │ │ │ │ │ │ │ │ ├── CurveTexture.java │ │ │ │ │ │ │ │ ├── ECBCurves.java │ │ │ │ │ │ │ │ ├── RandomCurve.java │ │ │ │ │ │ │ │ ├── RandomCurveLineWidget.java │ │ │ │ │ │ │ │ └── RandomCurveTexture.java │ │ │ │ │ │ └── shape │ │ │ │ │ │ │ ├── Box.java │ │ │ │ │ │ │ ├── Circle.java │ │ │ │ │ │ │ ├── Cone.java │ │ │ │ │ │ │ ├── Cylinder.java │ │ │ │ │ │ │ ├── Dot.java │ │ │ │ │ │ │ ├── Function.java │ │ │ │ │ │ │ ├── IShape.java │ │ │ │ │ │ │ ├── Mesh.java │ │ │ │ │ │ │ ├── MeshData.java │ │ │ │ │ │ │ └── Sphere.java │ │ │ │ │ ├── particle │ │ │ │ │ │ ├── ParticleConfig.java │ │ │ │ │ │ └── ParticleEmitter.java │ │ │ │ │ └── trail │ │ │ │ │ │ ├── TrailConfig.java │ │ │ │ │ │ └── TrailEmitter.java │ │ │ │ └── particle │ │ │ │ │ ├── BeamParticle.java │ │ │ │ │ ├── IParticle.java │ │ │ │ │ ├── TileParticle.java │ │ │ │ │ ├── TrailParticle.java │ │ │ │ │ └── TrailParticle.outdated │ │ │ └── postprocessing │ │ │ │ └── BloomEffect.java │ │ │ ├── command │ │ │ ├── BlockEffectCommand.java │ │ │ ├── EffectCommand.java │ │ │ ├── EntityEffectCommand.java │ │ │ ├── FxLocationArgument.java │ │ │ ├── RemoveBlockEffectCommand.java │ │ │ └── RemoveEntityEffectCommand.java │ │ │ ├── core │ │ │ └── mixins │ │ │ │ ├── WorldSceneRendererMixin.java │ │ │ │ └── accessor │ │ │ │ ├── BlendModeAccessor.java │ │ │ │ ├── MinecraftAccessor.java │ │ │ │ ├── ParticleEngineAccessor.java │ │ │ │ └── ShaderInstanceAccessor.java │ │ │ ├── gui │ │ │ └── editor │ │ │ │ ├── CurvesResource.java │ │ │ │ ├── FXEditor.java │ │ │ │ ├── FXObjectsList.java │ │ │ │ ├── FXProject.java │ │ │ │ ├── GradientsResource.java │ │ │ │ ├── MaterialsResource.java │ │ │ │ ├── MaterialsResourceContainer.java │ │ │ │ ├── MeshesResource.java │ │ │ │ ├── ParticleInfoView.java │ │ │ │ ├── ParticleScene.java │ │ │ │ ├── ParticleScenePanel.java │ │ │ │ ├── SceneMenu.java │ │ │ │ ├── accessor │ │ │ │ ├── IShapeAccessor.java │ │ │ │ ├── NumberFunction3Accessor.java │ │ │ │ └── NumberFunctionAccessor.java │ │ │ │ └── configurator │ │ │ │ ├── NumberFunction3Accessor.java │ │ │ │ ├── NumberFunction3Configurator.java │ │ │ │ ├── NumberFunctionAccessor.java │ │ │ │ └── NumberFunctionConfigurator.java │ │ │ └── integration │ │ │ └── PhotonLDLibPlugin.java │ └── expr │ │ ├── Benchmark.java │ │ ├── Example.java │ │ ├── Expr.java │ │ ├── Parser.java │ │ ├── RegressionTest.java │ │ ├── Scanner.java │ │ ├── SyntaxException.java │ │ ├── Token.java │ │ └── Variable.java │ └── resources │ ├── architectury.common.json │ ├── assets │ └── photon │ │ ├── lang │ │ ├── en_us.json │ │ └── zh_cn.json │ │ ├── shaders │ │ ├── catmull_rom.comp │ │ └── core │ │ │ ├── circle.fsh │ │ │ ├── circle.json │ │ │ ├── separable_blur.fsh │ │ │ ├── separable_blur.json │ │ │ ├── unreal_composite.fsh │ │ │ └── unreal_composite.json │ │ └── textures │ │ └── particle │ │ ├── kila_tail.png │ │ ├── laser.png │ │ ├── ring.png │ │ ├── smoke.png │ │ ├── thaumcraft.png │ │ └── thaumcraft.png.mcmeta │ ├── hotswap-agent.properties │ ├── photon-common.mixins.json │ └── photon.accesswidener ├── fabric ├── build.gradle └── src │ └── main │ ├── java │ └── com │ │ └── lowdragmc │ │ └── photon │ │ ├── client │ │ └── fabric │ │ │ └── ClientProxyImpl.java │ │ └── fabric │ │ ├── PhotonImpl.java │ │ └── core │ │ ├── PhotonMixinPlugin.java │ │ └── mixins │ │ ├── ArgumentTypeInfosMixin.java │ │ ├── LevelRendererMixin.java │ │ ├── ParticleEngineMixin.java │ │ ├── ShaderInstanceMixin.java │ │ └── no_iris │ │ └── ParticleEngineMixin.java │ └── resources │ ├── assets │ └── photon │ │ └── icon.png │ ├── fabric.mod.json │ └── photon.mixins.json ├── forge ├── build.gradle ├── gradle.properties └── src │ └── main │ ├── java │ └── com │ │ └── lowdragmc │ │ └── photon │ │ ├── client │ │ └── forge │ │ │ ├── ClientEventListener.java │ │ │ └── ClientProxyImpl.java │ │ └── forge │ │ ├── CommonProxyImpl.java │ │ ├── PhotonImpl.java │ │ └── core │ │ ├── PhotonMixinPlugin.java │ │ └── mixins │ │ ├── LevelRendererMixin.java │ │ ├── ParticleEngineMixin.java │ │ └── no_iris │ │ └── ParticleEngineMixin.java │ └── resources │ ├── META-INF │ └── mods.toml │ ├── icon.png │ ├── pack.mcmeta │ └── photon.mixins.json ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=autolf 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | *.json text eol=lf 7 | 8 | # Denote all files that are truly binary and should not be modified. 9 | *.png binary -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.ipr 3 | run/ 4 | *.iws 5 | out/ 6 | *.iml 7 | .gradle/ 8 | output/ 9 | bin/ 10 | libs/ 11 | 12 | .classpath 13 | .project 14 | .idea/ 15 | classes/ 16 | .metadata 17 | .vscode 18 | .settings 19 | *.launch 20 | .architectury-transformer/debug.log 21 | forge/src/generated/resources/.cache/ 22 | fabric/src/generated/resources/.cache/ 23 | *.DS_Store 24 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## ChangeLog 2 | 3 | # 1.1.8 4 | * Fixed remove entity command. 5 | * Bump up ldlib to the latest. 6 | * Added Auto Rotation for entity command. 7 | 8 | # 1.1.7 9 | * Added beam and trail emitters lifetime. 10 | * Added command to remove fx from block / entities. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Photon 2 | Photon is a VFX (visual effect) editor mod developed for minecraft which is inspired by unity. 3 | 4 | It includes unity's particle system and the trailing system. Can help mod creators to create effects for their contents, and players can also enjoy effects by command. 5 | 6 | Its original intention is to let players who love vfx, not be confused by technical skill and math problems. Its creativity allows you to make various dream scenarios!! 7 | 8 | 9 | 10 | Discord: https://discord.com/invite/sDdf2yD9bh 11 | 12 | Github: https://github.com/Low-Drag-MC/Photon 13 | 14 | Video: https://youtu.be/rdB0qVXRgaY 15 | 16 | CurseForge: https://www.curseforge.com/minecraft/mc-mods/photon 17 | 18 | Modrinth: https://modrinth.com/mod/photon-editor 19 | 20 | QQ: 933426877 21 | 22 | 23 | 24 | There will be video tutorials in details in the future. 25 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias libs.plugins.architectury 3 | alias libs.plugins.architectury.loom apply false 4 | alias libs.plugins.quiltFlower apply false // Quiltflower, a better decompiler 5 | alias libs.plugins.machete // automatic jar compressing on build 6 | } 7 | 8 | def is_root_project = project == rootProject 9 | 10 | architectury { 11 | minecraft = libs.versions.minecraft 12 | } 13 | 14 | subprojects { 15 | apply plugin: "dev.architectury.loom" 16 | // apply plugin: "io.github.juuxel.loom-quiltflower" 17 | 18 | loom { 19 | silentMojangMappingsLicense() 20 | // for (final def setting in runConfigs) { 21 | // setting.vmArgs() 22 | // } 23 | } 24 | 25 | repositories { 26 | mavenLocal() 27 | mavenCentral() 28 | maven { url = "https://maven.shedaniel.me/" } // Cloth Config, REI 29 | maven { 30 | name = "Modrinth" 31 | url = "https://api.modrinth.com/maven" 32 | content { 33 | includeGroup "maven.modrinth" 34 | } 35 | } // Modrinth File 36 | maven { 37 | url "https://cursemaven.com" 38 | content { 39 | includeGroup "curse.maven" 40 | } 41 | } // Curse Forge File 42 | maven { 43 | name = "Jared's maven" 44 | url = "https://maven.blamejared.com/" 45 | } // JEI 46 | maven { 47 | // location of a maven mirror for JEI files, as a fallback 48 | name = "ModMaven" 49 | url = "https://modmaven.dev" 50 | } // JEI mirror, AE2 51 | maven { url = "https://maven.parchmentmc.org" } // Parchment mappings 52 | maven { url = "https://maven.quiltmc.org/repository/release" } // Quilt Mappings 53 | maven { url = "https://maven.firstdarkdev.xyz/snapshots" } // LDLib 54 | maven { // Flywheel 55 | url = "https://maven.tterrag.com/" 56 | content { 57 | // need to be specific here due to version overlaps 58 | includeGroup("com.jozufozu.flywheel") 59 | } 60 | } 61 | maven { // TOP-Fabric 62 | url "https://maven.wispforest.io" 63 | } 64 | 65 | } 66 | 67 | dependencies { 68 | minecraft "com.mojang:minecraft:${libs.versions.minecraft.get()}" 69 | 70 | if (is_root_project) { 71 | // layered mappings - Mojmap names, parchment and QM docs and parameters 72 | mappings loom.layered { 73 | it.mappings("org.quiltmc:quilt-mappings:${libs.versions.minecraft.get()}+build.${libs.versions.quiltMappings.get()}:intermediary-v2") 74 | it.parchment("org.parchmentmc.data:parchment-${libs.versions.parchment.get()}@zip") 75 | it.officialMojangMappings { nameSyntheticMembers = false } 76 | } 77 | } 78 | 79 | // see each subproject for dependencies. 80 | 81 | // lombok 82 | compileOnly 'org.projectlombok:lombok:1.18.24' 83 | annotationProcessor 'org.projectlombok:lombok:1.18.24' 84 | 85 | implementation 'com.google.code.findbugs:jsr305:3.0.2' 86 | } 87 | } 88 | 89 | allprojects { 90 | apply plugin: "java" 91 | apply plugin: "architectury-plugin" 92 | apply plugin: "maven-publish" 93 | 94 | archivesBaseName = "${project.name}-${libs.versions.minecraft.get()}" 95 | group = rootProject.maven_group 96 | version = "${mod_version}" 97 | 98 | repositories { 99 | // Add repositories to retrieve artifacts from in here. 100 | // You should only use this when depending on other mods because 101 | // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. 102 | // See https://docs.gradle.org/current/userguide/declaring_repositories.html 103 | // for more information about repositories. 104 | } 105 | 106 | tasks.withType(JavaCompile) { 107 | options.encoding = "UTF-8" 108 | } 109 | 110 | java { 111 | withSourcesJar() 112 | } 113 | 114 | machete { 115 | // disable machete locally for faster builds 116 | enabled = false 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /common/build.gradle: -------------------------------------------------------------------------------- 1 | architectury { 2 | common(rootProject.enabled_platforms.split(",")) 3 | } 4 | 5 | String getConfig(String key) { 6 | return project.getParent().properties.get(key) 7 | } 8 | 9 | def mod_id = getConfig("mod_id") 10 | 11 | loom { 12 | accessWidenerPath = file("src/main/resources/${mod_id}.accesswidener") 13 | } 14 | 15 | repositories { 16 | // mavens for Create Fabric and dependencies 17 | maven { url = "https://maven.jamieswhiteshirt.com/libs-release" } // Reach Entity Attributes 18 | maven { url = "https://jitpack.io/" } // Mixin Extras, Fabric ASM 19 | } 20 | 21 | configurations { 22 | // snapshotModImplementation.extendsFrom modImplementation 23 | // snapshotModImplementation { 24 | // resolutionStrategy.cacheChangingModulesFor(0, "seconds") 25 | // } 26 | } 27 | 28 | //configurations.all { 29 | // resolutionStrategy.cacheChangingModulesFor(0, "seconds") 30 | // resolutionStrategy.cacheDynamicVersionsFor(0, "seconds") 31 | //} 32 | 33 | dependencies { 34 | // We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies 35 | // Do NOT use other classes from fabric loader 36 | modImplementation fabric.fabricLoader 37 | modCompileOnly fabric.fabricApi 38 | 39 | modCompileOnly fabric.ldlib.common 40 | 41 | // Iris 42 | modCompileOnly(fabric.sodium) { transitive = false } 43 | modCompileOnly(fabric.iris) { transitive = false } 44 | } 45 | 46 | publishing { 47 | publications { 48 | mavenCommon(MavenPublication) { 49 | artifactId = archivesBaseName 50 | from components.java 51 | } 52 | } 53 | 54 | // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. 55 | repositories { 56 | // Add repositories to publish to here. 57 | maven { 58 | url "https://maven.firstdarkdev.xyz/snapshots" 59 | credentials { 60 | username System.getenv("MAVEN_USER") 61 | password System.getenv("MAVEN_PASS") 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/Photon.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon; 2 | 3 | import com.lowdragmc.lowdraglib.LDLib; 4 | import com.lowdragmc.lowdraglib.Platform; 5 | import com.mojang.blaze3d.pipeline.RenderTarget; 6 | import dev.architectury.injectables.annotations.ExpectPlatform; 7 | import net.irisshaders.iris.api.v0.IrisApi; 8 | import net.minecraft.resources.ResourceLocation; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class Photon { 13 | public static final String MOD_ID = "photon"; 14 | public static final String NAME = "Photon"; 15 | public static final Logger LOGGER = LoggerFactory.getLogger(NAME); 16 | 17 | public static void init() { 18 | LOGGER.info("{} is initializing on platform: {}", NAME, Platform.platformName()); 19 | } 20 | 21 | public static ResourceLocation id(String path) { 22 | return new ResourceLocation(MOD_ID, path); 23 | } 24 | 25 | @ExpectPlatform 26 | public static boolean isStencilEnabled(RenderTarget target) { 27 | throw new AssertionError(); 28 | } 29 | 30 | @ExpectPlatform 31 | public static boolean useCombinedDepthStencilAttachment() { 32 | throw new AssertionError(); 33 | } 34 | 35 | public static boolean isShaderModInstalled() { 36 | return LDLib.isModLoaded("iris") || LDLib.isModLoaded("oculus"); 37 | } 38 | 39 | public static boolean isUsingShaderPack() { 40 | if (isShaderModInstalled()) { 41 | return IrisApi.getInstance().isShaderPackInUse(); 42 | } 43 | return false; 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/PhotonCommonProxy.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon; 2 | 3 | 4 | public class PhotonCommonProxy { 5 | public static void init() { 6 | PhotonNetworking.init(); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/PhotonNetworking.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon; 2 | 3 | import com.lowdragmc.lowdraglib.networking.INetworking; 4 | import com.lowdragmc.lowdraglib.networking.LDLNetworking; 5 | import com.lowdragmc.photon.command.BlockEffectCommand; 6 | import com.lowdragmc.photon.command.EntityEffectCommand; 7 | import com.lowdragmc.photon.command.RemoveBlockEffectCommand; 8 | import com.lowdragmc.photon.command.RemoveEntityEffectCommand; 9 | import net.minecraft.resources.ResourceLocation; 10 | 11 | public class PhotonNetworking { 12 | 13 | public static final INetworking NETWORK = LDLNetworking.createNetworking(new ResourceLocation(Photon.MOD_ID, "networking"), "0.0.1"); 14 | 15 | public static void init() { 16 | NETWORK.registerS2C(BlockEffectCommand.class); 17 | NETWORK.registerS2C(EntityEffectCommand.class); 18 | NETWORK.registerS2C(RemoveBlockEffectCommand.class); 19 | NETWORK.registerS2C(RemoveEntityEffectCommand.class); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/ServerCommands.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon; 2 | 3 | import com.lowdragmc.photon.command.*; 4 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 5 | import net.minecraft.commands.CommandSourceStack; 6 | import net.minecraft.commands.Commands; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author KilaBash 12 | * @date 2023/2/9 13 | * @implNote ServerCommands 14 | */ 15 | public class ServerCommands { 16 | public static List> createServerCommands() { 17 | return List.of( 18 | Commands.literal("photon") 19 | .then(Commands.literal("fx").requires(source -> source.hasPermission(2)) 20 | .then(Commands.argument("location", new FxLocationArgument()) 21 | .then(BlockEffectCommand.createServerCommand()) 22 | .then(EntityEffectCommand.createServerCommand()) 23 | ) 24 | .then(Commands.literal("remove") 25 | .then(RemoveBlockEffectCommand.createServerCommand()) 26 | .then(RemoveEntityEffectCommand.createServerCommand()) 27 | ) 28 | ) 29 | 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/ClientCommands.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client; 2 | 3 | import com.lowdragmc.lowdraglib.LDLib; 4 | import com.lowdragmc.lowdraglib.gui.modular.IUIHolder; 5 | import com.lowdragmc.lowdraglib.gui.modular.ModularUI; 6 | import com.lowdragmc.lowdraglib.gui.modular.ModularUIGuiContainer; 7 | import com.lowdragmc.photon.client.gameobject.FXObject; 8 | import com.lowdragmc.photon.client.gameobject.emitter.PhotonParticleRenderType; 9 | import com.lowdragmc.photon.client.fx.BlockEffect; 10 | import com.lowdragmc.photon.client.fx.EntityEffect; 11 | import com.lowdragmc.photon.client.fx.FXHelper; 12 | import com.lowdragmc.photon.core.mixins.accessor.ParticleEngineAccessor; 13 | import com.lowdragmc.photon.gui.editor.FXEditor; 14 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 15 | import net.fabricmc.api.EnvType; 16 | import net.fabricmc.api.Environment; 17 | import net.minecraft.client.Minecraft; 18 | import net.minecraft.network.chat.Component; 19 | 20 | import java.util.List; 21 | 22 | import static com.lowdragmc.lowdraglib.client.ClientCommands.createLiteral; 23 | 24 | /** 25 | * @author KilaBash 26 | * @date 2023/2/9 27 | * @implNote ClientCommands 28 | */ 29 | @Environment(EnvType.CLIENT) 30 | public class ClientCommands { 31 | 32 | @SuppressWarnings("unchecked") 33 | public static List> createClientCommands() { 34 | return List.of( 35 | (LiteralArgumentBuilder) createLiteral("photon_editor").executes(context -> { 36 | var minecraft = Minecraft.getInstance(); 37 | var entityPlayer = minecraft.player; 38 | var modular = new ModularUI(IUIHolder.EMPTY, entityPlayer).widget(new FXEditor(LDLib.getLDLibDir())); 39 | modular.initWidgets(); 40 | ModularUIGuiContainer ModularUIGuiContainer = new ModularUIGuiContainer(modular, entityPlayer.containerMenu.containerId); 41 | minecraft.setScreen(ModularUIGuiContainer); 42 | entityPlayer.containerMenu = ModularUIGuiContainer.getMenu(); 43 | return 1; 44 | }), 45 | (LiteralArgumentBuilder) createLiteral("photon_client") 46 | .then(createLiteral("clear_particles") 47 | .executes(context -> { 48 | if (Minecraft.getInstance().particleEngine instanceof ParticleEngineAccessor accessor) { 49 | accessor.getParticles().entrySet().removeIf(entry -> 50 | entry.getKey() instanceof PhotonParticleRenderType || 51 | entry.getKey() == FXObject.NO_RENDER_RENDER_TYPE); 52 | } 53 | EntityEffect.CACHE.clear(); 54 | BlockEffect.CACHE.clear(); 55 | return 1; 56 | })) 57 | .then(createLiteral("clear_client_fx_cache") 58 | .executes(context -> { 59 | if (Minecraft.getInstance().player != null) { 60 | Minecraft.getInstance().player.sendSystemMessage(Component.literal("clear client cache fx: " + FXHelper.clearCache())); 61 | } else { 62 | FXHelper.clearCache(); 63 | } 64 | return 1; 65 | })) 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/PhotonClientProxy.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client; 2 | 3 | import net.fabricmc.api.EnvType; 4 | import net.fabricmc.api.Environment; 5 | 6 | @Environment(EnvType.CLIENT) 7 | public class PhotonClientProxy { 8 | 9 | /** 10 | * should be called when Minecraft is prepared. 11 | */ 12 | public static void init() { 13 | PhotonShaders.init(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/PhotonParticleManager.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client; 2 | 3 | import com.lowdragmc.lowdraglib.client.scene.ParticleManager; 4 | import com.lowdragmc.photon.client.gameobject.emitter.PhotonParticleRenderType; 5 | import com.mojang.blaze3d.vertex.PoseStack; 6 | import lombok.val; 7 | import net.fabricmc.api.EnvType; 8 | import net.fabricmc.api.Environment; 9 | import net.minecraft.client.Camera; 10 | 11 | import java.util.Arrays; 12 | 13 | /** 14 | * @author KilaBash 15 | * @date 2023/6/10 16 | * @implNote SimulatedParticleManager 17 | */ 18 | @Environment(EnvType.CLIENT) 19 | public class PhotonParticleManager extends ParticleManager { 20 | 21 | private final long[] lastCPUTimes = new long[60]; 22 | private int tickIndex = 0; 23 | 24 | private final long[] lastFrameTimes = new long[60]; 25 | private int frameIndex = 0; 26 | 27 | @Override 28 | public void render(PoseStack pMatrixStack, Camera pActiveRenderInfo, float pPartialTicks) { 29 | val startTime = System.nanoTime(); 30 | super.render(pMatrixStack, pActiveRenderInfo, pPartialTicks); 31 | PhotonParticleRenderType.finishRender(); 32 | lastFrameTimes[frameIndex] = System.nanoTime() - startTime; 33 | } 34 | 35 | @Override 36 | public void tick() { 37 | val startTime = System.nanoTime(); 38 | super.tick(); 39 | lastCPUTimes[tickIndex] = System.nanoTime() - startTime; 40 | tickIndex = (tickIndex + 1) % lastCPUTimes.length; 41 | } 42 | 43 | public long getCPUTime() { 44 | return (long) Arrays.stream(lastCPUTimes).average().orElse(0) / 1000; 45 | } 46 | 47 | public long getFrameTime() { 48 | return (long) Arrays.stream(lastFrameTimes).average().orElse(0) / 1000; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/PhotonShaders.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client; 2 | 3 | import com.lowdragmc.lowdraglib.client.shader.Shaders; 4 | import com.lowdragmc.lowdraglib.client.shader.management.Shader; 5 | import com.lowdragmc.lowdraglib.client.shader.management.ShaderProgram; 6 | import com.lowdragmc.photon.Photon; 7 | import net.fabricmc.api.EnvType; 8 | import net.fabricmc.api.Environment; 9 | 10 | @Environment(EnvType.CLIENT) 11 | public class PhotonShaders { 12 | private static Shader CATMULL_ROM; 13 | private static ShaderProgram CATMULL_ROM_PROGRAM; 14 | 15 | public static void init() { 16 | CATMULL_ROM = Shaders.load(Shader.ShaderType.COMPUTE, Photon.id("catmull_rom")); 17 | } 18 | 19 | public static ShaderProgram getCatmullRomProgram() { 20 | if (CATMULL_ROM_PROGRAM == null) { 21 | CATMULL_ROM_PROGRAM = new ShaderProgram(); 22 | CATMULL_ROM_PROGRAM.attach(CATMULL_ROM); 23 | } 24 | return CATMULL_ROM_PROGRAM; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/fx/BlockEffect.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.fx; 2 | 3 | import com.lowdragmc.photon.client.gameobject.IFXObject; 4 | import org.joml.Vector3f; 5 | import lombok.Setter; 6 | import net.fabricmc.api.EnvType; 7 | import net.fabricmc.api.Environment; 8 | import net.minecraft.core.BlockPos; 9 | import net.minecraft.world.level.Level; 10 | import net.minecraft.world.level.block.state.BlockState; 11 | 12 | import java.util.*; 13 | 14 | /** 15 | * @author KilaBash 16 | * @date 2023/6/5 17 | * @implNote BlockEffect 18 | */ 19 | @Environment(EnvType.CLIENT) 20 | public class BlockEffect extends FXEffect { 21 | public static Map> CACHE = new HashMap<>(); 22 | public final BlockPos pos; 23 | @Setter 24 | private boolean checkState; 25 | // runtime 26 | private BlockState lastState; 27 | 28 | public BlockEffect(FX fx, Level level, BlockPos pos) { 29 | super(fx, level); 30 | this.pos = pos; 31 | } 32 | 33 | @Override 34 | public void updateFXObjectTick(IFXObject fxObject) { 35 | if (runtime != null && fxObject == runtime.root) { 36 | if (!level.isLoaded(pos) || lastState.getBlock() != level.getBlockState(pos).getBlock() || (checkState && level.getBlockState(pos) != lastState)) { 37 | runtime.destroy(forcedDeath); 38 | CACHE.computeIfAbsent(pos, p -> new ArrayList<>()).remove(this); 39 | } 40 | } 41 | } 42 | 43 | @Override 44 | public void start() { 45 | var effects = CACHE.computeIfAbsent(pos, p -> new ArrayList<>()); 46 | if (!allowMulti) { 47 | var iter = effects.iterator(); 48 | while (iter.hasNext()) { 49 | var effect = iter.next(); 50 | boolean removed = false; 51 | if (effect.runtime != null && !effect.runtime.isAlive()) { 52 | iter.remove(); 53 | removed = true; 54 | } 55 | if ((effect.fx.equals(fx) || Objects.equals(effect.fx.getFxLocation(), fx.getFxLocation())) && !removed) { 56 | return; 57 | } 58 | } 59 | } 60 | this.runtime = fx.createRuntime(); 61 | var root = this.runtime.getRoot(); 62 | root.updatePos(new Vector3f(pos.getX(), pos.getY(), pos.getZ()) 63 | .add(offset.x + 0.5f, offset.y + 0.5f, offset.z + 0.5f)); 64 | root.updateRotation(rotation); 65 | root.updateScale(scale); 66 | this.runtime.emmit(this); 67 | lastState = level.getBlockState(pos); 68 | effects.add(this); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/fx/FX.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.fx; 2 | 3 | import com.lowdragmc.lowdraglib.syncdata.ITagSerializable; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import net.minecraft.nbt.CompoundTag; 7 | import net.minecraft.resources.ResourceLocation; 8 | 9 | import javax.annotation.Nullable; 10 | import java.util.*; 11 | 12 | /** 13 | * FX is a definition of a FX. 14 | *
15 | * In general, use {@link #createRuntime()} to create a runtime of this FX. 16 | */ 17 | @Getter 18 | public class FX implements ITagSerializable { 19 | @Nullable 20 | @Setter 21 | private ResourceLocation fxLocation; 22 | private final FXData mainFX; 23 | private final Map subFXs = new LinkedHashMap<>(); 24 | 25 | public FX() { 26 | mainFX = new FXData(); 27 | } 28 | 29 | @Override 30 | public CompoundTag serializeNBT() { 31 | var tag = new CompoundTag(); 32 | tag.put("mainFX", mainFX.serializeNBT()); 33 | var subFXs = new CompoundTag(); 34 | for (var entry : this.subFXs.entrySet()) { 35 | subFXs.put(entry.getKey(), entry.getValue().serializeNBT()); 36 | } 37 | return tag; 38 | } 39 | 40 | @Override 41 | public void deserializeNBT(CompoundTag tag) { 42 | mainFX.deserializeNBT(tag.getCompound("mainFX")); 43 | var subFXs = tag.getCompound("subFXs"); 44 | for (var key : subFXs.getAllKeys()) { 45 | var subFX = new FXData(); 46 | subFX.deserializeNBT(subFXs.getCompound(key)); 47 | this.subFXs.put(key, subFX); 48 | } 49 | } 50 | 51 | /** 52 | * Create a runtime of this FX. 53 | * @return a runtime of this FX 54 | */ 55 | public FXRuntime createRuntime() { 56 | return new FXRuntime(this, mainFX, true, false); 57 | } 58 | 59 | /** 60 | * Create a runtime of this FX. 61 | * @param deepCopy if true, deep copy the data 62 | * @return a runtime of this FX 63 | */ 64 | public FXRuntime createRuntime(boolean deepCopy) { 65 | return new FXRuntime(this, mainFX, true, deepCopy); 66 | } 67 | 68 | /** 69 | * Create a runtime of this FX which use the raw data. 70 | */ 71 | public FXRuntime createInternalRuntime() { 72 | return new FXRuntime(this, mainFX, false, false); 73 | } 74 | 75 | @Nullable 76 | public FXRuntime createSubFXRuntime(String name) { 77 | if (!subFXs.containsKey(name)) { 78 | return null; 79 | } 80 | return new FXRuntime(this, subFXs.get(name), true, false); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/fx/FXData.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.fx; 2 | 3 | import com.lowdragmc.lowdraglib.syncdata.ITagSerializable; 4 | import com.lowdragmc.photon.client.gameobject.IFXObject; 5 | import net.minecraft.nbt.CompoundTag; 6 | import net.minecraft.nbt.ListTag; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | public record FXData(List objects) implements ITagSerializable { 12 | 13 | public FXData() { 14 | this(new ArrayList<>()); 15 | } 16 | 17 | public CompoundTag serializeNBT() { 18 | var tag = new CompoundTag(); 19 | var fxObjects = new ListTag(); 20 | for (var fxObject : objects) { 21 | fxObjects.add(fxObject.serializeNBT()); 22 | } 23 | tag.put("fxObjects", fxObjects); 24 | return tag; 25 | } 26 | 27 | @Override 28 | public void deserializeNBT(CompoundTag tag) { 29 | objects.clear(); 30 | var list = tag.getList("fxObjects", ListTag.TAG_COMPOUND); 31 | for (var nbt : list) { 32 | if (nbt instanceof CompoundTag data) { 33 | var fxObject = IFXObject.deserializeWrapper(data); 34 | if (fxObject != null) { 35 | objects.add(fxObject); 36 | } 37 | } 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/fx/FXEffect.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.fx; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import net.minecraft.world.level.Level; 6 | import org.joml.Quaternionf; 7 | import org.joml.Vector3f; 8 | 9 | import javax.annotation.Nullable; 10 | 11 | /** 12 | * @author KilaBash 13 | * @date 2023/7/19 14 | * @implNote FXEffect 15 | */ 16 | public abstract class FXEffect implements IFXEffect { 17 | @Getter 18 | public final FX fx; 19 | @Getter 20 | public final Level level; 21 | @Setter 22 | protected Vector3f offset = new Vector3f(); 23 | @Setter 24 | protected Quaternionf rotation = new Quaternionf(); 25 | @Setter 26 | protected Vector3f scale = new Vector3f(1, 1, 1); 27 | @Setter 28 | protected int delay; 29 | @Setter 30 | protected boolean forcedDeath; 31 | @Setter 32 | protected boolean allowMulti; 33 | 34 | //runtime 35 | @Getter 36 | @Nullable 37 | protected FXRuntime runtime; 38 | 39 | protected FXEffect(FX fx, Level level) { 40 | this.fx = fx; 41 | this.level = level; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/fx/FXHelper.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.fx; 2 | 3 | import net.fabricmc.api.EnvType; 4 | import net.fabricmc.api.Environment; 5 | import net.minecraft.client.Minecraft; 6 | import net.minecraft.nbt.CompoundTag; 7 | import net.minecraft.nbt.NbtIo; 8 | import net.minecraft.nbt.Tag; 9 | import net.minecraft.resources.ResourceLocation; 10 | 11 | import javax.annotation.Nullable; 12 | import javax.annotation.ParametersAreNonnullByDefault; 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | 16 | /** 17 | * @author KilaBash 18 | * @date 2023/6/5 19 | * @implNote FXHelper 20 | */ 21 | @Environment(EnvType.CLIENT) 22 | @ParametersAreNonnullByDefault 23 | public class FXHelper { 24 | private final static Map CACHE = new HashMap<>(); 25 | public static final String FX_PATH = "fx/"; 26 | 27 | public static int clearCache() { 28 | var count = CACHE.size(); 29 | CACHE.clear(); 30 | return count; 31 | } 32 | 33 | @Nullable 34 | public static FX getFX(ResourceLocation fxLocation) { 35 | return CACHE.computeIfAbsent(fxLocation, location -> { 36 | ResourceLocation resourceLocation = new ResourceLocation(fxLocation.getNamespace(), FX_PATH + fxLocation.getPath() + ".fx"); 37 | try (var inputStream = Minecraft.getInstance().getResourceManager().open(resourceLocation);) { 38 | var tag = NbtIo.readCompressed(inputStream); 39 | var version = tag.contains("_version") ? tag.getInt("_version") : 0; 40 | var fx = new FX(); 41 | fx.setFxLocation(fxLocation); 42 | fx.deserializeNBT(tag.getCompound("fx")); 43 | if (version < 1) { 44 | var emitters = new CompoundTag(); 45 | emitters.put("fxObjects", tag.getList("emitters", Tag.TAG_COMPOUND)); 46 | fx.getMainFX().deserializeNBT(emitters); 47 | } 48 | return fx; 49 | } catch (Exception ignored) { 50 | return null; 51 | } 52 | }); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/fx/FXOutDated.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.fx; 2 | 3 | import com.lowdragmc.photon.client.gameobject.emitter.IParticleEmitter; 4 | import net.minecraft.nbt.CompoundTag; 5 | import net.minecraft.resources.ResourceLocation; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Collection; 9 | import java.util.List; 10 | 11 | /** 12 | * @author KilaBash 13 | * @date 2023/6/6 14 | * @implNote FX 15 | */ 16 | public record FXOutDated(ResourceLocation location, List emitters, CompoundTag rawData) { 17 | 18 | public Collection generateEmitters() { 19 | // List list = new ArrayList<>(emitters.size()); 20 | // for (IParticleEmitter emitter : emitters) { 21 | // list.add(emitter.copy()); 22 | // } 23 | return List.of(); 24 | } 25 | 26 | @Override 27 | public int hashCode() { 28 | return location.hashCode(); 29 | } 30 | 31 | @Override 32 | public boolean equals(Object obj) { 33 | if (obj instanceof FXOutDated fx) { 34 | return fx.location.equals(location); 35 | } 36 | return false; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/fx/FXProjectEffect.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.fx; 2 | 3 | import lombok.Getter; 4 | import net.fabricmc.api.EnvType; 5 | import net.fabricmc.api.Environment; 6 | import net.minecraft.world.level.Level; 7 | 8 | /** 9 | * @author KilaBash 10 | * @date 2023/7/17 11 | * @implNote EditorEffect 12 | */ 13 | @Environment(EnvType.CLIENT) 14 | public class FXProjectEffect implements IEffect { 15 | @Getter 16 | public final Level level; 17 | 18 | public FXProjectEffect(Level level) { 19 | this.level = level; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/fx/IEffect.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.fx; 2 | 3 | import com.lowdragmc.photon.client.gameobject.IFXObject; 4 | import net.fabricmc.api.EnvType; 5 | import net.fabricmc.api.Environment; 6 | import net.minecraft.world.level.Level; 7 | 8 | /** 9 | * @author KilaBash 10 | * @date 2023/7/17 11 | * @implNote IEffect 12 | */ 13 | @Environment(EnvType.CLIENT) 14 | public interface IEffect { 15 | 16 | Level getLevel(); 17 | 18 | /** 19 | * update each FX objects during their duration, per tick. Execute low frequency logic here. 20 | *
21 | * e.g., kill particle 22 | * @param fxObject fx object 23 | */ 24 | default void updateFXObjectTick(IFXObject fxObject) { 25 | } 26 | 27 | /** 28 | * update each FX objects during rendering, per frame. Execute high frequency logic here. 29 | *
30 | * e.g., update emitter position, rotation, scale 31 | * @param fxObject fx object 32 | * @param partialTicks partialTicks 33 | */ 34 | default void updateFXObjectFrame(IFXObject fxObject, float partialTicks) { 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/fx/IFXEffect.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.fx; 2 | 3 | import net.fabricmc.api.EnvType; 4 | import net.fabricmc.api.Environment; 5 | import net.minecraft.util.Mth; 6 | import org.joml.Quaternionf; 7 | import org.joml.Vector3f; 8 | 9 | /** 10 | * @author KilaBash 11 | * @date 2023/6/5 12 | * @implNote IFXEffect 13 | */ 14 | @Environment(EnvType.CLIENT) 15 | public interface IFXEffect extends IEffect { 16 | /** 17 | * get all emitters included in this effect. 18 | */ 19 | FX getFx(); 20 | 21 | /** 22 | * set effect offset 23 | */ 24 | default void setOffset(double x, double y, double z) { 25 | setOffset(new Vector3f((float) x, (float) y, (float) z)); 26 | } 27 | 28 | /** 29 | * set effect rotation in degree 30 | */ 31 | default void setRotation(double x, double y, double z) { 32 | setRotation(new Quaternionf().rotationXYZ((float) Math.toRadians(x), (float) Math.toRadians(y), (float) Math.toRadians(z))); 33 | } 34 | 35 | /** 36 | * set effect scale 37 | */ 38 | default void setScale(double x, double y, double z) { 39 | setScale(new Vector3f((float) x, (float) y, (float) z)); 40 | } 41 | 42 | /** 43 | * set effect offset 44 | */ 45 | void setOffset(Vector3f offset); 46 | 47 | /** 48 | * set effect rotation 49 | */ 50 | void setRotation(Quaternionf quaternion); 51 | 52 | /** 53 | * set effect scale 54 | */ 55 | void setScale(Vector3f scale); 56 | 57 | /** 58 | * set effect delay 59 | */ 60 | void setDelay(int delay); 61 | 62 | /** 63 | * Whether to remove particles directly when the bound object invalid. 64 | *
65 | * default - wait for particles death. 66 | */ 67 | void setForcedDeath(boolean forcedDeath); 68 | 69 | /** 70 | * Allows multiple identical effects to be bound to a same object。 71 | */ 72 | void setAllowMulti(boolean allowMulti); 73 | 74 | /** 75 | * start effect。 76 | */ 77 | void start(); 78 | 79 | } 80 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/EmptyFXObject.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegisterClient; 4 | import lombok.Getter; 5 | 6 | import javax.annotation.ParametersAreNonnullByDefault; 7 | 8 | @ParametersAreNonnullByDefault 9 | @LDLRegisterClient(name = "empty", group = "fxObject", priority = -99) 10 | @Getter 11 | public class EmptyFXObject extends FXObject { 12 | 13 | public EmptyFXObject() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/IParticleEmitter.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.configurator.IConfigurable; 4 | import com.lowdragmc.photon.client.fx.FXProjectEffect; 5 | import com.lowdragmc.photon.client.gameobject.IFXObject; 6 | import net.fabricmc.api.EnvType; 7 | import net.fabricmc.api.Environment; 8 | import net.minecraft.core.BlockPos; 9 | import net.minecraft.util.RandomSource; 10 | import net.minecraft.world.phys.AABB; 11 | import org.joml.Vector3f; 12 | import org.joml.Vector4f; 13 | 14 | import javax.annotation.Nullable; 15 | import java.util.function.Function; 16 | 17 | 18 | /** 19 | * @author KilaBash 20 | * @date 2023/6/2 21 | * @implNote IParticleEmitter 22 | */ 23 | @Environment(EnvType.CLIENT) 24 | public interface IParticleEmitter extends IFXObject, IConfigurable { 25 | 26 | default Emitter self() { 27 | return (Emitter) this; 28 | } 29 | 30 | /** 31 | * get amount of existing particle which emitted from it. 32 | */ 33 | int getParticleAmount(); 34 | 35 | Vector3f getVelocity(); 36 | 37 | /** 38 | * get the box of cull. 39 | *
40 | * return null - culling disabled. 41 | */ 42 | @Nullable 43 | default AABB getCullBox(float partialTicks) { 44 | return null; 45 | } 46 | 47 | default boolean isDev() { 48 | return getEffect() instanceof FXProjectEffect; 49 | } 50 | 51 | int getAge(); 52 | 53 | void setAge(int age); 54 | 55 | boolean isLooping(); 56 | 57 | void setRGBAColor(Vector4f color); 58 | 59 | Vector4f getRGBAColor(); 60 | 61 | float getT(); 62 | 63 | float getT(float partialTicks); 64 | 65 | float getMemRandom(Object object); 66 | 67 | float getMemRandom(Object object, Function randomFunc); 68 | 69 | RandomSource getRandomSource(); 70 | 71 | int getLightColor(BlockPos pos); 72 | 73 | } 74 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/ColorBySpeedSetting.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.lowdraglib.gui.editor.annotation.NumberRange; 5 | import com.lowdragmc.lowdraglib.utils.Range; 6 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunctionConfig; 8 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.color.Gradient; 9 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.color.RandomGradient; 10 | 11 | import com.lowdragmc.photon.client.gameobject.particle.IParticle; 12 | import com.lowdragmc.photon.client.gameobject.particle.TileParticle; 13 | import lombok.Getter; 14 | import lombok.Setter; 15 | import net.fabricmc.api.EnvType; 16 | import net.fabricmc.api.Environment; 17 | import org.joml.Vector4f; 18 | 19 | /** 20 | * @author KilaBash 21 | * @date 2023/5/30 22 | * @implNote ColorBySpeedSetting 23 | */ 24 | @Environment(EnvType.CLIENT) 25 | @Setter 26 | @Getter 27 | public class ColorBySpeedSetting extends ToggleGroup { 28 | 29 | @Configurable(tips = "photon.emitter.config.colorBySpeed.color") 30 | @NumberFunctionConfig(types = {Gradient.class, RandomGradient.class}, defaultValue = -1) 31 | protected NumberFunction color = new Gradient(); 32 | 33 | @Configurable(tips = "photon.emitter.config.colorBySpeed.speedRange") 34 | @NumberRange(range = {0, 1000}) 35 | protected Range speedRange = new Range(0f, 1f); 36 | 37 | public Vector4f getColor(TileParticle particle) { 38 | var value = particle.getRealVelocity().length() * 20; 39 | var c = color.get(((value - speedRange.getA().floatValue()) / (speedRange.getB().floatValue() - speedRange.getA().floatValue())), () -> particle.getMemRandom(this)).intValue(); 40 | return new Vector4f((c >> 16 & 0xff) / 255f, (c >> 8 & 0xff) / 255f, (c & 0xff) / 255f, (c >> 24 & 0xff) / 255f); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/ColorOverLifetimeSetting.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 5 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunctionConfig; 6 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.color.Gradient; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.color.RandomGradient; 8 | import com.lowdragmc.photon.client.gameobject.particle.IParticle; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | import net.fabricmc.api.EnvType; 12 | import net.fabricmc.api.Environment; 13 | import org.joml.Vector4f; 14 | 15 | /** 16 | * @author KilaBash 17 | * @date 2023/5/30 18 | * @implNote ColorOverLifetimeSetting 19 | */ 20 | @Environment(EnvType.CLIENT) 21 | @Setter 22 | @Getter 23 | public class ColorOverLifetimeSetting extends ToggleGroup { 24 | 25 | 26 | @Configurable(tips = "photon.emitter.config.colorOverLifetime.color") 27 | @NumberFunctionConfig(types = {Gradient.class, RandomGradient.class}, defaultValue = -1) 28 | protected NumberFunction color = new Gradient(); 29 | 30 | public Vector4f getColor(IParticle particle, float partialTicks) { 31 | var c = color.get(particle.getT(partialTicks), () -> particle.getMemRandom(this)).intValue(); 32 | return new Vector4f((c >> 16 & 0xff) / 255f, (c >> 8 & 0xff) / 255f, (c & 0xff) / 255f, (c >> 24 & 0xff) / 255f); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/ForceOverLifetimeSetting.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.*; 5 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.Curve; 6 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.CurveConfig; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.RandomCurve; 8 | import com.lowdragmc.photon.client.gameobject.emitter.particle.ParticleConfig; 9 | import com.lowdragmc.photon.client.gameobject.particle.IParticle; 10 | import org.joml.Vector3f; 11 | import lombok.Getter; 12 | import lombok.Setter; 13 | import net.fabricmc.api.EnvType; 14 | import net.fabricmc.api.Environment; 15 | 16 | /** 17 | * @author KilaBash 18 | * @date 2023/5/30 19 | * @implNote LifetimeByEmitterSpeed 20 | */ 21 | @Environment(EnvType.CLIENT) 22 | @Setter 23 | @Getter 24 | public class ForceOverLifetimeSetting extends ToggleGroup { 25 | 26 | @Configurable(tips = "photon.emitter.config.forceOverLifetime.force") 27 | @NumberFunction3Config(common = @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, curveConfig = @CurveConfig(bound = {-1, 1}, xAxis = "lifetime", yAxis = "force"))) 28 | protected NumberFunction3 force = new NumberFunction3(0, 0, 0); 29 | 30 | @Setter 31 | @Getter 32 | @Configurable(tips = "photon.emitter.config.simulationSpace") 33 | protected ParticleConfig.Space simulationSpace = ParticleConfig.Space.Local; 34 | 35 | public Vector3f getForce(IParticle particle) { 36 | return force.get(particle.getT(), () -> particle.getMemRandom(this)).mul(0.05f); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/InheritVelocitySetting.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.Constant; 5 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 6 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunctionConfig; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.RandomConstant; 8 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.Curve; 9 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.CurveConfig; 10 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.RandomCurve; 11 | import org.joml.Vector3f; 12 | import com.lowdragmc.photon.client.gameobject.emitter.Emitter; 13 | import lombok.Getter; 14 | import lombok.Setter; 15 | import net.fabricmc.api.EnvType; 16 | import net.fabricmc.api.Environment; 17 | 18 | /** 19 | * @author KilaBash 20 | * @date 2023/5/30 21 | * @implNote InheritVelocitySetting 22 | */ 23 | @Environment(EnvType.CLIENT) 24 | @Setter 25 | @Getter 26 | public class InheritVelocitySetting extends ToggleGroup { 27 | public enum Mode { 28 | CURRENT, 29 | INITIAL, 30 | } 31 | 32 | @Configurable(tips = "photon.emitter.config.inheritVelocity.mode") 33 | protected Mode mode = Mode.INITIAL; 34 | 35 | @Configurable(tips = "photon.emitter.config.inheritVelocity.multiply") 36 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, defaultValue = 1f, curveConfig = @CurveConfig(bound = {-1, 1}, xAxis = "lifetime", yAxis = "speed modifier")) 37 | protected NumberFunction multiply = NumberFunction.constant(1); 38 | 39 | public Vector3f getVelocity(Emitter emitter) { 40 | return emitter.getVelocity().mul(multiply.get(emitter.getT(), () -> emitter.getMemRandom(this)).floatValue()); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/LifetimeByEmitterSpeedSetting.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.lowdraglib.gui.editor.annotation.NumberRange; 5 | import com.lowdragmc.lowdraglib.utils.Range; 6 | import com.lowdragmc.photon.client.gameobject.emitter.IParticleEmitter; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.Constant; 8 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 9 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunctionConfig; 10 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.RandomConstant; 11 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.Curve; 12 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.CurveConfig; 13 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.RandomCurve; 14 | import com.lowdragmc.photon.client.gameobject.particle.IParticle; 15 | import lombok.Getter; 16 | import lombok.Setter; 17 | import net.fabricmc.api.EnvType; 18 | import net.fabricmc.api.Environment; 19 | 20 | /** 21 | * @author KilaBash 22 | * @date 2023/5/30 23 | * @implNote LifetimeByEmitterSpeed 24 | */ 25 | @Environment(EnvType.CLIENT) 26 | @Setter 27 | @Getter 28 | public class LifetimeByEmitterSpeedSetting extends ToggleGroup { 29 | 30 | @Configurable(tips = "photon.emitter.config.lifetimeByEmitterSpeed.multiplier") 31 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, min = 0, defaultValue = 1f, curveConfig = @CurveConfig(bound = {0, 1}, xAxis = "multiplier", yAxis = "emitter velocity")) 32 | protected NumberFunction multiplier = NumberFunction.constant(1); 33 | 34 | @Configurable(tips = "photon.emitter.config.lifetimeByEmitterSpeed.speedRange") 35 | @NumberRange(range = {0, 1000}) 36 | protected Range speedRange = new Range(0f, 1f); 37 | 38 | public int getLifetime(IParticle particle, IParticleEmitter emitter, int initialLifetime) { 39 | var value = emitter.getVelocity().length() * 20; 40 | return (int) (multiplier.get((value - speedRange.getA().floatValue()) / (speedRange.getB().floatValue() - speedRange.getA().floatValue()), () -> particle.getMemRandom(this)).floatValue() * initialLifetime); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/LightOverLifetimeSetting.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.Constant; 5 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 6 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunctionConfig; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.RandomConstant; 8 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.Curve; 9 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.CurveConfig; 10 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.RandomCurve; 11 | import com.lowdragmc.photon.client.gameobject.particle.IParticle; 12 | import lombok.Getter; 13 | import lombok.Setter; 14 | import net.fabricmc.api.EnvType; 15 | import net.fabricmc.api.Environment; 16 | 17 | /** 18 | * @author KilaBash 19 | * @date 2023/6/1 20 | * @implNote LightSetting 21 | */ 22 | @Environment(EnvType.CLIENT) 23 | @Setter 24 | @Getter 25 | public class LightOverLifetimeSetting extends ToggleGroup { 26 | 27 | @Configurable(tips = "photon.emitter.config.lights.skyLight") 28 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, isDecimals = false, defaultValue = 15, min = 0, max = 15, wheelDur = 1, curveConfig = @CurveConfig(xAxis = "lifetime", yAxis = "speed modifier")) 29 | protected NumberFunction skyLight = NumberFunction.constant(15); 30 | 31 | @Configurable(tips = "photon.emitter.config.lights.blockLight") 32 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, isDecimals = false, defaultValue = 15, min = 0, max = 15, wheelDur = 1, curveConfig = @CurveConfig(xAxis = "lifetime", yAxis = "speed modifier")) 33 | protected NumberFunction blockLight = NumberFunction.constant(15); 34 | 35 | public LightOverLifetimeSetting() { 36 | this.enable = true; 37 | } 38 | 39 | public int getLight(IParticle particle, float partialTicks) { 40 | int sky = skyLight.get(particle.getT(partialTicks), () -> particle.getMemRandom("sky-light")).intValue(); 41 | int block = blockLight.get(particle.getT(partialTicks), () -> particle.getMemRandom("block-light")).intValue(); 42 | return sky << 20 | block << 4; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/PhysicsSetting.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.Constant; 5 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 6 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunctionConfig; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.RandomConstant; 8 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.Curve; 9 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.CurveConfig; 10 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.RandomCurve; 11 | import com.lowdragmc.photon.client.gameobject.particle.IParticle; 12 | import lombok.Getter; 13 | import lombok.Setter; 14 | import net.fabricmc.api.EnvType; 15 | import net.fabricmc.api.Environment; 16 | 17 | /** 18 | * @author KilaBash 19 | * @date 2023/5/31 20 | * @implNote PhysicsSetting 21 | */ 22 | @Environment(EnvType.CLIENT) 23 | @Setter 24 | @Getter 25 | public class PhysicsSetting extends ToggleGroup { 26 | 27 | @Configurable(tips = "photon.emitter.config.physics.hasCollision") 28 | protected boolean hasCollision = true; 29 | @Configurable(tips = "photon.emitter.config.physics.removedWhenCollided") 30 | protected boolean removedWhenCollided = false; 31 | @Configurable(tips = "photon.emitter.config.physics.friction") 32 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, min = 0, max = 1, defaultValue = 1, curveConfig = @CurveConfig(xAxis = "duration", yAxis = "friction")) 33 | protected NumberFunction friction = NumberFunction.constant(1); 34 | @Configurable(tips = "photon.emitter.config.physics.gravity") 35 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, curveConfig = @CurveConfig(bound = {0, 1}, xAxis = "duration", yAxis = "gravity")) 36 | protected NumberFunction gravity = NumberFunction.constant(0); 37 | @Configurable(tips = "photon.emitter.config.physics.bounceChance") 38 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, min = 0, max = 1, defaultValue = 1, curveConfig = @CurveConfig(xAxis = "duration", yAxis = "bounce chance")) 39 | protected NumberFunction bounceChance = NumberFunction.constant(1); 40 | @Configurable(tips = "photon.emitter.config.physics.bounceRate") 41 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, min = 0, defaultValue = 1, curveConfig = @CurveConfig(bound = {0, 1}, xAxis = "duration", yAxis = "bounce rate")) 42 | protected NumberFunction bounceRate =NumberFunction.constant(1); 43 | @Configurable(tips = "photon.emitter.config.physics.bounceSpreadRate") 44 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, min = 0, curveConfig = @CurveConfig(bound = {0, 1}, xAxis = "duration", yAxis = "spread")) 45 | protected NumberFunction bounceSpreadRate = NumberFunction.constant(0); 46 | 47 | public float getFriction(IParticle particle) { 48 | return friction.get(particle.getT(), () -> particle.getMemRandom("friction")).floatValue(); 49 | } 50 | 51 | public float getGravity(IParticle particle) { 52 | return gravity.get(particle.getT(), () -> particle.getMemRandom("gravity")).floatValue(); 53 | } 54 | 55 | public float getBounceChance(IParticle particle) { 56 | return bounceChance.get(particle.getT(), () -> particle.getMemRandom("bounceChance")).floatValue(); 57 | } 58 | 59 | public float getBounceRate(IParticle particle) { 60 | return bounceRate.get(particle.getT(), () -> particle.getMemRandom("bounceRate")).floatValue(); 61 | } 62 | 63 | public float getBounceSpreadRate(IParticle particle) { 64 | return bounceSpreadRate.get(particle.getT(), () -> particle.getMemRandom("bounceSpreadRate")).floatValue(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/RotationBySpeedSetting.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.lowdraglib.gui.editor.annotation.NumberRange; 5 | import com.lowdragmc.lowdraglib.utils.Range; 6 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.Constant; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 8 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunctionConfig; 9 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.RandomConstant; 10 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.Curve; 11 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.CurveConfig; 12 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.RandomCurve; 13 | import com.lowdragmc.photon.client.gameobject.particle.TileParticle; 14 | import org.joml.Vector3f; 15 | import lombok.Getter; 16 | import lombok.Setter; 17 | import net.fabricmc.api.EnvType; 18 | import net.fabricmc.api.Environment; 19 | import net.minecraft.util.Mth; 20 | 21 | /** 22 | * @author KilaBash 23 | * @date 2023/5/30 24 | * @implNote RotationBySpeedSetting 25 | */ 26 | @Environment(EnvType.CLIENT) 27 | @Setter 28 | @Getter 29 | public class RotationBySpeedSetting extends ToggleGroup { 30 | 31 | @Configurable(tips = "photon.emitter.config.rotation.roll") 32 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, wheelDur = 10, curveConfig = @CurveConfig(bound = {0, 360}, xAxis = "speed", yAxis = "roll")) 33 | protected NumberFunction roll = NumberFunction.constant(0); 34 | 35 | @Configurable(tips = "photon.emitter.config.rotation.pitch") 36 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, wheelDur = 10, curveConfig = @CurveConfig(bound = {0, 360}, xAxis = "speed", yAxis = "pitch")) 37 | protected NumberFunction pitch = NumberFunction.constant(0); 38 | 39 | @Configurable(tips = "photon.emitter.config.rotation.yaw") 40 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, wheelDur = 10, curveConfig = @CurveConfig(bound = {0, 360}, xAxis = "speed", yAxis = "yaw")) 41 | protected NumberFunction yaw = NumberFunction.constant(0); 42 | 43 | @Configurable(tips = "photon.emitter.config.rotationBySpeed.speedRange") 44 | @NumberRange(range = {0, 1000}) 45 | protected Range speedRange = new Range(0f, 1f); 46 | 47 | public Vector3f getRotation(TileParticle particle) { 48 | var value = particle.getRealVelocity().length() * 20; 49 | var t = ((value - speedRange.getA().floatValue()) / (speedRange.getB().floatValue() - speedRange.getA().floatValue())); 50 | return new Vector3f( 51 | roll.get(t, () -> particle.getMemRandom("rbs0")).floatValue(), 52 | pitch.get(t, () -> particle.getMemRandom("rbs1")).floatValue(), 53 | yaw.get(t, () -> particle.getMemRandom("rbs2")).floatValue()).mul(Mth.TWO_PI / 360); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/RotationOverLifetimeSetting.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.Constant; 5 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 6 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunctionConfig; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.RandomConstant; 8 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.Curve; 9 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.CurveConfig; 10 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.RandomCurve; 11 | import com.lowdragmc.photon.client.gameobject.particle.IParticle; 12 | import org.joml.Vector3f; 13 | import lombok.Getter; 14 | import lombok.Setter; 15 | import net.fabricmc.api.EnvType; 16 | import net.fabricmc.api.Environment; 17 | import net.minecraft.util.Mth; 18 | 19 | /** 20 | * @author KilaBash 21 | * @date 2023/5/30 22 | * @implNote RotationOverLifetimeSetting 23 | */ 24 | @Environment(EnvType.CLIENT) 25 | @Setter 26 | @Getter 27 | public class RotationOverLifetimeSetting extends ToggleGroup { 28 | 29 | @Configurable(tips = "photon.emitter.config.rotation.roll") 30 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, wheelDur = 10, curveConfig = @CurveConfig(bound = {0, 360}, xAxis = "lifetime", yAxis = "roll")) 31 | protected NumberFunction roll = NumberFunction.constant(0); 32 | 33 | @Configurable(tips = "photon.emitter.config.rotation.pitch") 34 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, wheelDur = 10, curveConfig = @CurveConfig(bound = {0, 360}, xAxis = "lifetime", yAxis = "pitch")) 35 | protected NumberFunction pitch = NumberFunction.constant(0); 36 | 37 | @Configurable(tips = "photon.emitter.config.rotation.yaw") 38 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, wheelDur = 10, curveConfig = @CurveConfig(bound = {0, 360}, xAxis = "lifetime", yAxis = "yaw")) 39 | protected NumberFunction yaw = NumberFunction.constant(0); 40 | 41 | public Vector3f getRotation(IParticle particle, float partialTicks) { 42 | var t = particle.getT(partialTicks); 43 | return new Vector3f( 44 | yaw.get(t, () -> particle.getMemRandom("rol2")).floatValue(), 45 | pitch.get(t, () -> particle.getMemRandom("rol1")).floatValue(), 46 | roll.get(t, () -> particle.getMemRandom("rol0")).floatValue()).mul(Mth.TWO_PI / 360); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/SizeBySpeedSetting.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.lowdraglib.gui.editor.annotation.NumberRange; 5 | import com.lowdragmc.lowdraglib.utils.Range; 6 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.*; 7 | import com.lowdragmc.photon.client.gameobject.particle.TileParticle; 8 | import org.joml.Vector3f; 9 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.Curve; 10 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.CurveConfig; 11 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.RandomCurve; 12 | import lombok.Getter; 13 | import lombok.Setter; 14 | import net.fabricmc.api.EnvType; 15 | import net.fabricmc.api.Environment; 16 | 17 | /** 18 | * @author KilaBash 19 | * @date 2023/5/30 20 | * @implNote SizeOverLifetimeSetting 21 | */ 22 | @Environment(EnvType.CLIENT) 23 | @Setter 24 | @Getter 25 | public class SizeBySpeedSetting extends ToggleGroup { 26 | 27 | @Configurable(tips = "photon.emitter.config.sizeBySpeed.size") 28 | @NumberFunction3Config(common = @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, curveConfig = @CurveConfig(bound = {-1, 1}, xAxis = "speed", yAxis = "size"))) 29 | protected NumberFunction3 size = new NumberFunction3(1, 1, 1); 30 | 31 | @Configurable(tips = "photon.emitter.config.sizeBySpeed.speedRange") 32 | @NumberRange(range = {0, 1000}) 33 | protected Range speedRange = new Range(0f, 1f); 34 | 35 | public Vector3f getSize(TileParticle particle) { 36 | var value = particle.getRealVelocity().length() * 20; 37 | var t = (value - speedRange.getA().floatValue()) / (speedRange.getB().floatValue() - speedRange.getA().floatValue()); 38 | return size.get(t, () -> particle.getMemRandom("sbs0")); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/SizeOverLifetimeSetting.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.lowdraglib.syncdata.IPersistedSerializable; 5 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.*; 6 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.Curve; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.CurveConfig; 8 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.RandomCurve; 9 | import com.lowdragmc.photon.client.gameobject.particle.IParticle; 10 | import net.minecraft.nbt.CompoundTag; 11 | import org.joml.Vector3f; 12 | import lombok.Getter; 13 | import lombok.Setter; 14 | import net.fabricmc.api.EnvType; 15 | import net.fabricmc.api.Environment; 16 | 17 | /** 18 | * @author KilaBash 19 | * @date 2023/5/30 20 | * @implNote SizeOverLifetimeSetting 21 | */ 22 | @Environment(EnvType.CLIENT) 23 | @Setter 24 | @Getter 25 | public class SizeOverLifetimeSetting extends ToggleGroup implements IPersistedSerializable { 26 | 27 | @Configurable(tips = "photon.emitter.config.sizeOverLifetime.size") 28 | @NumberFunction3Config(common = @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, curveConfig = @CurveConfig(bound = {-1, 1}, xAxis = "lifetime", yAxis = "size"))) 29 | protected NumberFunction3 size = new NumberFunction3(1, 1, 1); 30 | 31 | public Vector3f getSize(IParticle particle, float partialTicks) { 32 | return size.get(particle.getT(partialTicks), () -> particle.getMemRandom("sol0")); 33 | } 34 | 35 | @Override 36 | public void deserializeNBT(CompoundTag tag) { 37 | IPersistedSerializable.super.deserializeNBT(tag); 38 | // compatible with old version 39 | if (tag.contains("scale")) { 40 | var number = NumberFunction.deserializeWrapper(tag.getCompound("scale")); 41 | size = new NumberFunction3(number, NumberFunction.copy(number), NumberFunction.copy(number)); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/ToggleGroup.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.configurator.IToggleConfigurable; 4 | import com.lowdragmc.lowdraglib.syncdata.annotation.Persisted; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | /** 9 | * @author KilaBash 10 | * @date 2023/5/30 11 | * @implNote ToggleGroup 12 | */ 13 | public class ToggleGroup implements IToggleConfigurable { 14 | 15 | @Getter 16 | @Setter 17 | @Persisted 18 | protected boolean enable; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/UVAnimationSetting.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.lowdraglib.gui.editor.annotation.NumberRange; 5 | import com.lowdragmc.lowdraglib.utils.Range; 6 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.Constant; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 8 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunctionConfig; 9 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.RandomConstant; 10 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.Curve; 11 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.CurveConfig; 12 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.RandomCurve; 13 | import com.lowdragmc.photon.client.gameobject.particle.IParticle; 14 | import lombok.Getter; 15 | import lombok.Setter; 16 | import net.fabricmc.api.EnvType; 17 | import net.fabricmc.api.Environment; 18 | import org.joml.Vector4f; 19 | 20 | /** 21 | * @author KilaBash 22 | * @date 2023/5/31 23 | * @implNote UVAnimation 24 | */ 25 | @Environment(EnvType.CLIENT) 26 | public class UVAnimationSetting extends ToggleGroup { 27 | public enum Animation { 28 | WholeSheet, 29 | SingleRow, 30 | } 31 | 32 | @Setter 33 | @Getter 34 | @Configurable(tips = "photon.emitter.config.uvAnimation.tiles") 35 | @NumberRange(range = {1, Integer.MAX_VALUE}) 36 | protected Range tiles = new Range(1, 1); 37 | 38 | @Setter 39 | @Getter 40 | @Configurable(tips = "photon.emitter.config.uvAnimation.animation") 41 | protected Animation animation = Animation.WholeSheet; 42 | 43 | @Setter 44 | @Getter 45 | @Configurable(tips = "photon.emitter.config.uvAnimation.frameOverTime") 46 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class, Curve.class, RandomCurve.class}, min = 0, curveConfig = @CurveConfig(bound = {0, 4}, xAxis = "lifetime", yAxis = "frame over time")) 47 | protected NumberFunction frameOverTime = NumberFunction.constant(0); 48 | 49 | @Setter 50 | @Getter 51 | @Configurable(tips = "photon.emitter.config.uvAnimation.startFrame") 52 | @NumberFunctionConfig(types = {Constant.class, RandomConstant.class}, min = 0) 53 | protected NumberFunction startFrame = NumberFunction.constant(0); 54 | 55 | @Setter 56 | @Getter 57 | @Configurable(tips = "photon.emitter.config.uvAnimation.cycle") 58 | @NumberRange(range = {0, Integer.MAX_VALUE}, wheel = 1) 59 | protected float cycle = 1; 60 | 61 | public Vector4f getUVs(IParticle particle, float partialTicks) { 62 | var t = particle.getT(partialTicks); 63 | var cellU = 1f / tiles.getA().intValue(); 64 | var cellV = 1f / tiles.getB().intValue(); 65 | var currentFrame = this.startFrame.get(t, () -> particle.getMemRandom("startFrame")).floatValue(); 66 | currentFrame += cycle * frameOverTime.get(t, () -> particle.getMemRandom("frameOverTime")).floatValue(); 67 | float u0, v0, u1, v1; 68 | var cellSize = tiles.getA().intValue(); 69 | if (animation == Animation.WholeSheet) { 70 | int X = (int) (currentFrame % cellSize); 71 | int Y = (int) (currentFrame / cellSize); 72 | u0 = X * cellU; 73 | v0 = Y * cellV; 74 | } else { 75 | int X = (int) (currentFrame % cellSize); 76 | int Y = (int) (particle.getMemRandom("randomRow") * tiles.getB().intValue()); 77 | u0 = X * cellU; 78 | v0 = Y * cellV; 79 | } 80 | u1 = u0 + cellU; 81 | v1 = v0 + cellV; 82 | return new Vector4f(u0, v0, u1, v1); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/material/BlendMode.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.material; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.mojang.blaze3d.systems.RenderSystem; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import net.fabricmc.api.EnvType; 8 | import net.fabricmc.api.Environment; 9 | 10 | import static com.mojang.blaze3d.platform.GlStateManager.DestFactor; 11 | import static com.mojang.blaze3d.platform.GlStateManager.SourceFactor; 12 | 13 | @Environment(value=EnvType.CLIENT) 14 | public class BlendMode { 15 | public enum BlendFuc { 16 | ADD(32774), 17 | sub(32778), 18 | REVERSE_sub(32779), 19 | MIN(32775), 20 | MAX(32776); 21 | public final int op; 22 | 23 | BlendFuc(int op) { 24 | this.op = op; 25 | } 26 | } 27 | 28 | @Getter @Setter 29 | @Configurable 30 | private boolean enableBlend; 31 | @Getter @Setter 32 | @Configurable 33 | private SourceFactor srcColorFactor; 34 | @Getter @Setter 35 | @Configurable 36 | private DestFactor dstColorFactor; 37 | @Getter @Setter 38 | @Configurable 39 | private SourceFactor srcAlphaFactor; 40 | @Getter @Setter 41 | @Configurable 42 | private DestFactor dstAlphaFactor; 43 | @Getter @Setter 44 | @Configurable 45 | private BlendFuc blendFunc; 46 | 47 | private BlendMode(boolean enableBlend, SourceFactor srcColorFactor, DestFactor dstColorFactor, SourceFactor srcAlphaFactor, DestFactor dstAlphaFactor, BlendFuc blendFunc) { 48 | this.srcColorFactor = srcColorFactor; 49 | this.dstColorFactor = dstColorFactor; 50 | this.srcAlphaFactor = srcAlphaFactor; 51 | this.dstAlphaFactor = dstAlphaFactor; 52 | this.enableBlend = enableBlend; 53 | this.blendFunc = blendFunc; 54 | } 55 | 56 | public BlendMode() { 57 | this(true, SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ONE, DestFactor.ZERO, BlendFuc.ADD); 58 | } 59 | 60 | public BlendMode(SourceFactor srcFactor, DestFactor dstFactor, BlendFuc blendFunc) { 61 | this(true, srcFactor, dstFactor, srcFactor, dstFactor, blendFunc); 62 | } 63 | 64 | public BlendMode(SourceFactor srcColorFactor, DestFactor dstColorFactor, SourceFactor srcAlphaFactor, DestFactor dstAlphaFactor, BlendFuc blendFunc) { 65 | this(true, srcColorFactor, dstColorFactor, srcAlphaFactor, dstAlphaFactor, blendFunc); 66 | } 67 | 68 | public void apply() { 69 | if (!this.enableBlend) { 70 | RenderSystem.disableBlend(); 71 | return; 72 | } 73 | RenderSystem.enableBlend(); 74 | RenderSystem.defaultBlendFunc(); 75 | RenderSystem.blendEquation(this.blendFunc.op); 76 | RenderSystem.blendFuncSeparate(this.srcColorFactor, this.dstColorFactor, this.srcAlphaFactor, this.dstAlphaFactor); 77 | } 78 | 79 | public boolean equals(Object object) { 80 | if (this == object) { 81 | return true; 82 | } 83 | if (!(object instanceof BlendMode blendMode)) { 84 | return false; 85 | } 86 | if (this.blendFunc != blendMode.blendFunc) { 87 | return false; 88 | } 89 | if (this.dstAlphaFactor != blendMode.dstAlphaFactor) { 90 | return false; 91 | } 92 | if (this.dstColorFactor != blendMode.dstColorFactor) { 93 | return false; 94 | } 95 | if (this.enableBlend != blendMode.enableBlend) { 96 | return false; 97 | } 98 | if (this.srcAlphaFactor != blendMode.srcAlphaFactor) { 99 | return false; 100 | } 101 | return this.srcColorFactor == blendMode.srcColorFactor; 102 | } 103 | 104 | public int hashCode() { 105 | int i = this.srcColorFactor.value; 106 | i = 31 * i + this.srcAlphaFactor.value; 107 | i = 31 * i + this.dstColorFactor.value; 108 | i = 31 * i + this.dstAlphaFactor.value; 109 | i = 31 * i + this.blendFunc.op; 110 | i = 31 * i + (this.enableBlend ? 1 : 0); 111 | return i; 112 | } 113 | 114 | } 115 | 116 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/material/BlockTextureSheetMaterial.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.material; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.configurator.ConfiguratorGroup; 4 | import net.fabricmc.api.EnvType; 5 | import net.fabricmc.api.Environment; 6 | import net.minecraft.world.inventory.InventoryMenu; 7 | 8 | @Environment(EnvType.CLIENT) 9 | public class BlockTextureSheetMaterial extends TextureMaterial { 10 | 11 | public BlockTextureSheetMaterial() { 12 | super(InventoryMenu.BLOCK_ATLAS); 13 | } 14 | 15 | @Override 16 | public void buildConfigurator(ConfiguratorGroup father) { 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/material/IMaterial.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.material; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.configurator.IConfigurable; 4 | import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; 5 | import com.lowdragmc.lowdraglib.syncdata.ITagSerializable; 6 | import net.fabricmc.api.EnvType; 7 | import net.fabricmc.api.Environment; 8 | import net.minecraft.nbt.CompoundTag; 9 | 10 | import javax.annotation.ParametersAreNonnullByDefault; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * @author KilaBash 16 | * @date 2023/5/29 17 | * @implNote Material 18 | */ 19 | @Environment(EnvType.CLIENT) 20 | @ParametersAreNonnullByDefault 21 | public interface IMaterial extends IConfigurable, ITagSerializable { 22 | 23 | List> MATERIALS = new ArrayList<>(List.of( 24 | TextureMaterial.class, CustomShaderMaterial.class, BlockTextureSheetMaterial.class 25 | )); 26 | 27 | static IMaterial deserializeWrapper(CompoundTag tag) { 28 | var type = tag.getString("_type"); 29 | for (var clazz : MATERIALS) { 30 | if (clazz.getSimpleName().equals(type)) { 31 | try { 32 | IMaterial shape = clazz.getConstructor().newInstance(); 33 | shape.deserializeNBT(tag); 34 | return shape; 35 | } catch (Throwable ignored) {} 36 | } 37 | } 38 | return null; 39 | } 40 | 41 | void begin(boolean isInstancing); 42 | 43 | void end(boolean isInstancing); 44 | 45 | IGuiTexture preview(); 46 | 47 | @Override 48 | default CompoundTag serializeNBT() { 49 | var tag = new CompoundTag(); 50 | tag.putString("_type", getClass().getSimpleName()); 51 | return serializeNBT(tag); 52 | } 53 | 54 | CompoundTag serializeNBT(CompoundTag tag); 55 | 56 | default IMaterial copy() { 57 | return deserializeWrapper(serializeNBT()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/number/Constant.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.number; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.configurator.NumberConfigurator; 4 | import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; 5 | import com.lowdragmc.photon.gui.editor.configurator.NumberFunctionConfigurator; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import net.minecraft.nbt.CompoundTag; 9 | import net.minecraft.nbt.Tag; 10 | import net.minecraft.util.RandomSource; 11 | 12 | import java.util.function.Supplier; 13 | 14 | /** 15 | * @author KilaBash 16 | * @date 2023/5/26 17 | * @implNote Constant 18 | */ 19 | public class Constant implements NumberFunction { 20 | 21 | @Setter 22 | @Getter 23 | private Number number; 24 | 25 | public Constant() { 26 | number = 0; 27 | } 28 | 29 | public Constant(Number number) { 30 | this.number = number; 31 | } 32 | 33 | public Constant(NumberFunctionConfig config) { 34 | this(config.isDecimals() ? config.defaultValue() : ((int) config.defaultValue())); 35 | } 36 | 37 | @Override 38 | public Number get(RandomSource randomSource, float t) { 39 | return number; 40 | } 41 | 42 | @Override 43 | public Number get(float t, Supplier lerp) { 44 | return number; 45 | } 46 | 47 | @Override 48 | public NumberFunction copy() { 49 | return new Constant(number); 50 | } 51 | 52 | @Override 53 | public boolean equals(Object obj) { 54 | if (obj instanceof Constant constant) { 55 | return number.equals(constant.number); 56 | } 57 | return super.equals(obj); 58 | } 59 | 60 | @Override 61 | public void createConfigurator(WidgetGroup group, NumberFunctionConfigurator configurator) { 62 | var widget = new NumberConfigurator("", () -> configurator.getConfig().isDecimals() ? number.floatValue() : number.intValue(), number -> { 63 | setNumber(number); 64 | configurator.updateValue(this); 65 | }, number, true); 66 | group.addWidget(widget); 67 | widget.setRange(configurator.getConfig().min(), configurator.getConfig().max()); 68 | widget.setWheel(configurator.getConfig().isDecimals() ? configurator.getConfig().wheelDur() : Math.max(1, (int) configurator.getConfig().wheelDur())); 69 | widget.setConfiguratorContainer(configurator.getConfiguratorContainer()); 70 | widget.init(group.getSize().width); 71 | } 72 | 73 | @Override 74 | public CompoundTag serializeNBT() { 75 | var tag = new CompoundTag(); 76 | if (number instanceof Float || number instanceof Double) { 77 | tag.putFloat("number", number.floatValue()); 78 | } else { 79 | tag.putInt("number", number.intValue()); 80 | } 81 | return tag; 82 | } 83 | 84 | @Override 85 | public void deserializeNBT(CompoundTag nbt) { 86 | if (nbt.contains("number", Tag.TAG_INT)) { 87 | number = nbt.getInt("number"); 88 | } else { 89 | number = nbt.getFloat("number"); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/number/NumberFunction.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.number; 2 | 3 | import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; 4 | import com.lowdragmc.lowdraglib.syncdata.ITagSerializable; 5 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.color.Color; 6 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.color.Gradient; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.color.RandomColor; 8 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.color.RandomGradient; 9 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.Curve; 10 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.RandomCurve; 11 | import com.lowdragmc.photon.gui.editor.configurator.NumberFunctionConfigurator; 12 | import net.minecraft.nbt.CompoundTag; 13 | import net.minecraft.nbt.Tag; 14 | import net.minecraft.util.RandomSource; 15 | 16 | import java.util.HashMap; 17 | import java.util.Map; 18 | import java.util.function.Supplier; 19 | 20 | /** 21 | * @author KilaBash 22 | * @date 2023/5/25 23 | * @implNote NumberFunction 24 | */ 25 | public interface NumberFunction extends ITagSerializable { 26 | Map> REGISTRY = new HashMap<>(Map.ofEntries( 27 | Map.entry(Color.class.getSimpleName(), Color.class), 28 | Map.entry(RandomColor.class.getSimpleName(), RandomColor.class), 29 | Map.entry(Constant.class.getSimpleName(), Constant.class), 30 | Map.entry(RandomConstant.class.getSimpleName(), RandomConstant.class), 31 | Map.entry(Curve.class.getSimpleName(), Curve.class), 32 | Map.entry(RandomCurve.class.getSimpleName(), RandomCurve.class), 33 | Map.entry(Gradient.class.getSimpleName(), Gradient.class), 34 | Map.entry(RandomGradient.class.getSimpleName(), RandomGradient.class) 35 | )); 36 | 37 | static NumberFunction constant(Number constant) { 38 | return new Constant(constant); 39 | } 40 | 41 | static NumberFunction color(Number color) { 42 | return new Color(color); 43 | } 44 | 45 | static CompoundTag serializeWrapper(NumberFunction value) { 46 | var tag = value.serializeNBT(); 47 | tag.putString("_type", value.getClass().getSimpleName()); 48 | return tag; 49 | } 50 | 51 | static NumberFunction deserializeWrapper(CompoundTag tag) { 52 | var type = REGISTRY.get(tag.getString("_type")); 53 | if (type != null) { 54 | try { 55 | var function = type.getConstructor().newInstance(); 56 | function.deserializeNBT(tag); 57 | return function; 58 | } catch (Throwable ignored) {} 59 | } 60 | return constant(0); 61 | } 62 | 63 | static NumberFunction copy(NumberFunction function) { 64 | return function.copy(); 65 | } 66 | 67 | static boolean isEqual(NumberFunction a, NumberFunction b) { 68 | return a.equals(b); 69 | } 70 | 71 | NumberFunction copy(); 72 | 73 | void createConfigurator(WidgetGroup group, NumberFunctionConfigurator configurator); 74 | 75 | default Number get(RandomSource randomSource, float t) { 76 | return get(t, randomSource::nextFloat); 77 | } 78 | 79 | Number get(float t, Supplier lerp); 80 | 81 | } 82 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/number/NumberFunction3.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.number; 2 | 3 | import com.google.common.base.Suppliers; 4 | import org.joml.Vector3f; 5 | import net.minecraft.util.RandomSource; 6 | 7 | import java.util.function.Supplier; 8 | 9 | /** 10 | * @author KilaBash 11 | * @date 2023/5/30 12 | * @implNote NumberFunction3 13 | */ 14 | public class NumberFunction3 { 15 | public NumberFunction x, y, z; 16 | 17 | public NumberFunction3(NumberFunction x, NumberFunction y, NumberFunction z) { 18 | this.x = x; 19 | this.y = y; 20 | this.z = z; 21 | } 22 | 23 | public NumberFunction3(Number x, Number y, Number z) { 24 | this.x = NumberFunction.constant(x); 25 | this.y = NumberFunction.constant(y); 26 | this.z = NumberFunction.constant(z); 27 | } 28 | 29 | public Vector3f get(RandomSource randomSource, float t) { 30 | var lerp = Suppliers.memoize(randomSource::nextFloat); 31 | return new Vector3f(x.get(t, lerp).floatValue(), y.get(t, lerp).floatValue(), z.get(t, lerp).floatValue()); 32 | } 33 | 34 | public Vector3f get(float t, Supplier lerp) { 35 | return new Vector3f(x.get(t, lerp).floatValue(), y.get(t, lerp).floatValue(), z.get(t, lerp).floatValue()); 36 | } 37 | 38 | @Override 39 | public boolean equals(Object obj) { 40 | if (this == obj) return true; 41 | return obj instanceof NumberFunction3 numberFunction3 && 42 | x.equals(numberFunction3.x) && 43 | y.equals(numberFunction3.y) && 44 | z.equals(numberFunction3.z); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/number/NumberFunction3Config.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.number; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author KilaBash 10 | * @date 2023/5/27 11 | * @implNote NumberFunction3Config 12 | */ 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target({ElementType.FIELD}) 15 | public @interface NumberFunction3Config { 16 | NumberFunctionConfig common() default @NumberFunctionConfig; 17 | NumberFunctionConfig[] xyz() default {}; 18 | boolean isSeperatedDefault() default false; 19 | boolean allowSeperated() default true; 20 | boolean affectX() default true; 21 | boolean affectY() default true; 22 | boolean affectZ() default true; 23 | } 24 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/number/NumberFunctionConfig.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.number; 2 | 3 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.curve.CurveConfig; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * @author KilaBash 12 | * @date 2023/5/27 13 | * @implNote NumberFunctionConfig 14 | */ 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Target({ElementType.FIELD}) 17 | public @interface NumberFunctionConfig { 18 | Class[] types() default { Constant.class }; 19 | float min() default Integer.MIN_VALUE; 20 | float max() default Integer.MAX_VALUE; 21 | float wheelDur() default 0.1f; 22 | float defaultValue() default 0; 23 | boolean isDecimals() default true; 24 | CurveConfig curveConfig() default @CurveConfig(); 25 | } 26 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/number/color/Color.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.number.color; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.configurator.ColorConfigurator; 4 | import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; 5 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.Constant; 6 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunctionConfig; 8 | import com.lowdragmc.photon.gui.editor.configurator.NumberFunctionConfigurator; 9 | 10 | /** 11 | * @author KilaBash 12 | * @date 2023/5/27 13 | * @implNote Color 14 | */ 15 | public class Color extends Constant { 16 | 17 | public Color() { 18 | super(-1); 19 | } 20 | 21 | public Color(Number number) { 22 | super(number); 23 | } 24 | 25 | public Color(NumberFunctionConfig config) { 26 | super(config); 27 | } 28 | 29 | @Override 30 | public void createConfigurator(WidgetGroup group, NumberFunctionConfigurator configurator) { 31 | var widget = new ColorConfigurator("", () -> getNumber().intValue(), number -> { 32 | setNumber(number); 33 | configurator.updateValue(this);; 34 | }, getNumber().intValue(), true); 35 | widget.setConfiguratorContainer(configurator.getConfiguratorContainer()); 36 | widget.init(group.getSize().width); 37 | group.addWidget(widget); 38 | } 39 | 40 | @Override 41 | public NumberFunction copy() { 42 | return new Color(getNumber()); 43 | } 44 | 45 | @Override 46 | public boolean equals(Object obj) { 47 | if (obj instanceof Color color) { 48 | return getNumber().equals(color.getNumber()); 49 | } 50 | return super.equals(obj); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/number/color/GradientColorTexture.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.number.color; 2 | 3 | import com.lowdragmc.lowdraglib.gui.texture.TransformTexture; 4 | import com.lowdragmc.lowdraglib.utils.GradientColor; 5 | import com.mojang.blaze3d.systems.RenderSystem; 6 | import com.mojang.blaze3d.vertex.*; 7 | import net.fabricmc.api.EnvType; 8 | import net.fabricmc.api.Environment; 9 | import net.minecraft.client.gui.GuiGraphics; 10 | import net.minecraft.client.renderer.GameRenderer; 11 | 12 | import java.util.function.Function; 13 | 14 | /** 15 | * @author KilaBash 16 | * @date 2023/5/30 17 | * @implNote GradientColorTexture 18 | */ 19 | public class GradientColorTexture extends TransformTexture { 20 | 21 | public final GradientColor gradientColor; 22 | 23 | public GradientColorTexture(GradientColor gradientColor) { 24 | this.gradientColor = gradientColor; 25 | } 26 | 27 | @Override 28 | @Environment(EnvType.CLIENT) 29 | protected void drawInternal(GuiGraphics graphics, int mouseX, int mouseY, float posx, float posy, int width, int height) { 30 | // render color bar 31 | RenderSystem.enableBlend(); 32 | RenderSystem.defaultBlendFunc(); 33 | var mat = graphics.pose().last().pose(); 34 | Tesselator tesselator = Tesselator.getInstance(); 35 | BufferBuilder buffer = tesselator.getBuilder(); 36 | RenderSystem.setShader(GameRenderer::getPositionColorShader); 37 | buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); 38 | 39 | Function getXPosition = coordX -> posx + width * coordX; 40 | var yh = height + posy; 41 | RandomGradientColorTexture.drawGradient(posy, width, mat, buffer, getXPosition, yh, gradientColor); 42 | 43 | tesselator.end(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/number/color/RandomColor.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.number.color; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.configurator.ColorConfigurator; 4 | import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; 5 | import com.lowdragmc.lowdraglib.utils.ColorUtils; 6 | import com.lowdragmc.lowdraglib.utils.Size; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 8 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunctionConfig; 9 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.RandomConstant; 10 | import com.lowdragmc.photon.gui.editor.configurator.NumberFunctionConfigurator; 11 | import net.minecraft.util.RandomSource; 12 | 13 | import java.util.function.Supplier; 14 | 15 | import static com.lowdragmc.lowdraglib.utils.ColorUtils.*; 16 | 17 | /** 18 | * @author KilaBash 19 | * @date 2023/5/27 20 | * @implNote RandomColor 21 | */ 22 | public class RandomColor extends RandomConstant { 23 | public RandomColor() { 24 | this(0xff000000, 0xffffffff); 25 | } 26 | 27 | public RandomColor(Number a, Number b) { 28 | super(a, b, false); 29 | } 30 | 31 | public RandomColor(NumberFunctionConfig config) { 32 | super(config); 33 | } 34 | 35 | @Override 36 | public NumberFunction copy() { 37 | return new RandomColor(getA(), getB()); 38 | } 39 | 40 | @Override 41 | public boolean equals(Object obj) { 42 | if (obj instanceof RandomColor randomColor) { 43 | return getA().equals(randomColor.getA()) && getB().equals(randomColor.getB()); 44 | } 45 | return super.equals(obj); 46 | } 47 | 48 | @Override 49 | public Number get(float t, Supplier lerp) { 50 | int colorA = getA().intValue(); 51 | int colorB = getB().intValue(); 52 | return ColorUtils.blendColor(colorA, colorB, lerp.get()); 53 | } 54 | 55 | private int randomColor(RandomSource randomSource, int minA, int maxA, int minR, int maxR, int minG, int maxG, int minB, int maxB) { 56 | return ((minR + randomSource.nextInt(maxA + 1 - minA)) << 24) | 57 | ((minR + randomSource.nextInt(maxR + 1 - minR)) << 16) | 58 | ((minG + randomSource.nextInt(maxG + 1 - minG)) << 8) | 59 | ((minB + randomSource.nextInt(maxB + 1 - minB))) ; 60 | } 61 | 62 | private int randomColor(RandomSource randomSource, int colorA, int colorB) { 63 | return randomColor(randomSource, Math.min(alphaI(colorA), alphaI(colorB)), Math.max(alphaI(colorA), alphaI(colorB)), 64 | Math.min(redI(colorA), redI(colorB)), Math.max(redI(colorA), redI(colorB)), 65 | Math.min(greenI(colorA), greenI(colorB)), Math.max(greenI(colorA), greenI(colorB)), 66 | Math.min(blueI(colorA), blueI(colorB)), Math.max(blueI(colorA), blueI(colorB))); 67 | } 68 | 69 | @Override 70 | public void createConfigurator(WidgetGroup group, NumberFunctionConfigurator configurator) { 71 | var size = group.getSize(); 72 | var aGroup = new WidgetGroup(0, 0, size.width / 2, size.height); 73 | var bGroup = new WidgetGroup(size.width / 2, 0, size.width / 2, size.height); 74 | group.addWidget(aGroup); 75 | group.addWidget(bGroup); 76 | 77 | setupNumberConfigurator(size, aGroup, new ColorConfigurator("", () -> getA().intValue(), number -> { 78 | setA(number); 79 | configurator.updateValue(this); 80 | }, getA().intValue(), true), configurator); 81 | setupNumberConfigurator(size, bGroup, new ColorConfigurator("", () -> getB().intValue(), number -> { 82 | setB(number); 83 | configurator.updateValue(this); 84 | }, getB().intValue(), true), configurator); 85 | } 86 | 87 | private void setupNumberConfigurator(Size size, WidgetGroup group, ColorConfigurator widget, NumberFunctionConfigurator configurator) { 88 | group.addWidget(widget); 89 | widget.setConfiguratorContainer(configurator.getConfiguratorContainer()); 90 | widget.init(size.width / 2); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/number/color/RandomGradientColorTexture.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.number.color; 2 | 3 | import com.lowdragmc.lowdraglib.gui.texture.TransformTexture; 4 | import com.lowdragmc.lowdraglib.utils.GradientColor; 5 | import com.mojang.blaze3d.systems.RenderSystem; 6 | import com.mojang.blaze3d.vertex.*; 7 | import net.fabricmc.api.EnvType; 8 | import net.fabricmc.api.Environment; 9 | import net.minecraft.client.gui.GuiGraphics; 10 | import net.minecraft.client.renderer.GameRenderer; 11 | import org.joml.Matrix4f; 12 | 13 | import java.util.function.Function; 14 | 15 | /** 16 | * @author KilaBash 17 | * @date 2023/5/30 18 | * @implNote RandomGradientColorTexture 19 | */ 20 | public class RandomGradientColorTexture extends TransformTexture { 21 | 22 | public final GradientColor gradientColor0; 23 | public final GradientColor gradientColor1; 24 | 25 | public RandomGradientColorTexture(GradientColor gradientColor0, GradientColor gradientColor1) { 26 | this.gradientColor0 = gradientColor0; 27 | this.gradientColor1 = gradientColor1; 28 | } 29 | 30 | @Override 31 | @Environment(EnvType.CLIENT) 32 | protected void drawInternal(GuiGraphics graphics, int mouseX, int mouseY, float posx, float posy, int width, int height) { 33 | // render color bar 34 | RenderSystem.enableBlend(); 35 | RenderSystem.defaultBlendFunc(); 36 | var mat = graphics.pose().last().pose(); 37 | Tesselator tesselator = Tesselator.getInstance(); 38 | BufferBuilder buffer = tesselator.getBuilder(); 39 | RenderSystem.setShader(GameRenderer::getPositionColorShader); 40 | buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); 41 | 42 | Function getXPosition = coordX -> posx + width * coordX; 43 | var yh = height / 2f + posy; 44 | drawGradient(posy, width, mat, buffer, getXPosition, yh, gradientColor0); 45 | 46 | posy += height / 2f; 47 | yh = height / 2f + posy; 48 | drawGradient(posy, width, mat, buffer, getXPosition, yh, gradientColor1); 49 | 50 | tesselator.end(); 51 | } 52 | 53 | static void drawGradient(float posy, int width, Matrix4f mat, BufferBuilder buffer, Function getXPosition, float yh, GradientColor gradientColor) { 54 | for (int i = 0; i < width; i++) { 55 | var x = getXPosition.apply(i * 1f / width); 56 | var xw = getXPosition.apply((i + 1f) / width); 57 | int startColor = gradientColor.getColor(i * 1f / width); 58 | int endColor = gradientColor.getColor((i + 1f) / width); 59 | float startAlpha = (float)(startColor >> 24 & 255) / 255.0F; 60 | float startRed = (float)(startColor >> 16 & 255) / 255.0F; 61 | float startGreen = (float)(startColor >> 8 & 255) / 255.0F; 62 | float startBlue = (float)(startColor & 255) / 255.0F; 63 | float endAlpha = (float)(endColor >> 24 & 255) / 255.0F; 64 | float endRed = (float)(endColor >> 16 & 255) / 255.0F; 65 | float endGreen = (float)(endColor >> 8 & 255) / 255.0F; 66 | float endBlue = (float)(endColor & 255) / 255.0F; 67 | 68 | buffer.vertex(mat, xw, posy, 0).color(endRed, endGreen, endBlue, endAlpha).endVertex(); 69 | buffer.vertex(mat, x, posy, 0).color(startRed, startGreen, startBlue, startAlpha).endVertex(); 70 | buffer.vertex(mat, x, yh, 0).color(startRed, startGreen, startBlue, startAlpha).endVertex(); 71 | buffer.vertex(mat, xw, yh, 0).color(endRed, endGreen, endBlue, endAlpha).endVertex(); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/number/curve/CurveConfig.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.number.curve; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author KilaBash 10 | * @date 2023/5/29 11 | * @implNote CurveConfig 12 | */ 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target({ElementType.FIELD}) 15 | public @interface CurveConfig { 16 | float[] bound() default {}; 17 | String xAxis() default ""; 18 | String yAxis() default ""; 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/number/curve/CurveTexture.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.number.curve; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.ColorPattern; 4 | import com.lowdragmc.lowdraglib.gui.texture.TransformTexture; 5 | import com.lowdragmc.lowdraglib.gui.util.DrawerHelper; 6 | import lombok.Setter; 7 | import net.fabricmc.api.EnvType; 8 | import net.fabricmc.api.Environment; 9 | import net.minecraft.client.gui.GuiGraphics; 10 | import net.minecraft.world.phys.Vec2; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | /** 16 | * @author KilaBash 17 | * @date 2023/5/30 18 | * @implNote CurveTexture 19 | */ 20 | public class CurveTexture extends TransformTexture { 21 | private final ECBCurves curves; 22 | 23 | private int color = ColorPattern.T_RED.color; 24 | 25 | @Setter 26 | private float width = 0.5f; 27 | 28 | public CurveTexture(ECBCurves curves) { 29 | this.curves = curves; 30 | } 31 | 32 | @Override 33 | public CurveTexture setColor(int color) { 34 | this.color = color; 35 | return this; 36 | } 37 | 38 | @Override 39 | @Environment(EnvType.CLIENT) 40 | protected void drawInternal(GuiGraphics graphics, int mouseX, int mouseY, float x, float y, int width, int height) { 41 | List points = new ArrayList<>(); 42 | for (int i = 0; i < width; i++) { 43 | float coordX = i * 1f / width; 44 | points.add(new Vec2(coordX, curves.getCurveY(coordX))); 45 | } 46 | points.add(new Vec2(1, curves.getCurveY(1))); 47 | DrawerHelper.drawLines(graphics, points.stream().map(coord -> new Vec2(x + width * coord.x, y + height * (1 - coord.y))).toList(), color, color, this.width); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/number/curve/ECBCurves.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.number.curve; 2 | 3 | import com.lowdragmc.lowdraglib.syncdata.ITagSerializable; 4 | import com.lowdragmc.lowdraglib.utils.curve.ExplicitCubicBezierCurve2; 5 | import net.minecraft.nbt.ListTag; 6 | import net.minecraft.nbt.Tag; 7 | import net.minecraft.world.phys.Vec2; 8 | 9 | import java.util.ArrayList; 10 | 11 | /** 12 | * @author KilaBash 13 | * @date 2023/5/29 14 | * @implNote ECBCurves 15 | */ 16 | public class ECBCurves extends ArrayList implements ITagSerializable { 17 | 18 | public ECBCurves() { 19 | add(new ExplicitCubicBezierCurve2(new Vec2(0, 0.5f), new Vec2(0.1f, 0.5f), new Vec2(0.9f, 0.5f), new Vec2(1, 0.5f))); 20 | } 21 | 22 | public ECBCurves(float... data) { 23 | for (int i = 0; i < data.length; i+=8) { 24 | add(new ExplicitCubicBezierCurve2(new Vec2(data[i], data[i + 1]), new Vec2(data[i + 2], data[i + 3]), new Vec2(data[i + 4], data[i + 5]), new Vec2(data[i + 6], data[i + 7]))); 25 | } 26 | } 27 | 28 | public float getCurveY(float x) { 29 | var value = get(0).p0.y; 30 | var found = x < get(0).p0.x; 31 | if (!found) { 32 | for (var curve : this) { 33 | if (x >= curve.p0.x && x <= curve.p1.x) { 34 | value = curve.getPoint((x - curve.p0.x) / (curve.p1.x - curve.p0.x)).y; 35 | found = true; 36 | break; 37 | } 38 | } 39 | } 40 | if (!found) { 41 | value = get(size() - 1).p1.y; 42 | } 43 | return value; 44 | } 45 | 46 | @Override 47 | public ListTag serializeNBT() { 48 | var list = new ListTag(); 49 | for (var curve : this) { 50 | list.add(curve.serializeNBT()); 51 | } 52 | return list; 53 | } 54 | 55 | @Override 56 | public void deserializeNBT(ListTag list) { 57 | clear(); 58 | for (Tag tag : list) { 59 | if (tag instanceof ListTag curve) { 60 | add(new ExplicitCubicBezierCurve2(curve)); 61 | } 62 | } 63 | } 64 | 65 | @Override 66 | public boolean equals(Object o) { 67 | if (o instanceof ECBCurves curves) { 68 | if (size() != curves.size()) return false; 69 | for (int i = 0; i < size(); i++) { 70 | if (!get(i).serializeNBT().equals(curves.get(i).serializeNBT())) return false; 71 | } 72 | return true; 73 | } 74 | return false; 75 | } 76 | 77 | public ECBCurves copy() { 78 | var curves = new ECBCurves(); 79 | curves.clear(); 80 | for (var curve : this) { 81 | curves.add(new ExplicitCubicBezierCurve2(curve.serializeNBT())); 82 | } 83 | return curves; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/shape/Box.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.shape; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; 5 | import com.lowdragmc.lowdraglib.utils.Vector3fHelper; 6 | import com.lowdragmc.photon.client.gameobject.emitter.IParticleEmitter; 7 | import com.lowdragmc.photon.client.gameobject.particle.TileParticle; 8 | import org.joml.Vector3f; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | 12 | /** 13 | * @author KilaBash 14 | * @date 2023/5/26 15 | * @implNote Box 16 | */ 17 | @LDLRegister(name = "box", group = "shape") 18 | public class Box implements IShape { 19 | public enum Type { 20 | Volume, 21 | Shell, 22 | Edge 23 | } 24 | 25 | @Getter @Setter 26 | @Configurable 27 | private Type emitFrom = Type.Volume; 28 | 29 | @Override 30 | public void nextPosVel(TileParticle particle, IParticleEmitter emitter, Vector3f position, Vector3f rotation, Vector3f scale) { 31 | var random = particle.getRandomSource(); 32 | scale = new Vector3f(Math.abs(scale.x), Math.abs(scale.y), Math.abs(scale.z)).mul(0.5f); 33 | Vector3f pos = new Vector3f(random.nextFloat() * 2 * scale.x - scale.x, 34 | random.nextFloat() * 2 * scale.y - scale.y, 35 | random.nextFloat() * 2 * scale.z - scale.z); 36 | if (emitFrom == Type.Shell) { 37 | double xy = scale.x * scale.y; 38 | double yz = scale.y * scale.z; 39 | double xz = scale.x * scale.z; 40 | var randomValue = random.nextDouble() * (xy + yz + xz); 41 | if (randomValue < xy) { 42 | pos.z = random.nextFloat() > 0.5 ? scale.z : -scale.z; 43 | } else if (randomValue < yz + xy) { 44 | pos.x = random.nextFloat() > 0.5 ? scale.x : -scale.x; 45 | } else { 46 | pos.y = random.nextFloat() > 0.5 ? scale.y : -scale.y; 47 | } 48 | } else if (emitFrom == Type.Edge) { 49 | var randomValue = random.nextDouble() * (scale.x + scale.y + scale.z); 50 | if (randomValue < scale.x) { 51 | pos.z = random.nextFloat() > 0.5 ? scale.z : -scale.z; 52 | pos.y = random.nextFloat() > 0.5 ? scale.y : -scale.y; 53 | } else if (randomValue < scale.x + scale.y) { 54 | pos.z = random.nextFloat() > 0.5 ? scale.z : -scale.z; 55 | pos.x = random.nextFloat() > 0.5 ? scale.x : -scale.x; 56 | } else { 57 | pos.x = random.nextFloat() > 0.5 ? scale.x : -scale.x; 58 | pos.y = random.nextFloat() > 0.5 ? scale.y : -scale.y; 59 | } 60 | } 61 | particle.setLocalPos(Vector3fHelper.rotateYXY(new Vector3f(pos), rotation).add(position).add(particle.getLocalPos()), true); 62 | particle.setInternalVelocity(Vector3fHelper.rotateYXY(new Vector3f(0, 0.05f, 0), rotation)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/shape/Circle.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.shape; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; 5 | import com.lowdragmc.lowdraglib.gui.editor.annotation.NumberRange; 6 | import com.lowdragmc.lowdraglib.utils.Vector3fHelper; 7 | import com.lowdragmc.photon.client.gameobject.emitter.IParticleEmitter; 8 | import com.lowdragmc.photon.client.gameobject.particle.TileParticle; 9 | import org.joml.Vector3f; 10 | import lombok.Getter; 11 | import lombok.Setter; 12 | import net.minecraft.util.Mth; 13 | 14 | /** 15 | * @author KilaBash 16 | * @date 2023/5/29 17 | * @implNote Circle 18 | */ 19 | @LDLRegister(name = "circle", group = "shape") 20 | public class Circle implements IShape { 21 | 22 | @Getter 23 | @Setter 24 | @Configurable 25 | @NumberRange(range = {0, 1000}) 26 | private float radius = .5f; 27 | @Getter @Setter 28 | @Configurable 29 | @NumberRange(range = {0, 1}) 30 | private float radiusThickness = 1; 31 | @Getter @Setter 32 | @Configurable 33 | @NumberRange(range = {0, 360}, wheel = 10) 34 | private float arc = 360; 35 | 36 | @Override 37 | public void nextPosVel(TileParticle particle, IParticleEmitter emitter, Vector3f position, Vector3f rotation, Vector3f scale) { 38 | var random = particle.getRandomSource(); 39 | var outer = radius; 40 | var inner = (1 - radiusThickness) * radius; 41 | var origin = inner * inner; 42 | var bound = outer * outer; 43 | var r = outer == inner ? outer : Math.sqrt(origin + random.nextDouble() * (bound - origin)); 44 | 45 | var theta = arc * Mth.TWO_PI * random.nextDouble() / 360; 46 | 47 | var pos = new Vector3f((float) (r * Math.cos(theta)), 48 | 0f, 49 | (float) (r * Math.sin(theta))).mul(scale); 50 | 51 | particle.setLocalPos(Vector3fHelper.rotateYXY(new Vector3f(pos), rotation).add(position).add(particle.getLocalPos()), true); 52 | particle.setInternalVelocity(Vector3fHelper.rotateYXY(new Vector3f(pos).normalize().mul(0.05f), rotation)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/shape/Cone.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.shape; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; 5 | import com.lowdragmc.lowdraglib.gui.editor.annotation.NumberRange; 6 | import com.lowdragmc.lowdraglib.utils.Vector3fHelper; 7 | import com.lowdragmc.photon.client.gameobject.emitter.IParticleEmitter; 8 | import com.lowdragmc.photon.client.gameobject.particle.TileParticle; 9 | import org.joml.Vector3f; 10 | import lombok.Getter; 11 | import lombok.Setter; 12 | import net.minecraft.util.Mth; 13 | 14 | /** 15 | * @author KilaBash 16 | * @date 2023/5/29 17 | * @implNote Circle 18 | */ 19 | @LDLRegister(name = "cone", group = "shape") 20 | public class Cone implements IShape { 21 | 22 | @Getter 23 | @Setter 24 | @Configurable 25 | @NumberRange(range = {0, 90}, wheel = 10) 26 | private float angle = 25; 27 | @Getter 28 | @Setter 29 | @Configurable 30 | @NumberRange(range = {0, 1000}) 31 | private float radius = .5f; 32 | @Getter @Setter 33 | @Configurable 34 | @NumberRange(range = {0, 1}) 35 | private float radiusThickness = 1; 36 | @Getter @Setter 37 | @Configurable 38 | @NumberRange(range = {0, 360}, wheel = 10) 39 | private float arc = 360; 40 | 41 | @Override 42 | public void nextPosVel(TileParticle particle, IParticleEmitter emitter, Vector3f position, Vector3f rotation, Vector3f scale) { 43 | var random = particle.getRandomSource(); 44 | var outer = radius; 45 | var inner = (1 - radiusThickness) * radius; 46 | var origin = inner * inner; 47 | var bound = outer * outer; 48 | var r = outer == inner ? outer : Math.sqrt(origin + random.nextDouble() * (bound - origin)); 49 | 50 | var theta = arc * Mth.TWO_PI * random.nextDouble() / 360; 51 | 52 | var pos = new Vector3f((float) (r * Math.cos(theta)), 53 | 0f, 54 | (float) (r * Math.sin(theta))).mul(scale); 55 | 56 | var speed = new Vector3f(0, 1, 0) 57 | .rotateAxis((float) ((r / radius) * Math.toRadians(angle)), 0, 0, -1) 58 | .rotateAxis((float) theta, 0, -1, 0); 59 | 60 | particle.setLocalPos(Vector3fHelper.rotateYXY(new Vector3f(pos), rotation).add(position).add(particle.getLocalPos()), true); 61 | particle.setInternalVelocity(Vector3fHelper.rotateYXY(speed.normalize().mul(0.05f), rotation)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/shape/Cylinder.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.shape; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; 5 | import com.lowdragmc.lowdraglib.gui.editor.annotation.NumberRange; 6 | import com.lowdragmc.lowdraglib.utils.Vector3fHelper; 7 | import com.lowdragmc.photon.client.gameobject.emitter.IParticleEmitter; 8 | import com.lowdragmc.photon.client.gameobject.particle.TileParticle; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | import net.minecraft.util.Mth; 12 | import org.joml.Vector3f; 13 | 14 | @LDLRegister(name = "cylinder", group = "shape") 15 | public class Cylinder implements IShape { 16 | 17 | @Getter 18 | @Setter 19 | @Configurable 20 | @NumberRange(range = {0, 1000}) 21 | private float radius = .5f; 22 | @Getter @Setter 23 | @Configurable 24 | @NumberRange(range = {0, 1}) 25 | private float radiusThickness = 1; 26 | @Getter @Setter 27 | @Configurable 28 | @NumberRange(range = {0, 360}, wheel = 10) 29 | private float arc = 360; 30 | 31 | 32 | @Override 33 | public void nextPosVel(TileParticle particle, IParticleEmitter emitter, Vector3f position, Vector3f rotation, Vector3f scale) { 34 | var random = particle.getRandomSource(); 35 | var outer = radius; 36 | var inner = (1 - radiusThickness) * radius; 37 | var origin = inner * inner; 38 | var bound = outer * outer; 39 | var r = outer == inner ? outer : Math.sqrt(origin + random.nextDouble() * (bound - origin)); 40 | 41 | var theta = arc * Mth.TWO_PI * random.nextDouble() / 360; 42 | 43 | var pos = new Vector3f((float) (r * Math.cos(theta)), 44 | random.nextFloat() * scale.y - scale.y / 2, 45 | (float) (r * Math.sin(theta))).mul(scale); 46 | 47 | particle.setLocalPos(Vector3fHelper.rotateYXY(new Vector3f(pos), rotation).add(position).add(particle.getLocalPos()), true); 48 | particle.setInternalVelocity(Vector3fHelper.rotateYXY(new Vector3f(pos).normalize().mul(0.05f), rotation)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/shape/Dot.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.shape; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; 4 | import com.lowdragmc.photon.client.gameobject.emitter.IParticleEmitter; 5 | import com.lowdragmc.photon.client.gameobject.particle.TileParticle; 6 | import org.joml.Vector3f; 7 | 8 | /** 9 | * @author KilaBash 10 | * @date 2023/5/26 11 | * @implNote Dot 12 | */ 13 | @LDLRegister(name = "dot", group = "shape") 14 | public class Dot implements IShape { 15 | 16 | @Override 17 | public void nextPosVel(TileParticle particle, IParticleEmitter emitter, Vector3f position, Vector3f rotation, Vector3f scale) { 18 | particle.setLocalPos(position.add(particle.getLocalPos()), true); 19 | particle.setInternalVelocity(new Vector3f(0, 0, 0)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/shape/IShape.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.shape; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.configurator.IConfigurable; 4 | import com.lowdragmc.lowdraglib.syncdata.IAutoPersistedSerializable; 5 | import com.lowdragmc.photon.client.gameobject.emitter.IParticleEmitter; 6 | import com.lowdragmc.photon.client.gameobject.particle.TileParticle; 7 | import com.lowdragmc.photon.integration.PhotonLDLibPlugin; 8 | import org.joml.Vector3f; 9 | import net.minecraft.nbt.CompoundTag; 10 | 11 | /** 12 | * @author KilaBash 13 | * @date 2023/5/26 14 | * @implNote IShape 15 | */ 16 | public interface IShape extends IConfigurable, IAutoPersistedSerializable { 17 | 18 | static CompoundTag serializeWrapper(IShape shape) { 19 | return shape.serializeNBT(); 20 | } 21 | 22 | static IShape deserializeWrapper(CompoundTag tag) { 23 | var type = tag.getString("_type"); 24 | var wrapper = PhotonLDLibPlugin.REGISTER_SHAPES.get(type); 25 | if (wrapper != null) { 26 | var shape = wrapper.creator().get(); 27 | shape.deserializeNBT(tag); 28 | return shape; 29 | } 30 | return null; 31 | } 32 | 33 | void nextPosVel(TileParticle particle, IParticleEmitter emitter, Vector3f position, Vector3f rotation, Vector3f scale); 34 | } 35 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/emitter/data/shape/Sphere.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.emitter.data.shape; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.Configurable; 4 | import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; 5 | import com.lowdragmc.lowdraglib.gui.editor.annotation.NumberRange; 6 | import com.lowdragmc.lowdraglib.utils.Vector3fHelper; 7 | import com.lowdragmc.photon.client.gameobject.emitter.IParticleEmitter; 8 | import com.lowdragmc.photon.client.gameobject.particle.TileParticle; 9 | import org.joml.Vector3f; 10 | import lombok.Getter; 11 | import lombok.Setter; 12 | import net.minecraft.util.Mth; 13 | 14 | /** 15 | * @author KilaBash 16 | * @date 2023/5/26 17 | * @implNote Sphere 18 | */ 19 | @LDLRegister(name = "sphere", group = "shape") 20 | public class Sphere implements IShape { 21 | 22 | @Getter @Setter 23 | @Configurable 24 | @NumberRange(range = {0, 1000}) 25 | private float radius = .5f; 26 | @Getter @Setter 27 | @Configurable 28 | @NumberRange(range = {0, 1}) 29 | private float radiusThickness = 1; 30 | @Getter @Setter 31 | @Configurable 32 | @NumberRange(range = {0, 360}, wheel = 10) 33 | private float arc = 360; 34 | 35 | @Override 36 | public void nextPosVel(TileParticle particle, IParticleEmitter emitter, Vector3f position, Vector3f rotation, Vector3f scale) { 37 | var random = particle.getRandomSource(); 38 | var outer = radius; 39 | var inner = (1 - radiusThickness) * radius; 40 | var origin = inner * inner * inner; 41 | var bound = outer * outer * outer; 42 | var r = outer == inner ? outer : Math.cbrt(origin + random.nextDouble() * (bound - origin)); 43 | 44 | var theta = Math.acos(2 * random.nextDouble() - 1); 45 | var phi = arc * Mth.TWO_PI * random.nextDouble() / 360; 46 | 47 | var pos = new Vector3f((float) (r * Math.sin(theta) * Math.cos(phi)), 48 | (float) (r * Math.sin(theta) * Math.sin(phi)), 49 | (float) (r * Math.cos(theta))).mul(scale); 50 | 51 | particle.setLocalPos(Vector3fHelper.rotateYXY(new Vector3f(pos), rotation).add(position).add(particle.getLocalPos()), true); 52 | particle.setInternalVelocity(Vector3fHelper.rotateYXY(new Vector3f(pos).normalize().mul(0.05f), rotation)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/client/gameobject/particle/IParticle.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.gameobject.particle; 2 | 3 | import com.lowdragmc.photon.client.gameobject.emitter.PhotonParticleRenderType; 4 | import com.mojang.blaze3d.vertex.VertexConsumer; 5 | import net.minecraft.client.Camera; 6 | import net.minecraft.util.RandomSource; 7 | 8 | import java.util.function.Function; 9 | 10 | public interface IParticle { 11 | 12 | PhotonParticleRenderType getRenderType(); 13 | 14 | RandomSource getRandomSource(); 15 | 16 | boolean isRemoved(); 17 | 18 | default boolean isAlive() { 19 | return !isRemoved(); 20 | } 21 | 22 | float getT(); 23 | 24 | float getT(float partialTicks); 25 | 26 | float getMemRandom(Object object); 27 | 28 | float getMemRandom(Object object, Function randomFunc); 29 | 30 | void tick(); 31 | 32 | void render(VertexConsumer buffer, Camera camera, float pPartialTicks); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/command/EffectCommand.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.command; 2 | 3 | import com.lowdragmc.lowdraglib.networking.IPacket; 4 | import lombok.Setter; 5 | import net.minecraft.network.FriendlyByteBuf; 6 | import net.minecraft.resources.ResourceLocation; 7 | import net.minecraft.world.phys.Vec3; 8 | 9 | /** 10 | * @author KilaBash 11 | * @date 2023/6/12 12 | * @implNote EffectCommand 13 | */ 14 | public abstract class EffectCommand implements IPacket { 15 | @Setter 16 | protected ResourceLocation location; 17 | @Setter 18 | protected Vec3 offset = Vec3.ZERO; 19 | @Setter 20 | protected Vec3 rotation = Vec3.ZERO; 21 | @Setter 22 | protected Vec3 scale = new Vec3(1, 1, 1); 23 | @Setter 24 | protected int delay; 25 | @Setter 26 | protected boolean forcedDeath; 27 | @Setter 28 | protected boolean allowMulti; 29 | 30 | @Override 31 | public void encode(FriendlyByteBuf buf) { 32 | buf.writeResourceLocation(location); 33 | buf.writeDouble(offset.x); 34 | buf.writeDouble(offset.y); 35 | buf.writeDouble(offset.z); 36 | buf.writeDouble(rotation.x); 37 | buf.writeDouble(rotation.y); 38 | buf.writeDouble(rotation.z); 39 | buf.writeDouble(scale.x); 40 | buf.writeDouble(scale.y); 41 | buf.writeDouble(scale.z); 42 | buf.writeVarInt(delay); 43 | buf.writeBoolean(forcedDeath); 44 | buf.writeBoolean(allowMulti); 45 | } 46 | 47 | @Override 48 | public void decode(FriendlyByteBuf buf) { 49 | location = buf.readResourceLocation(); 50 | offset = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()); 51 | rotation = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()); 52 | scale = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble()); 53 | delay = buf.readVarInt(); 54 | forcedDeath = buf.readBoolean(); 55 | allowMulti = buf.readBoolean(); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/command/FxLocationArgument.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.command; 2 | 3 | import com.lowdragmc.lowdraglib.LDLib; 4 | import com.mojang.brigadier.context.CommandContext; 5 | import com.mojang.brigadier.suggestion.Suggestions; 6 | import com.mojang.brigadier.suggestion.SuggestionsBuilder; 7 | import net.minecraft.client.Minecraft; 8 | import net.minecraft.commands.SharedSuggestionProvider; 9 | import net.minecraft.commands.arguments.ResourceLocationArgument; 10 | import net.minecraft.resources.ResourceLocation; 11 | 12 | import java.util.concurrent.CompletableFuture; 13 | 14 | /** 15 | * @author KilaBash 16 | * @date 2023/6/12 17 | * @implNote FxLocationArgument 18 | */ 19 | public class FxLocationArgument extends ResourceLocationArgument { 20 | @Override 21 | public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { 22 | if (LDLib.isClient()) { 23 | return SharedSuggestionProvider.suggestResource( 24 | Minecraft.getInstance().getResourceManager().listResources("fx", arg -> arg.getPath().endsWith(".fx")).keySet() 25 | .stream().map(rl -> new ResourceLocation(rl.getNamespace(), rl.getPath().substring(3, rl.getPath().length() - 3))), 26 | builder); 27 | } 28 | return super.listSuggestions(context, builder); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/command/RemoveBlockEffectCommand.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.command; 2 | 3 | import com.lowdragmc.lowdraglib.networking.IHandlerContext; 4 | import com.lowdragmc.lowdraglib.networking.IPacket; 5 | import com.lowdragmc.photon.PhotonNetworking; 6 | import com.lowdragmc.photon.client.fx.BlockEffect; 7 | import com.mojang.brigadier.Command; 8 | import com.mojang.brigadier.arguments.BoolArgumentType; 9 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 10 | import com.mojang.brigadier.context.CommandContext; 11 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 12 | import lombok.Setter; 13 | import net.fabricmc.api.EnvType; 14 | import net.fabricmc.api.Environment; 15 | import net.minecraft.commands.CommandSourceStack; 16 | import net.minecraft.commands.Commands; 17 | import net.minecraft.commands.arguments.ResourceLocationArgument; 18 | import net.minecraft.commands.arguments.coordinates.BlockPosArgument; 19 | import net.minecraft.core.BlockPos; 20 | import net.minecraft.network.FriendlyByteBuf; 21 | import net.minecraft.resources.ResourceLocation; 22 | 23 | import javax.annotation.Nullable; 24 | 25 | public class RemoveBlockEffectCommand implements IPacket { 26 | protected BlockPos pos; 27 | @Setter 28 | protected boolean force; 29 | @Nullable 30 | @Setter 31 | protected ResourceLocation location; 32 | 33 | public static LiteralArgumentBuilder createServerCommand() { 34 | return Commands.literal("block") 35 | .then(Commands.argument("pos", BlockPosArgument.blockPos()) 36 | .executes(c -> execute(c, false, false)) 37 | .then(Commands.argument("force", BoolArgumentType.bool()) 38 | .executes(c -> execute(c, true, false)) 39 | .then(Commands.argument("location", ResourceLocationArgument.id()) 40 | .executes(c -> execute(c, true, true))))); 41 | } 42 | 43 | private static int execute(CommandContext context, boolean force, boolean location) throws CommandSyntaxException { 44 | var command = new RemoveBlockEffectCommand(); 45 | command.pos = BlockPosArgument.getLoadedBlockPos(context, "pos"); 46 | if (force) { 47 | command.setForce(BoolArgumentType.getBool(context, "force")); 48 | } 49 | if (location) { 50 | command.setLocation(ResourceLocationArgument.getId(context, "location")); 51 | } 52 | PhotonNetworking.NETWORK.sendToTrackingChunk(command, context.getSource().getLevel().getChunkAt(command.pos)); 53 | return Command.SINGLE_SUCCESS; 54 | } 55 | 56 | @Override 57 | public void encode(FriendlyByteBuf buf) { 58 | buf.writeBlockPos(pos); 59 | buf.writeBoolean(force); 60 | buf.writeBoolean(location != null); 61 | if (location != null) { 62 | buf.writeResourceLocation(location); 63 | } 64 | } 65 | 66 | @Override 67 | public void decode(FriendlyByteBuf buf) { 68 | pos = buf.readBlockPos(); 69 | force = buf.readBoolean(); 70 | if (buf.readBoolean()) { 71 | location = buf.readResourceLocation(); 72 | } 73 | } 74 | 75 | @Override 76 | @Environment(EnvType.CLIENT) 77 | public void execute(IHandlerContext handler) { 78 | var effects = BlockEffect.CACHE.get(pos); 79 | if (effects == null) return; 80 | var iter = effects.iterator(); 81 | while (iter.hasNext()) { 82 | var effect = iter.next(); 83 | if (location == null || location.equals(effect.getFx().getFxLocation())) { 84 | iter.remove(); 85 | var runtime = effect.getRuntime(); 86 | if (runtime != null && runtime.isAlive()) { 87 | runtime.destroy(force); 88 | } 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/core/mixins/WorldSceneRendererMixin.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.core.mixins; 2 | 3 | import com.lowdragmc.lowdraglib.client.scene.CameraEntity; 4 | import com.lowdragmc.lowdraglib.client.scene.ISceneBlockRenderHook; 5 | import com.lowdragmc.lowdraglib.client.scene.ParticleManager; 6 | import com.lowdragmc.lowdraglib.client.scene.WorldSceneRenderer; 7 | import com.lowdragmc.photon.client.gameobject.emitter.PhotonParticleRenderType; 8 | import com.mojang.blaze3d.vertex.PoseStack; 9 | import net.minecraft.client.Camera; 10 | import net.minecraft.client.renderer.MultiBufferSource; 11 | import net.minecraft.core.BlockPos; 12 | import org.jetbrains.annotations.Nullable; 13 | import org.spongepowered.asm.mixin.Mixin; 14 | import org.spongepowered.asm.mixin.Shadow; 15 | import org.spongepowered.asm.mixin.injection.At; 16 | import org.spongepowered.asm.mixin.injection.Inject; 17 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 18 | 19 | import java.util.Collection; 20 | 21 | /** 22 | * @author KilaBash 23 | * @date 2023/6/10 24 | * @implNote WorldSceneRendererMixin 25 | */ 26 | @Mixin(WorldSceneRenderer.class) 27 | public class WorldSceneRendererMixin { 28 | @Shadow(remap = false) protected ParticleManager particleManager; 29 | @Shadow(remap = false) protected CameraEntity cameraEntity; 30 | 31 | @Shadow(remap = false) protected Camera camera; 32 | 33 | @Inject( 34 | method = {"renderTESR"}, 35 | at = {@At(value = "RETURN")}, 36 | remap = false 37 | ) 38 | private void injectRenderTESR(Collection poses, PoseStack pose, MultiBufferSource.BufferSource buffers, @Nullable ISceneBlockRenderHook hook, float partialTicks, CallbackInfo ci) { 39 | if (this.particleManager != null) { 40 | PhotonParticleRenderType.prepareForParticleRendering(null); 41 | PoseStack poseStack = new PoseStack(); 42 | poseStack.setIdentity(); 43 | poseStack.translate(this.cameraEntity.getX(), this.cameraEntity.getY(), this.cameraEntity.getZ()); 44 | particleManager.render(poseStack, this.camera, partialTicks); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/core/mixins/accessor/BlendModeAccessor.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.core.mixins.accessor; 2 | 3 | import com.mojang.blaze3d.shaders.BlendMode; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.gen.Accessor; 6 | 7 | /** 8 | * @author KilaBash 9 | * @date 2023/6/1 10 | * @implNote BlendModeAccessor 11 | */ 12 | @Mixin(BlendMode.class) 13 | public interface BlendModeAccessor { 14 | 15 | @Accessor 16 | static BlendMode getLastApplied() { 17 | return null; 18 | } 19 | 20 | @Accessor 21 | static void setLastApplied(BlendMode blendMode) { 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/core/mixins/accessor/MinecraftAccessor.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.core.mixins.accessor; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.gen.Accessor; 6 | 7 | /** 8 | * @author KilaBash 9 | * @date 2023/6/4 10 | * @implNote MinecraftAccessor 11 | */ 12 | @Mixin(Minecraft.class) 13 | public interface MinecraftAccessor { 14 | @Accessor 15 | static int getFps() { 16 | return 0; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/core/mixins/accessor/ParticleEngineAccessor.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.core.mixins.accessor; 2 | 3 | import net.minecraft.client.particle.Particle; 4 | import net.minecraft.client.particle.ParticleEngine; 5 | import net.minecraft.client.particle.ParticleRenderType; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.gen.Accessor; 8 | 9 | import java.util.Map; 10 | import java.util.Queue; 11 | 12 | /** 13 | * @author KilaBash 14 | * @date 2023/6/5 15 | * @implNote ParticleEngineAccessor 16 | */ 17 | @Mixin(ParticleEngine.class) 18 | public interface ParticleEngineAccessor { 19 | @Accessor 20 | Map> getParticles(); 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/core/mixins/accessor/ShaderInstanceAccessor.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.core.mixins.accessor; 2 | 3 | import com.mojang.blaze3d.shaders.BlendMode; 4 | import com.mojang.blaze3d.shaders.Uniform; 5 | import net.minecraft.client.renderer.ShaderInstance; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.gen.Accessor; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * @author KilaBash 14 | * @date 2023/6/1 15 | * @implNote ShaderInstanceAccessor 16 | */ 17 | @Mixin(ShaderInstance.class) 18 | public interface ShaderInstanceAccessor { 19 | @Accessor 20 | BlendMode getBlend(); 21 | 22 | @Accessor 23 | List getSamplerNames(); 24 | 25 | @Accessor 26 | Map getUniformMap(); 27 | } 28 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/gui/editor/FXEditor.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.gui.editor; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; 4 | import com.lowdragmc.lowdraglib.gui.editor.data.IProject; 5 | import com.lowdragmc.lowdraglib.gui.editor.ui.*; 6 | import com.lowdragmc.lowdraglib.gui.editor.ui.menu.ViewMenu; 7 | import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; 8 | import com.lowdragmc.photon.client.fx.IEffect; 9 | import net.fabricmc.api.EnvType; 10 | import net.fabricmc.api.Environment; 11 | 12 | import java.io.File; 13 | import java.util.List; 14 | 15 | @LDLRegister(name = "editor.fx", group = "editor") 16 | @Environment(EnvType.CLIENT) 17 | public class FXEditor extends Editor { 18 | public static final ConfigPanel.Tab BASIC = ConfigPanel.Tab.WIDGET; 19 | public static final ConfigPanel.Tab RESOURCE = ConfigPanel.Tab.RESOURCE; 20 | 21 | protected IEffect effect; 22 | 23 | public FXEditor(File workSpace) { 24 | super(workSpace); 25 | } 26 | 27 | public IEffect getEditorFX() { 28 | return effect; 29 | } 30 | 31 | @Override 32 | public void initEditorViews() { 33 | this.toolPanel = new ToolPanel(this); 34 | this.toolPanel.setSizeWidth(150); 35 | this.configPanel = new ConfigPanel(this, List.of(BASIC, RESOURCE)); 36 | this.tabPages = new StringTabContainer(this); 37 | this.resourcePanel = new ResourcePanel(this); 38 | this.menuPanel = new MenuPanel(this); 39 | this.floatView = new WidgetGroup(0, 0, this.getSize().width, this.getSize().height); 40 | 41 | this.addWidget(this.tabPages); 42 | this.addWidget(this.toolPanel); 43 | this.addWidget(this.configPanel); 44 | this.addWidget(this.resourcePanel); 45 | this.addWidget(this.menuPanel); 46 | this.addWidget(this.floatView); 47 | } 48 | 49 | @Override 50 | public void loadProject(IProject project) { 51 | if (project == null || project instanceof FXProject) { 52 | super.loadProject(project); 53 | } else { 54 | throw new IllegalArgumentException("Invalid project type"); 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/gui/editor/MaterialsResource.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.gui.editor; 2 | 3 | import com.lowdragmc.lowdraglib.LDLib; 4 | import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; 5 | import com.lowdragmc.lowdraglib.gui.editor.data.resource.Resource; 6 | import com.lowdragmc.lowdraglib.gui.editor.ui.ResourcePanel; 7 | import com.lowdragmc.lowdraglib.gui.editor.ui.resource.ResourceContainer; 8 | import com.lowdragmc.lowdraglib.gui.widget.ImageWidget; 9 | import com.lowdragmc.photon.client.gameobject.emitter.data.material.BlockTextureSheetMaterial; 10 | import com.lowdragmc.photon.client.gameobject.emitter.data.material.CustomShaderMaterial; 11 | import com.lowdragmc.photon.client.gameobject.emitter.data.material.IMaterial; 12 | import com.lowdragmc.photon.client.gameobject.emitter.data.material.TextureMaterial; 13 | import net.minecraft.nbt.CompoundTag; 14 | import net.minecraft.nbt.Tag; 15 | import net.minecraft.resources.ResourceLocation; 16 | 17 | import java.io.File; 18 | 19 | import static com.lowdragmc.photon.gui.editor.MaterialsResource.RESOURCE_NAME; 20 | 21 | /** 22 | * @author KilaBash 23 | * @date 2023/5/29 24 | * @implNote MaterialsResource 25 | */ 26 | @LDLRegister(name = RESOURCE_NAME, group = "resource") 27 | public class MaterialsResource extends Resource { 28 | public final static String RESOURCE_NAME = "material"; 29 | 30 | public MaterialsResource() { 31 | super(new File(LDLib.getLDLibDir(), "assets/resources/material")); 32 | } 33 | 34 | @Override 35 | public String name() { 36 | return RESOURCE_NAME; 37 | } 38 | 39 | @Override 40 | public void buildDefault() { 41 | addVanillaTextureMaterial("angry"); 42 | addVanillaTextureMaterial("bubble"); 43 | addVanillaTextureMaterial("damage"); 44 | addVanillaTextureMaterial("flame"); 45 | addVanillaTextureMaterial("glow"); 46 | addVanillaTextureMaterial("heart"); 47 | addVanillaTextureMaterial("lava"); 48 | addVanillaTextureMaterial("note"); 49 | 50 | addBuiltinTextureMaterial("kila_tail"); 51 | addBuiltinTextureMaterial("laser"); 52 | addBuiltinTextureMaterial("smoke"); 53 | addBuiltinTextureMaterial("thaumcraft"); 54 | addBuiltinTextureMaterial("ring"); 55 | 56 | addBuiltinShaderMaterial("circle"); 57 | addBuiltinResource("block_texture_sheet", new BlockTextureSheetMaterial()); 58 | 59 | } 60 | 61 | private void addVanillaTextureMaterial(String name) { 62 | addBuiltinResource(name, new TextureMaterial(new ResourceLocation("textures/particle/%s.png".formatted(name)))); 63 | } 64 | 65 | private void addBuiltinTextureMaterial(String name) { 66 | addBuiltinResource(name, new TextureMaterial(new ResourceLocation("photon:textures/particle/%s.png".formatted(name)))); 67 | } 68 | 69 | private void addBuiltinShaderMaterial(String name) { 70 | addBuiltinResource(name, new CustomShaderMaterial(new ResourceLocation("photon:%s".formatted(name)))); 71 | } 72 | 73 | @Override 74 | public ResourceContainer createContainer(ResourcePanel panel) { 75 | return new MaterialsResourceContainer(this, panel); 76 | } 77 | 78 | @Override 79 | public Tag serialize(IMaterial value) { 80 | return value.serializeNBT(); 81 | } 82 | 83 | @Override 84 | public IMaterial deserialize(Tag nbt) { 85 | if (nbt instanceof CompoundTag tag) { 86 | var type = tag.getString("_type"); 87 | for (var clazz : IMaterial.MATERIALS) { 88 | if (type.equals(clazz.getSimpleName())) { 89 | try { 90 | IMaterial mat = clazz.getConstructor().newInstance(); 91 | mat.deserializeNBT(tag); 92 | return mat; 93 | } catch (Throwable ignored) {} 94 | } 95 | } 96 | } 97 | return null; 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/gui/editor/MaterialsResourceContainer.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.gui.editor; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.Icons; 4 | import com.lowdragmc.lowdraglib.gui.editor.data.resource.Resource; 5 | import com.lowdragmc.lowdraglib.gui.editor.ui.ConfigPanel; 6 | import com.lowdragmc.lowdraglib.gui.editor.ui.ResourcePanel; 7 | import com.lowdragmc.lowdraglib.gui.editor.ui.resource.ResourceContainer; 8 | import com.lowdragmc.lowdraglib.gui.widget.ImageWidget; 9 | import com.lowdragmc.photon.client.gameobject.emitter.data.material.IMaterial; 10 | 11 | /** 12 | * @author KilaBash 13 | * @date 2022/12/5 14 | * @implNote TexturesResourceContainer 15 | */ 16 | public class MaterialsResourceContainer extends ResourceContainer { 17 | 18 | public MaterialsResourceContainer(Resource resource, ResourcePanel panel) { 19 | super(resource, panel); 20 | setWidgetSupplier(k -> new ImageWidget(0, 0, 30, 30, () -> getResource().getResource(k).preview())); 21 | setDragging(key -> getResource().getResource(key), IMaterial::preview); 22 | setOnEdit(key -> getPanel().getEditor().getConfigPanel().openConfigurator(ConfigPanel.Tab.RESOURCE, getResource().getResource(key))); 23 | setOnMenu((selected, m) -> m.branch(Icons.ADD_FILE, "ldlib.gui.editor.menu.add_resource", menu -> { 24 | for (var clazz : IMaterial.MATERIALS) { 25 | try { 26 | IMaterial icon = clazz.getConstructor().newInstance(); 27 | menu.leaf(icon.preview(), clazz.getSimpleName(), () -> { 28 | resource.addBuiltinResource(genNewFileName(), icon); 29 | reBuild(); 30 | }); 31 | } catch (Throwable ignored) {} 32 | } 33 | })); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/gui/editor/ParticleScene.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.gui.editor; 2 | 3 | import com.lowdragmc.lowdraglib.client.scene.ParticleManager; 4 | import com.lowdragmc.lowdraglib.gui.editor.ui.sceneeditor.SceneEditorWidget; 5 | import com.lowdragmc.photon.client.PhotonParticleManager; 6 | import lombok.Getter; 7 | 8 | /** 9 | * @author KilaBash 10 | * @date 2023/5/26 11 | * @implNote ParticleScene 12 | */ 13 | @Getter 14 | public class ParticleScene extends SceneEditorWidget { 15 | protected final PhotonParticleManager particleManager = new PhotonParticleManager(); 16 | 17 | public ParticleScene(int x, int y, int width, int height) { 18 | super(x, y, width, height, null); 19 | } 20 | 21 | @Override 22 | protected ParticleManager createParticleManager() { 23 | return particleManager; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/gui/editor/SceneMenu.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.gui.editor; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.Icons; 4 | import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; 5 | import com.lowdragmc.lowdraglib.gui.editor.ui.menu.MenuTab; 6 | import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; 7 | import com.lowdragmc.lowdraglib.gui.util.TreeBuilder; 8 | import com.lowdragmc.lowdraglib.utils.BlockInfo; 9 | import com.lowdragmc.lowdraglib.utils.TrackedDummyWorld; 10 | import lombok.Getter; 11 | import net.minecraft.client.Minecraft; 12 | import net.minecraft.core.BlockPos; 13 | import net.minecraft.nbt.CompoundTag; 14 | import net.minecraft.world.level.block.Blocks; 15 | 16 | import java.util.HashSet; 17 | import java.util.Set; 18 | 19 | /** 20 | * @author KilaBash 21 | * @date 2023/06/06 22 | * @implNote SceneMenu 23 | */ 24 | @LDLRegister(name = "scene", group = "editor.fx", priority = 99) 25 | @Getter 26 | public class SceneMenu extends MenuTab { 27 | private int range = 3; 28 | private boolean usingRealWorld = false; 29 | 30 | protected TreeBuilder.Menu createMenu() { 31 | var viewMenu = TreeBuilder.Menu.start(); 32 | viewMenu.branch("range", menu -> { 33 | for (int r : new int[]{1, 3, 5}) { 34 | menu.leaf(this.range == r ? Icons.CHECK : IGuiTexture.EMPTY, "%d×%d×%d".formatted(r, r, r), () -> setRange(r)); 35 | } 36 | }); 37 | viewMenu.crossLine(); 38 | viewMenu.leaf(usingRealWorld ? Icons.CHECK : IGuiTexture.EMPTY, "photon.gui.editor.menu.scene.real_world", () -> setUsingRealWorld(!usingRealWorld)); 39 | return viewMenu; 40 | } 41 | 42 | protected void updateScene() { 43 | if (editor instanceof FXEditor fxEditor && fxEditor.getTabPages().focus instanceof ParticleScenePanel panel) { 44 | panel.resetScene(); 45 | } 46 | } 47 | 48 | public void setRange(int range) { 49 | this.range = range; 50 | updateScene(); 51 | } 52 | 53 | public void setUsingRealWorld(boolean usingRealWorld) { 54 | this.usingRealWorld = usingRealWorld; 55 | updateScene(); 56 | } 57 | 58 | public Set createScene(TrackedDummyWorld level) { 59 | Set plane = new HashSet<>(); 60 | if (usingRealWorld) { 61 | var world = Minecraft.getInstance().level; 62 | var playerPos = Minecraft.getInstance().player.getOnPos(); 63 | for (int x = -range; x <= range; x++) { 64 | for (int y = -range; y <= range; y++) { 65 | for (int z = -range; z <= range; z++) { 66 | var state = world.getBlockState(new BlockPos(x, y, z).offset(playerPos)); 67 | if (state.getBlock() != Blocks.AIR) { 68 | plane.add(new BlockPos(x, y, z)); 69 | level.addBlock(new BlockPos(x, y, z), BlockInfo.fromBlockState(state)); 70 | } 71 | } 72 | } 73 | } 74 | } else { 75 | int i = 0; 76 | for (int x = -range; x <= range; x++) { 77 | for (int z = -range; z <= range; z++) { 78 | plane.add(new BlockPos(x, 0, z)); 79 | level.addBlock(new BlockPos(x, 0, z), BlockInfo.fromBlock(i % 2 == 0 ? Blocks.GRAY_CONCRETE : Blocks.LIGHT_GRAY_CONCRETE)); 80 | i++; 81 | } 82 | } 83 | } 84 | return plane; 85 | } 86 | 87 | @Override 88 | public CompoundTag serializeNBT() { 89 | var tag = new CompoundTag(); 90 | tag.putInt("range", range); 91 | tag.putBoolean("usingRealWorld", usingRealWorld); 92 | return tag; 93 | } 94 | 95 | @Override 96 | public void deserializeNBT(CompoundTag nbt) { 97 | range = nbt.getInt("range"); 98 | usingRealWorld = nbt.getBoolean("usingRealWorld"); 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/gui/editor/accessor/IShapeAccessor.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.gui.editor.accessor; 2 | 3 | import com.lowdragmc.lowdraglib.syncdata.AccessorOp; 4 | import com.lowdragmc.lowdraglib.syncdata.accessor.CustomObjectAccessor; 5 | import com.lowdragmc.lowdraglib.syncdata.payload.ITypedPayload; 6 | import com.lowdragmc.lowdraglib.syncdata.payload.NbtTagPayload; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.shape.IShape; 8 | import net.minecraft.nbt.CompoundTag; 9 | 10 | /** 11 | * @author KilaBash 12 | * @date 2023/6/3 13 | * @implNote IShapeAccessor 14 | */ 15 | public class IShapeAccessor extends CustomObjectAccessor { 16 | 17 | public IShapeAccessor() { 18 | super(IShape.class, true); 19 | } 20 | 21 | @Override 22 | public ITypedPayload serialize(AccessorOp op, IShape value) { 23 | return NbtTagPayload.of(IShape.serializeWrapper(value)); 24 | } 25 | 26 | @Override 27 | public IShape deserialize(AccessorOp op, ITypedPayload payload) { 28 | if (payload instanceof NbtTagPayload nbtTagPayload && nbtTagPayload.getPayload() instanceof CompoundTag tag) { 29 | return IShape.deserializeWrapper(tag); 30 | } 31 | return null; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/gui/editor/accessor/NumberFunction3Accessor.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.gui.editor.accessor; 2 | 3 | import com.lowdragmc.lowdraglib.syncdata.AccessorOp; 4 | import com.lowdragmc.lowdraglib.syncdata.accessor.CustomObjectAccessor; 5 | import com.lowdragmc.lowdraglib.syncdata.payload.ITypedPayload; 6 | import com.lowdragmc.lowdraglib.syncdata.payload.NbtTagPayload; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 8 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction3; 9 | import net.minecraft.nbt.CompoundTag; 10 | import net.minecraft.nbt.Tag; 11 | 12 | /** 13 | * @author KilaBash 14 | * @date 2023/6/3 15 | * @implNote NumberFunction3Accessor 16 | */ 17 | public class NumberFunction3Accessor extends CustomObjectAccessor { 18 | 19 | public NumberFunction3Accessor() { 20 | super(NumberFunction3.class, true); 21 | } 22 | 23 | @Override 24 | public ITypedPayload serialize(AccessorOp op, NumberFunction3 value) { 25 | var tag = new CompoundTag(); 26 | tag.put("x", NumberFunction.serializeWrapper(value.x)); 27 | tag.put("y", NumberFunction.serializeWrapper(value.y)); 28 | tag.put("z", NumberFunction.serializeWrapper(value.z)); 29 | return NbtTagPayload.of(tag); 30 | } 31 | 32 | @Override 33 | public NumberFunction3 deserialize(AccessorOp op, ITypedPayload payload) { 34 | if (payload instanceof NbtTagPayload nbtTagPayload && nbtTagPayload.getPayload() instanceof CompoundTag tag) { 35 | if (tag.getTagType("x") == Tag.TAG_FLOAT) { 36 | return new NumberFunction3(tag.getFloat("x"), tag.getFloat("y"), tag.getFloat("z")); 37 | } else { 38 | return new NumberFunction3(NumberFunction.deserializeWrapper(tag.getCompound("x")), 39 | NumberFunction.deserializeWrapper(tag.getCompound("y")), 40 | NumberFunction.deserializeWrapper(tag.getCompound("z"))); 41 | } 42 | } 43 | return null; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/gui/editor/accessor/NumberFunctionAccessor.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.gui.editor.accessor; 2 | 3 | import com.lowdragmc.lowdraglib.syncdata.AccessorOp; 4 | import com.lowdragmc.lowdraglib.syncdata.accessor.CustomObjectAccessor; 5 | import com.lowdragmc.lowdraglib.syncdata.payload.ITypedPayload; 6 | import com.lowdragmc.lowdraglib.syncdata.payload.NbtTagPayload; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 8 | import net.minecraft.nbt.CompoundTag; 9 | 10 | /** 11 | * @author KilaBash 12 | * @date 2023/6/3 13 | * @implNote NumberFunctionAccessor 14 | */ 15 | public class NumberFunctionAccessor extends CustomObjectAccessor { 16 | 17 | public NumberFunctionAccessor() { 18 | super(NumberFunction.class, true); 19 | } 20 | 21 | @Override 22 | public ITypedPayload serialize(AccessorOp op, NumberFunction value) { 23 | return NbtTagPayload.of(NumberFunction.serializeWrapper(value)); 24 | } 25 | 26 | @Override 27 | public NumberFunction deserialize(AccessorOp op, ITypedPayload payload) { 28 | if (payload instanceof NbtTagPayload nbtTagPayload && nbtTagPayload.getPayload() instanceof CompoundTag tag) { 29 | return NumberFunction.deserializeWrapper(tag); 30 | } 31 | return null; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/gui/editor/configurator/NumberFunction3Accessor.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.gui.editor.configurator; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.accessors.TypesAccessor; 4 | import com.lowdragmc.lowdraglib.gui.editor.annotation.ConfigAccessor; 5 | import com.lowdragmc.lowdraglib.gui.editor.configurator.Configurator; 6 | import com.lowdragmc.lowdraglib.gui.editor.configurator.ConfiguratorSelectorConfigurator; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 8 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction3; 9 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction3Config; 10 | 11 | import java.lang.reflect.Field; 12 | import java.util.List; 13 | import java.util.concurrent.atomic.AtomicBoolean; 14 | import java.util.function.Consumer; 15 | import java.util.function.Supplier; 16 | 17 | /** 18 | * @author KilaBash 19 | * @date 2022/12/1 20 | * @implNote NumberFunctionAccessor 21 | */ 22 | @ConfigAccessor 23 | public class NumberFunction3Accessor extends TypesAccessor { 24 | 25 | public NumberFunction3Accessor() { 26 | super(NumberFunction3.class); 27 | } 28 | 29 | @Override 30 | public NumberFunction3 defaultValue(Field field, Class type) { 31 | return new NumberFunction3(NumberFunction.constant(0), NumberFunction.constant(0), NumberFunction.constant(0)); 32 | } 33 | 34 | @Override 35 | public Configurator create(String name, Supplier supplier, Consumer consumer, boolean forceUpdate, Field field) { 36 | var config = field.getAnnotation(NumberFunction3Config.class); 37 | var value = supplier.get(); 38 | Consumer singleConsumer = number -> { 39 | var previous = supplier.get(); 40 | consumer.accept(new NumberFunction3( 41 | config.affectX() ? (previous.x == number ? number : NumberFunction.copy(number)) : previous.x, 42 | config.affectY() ? (previous.y == number ? number : NumberFunction.copy(number)) : previous.y, 43 | config.affectZ() ? (previous.z == number ? number : NumberFunction.copy(number)) : previous.z)); 44 | }; 45 | Supplier singleSupplier = () -> { 46 | if (config.affectX()) return supplier.get().x; 47 | if (config.affectY()) return supplier.get().y; 48 | return supplier.get().z; 49 | }; 50 | if (config.allowSeperated()) { 51 | AtomicBoolean isSeperated = new AtomicBoolean(config.isSeperatedDefault()); 52 | if (!NumberFunction.isEqual(value.x, value.y) || !NumberFunction.isEqual(value.y, value.z)) { 53 | isSeperated.set(true); 54 | } 55 | return new ConfiguratorSelectorConfigurator<>(name, false, isSeperated::get, isSeperated::set, isSeperated.get(), true, 56 | List.of(true, false), v -> v ? "Separate Axes" : "All in one", (v, father) -> { 57 | if (v) { 58 | father.addConfigurators(new NumberFunction3Configurator("", supplier, consumer, forceUpdate, config)); 59 | } else { 60 | singleConsumer.accept(singleSupplier.get()); 61 | father.addConfigurators(new NumberFunctionConfigurator("", singleSupplier, singleConsumer, forceUpdate, config.common())); 62 | } 63 | }); 64 | } else { 65 | if (config.isSeperatedDefault()) { 66 | return new NumberFunction3Configurator(name, supplier, consumer, forceUpdate, config); 67 | } else { 68 | return new NumberFunctionConfigurator(name, singleSupplier, singleConsumer, forceUpdate, config.common()); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/gui/editor/configurator/NumberFunction3Configurator.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.gui.editor.configurator; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.configurator.ValueConfigurator; 4 | import com.lowdragmc.lowdraglib.utils.Size; 5 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 6 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction3; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction3Config; 8 | import lombok.Getter; 9 | 10 | import java.util.function.Consumer; 11 | import java.util.function.Supplier; 12 | 13 | /** 14 | * @author KilaBash 15 | * @date 2023/5/27 16 | * @implNote NumberFunction3Configurator 17 | */ 18 | public class NumberFunction3Configurator extends ValueConfigurator { 19 | 20 | @Getter 21 | private NumberFunction3Config config; 22 | private NumberFunctionConfigurator x, y, z; 23 | 24 | public NumberFunction3Configurator(String name, Supplier supplier, Consumer onUpdate, boolean forceUpdate, NumberFunction3Config config) { 25 | super(name, supplier, onUpdate, new NumberFunction3( 26 | config.xyz().length > 0 ? NumberFunction.constant(config.xyz()[0].defaultValue()) : NumberFunction.constant(config.common().defaultValue()), 27 | config.xyz().length > 1 ? NumberFunction.constant(config.xyz()[1].defaultValue()) : NumberFunction.constant(config.common().defaultValue()), 28 | config.xyz().length > 2 ? NumberFunction.constant(config.xyz()[2].defaultValue()) : NumberFunction.constant(config.common().defaultValue())), 29 | forceUpdate); 30 | this.config = config; 31 | if (value == null) { 32 | value = defaultValue; 33 | } 34 | } 35 | 36 | @Override 37 | protected void onValueUpdate(NumberFunction3 newValue) { 38 | if (newValue == null) newValue = defaultValue; 39 | if (newValue.equals(value)) return; 40 | super.onValueUpdate(newValue); 41 | } 42 | 43 | @Override 44 | public void init(int width) { 45 | super.init(width); 46 | assert value != null; 47 | var w = (width - leftWidth - rightWidth) / 3; 48 | x = new NumberFunctionConfigurator("x", () -> this.value.x, number -> { 49 | this.value.x = number; 50 | updateValue(); 51 | }, forceUpdate, config.xyz().length > 0 ? config.xyz()[0] : config.common()); 52 | x.setConfiguratorContainer(configuratorContainer); 53 | x.init(w); 54 | x.addSelfPosition(leftWidth, 0); 55 | addWidget(x); 56 | 57 | y = new NumberFunctionConfigurator("y", () -> this.value.y, number -> { 58 | this.value.y = number; 59 | updateValue(); 60 | }, forceUpdate, config.xyz().length > 1 ? config.xyz()[1] : config.common()); 61 | y.setConfiguratorContainer(configuratorContainer); 62 | y.init(w); 63 | y.addSelfPosition(leftWidth + w, 0); 64 | addWidget(y); 65 | 66 | z = new NumberFunctionConfigurator("z", () -> this.value.z, number -> { 67 | this.value.z = number; 68 | updateValue(); 69 | }, forceUpdate, config.xyz().length > 2 ? config.xyz()[2] : config.common()); 70 | z.setConfiguratorContainer(configuratorContainer); 71 | z.init(w); 72 | z.addSelfPosition(leftWidth + w * 2, 0); 73 | addWidget(z); 74 | } 75 | 76 | @Override 77 | public void computeHeight() { 78 | super.computeHeight(); 79 | var size = getSize(); 80 | x.computeHeight(); 81 | y.computeHeight(); 82 | z.computeHeight(); 83 | setSize(new Size(size.width, Math.max(15, Math.max(x.getSize().height, Math.max(y.getSize().height, z.getSize().height))))); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/gui/editor/configurator/NumberFunctionAccessor.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.gui.editor.configurator; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.accessors.TypesAccessor; 4 | import com.lowdragmc.lowdraglib.gui.editor.annotation.ConfigAccessor; 5 | import com.lowdragmc.lowdraglib.gui.editor.configurator.Configurator; 6 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 7 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunctionConfig; 8 | 9 | import java.lang.reflect.Field; 10 | import java.util.function.Consumer; 11 | import java.util.function.Supplier; 12 | 13 | /** 14 | * @author KilaBash 15 | * @date 2022/12/1 16 | * @implNote NumberFunctionAccessor 17 | */ 18 | @ConfigAccessor 19 | public class NumberFunctionAccessor extends TypesAccessor { 20 | 21 | public NumberFunctionAccessor() { 22 | super(NumberFunction.class); 23 | } 24 | 25 | @Override 26 | public NumberFunction defaultValue(Field field, Class type) { 27 | return NumberFunction.constant(0); 28 | } 29 | 30 | @Override 31 | public Configurator create(String name, Supplier supplier, Consumer consumer, boolean forceUpdate, Field field) { 32 | return new NumberFunctionConfigurator(name, supplier, consumer, forceUpdate, field.getAnnotation(NumberFunctionConfig.class)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/gui/editor/configurator/NumberFunctionConfigurator.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.gui.editor.configurator; 2 | 3 | import com.lowdragmc.lowdraglib.gui.editor.Icons; 4 | import com.lowdragmc.lowdraglib.gui.editor.configurator.ValueConfigurator; 5 | import com.lowdragmc.lowdraglib.gui.editor.ui.Editor; 6 | import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; 7 | import com.lowdragmc.lowdraglib.gui.util.TreeBuilder; 8 | import com.lowdragmc.lowdraglib.gui.widget.ButtonWidget; 9 | import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; 10 | import com.lowdragmc.lowdraglib.utils.Size; 11 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunction; 12 | import com.lowdragmc.photon.client.gameobject.emitter.data.number.NumberFunctionConfig; 13 | import lombok.Getter; 14 | 15 | import java.util.function.Consumer; 16 | import java.util.function.Supplier; 17 | 18 | 19 | /** 20 | * @author KilaBash 21 | * @date 2022/12/1 22 | * @implNote NumberFunctionConfigurator 23 | */ 24 | public class NumberFunctionConfigurator extends ValueConfigurator { 25 | @Getter 26 | private NumberFunctionConfig config; 27 | private WidgetGroup group; 28 | 29 | public NumberFunctionConfigurator(String name, Supplier supplier, Consumer onUpdate, boolean forceUpdate, NumberFunctionConfig config) { 30 | super(name, supplier, onUpdate, NumberFunction.constant(config.defaultValue()), forceUpdate); 31 | this.config = config; 32 | if (value == null) { 33 | value = defaultValue; 34 | } 35 | } 36 | 37 | @Override 38 | protected void onValueUpdate(NumberFunction newValue) { 39 | if (newValue == null) newValue = defaultValue; 40 | if (newValue == value || newValue.equals(value)) return; 41 | super.onValueUpdate(newValue); 42 | } 43 | 44 | @Override 45 | public void init(int width) { 46 | super.init(width); 47 | var w = width - leftWidth - 6 - rightWidth - 9; 48 | group = new WidgetGroup(leftWidth, 0, w, 15); 49 | this.addWidget(group); 50 | this.addWidget(new ButtonWidget(width - (tips.length > 0 ? 24 : 12), 2, 9, 9, 51 | Icons.DOWN, 52 | cd -> { 53 | if (Editor.INSTANCE != null) { 54 | var menu = TreeBuilder.Menu.start(); 55 | for (Class type : config.types()) { 56 | menu.leaf(type == value.getClass() ?Icons.CHECK : IGuiTexture.EMPTY, type.getSimpleName(), () -> { 57 | if (type == value.getClass()) return; 58 | try { 59 | var newValue = type.getConstructor(NumberFunctionConfig.class).newInstance(config); 60 | updateValue(newValue); 61 | group.clearAllWidgets(); 62 | group.setSize(new Size(w, 15)); 63 | value.createConfigurator(group, this); 64 | computeLayout(); 65 | } catch (Throwable ignored) { 66 | } 67 | }); 68 | } 69 | Editor.INSTANCE.openMenu(group.getPosition().x + width, group.getPosition().y, menu); 70 | } 71 | }).setHoverTooltips("ldlib.gui.editor.tips.other")); 72 | assert value != null; 73 | value.createConfigurator(group, this); 74 | } 75 | 76 | @Override 77 | public void computeHeight() { 78 | super.computeHeight(); 79 | setSize(new Size(getSize().width, group.getSize().height)); 80 | } 81 | 82 | public void updateValue(NumberFunction value) { 83 | onValueUpdate(value); 84 | super.updateValue(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /common/src/main/java/com/lowdragmc/photon/integration/PhotonLDLibPlugin.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.integration; 2 | 3 | import com.lowdragmc.lowdraglib.LDLib; 4 | import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegister; 5 | import com.lowdragmc.lowdraglib.gui.editor.annotation.LDLRegisterClient; 6 | import com.lowdragmc.lowdraglib.gui.editor.runtime.AnnotationDetector; 7 | import com.lowdragmc.lowdraglib.plugin.ILDLibPlugin; 8 | import com.lowdragmc.lowdraglib.plugin.LDLibPlugin; 9 | import com.lowdragmc.lowdraglib.syncdata.IAccessor; 10 | import com.lowdragmc.lowdraglib.syncdata.payload.NbtTagPayload; 11 | import com.lowdragmc.photon.Photon; 12 | import com.lowdragmc.photon.client.gameobject.IFXObject; 13 | import com.lowdragmc.photon.client.gameobject.emitter.data.shape.IShape; 14 | import com.lowdragmc.photon.gui.editor.accessor.IShapeAccessor; 15 | import com.lowdragmc.photon.gui.editor.accessor.NumberFunction3Accessor; 16 | import com.lowdragmc.photon.gui.editor.accessor.NumberFunctionAccessor; 17 | import net.fabricmc.api.EnvType; 18 | import net.fabricmc.api.Environment; 19 | 20 | import java.io.File; 21 | import java.util.HashMap; 22 | import java.util.Map; 23 | import java.util.stream.Collectors; 24 | 25 | import static com.lowdragmc.lowdraglib.syncdata.TypedPayloadRegistries.register; 26 | 27 | /** 28 | * @author KilaBash 29 | * @date 2023/6/4 30 | * @implNote LDLibPlugin 31 | */ 32 | @LDLibPlugin 33 | public class PhotonLDLibPlugin implements ILDLibPlugin { 34 | public static final IAccessor NUMBER_FUNCTION_ACCESSOR = new NumberFunctionAccessor(); 35 | public static final IAccessor NUMBER_FUNCTION3_ACCESSOR = new NumberFunction3Accessor(); 36 | public static final IAccessor SHAPE_ACCESSOR = new IShapeAccessor(); 37 | 38 | @Environment(EnvType.CLIENT) 39 | public static Map> REGISTER_FX_OBJECTS; 40 | public static Map> REGISTER_SHAPES; 41 | 42 | @Override 43 | public void onLoad() { 44 | var fxLocation = new File(LDLib.getLDLibDir(), "assets/photon/fx"); 45 | if (fxLocation.mkdirs()) { 46 | Photon.LOGGER.info("creat the photon fx folder"); 47 | } 48 | 49 | register(NbtTagPayload.class, NbtTagPayload::new, NUMBER_FUNCTION_ACCESSOR, 1000); 50 | register(NbtTagPayload.class, NbtTagPayload::new, NUMBER_FUNCTION3_ACCESSOR, 1000); 51 | register(NbtTagPayload.class, NbtTagPayload::new, SHAPE_ACCESSOR, 1000); 52 | 53 | if (LDLib.isClient()) { 54 | REGISTER_FX_OBJECTS = new HashMap<>(); 55 | AnnotationDetector.scanClasses(LDLRegisterClient.class, IFXObject.class, AnnotationDetector::checkNoArgsConstructor, PhotonLDLibPlugin::toUINoArgsBuilder, PhotonLDLibPlugin::UIWrapperSorter, l -> REGISTER_FX_OBJECTS.putAll(l.stream().collect(Collectors.toMap(w -> w.annotation().name(), w -> w)))); 56 | } 57 | REGISTER_SHAPES = new HashMap<>(); 58 | AnnotationDetector.scanClasses(LDLRegister.class, IShape.class, AnnotationDetector::checkNoArgsConstructor, AnnotationDetector::toUINoArgsBuilder, AnnotationDetector::UIWrapperSorter, l -> REGISTER_SHAPES.putAll(l.stream().collect(Collectors.toMap(w -> w.annotation().name(), w -> w)))); 59 | } 60 | 61 | public static AnnotationDetector.Wrapper toUINoArgsBuilder(Class clazz) { 62 | return new AnnotationDetector.Wrapper<>(clazz.getAnnotation(LDLRegisterClient.class), clazz, () -> AnnotationDetector.createNoArgsInstance(clazz)); 63 | } 64 | 65 | public static int UIWrapperSorter(AnnotationDetector.Wrapper a, AnnotationDetector.Wrapper b) { 66 | return b.annotation().priority() - a.annotation().priority(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /common/src/main/java/expr/Benchmark.java: -------------------------------------------------------------------------------- 1 | // Run benchmarks from the command line. 2 | 3 | package expr; 4 | 5 | /** 6 | * Time evaluating many expressions over many values. 7 | */ 8 | public class Benchmark { 9 | public static void main(String[] args) { 10 | double parse_product = 1.0; 11 | double run_product = 1.0; 12 | for (String arg : args) { 13 | long parsetime = timeParse(arg); 14 | long runtime = timeRun(arg); 15 | System.out.println("" + msec(parsetime) + " ms(parse) " 16 | + msec(runtime) + " ms(run): " 17 | + arg); 18 | parse_product *= parsetime; 19 | run_product *= runtime; 20 | } 21 | if (0 < args.length) { 22 | double run_geomean = Math.pow(run_product, 1.0 / args.length); 23 | double parse_geomean = Math.pow(parse_product, 1.0 / args.length); 24 | System.out.println("" + msec(parse_geomean) + " ms(parse) " 25 | + msec(run_geomean) + " ms(run): (geometric mean)"); 26 | } 27 | } 28 | 29 | static long msec(double nsec) { 30 | return (long) Math.rint(nsec * 1e-6); 31 | } 32 | 33 | static final int nruns = 1000000; 34 | 35 | static long timeRun(String expression) { 36 | Variable x = Variable.make("x"); 37 | Expr expr = parse(expression); 38 | 39 | double low = 0.0; 40 | double high = 4.0; 41 | double step = (high - low) / nruns; 42 | 43 | long start = System.nanoTime(); 44 | for (double xval = low; xval <= high; xval += step) { 45 | x.setValue(xval); 46 | expr.value(); 47 | } 48 | return System.nanoTime() - start; 49 | } 50 | 51 | static final int nparses = 1000; 52 | 53 | static long timeParse(String expression) { 54 | long start = System.nanoTime(); 55 | for (int i = 0; i < nparses; ++i) 56 | parse(expression); 57 | return System.nanoTime() - start; 58 | } 59 | 60 | static Expr parse(String expression) { 61 | try { 62 | return Parser.parse(expression); 63 | } catch (SyntaxException e) { 64 | System.err.println(e.explain()); 65 | throw new Error(e); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /common/src/main/java/expr/Example.java: -------------------------------------------------------------------------------- 1 | // Put the expression evaluator through its paces. 2 | 3 | // Sample usage: 4 | 5 | // $ java expr.Example '3.14159 * x^2' 0 4 1 6 | // 0 7 | // 3.14159 8 | // 12.5664 9 | // 28.2743 10 | // 50.2654 11 | // 12 | // $ java expr.Example 'sin (pi/4 * x)' 0 4 1 13 | // 0 14 | // 0.707107 15 | // 1 16 | // 0.707107 17 | // 1.22461e-16 18 | // 19 | // $ java expr.Example 'sin (pi/4 x)' 0 4 1 20 | // I don't understand your formula "sin (pi/4 x)". 21 | // 22 | // I got as far as "sin (pi/4" and then saw "x". 23 | // I expected ")" at that point, instead. 24 | // An example of a formula I can parse is "sin (pi/4 + x)". 25 | 26 | package expr; 27 | 28 | /** 29 | * A simple example of parsing and evaluating an expression. 30 | */ 31 | public class Example { 32 | public static void main(String[] args) { 33 | Expr expr; 34 | try { 35 | expr = Parser.parse("3 * x^2"); 36 | } catch (SyntaxException e) { 37 | System.err.println(e.explain()); 38 | return; 39 | } 40 | 41 | 42 | Variable x = Variable.make("x"); 43 | for (double xval = 0; xval <= 3; xval += 1) { 44 | x.setValue(xval); 45 | System.out.println(expr.value()); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /common/src/main/java/expr/Token.java: -------------------------------------------------------------------------------- 1 | // A lexical token from an input string. 2 | 3 | package expr; 4 | 5 | class Token { 6 | public static final int TT_ERROR = -1; 7 | public static final int TT_EOF = -2; 8 | public static final int TT_NUMBER = -3; 9 | public static final int TT_WORD = -4; 10 | public static final int TT_LE = -5; 11 | public static final int TT_NE = -6; 12 | public static final int TT_GE = -7; 13 | 14 | public Token(int ttype, double nval, String input, int start, int end) { 15 | this.ttype = ttype; 16 | this.sval = input.substring(start, end); 17 | this.nval = nval; 18 | this.location = start; 19 | 20 | int count = 0; 21 | for (int i = start - 1; 0 <= i; --i) { 22 | if (!Character.isWhitespace(input.charAt(i))) break; 23 | ++count; 24 | } 25 | this.leadingWhitespace = count; 26 | 27 | count = 0; 28 | for (int i = end; i < input.length(); ++i) { 29 | if (!Character.isWhitespace(input.charAt(i))) break; 30 | ++count; 31 | } 32 | this.trailingWhitespace = count; 33 | } 34 | 35 | Token(int ttype, double nval, String sval, Token token) { 36 | this.ttype = ttype; 37 | this.sval = sval; 38 | this.nval = nval; 39 | this.location = token.location; 40 | this.leadingWhitespace = token.leadingWhitespace; 41 | this.trailingWhitespace = token.trailingWhitespace; 42 | } 43 | 44 | public final int ttype; 45 | public final String sval; 46 | public final double nval; 47 | 48 | public final int location; 49 | 50 | public final int leadingWhitespace, trailingWhitespace; 51 | } 52 | -------------------------------------------------------------------------------- /common/src/main/java/expr/Variable.java: -------------------------------------------------------------------------------- 1 | // Variables associate values with names. 2 | // Copyright 1996 by Darius Bacon; see the file COPYING. 3 | 4 | package expr; 5 | 6 | import java.util.Hashtable; 7 | 8 | /** 9 | * A variable is a simple expression with a name (like "x") and a 10 | * settable value. 11 | */ 12 | public class Variable extends Expr { 13 | private static Hashtable variables = new Hashtable(); 14 | 15 | /** 16 | * Return a unique variable named `name'. There can be only one 17 | * variable with the same name returned by this method; that is, 18 | * make(s1) == make(s2) if and only if s1.equals(s2). 19 | * 20 | * @param name the variable's name 21 | * @return the variable; create it initialized to 0 if it doesn't 22 | * yet exist 23 | */ 24 | static public synchronized Variable make(String name) { 25 | Variable result = (Variable) variables.get(name); 26 | if (result == null) 27 | variables.put(name, result = new Variable(name)); 28 | return result; 29 | } 30 | 31 | private String name; 32 | private double val; 33 | 34 | /** 35 | * Create a new variable, with initial value 0. 36 | * 37 | * @param name the variable's name 38 | */ 39 | public Variable(String name) { 40 | this.name = name; 41 | val = 0; 42 | } 43 | 44 | /** 45 | * Return the name. 46 | */ 47 | public String toString() { 48 | return name; 49 | } 50 | 51 | /** 52 | * Get the value. 53 | * 54 | * @return the current value 55 | */ 56 | public double value() { 57 | return val; 58 | } 59 | 60 | /** 61 | * Set the value. 62 | * 63 | * @param value the new value 64 | */ 65 | public void setValue(double value) { 66 | val = value; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /common/src/main/resources/architectury.common.json: -------------------------------------------------------------------------------- 1 | { 2 | "accessWidener": "photon.accesswidener" 3 | } 4 | -------------------------------------------------------------------------------- /common/src/main/resources/assets/photon/shaders/catmull_rom.comp: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout(local_size_x = 256) in; 4 | 5 | struct Vertex { 6 | vec3 position; 7 | vec4 color; 8 | float lifeTime; 9 | float width; 10 | }; 11 | 12 | layout(std430, binding = 0) buffer InputVertices { 13 | Vertex vertices[]; 14 | }; 15 | 16 | layout(std430, binding = 1) buffer OutputVertices { 17 | Vertex smoothVertices[]; 18 | }; 19 | 20 | layout(binding = 2, offset = 0) uniform atomic_uint outputCount; // 用于记录输出顶点数量 21 | 22 | uniform int inputCount; // 传入的输入顶点数量 23 | uniform float minDistance; 24 | 25 | void main() { 26 | uint id = gl_GlobalInvocationID.x; // 获取全局工作项的ID 27 | 28 | // 只处理有效的顶点索引 29 | if (id >= inputCount - 1) return; 30 | 31 | Vertex current = vertices[id]; 32 | Vertex next = vertices[id + 1]; 33 | 34 | vec3 p0 = vertices[max(int(id) - 1, 0)].position; 35 | vec3 p1 = current.position; 36 | vec3 p2 = next.position; 37 | vec3 p3 = vertices[min(int(id) + 2, inputCount - 1)].position; 38 | 39 | float distance = length(p2 - p1); 40 | 41 | // 插值生成新顶点 42 | if (distance > minDistance) { 43 | int steps = int(distance / minDistance); 44 | for (int j = 1; j <= steps; j++) { 45 | float t = float(j) / float(steps); 46 | vec3 interpolated = 0.5 * ( 47 | (2.0 * p1) + 48 | (-p0 + p2) * t + 49 | (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) * t * t + 50 | (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t * t * t 51 | ); 52 | 53 | // 原子操作增加输出数量,并写入插值顶点 54 | uint idx = atomicCounterIncrement(outputCount); 55 | smoothVertices[idx].position = interpolated; 56 | smoothVertices[idx].color = mix(current.color, next.color, t); 57 | smoothVertices[idx].lifeTime = mix(current.lifeTime, next.lifeTime, t); 58 | smoothVertices[idx].width = mix(current.width, next.width, t); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /common/src/main/resources/assets/photon/shaders/core/circle.fsh: -------------------------------------------------------------------------------- 1 | #version 150 2 | 3 | #moj_import 4 | 5 | uniform vec4 ColorModulator; 6 | uniform float FogStart; 7 | uniform float FogEnd; 8 | uniform vec4 FogColor; 9 | uniform float DiscardThreshold; 10 | uniform float Radius; 11 | 12 | in float vertexDistance; 13 | in vec2 texCoord0; 14 | in vec4 vertexColor; 15 | 16 | out vec4 fragColor; 17 | 18 | void main() { 19 | float dist = distance(vec2(0.5, 0.5), texCoord0); 20 | vec4 color = vertexColor * ColorModulator; 21 | color.a = smoothstep(0., 1., 1. - dist / Radius) * color.a; 22 | if (color.a < DiscardThreshold) { 23 | discard; 24 | } 25 | fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); 26 | } 27 | -------------------------------------------------------------------------------- /common/src/main/resources/assets/photon/shaders/core/circle.json: -------------------------------------------------------------------------------- 1 | { 2 | "blend": { 3 | "func": "add", 4 | "srcrgb": "srcalpha", 5 | "dstrgb": "1-srcalpha" 6 | }, 7 | "vertex": "ldlib:particle", 8 | "fragment": "photon:circle", 9 | "attributes": [ 10 | "Position", 11 | "UV0", 12 | "Color", 13 | "UV2" 14 | ], 15 | "samplers": [ 16 | { "name": "Sampler2" } 17 | ], 18 | "uniforms": [ 19 | { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, 20 | { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, 21 | { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, 22 | { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, 23 | { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, 24 | { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, 25 | { "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] }, 26 | { "name": "DiscardThreshold", "type": "float", "count": 1, "values": [ 0.01 ] }, 27 | { "name": "Radius", "type": "float", "count": 1, "values": [ 0.3 ] } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /common/src/main/resources/assets/photon/shaders/core/separable_blur.fsh: -------------------------------------------------------------------------------- 1 | #version 150 2 | 3 | uniform sampler2D DiffuseSampler; 4 | uniform vec2 OutSize; 5 | uniform vec2 BlurDir; 6 | uniform int Radius; 7 | 8 | in vec2 texCoord; 9 | out vec4 fragColor; 10 | 11 | float gaussianPdf(in float x, in float sigma) { 12 | return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma; 13 | } 14 | 15 | void main(){ 16 | vec2 invSize = 1.0 / OutSize; 17 | float fSigma = float(Radius); 18 | float weightSum = gaussianPdf(0.0, fSigma); 19 | vec3 diffuseSum = texture(DiffuseSampler, texCoord).rgb * weightSum; 20 | for( int i = 1; i < Radius; i ++) { 21 | float x = float(i); 22 | float w = gaussianPdf(x, fSigma); 23 | vec2 uvOffset = BlurDir * invSize * x; 24 | vec3 sample1 = texture(DiffuseSampler, texCoord + uvOffset).rgb; 25 | vec3 sample2 = texture(DiffuseSampler, texCoord - uvOffset).rgb; 26 | diffuseSum += (sample1 + sample2) * w; 27 | weightSum += 2.0 * w; 28 | } 29 | fragColor = vec4(diffuseSum/weightSum, 1.0); 30 | } 31 | -------------------------------------------------------------------------------- /common/src/main/resources/assets/photon/shaders/core/separable_blur.json: -------------------------------------------------------------------------------- 1 | { 2 | "blend": { 3 | "func": "add", 4 | "srcrgb": "one", 5 | "dstrgb": "zero" 6 | }, 7 | "vertex": "ldlib:fast_blit", 8 | "fragment": "photon:separable_blur", 9 | "attributes": [ "Position" ], 10 | "samplers": [ 11 | { "name": "DiffuseSampler" } 12 | ], 13 | "uniforms": [ 14 | { "name": "OutSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] }, 15 | { "name": "BlurDir", "type": "float", "count": 2, "values": [ 0.0, 0.0 ] }, 16 | { "name": "Radius", "type": "int", "count": 1, "values": [ 5 ] } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /common/src/main/resources/assets/photon/shaders/core/unreal_composite.fsh: -------------------------------------------------------------------------------- 1 | #version 150 2 | 3 | uniform sampler2D DiffuseSampler; 4 | uniform sampler2D HighLight; 5 | uniform sampler2D BlurTexture1; 6 | uniform sampler2D BlurTexture2; 7 | uniform sampler2D BlurTexture3; 8 | //uniform sampler2D BlurTexture4; 9 | uniform float BloomRadius; 10 | uniform float BloomIntensive; 11 | //uniform float BloomBase; 12 | //uniform float BloomThresholdUp; 13 | //uniform float BloomThresholdDown; 14 | 15 | in vec2 texCoord; 16 | out vec4 fragColor; 17 | 18 | float lerpBloomFactor(const in float factor) { 19 | float mirrorFactor = 1.2 - factor; 20 | return mix(factor, mirrorFactor, BloomRadius); 21 | } 22 | 23 | vec3 aces(vec3 x) { 24 | const float a = 2.51; 25 | const float b = 0.03; 26 | const float c = 2.43; 27 | const float d = 0.59; 28 | const float e = 0.14; 29 | return clamp((x * (a * x + b)) / (x * (c * x + d) + e), 0.0, 1.0); 30 | } 31 | 32 | vec3 aces_tonemap(vec3 color){ 33 | mat3 m1 = mat3( 34 | 0.59719, 0.07600, 0.02840, 35 | 0.35458, 0.90834, 0.13383, 36 | 0.04823, 0.01566, 0.83777 37 | ); 38 | mat3 m2 = mat3( 39 | 1.60475, -0.10208, -0.00327, 40 | -0.53108, 1.10813, -0.07276, 41 | -0.07367, -0.00605, 1.07602 42 | ); 43 | vec3 v = m1 * color; 44 | vec3 a = v * (v + 0.0245786) - 0.000090537; 45 | vec3 b = v * (0.983729 * v + 0.4329510) + 0.238081; 46 | return pow(clamp(m2 * (a / b), 0.0, 1.0), vec3(1.0 / 2.2)); 47 | } 48 | 49 | vec3 jodieReinhardTonemap(vec3 c){ 50 | float l = dot(c, vec3(0.2126, 0.7152, 0.0722)); 51 | vec3 tc = c / (c + 1.0); 52 | 53 | return mix(c / (l + 1.0), tc, tc); 54 | } 55 | 56 | void main() { 57 | vec4 bloom = BloomIntensive * (lerpBloomFactor(1.) * texture(BlurTexture1, texCoord) + 58 | lerpBloomFactor(0.8) * texture(BlurTexture2, texCoord) + 59 | lerpBloomFactor(0.6) * texture(BlurTexture3, texCoord) 60 | // +lerpBloomFactor(0.4) * texture(BlurTexture4, texCoord) 61 | ); 62 | 63 | vec4 background = texture(DiffuseSampler, texCoord); 64 | vec4 highLight = texture(HighLight, texCoord); 65 | background.rgb = background.rgb * (1 - highLight.a) + highLight.a * highLight.rgb; 66 | fragColor = vec4(background.rgb + jodieReinhardTonemap(bloom.rgb), 1.); 67 | } -------------------------------------------------------------------------------- /common/src/main/resources/assets/photon/shaders/core/unreal_composite.json: -------------------------------------------------------------------------------- 1 | { 2 | "blend": { 3 | "func": "add", 4 | "srcrgb": "one", 5 | "dstrgb": "zero" 6 | }, 7 | "vertex": "ldlib:fast_blit", 8 | "fragment": "photon:unreal_composite", 9 | "attributes": [ "Position" ], 10 | "samplers": [ 11 | { "name": "DiffuseSampler" }, 12 | { "name": "HighLight" }, 13 | { "name": "BlurTexture1" }, 14 | { "name": "BlurTexture2" }, 15 | { "name": "BlurTexture3" } 16 | ], 17 | "uniforms": [ 18 | { "name": "BloomRadius", "type": "float", "count": 1, "values": [ 1.0 ] }, 19 | { "name": "BloomIntensive", "type": "float", "count": 1, "values": [ 1.7 ] } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/resources/assets/photon/textures/particle/kila_tail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Low-Drag-MC/Photon/ce4035f9f086681c3b1b9b0a914c67f357049f67/common/src/main/resources/assets/photon/textures/particle/kila_tail.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/photon/textures/particle/laser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Low-Drag-MC/Photon/ce4035f9f086681c3b1b9b0a914c67f357049f67/common/src/main/resources/assets/photon/textures/particle/laser.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/photon/textures/particle/ring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Low-Drag-MC/Photon/ce4035f9f086681c3b1b9b0a914c67f357049f67/common/src/main/resources/assets/photon/textures/particle/ring.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/photon/textures/particle/smoke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Low-Drag-MC/Photon/ce4035f9f086681c3b1b9b0a914c67f357049f67/common/src/main/resources/assets/photon/textures/particle/smoke.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/photon/textures/particle/thaumcraft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Low-Drag-MC/Photon/ce4035f9f086681c3b1b9b0a914c67f357049f67/common/src/main/resources/assets/photon/textures/particle/thaumcraft.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/photon/textures/particle/thaumcraft.png.mcmeta: -------------------------------------------------------------------------------- 1 | { "texture": { "blur": true }} -------------------------------------------------------------------------------- /common/src/main/resources/hotswap-agent.properties: -------------------------------------------------------------------------------- 1 | # Comma separated list of disabled plugins 2 | disabledPlugins=Log4j2,Proxy 3 | 4 | LOGGER=info -------------------------------------------------------------------------------- /common/src/main/resources/photon-common.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "minVersion": "0.8", 4 | "package": "com.lowdragmc.photon.core.mixins", 5 | "compatibilityLevel": "JAVA_17", 6 | "client": [ 7 | "WorldSceneRendererMixin", 8 | "accessor.BlendModeAccessor", 9 | "accessor.MinecraftAccessor", 10 | "accessor.ParticleEngineAccessor", 11 | "accessor.ShaderInstanceAccessor" 12 | ], 13 | "mixins": [ 14 | ], 15 | "injectors": { 16 | "defaultRequire": 1 17 | } 18 | } -------------------------------------------------------------------------------- /common/src/main/resources/photon.accesswidener: -------------------------------------------------------------------------------- 1 | accessWidener v2 named 2 | -------------------------------------------------------------------------------- /fabric/src/main/java/com/lowdragmc/photon/client/fabric/ClientProxyImpl.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.fabric; 2 | 3 | import com.lowdragmc.photon.client.ClientCommands; 4 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 5 | import net.fabricmc.api.ClientModInitializer; 6 | import net.fabricmc.api.EnvType; 7 | import net.fabricmc.api.Environment; 8 | import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; 9 | import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @author KilaBash 15 | * @date 2023/2/8 16 | * @implNote ClientProxyImpl 17 | */ 18 | @Environment(EnvType.CLIENT) 19 | public class ClientProxyImpl implements ClientModInitializer { 20 | @Override 21 | public void onInitializeClient() { 22 | // register client commands 23 | ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { 24 | List> commands = ClientCommands.createClientCommands(); 25 | commands.forEach(dispatcher::register); 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /fabric/src/main/java/com/lowdragmc/photon/fabric/PhotonImpl.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.fabric; 2 | 3 | import com.lowdragmc.photon.PhotonCommonProxy; 4 | import com.lowdragmc.photon.Photon; 5 | import com.lowdragmc.photon.ServerCommands; 6 | import com.mojang.blaze3d.pipeline.RenderTarget; 7 | import net.fabricmc.api.ModInitializer; 8 | import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; 9 | 10 | public class PhotonImpl implements ModInitializer { 11 | 12 | @Override 13 | public void onInitialize() { 14 | Photon.init(); 15 | // register server commands 16 | CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> ServerCommands.createServerCommands().forEach(dispatcher::register)); 17 | // init common features 18 | PhotonCommonProxy.init(); 19 | } 20 | 21 | public static boolean isStencilEnabled(RenderTarget fbo) { 22 | return false; 23 | } 24 | 25 | public static boolean useCombinedDepthStencilAttachment() { 26 | return false; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /fabric/src/main/java/com/lowdragmc/photon/fabric/core/PhotonMixinPlugin.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.fabric.core; 2 | 3 | import com.lowdragmc.lowdraglib.core.mixins.MixinPluginShared; 4 | import org.objectweb.asm.tree.ClassNode; 5 | import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; 6 | import org.spongepowered.asm.mixin.extensibility.IMixinInfo; 7 | 8 | import java.util.List; 9 | import java.util.Set; 10 | 11 | /** 12 | * @author KilaBash 13 | * @date 2023/6/10 14 | * @implNote PhotonMixinPlugin 15 | */ 16 | public class PhotonMixinPlugin implements IMixinConfigPlugin, MixinPluginShared { 17 | 18 | boolean IS_IRIS_LOAD = MixinPluginShared.isClassFound("net.irisshaders.iris.api.v0.IrisApi"); 19 | 20 | @Override 21 | public void onLoad(String mixinPackage) { 22 | } 23 | 24 | @Override 25 | public String getRefMapperConfig() { 26 | return null; 27 | } 28 | 29 | @Override 30 | public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { 31 | if (mixinClassName.contains("com.lowdragmc.photon.fabric.core.mixins.no_iris")) { 32 | return !IS_IRIS_LOAD; 33 | } 34 | return true; 35 | } 36 | 37 | @Override 38 | public void acceptTargets(Set myTargets, Set otherTargets) { 39 | 40 | } 41 | 42 | @Override 43 | public List getMixins() { 44 | return null; 45 | } 46 | 47 | @Override 48 | public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { 49 | 50 | } 51 | 52 | @Override 53 | public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /fabric/src/main/java/com/lowdragmc/photon/fabric/core/mixins/ArgumentTypeInfosMixin.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.fabric.core.mixins; 2 | 3 | import com.lowdragmc.photon.command.EntityEffectCommand; 4 | import com.lowdragmc.photon.command.FxLocationArgument; 5 | import com.mojang.brigadier.arguments.ArgumentType; 6 | import net.minecraft.commands.synchronization.ArgumentTypeInfo; 7 | import net.minecraft.commands.synchronization.ArgumentTypeInfos; 8 | import net.minecraft.commands.synchronization.SingletonArgumentInfo; 9 | import net.minecraft.core.Registry; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | import org.spongepowered.asm.mixin.injection.At; 13 | import org.spongepowered.asm.mixin.injection.Inject; 14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 15 | 16 | 17 | /** 18 | * @author KilaBash 19 | * @date 2023/6/12 20 | * @implNote ArgumentTypeInfosMixin 21 | */ 22 | @Mixin(ArgumentTypeInfos.class) 23 | public abstract class ArgumentTypeInfosMixin { 24 | @Shadow 25 | private static , T extends ArgumentTypeInfo.Template> ArgumentTypeInfo register(Registry> registry, String id, Class argumentClass, ArgumentTypeInfo info) { 26 | return null; 27 | } 28 | 29 | @Inject( 30 | method = "bootstrap", 31 | at = {@At(value = "HEAD")}) 32 | private static void injectRegisterArgumentTypes(Registry> registry, CallbackInfoReturnable> cir) { 33 | register(registry, "fx_location", FxLocationArgument.class, SingletonArgumentInfo.contextFree(FxLocationArgument::new)); 34 | register(registry, "fx_auto_rotate", EntityEffectCommand.AutoRotateType.class, SingletonArgumentInfo.contextFree(EntityEffectCommand.AutoRotateType::new)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /fabric/src/main/java/com/lowdragmc/photon/fabric/core/mixins/LevelRendererMixin.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.fabric.core.mixins; 2 | 3 | import com.lowdragmc.photon.Photon; 4 | import com.lowdragmc.photon.client.gameobject.emitter.PhotonParticleRenderType; 5 | import com.mojang.blaze3d.vertex.PoseStack; 6 | import net.minecraft.client.Camera; 7 | import net.minecraft.client.Minecraft; 8 | import net.minecraft.client.renderer.*; 9 | import net.minecraft.client.renderer.culling.Frustum; 10 | import org.joml.Matrix4f; 11 | import org.spongepowered.asm.mixin.Final; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.Shadow; 14 | import org.spongepowered.asm.mixin.injection.At; 15 | import org.spongepowered.asm.mixin.injection.Inject; 16 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 17 | 18 | /** 19 | * @author KilaBash 20 | * @date 2023/6/10 21 | * @implNote LevelRendererMixin 22 | */ 23 | @Mixin(LevelRenderer.class) 24 | public class LevelRendererMixin { 25 | 26 | @Shadow private Frustum cullingFrustum; 27 | 28 | @Shadow @Final private Minecraft minecraft; 29 | 30 | @Shadow @Final private RenderBuffers renderBuffers; 31 | 32 | /** 33 | * inject opaque layer being rendered 34 | */ 35 | @Inject( 36 | method = {"renderLevel"}, 37 | at = {@At( 38 | value = "CONSTANT", 39 | args = {"stringValue=entities"}, 40 | shift = At.Shift.BEFORE, 41 | by = 1 42 | )} 43 | ) 44 | private void prepareForParticleRendering(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci) { 45 | PhotonParticleRenderType.prepareForParticleRendering(cullingFrustum); 46 | if (!Photon.isShaderModInstalled()) { // if we install shader mod, it will help to do it. 47 | MultiBufferSource.BufferSource bufferSource = this.renderBuffers.bufferSource(); 48 | this.minecraft.particleEngine.render(poseStack, bufferSource, lightTexture, camera, partialTick); 49 | 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /fabric/src/main/java/com/lowdragmc/photon/fabric/core/mixins/ShaderInstanceMixin.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.fabric.core.mixins; 2 | 3 | import com.lowdragmc.photon.Photon; 4 | import net.minecraft.client.renderer.ShaderInstance; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.ModifyArg; 8 | 9 | 10 | /** 11 | * @author KilaBash 12 | * @date 2022/05/02 13 | * @implNote ShaderInstanceMixin, inject custom shader config to vanilla shader configs. 14 | * Ensure the shader is loading from the correct resource location. Fabric ignores the ResourceLocation path passed to this method 15 | */ 16 | @Mixin(ShaderInstance.class) 17 | public abstract class ShaderInstanceMixin { 18 | 19 | @ModifyArg(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/resources/ResourceLocation;(Ljava/lang/String;)V"), index = 0) 20 | private String injectInit(String string) { 21 | if (string.startsWith("shaders/core/%s:".formatted(Photon.MOD_ID))) { 22 | return Photon.MOD_ID + ":" + string.replace(Photon.MOD_ID + ":", ""); 23 | } 24 | return string; 25 | } 26 | 27 | @ModifyArg(method = "getOrCreate", at = @At(value = "INVOKE", target = "Lnet/minecraft/FileUtil;getFullResourcePath(Ljava/lang/String;)Ljava/lang/String;"), index = 0) 28 | private static String injectFile(String string) { 29 | if (string.startsWith("shaders/core/%s:".formatted(Photon.MOD_ID))) { 30 | return Photon.MOD_ID + ":" + string.replace(Photon.MOD_ID + ":", ""); 31 | } 32 | return string; 33 | } 34 | 35 | @ModifyArg(method = "getOrCreate", at = @At(value = "INVOKE", target = "Lnet/minecraft/resources/ResourceLocation;(Ljava/lang/String;)V"), index = 0) 36 | private static String injectCreate(String string) { 37 | if (string.startsWith("shaders/core/%s:".formatted(Photon.MOD_ID))) { 38 | return Photon.MOD_ID + ":" + string.replace(Photon.MOD_ID + ":", ""); 39 | } 40 | return string; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /fabric/src/main/java/com/lowdragmc/photon/fabric/core/mixins/no_iris/ParticleEngineMixin.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.fabric.core.mixins.no_iris; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import com.lowdragmc.photon.client.gameobject.emitter.PhotonParticleRenderType; 5 | import com.lowdragmc.photon.client.gameobject.emitter.data.RendererSetting; 6 | import net.minecraft.client.particle.ParticleEngine; 7 | import net.minecraft.client.particle.ParticleRenderType; 8 | import org.spongepowered.asm.mixin.Final; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Redirect; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | /** 18 | * @author KilaBash 19 | * @date 2022/05/02 20 | * @implNote ParticleEngineMixin, inject particle postprocessing 21 | */ 22 | @Mixin(ParticleEngine.class) 23 | public abstract class ParticleEngineMixin { 24 | private static final List OPAQUE_PARTICLE_RENDER_TYPES = ImmutableList.of(ParticleRenderType.TERRAIN_SHEET, ParticleRenderType.PARTICLE_SHEET_OPAQUE, ParticleRenderType.PARTICLE_SHEET_LIT, ParticleRenderType.CUSTOM, ParticleRenderType.NO_RENDER); 25 | @Shadow @Final private static List RENDER_ORDER; 26 | @Redirect( 27 | method = {"render"}, 28 | at = @At( 29 | value = "FIELD", 30 | target = "Lnet/minecraft/client/particle/ParticleEngine;RENDER_ORDER:Ljava/util/List;" 31 | ) 32 | ) 33 | private List injectParticlesToRender() { 34 | List toRender = new ArrayList<>(RENDER_ORDER); 35 | if (PhotonParticleRenderType.getLAYER() == RendererSetting.Layer.Opaque) { 36 | toRender.remove(ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT); 37 | return toRender; 38 | } else { 39 | toRender.removeAll(OPAQUE_PARTICLE_RENDER_TYPES); 40 | } 41 | return toRender; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /fabric/src/main/resources/assets/photon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Low-Drag-MC/Photon/ce4035f9f086681c3b1b9b0a914c67f357049f67/fabric/src/main/resources/assets/photon/icon.png -------------------------------------------------------------------------------- /fabric/src/main/resources/fabric.mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 1, 3 | "id": "${mod_id}", 4 | "version": "${version}", 5 | "name": "${mod_name}", 6 | "description": "${mod_description}", 7 | "authors": [ 8 | "KilaBash" 9 | ], 10 | "contact": { 11 | "homepage": "${mod_url}", 12 | "sources": "${mod_url}" 13 | }, 14 | "license": "${mod_license}", 15 | "icon": "assets/${mod_id}/icon.png", 16 | "environment": "*", 17 | "entrypoints": { 18 | "main": [ 19 | "com.lowdragmc.photon.fabric.PhotonImpl" 20 | ], 21 | "client": [ 22 | "com.lowdragmc.photon.client.fabric.ClientProxyImpl" 23 | ], 24 | "ldlib_pugin": [ 25 | "com.lowdragmc.photon.integration.PhotonLDLibPlugin" 26 | ] 27 | }, 28 | "mixins": [ 29 | "${mod_id}.mixins.json", 30 | "${mod_id}-common.mixins.json" 31 | ], 32 | "depends": { 33 | "minecraft": "${minecraft_version}", 34 | "fabricloader": ">=${fabric_loader_version}", 35 | "fabric-api": ">=${fabric_api_version}" 36 | } 37 | } -------------------------------------------------------------------------------- /fabric/src/main/resources/photon.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "minVersion": "0.8", 4 | "package": "com.lowdragmc.photon.fabric.core.mixins", 5 | "plugin": "com.lowdragmc.photon.fabric.core.PhotonMixinPlugin", 6 | "compatibilityLevel": "JAVA_17", 7 | "client": [ 8 | "LevelRendererMixin", 9 | "ParticleEngineMixin", 10 | "ShaderInstanceMixin", 11 | "no_iris.ParticleEngineMixin" 12 | ], 13 | "mixins": [ 14 | "ArgumentTypeInfosMixin" 15 | ], 16 | "injectors": { 17 | "defaultRequire": 1 18 | } 19 | } -------------------------------------------------------------------------------- /forge/gradle.properties: -------------------------------------------------------------------------------- 1 | loom.platform=forge -------------------------------------------------------------------------------- /forge/src/main/java/com/lowdragmc/photon/client/forge/ClientEventListener.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.forge; 2 | 3 | import com.lowdragmc.photon.Photon; 4 | import com.lowdragmc.photon.client.ClientCommands; 5 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 6 | import net.minecraft.commands.CommandSourceStack; 7 | import net.minecraftforge.api.distmarker.Dist; 8 | import net.minecraftforge.api.distmarker.OnlyIn; 9 | import net.minecraftforge.client.event.RegisterClientCommandsEvent; 10 | import net.minecraftforge.eventbus.api.SubscribeEvent; 11 | import net.minecraftforge.fml.common.Mod; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * @author KilaBash 17 | * @date 2022/5/12 18 | * @implNote EventListener 19 | */ 20 | @Mod.EventBusSubscriber(modid = Photon.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE, value = Dist.CLIENT) 21 | @OnlyIn(Dist.CLIENT) 22 | public class ClientEventListener { 23 | 24 | @SubscribeEvent 25 | public static void onRegisterClientCommands(RegisterClientCommandsEvent event) { 26 | var dispatcher = event.getDispatcher(); 27 | List> commands = ClientCommands.createClientCommands(); 28 | commands.forEach(dispatcher::register); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /forge/src/main/java/com/lowdragmc/photon/client/forge/ClientProxyImpl.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.client.forge; 2 | 3 | import com.lowdragmc.photon.forge.CommonProxyImpl; 4 | import net.minecraftforge.api.distmarker.Dist; 5 | import net.minecraftforge.api.distmarker.OnlyIn; 6 | 7 | 8 | @OnlyIn(Dist.CLIENT) 9 | public class ClientProxyImpl extends CommonProxyImpl { 10 | 11 | public ClientProxyImpl() { 12 | super(); 13 | 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /forge/src/main/java/com/lowdragmc/photon/forge/CommonProxyImpl.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.forge; 2 | 3 | import com.lowdragmc.photon.Photon; 4 | import com.lowdragmc.photon.PhotonCommonProxy; 5 | import com.lowdragmc.photon.ServerCommands; 6 | import com.lowdragmc.photon.command.EntityEffectCommand; 7 | import com.lowdragmc.photon.command.FxLocationArgument; 8 | import net.minecraft.commands.synchronization.ArgumentTypeInfo; 9 | import net.minecraft.commands.synchronization.ArgumentTypeInfos; 10 | import net.minecraft.commands.synchronization.SingletonArgumentInfo; 11 | import net.minecraftforge.common.MinecraftForge; 12 | import net.minecraftforge.event.RegisterCommandsEvent; 13 | import net.minecraftforge.eventbus.api.IEventBus; 14 | import net.minecraftforge.eventbus.api.SubscribeEvent; 15 | import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; 16 | import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; 17 | import net.minecraftforge.registries.DeferredRegister; 18 | import net.minecraftforge.registries.ForgeRegistries; 19 | import net.minecraftforge.registries.RegistryObject; 20 | 21 | public class CommonProxyImpl { 22 | static final DeferredRegister> ARG_TYPES = DeferredRegister.create(ForgeRegistries.COMMAND_ARGUMENT_TYPES, Photon.MOD_ID); 23 | static final RegistryObject> FX_LOCATION_ARG_TYPE = ARG_TYPES.register("fx_location", () -> SingletonArgumentInfo.contextFree(FxLocationArgument::new)); 24 | static final RegistryObject> AUTO_ROTATE_ARG_TYPE = ARG_TYPES.register("fx_auto_rotate", () -> SingletonArgumentInfo.contextFree(EntityEffectCommand.AutoRotateType::new)); 25 | 26 | public CommonProxyImpl() { 27 | // used for forge events (ClientProxy + CommonProxy) 28 | IEventBus eventBus = FMLJavaModLoadingContext.get().getModEventBus(); 29 | eventBus.register(this); 30 | // register server commands 31 | ARG_TYPES.register(eventBus); 32 | MinecraftForge.EVENT_BUS.addListener(this::registerCommand); 33 | // init common features 34 | PhotonCommonProxy.init(); 35 | } 36 | 37 | @SubscribeEvent 38 | public void setup(FMLCommonSetupEvent event) { 39 | ArgumentTypeInfos.registerByClass(FxLocationArgument.class, FX_LOCATION_ARG_TYPE.get()); 40 | ArgumentTypeInfos.registerByClass(EntityEffectCommand.AutoRotateType.class, AUTO_ROTATE_ARG_TYPE.get()); 41 | } 42 | 43 | public void registerCommand(RegisterCommandsEvent event) { 44 | var dispatcher = event.getDispatcher(); 45 | ServerCommands.createServerCommands().forEach(dispatcher::register); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /forge/src/main/java/com/lowdragmc/photon/forge/PhotonImpl.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.forge; 2 | 3 | import com.lowdragmc.photon.Photon; 4 | import com.lowdragmc.photon.client.forge.ClientProxyImpl; 5 | import com.mojang.blaze3d.pipeline.RenderTarget; 6 | import net.minecraftforge.common.ForgeConfig; 7 | import net.minecraftforge.fml.DistExecutor; 8 | import net.minecraftforge.fml.common.Mod; 9 | 10 | @Mod(Photon.MOD_ID) 11 | public class PhotonImpl { 12 | public PhotonImpl() { 13 | Photon.init(); 14 | DistExecutor.unsafeRunForDist(() -> ClientProxyImpl::new, () -> CommonProxyImpl::new); 15 | } 16 | 17 | public static boolean isStencilEnabled(RenderTarget target) { 18 | return target.isStencilEnabled(); 19 | } 20 | 21 | public static boolean useCombinedDepthStencilAttachment() { 22 | return ForgeConfig.CLIENT.useCombinedDepthStencilAttachment.get(); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /forge/src/main/java/com/lowdragmc/photon/forge/core/PhotonMixinPlugin.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.forge.core; 2 | 3 | import com.lowdragmc.lowdraglib.core.mixins.MixinPluginShared; 4 | import org.objectweb.asm.tree.ClassNode; 5 | import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; 6 | import org.spongepowered.asm.mixin.extensibility.IMixinInfo; 7 | 8 | import java.util.List; 9 | import java.util.Set; 10 | 11 | /** 12 | * @author KilaBash 13 | * @date 2023/6/10 14 | * @implNote PhotonMixinPlugin 15 | */ 16 | public class PhotonMixinPlugin implements IMixinConfigPlugin, MixinPluginShared { 17 | 18 | boolean IS_IRIS_LOAD = MixinPluginShared.isClassFound("net.irisshaders.iris.api.v0.IrisApi"); 19 | 20 | @Override 21 | public void onLoad(String mixinPackage) { 22 | 23 | } 24 | 25 | @Override 26 | public String getRefMapperConfig() { 27 | return null; 28 | } 29 | 30 | @Override 31 | public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { 32 | if (mixinClassName.contains("com.lowdragmc.photon.forge.core.mixins.no_iris")) { 33 | return !IS_IRIS_LOAD; 34 | } 35 | return true; 36 | } 37 | 38 | @Override 39 | public void acceptTargets(Set myTargets, Set otherTargets) { 40 | 41 | } 42 | 43 | @Override 44 | public List getMixins() { 45 | return null; 46 | } 47 | 48 | @Override 49 | public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { 50 | 51 | } 52 | 53 | @Override 54 | public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /forge/src/main/java/com/lowdragmc/photon/forge/core/mixins/LevelRendererMixin.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.forge.core.mixins; 2 | 3 | import com.lowdragmc.photon.Photon; 4 | import com.lowdragmc.photon.client.gameobject.emitter.PhotonParticleRenderType; 5 | import com.mojang.blaze3d.vertex.PoseStack; 6 | import net.minecraft.client.Camera; 7 | import net.minecraft.client.Minecraft; 8 | import net.minecraft.client.renderer.*; 9 | import net.minecraft.client.renderer.culling.Frustum; 10 | import org.joml.Matrix4f; 11 | import org.spongepowered.asm.mixin.Final; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.Shadow; 14 | import org.spongepowered.asm.mixin.injection.At; 15 | import org.spongepowered.asm.mixin.injection.Inject; 16 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 17 | 18 | /** 19 | * @author KilaBash 20 | * @date 2023/6/10 21 | * @implNote LevelRendererMixin 22 | */ 23 | @Mixin(LevelRenderer.class) 24 | public class LevelRendererMixin { 25 | 26 | @Shadow private Frustum cullingFrustum; 27 | 28 | @Shadow @Final private Minecraft minecraft; 29 | 30 | @Shadow @Final private RenderBuffers renderBuffers; 31 | 32 | /** 33 | * inject opaque layer being rendered 34 | */ 35 | @Inject( 36 | method = {"renderLevel"}, 37 | at = {@At( 38 | value = "CONSTANT", 39 | args = {"stringValue=entities"}, 40 | shift = At.Shift.BEFORE, 41 | by = 1 42 | )} 43 | ) 44 | private void prepareForParticleRendering(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci) { 45 | PhotonParticleRenderType.prepareForParticleRendering(cullingFrustum); 46 | if (!Photon.isShaderModInstalled()) { // if we install shader mod, it will help to do it. 47 | MultiBufferSource.BufferSource bufferSource = this.renderBuffers.bufferSource(); 48 | this.minecraft.particleEngine.render(poseStack, bufferSource, lightTexture, camera, partialTick, cullingFrustum); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /forge/src/main/java/com/lowdragmc/photon/forge/core/mixins/ParticleEngineMixin.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.forge.core.mixins; 2 | 3 | import com.lowdragmc.photon.client.gameobject.emitter.PhotonParticleRenderType; 4 | import com.lowdragmc.photon.client.fx.BlockEffect; 5 | import com.lowdragmc.photon.client.fx.EntityEffect; 6 | import com.mojang.blaze3d.vertex.PoseStack; 7 | import net.minecraft.client.Camera; 8 | import net.minecraft.client.multiplayer.ClientLevel; 9 | import net.minecraft.client.particle.ParticleEngine; 10 | import net.minecraft.client.renderer.LightTexture; 11 | import net.minecraft.client.renderer.MultiBufferSource; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.injection.At; 14 | import org.spongepowered.asm.mixin.injection.Inject; 15 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 16 | 17 | 18 | /** 19 | * @author KilaBash 20 | * @date 2022/05/02 21 | * @implNote ParticleEngineMixin, inject particle postprocessing 22 | */ 23 | @Mixin(ParticleEngine.class) 24 | public abstract class ParticleEngineMixin { 25 | 26 | /** 27 | * notify finish render switch to next render layer 28 | */ 29 | @Inject(method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/culling/Frustum;)V", 30 | at = @At(value = "RETURN"), remap = false) 31 | private void injectRenderReturn(PoseStack pMatrixStack, MultiBufferSource.BufferSource pBuffer, LightTexture pLightTexture, Camera pActiveRenderInfo, float pPartialTicks, net.minecraft.client.renderer.culling.Frustum clippingHelper, CallbackInfo ci) { 32 | PhotonParticleRenderType.finishRender(); 33 | } 34 | 35 | /** 36 | * clear effect cache while level changes. 37 | */ 38 | @Inject(method = "setLevel", 39 | at = @At(value = "RETURN")) 40 | private void injectSetLevel(ClientLevel level, CallbackInfo ci) { 41 | EntityEffect.CACHE.clear(); 42 | BlockEffect.CACHE.clear(); 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /forge/src/main/java/com/lowdragmc/photon/forge/core/mixins/no_iris/ParticleEngineMixin.java: -------------------------------------------------------------------------------- 1 | package com.lowdragmc.photon.forge.core.mixins.no_iris; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import com.lowdragmc.photon.client.gameobject.emitter.PhotonParticleRenderType; 5 | import com.lowdragmc.photon.client.gameobject.emitter.data.RendererSetting; 6 | import net.minecraft.client.particle.Particle; 7 | import net.minecraft.client.particle.ParticleEngine; 8 | import net.minecraft.client.particle.ParticleRenderType; 9 | import org.spongepowered.asm.mixin.Final; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | import org.spongepowered.asm.mixin.injection.At; 13 | import org.spongepowered.asm.mixin.injection.Redirect; 14 | 15 | import java.util.*; 16 | 17 | /** 18 | * @author KilaBash 19 | * @date 2022/05/02 20 | * @implNote ParticleEngineMixin, inject particle postprocessing 21 | */ 22 | @Mixin(ParticleEngine.class) 23 | public abstract class ParticleEngineMixin { 24 | private static final List OPAQUE_PARTICLE_RENDER_TYPES = ImmutableList.of(ParticleRenderType.TERRAIN_SHEET, ParticleRenderType.PARTICLE_SHEET_OPAQUE, ParticleRenderType.PARTICLE_SHEET_LIT, ParticleRenderType.CUSTOM, ParticleRenderType.NO_RENDER); 25 | @Shadow @Final private Map> particles; 26 | 27 | @Redirect( 28 | method = {"render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/culling/Frustum;)V"}, 29 | at = @At( 30 | value = "FIELD", 31 | target = "Lnet/minecraft/client/particle/ParticleEngine;particles:Ljava/util/Map;" 32 | ) 33 | ) 34 | private Map> iris$selectParticlesToRender(ParticleEngine instance) { 35 | Map> toRender = new HashMap<>(this.particles); 36 | if (PhotonParticleRenderType.getLAYER() == RendererSetting.Layer.Opaque) { 37 | toRender.remove(ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT); 38 | } else { 39 | for (var type : OPAQUE_PARTICLE_RENDER_TYPES) { 40 | toRender.remove(type); 41 | } 42 | } 43 | return toRender; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /forge/src/main/resources/META-INF/mods.toml: -------------------------------------------------------------------------------- 1 | modLoader = "javafml" 2 | loaderVersion = "[${forge_version},)" 3 | #issueTrackerURL = "" 4 | license = "${mod_license}" 5 | 6 | [[mods]] 7 | modId = "${mod_id}" 8 | version = "${version}" 9 | displayName = "${mod_name}" 10 | authors = "KilaBash" 11 | description = "${mod_description}" 12 | logoFile = "icon.png" 13 | displayURL = "${mod_url}" 14 | 15 | [[dependencies.${mod_id}]] 16 | modId = "forge" 17 | mandatory = true 18 | versionRange = "[${forge_version},)" 19 | ordering = "NONE" 20 | side = "BOTH" 21 | 22 | [[dependencies.${mod_id}]] 23 | modId = "minecraft" 24 | mandatory = true 25 | versionRange = "${minecraft_version}" 26 | ordering = "NONE" 27 | side = "BOTH" -------------------------------------------------------------------------------- /forge/src/main/resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Low-Drag-MC/Photon/ce4035f9f086681c3b1b9b0a914c67f357049f67/forge/src/main/resources/icon.png -------------------------------------------------------------------------------- /forge/src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "GTCEu Resource Pack", 4 | "pack_format": 8 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /forge/src/main/resources/photon.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "minVersion": "0.8", 4 | "package": "com.lowdragmc.photon.forge.core.mixins", 5 | "plugin": "com.lowdragmc.photon.forge.core.PhotonMixinPlugin", 6 | "compatibilityLevel": "JAVA_17", 7 | "client": [ 8 | "ParticleEngineMixin", 9 | "LevelRendererMixin", 10 | "no_iris.ParticleEngineMixin" 11 | ], 12 | "mixins": [ 13 | ], 14 | "injectors": { 15 | "defaultRequire": 1 16 | } 17 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs = -Xmx6G 2 | 3 | # Mod Info 4 | mod_id = photon 5 | mod_name = Photon 6 | mod_version = 1.1.8 7 | mod_description = Photon, particle system 8 | mod_license = GPL-3.0 license 9 | mod_url = https://github.com/Low-Drag-MC/Photon/ 10 | 11 | 12 | maven_group = com.lowdragmc.photon 13 | 14 | enabled_platforms = fabric,forge 15 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Low-Drag-MC/Photon/ce4035f9f086681c3b1b9b0a914c67f357049f67/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | --------------------------------------------------------------------------------