From e6bb0c00e09d91e5c56087ad889ce752a6a961c8 Mon Sep 17 00:00:00 2001 From: Klemen Date: Wed, 2 Dec 2020 21:03:02 +0100 Subject: [PATCH] Added 1.16.4 living entity element support (#590) * Added 1.16.4 mob element support (#4) Signed-off-by: KlemenDEV * Made unit tests ignore AI tasks if not defined Signed-off-by: KlemenDEV * Added AI Tasks (#591) * Fixed AI tasks Signed-off-by: KlemenDEV Co-authored-by: Max094Reikeb <49318596+Max094Reikeb@users.noreply.github.com> --- .../aitasks/attack_action.java.ftl | 3 + .../aitasks/attack_entity.java.ftl | 4 + .../forge-1.16.4/aitasks/attack_fly.java.ftl | 57 ++ .../aitasks/attack_on_collide.java.ftl | 2 + .../aitasks/avoid_entity.java.ftl | 3 + .../aitasks/break_blocks.java.ftl | 4 + .../forge-1.16.4/aitasks/breed.java.ftl | 4 + .../forge-1.16.4/aitasks/doors_break.java.ftl | 4 + .../forge-1.16.4/aitasks/doors_close.java.ftl | 4 + .../forge-1.16.4/aitasks/doors_open.java.ftl | 4 + .../forge-1.16.4/aitasks/eat_grass.java.ftl | 2 + .../aitasks/fight_as_owner.java.ftl | 4 + .../forge-1.16.4/aitasks/fly.java.ftl | 16 + .../aitasks/follow_entity.java.ftl | 2 + .../aitasks/follow_item_in_hands.java.ftl | 3 + .../aitasks/follow_owner.java.ftl | 4 + .../aitasks/follow_parent.java.ftl | 4 + .../aitasks/leap_at_target.java.ftl | 2 + .../forge-1.16.4/aitasks/look_around.java.ftl | 2 + .../aitasks/move_indoors.java.ftl | 2 + .../aitasks/panic_when_attacked.java.ftl | 2 + .../aitasks/protect_owner.java.ftl | 4 + .../aitasks/restrict_sun.java.ftl | 2 + .../forge-1.16.4/aitasks/swim.java.ftl | 2 + .../aitasks/swim_in_water.java.ftl | 2 + .../forge-1.16.4/aitasks/wander.java.ftl | 2 + .../aitasks/wander_avoid_water.java.ftl | 2 + .../aitasks/watch_closest_entity.java.ftl | 2 + .../forge-1.16.4/mob.definition.yaml | 15 + .../templates/json/spawn_egg.json.ftl | 3 + .../forge-1.16.4/templates/mob.java.ftl | 920 ++++++++++++++++++ .../TestWorkspaceDataProvider.java | 22 +- 32 files changed, 1102 insertions(+), 6 deletions(-) create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_action.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_entity.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_fly.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_on_collide.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/avoid_entity.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/break_blocks.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/breed.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/doors_break.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/doors_close.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/doors_open.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/eat_grass.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/fight_as_owner.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/fly.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_entity.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_item_in_hands.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_owner.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_parent.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/leap_at_target.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/look_around.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/move_indoors.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/panic_when_attacked.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/protect_owner.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/restrict_sun.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/swim.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/swim_in_water.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/wander.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/wander_avoid_water.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/aitasks/watch_closest_entity.java.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/mob.definition.yaml create mode 100644 plugins/generator-1.16.4/forge-1.16.4/templates/json/spawn_egg.json.ftl create mode 100644 plugins/generator-1.16.4/forge-1.16.4/templates/mob.java.ftl diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_action.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_action.java.ftl new file mode 100644 index 00000000000..c277be0d8ec --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_action.java.ftl @@ -0,0 +1,3 @@ +<#include "aiconditions.java.ftl"> +this.targetSelector.addGoal(${customBlockIndex+1}, new HurtByTargetGoal(this)<@conditionCode field$condition/> +<#if field$callhelp?lower_case == "true">.setCallsForHelp(this.getClass())); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_entity.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_entity.java.ftl new file mode 100644 index 00000000000..453b56cedf9 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_entity.java.ftl @@ -0,0 +1,4 @@ +<#include "aiconditions.java.ftl"> +this.targetSelector.addGoal(${customBlockIndex+1}, + new NearestAttackableTargetGoal(this, ${generator.map(field$entity, "entities")}.class, ${field$insight?lower_case}, + ${field$nearby?lower_case})<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_fly.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_fly.java.ftl new file mode 100644 index 00000000000..cd692ba8e72 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_fly.java.ftl @@ -0,0 +1,57 @@ +<#-- @formatter:off --> +<#include "procedures.java.ftl"> +<#if field$condition?has_content> + <#assign conditions = generator.procedureNamesToObjects(field$condition)> +<#else> + <#assign conditions = ["", ""]> + +this.goalSelector.addGoal(${customBlockIndex+1}, new Goal() { + { + this.setMutexFlags(EnumSet.of(Goal.Flag.MOVE)); + } + + public boolean shouldExecute() { + if (CustomEntity.this.getAttackTarget() != null && !CustomEntity.this.getMoveHelper().isUpdating()) { + <#if hasCondition(conditions[0])> + double x = CustomEntity.this.getPosX(); + double y = CustomEntity.this.getPosY(); + double z = CustomEntity.this.getPosZ(); + Entity entity = CustomEntity.this; + + return <#if hasCondition(conditions[0])><@procedureOBJToConditionCode conditions[0]/><#else>true; + } else { + return false; + } + } + + @Override public boolean shouldContinueExecuting() { + <#if hasCondition(conditions[1])> + double x = CustomEntity.this.getPosX(); + double y = CustomEntity.this.getPosY(); + double z = CustomEntity.this.getPosZ(); + Entity entity = CustomEntity.this; + + return <#if hasCondition(conditions[1])><@procedureOBJToConditionCode conditions[1]/> && + CustomEntity.this.getMoveHelper().isUpdating() && CustomEntity.this.getAttackTarget() != null && CustomEntity.this.getAttackTarget().isAlive(); + } + + @Override public void startExecuting() { + LivingEntity livingentity = CustomEntity.this.getAttackTarget(); + Vector3d vec3d = livingentity.getEyePosition(1); + CustomEntity.this.moveController.setMoveTo(vec3d.x, vec3d.y, vec3d.z, ${field$speed}); + } + + @Override public void tick() { + LivingEntity livingentity = CustomEntity.this.getAttackTarget(); + if (CustomEntity.this.getBoundingBox().intersects(livingentity.getBoundingBox())) { + CustomEntity.this.attackEntityAsMob(livingentity); + } else { + double d0 = CustomEntity.this.getDistanceSq(livingentity); + if (d0 < ${field$radius}) { + Vector3d vec3d = livingentity.getEyePosition(1); + CustomEntity.this.moveController.setMoveTo(vec3d.x, vec3d.y, vec3d.z, ${field$speed}); + } + } + } +}); +<#-- @formatter:on --> \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_on_collide.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_on_collide.java.ftl new file mode 100644 index 00000000000..8009bc2e93a --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/attack_on_collide.java.ftl @@ -0,0 +1,2 @@ +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new MeleeAttackGoal(this, ${field$speed}, ${field$longmemory?lower_case})<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/avoid_entity.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/avoid_entity.java.ftl new file mode 100644 index 00000000000..306d0445a85 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/avoid_entity.java.ftl @@ -0,0 +1,3 @@ +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, + new AvoidEntityGoal(this, ${generator.map(field$entity, "entities")}.class, (float)${field$radius}, ${field$farspeed}, ${field$nearspeed})<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/break_blocks.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/break_blocks.java.ftl new file mode 100644 index 00000000000..6a38d27de4e --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/break_blocks.java.ftl @@ -0,0 +1,4 @@ +<#include "mcitems.ftl"> +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new BreakBlockGoal(${mappedBlockToBlockStateCode(input$block)}.getBlock(), + this, ${field$speed}, (int) ${field$y_max})<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/breed.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/breed.java.ftl new file mode 100644 index 00000000000..d569f032fb9 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/breed.java.ftl @@ -0,0 +1,4 @@ +<#if data.breedable> +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new BreedGoal(this, ${field$speed})<@conditionCode field$condition/>); + \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/doors_break.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/doors_break.java.ftl new file mode 100644 index 00000000000..b7423474c71 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/doors_break.java.ftl @@ -0,0 +1,4 @@ +<#if !data.flyingMob> +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new BreakDoorGoal(this, e -> true)<@conditionCode field$condition/>); + \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/doors_close.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/doors_close.java.ftl new file mode 100644 index 00000000000..960a24d9f7e --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/doors_close.java.ftl @@ -0,0 +1,4 @@ +<#if !data.flyingMob> +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new OpenDoorGoal(this, false)<@conditionCode field$condition/>); + \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/doors_open.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/doors_open.java.ftl new file mode 100644 index 00000000000..8d4bb7cfcb6 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/doors_open.java.ftl @@ -0,0 +1,4 @@ +<#if !data.flyingMob> +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new OpenDoorGoal(this, true)<@conditionCode field$condition/>); + \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/eat_grass.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/eat_grass.java.ftl new file mode 100644 index 00000000000..037a27593df --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/eat_grass.java.ftl @@ -0,0 +1,2 @@ +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new EatGrassGoal(this)<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/fight_as_owner.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/fight_as_owner.java.ftl new file mode 100644 index 00000000000..01b73090cc0 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/fight_as_owner.java.ftl @@ -0,0 +1,4 @@ +<#if data.tameable> +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new OwnerHurtTargetGoal(this)<@conditionCode field$condition/>); + \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/fly.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/fly.java.ftl new file mode 100644 index 00000000000..aed34513e69 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/fly.java.ftl @@ -0,0 +1,16 @@ +<#-- @formatter:off --> +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new RandomWalkingGoal(this, ${field$speed}, 20) { + + @Override protected Vector3d getPosition() { + Random random = CustomEntity.this.getRNG(); + double dir_x = CustomEntity.this.getPosX() + ((random.nextFloat() * 2 - 1) * 16); + double dir_y = CustomEntity.this.getPosY() + ((random.nextFloat() * 2 - 1) * 16); + double dir_z = CustomEntity.this.getPosZ() + ((random.nextFloat() * 2 - 1) * 16); + return new Vector3d(dir_x, dir_y, dir_z); + } + + <@conditionCode field$condition false/> + +}); +<#-- @formatter:on --> \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_entity.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_entity.java.ftl new file mode 100644 index 00000000000..252854482d1 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_entity.java.ftl @@ -0,0 +1,2 @@ +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new FollowMobGoal(this, (float)${field$speed}, ${field$maxrange}, ${field$followarea})<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_item_in_hands.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_item_in_hands.java.ftl new file mode 100644 index 00000000000..77ad01597ce --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_item_in_hands.java.ftl @@ -0,0 +1,3 @@ +<#include "mcitems.ftl"> +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new TemptGoal(this, ${field$speed}, Ingredient.fromItems(${mappedMCItemToItem(input$item)}), ${field$scared?lower_case})<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_owner.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_owner.java.ftl new file mode 100644 index 00000000000..bec6fad4875 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_owner.java.ftl @@ -0,0 +1,4 @@ +<#if data.tameable> +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new FollowOwnerGoal(this, ${field$speed}, (float) ${field$min_distance}, (float) ${field$max_distance}, false)<@conditionCode field$condition/>); + \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_parent.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_parent.java.ftl new file mode 100644 index 00000000000..2d81b8eb7d3 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/follow_parent.java.ftl @@ -0,0 +1,4 @@ +<#if data.breedable> +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new FollowParentGoal(this, ${field$speed})<@conditionCode field$condition/>); + \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/leap_at_target.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/leap_at_target.java.ftl new file mode 100644 index 00000000000..bdfd0bcf9e5 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/leap_at_target.java.ftl @@ -0,0 +1,2 @@ +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new LeapAtTargetGoal(this, (float)${field$speed})<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/look_around.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/look_around.java.ftl new file mode 100644 index 00000000000..9ff354651a9 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/look_around.java.ftl @@ -0,0 +1,2 @@ +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new LookRandomlyGoal(this)<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/move_indoors.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/move_indoors.java.ftl new file mode 100644 index 00000000000..34b2253eae4 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/move_indoors.java.ftl @@ -0,0 +1,2 @@ +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new ReturnToVillageGoal(this, 0.6, false)<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/panic_when_attacked.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/panic_when_attacked.java.ftl new file mode 100644 index 00000000000..bfa3a687591 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/panic_when_attacked.java.ftl @@ -0,0 +1,2 @@ +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1},new PanicGoal(this, ${field$speed})<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/protect_owner.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/protect_owner.java.ftl new file mode 100644 index 00000000000..05497919292 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/protect_owner.java.ftl @@ -0,0 +1,4 @@ +<#if data.tameable> +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new OwnerHurtByTargetGoal(this)<@conditionCode field$condition/>); + \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/restrict_sun.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/restrict_sun.java.ftl new file mode 100644 index 00000000000..33ff6badb1d --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/restrict_sun.java.ftl @@ -0,0 +1,2 @@ +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new RestrictSunGoal(this)<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/swim.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/swim.java.ftl new file mode 100644 index 00000000000..6c86516666b --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/swim.java.ftl @@ -0,0 +1,2 @@ +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new RandomSwimmingGoal(this, ${field$speed}, 40)<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/swim_in_water.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/swim_in_water.java.ftl new file mode 100644 index 00000000000..03d8fcb404c --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/swim_in_water.java.ftl @@ -0,0 +1,2 @@ +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new SwimGoal(this)<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/wander.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/wander.java.ftl new file mode 100644 index 00000000000..12c6894b871 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/wander.java.ftl @@ -0,0 +1,2 @@ +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new RandomWalkingGoal(this, ${field$speed})<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/wander_avoid_water.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/wander_avoid_water.java.ftl new file mode 100644 index 00000000000..24a0a083114 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/wander_avoid_water.java.ftl @@ -0,0 +1,2 @@ +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new WaterAvoidingRandomWalkingGoal(this, ${field$speed})<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/aitasks/watch_closest_entity.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/aitasks/watch_closest_entity.java.ftl new file mode 100644 index 00000000000..eef2619fa5b --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/aitasks/watch_closest_entity.java.ftl @@ -0,0 +1,2 @@ +<#include "aiconditions.java.ftl"> +this.goalSelector.addGoal(${customBlockIndex+1}, new LookAtGoal(this, ${generator.map(field$entity, "entities")}.class,(float)${field$radius})<@conditionCode field$condition/>); \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/mob.definition.yaml b/plugins/generator-1.16.4/forge-1.16.4/mob.definition.yaml new file mode 100644 index 00000000000..89146fc9edc --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/mob.definition.yaml @@ -0,0 +1,15 @@ +templates: + - template: mob.java.ftl + name: "@SRCROOT/@BASEPACKAGEPATH/entity/@NAMEEntity.java" + - template: json/spawn_egg.json.ftl + writer: json + name: "@MODASSETSROOT/models/item/@registryname_spawn_egg.json" + condition: hasSpawnEgg + deleteWhenConditionFalse: true + +localizationkeys: + - key: item.@modid.@registryname_spawn_egg + mapto: mobName + suffix: " Spawn Egg" + - key: entity.@modid.@registryname + mapto: mobName \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/templates/json/spawn_egg.json.ftl b/plugins/generator-1.16.4/forge-1.16.4/templates/json/spawn_egg.json.ftl new file mode 100644 index 00000000000..2cba2707e29 --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/templates/json/spawn_egg.json.ftl @@ -0,0 +1,3 @@ +{ + "parent": "item/template_spawn_egg" +} \ No newline at end of file diff --git a/plugins/generator-1.16.4/forge-1.16.4/templates/mob.java.ftl b/plugins/generator-1.16.4/forge-1.16.4/templates/mob.java.ftl new file mode 100644 index 00000000000..a4c02599fba --- /dev/null +++ b/plugins/generator-1.16.4/forge-1.16.4/templates/mob.java.ftl @@ -0,0 +1,920 @@ +<#-- + # MCreator (https://mcreator.net/) + # Copyright (C) 2020 Pylo and contributors + # + # This program is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation, either version 3 of the License, or + # (at your option) any later version. + # + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + # + # Additional permission for code generator templates (*.ftl files) + # + # As a special exception, you may create a larger work that contains part or + # all of the MCreator code generator templates (*.ftl files) and distribute + # that work under terms of your choice, so long as that work isn't itself a + # template for code generation. Alternatively, if you modify or redistribute + # the template itself, you may (at your option) remove this special exception, + # which will cause the template and the resulting code generator output files + # to be licensed under the GNU General Public License without this special + # exception. +--> + +<#-- @formatter:off --> +<#include "mcitems.ftl"> +<#include "procedures.java.ftl"> +<#include "particles.java.ftl"> + +package ${package}.entity; + +import net.minecraft.block.material.Material; + +@${JavaModName}Elements.ModElement.Tag public class ${name}Entity extends ${JavaModName}Elements.ModElement { + + public static EntityType entity = null; + + <#if data.ranged && data.rangedItemType == "Default item"> + @ObjectHolder("${modid}:entitybullet${registryname}") + public static final EntityType arrow = null; + + + public ${name}Entity (${JavaModName}Elements instance) { + super(instance, ${data.getModElement().getSortID()}); + + FMLJavaModLoadingContext.get().getModEventBus().register(new ModelRegisterHandler()); + + <#if data.spawnThisMob> + MinecraftForge.EVENT_BUS.register(this); + + } + + + + @Override public void initElements() { + entity = (EntityType.Builder.create(CustomEntity::new, ${generator.map(data.mobSpawningType, "mobspawntypes")}) + .setShouldReceiveVelocityUpdates(true).setTrackingRange(${data.trackingRange}).setUpdateInterval(3).setCustomClientFactory(CustomEntity::new) + <#if data.immuneToFire>.immuneToFire().size(${data.modelWidth}f, ${data.modelHeight}f)) + .build("${registryname}").setRegistryName("${registryname}"); + + elements.entities.add(() -> entity); + + <#if data.hasSpawnEgg> + elements.items.add(() -> new SpawnEggItem(entity, ${data.spawnEggBaseColor.getRGB()}, ${data.spawnEggDotColor.getRGB()}, + new Item.Properties()<#if data.creativeTab??>.group(${data.creativeTab})<#else>.group(ItemGroup.MISC)) + .setRegistryName("${registryname}_spawn_egg")); + + + <#if data.ranged && data.rangedItemType == "Default item"> + elements.entities.add(() -> (EntityType.Builder.create(ArrowCustomEntity::new, EntityClassification.MISC) + .setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(1) + .setCustomClientFactory(ArrowCustomEntity::new).size(0.5f, 0.5f)).build("entitybullet${registryname}").setRegistryName("entitybullet${registryname}")); + + } + + <#if data.spawnThisMob> + @SubscribeEvent public void addFeatureToBiomes(BiomeLoadingEvent event) { + <#if data.restrictionBiomes?has_content> + boolean biomeCriteria = false; + <#list data.restrictionBiomes as restrictionBiome> + <#if restrictionBiome.canProperlyMap()> + if (new ResourceLocation("${restrictionBiome}").equals(event.getName())) + biomeCriteria = true; + + + if (!biomeCriteria) + return; + + + event.getSpawns().getSpawner(${generator.map(data.mobSpawningType, "mobspawntypes")}).add(new MobSpawnInfo.Spawners(entity, ${data.spawningProbability}, + ${data.minNumberOfMobsPerGroup}, ${data.maxNumberOfMobsPerGroup})); + } + + + @Override public void init(FMLCommonSetupEvent event) { + DeferredWorkQueue.runLater(this::setupAttributes); + + <#if data.spawnThisMob> + <#if data.mobSpawningType == "creature"> + EntitySpawnPlacementRegistry.register(entity, EntitySpawnPlacementRegistry.PlacementType.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, + <#if hasCondition(data.spawningCondition)> + (entityType, world, reason, pos, random) -> { + int x = pos.getX(); + int y = pos.getY(); + int z = pos.getZ(); + return <@procedureOBJToConditionCode data.spawningCondition/>; + } + <#else> + (entityType, world, reason, pos, random) -> (world.getBlockState(pos.down()).getMaterial() == Material.ORGANIC && world.getLightSubtracted(pos, 0) > 8) + + ); + <#elseif data.mobSpawningType == "ambient"> + EntitySpawnPlacementRegistry.register(entity, EntitySpawnPlacementRegistry.PlacementType.NO_RESTRICTIONS, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, + <#if hasCondition(data.spawningCondition)> + (entityType, world, reason, pos, random) -> { + int x = pos.getX(); + int y = pos.getY(); + int z = pos.getZ(); + return <@procedureOBJToConditionCode data.spawningCondition/>; + } + <#else> + MobEntity::canSpawnOn + + ); + <#elseif data.mobSpawningType == "waterCreature"> + EntitySpawnPlacementRegistry.register(entity, EntitySpawnPlacementRegistry.PlacementType.IN_WATER, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, + <#if hasCondition(data.spawningCondition)> + (entityType, world, reason, pos, random) -> { + int x = pos.getX(); + int y = pos.getY(); + int z = pos.getZ(); + return <@procedureOBJToConditionCode data.spawningCondition/>; + } + <#else> + SquidEntity::func_223365_b + + ); + <#else> + EntitySpawnPlacementRegistry.register(entity, EntitySpawnPlacementRegistry.PlacementType.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, + <#if hasCondition(data.spawningCondition)> + (entityType, world, reason, pos, random) -> { + int x = pos.getX(); + int y = pos.getY(); + int z = pos.getZ(); + return <@procedureOBJToConditionCode data.spawningCondition/>; + } + <#else> + MonsterEntity::canMonsterSpawn + + ); + + + + <#if data.spawnInDungeons> + DungeonHooks.addDungeonMob(entity, 180); + + } + + private static class ModelRegisterHandler { + + @SubscribeEvent @OnlyIn(Dist.CLIENT) public void registerModels(ModelRegistryEvent event) { + <#if data.mobModelName == "Chicken"> + RenderingRegistry.registerEntityRenderingHandler(entity, renderManager -> new MobRenderer(renderManager, new ChickenModel(), ${data.modelShadowSize}f) { + <#if data.mobModelGlowTexture?has_content>{ this.addLayer(new GlowingLayer<>(this)); } + @Override public ResourceLocation getEntityTexture(Entity entity) { return new ResourceLocation("${modid}:textures/${data.mobModelTexture}"); } + }); + <#elseif data.mobModelName == "Cow"> + RenderingRegistry.registerEntityRenderingHandler(entity, renderManager -> new MobRenderer(renderManager, new CowModel(), ${data.modelShadowSize}f) { + <#if data.mobModelGlowTexture?has_content>{ this.addLayer(new GlowingLayer<>(this)); } + @Override public ResourceLocation getEntityTexture(Entity entity) { return new ResourceLocation("${modid}:textures/${data.mobModelTexture}"); } + }); + <#elseif data.mobModelName == "Creeper"> + RenderingRegistry.registerEntityRenderingHandler(entity, renderManager -> new MobRenderer(renderManager, new CreeperModel(), ${data.modelShadowSize}f) { + <#if data.mobModelGlowTexture?has_content>{ this.addLayer(new GlowingLayer<>(this)); } + @Override public ResourceLocation getEntityTexture(Entity entity) { return new ResourceLocation("${modid}:textures/${data.mobModelTexture}"); } + }); + <#elseif data.mobModelName == "Ghast"> + RenderingRegistry.registerEntityRenderingHandler(entity, renderManager -> new MobRenderer(renderManager, new GhastModel(), ${data.modelShadowSize}f) { + <#if data.mobModelGlowTexture?has_content>{ this.addLayer(new GlowingLayer<>(this)); } + @Override public ResourceLocation getEntityTexture(Entity entity) { return new ResourceLocation("${modid}:textures/${data.mobModelTexture}"); } + }); + <#elseif data.mobModelName == "Pig"> + RenderingRegistry.registerEntityRenderingHandler(entity, renderManager -> new MobRenderer(renderManager, new PigModel(), ${data.modelShadowSize}f) { + <#if data.mobModelGlowTexture?has_content>{ this.addLayer(new GlowingLayer<>(this)); } + @Override public ResourceLocation getEntityTexture(Entity entity) { return new ResourceLocation("${modid}:textures/${data.mobModelTexture}"); } + }); + <#elseif data.mobModelName == "Slime"> + RenderingRegistry.registerEntityRenderingHandler(entity, renderManager -> new MobRenderer(renderManager, new SlimeModel(0), ${data.modelShadowSize}f) { + <#if data.mobModelGlowTexture?has_content>{ this.addLayer(new GlowingLayer<>(this)); } + @Override public ResourceLocation getEntityTexture(Entity entity) { return new ResourceLocation("${modid}:textures/${data.mobModelTexture}"); } + }); + <#elseif data.mobModelName == "Spider"> + RenderingRegistry.registerEntityRenderingHandler(entity, renderManager -> new MobRenderer(renderManager, new SpiderModel(), ${data.modelShadowSize}f) { + <#if data.mobModelGlowTexture?has_content>{ this.addLayer(new GlowingLayer<>(this)); } + @Override public ResourceLocation getEntityTexture(Entity entity) { return new ResourceLocation("${modid}:textures/${data.mobModelTexture}"); } + }); + <#elseif data.mobModelName == "Villager"> + RenderingRegistry.registerEntityRenderingHandler(entity, renderManager -> new MobRenderer(renderManager, new VillagerModel(0), ${data.modelShadowSize}f) { + <#if data.mobModelGlowTexture?has_content>{ this.addLayer(new GlowingLayer<>(this)); } + @Override public ResourceLocation getEntityTexture(Entity entity) { return new ResourceLocation("${modid}:textures/${data.mobModelTexture}"); } + }); + <#elseif data.mobModelName == "Silverfish"> + RenderingRegistry.registerEntityRenderingHandler(entity, renderManager -> new MobRenderer(renderManager, new SilverfishModel(), ${data.modelShadowSize}f) { + <#if data.mobModelGlowTexture?has_content>{ this.addLayer(new GlowingLayer<>(this)); } + @Override public ResourceLocation getEntityTexture(Entity entity) { return new ResourceLocation("${modid}:textures/${data.mobModelTexture}"); } + }); + <#elseif !data.isBuiltInModel()> + RenderingRegistry.registerEntityRenderingHandler(entity, renderManager -> { + return new MobRenderer(renderManager, new ${data.mobModelName}(), ${data.modelShadowSize}f) { + <#if data.mobModelGlowTexture?has_content>{ this.addLayer(new GlowingLayer<>(this)); } + @Override public ResourceLocation getEntityTexture(Entity entity) { return new ResourceLocation("${modid}:textures/${data.mobModelTexture}"); } + }; + }); + <#else> + RenderingRegistry.registerEntityRenderingHandler(entity, renderManager -> { + BipedRenderer customRender = new BipedRenderer(renderManager, new BipedModel(0), ${data.modelShadowSize}f) { + @Override public ResourceLocation getEntityTexture(Entity entity) { return new ResourceLocation("${modid}:textures/${data.mobModelTexture}"); } + }; + customRender.addLayer(new BipedArmorLayer(customRender, new BipedModel(0.5f), new BipedModel(1))); + <#if data.mobModelGlowTexture?has_content>customRender.addLayer(new GlowingLayer<>(customRender)); + return customRender; + }); + + + + <#if data.ranged && data.rangedItemType == "Default item"> + RenderingRegistry.registerEntityRenderingHandler(arrow, renderManager -> new SpriteRenderer(renderManager, Minecraft.getInstance().getItemRenderer())); + + } + } + + private void setupAttributes() { + AttributeModifierMap.MutableAttribute ammma = MobEntity.func_233666_p_(); + ammma = ammma.createMutableAttribute(Attributes.MOVEMENT_SPEED, ${data.movementSpeed}); + ammma = ammma.createMutableAttribute(Attributes.MAX_HEALTH, ${data.health}); + ammma = ammma.createMutableAttribute(Attributes.ARMOR, ${data.armorBaseValue}); + ammma = ammma.createMutableAttribute(Attributes.ATTACK_DAMAGE, ${data.attackStrength}); + + <#if (data.knockbackResistance > 0)> + ammma = ammma.createMutableAttribute(Attributes.KNOCKBACK_RESISTANCE, ${data.knockbackResistance}); + + + <#if (data.attackKnockback > 0)> + ammma = ammma.createMutableAttribute(Attributes.ATTACK_KNOCKBACK, ${data.attackKnockback}); + + + <#if data.flyingMob> + ammma = ammma.createMutableAttribute(Attributes.FLYING_SPEED, ${data.movementSpeed}); + + + <#if data.waterMob> + ammma = ammma.createMutableAttribute(ForgeMod.SWIM_SPEED.get(), ${data.movementSpeed}); + + + GlobalEntityTypeAttributes.put(entity, ammma.create()); + } + + <#assign extendsClass = "Creature"> + <#if data.aiBase != "(none)" > + <#assign extendsClass = data.aiBase> + <#else> + <#assign extendsClass = data.mobBehaviourType.replace("Mob", "Monster")> + + + <#if data.breedable> + <#assign extendsClass = "Animal"> + + + <#if data.tameable> + <#assign extendsClass = "Tameable"> + + + public static class CustomEntity extends ${extendsClass}Entity<#if data.ranged> implements IRangedAttackMob { + + public CustomEntity(FMLPlayMessages.SpawnEntity packet, World world) { + this(entity, world); + } + + public CustomEntity(EntityType type, World world) { + super(type, world); + experienceValue = ${data.xpAmount}; + setNoAI(${(!data.hasAI)}); + + <#if data.mobLabel?has_content > + setCustomName(new StringTextComponent("${data.mobLabel}")); + setCustomNameVisible(true); + + + <#if !data.doesDespawnWhenIdle> + enablePersistence(); + + + <#if !data.equipmentMainHand.isEmpty()> + this.setItemStackToSlot(EquipmentSlotType.MAINHAND, ${mappedMCItemToItemStackCode(data.equipmentMainHand, 1)}); + + <#if !data.equipmentOffHand.isEmpty()> + this.setItemStackToSlot(EquipmentSlotType.OFFHAND, ${mappedMCItemToItemStackCode(data.equipmentOffHand, 1)}); + + <#if !data.equipmentHelmet.isEmpty()> + this.setItemStackToSlot(EquipmentSlotType.HEAD, ${mappedMCItemToItemStackCode(data.equipmentHelmet, 1)}); + + <#if !data.equipmentBody.isEmpty()> + this.setItemStackToSlot(EquipmentSlotType.CHEST, ${mappedMCItemToItemStackCode(data.equipmentBody, 1)}); + + <#if !data.equipmentLeggings.isEmpty()> + this.setItemStackToSlot( + EquipmentSlotType.LEGS, ${mappedMCItemToItemStackCode(data.equipmentLeggings, 1)}); + + <#if !data.equipmentBoots.isEmpty()> + this.setItemStackToSlot(EquipmentSlotType.FEET, ${mappedMCItemToItemStackCode(data.equipmentBoots, 1)}); + + + <#if data.flyingMob> + this.moveController = new FlyingMovementController(this, 10, true); + this.navigator = new FlyingPathNavigator(this, this.world); + <#elseif data.waterMob> + this.moveController = new MovementController(this) { + @Override public void tick() { + if (CustomEntity.this.areEyesInFluid(FluidTags.WATER)) + CustomEntity.this.setMotion(CustomEntity.this.getMotion().add(0, 0.005, 0)); + + if (this.action == MovementController.Action.MOVE_TO && !CustomEntity.this.getNavigator().noPath()) { + double dx = this.posX - CustomEntity.this.getPosX(); + double dy = this.posY - CustomEntity.this.getPosY(); + double dz = this.posZ - CustomEntity.this.getPosZ(); + dy = dy / (double)MathHelper.sqrt(dx * dx + dy * dy + dz * dz); + CustomEntity.this.rotationYaw = this.limitAngle(CustomEntity.this.rotationYaw, + (float)(MathHelper.atan2(dz, dx) * (double) (180 / (float) Math.PI)) - 90, 90); + CustomEntity.this.renderYawOffset = CustomEntity.this.rotationYaw; + CustomEntity.this.setAIMoveSpeed(MathHelper.lerp(0.125f, CustomEntity.this.getAIMoveSpeed(), + (float)(this.speed * CustomEntity.this.getAttributeValue(Attributes.MOVEMENT_SPEED)))); + CustomEntity.this.setMotion(CustomEntity.this.getMotion().add(0, CustomEntity.this.getAIMoveSpeed() * dy * 0.1, 0)); + } else { + CustomEntity.this.setAIMoveSpeed(0); + } + } + }; + this.navigator = new SwimmerPathNavigator(this, this.world); + + } + + @Override public IPacket createSpawnPacket() { + return NetworkHooks.getEntitySpawningPacket(this); + } + + <#if data.hasAI> + @Override protected void registerGoals() { + super.registerGoals(); + + <#if aicode??> + ${aicode} + + + <#if data.ranged> + this.goalSelector.addGoal(1, new RangedAttackGoal(this, 1.25, 20, 10) { + @Override public boolean shouldContinueExecuting() { + return this.shouldExecute(); + } + }); + + } + + + @Override public CreatureAttribute getCreatureAttribute() { + return CreatureAttribute.${data.mobCreatureType}; + } + + <#if !data.doesDespawnWhenIdle> + @Override public boolean canDespawn(double distanceToClosestPlayer) { + return false; + } + + + <#if data.mountedYOffset != 0> + @Override public double getMountedYOffset() { + return super.getMountedYOffset() + ${data.mountedYOffset}; + } + + + <#if !data.mobDrop.isEmpty()> + protected void dropSpecialItems(DamageSource source, int looting, boolean recentlyHitIn) { + super.dropSpecialItems(source, looting, recentlyHitIn); + this.entityDropItem(${mappedMCItemToItemStackCode(data.mobDrop, 1)}); + } + + + <#if data.livingSound.getMappedValue()?has_content> + @Override public net.minecraft.util.SoundEvent getAmbientSound() { + return (net.minecraft.util.SoundEvent) ForgeRegistries.SOUND_EVENTS.getValue(new ResourceLocation("${data.livingSound}")); + } + + + <#if data.stepSound?has_content && data.stepSound.getMappedValue()?has_content> + @Override public void playStepSound(BlockPos pos, BlockState blockIn) { + this.playSound((net.minecraft.util.SoundEvent) ForgeRegistries.SOUND_EVENTS.getValue(new ResourceLocation("${data.stepSound}")), 0.15f, 1); + } + + + @Override public net.minecraft.util.SoundEvent getHurtSound(DamageSource ds) { + return (net.minecraft.util.SoundEvent) ForgeRegistries.SOUND_EVENTS.getValue(new ResourceLocation("${data.hurtSound}")); + } + + @Override public net.minecraft.util.SoundEvent getDeathSound() { + return (net.minecraft.util.SoundEvent) ForgeRegistries.SOUND_EVENTS.getValue(new ResourceLocation("${data.deathSound}")); + } + + <#if hasProcedure(data.onStruckByLightning)> + @Override public void func_241841_a(ServerWorld serverWorld, LightningBoltEntity entityLightningBolt) { + super.func_241841_a(serverWorld, entityLightningBolt); + double x = this.getPosX(); + double y = this.getPosY(); + double z = this.getPosZ(); + Entity entity = this; + <@procedureOBJToCode data.onStruckByLightning/> + } + + + <#if hasProcedure(data.whenMobFalls) || data.flyingMob> + @Override public boolean onLivingFall(float l, float d) { + <#if hasProcedure(data.whenMobFalls) > + double x = this.getPosX(); + double y = this.getPosY(); + double z = this.getPosZ(); + Entity entity = this; + <@procedureOBJToCode data.whenMobFalls/> + + + <#if data.flyingMob > + return false; + <#else> + return super.onLivingFall(l, d); + + } + + + <#if hasProcedure(data.whenMobIsHurt) || data.immuneToArrows || data.immuneToFallDamage + || data.immuneToCactus || data.immuneToDrowning || data.immuneToLightning || data.immuneToPotions || data.immuneToPlayer> + @Override public boolean attackEntityFrom(DamageSource source, float amount) { + <#if hasProcedure(data.whenMobIsHurt)> + double x = this.getPosX(); + double y = this.getPosY(); + double z = this.getPosZ(); + Entity entity = this; + Entity sourceentity = source.getTrueSource(); + <@procedureOBJToCode data.whenMobIsHurt/> + + <#if data.immuneToArrows> + if (source.getImmediateSource() instanceof ArrowEntity) + return false; + + <#if data.immuneToPlayer> + if (source.getImmediateSource() instanceof PlayerEntity) + return false; + + <#if data.immuneToPotions> + if (source.getImmediateSource() instanceof PotionEntity) + return false; + + <#if data.immuneToFallDamage> + if (source == DamageSource.FALL) + return false; + + <#if data.immuneToCactus> + if (source == DamageSource.CACTUS) + return false; + + <#if data.immuneToDrowning> + if (source == DamageSource.DROWN) + return false; + + <#if data.immuneToLightning> + if (source == DamageSource.LIGHTNING_BOLT) + return false; + + return super.attackEntityFrom(source, amount); + } + + + <#if hasProcedure(data.whenMobDies)> + @Override public void onDeath(DamageSource source) { + super.onDeath(source); + double x = this.getPosX(); + double y = this.getPosY(); + double z = this.getPosZ(); + Entity sourceentity = source.getTrueSource(); + Entity entity = this; + <@procedureOBJToCode data.whenMobDies/> + } + + + <#if hasProcedure(data.onInitialSpawn)> + @Override public ILivingEntityData onInitialSpawn(IServerWorld world, DifficultyInstance difficulty, + SpawnReason reason, @Nullable ILivingEntityData livingdata, @Nullable CompoundNBT tag) { + ILivingEntityData retval = super.onInitialSpawn(world, difficulty, reason, livingdata, tag); + double x = this.getPosX(); + double y = this.getPosY(); + double z = this.getPosZ(); + Entity entity = this; + <@procedureOBJToCode data.onInitialSpawn/> + return retval; + } + + + <#if data.guiBoundTo?has_content && data.guiBoundTo != ""> + private final ItemStackHandler inventory = new ItemStackHandler(${data.inventorySize}) { + @Override public int getSlotLimit(int slot) { + return ${data.inventoryStackSize}; + } + }; + + private final CombinedInvWrapper combined = new CombinedInvWrapper(inventory, new EntityHandsInvWrapper(this), new EntityArmorInvWrapper(this)); + + @Override public LazyOptional getCapability(@Nonnull Capability capability, @Nullable Direction side) { + if (this.isAlive() && capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY && side == null) + return LazyOptional.of(() -> combined).cast(); + + return super.getCapability(capability, side); + } + + @Override protected void dropInventory() { + super.dropInventory(); + for(int i = 0; i < inventory.getSlots(); ++i) { + ItemStack itemstack = inventory.getStackInSlot(i); + if (!itemstack.isEmpty() && !EnchantmentHelper.hasVanishingCurse(itemstack)) { + this.entityDropItem(itemstack); + } + } + } + + @Override public void writeAdditional(CompoundNBT compound) { + super.writeAdditional(compound); + compound.put("InventoryCustom", inventory.serializeNBT()); + } + + @Override public void readAdditional(CompoundNBT compound) { + super.readAdditional(compound); + INBT inventoryCustom = compound.get("InventoryCustom"); + if(inventoryCustom instanceof CompoundNBT) + inventory.deserializeNBT((CompoundNBT) inventoryCustom); + } + + + <#if hasProcedure(data.onRightClickedOn) || data.ridable || data.tameable || (data.guiBoundTo?has_content && data.guiBoundTo != "")> + @Override public ActionResultType func_230254_b_(PlayerEntity sourceentity, Hand hand) { + ItemStack itemstack = sourceentity.getHeldItem(hand); + ActionResultType retval = ActionResultType.func_233537_a_(this.world.isRemote); + + <#if data.guiBoundTo?has_content && data.guiBoundTo != ""> + <#if data.ridable> + if (sourceentity.isSecondaryUseActive()) { + + if(sourceentity instanceof ServerPlayerEntity) { + NetworkHooks.openGui((ServerPlayerEntity) sourceentity, new INamedContainerProvider() { + + @Override public ITextComponent getDisplayName() { + return new StringTextComponent("${data.mobName}"); + } + + @Override public Container createMenu(int id, PlayerInventory inventory, PlayerEntity player) { + PacketBuffer packetBuffer = new PacketBuffer(Unpooled.buffer()); + packetBuffer.writeBlockPos(new BlockPos(sourceentity.getPosition())); + packetBuffer.writeByte(0); + packetBuffer.writeVarInt(CustomEntity.this.getEntityId()); + return new ${(data.guiBoundTo)}Gui.GuiContainerMod(id, inventory, packetBuffer); + } + + }, buf -> { + buf.writeBlockPos(new BlockPos(sourceentity.getPosition())); + buf.writeByte(0); + buf.writeVarInt(this.getEntityId()); + }); + } + <#if data.ridable> + return ActionResultType.func_233537_a_(this.world.isRemote); + } + + + + <#if data.tameable> + Item item = itemstack.getItem(); + if (itemstack.getItem() instanceof SpawnEggItem) { + retval = super.func_230254_b_(sourceentity, hand); + } else if (this.world.isRemote) { + retval = (this.isTamed() && this.isOwner(sourceentity) || this.isBreedingItem(itemstack)) + ? ActionResultType.func_233537_a_(this.world.isRemote) : ActionResultType.PASS; + } else { + if (this.isTamed()) { + if (this.isOwner(sourceentity)) { + if (item.isFood() && this.isBreedingItem(itemstack) && this.getHealth() < this.getMaxHealth()) { + this.consumeItemFromStack(sourceentity, itemstack); + this.heal((float)item.getFood().getHealing()); + retval = ActionResultType.func_233537_a_(this.world.isRemote); + } else if (this.isBreedingItem(itemstack) && this.getHealth() < this.getMaxHealth()) { + this.consumeItemFromStack(sourceentity, itemstack); + this.heal(4); + retval = ActionResultType.func_233537_a_(this.world.isRemote); + } else { + retval = super.func_230254_b_(sourceentity, hand); + } + } + } else if (this.isBreedingItem(itemstack)) { + this.consumeItemFromStack(sourceentity, itemstack); + if (this.rand.nextInt(3) == 0 && !net.minecraftforge.event.ForgeEventFactory.onAnimalTame(this, sourceentity)) { + this.setTamedBy(sourceentity); + this.world.setEntityState(this, (byte) 7); + } else { + this.world.setEntityState(this, (byte) 6); + } + + this.enablePersistence(); + retval = ActionResultType.func_233537_a_(this.world.isRemote); + } else { + retval = super.func_230254_b_(sourceentity, hand); + if (retval == ActionResultType.SUCCESS || retval == ActionResultType.CONSUME) + this.enablePersistence(); + } + } + <#else> + super.func_230254_b_(sourceentity, hand); + + + <#if data.ridable> + sourceentity.startRiding(this); + + + double x = this.getPosX(); + double y = this.getPosY(); + double z = this.getPosZ(); + Entity entity = this; + <@procedureOBJToCode data.onRightClickedOn/> + return retval; + } + + + <#if hasProcedure(data.whenThisMobKillsAnother)> + @Override public void awardKillScore(Entity entity, int score, DamageSource damageSource) { + super.awardKillScore(entity, score, damageSource); + double x = this.getPosX(); + double y = this.getPosY(); + double z = this.getPosZ(); + Entity sourceentity = this; + <@procedureOBJToCode data.whenThisMobKillsAnother/> + } + + + <#if hasProcedure(data.onMobTickUpdate)> + @Override public void baseTick() { + super.baseTick(); + double x = this.getPosX(); + double y = this.getPosY(); + double z = this.getPosZ(); + Entity entity = this; + <@procedureOBJToCode data.onMobTickUpdate/> + } + + + <#if hasProcedure(data.onPlayerCollidesWith)> + @Override public void onCollideWithPlayer(PlayerEntity sourceentity) { + super.onCollideWithPlayer(sourceentity); + Entity entity = this; + double x = this.getPosX(); + double y = this.getPosY(); + double z = this.getPosZ(); + <@procedureOBJToCode data.onPlayerCollidesWith/> + } + + + <#if data.ranged> + public void attackEntityWithRangedAttack(LivingEntity target, float flval) { + <#if data.rangedItemType == "Default item"> + ArrowCustomEntity entityarrow = new ArrowCustomEntity(arrow, this, this.world); + double d0 = target.getPosY() + (double) target.getEyeHeight() - 1.1; + double d1 = target.getPosX() - this.getPosX(); + double d3 = target.getPosZ() - this.getPosZ(); + entityarrow.shoot(d1, d0 - entityarrow.getPosY() + (double) MathHelper.sqrt(d1 * d1 + d3 * d3) * 0.2F, d3, 1.6F, 12.0F); + world.addEntity(entityarrow); + <#else> + ${data.rangedItemType}Item.shoot(this, target); + + } + + + <#if data.breedable> + @Override public AgeableEntity func_241840_a(ServerWorld serverWorld, AgeableEntity ageable) { + CustomEntity retval = (CustomEntity) entity.create(serverWorld); + retval.onInitialSpawn(serverWorld, serverWorld.getDifficultyForLocation(new BlockPos(retval.getPosition())), SpawnReason.BREEDING, (ILivingEntityData)null, (CompoundNBT)null); + return retval; + } + + @Override public boolean isBreedingItem(ItemStack stack) { + if (stack == null) + return false; + + <#list data.breedTriggerItems as breedTriggerItem> + if (${mappedMCItemToItemStackCode(breedTriggerItem,1)}.getItem() == stack.getItem()) + return true; + + + return false; + } + + + <#if data.waterMob> + @Override public boolean canBreatheUnderwater() { + return true; + } + + @Override public boolean isNotColliding(IWorldReader worldreader) { + return worldreader.checkNoEntityCollision(this, VoxelShapes.create(this.getBoundingBox())); + } + + @Override public boolean isPushedByWater() { + return false; + } + + + <#if data.disableCollisions> + @Override public boolean canBeCollidedWith() { + return false; + } + + + <#if data.isBoss> + @Override public boolean isNonBoss() { + return false; + } + + private final ServerBossInfo bossInfo = new ServerBossInfo(this.getDisplayName(), + BossInfo.Color.${data.bossBarColor}, BossInfo.Overlay.${data.bossBarType}); + + @Override public void addTrackingPlayer(ServerPlayerEntity player) { + super.addTrackingPlayer(player); + this.bossInfo.addPlayer(player); + } + + @Override public void removeTrackingPlayer(ServerPlayerEntity player) { + super.removeTrackingPlayer(player); + this.bossInfo.removePlayer(player); + } + + @Override public void updateAITasks() { + super.updateAITasks(); + this.bossInfo.setPercent(this.getHealth() / this.getMaxHealth()); + } + + + <#if data.ridable && (data.canControlForward || data.canControlStrafe)> + @Override public void travel(Vector3d dir) { + <#if data.canControlForward || data.canControlStrafe> + Entity entity = this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); + if (this.isBeingRidden()) { + this.rotationYaw = entity.rotationYaw; + this.prevRotationYaw = this.rotationYaw; + this.rotationPitch = entity.rotationPitch * 0.5F; + this.setRotation(this.rotationYaw, this.rotationPitch); + this.jumpMovementFactor = this.getAIMoveSpeed() * 0.15F; + this.renderYawOffset = entity.rotationYaw; + this.rotationYawHead = entity.rotationYaw; + this.stepHeight = 1.0F; + + if (entity instanceof LivingEntity) { + this.setAIMoveSpeed((float) this.getAttributeValue(Attributes.MOVEMENT_SPEED)); + + <#if data.canControlForward> + float forward = ((LivingEntity) entity).moveForward; + <#else> + float forward = 0; + + + <#if data.canControlStrafe> + float strafe = ((LivingEntity) entity).moveStrafing; + <#else> + float strafe = 0; + + + super.travel(new Vector3d(strafe, 0, forward)); + } + + this.prevLimbSwingAmount = this.limbSwingAmount; + double d1 = this.getPosX() - this.prevPosX; + double d0 = this.getPosZ() - this.prevPosZ; + float f1 = MathHelper.sqrt(d1 * d1 + d0 * d0) * 4.0F; + if (f1 > 1.0F) f1 = 1.0F; + this.limbSwingAmount += (f1 - this.limbSwingAmount) * 0.4F; + this.limbSwing += this.limbSwingAmount; + return; + } + this.stepHeight = 0.5F; + this.jumpMovementFactor = 0.02F; + + + super.travel(dir); + } + + + <#if data.flyingMob> + @Override protected void updateFallState(double y, boolean onGroundIn, BlockState state, BlockPos pos) { + } + + @Override public void setNoGravity(boolean ignored) { + super.setNoGravity(true); + } + + + <#if data.spawnParticles || data.flyingMob> + public void livingTick() { + super.livingTick(); + + <#if data.flyingMob> + this.setNoGravity(true); + + + <#if data.spawnParticles> + double x = this.getPosX(); + double y = this.getPosY(); + double z = this.getPosZ(); + Random random = this.rand; + Entity entity = this; + <@particles data.particleSpawningShape data.particleToSpawn data.particleSpawningRadious data.particleAmount data.particleCondition/> + + } + + + } + + <#if data.mobModelGlowTexture?has_content> + @OnlyIn(Dist.CLIENT) private static class GlowingLayer> extends LayerRenderer { + + public GlowingLayer(IEntityRenderer er) { + super(er); + } + + public void render(MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int packedLightIn, T entitylivingbaseIn, float limbSwing, + float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { + IVertexBuilder ivertexbuilder = bufferIn.getBuffer(RenderType.getEyes(new ResourceLocation("${modid}:textures/${data.mobModelGlowTexture}"))); + this.getEntityModel().render(matrixStackIn, ivertexbuilder, 15728640, OverlayTexture.NO_OVERLAY, 1, 1, 1, 1); + } + + } + + + <#if data.ranged && data.rangedItemType == "Default item"> + @OnlyIn(value = Dist.CLIENT, _interface = IRendersAsItem.class) private static class ArrowCustomEntity extends AbstractArrowEntity implements IRendersAsItem { + + public ArrowCustomEntity(FMLPlayMessages.SpawnEntity packet, World world) { + super(arrow, world); + } + + public ArrowCustomEntity(EntityType type, World world) { + super(type, world); + } + + public ArrowCustomEntity(EntityType type, double x, double y, double z, World world) { + super(type, x, y, z, world); + } + + public ArrowCustomEntity(EntityType type, LivingEntity entity, World world) { + super(type, entity, world); + } + + @Override public IPacket createSpawnPacket() { + return NetworkHooks.getEntitySpawningPacket(this); + } + + @Override @OnlyIn(Dist.CLIENT) public ItemStack getItem() { + return ${mappedMCItemToItemStackCode(data.rangedAttackItem, 1)}; + } + + @Override protected ItemStack getArrowStack() { + return ${mappedMCItemToItemStackCode(data.rangedAttackItem, 1)}; + } + } + + + <#if data.getModelCode()?? && !data.isBuiltInModel() > + ${data.getModelCode().toString() + .replace("extends ModelBase", "extends EntityModel") + .replace("GlStateManager.translate", "GlStateManager.translated") + .replace("RendererModel ", "ModelRenderer ") + .replace("RendererModel(", "ModelRenderer(") + .replace("GlStateManager.scale", "GlStateManager.scaled") + .replaceAll("(.*?)\\.cubeList\\.add\\(new\\sModelBox\\(", "addBoxHelper(") + .replaceAll(",[\n\r\t\\s]+true\\)\\);", ", true);") + .replaceAll(",[\n\r\t\\s]+false\\)\\);", ", false);") + .replaceAll("setRotationAngles\\(float[\n\r\t\\s]+f,[\n\r\t\\s]+float[\n\r\t\\s]+f1,[\n\r\t\\s]+float[\n\r\t\\s]+f2,[\n\r\t\\s]+float[\n\r\t\\s]+f3,[\n\r\t\\s]+float[\n\r\t\\s]+f4,[\n\r\t\\s]+float[\n\r\t\\s]+f5,[\n\r\t\\s]+Entity[\n\r\t\\s]+e\\)", + "setRotationAngles(Entity e, float f, float f1, float f2, float f3, float f4)") + .replaceAll("setRotationAngles\\(float[\n\r\t\\s]+f,[\n\r\t\\s]+float[\n\r\t\\s]+f1,[\n\r\t\\s]+float[\n\r\t\\s]+f2,[\n\r\t\\s]+float[\n\r\t\\s]+f3,[\n\r\t\\s]+float[\n\r\t\\s]+f4,[\n\r\t\\s]+float[\n\r\t\\s]+f5,[\n\r\t\\s]+Entity[\n\r\t\\s]+entity\\)", + "setRotationAngles(Entity entity, float f, float f1, float f2, float f3, float f4)") + + .replaceAll("((super\\.)?)setRotationAngles\\(f,[\n\r\t\\s]+f1,[\n\r\t\\s]+f2,[\n\r\t\\s]+f3,[\n\r\t\\s]+f4,[\n\r\t\\s]+f5,[\n\r\t\\s]+e\\);", + "") + .replaceAll("((super\\.)?)setRotationAngles\\(f,[\n\r\t\\s]+f1,[\n\r\t\\s]+f2,[\n\r\t\\s]+f3,[\n\r\t\\s]+f4,[\n\r\t\\s]+f5,[\n\r\t\\s]+entity\\);", + "") + + .replaceAll("render\\(Entity[\n\r\t\\s]+entity,[\n\r\t\\s]+float[\n\r\t\\s]+f,[\n\r\t\\s]+float[\n\r\t\\s]+f1,[\n\r\t\\s]+float[\n\r\t\\s]+f2,[\n\r\t\\s]+float[\n\r\t\\s]+f3,[\n\r\t\\s]+float[\n\r\t\\s]+f4,[\n\r\t\\s]+float[\n\r\t\\s]+f5\\)", + "render(MatrixStack ms, IVertexBuilder vb, int i1, int i2, float f1, float f2, float f3, float f4)") + .replaceAll("super\\.render\\(entity,[\n\r\t\\s]+f,[\n\r\t\\s]+f1,[\n\r\t\\s]+f2,[\n\r\t\\s]+f3,[\n\r\t\\s]+f4,[\n\r\t\\s]+f5\\);", "") + .replace(".render(f5);", ".render(ms, vb, i1, i2, f1, f2, f3, f4);") + } + + <#if data.getModelCode().contains(".cubeList.add(new")> <#-- if the model is pre 1.15.2 --> + @OnlyIn(Dist.CLIENT) public static void addBoxHelper(ModelRenderer renderer, int texU, int texV, float x, float y, float z, int dx, int dy, int dz, float delta) { + addBoxHelper(renderer, texU, texV, x, y, z, dx, dy, dz, delta, renderer.mirror); + } + + @OnlyIn(Dist.CLIENT) public static void addBoxHelper(ModelRenderer renderer, int texU, int texV, float x, float y, float z, int dx, int dy, int dz, float delta, boolean mirror) { + renderer.mirror = mirror; + renderer.addBox("", x, y, z, dx, dy, dz, delta, texU, texV); + } + + + + +} +<#-- @formatter:on --> \ No newline at end of file diff --git a/src/test/java/net/mcreator/integration/TestWorkspaceDataProvider.java b/src/test/java/net/mcreator/integration/TestWorkspaceDataProvider.java index 0adf28ec713..e36bec3b576 100644 --- a/src/test/java/net/mcreator/integration/TestWorkspaceDataProvider.java +++ b/src/test/java/net/mcreator/integration/TestWorkspaceDataProvider.java @@ -551,12 +551,22 @@ null, null, new MItemBlock(modElement.getWorkspace(), } mob.hasAI = _true; mob.aiBase = "(none)"; - mob.aixml = "" - + "1" - + "" - + "1.2" - + "!_true" - + ""; + if(!emptyLists) { + Set aiTasks = modElement.getWorkspace().getGenerator().getGeneratorStats().getGeneratorAITasks(); + if (aiTasks.contains("wander") && aiTasks.contains("look_around") + && aiTasks.contains("panic_when_attacked") && aiTasks.contains("attack_action")) { + mob.aixml = "" + + "1" + + "" + + "1.2" + + "!_true" + + ""; + } + } + // fallback + if (mob.aixml == null) { + mob.aixml = ""; + } mob.breedable = _true; mob.tameable = _true; mob.breedTriggerItems = new ArrayList<>();