Explorar o código

Particle Factory API (closes architectury#93)

Leo40Git %!s(int64=4) %!d(string=hai) anos
pai
achega
81b0cc5821

+ 55 - 0
common/src/main/java/me/shedaniel/architectury/registry/ParticleFactories.java

@@ -0,0 +1,55 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020, 2021 architectury
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package me.shedaniel.architectury.registry;
+
+import me.shedaniel.architectury.annotations.ExpectPlatform;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.client.particle.ParticleProvider;
+import net.minecraft.client.particle.SpriteSet;
+import net.minecraft.client.renderer.texture.TextureAtlas;
+import net.minecraft.client.renderer.texture.TextureAtlasSprite;
+import net.minecraft.core.particles.ParticleOptions;
+import net.minecraft.core.particles.ParticleType;
+
+import java.util.List;
+
+@Environment(EnvType.CLIENT)
+public final class ParticleFactories {
+    public interface ExtendedSpriteSet extends SpriteSet {
+        TextureAtlas getAtlas();
+        List<TextureAtlasSprite> getSprites();
+    }
+
+    @ExpectPlatform
+    <T extends ParticleOptions> void register(ParticleType<T> type, ParticleProvider<T> provider) {
+        throw new AssertionError();
+    }
+
+    @ExpectPlatform
+    <T extends ParticleOptions> void register(ParticleType<T> type, PendingParticleProvider<T> constructor) {
+        throw new AssertionError();
+    }
+
+    @FunctionalInterface
+    public interface PendingParticleProvider<T extends ParticleOptions> {
+        ParticleProvider<T> create(ExtendedSpriteSet spriteSet);
+    }
+}

+ 70 - 0
fabric/src/main/java/me/shedaniel/architectury/registry/fabric/ParticleFactoriesImpl.java

@@ -0,0 +1,70 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020, 2021 architectury
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package me.shedaniel.architectury.registry.fabric;
+
+import me.shedaniel.architectury.registry.ParticleFactories;
+import net.fabricmc.fabric.api.client.particle.v1.FabricSpriteProvider;
+import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry;
+import net.minecraft.client.particle.ParticleProvider;
+import net.minecraft.client.renderer.texture.TextureAtlas;
+import net.minecraft.client.renderer.texture.TextureAtlasSprite;
+import net.minecraft.core.particles.ParticleOptions;
+import net.minecraft.core.particles.ParticleType;
+
+import java.util.List;
+import java.util.Random;
+
+public class ParticleFactoriesImpl {
+    public static class ExtendedSpriteSetImpl implements ParticleFactories.ExtendedSpriteSet {
+        private final FabricSpriteProvider delegate;
+    
+        public ExtendedSpriteSetImpl(FabricSpriteProvider delegate) {
+            this.delegate = delegate;
+        }
+    
+        @Override
+        public TextureAtlas getAtlas() {
+            return delegate.getAtlas();
+        }
+    
+        @Override
+        public List<TextureAtlasSprite> getSprites() {
+            return delegate.getSprites();
+        }
+    
+        @Override
+        public TextureAtlasSprite get(int i, int j) {
+            return delegate.get(i, j);
+        }
+    
+        @Override
+        public TextureAtlasSprite get(Random random) {
+            return delegate.get(random);
+        }
+    }
+
+    public static <T extends ParticleOptions> void register(ParticleType<T> type, ParticleProvider<T> provider) {
+        ParticleFactoryRegistry.getInstance().register(type, provider);
+    }
+
+    public static <T extends ParticleOptions> void register(ParticleType<T> type, ParticleFactories.PendingParticleProvider<T> constructor) {
+        ParticleFactoryRegistry.getInstance().register(type, provider -> constructor.create(new ExtendedSpriteSetImpl(provider)));
+    }
+}

+ 47 - 0
forge/src/main/java/me/shedaniel/architectury/mixin/forge/ParticleEngineAccessor.java

@@ -0,0 +1,47 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020, 2021 architectury
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package me.shedaniel.architectury.mixin.forge;
+
+import net.minecraft.client.particle.ParticleEngine;
+import net.minecraft.client.particle.SpriteSet;
+import net.minecraft.client.renderer.texture.TextureAtlas;
+import net.minecraft.client.renderer.texture.TextureAtlasSprite;
+import net.minecraft.resources.ResourceLocation;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+import java.util.List;
+import java.util.Map;
+
+@Mixin(ParticleEngine.class)
+public interface ParticleEngineAccessor {
+    @Accessor
+    TextureAtlas getTextureAtlas();
+    
+    // this is actually a Map<ResourceLocation, ParticleEngine.MutableSpriteSet>, but luckily type erasure saves the day
+    @Accessor
+    Map<ResourceLocation, SpriteSet> getProviders();
+    
+    @Mixin(targets = "net/minecraft/client/particle/ParticleEngine$MutableSpriteSet")
+    interface MutableSpriteSetAccessor {
+        @Accessor
+        List<TextureAtlasSprite> getSprites();
+    }
+}

+ 108 - 0
forge/src/main/java/me/shedaniel/architectury/registry/forge/ParticleFactoriesImpl.java

@@ -0,0 +1,108 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020, 2021 architectury
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package me.shedaniel.architectury.registry.forge;
+
+import me.shedaniel.architectury.forge.ArchitecturyForge;
+import me.shedaniel.architectury.mixin.forge.ParticleEngineAccessor;
+import me.shedaniel.architectury.registry.ParticleFactories;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.particle.ParticleEngine;
+import net.minecraft.client.particle.ParticleProvider;
+import net.minecraft.client.particle.SpriteSet;
+import net.minecraft.client.renderer.texture.TextureAtlas;
+import net.minecraft.client.renderer.texture.TextureAtlasSprite;
+import net.minecraft.core.particles.ParticleOptions;
+import net.minecraft.core.particles.ParticleType;
+import net.minecraftforge.client.event.ParticleFactoryRegisterEvent;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.fml.common.Mod;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+@Mod.EventBusSubscriber(modid = ArchitecturyForge.MOD_ID)
+public class ParticleFactoriesImpl {
+    private static final class ExtendedSpriteSetImpl implements ParticleFactories.ExtendedSpriteSet {
+        private final ParticleEngine engine;
+        private final SpriteSet delegate;
+    
+        private ExtendedSpriteSetImpl(ParticleEngine engine, SpriteSet delegate) {
+            this.engine = engine;
+            this.delegate = delegate;
+        }
+
+        @Override
+        public TextureAtlas getAtlas() {
+            return ((ParticleEngineAccessor) engine).getTextureAtlas();
+        }
+
+        @Override
+        public List<TextureAtlasSprite> getSprites() {
+            return ((ParticleEngineAccessor.MutableSpriteSetAccessor) delegate).getSprites();
+        }
+
+        @Override
+        public TextureAtlasSprite get(int i, int j) {
+            return delegate.get(i, j);
+        }
+
+        @Override
+        public TextureAtlasSprite get(Random random) {
+            return delegate.get(random);
+        }
+    }
+
+    private static ArrayList<Runnable> deferred = new ArrayList<>();
+
+    private static <T extends ParticleOptions> void _register(ParticleType<T> type, ParticleProvider<T> provider) {
+        Minecraft.getInstance().particleEngine.register(type, provider);
+    }
+
+    private static <T extends ParticleOptions> void _register(ParticleType<T> type, ParticleFactories.PendingParticleProvider<T> constructor) {
+        Minecraft.getInstance().particleEngine.register(type, arg ->
+                constructor.create(new ExtendedSpriteSetImpl(Minecraft.getInstance().particleEngine, arg)));
+    }
+
+    public static <T extends ParticleOptions> void register(ParticleType<T> type, ParticleProvider<T> provider) {
+        if (deferred == null)
+            _register(type, provider);
+        else
+            deferred.add(() -> _register(type, provider));
+    }
+
+    public static <T extends ParticleOptions> void register(ParticleType<T> type, ParticleFactories.PendingParticleProvider<T> constructor) {
+        if (deferred == null)
+            _register(type, constructor);
+        else
+            deferred.add(() -> _register(type, constructor));
+    }
+
+    @SubscribeEvent
+    public static void onParticleFactoryRegister(ParticleFactoryRegisterEvent unused) {
+        if (deferred != null) {
+            // run all deferred registrations
+            for (Runnable r : deferred)
+                r.run();
+            // yeet deferred list - register immediately from now on
+            deferred = null;
+        }
+    }
+}

+ 3 - 1
forge/src/main/resources/architectury.mixins.json

@@ -20,7 +20,9 @@
     "MixinItemExtension",
     "MixinRegistryEntry",
     "MixinWorldEvent",
-    "MobSpawnSettingsBuilderAccessor"
+    "MobSpawnSettingsBuilderAccessor",
+    "ParticleEngineAccessor",
+    "ParticleEngineAccessor$MutableSpriteSetAccessor"
   ],
   "injectors": {
     "defaultRequire": 1