From dd380f1e7ad098b3f129bf96b167186e02e78bcd Mon Sep 17 00:00:00 2001 From: Timo Ley Date: Wed, 17 Apr 2024 11:39:15 +0200 Subject: [PATCH] chore: init 1.7.10 --- build.gradle | 128 +++-- common/build.gradle | 23 - .../net/anvilcraft/anvillib/AnvilLib.java | 21 - .../java/net/anvilcraft/anvillib/Util.java | 28 -- .../cosmetics/ClientEventHandler.java | 43 -- .../cosmetics/CosmeticArmorRenderer.java | 453 ------------------ .../cosmetics/CosmeticFeatureRenderer.java | 94 ---- .../anvillib/cosmetics/CosmeticItem.java | 49 -- .../anvillib/cosmetics/CosmeticModel.java | 67 --- .../anvillib/cosmetics/CosmeticParts.java | 53 -- .../anvillib/cosmetics/CosmeticsManager.java | 90 ---- .../anvillib/cosmetics/ICosmetic.java | 56 --- .../anvillib/cosmetics/ICosmeticProvider.java | 16 - .../cosmetics/remote/RemoteCosmetic.java | 123 ----- .../remote/RemoteCosmeticProvider.java | 121 ----- .../cosmetics/remote/model/AnimationData.java | 12 - .../cosmetics/remote/model/CapeData.java | 10 - .../cosmetics/remote/model/CosmeticData.java | 18 - .../cosmetics/remote/model/PlayerData.java | 15 - .../cosmetics/remote/model/TextureData.java | 18 - .../thread/AbstractFileDownloaderThread.java | 84 ---- .../remote/thread/CapeLoaderThread.java | 65 --- .../thread/CosmeticAssetsLoaderThread.java | 156 ------ .../remote/thread/CosmeticLoaderThread.java | 34 -- .../thread/PlayerCosmeticLoaderThread.java | 39 -- .../event/AddEntityRenderLayersEvent.java | 9 - .../net/anvilcraft/anvillib/event/Bus.java | 31 -- .../anvillib/event/IEventBusRegisterable.java | 12 - .../accessor/AnimatedGeoModelAccessor.java | 20 - .../AbstractClientPlayerEntityMixin.java | 42 -- .../mixin/client/MinecraftClientMixin.java | 18 - .../mixin/common/RecipeManagerMixin.java | 48 -- .../StructurePoolBasedGeneratorMixin.java | 32 -- .../anvillib/mixinutils/BeardifierLocals.java | 14 - .../recipe/AbstractIngredientCondition.java | 23 - .../anvillib/recipe/IRecipeMapper.java | 12 - .../recipe/IngredientsContainPredicate.java | 19 - .../recipe/InputReplaceRecipeMapper.java | 54 --- .../recipe/RecipeContainsPredicate.java | 22 - .../anvillib/recipe/RecipesEvent.java | 79 --- .../anvillib/recipe/ShapedRecipeBuilder.java | 94 ---- .../recipe/StackIngredientCondition.java | 18 - .../recipe/TagIngredientCondition.java | 18 - .../AdvancedStructurePoolFeatureConfig.java | 53 -- .../resources/anvillib-common.mixins.json | 18 - .../src/main/resources/anvillib.accesswidener | 12 - .../main/resources/architectury.common.json | 3 - common/src/main/resources/pack.mcmeta | 7 - fabric/build.gradle | 71 --- .../anvilcraft/anvillib/AnvilLibFabric.java | 16 - .../client/EntityRenderDispatcherMixin.java | 27 -- .../mixin/fabric/common/BeardifierMixin.java | 126 ----- .../src/main/resources/anvillib.mixins.json | 15 - fabric/src/main/resources/fabric.mod.json | 32 -- forge/build.gradle | 79 --- forge/gradle.properties | 1 - .../anvilcraft/anvillib/AnvilLibForge.java | 15 - .../anvillib/client/ClientEventHandler.java | 21 - .../forge/accessor/AddLayersAccessor.java | 16 - .../mixin/forge/common/BeardifierMixin.java | 138 ------ forge/src/main/resources/META-INF/mods.toml | 36 -- forge/src/main/resources/anvillib.mixins.json | 15 - gradle.properties | 16 - gradle/scripts/mixins.gradle | 78 +++ gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 51017 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- settings.gradle | 14 - 67 files changed, 167 insertions(+), 3027 deletions(-) delete mode 100644 common/build.gradle delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/AnvilLib.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/Util.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/ClientEventHandler.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticArmorRenderer.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticFeatureRenderer.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticItem.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticModel.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticParts.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticsManager.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/ICosmetic.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/ICosmeticProvider.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/RemoteCosmetic.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/RemoteCosmeticProvider.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/AnimationData.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/CapeData.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/CosmeticData.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/PlayerData.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/TextureData.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/AbstractFileDownloaderThread.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/CapeLoaderThread.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/CosmeticAssetsLoaderThread.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/CosmeticLoaderThread.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/PlayerCosmeticLoaderThread.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/event/AddEntityRenderLayersEvent.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/event/Bus.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/event/IEventBusRegisterable.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/mixin/accessor/AnimatedGeoModelAccessor.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/mixin/client/AbstractClientPlayerEntityMixin.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/mixin/client/MinecraftClientMixin.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/mixin/common/RecipeManagerMixin.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/mixin/common/StructurePoolBasedGeneratorMixin.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/mixinutils/BeardifierLocals.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/recipe/AbstractIngredientCondition.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/recipe/IRecipeMapper.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/recipe/IngredientsContainPredicate.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/recipe/InputReplaceRecipeMapper.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/recipe/RecipeContainsPredicate.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/recipe/RecipesEvent.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/recipe/ShapedRecipeBuilder.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/recipe/StackIngredientCondition.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/recipe/TagIngredientCondition.java delete mode 100644 common/src/main/java/net/anvilcraft/anvillib/worldgen/AdvancedStructurePoolFeatureConfig.java delete mode 100644 common/src/main/resources/anvillib-common.mixins.json delete mode 100644 common/src/main/resources/anvillib.accesswidener delete mode 100644 common/src/main/resources/architectury.common.json delete mode 100644 common/src/main/resources/pack.mcmeta delete mode 100644 fabric/build.gradle delete mode 100644 fabric/src/main/java/net/anvilcraft/anvillib/AnvilLibFabric.java delete mode 100644 fabric/src/main/java/net/anvilcraft/anvillib/mixin/fabric/client/EntityRenderDispatcherMixin.java delete mode 100644 fabric/src/main/java/net/anvilcraft/anvillib/mixin/fabric/common/BeardifierMixin.java delete mode 100644 fabric/src/main/resources/anvillib.mixins.json delete mode 100644 fabric/src/main/resources/fabric.mod.json delete mode 100644 forge/build.gradle delete mode 100644 forge/gradle.properties delete mode 100644 forge/src/main/java/net/anvilcraft/anvillib/AnvilLibForge.java delete mode 100644 forge/src/main/java/net/anvilcraft/anvillib/client/ClientEventHandler.java delete mode 100644 forge/src/main/java/net/anvilcraft/anvillib/mixin/forge/accessor/AddLayersAccessor.java delete mode 100644 forge/src/main/java/net/anvilcraft/anvillib/mixin/forge/common/BeardifierMixin.java delete mode 100644 forge/src/main/resources/META-INF/mods.toml delete mode 100644 forge/src/main/resources/anvillib.mixins.json delete mode 100644 gradle.properties create mode 100644 gradle/scripts/mixins.gradle delete mode 100644 settings.gradle diff --git a/build.gradle b/build.gradle index 3e23cb5..7698397 100644 --- a/build.gradle +++ b/build.gradle @@ -1,50 +1,95 @@ -plugins { - id "architectury-plugin" version "3.4-SNAPSHOT" - id "dev.architectury.loom" version "1.3-SNAPSHOT" apply false -} - -architectury { - minecraft = rootProject.minecraft_version -} - -subprojects { - apply plugin: "dev.architectury.loom" - +buildscript { + repositories { + mavenCentral() + maven { + name = "forge" + url = "https://maven.minecraftforge.net/" + } + maven { + name = "sonatype" + url = "https://oss.sonatype.org/content/repositories/snapshots/" + } + } dependencies { - minecraft "com.mojang:minecraft:${rootProject.minecraft_version}" - // The following line declares the yarn mappings you may select this one as well. - mappings "net.fabricmc:yarn:1.18.2+build.4:v2" + classpath ('com.anatawa12.forge:ForgeGradle:1.2-1.0.+') { + changing = true + } } } -allprojects { - apply plugin: "java" - apply plugin: "architectury-plugin" - apply plugin: "maven-publish" +apply plugin: 'forge' +apply plugin: 'maven-publish' +apply from: './gradle/scripts/mixins.gradle' - base { - archivesName = rootProject.archives_base_name +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 + +version = "0.1.0" +group= "net.anvilcraft" +archivesBaseName = "anvillib-7" + +configurations { + embedded + implementation.extendsFrom(embedded) +} + +minecraft { + version = "1.7.10-10.13.4.1614-1.7.10" + runDir = "run" +} + +repositories { + mavenCentral() + maven { url = "https://maven.tilera.xyz" } + maven { url = "https://jitpack.io" } +} + +dependencies { + embedded "net.anvilcraft:jalec:0.1.2" + implementation "com.github.tox1cozZ:mixin-booter-legacy:1.1.2" + annotationProcessor "com.github.tox1cozZ:mixin-booter-legacy:1.1.2:processor" +} + +jar { + from (configurations.embedded.collect { it.isDirectory() ? it : zipTree(it) }) { + duplicatesStrategy = 'exclude' + exclude 'LICENSE.txt', 'META-INF/MANIFSET.MF', 'META-INF/maven/**', 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/services/*.Processor', 'META-INF/versions/**' } +} - version = rootProject.mod_version - group = rootProject.maven_group +processResources { + inputs.property "version", project.version + inputs.property "mcversion", project.minecraft.version + + filesMatching('mcmod.info') { + expand 'version':project.version, 'mcversion':project.minecraft.version + } +} + +task deobfJar(type: Jar) { + from sourceSets.main.output + classifier = 'deobf' +} + +task sourcesJar(type: Jar) { + from sourceSets.main.allSource + classifier = 'sources' +} + +publishing { + tasks.publish.dependsOn 'build' + publications { + mavenJava(MavenPublication) { + artifactId = project.archivesBaseName + + artifact deobfJar + artifact sourcesJar + artifact jar + } + } repositories { - maven { url "https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/" } - } - - tasks.withType(JavaCompile) { - options.encoding = "UTF-8" - options.release = 17 - } - - java { - withSourcesJar() - } - - publishing { - repositories { - if (project.hasProperty("mvnURL")) { + if (project.hasProperty('mvnURL')) { maven { credentials { username findProperty("mvnUsername") @@ -52,8 +97,9 @@ allprojects { } url = findProperty("mvnURL") } - } - mavenLocal() + } + else { + mavenLocal() } } -} +} \ No newline at end of file diff --git a/common/build.gradle b/common/build.gradle deleted file mode 100644 index 482ed4c..0000000 --- a/common/build.gradle +++ /dev/null @@ -1,23 +0,0 @@ -architectury { - common(rootProject.enabled_platforms.split(",")) -} - -loom { - accessWidenerPath = file("src/main/resources/anvillib.accesswidener") -} - -dependencies { - // We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies - // Do NOT use other classes from fabric loader - modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" - modImplementation "software.bernie.geckolib:geckolib-fabric-1.18:3.0.80" -} - -publishing { - publications { - mavenCommon(MavenPublication) { - artifactId = rootProject.archives_base_name - from components.java - } - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/AnvilLib.java b/common/src/main/java/net/anvilcraft/anvillib/AnvilLib.java deleted file mode 100644 index a96814b..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/AnvilLib.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.anvilcraft.anvillib; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import net.anvilcraft.anvillib.cosmetics.ClientEventHandler; -import net.anvilcraft.anvillib.event.Bus; -import software.bernie.geckolib3.GeckoLib; - -public class AnvilLib { - public static final String MODID = "anvillib"; - public static final Logger LOGGER = LogManager.getLogger(); - - public static void initialize() { - GeckoLib.initialize(); - } - - public static void initializeClient() { - Bus.MAIN.register(new ClientEventHandler()); - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/Util.java b/common/src/main/java/net/anvilcraft/anvillib/Util.java deleted file mode 100644 index 8d76795..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/Util.java +++ /dev/null @@ -1,28 +0,0 @@ -package net.anvilcraft.anvillib; - -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.Ingredient; -import net.minecraft.tag.TagKey; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; - -public class Util { - public static ItemStack stackFromRegistry(Identifier id) { - if (Registry.ITEM.containsId(id)) { - return new ItemStack(Registry.ITEM.get(id)); - } else if (Registry.BLOCK.containsId(id)) { - return new ItemStack(Registry.BLOCK.get(id)); - } else { - throw new IllegalArgumentException("No block or item with ID " + id + "!"); - } - } - - public static Ingredient ingredientFromString(String s) { - if (s.charAt(0) == '#') - return Ingredient.fromTag( - TagKey.of(Registry.ITEM_KEY, new Identifier(s.substring(1))) - ); - - return Ingredient.ofStacks(stackFromRegistry(new Identifier(s))); - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/ClientEventHandler.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/ClientEventHandler.java deleted file mode 100644 index 2982abb..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/ClientEventHandler.java +++ /dev/null @@ -1,43 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics; - -import java.io.File; -import java.net.URI; -import java.util.Objects; -import java.util.Map.Entry; - -import net.anvilcraft.anvillib.AnvilLib; -import net.anvilcraft.anvillib.cosmetics.remote.RemoteCosmeticProvider; -import net.anvilcraft.anvillib.event.AddEntityRenderLayersEvent; -import net.anvilcraft.anvillib.event.Bus; -import net.anvilcraft.anvillib.event.IEventBusRegisterable; -import net.minecraft.client.render.entity.EntityRenderer; -import net.minecraft.client.render.entity.PlayerEntityRenderer; -import net.minecraft.entity.player.PlayerEntity; - -public class ClientEventHandler implements IEventBusRegisterable { - private void onAddLayers(AddEntityRenderLayersEvent ev) { - for (Entry> skin : - ev.skinMap().entrySet()) - if (skin.getValue() instanceof PlayerEntityRenderer render) - render.addFeature(new CosmeticFeatureRenderer(render, skin.getKey())); - } - - public static void registerRemoteCosmetics(File assetsCache) { - File cacheDir = new File(Objects.requireNonNull(assetsCache), "anvillib"); - try { - URI playerBase = new URI("https://api.tilera.xyz/anvillib/data/players/"); - URI cosmeticBase = new URI("https://api.tilera.xyz/anvillib/data/cosmetics/"); - URI capeBase = new URI("https://api.tilera.xyz/anvillib/data/capes/"); - CosmeticsManager.registerProvider( - new RemoteCosmeticProvider(playerBase, cosmeticBase, capeBase, cacheDir) - ); - } catch (Exception e) { - AnvilLib.LOGGER.error(e); - } - } - - @Override - public void registerEventHandlers(Bus bus) { - bus.register(AddEntityRenderLayersEvent.class, this::onAddLayers); - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticArmorRenderer.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticArmorRenderer.java deleted file mode 100644 index 00287e5..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticArmorRenderer.java +++ /dev/null @@ -1,453 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics; - -import java.util.Arrays; -import java.util.Objects; - -import com.mojang.blaze3d.systems.RenderSystem; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.AbstractClientPlayerEntity; -import net.minecraft.client.render.OverlayTexture; -import net.minecraft.client.render.RenderLayer; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.entity.model.BipedEntityModel; -import net.minecraft.client.render.entity.model.EntityModelLayers; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.Matrix4f; -import net.minecraft.util.math.Vec3d; -import net.minecraft.util.math.Vec3f; -import net.minecraft.util.math.Vector4f; -import software.bernie.geckolib3.core.IAnimatable; -import software.bernie.geckolib3.core.IAnimatableModel; -import software.bernie.geckolib3.core.controller.AnimationController; -import software.bernie.geckolib3.core.controller.AnimationController.ModelFetcher; -import software.bernie.geckolib3.core.event.predicate.AnimationEvent; -import software.bernie.geckolib3.core.processor.IBone; -import software.bernie.geckolib3.core.util.Color; -import software.bernie.geckolib3.geo.render.built.GeoBone; -import software.bernie.geckolib3.geo.render.built.GeoModel; -import software.bernie.geckolib3.geo.render.built.GeoQuad; -import software.bernie.geckolib3.geo.render.built.GeoVertex; -import software.bernie.geckolib3.model.AnimatedGeoModel; -import software.bernie.geckolib3.renderers.geo.IGeoRenderer; -import software.bernie.geckolib3.util.EModelRenderCycle; -import software.bernie.geckolib3.util.GeoUtils; -import software.bernie.geckolib3.util.IRenderCycle; -import software.bernie.geckolib3.util.RenderUtils; - -public class CosmeticArmorRenderer extends BipedEntityModel - implements IGeoRenderer, ModelFetcher { - protected CosmeticItem currentArmorItem; - protected LivingEntity entityLiving; - protected float widthScale = 1; - protected float heightScale = 1; - protected Matrix4f dispatchedMat = new Matrix4f(); - protected Matrix4f renderEarlyMat = new Matrix4f(); - protected int currentFrame = 0; - - public String headBone = null; - public String bodyBone = null; - public String rightArmBone = null; - public String leftArmBone = null; - public String rightLegBone = null; - public String leftLegBone = null; - - private final AnimatedGeoModel modelProvider; - - protected VertexConsumerProvider rtb = null; - - private IRenderCycle currentModelRenderCycle = EModelRenderCycle.INITIAL; - - { AnimationController.addModelFetcher(this); } - - @Override - public IAnimatableModel apply(IAnimatable t) { - if (t instanceof CosmeticItem) - return this.getGeoModelProvider(); - return null; - } - - public CosmeticArmorRenderer() { - super(MinecraftClient.getInstance().getEntityModelLoader().getModelPart( - EntityModelLayers.PLAYER_INNER_ARMOR - )); - - this.modelProvider = new CosmeticModel(); - } - - @Override - public void render( - MatrixStack poseStack, - VertexConsumer buffer, - int packedLight, - int packedOverlay, - float red, - float green, - float blue, - float alpha - ) { - this.render(0, poseStack, buffer, packedLight); - } - - public void render( - float partialTick, MatrixStack poseStack, VertexConsumer buffer, int packedLight - ) { - GeoModel model = this.modelProvider.getModel( - this.modelProvider.getModelLocation(this.currentArmorItem) - ); - AnimationEvent animationEvent = new AnimationEvent<>( - this.currentArmorItem, - 0, - 0, - MinecraftClient.getInstance().getTickDelta(), - false, // can also be getLastFrameDuration() - Arrays.asList(this.entityLiving) - ); - - poseStack.push(); - poseStack.translate(0, 24 / 16F, 0); - poseStack.scale(-1, -1, 1); - - double currentTick = entityLiving.age / this.getCurrentCosmetic().getFrameTime(); - currentFrame - = ((int) (currentTick * 1.0F)) % this.getCurrentCosmetic().getTotalFrames(); - ; - - //this.dispatchedMat = poseStack.last().pose().copy(); - this.dispatchedMat = poseStack.peek().getPositionMatrix().copy(); - - this.modelProvider.setCustomAnimations( - this.currentArmorItem, getInstanceId(this.currentArmorItem), animationEvent - ); - setCurrentModelRenderCycle(EModelRenderCycle.INITIAL); - fitToBiped(); - RenderSystem.setShaderTexture(0, getTextureLocation(this.currentArmorItem)); - - Color renderColor = getRenderColor( - this.currentArmorItem, partialTick, poseStack, null, buffer, packedLight - ); - RenderLayer renderType = getRenderType( - this.currentArmorItem, - partialTick, - poseStack, - null, - buffer, - packedLight, - getTextureLocation(this.currentArmorItem) - ); - - render( - model, - this.currentArmorItem, - partialTick, - renderType, - poseStack, - null, - buffer, - packedLight, - OverlayTexture.DEFAULT_UV, - renderColor.getRed() / 255f, - renderColor.getGreen() / 255f, - renderColor.getBlue() / 255f, - renderColor.getAlpha() / 255f - ); - - //if (ModList.get().isLoaded("patchouli")) - // PatchouliCompat.patchouliLoaded(poseStack); - - poseStack.pop(); - } - - @Override - public void renderEarly( - CosmeticItem animatable, - MatrixStack poseStack, - float partialTick, - VertexConsumerProvider bufferSource, - VertexConsumer buffer, - int packedLight, - int packedOverlay, - float red, - float green, - float blue, - float alpha - ) { - //this.renderEarlyMat = poseStack.last().pose().copy(); - this.renderEarlyMat = poseStack.peek().getPositionMatrix().copy(); - this.currentArmorItem = animatable; - - IGeoRenderer.super.renderEarly( - animatable, - poseStack, - partialTick, - bufferSource, - buffer, - packedLight, - packedOverlay, - red, - green, - blue, - alpha - ); - } - - @Override - public void renderRecursively( - GeoBone bone, - MatrixStack poseStack, - VertexConsumer buffer, - int packedLight, - int packedOverlay, - float red, - float green, - float blue, - float alpha - ) { - if (bone.isTrackingXform()) { - //Matrix4f poseState = poseStack.last().pose(); - Matrix4f poseState = poseStack.peek().getPositionMatrix(); - Vec3d renderOffset = getRenderOffset(this.currentArmorItem, 1); - Matrix4f localMatrix - = RenderUtils.invertAndMultiplyMatrices(poseState, this.dispatchedMat); - - bone.setModelSpaceXform( - RenderUtils.invertAndMultiplyMatrices(poseState, this.renderEarlyMat) - ); - //localMatrix.translate(new Vec3f(renderOffset)); - localMatrix.addToLastColumn(new Vec3f(renderOffset)); - bone.setLocalSpaceXform(localMatrix); - } - - IGeoRenderer.super.renderRecursively( - bone, poseStack, buffer, packedLight, packedOverlay, red, green, blue, alpha - ); - } - - public Vec3d getRenderOffset(CosmeticItem entity, float partialTick) { - return Vec3d.ZERO; - } - - protected void fitToBiped() { - if (this.headBone != null) { - IBone headBone = this.modelProvider.getBone(this.headBone); - - GeoUtils.copyRotations(this.head, headBone); - headBone.setPositionX(this.head.pivotX); - headBone.setPositionY(-this.head.pivotY); - headBone.setPositionZ(this.head.pivotZ); - } - - if (this.bodyBone != null) { - IBone bodyBone = this.modelProvider.getBone(this.bodyBone); - - GeoUtils.copyRotations(this.body, bodyBone); - bodyBone.setPositionX(this.body.pivotX); - bodyBone.setPositionY(-this.body.pivotY); - bodyBone.setPositionZ(this.body.pivotZ); - } - - if (this.rightArmBone != null) { - IBone rightArmBone = this.modelProvider.getBone(this.rightArmBone); - - GeoUtils.copyRotations(this.rightArm, rightArmBone); - rightArmBone.setPositionX(this.rightArm.pivotX + 5); - rightArmBone.setPositionY(2 - this.rightArm.pivotY); - rightArmBone.setPositionZ(this.rightArm.pivotZ); - } - - if (this.leftArmBone != null) { - IBone leftArmBone = this.modelProvider.getBone(this.leftArmBone); - - GeoUtils.copyRotations(this.leftArm, leftArmBone); - leftArmBone.setPositionX(this.leftArm.pivotX - 5); - leftArmBone.setPositionY(2 - this.leftArm.pivotY); - leftArmBone.setPositionZ(this.leftArm.pivotZ); - } - - if (this.rightLegBone != null) { - IBone rightLegBone = this.modelProvider.getBone(this.rightLegBone); - - GeoUtils.copyRotations(this.rightLeg, rightLegBone); - rightLegBone.setPositionX(this.rightLeg.pivotX + 2); - rightLegBone.setPositionY(12 - this.rightLeg.pivotY); - rightLegBone.setPositionZ(this.rightLeg.pivotZ); - } - - if (this.leftLegBone != null) { - IBone leftLegBone = this.modelProvider.getBone(this.leftLegBone); - - GeoUtils.copyRotations(this.leftLeg, leftLegBone); - leftLegBone.setPositionX(this.leftLeg.pivotX - 2); - leftLegBone.setPositionY(12 - this.leftLeg.pivotY); - leftLegBone.setPositionZ(this.leftLeg.pivotZ); - } - } - - @Override - public AnimatedGeoModel getGeoModelProvider() { - return this.modelProvider; - } - - @Override - public IRenderCycle getCurrentModelRenderCycle() { - return this.currentModelRenderCycle; - } - - @Override - public void setCurrentModelRenderCycle(IRenderCycle currentModelRenderCycle) { - this.currentModelRenderCycle = currentModelRenderCycle; - } - - @Override - public float getWidthScale(CosmeticItem animatable) { - return this.widthScale; - } - - @Override - public float getHeightScale(CosmeticItem entity) { - return this.heightScale; - } - - @Override - public Identifier getTextureLocation(CosmeticItem animatable) { - return this.modelProvider.getTextureLocation(animatable); - } - - /** - * Everything after this point needs to be called every frame before rendering - */ - public CosmeticArmorRenderer setCurrentItem(LivingEntity entity, CosmeticItem item) { - this.entityLiving = entity; - this.currentArmorItem = item; - - return this; - } - - public final CosmeticArmorRenderer - applyEntityStats(BipedEntityModel defaultArmor) { - this.child = defaultArmor.child; - this.sneaking = defaultArmor.sneaking; - this.riding = defaultArmor.riding; - this.rightArmPose = defaultArmor.rightArmPose; - this.leftArmPose = defaultArmor.leftArmPose; - - return this; - } - - public void filterBones() { - this.headBone = getCurrentCosmetic().getHead(); - this.bodyBone = getCurrentCosmetic().getBody(); - this.leftArmBone = getCurrentCosmetic().getLeftArm(); - this.rightArmBone = getCurrentCosmetic().getRightArm(); - this.leftLegBone = getCurrentCosmetic().getLeftLeg(); - this.rightLegBone = getCurrentCosmetic().getRightLeg(); - - getGeoModelProvider().getModel(getCurrentCosmetic().getModelLocation()); - - this.setBoneVisibility(this.headBone, getCurrentCosmetic().getHead() != null); - this.setBoneVisibility(this.bodyBone, getCurrentCosmetic().getBody() != null); - this.setBoneVisibility( - this.leftArmBone, getCurrentCosmetic().getLeftArm() != null - ); - this.setBoneVisibility( - this.rightArmBone, getCurrentCosmetic().getRightArm() != null - ); - this.setBoneVisibility( - this.leftLegBone, getCurrentCosmetic().getLeftLeg() != null - ); - this.setBoneVisibility( - this.rightLegBone, getCurrentCosmetic().getRightLeg() != null - ); - } - - /** - * Sets a specific bone (and its child-bones) to visible or not - * @param boneName The name of the bone - * @param isVisible Whether the bone should be visible - */ - protected void setBoneVisibility(String boneName, boolean isVisible) { - if (boneName == null) - return; - - this.modelProvider.getBone(boneName).setHidden(!isVisible); - } - - /** - * Use {@link CosmeticArmorRenderer#setBoneVisibility(String, boolean)} - */ - @Deprecated(forRemoval = true) - protected IBone getAndHideBone(String boneName) { - setBoneVisibility(boneName, false); - - return this.modelProvider.getBone(boneName); - } - - @Override - public int getInstanceId(CosmeticItem animatable) { - return Objects.hash( - this.currentArmorItem.getCosmetic().getID(), this.entityLiving.getUuid() - ); - } - - @Override - public void setCurrentRTB(VertexConsumerProvider bufferSource) { - this.rtb = bufferSource; - } - - @Override - public VertexConsumerProvider getCurrentRTB() { - return this.rtb; - } - - public ICosmetic getCurrentCosmetic() { - return this.currentArmorItem.getCosmetic(); - } - - public float calcVOffset(float v) { - float totalFrames = (float) this.getCurrentCosmetic().getTotalFrames(); - float currentTextureOffset = (float) currentFrame / totalFrames; - return (v / totalFrames) + currentTextureOffset; - } - - @Override - public void createVerticesOfQuad( - GeoQuad quad, - Matrix4f poseState, - Vec3f normal, - VertexConsumer buffer, - int packedLight, - int packedOverlay, - float red, - float green, - float blue, - float alpha - ) { - for (GeoVertex vertex : quad.vertices) { - Vector4f vector4f = new Vector4f( - vertex.position.getX(), vertex.position.getY(), vertex.position.getZ(), 1 - ); - - vector4f.transform(poseState); - buffer.vertex( - vector4f.getX(), - vector4f.getY(), - vector4f.getZ(), - red, - green, - blue, - alpha, - vertex.textureU, - calcVOffset(vertex.textureV), - packedOverlay, - packedLight, - normal.getX(), - normal.getY(), - normal.getZ() - ); - } - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticFeatureRenderer.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticFeatureRenderer.java deleted file mode 100644 index 67bb795..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticFeatureRenderer.java +++ /dev/null @@ -1,94 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics; - -import java.util.HashMap; -import java.util.Map; - -import net.minecraft.client.model.ModelPart; -import net.minecraft.client.network.AbstractClientPlayerEntity; -import net.minecraft.client.render.RenderLayer; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.entity.PlayerEntityRenderer; -import net.minecraft.client.render.entity.feature.ArmorFeatureRenderer; -import net.minecraft.client.render.entity.model.BipedEntityModel; -import net.minecraft.client.render.entity.model.PlayerEntityModel; -import net.minecraft.client.render.item.ItemRenderer; -import net.minecraft.client.util.math.MatrixStack; - -public class CosmeticFeatureRenderer extends ArmorFeatureRenderer< - AbstractClientPlayerEntity, - PlayerEntityModel, - BipedEntityModel> { - private static final Map modelCache = new HashMap<>(); - private static CosmeticArmorRenderer cosmeticRenderer = null; - PlayerEntityRenderer renderer; - String skin; - - public CosmeticFeatureRenderer(PlayerEntityRenderer renderer, String skin) { - super(renderer, null, null); - this.renderer = renderer; - this.skin = skin; - } - - @Override - public void render( - MatrixStack matrix, - VertexConsumerProvider buffer, - int light, - AbstractClientPlayerEntity player, - float limbSwing, - float limbSwingAmount, - float partialTicks, - float ageInTicks, - float netHeadYaw, - float headPitch - ) { - if (player.isInvisible()) - return; - for (ICosmetic c : CosmeticsManager.getCosmeticsForPlayer(player.getUuid())) { - if (c.readyToRender()) - this.renderCosmetic(matrix, buffer, player, light, c, partialTicks); - } - } - - private void renderCosmetic( - MatrixStack matrix, - VertexConsumerProvider buffer, - AbstractClientPlayerEntity player, - int light, - ICosmetic cosmetic, - float partialTicks - ) { - if (cosmeticRenderer == null) - cosmeticRenderer = new CosmeticArmorRenderer(); - if (!modelCache.containsKey(cosmetic)) - modelCache.put(cosmetic, new CosmeticItem(cosmetic)); - CosmeticItem item = modelCache.get(cosmetic); - copyRotations(this.renderer.getModel(), cosmeticRenderer); - cosmeticRenderer.applyEntityStats(this.renderer.getModel()); - cosmeticRenderer.setCurrentItem(player, item); - cosmeticRenderer.filterBones(); - - VertexConsumer vertex = ItemRenderer.getArmorGlintConsumer( - buffer, - RenderLayer.getArmorCutoutNoCull(cosmetic.getTextureLocation()), - false, - false - ); - cosmeticRenderer.render(partialTicks, matrix, vertex, light); - } - - private static void copyRotations(BipedEntityModel from, BipedEntityModel to) { - copyRotations(from.head, to.head); - copyRotations(from.hat, to.hat); - copyRotations(from.body, to.body); - copyRotations(from.leftArm, to.leftArm); - copyRotations(from.rightArm, to.rightArm); - copyRotations(from.rightLeg, to.rightLeg); - copyRotations(from.leftLeg, to.leftLeg); - } - - private static void copyRotations(ModelPart from, ModelPart to) { - to.copyTransform(from); - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticItem.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticItem.java deleted file mode 100644 index e7c1faf..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticItem.java +++ /dev/null @@ -1,49 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics; - -import software.bernie.geckolib3.core.IAnimatable; -import software.bernie.geckolib3.core.PlayState; -import software.bernie.geckolib3.core.builder.AnimationBuilder; -import software.bernie.geckolib3.core.builder.ILoopType.EDefaultLoopTypes; -import software.bernie.geckolib3.core.controller.AnimationController; -import software.bernie.geckolib3.core.event.predicate.AnimationEvent; -import software.bernie.geckolib3.core.manager.AnimationData; -import software.bernie.geckolib3.core.manager.AnimationFactory; -import software.bernie.geckolib3.util.GeckoLibUtil; - -public class CosmeticItem implements IAnimatable { - private ICosmetic cosmetic = null; - private AnimationBuilder animationBuilder = new AnimationBuilder(); - - public CosmeticItem(ICosmetic cosmetic) { - this.cosmetic = cosmetic; - if (cosmetic.getIdleAnimationName() != null) { - this.animationBuilder.addAnimation( - cosmetic.getIdleAnimationName(), EDefaultLoopTypes.LOOP - ); - } - } - - private

PlayState predicate(AnimationEvent

event) { - event.getController().transitionLengthTicks = 0; - event.getController().setAnimation(animationBuilder); - return PlayState.CONTINUE; - } - - @Override - public void registerControllers(AnimationData data) { - data.addAnimationController( - new AnimationController<>(this, "controller", 20, this::predicate) - ); - } - - private final AnimationFactory factory = GeckoLibUtil.createFactory(this); - - @Override - public AnimationFactory getFactory() { - return this.factory; - } - - public ICosmetic getCosmetic() { - return this.cosmetic; - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticModel.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticModel.java deleted file mode 100644 index 2681a1f..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticModel.java +++ /dev/null @@ -1,67 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics; - -import net.anvilcraft.anvillib.mixin.accessor.AnimatedGeoModelAccessor; -import net.minecraft.util.Identifier; -import software.bernie.geckolib3.core.IAnimatable; -import software.bernie.geckolib3.core.builder.Animation; -import software.bernie.geckolib3.file.AnimationFile; -import software.bernie.geckolib3.geo.exception.GeckoLibException; -import software.bernie.geckolib3.geo.render.built.GeoBone; -import software.bernie.geckolib3.geo.render.built.GeoModel; -import software.bernie.geckolib3.model.AnimatedGeoModel; -import software.bernie.geckolib3.resource.GeckoLibCache; - -public class CosmeticModel extends AnimatedGeoModel { - @Override - public Identifier getAnimationFileLocation(CosmeticItem animatable) { - return animatable.getCosmetic().getAnimationFileLocation(); - } - - @Override - public Identifier getModelLocation(CosmeticItem animatable) { - return animatable.getCosmetic().getModelLocation(); - } - - @Override - public Identifier getTextureLocation(CosmeticItem animatable) { - return animatable.getCosmetic().getTextureLocation(); - } - - @Override - public Animation getAnimation(String name, IAnimatable animatable) { - Identifier location - = ((CosmeticItem) animatable).getCosmetic().getAnimationFileLocation(); - AnimationFile animation = CosmeticsManager.getAnimations(location); - if (animation == null) { - animation = GeckoLibCache.getInstance().getAnimations().get(location); - } - - if (animation == null) { - throw new GeckoLibException( - location, "Could not find animation file. Please double check name." - ); - } - - return animation.getAnimation(name); - } - - @Override - public GeoModel getModel(Identifier location) { - GeoModel model = CosmeticsManager.getModel(location); - if (model == null) { - model = GeckoLibCache.getInstance().getGeoModels().get(location); - } - - AnimatedGeoModelAccessor accessor = (AnimatedGeoModelAccessor) this; - if (model != accessor.getCurrentModel()) { - accessor.getAnimationProcessor().clearModelRendererList(); - accessor.setCurrentModel(model); - - for (GeoBone bone : model.topLevelBones) { - registerBone(bone); - } - } - - return model; - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticParts.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticParts.java deleted file mode 100644 index 5323ec7..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticParts.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics; - -import java.util.Optional; - -import software.bernie.geckolib3.geo.render.built.GeoBone; -import software.bernie.geckolib3.geo.render.built.GeoModel; - -public class CosmeticParts { - public boolean head = false; - public boolean body = false; - public boolean leftArm = false; - public boolean leftLeg = false; - public boolean rightArm = false; - public boolean rightLeg = false; - - public final String headName = "head"; - public final String bodyName = "body"; - public final String leftArmName = "arm_left"; - public final String leftLegName = "leg_left"; - public final String rightArmName = "arm_right"; - public final String rightLegName = "leg_right"; - - public CosmeticParts() {} - - public CosmeticParts(GeoModel model) { - Optional maybeRoot = model.getBone("root"); - if (maybeRoot.isEmpty()) - return; - GeoBone root = maybeRoot.get(); - for (GeoBone bone : root.childBones) { - switch (bone.name) { - case headName: - this.head = true; - break; - case bodyName: - this.body = true; - break; - case leftArmName: - this.leftArm = true; - break; - case leftLegName: - this.leftLeg = true; - break; - case rightArmName: - this.rightArm = true; - break; - case rightLegName: - this.rightLeg = true; - break; - } - } - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticsManager.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticsManager.java deleted file mode 100644 index c191de6..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/CosmeticsManager.java +++ /dev/null @@ -1,90 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -import net.minecraft.util.Identifier; -import software.bernie.geckolib3.file.AnimationFile; -import software.bernie.geckolib3.geo.render.built.GeoModel; - -public class CosmeticsManager { - private static List providers = new ArrayList<>(); - private static Map> cosmeticCache = new HashMap<>(); - private static Map capeCache = new HashMap<>(); - private static Set activePlayers = new HashSet<>(); - private static Map cachedModels = new ConcurrentHashMap<>(); - private static Map cachedAnimations - = new ConcurrentHashMap<>(); - - private static void refresh() { - boolean doRefresh = false; - for (ICosmeticProvider provider : providers) { - doRefresh = doRefresh || provider.requestsRefresh(); - } - if (!doRefresh) - return; - cosmeticCache.clear(); - for (UUID uuid : activePlayers) { - loadPlayer(uuid); - } - } - - private static void loadPlayer(UUID player) { - if (cosmeticCache.containsKey(player)) - return; - cosmeticCache.put(player, new ArrayList<>()); - List cosmetics = cosmeticCache.get(player); - for (ICosmeticProvider provider : providers) { - provider.addCosmetics(player, (cosmetic) -> cosmetics.add(cosmetic)); - if (!capeCache.containsKey(player)) { - Identifier cape = provider.getCape(player); - if (cape != null) - capeCache.put(player, cape); - } - } - } - - public static void registerProvider(ICosmeticProvider provider) { - providers.add(provider); - } - - protected static List getCosmeticsForPlayer(UUID uuid) { - if (!activePlayers.contains(uuid)) { - activePlayers.add(uuid); - loadPlayer(uuid); - } - refresh(); - return cosmeticCache.get(uuid); - } - - public static Identifier getCape(UUID player) { - if (!activePlayers.contains(player)) { - activePlayers.add(player); - loadPlayer(player); - } - refresh(); - return capeCache.get(player); - } - - protected static GeoModel getModel(Identifier id) { - return cachedModels.get(id); - } - - protected static AnimationFile getAnimations(Identifier id) { - return cachedAnimations.get(id); - } - - public static void loadModel(Identifier id, GeoModel model) { - cachedModels.put(id, model); - } - - public static void loadAnimations(Identifier id, AnimationFile animations) { - cachedAnimations.put(id, animations); - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/ICosmetic.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/ICosmetic.java deleted file mode 100644 index f650410..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/ICosmetic.java +++ /dev/null @@ -1,56 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics; - -import net.minecraft.util.Identifier; - -public interface ICosmetic { - Identifier getAnimationFileLocation(); - - Identifier getModelLocation(); - - Identifier getTextureLocation(); - - default String getHead() { - return null; //head - } - - default String getBody() { - return null; //body - } - - default String getLeftArm() { - return null; //arm_left - } - - default String getRightArm() { - return null; //arm_right - } - - default String getLeftLeg() { - return null; //leg_left - } - - default String getRightLeg() { - return null; //leg_right - } - - default String getIdleAnimationName() { - return null; - } - - default boolean readyToRender() { - return true; - } - - Identifier getID(); - - default int getTotalFrames() { - return 1; - } - - /** - * Returns how many ticks a frame of the animation should take. - */ - default int getFrameTime() { - return 1; - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/ICosmeticProvider.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/ICosmeticProvider.java deleted file mode 100644 index 8803474..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/ICosmeticProvider.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics; - -import java.util.UUID; -import java.util.function.Consumer; - -import net.minecraft.util.Identifier; - -public interface ICosmeticProvider { - boolean requestsRefresh(); - - void addCosmetics(UUID player, Consumer cosmeticAdder); - - default Identifier getCape(UUID player) { - return null; - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/RemoteCosmetic.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/RemoteCosmetic.java deleted file mode 100644 index 7d7313b..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/RemoteCosmetic.java +++ /dev/null @@ -1,123 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics.remote; - -import net.anvilcraft.anvillib.cosmetics.CosmeticsManager; -import net.anvilcraft.anvillib.cosmetics.ICosmetic; -import net.anvilcraft.anvillib.cosmetics.remote.model.AnimationData; -import net.anvilcraft.anvillib.cosmetics.remote.model.TextureData; -import net.anvilcraft.anvillib.cosmetics.CosmeticParts; -import net.minecraft.util.Identifier; -import software.bernie.geckolib3.file.AnimationFile; -import software.bernie.geckolib3.geo.render.built.GeoModel; - -public class RemoteCosmetic implements ICosmetic { - private Identifier id; - private boolean loadedModel = false; - private boolean loadedTexture = false; - private boolean loadedAnimations = false; - private Identifier modelLocation; - private Identifier textureLocation; - private Identifier animationsLocation; - private CosmeticParts parts = new CosmeticParts(); - private String idleAnimation = null; - private int frameTime = 1; - private int frameCount = 1; - - public RemoteCosmetic(String id) { - this.id = new Identifier("anvillib", id); - this.modelLocation = new Identifier("anvillib", "models/remote/" + id); - this.textureLocation = new Identifier("anvillib", "textures/remote/" + id); - this.animationsLocation = new Identifier("anvillib", "animations/remote/" + id); - } - - @Override - public Identifier getAnimationFileLocation() { - return this.animationsLocation; - } - - @Override - public Identifier getModelLocation() { - return this.modelLocation; - } - - @Override - public Identifier getTextureLocation() { - return this.textureLocation; - } - - @Override - public Identifier getID() { - return this.id; - } - - @Override - public boolean readyToRender() { - return this.loadedModel && this.loadedTexture && this.loadedAnimations; - } - - public void loadModel(GeoModel model) { - CosmeticsManager.loadModel(this.modelLocation, model); - this.parts = new CosmeticParts(model); - this.loadedModel = true; - } - - public void loadTexture(TextureData data) { - this.frameCount = data.frameCount; - this.frameTime = data.frameTime; - this.loadedTexture = true; - } - - public void loadAnimations(AnimationFile file, AnimationData data) { - if (data == null || file == null) { - this.animationsLocation = null; - } else { - CosmeticsManager.loadAnimations(this.animationsLocation, file); - this.idleAnimation = data.idleAnimation; - } - this.loadedAnimations = true; - } - - @Override - public String getBody() { - return this.parts.body ? this.parts.bodyName : null; - } - - @Override - public String getHead() { - return this.parts.head ? this.parts.headName : null; - } - - @Override - public String getLeftArm() { - return this.parts.leftArm ? this.parts.leftArmName : null; - } - - @Override - public String getLeftLeg() { - return this.parts.leftLeg ? this.parts.leftLegName : null; - } - - @Override - public String getRightArm() { - return this.parts.rightArm ? this.parts.rightArmName : null; - } - - @Override - public String getRightLeg() { - return this.parts.rightLeg ? this.parts.rightLegName : null; - } - - @Override - public String getIdleAnimationName() { - return this.idleAnimation; - } - - @Override - public int getTotalFrames() { - return this.frameCount; - } - - @Override - public int getFrameTime() { - return this.frameTime; - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/RemoteCosmeticProvider.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/RemoteCosmeticProvider.java deleted file mode 100644 index f32c4a2..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/RemoteCosmeticProvider.java +++ /dev/null @@ -1,121 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics.remote; - -import java.io.File; -import java.net.MalformedURLException; -import java.net.URI; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Consumer; - -import net.anvilcraft.anvillib.AnvilLib; -import net.anvilcraft.anvillib.cosmetics.ICosmetic; -import net.anvilcraft.anvillib.cosmetics.ICosmeticProvider; -import net.anvilcraft.anvillib.cosmetics.remote.model.CosmeticData; -import net.anvilcraft.anvillib.cosmetics.remote.thread.CapeLoaderThread; -import net.anvilcraft.anvillib.cosmetics.remote.thread.CosmeticAssetsLoaderThread; -import net.anvilcraft.anvillib.cosmetics.remote.thread.CosmeticLoaderThread; -import net.anvilcraft.anvillib.cosmetics.remote.thread.PlayerCosmeticLoaderThread; -import net.minecraft.util.Identifier; -import net.minecraft.util.Util; - -public class RemoteCosmeticProvider implements ICosmeticProvider { - public static RemoteCosmeticProvider INSTANCE = null; - - public final Map cosmetics = new ConcurrentHashMap<>(); - public final Map> playerCosmetics = new ConcurrentHashMap<>(); - public final Map capes = new ConcurrentHashMap<>(); - public final Map playerCapes = new ConcurrentHashMap<>(); - private final Map knownCosmetics = new ConcurrentHashMap<>(); - private final Map knownCapes = new ConcurrentHashMap<>(); - private boolean dirty = false; - - public final URI playerBase; - public final URI cosmeticBase; - public final URI capeBase; - private final File cacheDir; - - public RemoteCosmeticProvider( - URI playerBase, URI cosmeticBase, URI capeBase, File cacheDir - ) { - this.playerBase = playerBase; - this.cosmeticBase = cosmeticBase; - this.capeBase = capeBase; - this.cacheDir = cacheDir; - } - - @Override - public boolean requestsRefresh() { - return this.dirty; - } - - @Override - public void addCosmetics(UUID player, Consumer cosmeticAdder) { - this.dirty = false; - if (playerCosmetics.containsKey(player)) { - for (String id : playerCosmetics.get(player)) { - if (!this.cosmetics.containsKey(id) - || !this.cosmetics.get(id).readyToRender()) - continue; - cosmeticAdder.accept(this.cosmetics.get(id)); - } - } else { - try { - this.loadNewPlayer(player); - } catch (MalformedURLException e) { - AnvilLib.LOGGER.error(e); - } - } - } - - @Override - public Identifier getCape(UUID player) { - if (!this.playerCapes.containsKey(player)) - return null; - String cape = this.playerCapes.get(player); - return this.capes.getOrDefault(cape, null); - } - - public void markDirty() { - synchronized (this) { - this.dirty = true; - } - } - - private void loadNewPlayer(UUID id) throws MalformedURLException { - this.playerCosmetics.putIfAbsent(id, new HashSet<>()); - URI url = playerBase.resolve(id.toString()); - Util.getMainWorkerExecutor().execute(new PlayerCosmeticLoaderThread(url, this)); - } - - public void loadCosmetic(String id) throws MalformedURLException { - if (this.cosmetics.containsKey(id) || this.knownCosmetics.containsKey(id)) - return; - this.knownCosmetics.put(id, true); - URI url = cosmeticBase.resolve(id); - Util.getMainWorkerExecutor().execute(new CosmeticLoaderThread(url, this)); - } - - public void loadAssets(CosmeticData data, RemoteCosmetic cosmetic) { - Util.getMainWorkerExecutor().execute( - new CosmeticAssetsLoaderThread(cosmetic, data, this.cacheDir, this) - ); - } - - public void loadCape(String id) throws MalformedURLException { - if (this.capes.containsKey(id) || this.knownCapes.containsKey(id)) - return; - this.knownCapes.put(id, true); - URI url = capeBase.resolve(id); - Util.getMainWorkerExecutor().execute( - new CapeLoaderThread(id, url, this.cacheDir, this) - ); - } - - public void failCosmeticLoading(String id) { - AnvilLib.LOGGER.error("Cosmetic loading failed: {}", id); - this.cosmetics.remove(id); - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/AnimationData.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/AnimationData.java deleted file mode 100644 index 474ca03..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/AnimationData.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics.remote.model; - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class AnimationData { - @Expose - public String url; - @Expose - @SerializedName("idle_animation") - public String idleAnimation; -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/CapeData.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/CapeData.java deleted file mode 100644 index d52bc0f..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/CapeData.java +++ /dev/null @@ -1,10 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics.remote.model; - -import com.google.gson.annotations.Expose; - -public class CapeData { - @Expose - public String id; - @Expose - public String url; -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/CosmeticData.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/CosmeticData.java deleted file mode 100644 index 252997e..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/CosmeticData.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics.remote.model; - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class CosmeticData { - @Expose - public String id; - @Expose - @SerializedName("model_url") - public String modelUrl; - @Expose - @SerializedName("animation_data") - public AnimationData animationData; - @Expose - @SerializedName("texture_data") - public TextureData textureData; -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/PlayerData.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/PlayerData.java deleted file mode 100644 index a263651..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/PlayerData.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics.remote.model; - -import java.util.List; -import java.util.UUID; - -import com.google.gson.annotations.Expose; - -public class PlayerData { - @Expose - public UUID uuid; - @Expose - public List cosmetics; - @Expose - public String cape; -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/TextureData.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/TextureData.java deleted file mode 100644 index 845cba1..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/model/TextureData.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics.remote.model; - -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - -public class TextureData { - @Expose - public String url; - - @Expose - @SerializedName("total_frames") - public int frameCount; - - @Expose - @SerializedName("frame_time") - public int frameTime; -} - diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/AbstractFileDownloaderThread.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/AbstractFileDownloaderThread.java deleted file mode 100644 index bb1dcf2..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/AbstractFileDownloaderThread.java +++ /dev/null @@ -1,84 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics.remote.thread; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonIOException; -import com.google.gson.JsonSyntaxException; - -import net.anvilcraft.anvillib.AnvilLib; - -public abstract class AbstractFileDownloaderThread implements Runnable { - protected Gson gson = new GsonBuilder().create(); - protected HttpClient client = HttpClient.newBuilder().build(); - protected final String version; - - public AbstractFileDownloaderThread(String version) { - this.version = version; - } - - protected HttpRequest buildRequest(URI url) { - return HttpRequest.newBuilder() - .GET() - .uri(url) - .header("User-Agent", System.getProperty("java.version")) - .header("X-AnvilLib-Version", this.version) - .header("X-Minecraft-Version", "1.18.2") - .build(); - } - - public InputStream getStreamForURL(URI url) { - HttpRequest req = this.buildRequest(url); - InputStream is = null; - try { - HttpResponse res - = client.send(req, HttpResponse.BodyHandlers.ofInputStream()); - if (res.statusCode() == 200) { - is = res.body(); - } else if (res.statusCode() != 404) { - AnvilLib.LOGGER.error("Unexpected status code: {}", res.statusCode()); - } - } catch (IOException | InterruptedException e) { - AnvilLib.LOGGER.error(e); - } - return is; - } - - public String getStringForURL(URI url) { - HttpRequest req = this.buildRequest(url); - String is = null; - try { - HttpResponse res - = client.send(req, HttpResponse.BodyHandlers.ofString()); - if (res.statusCode() == 200) { - is = res.body(); - } else if (res.statusCode() != 404) { - AnvilLib.LOGGER.error("Unexpected status code: {}", res.statusCode()); - } - } catch (IOException | InterruptedException e) { - AnvilLib.LOGGER.error(e); - } - return is; - } - - public T loadJson(URI url, Class type) throws IOException { - InputStream stream = this.getStreamForURL(url); - if (stream == null) - return null; - try { - T json = this.gson.fromJson(new InputStreamReader(stream), type); - return json; - } catch (JsonSyntaxException | JsonIOException e) { - throw new IOException(e); - } finally { - stream.close(); - } - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/CapeLoaderThread.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/CapeLoaderThread.java deleted file mode 100644 index 6da186e..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/CapeLoaderThread.java +++ /dev/null @@ -1,65 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics.remote.thread; - -import java.io.File; -import java.io.IOException; -import java.net.URI; - -import com.google.common.hash.Hashing; - -import net.anvilcraft.anvillib.AnvilLib; -import net.anvilcraft.anvillib.cosmetics.remote.RemoteCosmeticProvider; -import net.anvilcraft.anvillib.cosmetics.remote.model.CapeData; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.texture.AbstractTexture; -import net.minecraft.client.texture.MissingSprite; -import net.minecraft.client.texture.PlayerSkinTexture; -import net.minecraft.client.texture.TextureManager; -import net.minecraft.util.Identifier; - -public class CapeLoaderThread extends AbstractFileDownloaderThread { - private String id; - private File cacheDir; - private URI url; - private RemoteCosmeticProvider provider; - private TextureManager textureManager - = MinecraftClient.getInstance().getTextureManager(); - - public CapeLoaderThread( - String id, URI url, File cacheDir, RemoteCosmeticProvider provider - ) { - super("0.2.0"); - this.id = id; - this.url = url; - this.cacheDir = cacheDir; - this.provider = provider; - } - - @SuppressWarnings("deprecation") - @Override - public void run() { - CapeData data = null; - try { - data = this.loadJson(url, CapeData.class); - } catch (IOException e) { - AnvilLib.LOGGER.error("Can't load cape: {}", id, e); - return; - } - Identifier location = new Identifier("anvillib", "textures/cape/" + data.id); - String hash = Hashing.sha1().hashUnencodedChars(data.id).toString(); - AbstractTexture texture = this.textureManager.getOrDefault( - location, MissingSprite.getMissingSpriteTexture() - ); - if (texture == MissingSprite.getMissingSpriteTexture()) { - File file = new File( - this.cacheDir, hash.length() > 2 ? hash.substring(0, 2) : "xx" - ); - File file2 = new File(file, hash); - texture = new PlayerSkinTexture( - file2, data.url, new Identifier("textures/block/dirt.png"), false, null - ); - this.textureManager.registerTexture(location, texture); - } - this.provider.capes.put(data.id, location); - this.provider.markDirty(); - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/CosmeticAssetsLoaderThread.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/CosmeticAssetsLoaderThread.java deleted file mode 100644 index 572edb6..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/CosmeticAssetsLoaderThread.java +++ /dev/null @@ -1,156 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics.remote.thread; - -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Map; -import java.util.Objects; - -import com.google.common.hash.Hashing; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; - -import net.anvilcraft.anvillib.AnvilLib; -import net.anvilcraft.anvillib.cosmetics.remote.RemoteCosmetic; -import net.anvilcraft.anvillib.cosmetics.remote.RemoteCosmeticProvider; -import net.anvilcraft.anvillib.cosmetics.remote.model.AnimationData; -import net.anvilcraft.anvillib.cosmetics.remote.model.CosmeticData; -import net.anvilcraft.anvillib.cosmetics.remote.model.TextureData; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.texture.AbstractTexture; -import net.minecraft.client.texture.MissingSprite; -import net.minecraft.client.texture.PlayerSkinTexture; -import net.minecraft.client.texture.TextureManager; -import net.minecraft.util.Identifier; -import software.bernie.geckolib3.core.builder.Animation; -import software.bernie.geckolib3.core.molang.MolangParser; -import software.bernie.geckolib3.file.AnimationFile; -import software.bernie.geckolib3.geo.exception.GeckoLibException; -import software.bernie.geckolib3.geo.raw.pojo.Converter; -import software.bernie.geckolib3.geo.raw.pojo.FormatVersion; -import software.bernie.geckolib3.geo.raw.pojo.RawGeoModel; -import software.bernie.geckolib3.geo.raw.tree.RawGeometryTree; -import software.bernie.geckolib3.geo.render.GeoBuilder; -import software.bernie.geckolib3.geo.render.built.GeoModel; -import software.bernie.geckolib3.util.json.JsonAnimationUtils; - -public class CosmeticAssetsLoaderThread extends AbstractFileDownloaderThread { - private RemoteCosmetic cosmetic; - private CosmeticData data; - private MolangParser parser = new MolangParser(); - private TextureManager textureManager - = MinecraftClient.getInstance().getTextureManager(); - private File cacheDir; - private RemoteCosmeticProvider provider; - - public CosmeticAssetsLoaderThread( - RemoteCosmetic cosmetic, - CosmeticData data, - File cacheDir, - RemoteCosmeticProvider provider - ) { - super("0.2.0"); - this.cosmetic = cosmetic; - this.data = data; - this.cacheDir = cacheDir; - this.provider = provider; - } - - @Override - public void run() { - this.loadModel(this.data.modelUrl); - this.loadTexture(this.data.textureData); - this.loadAnimations(this.data.animationData); - this.provider.markDirty(); - } - - private void loadAnimations(AnimationData anim) { - if (anim == null) { - this.cosmetic.loadAnimations(null, anim); - return; - } - AnimationFile animations = null; - try { - URI url = new URI(this.data.animationData.url); - JsonObject data = this.loadJson(url, JsonObject.class); - animations = this.buildAnimationFile(data); - } catch (IOException | URISyntaxException | NullPointerException e) { - AnvilLib.LOGGER.error( - "Could not load animation: {}", this.data.animationData.url, e - ); - } - this.cosmetic.loadAnimations(animations, anim); - } - - @SuppressWarnings("deprecation") - private void loadTexture(TextureData data) { - String hash = Hashing.sha1().hashUnencodedChars(this.data.id).toString(); - AbstractTexture texture = this.textureManager.getOrDefault( - this.cosmetic.getTextureLocation(), MissingSprite.getMissingSpriteTexture() - ); - if (texture == MissingSprite.getMissingSpriteTexture()) { - File file = new File( - this.cacheDir, hash.length() > 2 ? hash.substring(0, 2) : "xx" - ); - File file2 = new File(file, hash); - texture = new PlayerSkinTexture( - file2, data.url, new Identifier("textures/block/dirt.png"), false, null - ); - this.textureManager.registerTexture( - this.cosmetic.getTextureLocation(), texture - ); - } - this.cosmetic.loadTexture(data); - } - - private void loadModel(String url) { - try { - URI uri = new URI(url); - String data = Objects.requireNonNull(this.getStringForURL(uri)); - GeoModel model = this.buildModel(data); - this.cosmetic.loadModel(model); - } catch ( - NullPointerException | URISyntaxException | IOException | GeckoLibException e - ) { - AnvilLib.LOGGER.error("Can't load remote model: {}", url, e); - this.handleFailure(); - } - } - - private void handleFailure() { - this.provider.failCosmeticLoading(this.data.id); - } - - private AnimationFile buildAnimationFile(JsonObject json) { - AnimationFile animationFile = new AnimationFile(); - for (Map.Entry entry : - JsonAnimationUtils.getAnimations(json)) { - String animationName = entry.getKey(); - Animation animation; - try { - animation = JsonAnimationUtils.deserializeJsonToAnimation( - JsonAnimationUtils.getAnimation(json, animationName), parser - ); - animationFile.putAnimation(animationName, animation); - } catch (Exception e) { - AnvilLib.LOGGER.error("Could not load animation: {}", animationName, e); - throw new RuntimeException(e); - } - } - return animationFile; - } - - private GeoModel buildModel(String json) throws IOException { - Identifier location = this.cosmetic.getModelLocation(); - RawGeoModel rawModel = Converter.fromJsonString(json); - if (rawModel.getFormatVersion() != FormatVersion.VERSION_1_12_0) { - throw new GeckoLibException( - location, "Wrong geometry json version, expected 1.12.0" - ); - } - RawGeometryTree rawGeometryTree = RawGeometryTree.parseHierarchy(rawModel); - return GeoBuilder.getGeoBuilder(location.getNamespace()) - .constructGeoModel(rawGeometryTree); - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/CosmeticLoaderThread.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/CosmeticLoaderThread.java deleted file mode 100644 index 8c4ee72..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/CosmeticLoaderThread.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics.remote.thread; - -import java.io.IOException; -import java.net.URI; - -import net.anvilcraft.anvillib.AnvilLib; -import net.anvilcraft.anvillib.cosmetics.remote.RemoteCosmetic; -import net.anvilcraft.anvillib.cosmetics.remote.RemoteCosmeticProvider; -import net.anvilcraft.anvillib.cosmetics.remote.model.CosmeticData; - -public class CosmeticLoaderThread extends AbstractFileDownloaderThread { - private URI url; - private RemoteCosmeticProvider provider; - - public CosmeticLoaderThread(URI url, RemoteCosmeticProvider provider) { - super("0.2.0"); - this.url = url; - this.provider = provider; - } - - @Override - public void run() { - try { - CosmeticData data = this.loadJson(url, CosmeticData.class); - if (data == null) - throw new IOException("Cosmetic not found"); - RemoteCosmetic cosmetic = new RemoteCosmetic(data.id); - this.provider.cosmetics.put(data.id, cosmetic); - this.provider.loadAssets(data, cosmetic); - } catch (IOException e) { - AnvilLib.LOGGER.error("Can't load cosmetic", e); - } - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/PlayerCosmeticLoaderThread.java b/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/PlayerCosmeticLoaderThread.java deleted file mode 100644 index c734fb6..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/cosmetics/remote/thread/PlayerCosmeticLoaderThread.java +++ /dev/null @@ -1,39 +0,0 @@ -package net.anvilcraft.anvillib.cosmetics.remote.thread; - -import java.io.IOException; -import java.net.URI; - -import net.anvilcraft.anvillib.cosmetics.remote.RemoteCosmeticProvider; -import net.anvilcraft.anvillib.cosmetics.remote.model.PlayerData; - -public class PlayerCosmeticLoaderThread extends AbstractFileDownloaderThread { - private URI config; - private RemoteCosmeticProvider provider; - - public PlayerCosmeticLoaderThread(URI config, RemoteCosmeticProvider provider) { - super("0.2.0"); - this.config = config; - this.provider = provider; - } - - @Override - public void run() { - try { - PlayerData player = this.loadJson(config, PlayerData.class); - if (player == null) - return; - for (String id : player.cosmetics) { - this.provider.loadCosmetic(id); - this.provider.playerCosmetics.get(player.uuid).add(id); - } - if (player.cape != null) { - this.provider.loadCape(player.cape); - this.provider.playerCapes.put(player.uuid, player.cape); - } - - this.provider.markDirty(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/event/AddEntityRenderLayersEvent.java b/common/src/main/java/net/anvilcraft/anvillib/event/AddEntityRenderLayersEvent.java deleted file mode 100644 index 6b3232d..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/event/AddEntityRenderLayersEvent.java +++ /dev/null @@ -1,9 +0,0 @@ -package net.anvilcraft.anvillib.event; - -import java.util.Map; - -import net.minecraft.client.render.entity.EntityRenderer; -import net.minecraft.entity.player.PlayerEntity; - -public record -AddEntityRenderLayersEvent(Map> skinMap) {} diff --git a/common/src/main/java/net/anvilcraft/anvillib/event/Bus.java b/common/src/main/java/net/anvilcraft/anvillib/event/Bus.java deleted file mode 100644 index 0cafab6..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/event/Bus.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.anvilcraft.anvillib.event; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; - -public class Bus { - public static final Bus MAIN = new Bus(); - - private final Map, List>> handlerMap = new HashMap<>(); - - public void register(IEventBusRegisterable obj) { - obj.registerEventHandlers(this); - } - - public void register(Class clazz, Consumer handler) { - handlerMap.computeIfAbsent(clazz, alec -> new ArrayList<>()).add(handler); - } - - @SuppressWarnings("unchecked") - public void fire(T ev) { - var clazz = ev.getClass(); - if (handlerMap.containsKey(clazz)) { - for (Consumer handler : handlerMap.get(clazz)) { - ((Consumer) handler).accept(ev); - } - } - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/event/IEventBusRegisterable.java b/common/src/main/java/net/anvilcraft/anvillib/event/IEventBusRegisterable.java deleted file mode 100644 index 89d25fc..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/event/IEventBusRegisterable.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.anvilcraft.anvillib.event; - -/** - * IEventBusRegisterable describes a class which contains one or more event handlers to be - * registered on the anvillib event bus. - */ -public interface IEventBusRegisterable { - /** - * Register this object's event handlers on the given bus. - */ - public void registerEventHandlers(Bus bus); -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/mixin/accessor/AnimatedGeoModelAccessor.java b/common/src/main/java/net/anvilcraft/anvillib/mixin/accessor/AnimatedGeoModelAccessor.java deleted file mode 100644 index 61ae72c..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/mixin/accessor/AnimatedGeoModelAccessor.java +++ /dev/null @@ -1,20 +0,0 @@ -package net.anvilcraft.anvillib.mixin.accessor; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import software.bernie.geckolib3.core.processor.AnimationProcessor; -import software.bernie.geckolib3.geo.render.built.GeoModel; -import software.bernie.geckolib3.model.AnimatedGeoModel; - -@Mixin(AnimatedGeoModel.class) -public interface AnimatedGeoModelAccessor { - @Accessor(remap = false) - AnimationProcessor getAnimationProcessor(); - - @Accessor(remap = false) - GeoModel getCurrentModel(); - - @Accessor(remap = false) - void setCurrentModel(GeoModel model); -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/mixin/client/AbstractClientPlayerEntityMixin.java b/common/src/main/java/net/anvilcraft/anvillib/mixin/client/AbstractClientPlayerEntityMixin.java deleted file mode 100644 index e24565a..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/mixin/client/AbstractClientPlayerEntityMixin.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.anvilcraft.anvillib.mixin.client; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -import com.mojang.authlib.GameProfile; - -import net.anvilcraft.anvillib.cosmetics.CosmeticsManager; -import net.minecraft.client.network.AbstractClientPlayerEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -@Mixin(AbstractClientPlayerEntity.class) -public abstract class AbstractClientPlayerEntityMixin extends PlayerEntity { - private static Identifier ELYTRA = new Identifier("textures/entity/elytra.png"); - - public AbstractClientPlayerEntityMixin( - World world, BlockPos pos, float yaw, GameProfile profile - ) { - super(world, pos, yaw, profile); - } - - /** - * @reason Custom capes & no Mojank capes - * @author tilera - */ - @Overwrite - public Identifier getCapeTexture() { - return CosmeticsManager.getCape(this.uuid); - } - - /** - * @reason Custom capes & no Mojank capes - * @author tilera - */ - @Overwrite - public Identifier getElytraTexture() { - return ELYTRA; - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/mixin/client/MinecraftClientMixin.java b/common/src/main/java/net/anvilcraft/anvillib/mixin/client/MinecraftClientMixin.java deleted file mode 100644 index d4374e3..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/mixin/client/MinecraftClientMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.anvilcraft.anvillib.mixin.client; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.At; - -import net.anvilcraft.anvillib.cosmetics.ClientEventHandler; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.RunArgs; - -@Mixin(MinecraftClient.class) -public class MinecraftClientMixin { - @Inject(at = @At("RETURN"), method = "") - public void init(RunArgs args, CallbackInfo info) { - ClientEventHandler.registerRemoteCosmetics(args.directories.assetDir); - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/mixin/common/RecipeManagerMixin.java b/common/src/main/java/net/anvilcraft/anvillib/mixin/common/RecipeManagerMixin.java deleted file mode 100644 index 258cb60..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/mixin/common/RecipeManagerMixin.java +++ /dev/null @@ -1,48 +0,0 @@ -package net.anvilcraft.anvillib.mixin.common; - -import java.util.HashMap; -import java.util.Map; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import com.google.gson.JsonElement; - -import net.anvilcraft.anvillib.AnvilLib; -import net.anvilcraft.anvillib.event.Bus; -import net.anvilcraft.anvillib.recipe.RecipesEvent; -import net.minecraft.recipe.Recipe; -import net.minecraft.recipe.RecipeManager; -import net.minecraft.recipe.RecipeType; -import net.minecraft.resource.ResourceManager; -import net.minecraft.util.Identifier; -import net.minecraft.util.profiler.Profiler; - -@Mixin(RecipeManager.class) -public class RecipeManagerMixin { - @Shadow - private Map, Map>> recipes; - - @Shadow - private Map> recipesById; - - @Inject(method = "apply", at = @At("RETURN")) - private void afterLoad( - Map alec1, - ResourceManager alec2, - Profiler alec3, - CallbackInfo ci - ) { - AnvilLib.LOGGER.info("Firing Recipe Event"); - Map, Map>> recipes = new HashMap<>(); - this.recipes.forEach((k, v) -> recipes.put(k, new HashMap<>(v))); - - var ev = new RecipesEvent(recipes, new HashMap<>(this.recipesById)); - Bus.MAIN.fire(ev); - this.recipes = ev.recipes; - this.recipesById = ev.recipesById; - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/mixin/common/StructurePoolBasedGeneratorMixin.java b/common/src/main/java/net/anvilcraft/anvillib/mixin/common/StructurePoolBasedGeneratorMixin.java deleted file mode 100644 index 3e0dc69..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/mixin/common/StructurePoolBasedGeneratorMixin.java +++ /dev/null @@ -1,32 +0,0 @@ -package net.anvilcraft.anvillib.mixin.common; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyVariable; - -import net.anvilcraft.anvillib.worldgen.AdvancedStructurePoolFeatureConfig; -import net.minecraft.structure.PoolStructurePiece; -import net.minecraft.structure.pool.StructurePoolBasedGenerator; -import net.minecraft.util.math.Box; -import net.minecraft.world.gen.feature.StructurePoolFeatureConfig; - -@Mixin(StructurePoolBasedGenerator.class) -public class StructurePoolBasedGeneratorMixin { - // this is a lambda - @ModifyVariable(method = "method_39824", at = @At(value = "STORE", ordinal = 0)) - private static Box adjustAdvBoundingBox( - Box box, PoolStructurePiece alec, StructurePoolFeatureConfig conf - ) { - if (conf instanceof AdvancedStructurePoolFeatureConfig aconf) { - return new Box( - box.minX + 80 - aconf.maxDistanceFromCenter, - box.minY + 80 - aconf.maxDistanceFromCenter, - box.minZ + 80 - aconf.maxDistanceFromCenter, - box.maxX - 80 + aconf.maxDistanceFromCenter, - box.maxY - 80 + aconf.maxDistanceFromCenter, - box.maxZ - 80 + aconf.maxDistanceFromCenter - ); - } - return box; - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/mixinutils/BeardifierLocals.java b/common/src/main/java/net/anvilcraft/anvillib/mixinutils/BeardifierLocals.java deleted file mode 100644 index 25be623..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/mixinutils/BeardifierLocals.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.anvilcraft.anvillib.mixinutils; - -import net.minecraft.structure.StructurePiece; -import net.minecraft.util.math.BlockBox; - -public record BeardifierLocals( - int x, - int y, - int z, - StructurePiece structurePiece, - BlockBox boundingBox, - int l, - int m -) {} diff --git a/common/src/main/java/net/anvilcraft/anvillib/recipe/AbstractIngredientCondition.java b/common/src/main/java/net/anvilcraft/anvillib/recipe/AbstractIngredientCondition.java deleted file mode 100644 index c17d74e..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/recipe/AbstractIngredientCondition.java +++ /dev/null @@ -1,23 +0,0 @@ -package net.anvilcraft.anvillib.recipe; - -import java.util.Arrays; -import java.util.function.Predicate; - -import net.anvilcraft.anvillib.Util; -import net.minecraft.recipe.Ingredient; -import net.minecraft.util.Identifier; - -public abstract class AbstractIngredientCondition implements Predicate { - public static AbstractIngredientCondition of(String s) { - return s.charAt(0) == '#' - ? new TagIngredientCondition(new Identifier(s.substring(1))) - : new StackIngredientCondition(Util.stackFromRegistry(new Identifier(s))); - } - - @Override - public boolean test(Ingredient i) { - return Arrays.stream(i.entries).anyMatch(this::entryMatches); - } - - public abstract boolean entryMatches(Ingredient.Entry e); -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/recipe/IRecipeMapper.java b/common/src/main/java/net/anvilcraft/anvillib/recipe/IRecipeMapper.java deleted file mode 100644 index c814161..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/recipe/IRecipeMapper.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.anvilcraft.anvillib.recipe; - -import java.util.function.Function; - -import net.minecraft.recipe.Recipe; - -/** - * IRecipeMapper describes a class that knows how to conditionally replace recipes. - */ -public interface IRecipeMapper extends Function, Recipe> { - public boolean shouldMap(Recipe recipe); -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/recipe/IngredientsContainPredicate.java b/common/src/main/java/net/anvilcraft/anvillib/recipe/IngredientsContainPredicate.java deleted file mode 100644 index 97ba77c..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/recipe/IngredientsContainPredicate.java +++ /dev/null @@ -1,19 +0,0 @@ -package net.anvilcraft.anvillib.recipe; - -import java.util.function.Predicate; - -import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.Recipe; - -public class IngredientsContainPredicate implements Predicate> { - public Predicate pred; - - public IngredientsContainPredicate(Predicate pred) { - this.pred = pred; - } - - @Override - public boolean test(Recipe r) { - return r.getIngredients().stream().anyMatch(this.pred); - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/recipe/InputReplaceRecipeMapper.java b/common/src/main/java/net/anvilcraft/anvillib/recipe/InputReplaceRecipeMapper.java deleted file mode 100644 index 561cf81..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/recipe/InputReplaceRecipeMapper.java +++ /dev/null @@ -1,54 +0,0 @@ -package net.anvilcraft.anvillib.recipe; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.Predicate; - -import net.anvilcraft.anvillib.Util; -import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.Recipe; - -public class InputReplaceRecipeMapper implements IRecipeMapper { - public Map, Ingredient> replacements = new HashMap<>(); - - public InputReplaceRecipeMapper replace(Predicate p, Ingredient i) { - this.replacements.put(p, i); - return this; - } - - public InputReplaceRecipeMapper replace(String p, Ingredient i) { - return this.replace(AbstractIngredientCondition.of(p), i); - } - - public InputReplaceRecipeMapper replace(String p, String i) { - return this.replace(p, Util.ingredientFromString(i)); - } - - public InputReplaceRecipeMapper replace(Predicate p, String i) { - return this.replace(p, Util.ingredientFromString(i)); - } - - @Override - public boolean shouldMap(Recipe recipe) { - var ingredients = recipe.getIngredients(); - if (ingredients == null) - return false; - - for (var k : this.replacements.keySet()) - if (ingredients.stream().anyMatch(k)) - return true; - return false; - } - - @Override - public Recipe apply(Recipe recipe) { - var ingredients = recipe.getIngredients(); - for (int i = 0; i < ingredients.size(); i++) { - var ing = ingredients.get(i); - for (var entry : this.replacements.entrySet()) - if (entry.getKey().test(ing)) - ingredients.set(i, entry.getValue()); - } - return recipe; - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/recipe/RecipeContainsPredicate.java b/common/src/main/java/net/anvilcraft/anvillib/recipe/RecipeContainsPredicate.java deleted file mode 100644 index 0e2a19a..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/recipe/RecipeContainsPredicate.java +++ /dev/null @@ -1,22 +0,0 @@ -package net.anvilcraft.anvillib.recipe; - -import java.util.function.Predicate; - -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.Recipe; - -public class RecipeContainsPredicate implements Predicate> { - public ItemStack item; - - public RecipeContainsPredicate(ItemStack item) { - this.item = item; - } - - @Override - public boolean test(Recipe r) { - return r.getIngredients() == null - ? false - : r.getIngredients().stream().anyMatch(new StackIngredientCondition(this.item) - ) || r.getOutput().isItemEqual(this.item); - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/recipe/RecipesEvent.java b/common/src/main/java/net/anvilcraft/anvillib/recipe/RecipesEvent.java deleted file mode 100644 index 05f68c2..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/recipe/RecipesEvent.java +++ /dev/null @@ -1,79 +0,0 @@ -package net.anvilcraft.anvillib.recipe; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; -import java.util.function.Predicate; - -import net.minecraft.recipe.Recipe; -import net.minecraft.recipe.RecipeType; -import net.minecraft.util.Identifier; - -public class RecipesEvent { - public Map, Map>> recipes; - public Map> recipesById; - - public RecipesEvent( - Map, Map>> recipes, - Map> recipesById - ) { - this.recipes = recipes; - this.recipesById = recipesById; - } - - public void registerRecipe(Recipe recipe) { - if (!this.recipes.containsKey(recipe.getType())) - this.recipes.put(recipe.getType(), new HashMap<>()); - - this.recipes.get(recipe.getType()).put(recipe.getId(), recipe); - this.recipesById.put(recipe.getId(), recipe); - } - - public Optional> removeRecipeID(Identifier id) { - if (this.recipesById.containsKey(id)) { - return Optional.of( - this.recipes.get(this.recipesById.remove(id).getType()).remove(id) - ); - } - - return Optional.empty(); - } - - public void removeRecipesMatching(Predicate> p) { - var iter = this.recipesById.entrySet().iterator(); - while (iter.hasNext()) { - var entry = iter.next(); - if (p.test(entry.getValue())) { - iter.remove(); - this.recipes.get(entry.getValue().getType()).remove(entry.getKey()); - } - } - } - - public void mapRecipes(IRecipeMapper mapper) { - var iter = this.recipesById.entrySet().iterator(); - while (iter.hasNext()) { - var entry = iter.next(); - if (mapper.shouldMap(entry.getValue())) { - var mapped = mapper.apply(entry.getValue()); - if (mapped != entry.getValue()) { - iter.remove(); - this.recipes.get(entry.getValue().getType()).remove(entry.getKey()); - this.registerRecipe(mapped); - } - } - } - } - - public void mapRecipeID(Identifier id, Function, Recipe> func) { - var recipe = this.recipesById.get(id); - if (recipe != null) { - var mapped = func.apply(recipe); - if (recipe != mapped) { - this.removeRecipeID(id); - this.registerRecipe(mapped); - } - } - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/recipe/ShapedRecipeBuilder.java b/common/src/main/java/net/anvilcraft/anvillib/recipe/ShapedRecipeBuilder.java deleted file mode 100644 index ab06fef..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/recipe/ShapedRecipeBuilder.java +++ /dev/null @@ -1,94 +0,0 @@ -package net.anvilcraft.anvillib.recipe; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import net.minecraft.block.Block; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.ShapedRecipe; -import net.minecraft.tag.TagKey; -import net.minecraft.util.Identifier; -import net.minecraft.util.collection.DefaultedList; -import net.minecraft.util.registry.Registry; - -public class ShapedRecipeBuilder { - public Identifier ident; - public String[] pattern; - public Map ingredients = new HashMap<>(); - public ItemStack output; - - public ShapedRecipeBuilder(Identifier ident, ItemStack output) { - this.ident = ident; - this.output = output; - } - - public ShapedRecipeBuilder pattern(String... pat) { - this.pattern = pat; - return this; - } - - public ShapedRecipeBuilder ingredient(char c, Ingredient i) { - this.ingredients.put(c, i); - return this; - } - - public ShapedRecipeBuilder ingredient(char c, ItemStack... is) { - return this.ingredient(c, Ingredient.ofStacks(is)); - } - - public ShapedRecipeBuilder ingredient(char c, Item i) { - return this.ingredient(c, new ItemStack(i)); - } - - public ShapedRecipeBuilder ingredient(char c, Block b) { - return this.ingredient(c, new ItemStack(b)); - } - - public ShapedRecipeBuilder ingredient(char c, String s) { - if (s.charAt(0) == '#') { - return this.tagIngredient(c, new Identifier(s.substring(1))); - } - - var ident = new Identifier(s); - var maybeItem = Registry.ITEM.get(ident); - if (maybeItem == null) { - var maybeBlock = Registry.BLOCK.get(ident); - if (maybeBlock == null) - throw new IllegalArgumentException( - "ID " + s + " not found in item or block registry!" - ); - - return this.ingredient(c, maybeBlock); - } - - return this.ingredient(c, maybeItem); - } - - public ShapedRecipeBuilder tagIngredient(char c, Identifier t) { - return this.ingredient(c, Ingredient.fromTag(TagKey.of(Registry.ITEM_KEY, t))); - } - - public ShapedRecipe build() { - int width = -1; - for (String line : this.pattern) { - if (width != -1 && width != line.length()) - throw new IllegalArgumentException( - "Lines in crafting pattern must be same width!" - ); - width = line.length(); - } - - DefaultedList ingredients = DefaultedList.of(); - Arrays.stream(this.pattern) - .flatMap(s -> s.chars().mapToObj(c -> (char) c)) - .map(k -> this.ingredients.getOrDefault(k, Ingredient.empty())) - .forEach(ingredients::add); - - return new ShapedRecipe( - this.ident, "", width, this.pattern.length, ingredients, this.output - ); - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/recipe/StackIngredientCondition.java b/common/src/main/java/net/anvilcraft/anvillib/recipe/StackIngredientCondition.java deleted file mode 100644 index 856b6de..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/recipe/StackIngredientCondition.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.anvilcraft.anvillib.recipe; - -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.Ingredient.Entry; -import net.minecraft.recipe.Ingredient.StackEntry; - -public class StackIngredientCondition extends AbstractIngredientCondition { - public ItemStack stack; - - public StackIngredientCondition(ItemStack stack) { - this.stack = stack; - } - - @Override - public boolean entryMatches(Entry e) { - return e instanceof StackEntry se && se.stack.isItemEqual(this.stack); - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/recipe/TagIngredientCondition.java b/common/src/main/java/net/anvilcraft/anvillib/recipe/TagIngredientCondition.java deleted file mode 100644 index 8b765f7..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/recipe/TagIngredientCondition.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.anvilcraft.anvillib.recipe; - -import net.minecraft.recipe.Ingredient.Entry; -import net.minecraft.recipe.Ingredient.TagEntry; -import net.minecraft.util.Identifier; - -public class TagIngredientCondition extends AbstractIngredientCondition { - public Identifier id; - - public TagIngredientCondition(Identifier id) { - this.id = id; - } - - @Override - public boolean entryMatches(Entry e) { - return e instanceof TagEntry te && te.tag.id().equals(this.id); - } -} diff --git a/common/src/main/java/net/anvilcraft/anvillib/worldgen/AdvancedStructurePoolFeatureConfig.java b/common/src/main/java/net/anvilcraft/anvillib/worldgen/AdvancedStructurePoolFeatureConfig.java deleted file mode 100644 index b6993fa..0000000 --- a/common/src/main/java/net/anvilcraft/anvillib/worldgen/AdvancedStructurePoolFeatureConfig.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.anvilcraft.anvillib.worldgen; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; - -import net.minecraft.structure.pool.StructurePool; -import net.minecraft.util.registry.RegistryEntry; -import net.minecraft.world.gen.feature.StructurePoolFeatureConfig; - -public class AdvancedStructurePoolFeatureConfig extends StructurePoolFeatureConfig { - public static final Codec CODEC - = RecordCodecBuilder.create((instance) -> { - return instance - .group( - StructurePool.REGISTRY_CODEC.fieldOf("start_pool") - .forGetter( - (self) - -> ((AdvancedStructurePoolFeatureConfig) self) - .getStartPool() - ), - Codec.intRange(0, 7).fieldOf("size").forGetter( - (self) -> ((AdvancedStructurePoolFeatureConfig) self).getSize() - ), - Codec.INT.fieldOf("max_distance_from_center") - .forGetter( - (self) - -> ((AdvancedStructurePoolFeatureConfig) self) - .maxDistanceFromCenter - ), - Codec.BOOL.fieldOf("use_box_beardifier").forGetter( - (self) -> ((AdvancedStructurePoolFeatureConfig) self).useBoxBeardifier - ) - ) - .apply(instance, AdvancedStructurePoolFeatureConfig::new); - }); - - public final int maxDistanceFromCenter; - public final boolean useBoxBeardifier; - - public AdvancedStructurePoolFeatureConfig( - RegistryEntry startPool, int size, int maxDistanceFromCenter, boolean useBoxBeardifier - ) { - super(startPool, size); - this.maxDistanceFromCenter = maxDistanceFromCenter; - this.useBoxBeardifier = useBoxBeardifier; - } - - public AdvancedStructurePoolFeatureConfig( - RegistryEntry startPool, int size, int maxDistanceFromCenter - ) { - this(startPool, size, maxDistanceFromCenter, false); - } -} diff --git a/common/src/main/resources/anvillib-common.mixins.json b/common/src/main/resources/anvillib-common.mixins.json deleted file mode 100644 index 0ea5eda..0000000 --- a/common/src/main/resources/anvillib-common.mixins.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "required": true, - "package": "net.anvilcraft.anvillib.mixin", - "compatibilityLevel": "JAVA_17", - "minVersion": "0.8", - "client": [ - "client.MinecraftClientMixin", - "client.AbstractClientPlayerEntityMixin" - ], - "mixins": [ - "accessor.AnimatedGeoModelAccessor", - "common.RecipeManagerMixin", - "common.StructurePoolBasedGeneratorMixin" - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/common/src/main/resources/anvillib.accesswidener b/common/src/main/resources/anvillib.accesswidener deleted file mode 100644 index 30776c0..0000000 --- a/common/src/main/resources/anvillib.accesswidener +++ /dev/null @@ -1,12 +0,0 @@ -accessWidener v2 named -# vim: ft=conf - -accessible class net/minecraft/recipe/Ingredient$Entry -accessible field net/minecraft/recipe/Ingredient entries [Lnet/minecraft/recipe/Ingredient$Entry; -accessible class net/minecraft/recipe/Ingredient$TagEntry -accessible field net/minecraft/recipe/Ingredient$TagEntry tag Lnet/minecraft/tag/TagKey; -accessible class net/minecraft/recipe/Ingredient$StackEntry -accessible field net/minecraft/recipe/Ingredient$StackEntry stack Lnet/minecraft/item/ItemStack; - -accessible method net/minecraft/client/render/entity/LivingEntityRenderer addFeature (Lnet/minecraft/client/render/entity/feature/FeatureRenderer;)Z - diff --git a/common/src/main/resources/architectury.common.json b/common/src/main/resources/architectury.common.json deleted file mode 100644 index bb4b472..0000000 --- a/common/src/main/resources/architectury.common.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "accessWidener": "anvillib.accesswidener" -} diff --git a/common/src/main/resources/pack.mcmeta b/common/src/main/resources/pack.mcmeta deleted file mode 100644 index 3dff4a1..0000000 --- a/common/src/main/resources/pack.mcmeta +++ /dev/null @@ -1,7 +0,0 @@ -{ - "pack": { - "description": "Resources for anvillib", - "pack_format": 8, - "_comment": "pack_format 8 is the current format for Minecraft 1.18.2. Be aware may have changed by the time you use this template!" - } -} diff --git a/fabric/build.gradle b/fabric/build.gradle deleted file mode 100644 index 7206d4f..0000000 --- a/fabric/build.gradle +++ /dev/null @@ -1,71 +0,0 @@ -plugins { - id "com.github.johnrengelman.shadow" version "7.1.2" -} - -architectury { - platformSetupLoomIde() - fabric() -} - -loom { - accessWidenerPath = project(":common").loom.accessWidenerPath -} - -configurations { - common - shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files. - compileClasspath.extendsFrom common - runtimeClasspath.extendsFrom common - developmentFabric.extendsFrom common -} - -dependencies { - modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" - - modImplementation "software.bernie.geckolib:geckolib-fabric-1.18:3.0.80" - - common(project(path: ":common", configuration: "namedElements")) { transitive false } - shadowCommon(project(path: ":common", configuration: "transformProductionFabric")) { transitive false } -} - -processResources { - inputs.property "version", project.version - - filesMatching("fabric.mod.json") { - expand "version": project.version - } -} - -shadowJar { - exclude "architectury.common.json" - - configurations = [project.configurations.shadowCommon] - archiveClassifier = "dev-shadow" -} - -remapJar { - injectAccessWidener = true - input.set shadowJar.archiveFile - dependsOn shadowJar -} - -sourcesJar { - def commonSources = project(":common").sourcesJar - dependsOn commonSources - from commonSources.archiveFile.map { zipTree(it) } -} - -components.java { - withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { - skip() - } -} - -publishing { - publications { - mavenFabric(MavenPublication) { - artifactId = rootProject.archives_base_name + "-" + project.name - from components.java - } - } -} diff --git a/fabric/src/main/java/net/anvilcraft/anvillib/AnvilLibFabric.java b/fabric/src/main/java/net/anvilcraft/anvillib/AnvilLibFabric.java deleted file mode 100644 index 7dfdda2..0000000 --- a/fabric/src/main/java/net/anvilcraft/anvillib/AnvilLibFabric.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.anvilcraft.anvillib; - -import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.api.ModInitializer; - -public class AnvilLibFabric implements ModInitializer, ClientModInitializer { - @Override - public void onInitialize() { - AnvilLib.initialize(); - } - - @Override - public void onInitializeClient() { - AnvilLib.initializeClient(); - } -} diff --git a/fabric/src/main/java/net/anvilcraft/anvillib/mixin/fabric/client/EntityRenderDispatcherMixin.java b/fabric/src/main/java/net/anvilcraft/anvillib/mixin/fabric/client/EntityRenderDispatcherMixin.java deleted file mode 100644 index af61225..0000000 --- a/fabric/src/main/java/net/anvilcraft/anvillib/mixin/fabric/client/EntityRenderDispatcherMixin.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.anvilcraft.anvillib.mixin.fabric.client; - -import java.util.Map; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import net.anvilcraft.anvillib.event.AddEntityRenderLayersEvent; -import net.anvilcraft.anvillib.event.Bus; -import net.minecraft.client.render.entity.EntityRenderDispatcher; -import net.minecraft.client.render.entity.EntityRenderer; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.resource.ResourceManager; - -@Mixin(EntityRenderDispatcher.class) -public class EntityRenderDispatcherMixin { - @Shadow - private Map> modelRenderers; - - @Inject(method = "reload", at = @At("TAIL")) - public void onReload(ResourceManager alec, CallbackInfo ci) { - Bus.MAIN.fire(new AddEntityRenderLayersEvent(this.modelRenderers)); - } -} diff --git a/fabric/src/main/java/net/anvilcraft/anvillib/mixin/fabric/common/BeardifierMixin.java b/fabric/src/main/java/net/anvilcraft/anvillib/mixin/fabric/common/BeardifierMixin.java deleted file mode 100644 index ec283d4..0000000 --- a/fabric/src/main/java/net/anvilcraft/anvillib/mixin/fabric/common/BeardifierMixin.java +++ /dev/null @@ -1,126 +0,0 @@ -package net.anvilcraft.anvillib.mixin.fabric.common; - -import java.util.HashMap; -import java.util.Map; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArgs; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import org.spongepowered.asm.mixin.injection.invoke.arg.Args; - -import net.anvilcraft.anvillib.mixinutils.BeardifierLocals; -import net.anvilcraft.anvillib.worldgen.AdvancedStructurePoolFeatureConfig; -import net.minecraft.structure.StructurePiece; -import net.minecraft.structure.StructureStart; -import net.minecraft.util.math.BlockBox; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.world.gen.StructureWeightSampler; -import net.minecraft.world.gen.densityfunction.DensityFunction; -import net.minecraft.world.gen.feature.ConfiguredStructureFeature; - -/** - * This mixin is responsible for reimplementing 1.19's BEARD_BOX which causes terrain - * to be removed around ancient city structures. - */ -@Mixin(StructureWeightSampler.class) -public class BeardifierMixin { - private static ThreadLocal currentLocals = new ThreadLocal<>(); - @Unique - private Map> featureMap = new HashMap<>(); - - @ModifyArgs( - method = "method_38319", - at = @At( - value = "INVOKE", - target = "Lit/unimi/dsi/fastutil/objects/ObjectList;add(Ljava/lang/Object;)Z" - ), - remap = false - ) - private void - addStructurePieceToMap( - Args args, ChunkPos alec1, int alec2, int alec3, StructureStart ss - ) { - featureMap.put(args.get(0), ss.getFeature()); - } - - @Inject( - method = "sample", - at = @At( - value = "INVOKE", - target - = "Lnet/minecraft/structure/StructurePiece;getWeightType()Lnet/minecraft/world/gen/StructureWeightType;" - ), - locals = LocalCapture.CAPTURE_FAILHARD - ) - private void - collectVariables( - DensityFunction.NoisePos alec1, - CallbackInfoReturnable ci, - int i, - int j, - int k, - double alec2, - StructurePiece structurePiece, - BlockBox boundingBox, - int l, - int m - ) { - currentLocals.set(new BeardifierLocals(i, j, k, structurePiece, boundingBox, l, m) - ); - } - - @Shadow - private static double getStructureWeight(int l, int m, int n) { - throw new AssertionError(); - } - - @Redirect( - method = "sample", - at = @At( - value = "INVOKE", - target - = "Lnet/minecraft/world/gen/StructureWeightSampler;getStructureWeight(III)D" - ) - ) - private double - beardContribution(int l, int m, int n) { - BeardifierLocals locals = currentLocals.get(); - if (locals == null) - return getStructureWeight(l, m, n); - currentLocals.remove(); - - ConfiguredStructureFeature sf = this.featureMap.get(locals.structurePiece()); - if (sf == null /* WTF */ || !(sf.config instanceof AdvancedStructurePoolFeatureConfig && ((AdvancedStructurePoolFeatureConfig) sf.config).useBoxBeardifier)) - return getStructureWeight(l, m, n); - - int q = Math.max(0, Math.max(-m, locals.y() - locals.boundingBox().getMaxY())); - - return getAncientCityBeardContribution(l, q, n, m); - } - - private static double getAncientCityBeardContribution(int i, int j, int k, int l) { - int m = i + 12; - int n = j + 12; - int o = k + 12; - if (!(m >= 0 && m < 24 && n >= 0 && n < 24 && o >= 0 && o < 24)) { - return 0.0; - } - double d = (double) l + 0.5; - double e = MathHelper.squaredMagnitude(i, d, k); - double f = -d * MathHelper.fastInverseSqrt(e / 2.0) / 2.0; - return f * (double) computeBeardContribution(o - 12, m - 12, n - 12); - } - - private static double computeBeardContribution(int i, double d, int j) { - double e = MathHelper.squaredMagnitude(i, d, j); - double f = Math.pow(Math.E, -e / 16.0); - return f; - } -} diff --git a/fabric/src/main/resources/anvillib.mixins.json b/fabric/src/main/resources/anvillib.mixins.json deleted file mode 100644 index ae032ff..0000000 --- a/fabric/src/main/resources/anvillib.mixins.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "required": true, - "package": "net.anvilcraft.anvillib.mixin.fabric", - "compatibilityLevel": "JAVA_17", - "minVersion": "0.8", - "client": [ - "client.EntityRenderDispatcherMixin" - ], - "mixins": [ - "common.BeardifierMixin" - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json deleted file mode 100644 index 216ef15..0000000 --- a/fabric/src/main/resources/fabric.mod.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "schemaVersion": 1, - "id": "anvillib", - "version": "${version}", - "name": "AnvilLib", - "description": "ALEC!", - "authors": [ - "LordMZTE", - "tilera" - ], - "contact": { - "homepage": "https://anvilcraft.net/", - "sources": "https://git.tilera.org/anvilcraft/anvillib" - }, - "license": "AGPL-3.0+ALEC", - "environment": "*", - "entrypoints": { - "main": [ - "net.anvilcraft.anvillib.AnvilLibFabric" - ], - "client": [ - "net.anvilcraft.anvillib.AnvilLibFabric" - ] - }, - "mixins": [ - "anvillib.mixins.json", - "anvillib-common.mixins.json" - ], - "depends": { - "minecraft": "1.18.2" - } -} diff --git a/forge/build.gradle b/forge/build.gradle deleted file mode 100644 index b62c4fe..0000000 --- a/forge/build.gradle +++ /dev/null @@ -1,79 +0,0 @@ -plugins { - id "com.github.johnrengelman.shadow" version "7.1.2" -} - -architectury { - platformSetupLoomIde() - forge() -} - -loom { - accessWidenerPath = project(":common").loom.accessWidenerPath - - forge { - convertAccessWideners = true - extraAccessWideners.add loom.accessWidenerPath.get().asFile.name - - mixinConfig "anvillib-common.mixins.json" - mixinConfig "anvillib.mixins.json" - } -} - -configurations { - common - shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files. - compileClasspath.extendsFrom common - runtimeClasspath.extendsFrom common - developmentForge.extendsFrom common -} - -dependencies { - forge "net.minecraftforge:forge:${rootProject.forge_version}" - - modImplementation "software.bernie.geckolib:geckolib-forge-1.18:3.0.57" - - common(project(path: ":common", configuration: "namedElements")) { transitive false } - shadowCommon(project(path: ":common", configuration: "transformProductionForge")) { transitive = false } -} - -processResources { - inputs.property "version", project.version - - filesMatching("META-INF/mods.toml") { - expand "version": project.version - } -} - -shadowJar { - exclude "fabric.mod.json" - exclude "architectury.common.json" - - configurations = [project.configurations.shadowCommon] - archiveClassifier = "dev-shadow" -} - -remapJar { - input.set shadowJar.archiveFile - dependsOn shadowJar -} - -sourcesJar { - def commonSources = project(":common").sourcesJar - dependsOn commonSources - from commonSources.archiveFile.map { zipTree(it) } -} - -components.java { - withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) { - skip() - } -} - -publishing { - publications { - mavenForge(MavenPublication) { - artifactId = rootProject.archives_base_name + "-" + project.name - from components.java - } - } -} diff --git a/forge/gradle.properties b/forge/gradle.properties deleted file mode 100644 index 32f842a..0000000 --- a/forge/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -loom.platform=forge \ No newline at end of file diff --git a/forge/src/main/java/net/anvilcraft/anvillib/AnvilLibForge.java b/forge/src/main/java/net/anvilcraft/anvillib/AnvilLibForge.java deleted file mode 100644 index 5e04132..0000000 --- a/forge/src/main/java/net/anvilcraft/anvillib/AnvilLibForge.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.anvilcraft.anvillib; - -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; - -@Mod(AnvilLib.MODID) -public class AnvilLibForge { - public AnvilLibForge() { - AnvilLib.initialize(); - IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus(); - bus.addListener(alec -> AnvilLib.initializeClient()); - } -} diff --git a/forge/src/main/java/net/anvilcraft/anvillib/client/ClientEventHandler.java b/forge/src/main/java/net/anvilcraft/anvillib/client/ClientEventHandler.java deleted file mode 100644 index 9f0204e..0000000 --- a/forge/src/main/java/net/anvilcraft/anvillib/client/ClientEventHandler.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.anvilcraft.anvillib.client; - -import net.anvilcraft.anvillib.AnvilLib; -import net.anvilcraft.anvillib.event.AddEntityRenderLayersEvent; -import net.anvilcraft.anvillib.event.Bus; -import net.anvilcraft.anvillib.mixin.forge.accessor.AddLayersAccessor; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.event.EntityRenderersEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; - -@EventBusSubscriber( - modid = AnvilLib.MODID, bus = EventBusSubscriber.Bus.MOD, value = { Dist.CLIENT } -) -public class ClientEventHandler { - @SubscribeEvent - public static void onAddLayers(EntityRenderersEvent.AddLayers ev) { - Bus.MAIN.fire(new AddEntityRenderLayersEvent(((AddLayersAccessor) ev).getSkinMap() - )); - } -} diff --git a/forge/src/main/java/net/anvilcraft/anvillib/mixin/forge/accessor/AddLayersAccessor.java b/forge/src/main/java/net/anvilcraft/anvillib/mixin/forge/accessor/AddLayersAccessor.java deleted file mode 100644 index d4601d8..0000000 --- a/forge/src/main/java/net/anvilcraft/anvillib/mixin/forge/accessor/AddLayersAccessor.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.anvilcraft.anvillib.mixin.forge.accessor; - -import java.util.Map; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import net.minecraft.client.render.entity.EntityRenderer; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraftforge.client.event.EntityRenderersEvent.AddLayers; - -@Mixin(AddLayers.class) -public interface AddLayersAccessor { - @Accessor(remap = false) - public Map> getSkinMap(); -} diff --git a/forge/src/main/java/net/anvilcraft/anvillib/mixin/forge/common/BeardifierMixin.java b/forge/src/main/java/net/anvilcraft/anvillib/mixin/forge/common/BeardifierMixin.java deleted file mode 100644 index 7a37998..0000000 --- a/forge/src/main/java/net/anvilcraft/anvillib/mixin/forge/common/BeardifierMixin.java +++ /dev/null @@ -1,138 +0,0 @@ -package net.anvilcraft.anvillib.mixin.forge.common; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import net.anvilcraft.anvillib.mixinutils.BeardifierLocals; -import net.anvilcraft.anvillib.worldgen.AdvancedStructurePoolFeatureConfig; -import net.minecraft.structure.StructurePiece; -import net.minecraft.structure.StructureStart; -import net.minecraft.util.math.BlockBox; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.world.gen.StructureWeightSampler; -import net.minecraft.world.gen.densityfunction.DensityFunction; -import net.minecraft.world.gen.feature.ConfiguredStructureFeature; - -/** - * This mixin is responsible for reimplementing 1.19's BEARD_BOX which causes terrain - * to be removed around ancient city structures. - */ -@Mixin(StructureWeightSampler.class) -public class BeardifierMixin { - private static ThreadLocal currentLocals = new ThreadLocal<>(); - @Unique - private Map> featureMap = new HashMap<>(); - - // This is different than the fabric implementation where this is @ModifyArgs, but - // that's borked on Forge (as per usual). - @Inject( - // for this nonsense to work in the devenv, replace this with method_38319 - // for prod, use m_208194_ - // very elegant! - method = "m_208194_", - at = @At( - value = "INVOKE", - target = "Lit/unimi/dsi/fastutil/objects/ObjectList;add(Ljava/lang/Object;)Z" - ), - remap = false, - locals = LocalCapture.CAPTURE_FAILHARD - ) - private void - addStructurePieceToMap( - ChunkPos alec1, - int alec2, - int alec3, - StructureStart ss, - CallbackInfo ci, - Iterator alec4, - StructurePiece sp - ) { - featureMap.put(sp, ss.getFeature()); - } - - @Inject( - method = "sample", - at = @At( - value = "INVOKE", - target - = "Lnet/minecraft/structure/StructurePiece;getWeightType()Lnet/minecraft/world/gen/StructureWeightType;" - ), - locals = LocalCapture.CAPTURE_FAILHARD - ) - private void - collectVariables( - DensityFunction.NoisePos alec1, - CallbackInfoReturnable ci, - int i, - int j, - int k, - double alec2, - StructurePiece structurePiece, - BlockBox boundingBox, - int l, - int m - ) { - currentLocals.set(new BeardifierLocals(i, j, k, structurePiece, boundingBox, l, m) - ); - } - - @Shadow - protected static double getStructureWeight(int l, int m, int n) { - throw new AssertionError(); - } - - @Redirect( - method = "sample", - at = @At( - value = "INVOKE", - target - = "Lnet/minecraft/world/gen/StructureWeightSampler;getStructureWeight(III)D" - ) - ) - private double - beardContribution(int l, int m, int n) { - BeardifierLocals locals = currentLocals.get(); - if (locals == null) - return getStructureWeight(l, m, n); - currentLocals.remove(); - - ConfiguredStructureFeature sf = this.featureMap.get(locals.structurePiece()); - if (sf == null /* WTF */ || !(sf.config instanceof AdvancedStructurePoolFeatureConfig && ((AdvancedStructurePoolFeatureConfig) sf.config).useBoxBeardifier)) - return getStructureWeight(l, m, n); - - int q = Math.max(0, Math.max(-m, locals.y() - locals.boundingBox().getMaxY())); - - return getAncientCityBeardContribution(l, q, n, m); - } - - private static double getAncientCityBeardContribution(int i, int j, int k, int l) { - int m = i + 12; - int n = j + 12; - int o = k + 12; - if (!(m >= 0 && m < 24 && n >= 0 && n < 24 && o >= 0 && o < 24)) { - return 0.0; - } - double d = (double) l + 0.5; - double e = MathHelper.squaredMagnitude(i, d, k); - double f = -d * MathHelper.fastInverseSqrt(e / 2.0) / 2.0; - return f * (double) computeBeardContribution(o - 12, m - 12, n - 12); - } - - private static double computeBeardContribution(int i, double d, int j) { - double e = MathHelper.squaredMagnitude(i, d, j); - double f = Math.pow(Math.E, -e / 16.0); - return f; - } -} diff --git a/forge/src/main/resources/META-INF/mods.toml b/forge/src/main/resources/META-INF/mods.toml deleted file mode 100644 index 05bf9ee..0000000 --- a/forge/src/main/resources/META-INF/mods.toml +++ /dev/null @@ -1,36 +0,0 @@ -modLoader = "javafml" -loaderVersion = "[40,)" -#issueTrackerURL = "" -license = "AGPL-3.0+ALEC" - -[[mods]] -modId = "anvillib" -version = "${version}" -displayName = "AnvilLib" -authors = "LordMZTE, tilera" -description = ''' -AnvilLib library mod -''' -#logoFile = "" - -[[dependencies.anvillib]] -modId = "forge" -mandatory = true -versionRange = "[40,)" -ordering = "NONE" -side = "BOTH" - -[[dependencies.anvillib]] -modId = "minecraft" -mandatory = true -versionRange = "[1.18.2]" -ordering = "NONE" -side = "BOTH" - -[[dependencies.anvillib]] -modId = "geckolib3" -mandatory = true -versionRange = "[3.0.57,)" -ordering = "NONE" -side = "BOTH" - diff --git a/forge/src/main/resources/anvillib.mixins.json b/forge/src/main/resources/anvillib.mixins.json deleted file mode 100644 index 3bc0afe..0000000 --- a/forge/src/main/resources/anvillib.mixins.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "required": true, - "package": "net.anvilcraft.anvillib.mixin.forge", - "compatibilityLevel": "JAVA_17", - "minVersion": "0.8", - "client": [ - "accessor.AddLayersAccessor" - ], - "mixins": [ - "common.BeardifierMixin" - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index bf2a774..0000000 --- a/gradle.properties +++ /dev/null @@ -1,16 +0,0 @@ -# Done to increase the memory available to gradle. -org.gradle.jvmargs=-Xmx2G - -minecraft_version=1.18.2 -enabled_platforms=fabric,forge - -#architectury_version=4.11.93 -fabric_loader_version=0.14.23 -fabric_api_version=0.76.0+1.18.2 -forge_version=1.18.2-40.2.10 - -mod_version=1.1.0 -maven_group=net.anvilcraft -archives_base_name=anvillib-18 -mod_id=anvillib -mod_author=LordMZTE, (tilera) diff --git a/gradle/scripts/mixins.gradle b/gradle/scripts/mixins.gradle new file mode 100644 index 0000000..91ba32d --- /dev/null +++ b/gradle/scripts/mixins.gradle @@ -0,0 +1,78 @@ +abstract class MixinTask extends DefaultTask { + + @Input + abstract Property getMixinRefMapName() + + private File mixinSrg + private File mixinRefMap + + MixinTask() { + mixinRefMapName.convention("mixin.${project.name.replaceAll('[_\\-.]', '').toLowerCase()}.refmap.json") + } + + @TaskAction + void action() { + def mixinDir = new File(project.buildDir, 'mixins') + if (!mixinDir.exists()) { + mixinDir.mkdirs() + } + def srgFile = new File(project.buildDir, 'srgs/mcp-srg.srg') + mixinSrg = new File(mixinDir, "${mixinRefMapName.get()}.srg") + mixinRefMap = new File(mixinDir, mixinRefMapName.get()) + + if (!mixinSrg.exists()) { + mixinSrg.createNewFile() + } + + project.tasks.reobf.configure { + addExtraSrgFile mixinSrg + } + + def compileJava = project.tasks.compileJava + compileJava.configure { + options.compilerArgs += [ + '-Xlint:-processing', + "-AoutSrgFile=${mixinSrg.canonicalPath}", + "-AoutRefMapFile=${mixinRefMap.canonicalPath}", + "-AreobfSrgFile=${srgFile.canonicalPath}" + ] + } + + project.tasks.jar.configure { + from mixinRefMap + } + } + + @Internal + File getMixinSrg() { + return mixinSrg + } + + @Internal + File getMixinRefMap() { + return mixinRefMap + } +} + +tasks.register('mixin', MixinTask) + +task copySrgs(type: Copy, dependsOn: 'genSrgs') { + from plugins.getPlugin('forge').delayedFile('{SRG_DIR}') + include '**/*.srg' + into layout.buildDirectory.file('srgs') +} + +compileJava.dependsOn(copySrgs, mixin) +tasks.findByPath(":prepareKotlinBuildScriptModel")?.dependsOn(copySrgs, mixin) + +processResources { + afterEvaluate { + def refmap = tasks.mixin.mixinRefMapName.get() + inputs.property 'mixin_refmap', refmap + from(sourceSets.main.resources.srcDirs) { + include '*.json' + expand 'mixin_refmap': refmap + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } + } +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..b7612167031001b7b84baf2a959e8ea8ad03c011 100644 GIT binary patch literal 51017 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

N(DARnfPMFG|;(rIGZH1uB1rN;y7UlJ8 znb!RwO#5WS_%cPPlwSw94PTKP64}}J!~E1}ch9``2jvUrB*#@up8L&*`tqgq ztTAS@^33w-5hFZAH&{j)?l0<)9X(d`N|yLk!E=iT%PD-FTJ!|hqyj%RFFP`SaL;|_ z$(+VYhKm)K@Oe~+eZK(6ElQNdfimBrdKjeVl57_7p^|)jrzt|wyRonj$j9Bji!


f)EE4q$t9yObmyG04W0z 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 QuEJmfE|#`Dqx|px0L@K;Y5)KL diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 744c64d..f6a15a7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ +#Wed Jul 02 15:54:47 CDT 2014 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip -networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-bin.zip diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index c9d56ed..0000000 --- a/settings.gradle +++ /dev/null @@ -1,14 +0,0 @@ -pluginManagement { - repositories { - maven { url "https://maven.fabricmc.net/" } - maven { url "https://maven.architectury.dev/" } - maven { url "https://maven.minecraftforge.net/" } - gradlePluginPortal() - } -} - -include("common") -include("fabric") -include("forge") - -rootProject.name = "anvillib"