First attempt of adding custom modeled scripted items

This commit is contained in:
Goodbird committed 2024-07-02 09:35:16 +03:00
1 parent 451702817d
commit cb3132c6d3
12 files changed
+344 -1

No files matched your search

@@ -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<EntityPlayerMP> 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);
}
@@ -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();
}
}
@@ -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<AnimatableStackWrapper> {
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());
}
}
@@ -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;
}
}
@@ -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 <P extends Item & IAnimatable> PlayState predicate(AnimationEvent<P> 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;
}
}
@@ -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();
}
@@ -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();
}
}
}
@@ -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;
}
}
@@ -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<NBTTagCompound> 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;
}
}