Skip to content

Commit

Permalink
feat: add bile spitter weapon
Browse files Browse the repository at this point in the history
  • Loading branch information
Elenterius committed Oct 12, 2022
1 parent dae1b20 commit 2fb2e71
Show file tree
Hide file tree
Showing 10 changed files with 2,176 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.github.elenterius.biomancy.client.model.item;

import com.github.elenterius.biomancy.BiomancyMod;
import com.github.elenterius.biomancy.world.item.weapon.BileSpitterItem;
import net.minecraft.resources.ResourceLocation;
import software.bernie.geckolib3.model.AnimatedGeoModel;

public class BileSpitterModel extends AnimatedGeoModel<BileSpitterItem> {

@Override
public ResourceLocation getModelLocation(BileSpitterItem item) {
return BiomancyMod.createRL("geo/item/bile_spitter.geo.json");
}

@Override
public ResourceLocation getTextureLocation(BileSpitterItem item) {
return BiomancyMod.createRL("textures/item/weapon/bile_spitter.png");
}

@Override
public ResourceLocation getAnimationFileLocation(BileSpitterItem item) {
return BiomancyMod.createRL("animations/item/bile_spitter.animation.json");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.github.elenterius.biomancy.client.renderer.item;

import com.github.elenterius.biomancy.client.model.item.BileSpitterModel;
import com.github.elenterius.biomancy.world.item.weapon.BileSpitterItem;
import software.bernie.geckolib3.renderers.geo.GeoItemRenderer;

public class BileSpitterRenderer extends GeoItemRenderer<BileSpitterItem> {

public BileSpitterRenderer() {
super(new BileSpitterModel());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public final class ModItems {
// public static final RegistryObject<WithershotItem> WITHERSHOT = ITEMS.register("withershot", () -> new WithershotItem(createBaseProperties().stacksTo(1).durability(ModTiers.BIOFLESH.getUses()).rarity(ModRarities.VERY_RARE)));
public static final RegistryObject<LongClawItem> LONG_CLAW = ITEMS.register("long_range_claw", () -> new LongClawItem(ModTiers.BIOFLESH, 3, -2.4f, 120, createBaseProperties().rarity(ModRarities.VERY_RARE)));
public static final RegistryObject<DevArmCannonItem> ARM_CANNON = ITEMS.register("dev_arm_cannon", () -> new DevArmCannonItem(createBaseProperties().stacksTo(1).durability(ModTiers.BIOFLESH.getUses()).rarity(ModRarities.ULTRA_RARE)));
public static final RegistryObject<BileSpitterItem> BILE_SPITTER = ITEMS.register("bile_spitter", () -> new BileSpitterItem(createBaseProperties().stacksTo(1).durability(ModTiers.BIOFLESH.getUses()).rarity(ModRarities.ULTRA_RARE)));

//# Creature
public static final RegistryObject<BoomlingItem> BOOMLING = ITEMS.register("boomling", () -> new BoomlingItem(createBaseProperties().rarity(ModRarities.RARE).stacksTo(1).tab(null)));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
package com.github.elenterius.biomancy.world.item.weapon;

import com.github.elenterius.biomancy.client.renderer.item.BileSpitterRenderer;
import com.github.elenterius.biomancy.init.ModProjectiles;
import com.github.elenterius.biomancy.styles.ClientTextUtil;
import com.github.elenterius.biomancy.styles.HrTooltipComponent;
import com.github.elenterius.biomancy.world.item.IArmPoseProvider;
import com.github.elenterius.biomancy.world.item.IBiomancyItem;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.tooltip.TooltipComponent;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ProjectileWeaponItem;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.UseAnim;
import net.minecraft.world.level.Level;
import net.minecraftforge.client.IItemRenderProperties;
import net.minecraftforge.network.PacketDistributor;
import software.bernie.geckolib3.core.IAnimatable;
import software.bernie.geckolib3.core.PlayState;
import software.bernie.geckolib3.core.builder.AnimationBuilder;
import software.bernie.geckolib3.core.controller.AnimationController;
import software.bernie.geckolib3.core.manager.AnimationData;
import software.bernie.geckolib3.core.manager.AnimationFactory;
import software.bernie.geckolib3.network.GeckoLibNetwork;
import software.bernie.geckolib3.network.ISyncable;
import software.bernie.geckolib3.util.GeckoLibUtil;

import javax.annotation.Nullable;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Predicate;

public class BileSpitterItem extends ProjectileWeaponItem implements IBiomancyItem, IAnimatable, ISyncable, IArmPoseProvider {

private static final String CONTROLLER_NAME = "controller";
public final float drawTime = 50f;
private final AnimationFactory animationFactory = new AnimationFactory(this);

public BileSpitterItem(Properties properties) {
super(properties);
GeckoLibNetwork.registerSyncable(this);
}

@Override
public Predicate<ItemStack> getAllSupportedProjectiles() {
return itemStack -> false;
}

@Override
public int getDefaultProjectileRange() {
return 15;
}

@Override
public void initializeClient(Consumer<IItemRenderProperties> consumer) {
super.initializeClient(consumer);
consumer.accept(new IItemRenderProperties() {
private final BileSpitterRenderer renderer = new BileSpitterRenderer();

@Override
public BlockEntityWithoutLevelRenderer getItemStackRenderer() {
return renderer;
}
});
}

public float getPullProgress(ItemStack stack, LivingEntity livingEntity) {
return (stack.getUseDuration() - livingEntity.getUseItemRemainingTicks()) / drawTime;
}

@Override
public int getUseDuration(ItemStack stack) {
return 3600 * 20;
}

@Override
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
ItemStack stack = player.getItemInHand(hand);
if (!level.isClientSide) {
broadcastAnimation((ServerLevel) level, player, stack, Animation.CHARGE);
}
player.startUsingItem(hand);
return InteractionResultHolder.consume(stack);
}

@Override
public void releaseUsing(ItemStack stack, Level level, LivingEntity entityLiving, int timeLeft) {
if (entityLiving instanceof Player player) {
if (!level.isClientSide) {
ModProjectiles.CORROSIVE.shoot(level, entityLiving);
broadcastAnimation((ServerLevel) level, player, stack, Animation.IDLE);
}
player.awardStat(Stats.ITEM_USED.get(this));
}
}

@Override
public void appendHoverText(ItemStack stack, @Nullable Level level, List<Component> tooltip, TooltipFlag isAdvanced) {
ClientTextUtil.appendItemInfoTooltip(stack.getItem(), tooltip);
}

@Override
public Optional<TooltipComponent> getTooltipImage(ItemStack stack) {
return Optional.of(new HrTooltipComponent());
}

@Override
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
return slotChanged;
}

@Override
public void registerControllers(AnimationData data) {
//IMPORTANT: transitionLengthTicks needs to be larger than 0, or else the controller.currentAnimation might be null and a NPE is thrown
AnimationController<BileSpitterItem> controller = new AnimationController<>(this, CONTROLLER_NAME, 1, event -> PlayState.CONTINUE);
controller.setAnimation(new AnimationBuilder().loop(Animation.IDLE.name()));
data.addAnimationController(controller);
}

@Override
public AnimationFactory getFactory() {
return animationFactory;
}

private void broadcastAnimation(ServerLevel level, Player player, ItemStack stack, Animation state) {
int stackId = GeckoLibUtil.guaranteeIDForStack(stack, level);
PacketDistributor.PacketTarget target = PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> player);
GeckoLibNetwork.syncAnimation(target, this, stackId, state.id);
}

@Override
public UseAnim getUseAnimation(ItemStack stack) {
return UseAnim.NONE;
}

@Override
public HumanoidModel.ArmPose getArmPose(Player player, InteractionHand usedHand, ItemStack stack) {
if (player.getUseItemRemainingTicks() > 0) {
return HumanoidModel.ArmPose.CROSSBOW_HOLD;
}
return HumanoidModel.ArmPose.ITEM;
}

@Override
public void onAnimationSync(int id, int state) {
if (Animation.CHARGE.is(state)) {
AnimationController<?> controller = GeckoLibUtil.getControllerForID(animationFactory, id, CONTROLLER_NAME);
controller.markNeedsReload(); //make sure animation can play more than once (animations are usually cached)
controller.setAnimation(new AnimationBuilder().addAnimation(Animation.CHARGE.name).loop(Animation.HOLD_CHARGE.name()));
} else if (Animation.IDLE.is(state)) {
AnimationController<?> controller = GeckoLibUtil.getControllerForID(animationFactory, id, CONTROLLER_NAME);
controller.setAnimation(new AnimationBuilder().loop(Animation.IDLE.name()));
}
}

protected record Animation(int id, String name) {
static Animation IDLE = new Animation(0, "bile_spitter.anim.idle");
static Animation CHARGE = new Animation(1, "bile_spitter.anim.charge");
static Animation HOLD_CHARGE = new Animation(2, "bile_spitter.anim.hold_charge");

public boolean is(int otherId) {
return otherId == id;
}
}

}
Loading

0 comments on commit 2fb2e71

Please sign in to comment.