diff --git a/dependencies.gradle b/dependencies.gradle index 3464f88..28e3910 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -38,5 +38,5 @@ dependencies { runtimeOnlyNonPublishable("curse.maven:Nashorn-374413:2924946") implementation rfg.deobf(name: "CustomNPC-Plus-1.9.2") - implementation name: "geckolib-unofficial-1.7.10-1.0.5-dev" + implementation name: "geckolib-unofficial-1.7.10-1.0.6-dev" } diff --git a/lib/geckolib-unofficial-1.7.10-1.0.5-dev.jar b/lib/geckolib-unofficial-1.7.10-1.0.6-dev.jar similarity index 97% rename from lib/geckolib-unofficial-1.7.10-1.0.5-dev.jar rename to lib/geckolib-unofficial-1.7.10-1.0.6-dev.jar index 141386e..92704aa 100644 Binary files a/lib/geckolib-unofficial-1.7.10-1.0.5-dev.jar and b/lib/geckolib-unofficial-1.7.10-1.0.6-dev.jar differ diff --git a/src/main/java/com/goodbird/npcgecko/api/AbstractGeckoAPI.java b/src/main/java/com/goodbird/npcgecko/api/AbstractGeckoAPI.java index c8e5c81..65d7789 100644 --- a/src/main/java/com/goodbird/npcgecko/api/AbstractGeckoAPI.java +++ b/src/main/java/com/goodbird/npcgecko/api/AbstractGeckoAPI.java @@ -1,11 +1,13 @@ package com.goodbird.npcgecko.api; +import com.goodbird.npcgecko.data.CustomItemModelData; import cpw.mods.fml.common.Loader; import net.minecraft.entity.player.EntityPlayerMP; import noppes.npcs.api.block.IBlockScripted; import noppes.npcs.api.entity.ICustomNpc; import noppes.npcs.api.entity.IPlayer; import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.scripted.item.ScriptCustomItem; import software.bernie.geckolib3.core.builder.AnimationBuilder; public abstract class AbstractGeckoAPI { @@ -46,4 +48,9 @@ public abstract class AbstractGeckoAPI { public abstract void setIdleAnimation(IBlockScripted scriptedBlock, String animation); public abstract void syncAnimForPlayer(IBlockScripted scriptedBlock, AnimationBuilder builder, IPlayer player); public abstract void syncAnimForAll(IBlockScripted scriptedBlock, AnimationBuilder builder); + + public abstract void setModel(ScriptCustomItem item, String model); + public abstract void setTexture(ScriptCustomItem item, String texture); + public abstract void setAnimationFile(ScriptCustomItem item, String animation); + public abstract void setIdleAnimation(ScriptCustomItem item, String animation); } diff --git a/src/main/java/com/goodbird/npcgecko/api/GeckoAPI.java b/src/main/java/com/goodbird/npcgecko/api/GeckoAPI.java index 56ed336..793a3ba 100644 --- a/src/main/java/com/goodbird/npcgecko/api/GeckoAPI.java +++ b/src/main/java/com/goodbird/npcgecko/api/GeckoAPI.java @@ -1,7 +1,9 @@ package com.goodbird.npcgecko.api; import com.goodbird.npcgecko.client.renderer.RenderTileCustomModel; +import com.goodbird.npcgecko.data.CustomItemModelData; import com.goodbird.npcgecko.mixin.IDataDisplay; +import com.goodbird.npcgecko.mixin.IScriptCustomItem; import com.goodbird.npcgecko.network.CPacketSyncManualAnim; import com.goodbird.npcgecko.network.CPacketSyncTileManualAnim; import com.goodbird.npcgecko.network.NetworkHandler; @@ -16,6 +18,7 @@ import noppes.npcs.api.entity.IPlayer; import noppes.npcs.blocks.tiles.TileScripted; import noppes.npcs.entity.EntityNPCInterface; import noppes.npcs.scripted.BlockScriptedWrapper; +import noppes.npcs.scripted.item.ScriptCustomItem; import software.bernie.geckolib3.core.builder.AnimationBuilder; public class GeckoAPI extends AbstractGeckoAPI { @@ -116,4 +119,40 @@ public class GeckoAPI extends AbstractGeckoAPI { public void syncAnimForAll(IBlockScripted scriptedBlock, AnimationBuilder builder) { NetworkHandler.sendToAll(new CPacketSyncTileManualAnim(scriptedBlock.getMCTileEntity(), builder)); } + + private CustomItemModelData getOrCreateCIMD(ScriptCustomItem item){ + IScriptCustomItem scriptCustomItem = (IScriptCustomItem) item; + if(!scriptCustomItem.hasCustomModel()){ + scriptCustomItem.setCustomModelData(new CustomItemModelData()); + } + return scriptCustomItem.getCustomModelData(); + } + + @Override + public void setModel(ScriptCustomItem item, String model) { + CustomItemModelData data = getOrCreateCIMD(item); + data.setModel(model); + item.saveItemData(); + } + + @Override + public void setTexture(ScriptCustomItem item, String texture) { + CustomItemModelData data = getOrCreateCIMD(item); + data.setTexture(texture); + item.saveItemData(); + } + + @Override + public void setAnimationFile(ScriptCustomItem item, String animation) { + CustomItemModelData data = getOrCreateCIMD(item); + data.setAnimFile(animation); + item.saveItemData(); + } + + @Override + public void setIdleAnimation(ScriptCustomItem item, String animation) { + CustomItemModelData data = getOrCreateCIMD(item); + data.setIdleAnim(animation); + item.saveItemData(); + } } diff --git a/src/main/java/com/goodbird/npcgecko/client/model/ItemModelCustom.java b/src/main/java/com/goodbird/npcgecko/client/model/ItemModelCustom.java new file mode 100644 index 0000000..033cbdc --- /dev/null +++ b/src/main/java/com/goodbird/npcgecko/client/model/ItemModelCustom.java @@ -0,0 +1,53 @@ +package com.goodbird.npcgecko.client.model; + +import com.goodbird.npcgecko.data.CustomItemModelData; +import com.goodbird.npcgecko.mixin.IScriptCustomItem; +import net.minecraft.util.ResourceLocation; +import noppes.npcs.api.item.IItemStack; +import noppes.npcs.scripted.NpcAPI; +import noppes.npcs.scripted.item.ScriptCustomItem; +import software.bernie.geckolib3.item.AnimatableStackWrapper; +import software.bernie.geckolib3.model.AnimatedGeoModel; +import software.bernie.geckolib3.resource.GeckoLibCache; + +public class ItemModelCustom extends AnimatedGeoModel { + + private CustomItemModelData getModelData(AnimatableStackWrapper animatable){ + IItemStack istack = NpcAPI.Instance().getIItemStack(animatable.getStack()); + if(!(istack instanceof ScriptCustomItem)) return null; + return ((IScriptCustomItem)istack).getCustomModelData(); + } + + @Override + public ResourceLocation getAnimationFileLocation(AnimatableStackWrapper animatable) { + CustomItemModelData data = getModelData(animatable); + if(data==null || !GeckoLibCache.getInstance().getAnimations().containsKey(new ResourceLocation(data.getAnimFile()))){ + return new ResourceLocation("npcgecko","animations/none.animations.json"); + } + return new ResourceLocation(data.getAnimFile()); + } + + @Override + public ResourceLocation getModelLocation(AnimatableStackWrapper animatable) { + CustomItemModelData data = getModelData(animatable); + if(data==null || !GeckoLibCache.getInstance().getGeoModels().containsKey(new ResourceLocation(data.getModel()))){ + return new ResourceLocation("npcgecko","geo/modelnotfound.geo.json"); + } + if(!GeckoLibCache.getInstance().getAnimations().containsKey(new ResourceLocation(data.getAnimFile()))){ + return new ResourceLocation("npcgecko","geo/animfilenotfound.geo.json"); + } + return new ResourceLocation(data.getModel()); + } + + @Override + public ResourceLocation getTextureLocation(AnimatableStackWrapper animatable) { + CustomItemModelData data = getModelData(animatable); + if(data==null || !GeckoLibCache.getInstance().getGeoModels().containsKey(new ResourceLocation(data.getModel()))){ + return new ResourceLocation("npcgecko","textures/model/alphabet.png"); + } + if(!GeckoLibCache.getInstance().getAnimations().containsKey(new ResourceLocation(data.getAnimFile()))){ + return new ResourceLocation("npcgecko","textures/model/alphabet.png"); + } + return new ResourceLocation(data.getTexture()); + } +} diff --git a/src/main/java/com/goodbird/npcgecko/data/CustomItemModelData.java b/src/main/java/com/goodbird/npcgecko/data/CustomItemModelData.java new file mode 100644 index 0000000..163cd84 --- /dev/null +++ b/src/main/java/com/goodbird/npcgecko/data/CustomItemModelData.java @@ -0,0 +1,75 @@ +package com.goodbird.npcgecko.data; + +import net.minecraft.nbt.NBTTagCompound; + +public class CustomItemModelData { + private String model = "geckolib3:geo/npc.geo.json"; + private String animFile = "custom:geo_npc.animation.json"; + private String texture = "geckolib3:textures/item/jack.png"; + private String idleAnim = ""; + private int transitionLengthTicks = 10; + + public CustomItemModelData() { + } + + public NBTTagCompound writeToNBT(NBTTagCompound nbttagcompound) { + nbttagcompound.setString("Model", model); + nbttagcompound.setString("AnimFile", animFile); + nbttagcompound.setString("IdleAnim", idleAnim); + nbttagcompound.setString("Texture", texture); + nbttagcompound.setInteger("TransitionLengthTicks", transitionLengthTicks); + return nbttagcompound; + } + + public void readFromNBT(NBTTagCompound nbttagcompound) { + if(nbttagcompound.hasKey("Model")) { + model = nbttagcompound.getString("Model"); + animFile = nbttagcompound.getString("AnimFile"); + idleAnim = nbttagcompound.getString("IdleAnim"); + texture = nbttagcompound.getString("Texture"); + if(nbttagcompound.hasKey("TransitionLengthTicks")){ + transitionLengthTicks = nbttagcompound.getInteger("TransitionLengthTicks"); + } + } + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public String getAnimFile() { + return animFile; + } + + public void setAnimFile(String animFile) { + this.animFile = animFile; + } + + public String getIdleAnim() { + return idleAnim; + } + + public void setIdleAnim(String idleAnim) { + this.idleAnim = idleAnim; + } + + public int getTransitionLengthTicks() { + return transitionLengthTicks; + } + + public void setTransitionLengthTicks(int transitionLengthTicks) { + this.transitionLengthTicks = transitionLengthTicks; + } + + public String getTexture() { + return texture; + } + + public void setTexture(String texture) { + this.texture = texture; + } +} diff --git a/src/main/java/com/goodbird/npcgecko/item/ItemCustomModelPredicate.java b/src/main/java/com/goodbird/npcgecko/item/ItemCustomModelPredicate.java new file mode 100644 index 0000000..fc42c05 --- /dev/null +++ b/src/main/java/com/goodbird/npcgecko/item/ItemCustomModelPredicate.java @@ -0,0 +1,23 @@ +package com.goodbird.npcgecko.item; + +import com.goodbird.npcgecko.mixin.IScriptCustomItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import noppes.npcs.api.item.IItemStack; +import noppes.npcs.scripted.NpcAPI; +import noppes.npcs.scripted.item.ScriptCustomItem; +import software.bernie.geckolib3.core.IAnimatable; +import software.bernie.geckolib3.core.PlayState; +import software.bernie.geckolib3.core.builder.AnimationBuilder; +import software.bernie.geckolib3.core.event.predicate.AnimationEvent; + +public class ItemCustomModelPredicate { + public static

PlayState predicate(AnimationEvent

event) { + ItemStack stack = (ItemStack) event.getExtraData().get(0); + IItemStack istack = NpcAPI.Instance().getIItemStack(stack); + if(!(istack instanceof ScriptCustomItem)) return PlayState.STOP; + IScriptCustomItem item = (IScriptCustomItem)istack; + event.getController().setAnimation(new AnimationBuilder().loop(item.getCustomModelData().getIdleAnim())); + return PlayState.CONTINUE; + } +} diff --git a/src/main/java/com/goodbird/npcgecko/mixin/IScriptCustomItem.java b/src/main/java/com/goodbird/npcgecko/mixin/IScriptCustomItem.java new file mode 100644 index 0000000..e4d0a2a --- /dev/null +++ b/src/main/java/com/goodbird/npcgecko/mixin/IScriptCustomItem.java @@ -0,0 +1,11 @@ +package com.goodbird.npcgecko.mixin; + +import com.goodbird.npcgecko.data.CustomItemModelData; + +public interface IScriptCustomItem { + CustomItemModelData getCustomModelData(); + + void setCustomModelData(CustomItemModelData data); + + boolean hasCustomModel(); +} diff --git a/src/main/java/com/goodbird/npcgecko/mixin/impl/MixinCustomItemRenderer.java b/src/main/java/com/goodbird/npcgecko/mixin/impl/MixinCustomItemRenderer.java new file mode 100644 index 0000000..a6709a2 --- /dev/null +++ b/src/main/java/com/goodbird/npcgecko/mixin/impl/MixinCustomItemRenderer.java @@ -0,0 +1,52 @@ +package com.goodbird.npcgecko.mixin.impl; + +import com.goodbird.npcgecko.client.model.ItemModelCustom; +import com.goodbird.npcgecko.mixin.IScriptCustomItem; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.item.ItemStack; +import noppes.npcs.client.renderer.items.CustomItemRenderer; +import noppes.npcs.scripted.item.ScriptCustomItem; +import org.lwjgl.opengl.GL11; +import org.spongepowered.asm.mixin.Mixin; +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.callback.CallbackInfo; +import software.bernie.geckolib3.item.AnimatableStackWrapper; +import software.bernie.geckolib3.renderers.geo.GeoItemStackRenderer; + +@Mixin(CustomItemRenderer.class) +public class MixinCustomItemRenderer { + @Unique + private static GeoItemStackRenderer renderer = new GeoItemStackRenderer(new ItemModelCustom()); + + @Inject(method = "renderEntityCustomItem", cancellable = true, at=@At("HEAD"), remap = false) + public void renderEntityCustomItem(ScriptCustomItem scriptCustomItem, ItemStack itemStack, EntityItem entityItem, CallbackInfo ci) { + if(((IScriptCustomItem)scriptCustomItem).hasCustomModel()){ + renderer.render(AnimatableStackWrapper.wrapItemStack(itemStack), itemStack); + ci.cancel(); + } + } + + @Inject(method = "renderInventoryCustomItem", cancellable = true, at=@At("HEAD"), remap = false) + public void renderInventoryCustomItem(ScriptCustomItem scriptCustomItem, CallbackInfo ci){ + if(((IScriptCustomItem)scriptCustomItem).hasCustomModel()){ + GL11.glPushMatrix(); + GL11.glTranslated(-1.0, -1.0, 0.0); + GL11.glRotatef(90.0F, 0.0F, 1.0F, 0.0F); + renderer.render(AnimatableStackWrapper.wrapItemStack(scriptCustomItem.item), scriptCustomItem.item); + GL11.glPopMatrix(); + ci.cancel(); + } + } + + @Inject(method = "renderItem3d", cancellable = true, at=@At("HEAD"), remap = false) + public void renderItem3d(ScriptCustomItem scriptCustomItem, EntityLivingBase entityLivingBase, ItemStack itemStack, CallbackInfo ci) { + if(((IScriptCustomItem)scriptCustomItem).hasCustomModel()){ + renderer.render(AnimatableStackWrapper.wrapItemStack(itemStack), itemStack); + ci.cancel(); + } + } + +} diff --git a/src/main/java/com/goodbird/npcgecko/mixin/impl/MixinItemScripted.java b/src/main/java/com/goodbird/npcgecko/mixin/impl/MixinItemScripted.java new file mode 100644 index 0000000..8c947b4 --- /dev/null +++ b/src/main/java/com/goodbird/npcgecko/mixin/impl/MixinItemScripted.java @@ -0,0 +1,30 @@ +package com.goodbird.npcgecko.mixin.impl; + +import com.goodbird.npcgecko.item.ItemCustomModelPredicate; +import net.minecraft.item.Item; +import noppes.npcs.items.ItemScripted; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import software.bernie.geckolib3.core.IAnimatable; +import software.bernie.geckolib3.core.controller.AnimationController; +import software.bernie.geckolib3.core.manager.AnimationData; +import software.bernie.geckolib3.core.manager.AnimationFactory; + +@Mixin(ItemScripted.class) +@Implements(value = @Interface(iface = IAnimatable.class, prefix = "customNPC_Gecko_Addon$")) +public abstract class MixinItemScripted extends Item implements IAnimatable { + @Unique + public AnimationFactory customNPC_Gecko_Addon$factory = new AnimationFactory(this); + + @Unique + public void customNPC_Gecko_Addon$registerControllers(AnimationData data) { + data.addAnimationController(new AnimationController<>(this, "controller", 20, ItemCustomModelPredicate::predicate)); + } + + @Unique + public AnimationFactory customNPC_Gecko_Addon$getFactory() { + return this.customNPC_Gecko_Addon$factory; + } +} diff --git a/src/main/java/com/goodbird/npcgecko/mixin/impl/MixinScriptCustomItem.java b/src/main/java/com/goodbird/npcgecko/mixin/impl/MixinScriptCustomItem.java new file mode 100644 index 0000000..5da9745 --- /dev/null +++ b/src/main/java/com/goodbird/npcgecko/mixin/impl/MixinScriptCustomItem.java @@ -0,0 +1,50 @@ +package com.goodbird.npcgecko.mixin.impl; + +import com.goodbird.npcgecko.data.CustomItemModelData; +import com.goodbird.npcgecko.mixin.IScriptCustomItem; +import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.scripted.item.ScriptCustomItem; +import org.spongepowered.asm.mixin.Mixin; +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.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ScriptCustomItem.class) +public class MixinScriptCustomItem implements IScriptCustomItem { + @Unique + private CustomItemModelData customNPC_Gecko_Addon$customModelData; + + @Inject(method = "getItemNBT", at = @At("HEAD"), remap = false) + public void writeToNBT(NBTTagCompound nbttagcompound, CallbackInfoReturnable cir) { + if(customNPC_Gecko_Addon$customModelData!=null){ + NBTTagCompound modelDataTag = new NBTTagCompound(); + customNPC_Gecko_Addon$customModelData.writeToNBT(modelDataTag); + nbttagcompound.setTag("GeckoModelData", modelDataTag); + } + } + + @Inject(method = "setItemNBT", at = @At("HEAD"), remap = false) + public void readFromNBT(NBTTagCompound nbttagcompound, CallbackInfo ci){ + if(nbttagcompound.hasKey("GeckoModelData")){ + customNPC_Gecko_Addon$customModelData = new CustomItemModelData(); + customNPC_Gecko_Addon$customModelData.readFromNBT(nbttagcompound.getCompoundTag("GeckoModelData")); + } + } + + @Unique + public CustomItemModelData getCustomModelData(){ + return customNPC_Gecko_Addon$customModelData; + } + + @Override + public void setCustomModelData(CustomItemModelData data) { + customNPC_Gecko_Addon$customModelData = data; + } + + @Unique + public boolean hasCustomModel() { + return customNPC_Gecko_Addon$customModelData!=null; + } +} diff --git a/src/main/resources/mixins.npcgecko.json b/src/main/resources/mixins.npcgecko.json index e16b80a..cb84187 100644 --- a/src/main/resources/mixins.npcgecko.json +++ b/src/main/resources/mixins.npcgecko.json @@ -8,9 +8,12 @@ "mixins": [ "MixinDataDisplay", "MixinGeckoAddon", + "MixinItemScripted", + "MixinScriptCustomItem", "TileScriptedMixin" ], "client": [ + "MixinCustomItemRenderer", "MixinBlockScriptedRenderer", "MixinGeckoAddonClient" ],