From dbec69fbb4e46660890faac5cca6393f0a9d55c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Fabi=C3=A1nek?= Date: Thu, 12 Oct 2023 20:09:05 +0200 Subject: [PATCH] wip --- blockbench/rascal/Rascal.bbmodel | 1 + blockbench/rascal/rascal.animation.json | 215 +++++++++ .../CompleteHideAndSeekGameCriterion.java | 71 +++ .../entity/animation/RascalAnimations.java | 303 ++++++++++++ .../context/AnimationContextTracker.java | 10 +- .../entity/model/AnimatedEntityModel.java | 9 + .../entity/model/RascalEntityModel.java | 93 ++++ .../entity/model/TuffGolemEntityModel.java | 11 - .../entity/renderer/RascalEntityRenderer.java | 25 + .../config/FriendsAndFoesConfig.java | 7 + .../friendsandfoes/entity/RascalEntity.java | 442 ++++++++++++++++++ .../entity/TuffGolemEntity.java | 17 +- .../entity/WildfireShieldDebrisEntity.java | 2 +- .../entity/ai/brain/RascalBrain.java | 170 +++++++ .../entity/ai/brain/WildfireBrain.java | 3 +- .../RascalFindInteractionTargetTask.java | 34 ++ .../task/rascal/RascalWaitForPlayerTask.java | 197 ++++++++ .../entity/animation/AnimatedEntity.java | 22 +- .../entity/pose/RascalEntityPose.java | 22 + .../init/FriendAndFoesEntityRenderer.java | 1 + .../init/FriendsAndFoesActivities.java | 2 + .../init/FriendsAndFoesCriteria.java | 3 + .../init/FriendsAndFoesEntityModelLayer.java | 3 + .../init/FriendsAndFoesEntityTypes.java | 8 + .../init/FriendsAndFoesItems.java | 2 + .../init/FriendsAndFoesMemoryModuleTypes.java | 2 + .../init/FriendsAndFoesSoundEvents.java | 14 + .../mixin}/AddCustomEntityPoseMixin.java | 40 +- .../mixin/BundleItemAccessor.java | 16 + .../mixin/ChunkRegionAccessor.java | 13 + .../mixin/StrongholdGeneratorMixin.java | 2 +- .../platform/CustomSpawnGroup.java | 24 +- .../tag/FriendsAndFoesTags.java | 1 + .../world/spawner/IceologerSpawner.java | 2 +- .../assets/friendsandfoes/lang/en_us.json | 14 +- .../models/item/ rascal_spawn_egg.json | 3 + .../assets/friendsandfoes/sounds.json | 59 ++- .../friendsandfoes-common.mixins.json | 2 + .../fabric/AddCustomEntityPoseMixin.java | 74 --- .../main/resources/friendsandfoes.mixins.json | 1 - .../main/resources/friendsandfoes.mixins.json | 1 - 41 files changed, 1811 insertions(+), 130 deletions(-) create mode 100644 blockbench/rascal/Rascal.bbmodel create mode 100644 blockbench/rascal/rascal.animation.json create mode 100644 common/src/main/java/com/faboslav/friendsandfoes/advancements/criterion/CompleteHideAndSeekGameCriterion.java create mode 100644 common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/animation/RascalAnimations.java create mode 100644 common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/model/RascalEntityModel.java create mode 100644 common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/renderer/RascalEntityRenderer.java create mode 100644 common/src/main/java/com/faboslav/friendsandfoes/entity/RascalEntity.java create mode 100644 common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/RascalBrain.java create mode 100644 common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/task/rascal/RascalFindInteractionTargetTask.java create mode 100644 common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/task/rascal/RascalWaitForPlayerTask.java create mode 100644 common/src/main/java/com/faboslav/friendsandfoes/entity/pose/RascalEntityPose.java rename {forge/src/main/java/com/faboslav/friendsandfoes/mixin/forge => common/src/main/java/com/faboslav/friendsandfoes/mixin}/AddCustomEntityPoseMixin.java (65%) create mode 100644 common/src/main/java/com/faboslav/friendsandfoes/mixin/BundleItemAccessor.java create mode 100644 common/src/main/java/com/faboslav/friendsandfoes/mixin/ChunkRegionAccessor.java create mode 100644 common/src/main/resources/assets/friendsandfoes/models/item/ rascal_spawn_egg.json delete mode 100644 fabric/src/main/java/com/faboslav/friendsandfoes/mixin/fabric/AddCustomEntityPoseMixin.java diff --git a/blockbench/rascal/Rascal.bbmodel b/blockbench/rascal/Rascal.bbmodel new file mode 100644 index 000000000..b684889b7 --- /dev/null +++ b/blockbench/rascal/Rascal.bbmodel @@ -0,0 +1 @@ +{"meta":{"format_version":"4.5","model_format":"animated_entity_model","box_uv":true},"name":"Rascal","model_identifier":"rascal - Converted","visible_box":[1,1,0],"variable_placeholders":"","variable_placeholder_buttons":[],"timeline_setups":[],"unhandled_root_fields":{},"resolution":{"width":64,"height":64},"elements":[{"name":"head","box_uv":true,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[-4,11,-10],"to":[4,17,-4],"autouv":0,"color":2,"origin":[0,0,0],"uv_offset":[0,52],"faces":{"north":{"uv":[6,58,14,64],"texture":0},"east":{"uv":[0,58,6,64],"texture":0},"south":{"uv":[20,58,28,64],"texture":0},"west":{"uv":[14,58,20,64],"texture":0},"up":{"uv":[14,58,6,52],"texture":0},"down":{"uv":[22,52,14,58],"texture":0}},"type":"cube","uuid":"5610797e-c25a-915d-ebd0-f98c266bd6b7"},{"name":"body","box_uv":true,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[-6,5,-4],"to":[6,20,4],"autouv":0,"color":2,"inflate":-0.01,"origin":[0,0,0],"faces":{"north":{"uv":[8,8,20,23],"texture":0},"east":{"uv":[0,8,8,23],"texture":0},"south":{"uv":[28,8,40,23],"texture":0},"west":{"uv":[20,8,28,23],"texture":0},"up":{"uv":[20,8,8,0],"texture":0},"down":{"uv":[32,0,20,8],"texture":0}},"type":"cube","uuid":"a1df3e93-d628-d164-4ae3-0d185d1c1fbb"},{"name":"rightArm","box_uv":true,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[-9,5,-2],"to":[-6,15,2],"autouv":0,"color":2,"origin":[0,0,0],"uv_offset":[50,28],"faces":{"north":{"uv":[54,32,57,42],"texture":0},"east":{"uv":[50,32,54,42],"texture":0},"south":{"uv":[61,32,64,42],"texture":0},"west":{"uv":[57,32,61,42],"texture":0},"up":{"uv":[57,32,54,28],"texture":0},"down":{"uv":[60,28,57,32],"texture":0}},"type":"cube","uuid":"179fffc8-c3cf-90a5-5543-4ccb1bffc903"},{"name":"scarf","box_uv":true,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[-4,9,-10],"to":[4,18,-4],"autouv":0,"color":2,"inflate":0.5,"origin":[0,0,0],"uv_offset":[28,36],"faces":{"north":{"uv":[34,42,42,51],"texture":0},"east":{"uv":[28,42,34,51],"texture":0},"south":{"uv":[48,42,56,51],"texture":0},"west":{"uv":[42,42,48,51],"texture":0},"up":{"uv":[42,42,34,36],"texture":0},"down":{"uv":[50,36,42,42],"texture":0}},"type":"cube","uuid":"bbb571c5-d309-7dd3-bdcc-71b68f8e646f"},{"name":"rightLeg","box_uv":true,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[-5,0,-2],"to":[-1,6,2],"autouv":0,"color":2,"origin":[0,0,0],"uv_offset":[28,54],"faces":{"north":{"uv":[32,58,36,64],"texture":0},"east":{"uv":[28,58,32,64],"texture":0},"south":{"uv":[40,58,44,64],"texture":0},"west":{"uv":[36,58,40,64],"texture":0},"up":{"uv":[36,58,32,54],"texture":0},"down":{"uv":[40,54,36,58],"texture":0}},"type":"cube","uuid":"548a108b-1e45-1f74-efd6-bebd0ed5f3b7"},{"name":"bag","box_uv":true,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[-7,8,4],"to":[1,17,10],"autouv":0,"color":2,"origin":[0,0,0],"uv_offset":[0,36],"faces":{"north":{"uv":[6,42,14,51],"texture":0},"east":{"uv":[0,42,6,51],"texture":0},"south":{"uv":[20,42,28,51],"texture":0},"west":{"uv":[14,42,20,51],"texture":0},"up":{"uv":[14,42,6,36],"texture":0},"down":{"uv":[22,36,14,42],"texture":0}},"type":"cube","uuid":"5a216366-ff71-da02-7427-6cc984f4c655"},{"name":"cloth","box_uv":true,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[-6,3,-4],"to":[6,8,4],"autouv":0,"color":2,"inflate":-0.5,"origin":[0,0,0],"uv_offset":[0,23],"faces":{"north":{"uv":[8,31,20,36],"texture":0},"east":{"uv":[0,31,8,36],"texture":0},"south":{"uv":[28,31,40,36],"texture":0},"west":{"uv":[20,31,28,36],"texture":0},"up":{"uv":[20,31,8,23],"texture":0},"down":{"uv":[32,23,20,31],"texture":0}},"type":"cube","uuid":"bc1d7d9f-9e05-85f9-6464-7bbd7a2c3ea3"},{"name":"stripe","box_uv":true,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[-5,5,-4],"to":[-3,20,4],"autouv":0,"color":2,"inflate":0.5,"origin":[0,0,0],"uv_offset":[44,0],"faces":{"north":{"uv":[52,8,54,23],"texture":0},"east":{"uv":[44,8,52,23],"texture":0},"south":{"uv":[62,8,64,23],"texture":0},"west":{"uv":[54,8,62,23],"texture":0},"up":{"uv":[54,8,52,0],"texture":0},"down":{"uv":[56,0,54,8],"texture":0}},"type":"cube","uuid":"950c57f0-4b76-bb9a-919b-156a5e446612"},{"name":"leftArm","box_uv":true,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[6,5,-2],"to":[9,15,2],"autouv":0,"color":2,"mirror_uv":true,"origin":[0,0,0],"uv_offset":[50,28],"faces":{"north":{"uv":[57,32,54,42],"texture":0},"east":{"uv":[61,32,57,42],"texture":0},"south":{"uv":[64,32,61,42],"texture":0},"west":{"uv":[54,32,50,42],"texture":0},"up":{"uv":[54,32,57,28],"texture":0},"down":{"uv":[57,28,60,32],"texture":0}},"type":"cube","uuid":"cf4e7090-c4a4-3bb1-5445-12df476a2ce7"},{"name":"leftLeg","box_uv":true,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[1,0,-2],"to":[5,6,2],"autouv":0,"color":2,"mirror_uv":true,"origin":[0,0,0],"uv_offset":[28,54],"faces":{"north":{"uv":[36,58,32,64],"texture":0},"east":{"uv":[40,58,36,64],"texture":0},"south":{"uv":[44,58,40,64],"texture":0},"west":{"uv":[32,58,28,64],"texture":0},"up":{"uv":[32,58,36,54],"texture":0},"down":{"uv":[36,54,40,58],"texture":0}},"type":"cube","uuid":"13c935a5-2ec9-17ad-278b-f9863ee5654f"}],"outliner":[{"name":"head","origin":[0,15,-5],"color":0,"uuid":"133fc098-1dae-95b0-7cde-23c6f350c6c8","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["5610797e-c25a-915d-ebd0-f98c266bd6b7","bbb571c5-d309-7dd3-bdcc-71b68f8e646f"]},{"name":"leftArm","origin":[6,13,0],"color":0,"uuid":"a0b7942c-2039-3008-d5d4-71874ab3159d","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["cf4e7090-c4a4-3bb1-5445-12df476a2ce7"]},{"name":"rightArm","origin":[-6,13,0],"color":0,"uuid":"9325e427-5b09-6ca2-085d-c56aa11d6c95","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["179fffc8-c3cf-90a5-5543-4ccb1bffc903"]},{"name":"leftLeg","origin":[3,6,0],"color":0,"uuid":"616ae677-c704-3100-eb8c-5f389da56bab","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["13c935a5-2ec9-17ad-278b-f9863ee5654f"]},{"name":"rightLeg","origin":[-3,6,0],"color":0,"uuid":"e6ebbda9-64b3-bc6f-11c8-a889976b8bd8","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["548a108b-1e45-1f74-efd6-bebd0ed5f3b7"]},{"name":"bag","origin":[-3,16.5,4.5],"color":0,"uuid":"9f44f743-c317-b6a7-404d-9d80547e4fdb","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["5a216366-ff71-da02-7427-6cc984f4c655"]},{"name":"body","origin":[0,20,0],"color":0,"uuid":"ba135b89-9ee8-7155-efbf-7cd095edee53","export":true,"mirror_uv":false,"isOpen":true,"locked":false,"visibility":true,"autouv":0,"children":["a1df3e93-d628-d164-4ae3-0d185d1c1fbb","bc1d7d9f-9e05-85f9-6464-7bbd7a2c3ea3","950c57f0-4b76-bb9a-919b-156a5e446612"]}],"textures":[{"path":"/Users/alesfabianek/Projects/Minecraft/friends-and-foes/common/src/main/resources/assets/friendsandfoes/textures/entity/rascal/rascal.png","name":"rascal.png","folder":"entity/rascal","namespace":"friendsandfoes","id":"2","particle":false,"render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"mode":"bitmap","saved":true,"uuid":"857975cb-cca7-d368-12c5-aa7266647fa0","relative_path":"../../../common/src/main/resources/assets/friendsandfoes/textures/entity/rascal/rascal.png","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAABzJJREFUeF7lWl1sVEUUvheLwSqmRWmlNipYy482EU0jSBR/YqPyU7UxRsEHwWhaHyQh4cWABt6akGCiJZoUX1RiTNUqCMFErYlC0igPKoIpRU0BadViwEKkds032zM5Ozt/9+697brel+7OOXPu+b4558zsnIaB4+nZ1pQhldo5VVrtgf5BOb503b7QZTNt+TN3X5N5/bNfvPxwKm1vmysIWFB/rfSbiODAITz0489Ba8cRp820CWh/pDaz4b0BLz+cSogA08qrQEBIMURA4gQAqIsEioaSI+Doh6tlDdCFLgFH+OMpyRRwFUHIiykCEi2C//saoNsFbFW8GGpApAgAwKb7G437O3KbtkBbIeS1APo63X17e8V7otiLQ6gPAaQT8hXmTgMQwB/84VywcP4lVqfVQkgg+XmBimRUe3GKqs82SDohmFjVPE8bAUQAhCABztOD77pHBch13uo+nDOfH65UW4XsKj4EyAjABwLInQCQzvLZYii86kqvw1vm19+k/pr+XkGaapN/N5EIHSLb90jL7UYi4KJlSzNrR46J+TvmNAZwnD6HFdXi8+Lq/N8A90y7Qsg+Pf+7fPf+U9nfBND/6si3wha3yQml95iYxTwQ+s/uHudpVbXhQwDNCcvWtsiDzu1zG4TjePhnIoIm6QgB+MzpU9kIGCcO37kd+dKKaqlrIgA2MH+0sytdAqaub8sAEK2eziECbNPh85K0d2FrR7oEIALUFSYw6oq6CoFL3yVX7U9IBPAUcAGcDHnqKYAiSFWe5y7A8qrO85cTQauq00/CXpwi6HMQkng4AXkhOL6ticLm2AqJLJuuj45Mv/F3xyEgSqSG02+pzYzMuj5bvcdBkqPlJ4+KcZLrwHFQqn4S9s5843ezEwU01w0pAmjb4aE+dvj7HGLUkFbTgusnZS/1CCACsJJYMb6iEiAbV1eV5vC5urEc1iPYmxAC8BIQob4MY3CcxoksXWXGbkLkJWkvdQJcuVO55EF5Uiwrn65VHx05I8eHv/w48sHF5UOacqezly1oFARMrZwp/SAiOHAILwwPBWcP9Tptpgkoqm2ns4gA08qrLwMhJRcBlAIuEigaSo6Amfc9Zr0WJ+AIfzwlmQIU6rYoKLYI4L9y9z7ZKrP13psbctK+ZGvAne0vychdVX+bJODZhx6IRoBuF7BV2mKpAZyAF5tazBFAADkobHmU0ypYvh3S1ufaegqxF7em8BR45Y4V5ggAASoo0iYSTHIOnBOWpD1fAggwfOJ3k/yzThbaDjrnjvdLjLqDEOR83EQCFc849nwJoJstfj+R8/vDcA8Z0kEHVVyt8lTZMW6S8zk++nAqij3fmsKv9vjVm+6iFj7Qr1VBAL2EyBj65J0cYmxyGKMTIB2akrTnSwC/2OE3WeqtliozboO4VqqrHNPWt77hKcGJ0+ettW/XwUHnFssN0N0kv6Cl1fPpDzy1cbP2wLboVn3f88DX2f6H0Uk0F7q/G9GCbL6pPPji2N9CNvzXaI5O5aVl4nscAtRGDBUwn9thlQAAr7uu1rpIfT8NuAkYOpsLEBafXnS5IEAFT28DCVEJ0F3Owh5Fget2+LUP9uRFwH+KAL6Noe2mttxcDRIQQGFNYc8JwGrjUcecKWCLgDRSgLfdoqSALgJUwDwfiJCiK4K0RfHwFzuNo0cYOwVQ7OqunpFTLPqO/5ENF2WclExyn3kvzF6Z123GSvP+Iz7zNEDDFgVSbcryCNFVO8xxpY74Bwl1u8M2JwiwbIM6uc88tL11Wx2/cudgedeZR4dPgcTW6oqcSSFAB4Rfy5uu2HXE2dKjYAJsqxxXhgggArDFATg6StR9Ml3Nkw7IUZsuplX2JsB6WkhYuPPPMQGWgMA8OkoAaGqDUftuyrwbhTecOHy3zXO11sLlC6syNRXTZL7zYy4flwWQHYPjzNtTMz8PvG/zA4cllQT4ZZqva/ao6ykJ4AI65wOg7jHJfeYRAWTX55xPumonm3eidH56EbCkfkYGR1cCCxB0xOXj9AKT3HfegRsasjVgvD9oC30VFKWC2sMsOAISTnOruZ7wYlnwooAno7ydT+34gmrARIIvxncZj8LL1j5nbYi4wOzufDXSfYDLXlpyJwFVNdl/lqRn8ET2fwHxqDKuUxIE2ACaZETCG1s2eUWAGmmqXV87cSPEGgE2ApKKgKImQAeSUgDk2O7bfFeu6AkwhdbKFcutUaf24EzKk06Aqdq7cpwXw7j5F2de0sU1dK2Ay0kdEa7a4bJpk6dGgM7p1S0PB81PrAkebck2F9/t+ijofntH8GbX+3k++m6PrshykeNbW1x2SC4iwOTUhnXPB49v2Rq03rVY6G//fH+wc+P6oH3by1r7NhJ48fR1TqeXKgFqVTfdq9ONKjlI19E+dcFVPF3k+BZXlx1tBJi6KSc3dQj9WZvb8uyCjEIJANGwQ39tzidNwL/B1qTFXkVWIQAAAABJRU5ErkJggg=="}],"animations":[{"uuid":"bf367973-9c39-500a-196f-41619e52a6bb","name":"nod","loop":"once","override":false,"length":0.4167,"snapping":12,"selected":false,"saved":true,"path":"/Users/alesfabianek/Downloads/rascal.animation.json","anim_time_update":"","blend_weight":"","start_delay":"","loop_delay":"","animators":{"133fc098-1dae-95b0-7cde-23c6f350c6c8":{"name":"head","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"68028f48-a178-14f8-c0eb-bf259bae56b0","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":15,"y":0,"z":0}],"uuid":"22970608-ef03-ea86-c1b4-fd10176bbad8","time":0.0833,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":20,"y":0,"z":0}],"uuid":"62bceae8-5e5c-a731-ed09-89c34a8d02e6","time":0.1667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":10,"y":0,"z":0}],"uuid":"feab9ad1-27a2-b6ad-c2af-2f7f4ae6df5e","time":0.25,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"b625a124-ccfc-830a-c361-6cabf7e0f4f8","time":0.4167,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"d4ff9c9f-cbd6-0ac1-f743-48f5c423ab3d","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":2,"z":0}],"uuid":"3d68b782-37d0-3a4f-6842-7fd098e016e3","time":0.1667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"079ac161-dc3f-1219-6439-4b1dc0fbfb70","time":0.4167,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]}]},"a0b7942c-2039-3008-d5d4-71874ab3159d":{"name":"leftArm","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"7443b36e-0fa5-b463-172f-23fdaef86121","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-15,"y":0,"z":0}],"uuid":"8edb7b07-3c44-a4c5-e566-849d21bb09eb","time":0.1667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-25,"y":0,"z":0}],"uuid":"b2f106ad-5a40-af54-1af9-be37b4edf2c2","time":0.25,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":5,"y":0,"z":0}],"uuid":"1a10873c-aecc-c6a0-bca6-fe90f4cdd145","time":0.3333,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"6917799d-823e-3f2d-e448-cc375227ff1b","time":0.4167,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"3b3fc7c3-4f14-ae3d-4309-58b589436897","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":2,"z":0}],"uuid":"3145f830-5d86-b4f9-f616-93c964f17867","time":0.1667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"c19c59d2-a9ef-acd3-cf0e-fe6be92825ef","time":0.4167,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]}]},"9325e427-5b09-6ca2-085d-c56aa11d6c95":{"name":"rightArm","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"258412cf-45da-0013-ad40-72b810439816","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":15,"y":0,"z":0}],"uuid":"14e62eb8-71e6-09c5-5b2a-4fb82f827868","time":0.1667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":25,"y":0,"z":0}],"uuid":"2d85af2f-719b-b030-bbf1-9f5772ce19d1","time":0.25,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":5,"y":0,"z":0}],"uuid":"17802068-56cd-2ead-3739-f2e2a4937e46","time":0.3333,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"9a5c4666-f2d3-1fef-b832-b59f00d213ba","time":0.4167,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"15c49bee-d5bf-440e-d7cb-ebf1fd9b047e","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":2,"z":0}],"uuid":"86a0f4b5-3f05-57a7-e2bc-1afae5c689c8","time":0.1667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"d994ed99-4178-b5df-e0c7-f4f86c98a814","time":0.4167,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]}]},"616ae677-c704-3100-eb8c-5f389da56bab":{"name":"leftLeg","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"e0fb010d-3190-1bfd-3c3c-1ddb974411b3","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":15,"y":0,"z":0}],"uuid":"54fa12c1-8ff4-103f-12d0-bc5f7f4232d8","time":0.1667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":20,"y":0,"z":0}],"uuid":"a08c38e3-7335-2277-8904-759d3d31b582","time":0.25,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-5,"y":0,"z":0}],"uuid":"ef99149c-46e5-875f-4d96-09f8526042fd","time":0.3333,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"688fcebb-0a6a-b5fe-201b-38bfe76ddda2","time":0.4167,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"ac707ced-690a-2fa1-c0c6-2abddd4bee0f","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":2,"z":0}],"uuid":"597f296b-0077-a9f4-a098-9c27352d97cd","time":0.1667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"93a1388a-e424-f8bd-5054-eac62000e769","time":0.4167,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]}]},"e6ebbda9-64b3-bc6f-11c8-a889976b8bd8":{"name":"rightLeg","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"74abd9e5-0153-9680-2cd8-30122acff1bf","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-15,"y":0,"z":0}],"uuid":"775fd33a-ff36-2fe3-41e1-7576e35617f5","time":0.1667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-20,"y":0,"z":0}],"uuid":"df2a9446-d289-1409-b614-a5e3824f4901","time":0.25,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":5,"y":0,"z":0}],"uuid":"26722351-d8b0-0dbe-24a2-707b608520ed","time":0.3333,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"6eda2e60-3fa9-6843-1e9e-a9c8c94ac152","time":0.4167,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"533a7380-91b5-1866-b4de-537cf49caa22","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":2,"z":0}],"uuid":"c9c7491f-2940-9cff-51b7-f3f8a5c23183","time":0.1667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"2e87dab6-89db-cc98-f711-c33d4434bc51","time":0.4167,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]}]},"9f44f743-c317-b6a7-404d-9d80547e4fdb":{"name":"bag","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"e2f72faf-db93-c0a0-06f0-50acbfd89f7e","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":10,"y":0,"z":0}],"uuid":"ecc16605-b850-408f-565d-e9aeb775f217","time":0.1667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":15,"y":0,"z":0}],"uuid":"d2a8b668-0103-b818-f347-789f05dabfb1","time":0.25,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-5,"y":0,"z":0}],"uuid":"fd3248c8-56b4-8769-953b-247b5ee358fe","time":0.3333,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"50bcaaa6-204e-a3aa-4aea-d47b55699cc7","time":0.4167,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"492e2754-deb7-d08f-134e-d70259dab0d1","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":2,"z":0}],"uuid":"b3844fea-4d9e-b83b-25f0-feee279ef86b","time":0.1667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"2b00b14d-27a7-c131-8bf2-f45225967eb3","time":0.4167,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]}]},"ba135b89-9ee8-7155-efbf-7cd095edee53":{"name":"body","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"63a39535-7992-ffb9-b413-9fdefc43b199","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-1,"y":0,"z":0}],"uuid":"adc19087-028d-13ae-627c-ef749b5b4fef","time":0.1667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":1,"y":0,"z":0}],"uuid":"6d9f4daf-ea8d-e10d-ba96-f0358b1d0fd8","time":0.25,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"feed89b5-6ab7-3500-07de-cb48fffa6067","time":0.4167,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"a26179a9-17b9-e884-43d7-fd7b29958fb9","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":2,"z":0}],"uuid":"130c99a6-ad72-0883-4d49-d1b9fde1ad6c","time":0.1667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"857416d2-be89-963f-e3fc-d552f20047b7","time":0.4167,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]}]}}},{"uuid":"bcc26bb9-6121-af56-f187-d95f289fd936","name":"give_reward","loop":"once","override":false,"length":1.5416666666666667,"snapping":24,"selected":true,"saved":true,"path":"/Users/alesfabianek/Downloads/rascal.animation.json","anim_time_update":"","blend_weight":"","start_delay":"","loop_delay":"","animators":{"133fc098-1dae-95b0-7cde-23c6f350c6c8":{"name":"head","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"49e58ef7-060e-09b5-3162-1e3b38fe5c62","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-7.5,"y":-50,"z":0}],"uuid":"8173b1e3-6850-3610-5087-f9391419bad4","time":0.375,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0],"easing":"linear"},{"channel":"rotation","data_points":[{"x":-7.5,"y":-40,"z":0}],"uuid":"f117fe51-5737-d098-376f-887fb96dc92d","time":0.4583,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"63e21710-b690-14f4-d808-ed11ddbfaef3","time":0.6667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":15,"y":0,"z":0}],"uuid":"5a846fcc-691d-1cd3-6540-6b0f2fda6c71","time":0.8333,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":15,"y":0,"z":0}],"uuid":"2ca86ac1-a646-27a8-d03a-9cc329d1b71f","time":0.9583,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"5f617e2c-4daa-0c4b-38f8-c544e0c37b91","time":1.0833,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"a48a6fbd-744a-1665-eee2-d5ed59790afb","time":1.5416666666666667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"cf6f312a-8336-20fa-13a6-afb684afd1e0","time":1.25,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]}]},"9325e427-5b09-6ca2-085d-c56aa11d6c95":{"name":"rightArm","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"a308f72c-d6be-228c-5ad8-f8b511f0134f","time":0,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-37.5,"y":0,"z":-20}],"uuid":"96e94fb3-8315-613b-e83e-bb50bfe48740","time":0.125,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-170,"y":0,"z":-20}],"uuid":"c433ea30-db65-356b-4b91-cde759f2183f","time":0.4583,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0],"easing":"easeInElastic"},{"channel":"rotation","data_points":[{"x":-170,"y":0,"z":-20}],"uuid":"ea446466-bf78-58ff-07dd-5c0b0845d7ae","time":0.5417,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0],"easing":"easeInElastic"},{"channel":"rotation","data_points":[{"x":-60,"y":0,"z":0}],"uuid":"82ef740b-7149-e41e-1a58-c4365d81599a","time":0.625,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-60,"y":20,"z":0}],"uuid":"58a5aa14-66b4-7f9a-64c8-2846495b34ec","time":0.75,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-60,"y":20,"z":0}],"uuid":"7cee4cd4-1dd6-ae95-7f0d-7fa24f96f1b6","time":1.0833,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"58719358-1807-6de2-7ea6-181a78595c84","time":1.5416666666666667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-60,"y":20,"z":0}],"uuid":"9f29bdf1-aabd-ef78-66c5-520570c16749","time":1.25,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"94e91bec-494a-31d2-b6c9-b2da81617a0a","time":0.625,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":-2,"z":-1}],"uuid":"3586756f-5f5e-b2a2-ee56-850d4a868eed","time":0.75,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":-2,"z":-1}],"uuid":"86061ca1-41f6-90f5-7c60-a2adaa80ebd4","time":1.0833,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"431e78a0-5fec-34ad-cfbc-a5994edd89df","time":1.5416666666666667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":-2,"z":-1}],"uuid":"639bc6db-a3c6-a813-473f-3fa5a2e2636e","time":1.25,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]}]},"9f44f743-c317-b6a7-404d-9d80547e4fdb":{"name":"bag","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"f6e6d089-b248-221d-7df0-096b7ebc4bf1","time":0.4583,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":5,"y":0,"z":0}],"uuid":"756e21b7-0366-2a50-044d-aecf84094338","time":0.5417,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":90,"z":0}],"uuid":"81cd931d-c61d-b78d-7489-9a16f8792c0d","time":0.625,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-30,"y":180,"z":0}],"uuid":"26521ef8-c3f3-a678-6e04-7f38d9d226b6","time":0.75,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-30,"y":180,"z":0}],"uuid":"18e1dcd5-4758-36bb-504f-aa929f5809a5","time":0.8333,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-30,"y":180,"z":0}],"uuid":"c6d41636-1b14-71c6-7330-982d4997b7a8","time":1.0833,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":90,"z":0}],"uuid":"f899f04a-93b5-c991-486f-e344a0c66b9e","time":1.375,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"8f43eabe-5cc0-fd8a-b527-efca9340afba","time":1.5416666666666667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":5,"y":0,"z":0}],"uuid":"964e7955-dfd3-e357-db7d-0e7862beaa4c","time":1.4583333333333333,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-30,"y":180,"z":0}],"uuid":"84b19f0f-3e27-9e68-6214-2b7c1c2a10cd","time":1.25,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"9671e34b-219e-9348-ed57-210eb8f32e73","time":0.4583,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":7,"y":0,"z":-6}],"uuid":"c52be187-6a5e-157e-a9e4-4edd37e4b41e","time":0.625,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":-3,"y":-7,"z":-12}],"uuid":"60788298-e846-1906-f9aa-6849c6ec9104","time":0.75,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":-3,"y":-7,"z":-12}],"uuid":"ab97aa43-f7bf-ca9f-cccb-2624003c9bad","time":1.0833,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":7,"y":0,"z":-6}],"uuid":"ce485e6f-73e9-caa3-81b6-0051e38b30e2","time":1.375,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"dcec27b5-fabd-256b-71a5-52004bfd6f56","time":1.5416666666666667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":-3,"y":-7,"z":-12}],"uuid":"21ff6a1c-dd05-b2b7-a956-d213e0c8e6f9","time":1.25,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]}]},"a0b7942c-2039-3008-d5d4-71874ab3159d":{"name":"leftArm","type":"bone","keyframes":[{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"31a52416-5b8b-2ff8-1c6c-cb9b7ffe3261","time":0.75,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-52.5,"y":0,"z":0}],"uuid":"0a82a540-e987-a54a-fc3c-831723f98629","time":0.8333,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-65,"y":-30,"z":0}],"uuid":"f7e9b8a2-9cf6-2586-1a47-5ac67bcb6126","time":0.9167,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-90,"y":0,"z":0}],"uuid":"9b9a0092-aaa6-2d7f-ac83-dc6ad98bf6ea","time":1.0833,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":0,"y":0,"z":0}],"uuid":"8ab3e61b-3787-0e68-cfa9-3cdcc7fa4121","time":1.5416666666666667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"rotation","data_points":[{"x":-90,"y":0,"z":0}],"uuid":"631fe700-be88-50aa-389f-102ba431cf21","time":1.25,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"dc4444ff-5e3a-06b8-c9c3-e99266b06cd5","time":0.4583,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":-0.25,"z":0}],"uuid":"4a4c2f63-0435-a266-ab4b-8e619b9a1198","time":0.5833,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0],"easing":"linear"},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"38ff154f-0a7b-fa1e-afa3-6510c45f4ead","time":0.6667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"27aa9190-9d64-be7d-0f3c-d8b165314435","time":0.75,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":-2,"z":-1}],"uuid":"94718078-eff9-6604-07f8-cbb0446483b6","time":0.8333,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"b3abc752-d378-2b06-5877-43d8754b8056","time":1.5416666666666667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":-2,"z":-1}],"uuid":"b625a61b-a63f-f9f0-e593-3dd1783ead2d","time":1.25,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]}]},"ba135b89-9ee8-7155-efbf-7cd095edee53":{"name":"body","type":"bone","keyframes":[{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"d92ad28c-4b83-fd20-b899-cfd457b112d9","time":0.4583,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":-0.25,"z":0}],"uuid":"d00881fe-1a7e-4859-da9c-28794c53a1ff","time":0.5833,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0],"easing":"linear"},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"f3a06a76-cbe6-20ab-d8f3-69d9fc46db37","time":0.6667,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"1de576d2-593a-16fd-8644-1ca2e815fb31","time":1.0833,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]},{"channel":"position","data_points":[{"x":0,"y":0,"z":0}],"uuid":"768ff7cb-2fbf-bfd8-52d9-b737bb907a59","time":1.5,"color":-1,"interpolation":"linear","bezier_linked":true,"bezier_left_time":[-0.1,-0.1,-0.1],"bezier_left_value":[0,0,0],"bezier_right_time":[0.1,0.1,0.1],"bezier_right_value":[0,0,0]}]}}}],"reference_images":[{"name":"Pasted","scope":"project","position":[960,0],"size":[653,653],"source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAE9klEQVR4nO3ZX0hbVxwH8K+ayDVktFu1mrlla5W1021SnEwRJsLcKHYrA4sbG2WFzYe+lRYGHfVBqE/t6x5a8WFI61Bpq+2EtUz2IGmRTtSl3YppZ6qN0TgFQ3JX0509pPc2N//8l+6e0u8HxHvPOffm5Pzu75x7bwAiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIjJbltkdyKTaN14S6eqH7/wt3fe1mN2B1bTUO9MOqsY9E8T+t2yrNROyBUHqAGiD/+2R99O2O3jsJ33wJxez4Z4JJm1XXmwHJAuC1AEAgC/278b03blV200uZgOIZkL74XcBALfuTBnaHLl8D5WKPfOd3ARTr4Scxro1TS8am88DZVutoUxdGAYAfL7lSQAA4MsPChKO1wLADMCTwT/xUZOh/OTUbXz32pspjzs5dRtbxxdQXL4LADDjBpbe2YbzQ/16EMbtNnRdm08aBNmYOgXV1tXjF3VB33f551BTuN1QFsvln4NY8mPRCYR/HtTLhTNiaBdylGDc59GDEB+MVHdLZmSGNGvA8K9D0f9/uFFbV79qe7XGmbIuqygf8HkAAF3X5vWMAKILcemL/yYcc+n30Ea6vWnSBKC2rl7PgEzQskAzbrcBavDxGiHPQixNALQMGB3qN5Tv+ezrDZ8z5Cgx7FsDq99N/d9MD8BodwcAIPYRqqmxRd/u7T6jbysAwnveAwCI2QCAx9PNMyzb7A4I1YGmxhZc7ByEUB0QqiOhXqgOXOwcTH78bAB5ozewkuLqtvk8+p81f3t0KpKIaRlg83kw2u0BEB3wl191ovTDvQCA6soqvd3ockSvB4C80Rv61KJd/eGifFiuDiT9DC1jNGI2gPM+j37LajbTArD823QWANjLHKK6sgoP7ntx+qsDCe20sgf3vTjVehZHj7cie3c5xJI/7flTDb5sTF8DAKD09Vc23c5ir8A5PwBLIRSXF6fazxrqj7V9o2dOyFEiTRZIEYB4vtbv9W1H2+FV2ysuLy6d60xZ39V3IaFsJTAHbCnaWAczyPR3IoozV1jsFYgEx9bU3mKvwD97q/QpaD2D33vlDEKOElgnXDhYYhx890zw+X0SDu+wweZLfABbCczBmm8sF2ri8ZN/Ta/5s6wTLgDAD57Z9XXyKTE9AKr3YZYClwi9XQNbzJOrJv5hKu/exl8ZCNUB1TttetbHkqYzijM36QuySMPHCWXxt5wWewVOt7elPPf1myPo6RtAJDgG1ftQmu8MSJABmtiBsZdVibzinVAXhvFoa2FC20cHjK8nLIMjac/d0zeA8A4brBMZ6mwGSROAePuqy9F7ZVjfV4b6odZ/AgAQS35kxQXm6PHWlOfKUnwASlLWm0naAMRbCcwhp6dD39eyIKenAxEYs0Is+Q3TlFXJzBvWp0HqAMQO+gu7PtXLl/+8YCiP3ddY7BUAgEhwLHo3JeGbUECiRTiWvazKsCDnFe9c1/HhmbsJZTIuwICkGRC8NWJYkIHoVa/Rrvr4rNDqNNrDnZYNtAGKM1cozlxR0NAsDp1oE9p+7HaqskMn2kRBQ7O+b/Z3SUa6lEyloKFZ7KsuT1p3+bob6ermr/4o7feUcgpKJfZ3AiD6gLWWOpmZ/z72OfdMBUD7PSDZ7wLp6mQm7dwYr6ChecOLqMxrwH8ii9KT6rax3QAAAABJRU5ErkJggg=="}],"geckoSettings":{"formatVersion":2,"modSDK":"Forge 1.12 - 1.16","objectType":"OBJ_TYPE_ENTITY","entityType":"Entity","javaPackage":"com.example.mod","animFileNamespace":"MODID","animFilePath":"animations/ANIMATIONFILE.json"}} \ No newline at end of file diff --git a/blockbench/rascal/rascal.animation.json b/blockbench/rascal/rascal.animation.json new file mode 100644 index 000000000..f8dde1993 --- /dev/null +++ b/blockbench/rascal/rascal.animation.json @@ -0,0 +1,215 @@ +{ + "format_version": "1.8.0", + "animations": { + "give_reward": { + "animation_length": 1.54167, + "bones": { + "head": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.375": { + "vector": [-7.5, -50, 0], + "easing": "linear" + }, + "0.4583": { + "vector": [-7.5, -40, 0] + }, + "0.6667": { + "vector": [0, 0, 0] + }, + "0.8333": { + "vector": [15, 0, 0] + }, + "0.9583": { + "vector": [15, 0, 0] + }, + "1.0833": { + "vector": [0, 0, 0] + }, + "1.25": { + "vector": [0, 0, 0] + }, + "1.5417": { + "vector": [0, 0, 0] + } + } + }, + "rightArm": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.125": { + "vector": [-37.5, 0, -20] + }, + "0.4583": { + "vector": [-170, 0, -20], + "easing": "easeInElastic" + }, + "0.5417": { + "vector": [-170, 0, -20], + "easing": "easeInElastic" + }, + "0.625": { + "vector": [-60, 0, 0] + }, + "0.75": { + "vector": [-60, 20, 0] + }, + "1.0833": { + "vector": [-60, 20, 0] + }, + "1.25": { + "vector": [-60, 20, 0] + }, + "1.5417": { + "vector": [0, 0, 0] + } + }, + "position": { + "0.625": { + "vector": [0, 0, 0] + }, + "0.75": { + "vector": [0, -2, -1] + }, + "1.0833": { + "vector": [0, -2, -1] + }, + "1.25": { + "vector": [0, -2, -1] + }, + "1.5417": { + "vector": [0, 0, 0] + } + } + }, + "bag": { + "rotation": { + "0.4583": { + "vector": [0, 0, 0] + }, + "0.5417": { + "vector": [5, 0, 0] + }, + "0.625": { + "vector": [0, 90, 0] + }, + "0.75": { + "vector": [-30, 180, 0] + }, + "0.8333": { + "vector": [-30, 180, 0] + }, + "1.0833": { + "vector": [-30, 180, 0] + }, + "1.25": { + "vector": [-30, 180, 0] + }, + "1.375": { + "vector": [0, 90, 0] + }, + "1.4583": { + "vector": [5, 0, 0] + }, + "1.5417": { + "vector": [0, 0, 0] + } + }, + "position": { + "0.4583": { + "vector": [0, 0, 0] + }, + "0.625": { + "vector": [7, 0, -6] + }, + "0.75": { + "vector": [-3, -7, -12] + }, + "1.0833": { + "vector": [-3, -7, -12] + }, + "1.25": { + "vector": [-3, -7, -12] + }, + "1.375": { + "vector": [7, 0, -6] + }, + "1.5417": { + "vector": [0, 0, 0] + } + } + }, + "leftArm": { + "rotation": { + "0.75": { + "vector": [0, 0, 0] + }, + "0.8333": { + "vector": [-52.5, 0, 0] + }, + "0.9167": { + "vector": [-65, -30, 0] + }, + "1.0833": { + "vector": [-90, 0, 0] + }, + "1.25": { + "vector": [-90, 0, 0] + }, + "1.5417": { + "vector": [0, 0, 0] + } + }, + "position": { + "0.4583": { + "vector": [0, 0, 0] + }, + "0.5833": { + "vector": [0, -0.25, 0], + "easing": "linear" + }, + "0.6667": { + "vector": [0, 0, 0] + }, + "0.75": { + "vector": [0, 0, 0] + }, + "0.8333": { + "vector": [0, -2, -1] + }, + "1.25": { + "vector": [0, -2, -1] + }, + "1.5417": { + "vector": [0, 0, 0] + } + } + }, + "body": { + "position": { + "0.4583": { + "vector": [0, 0, 0] + }, + "0.5833": { + "vector": [0, -0.25, 0], + "easing": "linear" + }, + "0.6667": { + "vector": [0, 0, 0] + }, + "1.0833": { + "vector": [0, 0, 0] + }, + "1.5": { + "vector": [0, 0, 0] + } + } + } + } + } + } +} \ No newline at end of file diff --git a/common/src/main/java/com/faboslav/friendsandfoes/advancements/criterion/CompleteHideAndSeekGameCriterion.java b/common/src/main/java/com/faboslav/friendsandfoes/advancements/criterion/CompleteHideAndSeekGameCriterion.java new file mode 100644 index 000000000..ae406ae1a --- /dev/null +++ b/common/src/main/java/com/faboslav/friendsandfoes/advancements/criterion/CompleteHideAndSeekGameCriterion.java @@ -0,0 +1,71 @@ +package com.faboslav.friendsandfoes.advancements.criterion; + +import com.faboslav.friendsandfoes.FriendsAndFoes; +import com.faboslav.friendsandfoes.entity.RascalEntity; +import com.google.gson.JsonObject; +import net.minecraft.advancement.criterion.AbstractCriterion; +import net.minecraft.advancement.criterion.AbstractCriterionConditions; +import net.minecraft.loot.context.LootContext; +import net.minecraft.predicate.entity.AdvancementEntityPredicateDeserializer; +import net.minecraft.predicate.entity.AdvancementEntityPredicateSerializer; +import net.minecraft.predicate.entity.EntityPredicate; +import net.minecraft.predicate.entity.LootContextPredicate; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; + +public final class CompleteHideAndSeekGameCriterion extends AbstractCriterion +{ + static final Identifier ID = FriendsAndFoes.makeID("complete_hide_and_seek_game"); + + public CompleteHideAndSeekGameCriterion() { + } + + public Identifier getId() { + return ID; + } + + public CompleteHideAndSeekGameCriterion.Conditions conditionsFromJson( + JsonObject jsonObject, + LootContextPredicate extended, + AdvancementEntityPredicateDeserializer advancementEntityPredicateDeserializer + ) { + LootContextPredicate extended2 = EntityPredicate.contextPredicateFromJson(jsonObject, "rascal", advancementEntityPredicateDeserializer); + + return new CompleteHideAndSeekGameCriterion.Conditions(extended, extended2); + } + + public void trigger(ServerPlayerEntity player, RascalEntity entity) { + LootContext lootContext = EntityPredicate.createAdvancementEntityLootContext(player, entity); + this.trigger(player, (conditions) -> { + return conditions.matches(lootContext); + }); + } + + public static class Conditions extends AbstractCriterionConditions + { + private final LootContextPredicate entity; + + public Conditions(LootContextPredicate player, LootContextPredicate entity) { + super(CompleteHideAndSeekGameCriterion.ID, player); + this.entity = entity; + } + + public static CompleteHideAndSeekGameCriterion.Conditions any() { + return new CompleteHideAndSeekGameCriterion.Conditions(LootContextPredicate.EMPTY, LootContextPredicate.EMPTY); + } + + public static CompleteHideAndSeekGameCriterion.Conditions create(EntityPredicate entity) { + return new CompleteHideAndSeekGameCriterion.Conditions(LootContextPredicate.EMPTY, EntityPredicate.asLootContextPredicate(entity)); + } + + public boolean matches(LootContext entityContext) { + return this.entity.test(entityContext); + } + + public JsonObject toJson(AdvancementEntityPredicateSerializer predicateSerializer) { + JsonObject jsonObject = super.toJson(predicateSerializer); + jsonObject.add("entity", this.entity.toJson(predicateSerializer)); + return jsonObject; + } + } +} diff --git a/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/animation/RascalAnimations.java b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/animation/RascalAnimations.java new file mode 100644 index 000000000..7e1757046 --- /dev/null +++ b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/animation/RascalAnimations.java @@ -0,0 +1,303 @@ +package com.faboslav.friendsandfoes.client.render.entity.animation; + +import com.faboslav.friendsandfoes.entity.animation.Animation; +import com.faboslav.friendsandfoes.entity.animation.Keyframe; +import com.faboslav.friendsandfoes.entity.animation.Transformation; +import com.faboslav.friendsandfoes.entity.animation.VectorHelper; + +import java.util.ArrayList; + +public final class RascalAnimations +{ + public static final KeyframeAnimation DEFAULT; + public static final KeyframeAnimation NOD; + public static final KeyframeAnimation GIVE_REWARD; + public static final ArrayList ANIMATIONS; + + public RascalAnimations() { + } + + static { + DEFAULT = new KeyframeAnimation("default", Animation.Builder.create(0.0f).build()); + NOD = new KeyframeAnimation("nod", Animation.Builder.create(0.4167f) + .addBoneAnimation("head", + new Transformation(Transformation.Type.TRANSLATE, + new Keyframe(0f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.1667f, VectorHelper.createTranslationalVector(0f, 2f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4167f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("head", + new Transformation(Transformation.Type.ROTATE, + new Keyframe(0f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.0833f, VectorHelper.createRotationalVector(15f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.1667f, VectorHelper.createRotationalVector(20f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.25f, VectorHelper.createRotationalVector(10f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4167f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("leftArm", + new Transformation(Transformation.Type.TRANSLATE, + new Keyframe(0f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.1667f, VectorHelper.createTranslationalVector(0f, 2f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4167f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("leftArm", + new Transformation(Transformation.Type.ROTATE, + new Keyframe(0f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.1667f, VectorHelper.createRotationalVector(-15f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.25f, VectorHelper.createRotationalVector(-25f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.3333f, VectorHelper.createRotationalVector(5f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4167f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("rightArm", + new Transformation(Transformation.Type.TRANSLATE, + new Keyframe(0f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.1667f, VectorHelper.createTranslationalVector(0f, 2f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4167f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("rightArm", + new Transformation(Transformation.Type.ROTATE, + new Keyframe(0f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.1667f, VectorHelper.createRotationalVector(15f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.25f, VectorHelper.createRotationalVector(25f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.3333f, VectorHelper.createRotationalVector(5f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4167f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("leftLeg", + new Transformation(Transformation.Type.TRANSLATE, + new Keyframe(0f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.1667f, VectorHelper.createTranslationalVector(0f, 2f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4167f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("leftLeg", + new Transformation(Transformation.Type.ROTATE, + new Keyframe(0f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.1667f, VectorHelper.createRotationalVector(15f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.25f, VectorHelper.createRotationalVector(20f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.3333f, VectorHelper.createRotationalVector(-5f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4167f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("rightLeg", + new Transformation(Transformation.Type.TRANSLATE, + new Keyframe(0f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.1667f, VectorHelper.createTranslationalVector(0f, 2f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4167f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("rightLeg", + new Transformation(Transformation.Type.ROTATE, + new Keyframe(0f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.1667f, VectorHelper.createRotationalVector(-15f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.25f, VectorHelper.createRotationalVector(-20f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.3333f, VectorHelper.createRotationalVector(5f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4167f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("bag", + new Transformation(Transformation.Type.TRANSLATE, + new Keyframe(0f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.1667f, VectorHelper.createTranslationalVector(0f, 2f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4167f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("bag", + new Transformation(Transformation.Type.ROTATE, + new Keyframe(0f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.1667f, VectorHelper.createRotationalVector(10f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.25f, VectorHelper.createRotationalVector(15f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.3333f, VectorHelper.createRotationalVector(-5f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4167f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("body", + new Transformation(Transformation.Type.TRANSLATE, + new Keyframe(0f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.1667f, VectorHelper.createTranslationalVector(0f, 2f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4167f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("body", + new Transformation(Transformation.Type.ROTATE, + new Keyframe(0f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.1667f, VectorHelper.createRotationalVector(-1f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.25f, VectorHelper.createRotationalVector(1f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4167f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))).build() + ); + GIVE_REWARD = new KeyframeAnimation("giveReward", Animation.Builder.create(1.5416767f) + .addBoneAnimation("head", + new Transformation(Transformation.Type.ROTATE, + new Keyframe(0f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.375f, VectorHelper.createRotationalVector(-7.5f, -50f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4583f, VectorHelper.createRotationalVector(-7.5f, -40f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.6667f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.8333f, VectorHelper.createRotationalVector(15f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.9583f, VectorHelper.createRotationalVector(15f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.0833f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.25f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.5416767f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("rightArm", + new Transformation(Transformation.Type.TRANSLATE, + new Keyframe(0.625f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.75f, VectorHelper.createTranslationalVector(0f, -2f, -1f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.0833f, VectorHelper.createTranslationalVector(0f, -2f, -1f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.25f, VectorHelper.createTranslationalVector(0f, -2f, -1f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.5416767f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("rightArm", + new Transformation(Transformation.Type.ROTATE, + new Keyframe(0f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.125f, VectorHelper.createRotationalVector(-37.5f, 0f, -20f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.4583f, VectorHelper.createRotationalVector(-170f, 0f, -20f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.5417f, VectorHelper.createRotationalVector(-170f, 0f, -20f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.625f, VectorHelper.createRotationalVector(-60f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.75f, VectorHelper.createRotationalVector(-60f, 20f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.0833f, VectorHelper.createRotationalVector(-60f, 20f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.25f, VectorHelper.createRotationalVector(-60f, 20f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.5416767f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("bag", + new Transformation(Transformation.Type.TRANSLATE, + new Keyframe(0.4583f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.625f, VectorHelper.createTranslationalVector(7f, 0f, -6f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.75f, VectorHelper.createTranslationalVector(-3f, -7f, -12f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.0833f, VectorHelper.createTranslationalVector(-3f, -7f, -12f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.25f, VectorHelper.createTranslationalVector(-3f, -7f, -12f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.375f, VectorHelper.createTranslationalVector(7f, 0f, -6f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.5416767f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("bag", + new Transformation(Transformation.Type.ROTATE, + new Keyframe(0.4583f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.5417f, VectorHelper.createRotationalVector(5f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.625f, VectorHelper.createRotationalVector(0f, 90f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.75f, VectorHelper.createRotationalVector(-30f, 180f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.8333f, VectorHelper.createRotationalVector(-30f, 180f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.0833f, VectorHelper.createRotationalVector(-30f, 180f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.25f, VectorHelper.createRotationalVector(-30f, 180f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.375f, VectorHelper.createRotationalVector(0f, 90f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.4583433f, VectorHelper.createRotationalVector(5f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.5416767f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("leftArm", + new Transformation(Transformation.Type.TRANSLATE, + new Keyframe(0.4583f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.5833f, VectorHelper.createTranslationalVector(0f, -0.25f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.6667f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.75f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.8333f, VectorHelper.createTranslationalVector(0f, -2f, -1f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.25f, VectorHelper.createTranslationalVector(0f, -2f, -1f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.5416767f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("leftArm", + new Transformation(Transformation.Type.ROTATE, + new Keyframe(0.75f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.8333f, VectorHelper.createRotationalVector(-52.5f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.9167f, VectorHelper.createRotationalVector(-65f, -30f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.0833f, VectorHelper.createRotationalVector(-90f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.25f, VectorHelper.createRotationalVector(-90f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.5416767f, VectorHelper.createRotationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))) + .addBoneAnimation("body", + new Transformation(Transformation.Type.TRANSLATE, + new Keyframe(0.4583f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.5833f, VectorHelper.createTranslationalVector(0f, -0.25f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(0.6667f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.0833f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR), + new Keyframe(1.5f, VectorHelper.createTranslationalVector(0f, 0f, 0f), + Transformation.Interpolations.LINEAR))).build() + ); + ANIMATIONS = new ArrayList<>() + {{ + add(DEFAULT); + add(NOD); + add(GIVE_REWARD); + }}; + } +} \ No newline at end of file diff --git a/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/animation/animator/context/AnimationContextTracker.java b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/animation/animator/context/AnimationContextTracker.java index 2f7b6716c..7a83e6682 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/animation/animator/context/AnimationContextTracker.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/animation/animator/context/AnimationContextTracker.java @@ -13,7 +13,13 @@ public final class AnimationContextTracker private final Map animationRotationContext = new HashMap<>(); public KeyframeAnimationContext get(KeyframeAnimation keyframeAnimation) { - return this.animationKeyframeContext.get(keyframeAnimation.getName()); + KeyframeAnimationContext keyframeAnimationContext = this.animationKeyframeContext.get(keyframeAnimation.getName()); + + if (keyframeAnimationContext == null) { + throw new RuntimeException(String.format("Keyframe animation '%s' is not added.", keyframeAnimation.getName())); + } + + return keyframeAnimationContext; } public void add(KeyframeAnimation keyframeAnimation) { @@ -61,4 +67,4 @@ public void remove(String modelPartName, ModelPartAnimationType type) { throw new RuntimeException(String.format("Invalid animation type '%s.'", type)); } } -} +} \ No newline at end of file diff --git a/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/model/AnimatedEntityModel.java b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/model/AnimatedEntityModel.java index d62f79e2e..50ce46c86 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/model/AnimatedEntityModel.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/model/AnimatedEntityModel.java @@ -288,4 +288,13 @@ public static void animateModelPartRotationBasedOnTicks( ticks ); } + + protected void updateKeyframeAnimations( + AnimatedEntity animatedEntity, + float animationProgress + ) { + animatedEntity.getAnimations().forEach((keyframeAnimation -> { + ModelAnimator.updateKeyframeAnimations(animatedEntity, this, keyframeAnimation, animationProgress); + })); + } } \ No newline at end of file diff --git a/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/model/RascalEntityModel.java b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/model/RascalEntityModel.java new file mode 100644 index 000000000..8919c16f7 --- /dev/null +++ b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/model/RascalEntityModel.java @@ -0,0 +1,93 @@ +package com.faboslav.friendsandfoes.client.render.entity.model; + +import com.faboslav.friendsandfoes.entity.RascalEntity; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.model.*; +import net.minecraft.util.math.MathHelper; + +@Environment(EnvType.CLIENT) +public final class RascalEntityModel extends AnimatedEntityModel +{ + private static final String MODEL_PART_HEAD = "head"; + private static final String MODEL_PART_BODY = "body"; + private static final String MODEL_PART_BAG = "bag"; + private static final String MODEL_PART_LEFT_ARM = "leftArm"; + private static final String MODEL_PART_RIGHT_ARM = "rightArm"; + private static final String MODEL_PART_LEFT_LEG = "leftLeg"; + private static final String MODEL_PART_RIGHT_LEG = "rightLeg"; + + private final ModelPart head; + private final ModelPart body; + private final ModelPart bag; + private final ModelPart leftArm; + private final ModelPart rightArm; + private final ModelPart leftLeg; + private final ModelPart rightLeg; + + public RascalEntityModel(ModelPart root) { + super(root); + this.head = this.root.getChild(MODEL_PART_HEAD); + this.body = this.root.getChild(MODEL_PART_BODY); + this.bag = this.root.getChild(MODEL_PART_BAG); + this.leftArm = this.root.getChild(MODEL_PART_LEFT_ARM); + this.rightArm = this.root.getChild(MODEL_PART_RIGHT_ARM); + this.leftLeg = this.root.getChild(MODEL_PART_LEFT_LEG); + this.rightLeg = this.root.getChild(MODEL_PART_RIGHT_LEG); + } + + public static TexturedModelData getTexturedModelData() { + ModelData modelData = new ModelData(); + ModelPartData root = modelData.getRoot(); + + root.addChild(MODEL_PART_HEAD, ModelPartBuilder.create().uv(0, 52).cuboid(-4.0F, -2.0F, -5.0F, 8.0F, 6.0F, 6.0F, new Dilation(0.0F)) + .uv(28, 36).cuboid(-4.0F, -3.0F, -5.0F, 8.0F, 9.0F, 6.0F, new Dilation(0.5F)), ModelTransform.pivot(0.0F, 9.0F, -5.0F)); + root.addChild(MODEL_PART_BODY, ModelPartBuilder.create().uv(0, 0).cuboid(-6.0F, 0.0F, -4.0F, 12.0F, 15.0F, 8.0F, new Dilation(-0.01F)) + .uv(0, 23).cuboid(-6.0F, 12.0F, -4.0F, 12.0F, 5.0F, 8.0F, new Dilation(-0.5F)) + .uv(44, 0).cuboid(3.0F, 0.0F, -4.0F, 2.0F, 15.0F, 8.0F, new Dilation(0.5F)), ModelTransform.pivot(0.0F, 4.0F, 0.0F)); + root.addChild(MODEL_PART_BAG, ModelPartBuilder.create().uv(0, 36).cuboid(-4.0F, -0.5F, -0.5F, 8.0F, 9.0F, 6.0F, new Dilation(0.0F)), ModelTransform.pivot(3.0F, 7.5F, 4.5F)); + root.addChild(MODEL_PART_LEFT_ARM, ModelPartBuilder.create().uv(50, 28).mirrored().cuboid(-3.0F, -2.0F, -2.0F, 3.0F, 10.0F, 4.0F, new Dilation(0.0F)).mirrored(false), ModelTransform.pivot(-6.0F, 11.0F, 0.0F)); + root.addChild(MODEL_PART_RIGHT_ARM, ModelPartBuilder.create().uv(50, 28).cuboid(0.0F, -2.0F, -2.0F, 3.0F, 10.0F, 4.0F, new Dilation(0.0F)), ModelTransform.pivot(6.0F, 11.0F, 0.0F)); + root.addChild(MODEL_PART_LEFT_LEG, ModelPartBuilder.create().uv(28, 54).mirrored().cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 6.0F, 4.0F, new Dilation(0.0F)).mirrored(false), ModelTransform.pivot(-3.0F, 18.0F, 0.0F)); + root.addChild(MODEL_PART_RIGHT_LEG, ModelPartBuilder.create().uv(28, 54).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 6.0F, 4.0F, new Dilation(0.0F)), ModelTransform.pivot(3.0F, 18.0F, 0.0F)); + + return TexturedModelData.of(modelData, 64, 64); + } + + @Override + public void animateModel( + T rascal, + float limbAngle, + float limbDistance, + float tickDelta + ) { + this.updateAnimations(rascal, limbAngle, limbDistance); + } + + @Override + public void setAngles( + T rascal, + float limbAngle, + float limbDistance, + float animationProgress, + float headYaw, + float headPitch + ) { + this.updateKeyframeAnimations(rascal, animationProgress); + } + + private void updateAnimations( + T rascal, + float limbAngle, + float limbDistance + ) { + this.applyModelTransforms(MODEL_PART_ROOT, this.root); + + this.rightLeg.pitch = -2.0F * MathHelper.wrap(limbAngle, 13.0F) * limbDistance; + this.leftLeg.pitch = 2.0F * MathHelper.wrap(limbAngle, 13.0F) * limbDistance; + this.rightLeg.yaw = 0.0F; + this.leftLeg.yaw = 0.0F; + this.leftArm.pitch = (-0.2F + 2.0F * MathHelper.wrap(limbAngle, 13.0F)) * limbDistance; + this.rightArm.pitch = (-0.2F - 2.0F * MathHelper.wrap(limbAngle, 13.0F)) * limbDistance; + } +} \ No newline at end of file diff --git a/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/model/TuffGolemEntityModel.java b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/model/TuffGolemEntityModel.java index 33664758b..d3209234a 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/model/TuffGolemEntityModel.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/model/TuffGolemEntityModel.java @@ -1,7 +1,5 @@ package com.faboslav.friendsandfoes.client.render.entity.model; -import com.faboslav.friendsandfoes.client.render.entity.animation.TuffGolemAnimations; -import com.faboslav.friendsandfoes.client.render.entity.animation.animator.ModelAnimator; import com.faboslav.friendsandfoes.entity.TuffGolemEntity; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -105,13 +103,4 @@ private void updateAnimations( this.rightArm.pitch = (-0.2F - 2.0F * MathHelper.wrap(limbAngle, 13.0F)) * limbDistance; } } - - private void updateKeyframeAnimations( - T tuffGolem, - float animationProgress - ) { - TuffGolemAnimations.ANIMATIONS.forEach((keyframeAnimation -> { - ModelAnimator.updateKeyframeAnimations(tuffGolem, this, keyframeAnimation, animationProgress); - })); - } } \ No newline at end of file diff --git a/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/renderer/RascalEntityRenderer.java b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/renderer/RascalEntityRenderer.java new file mode 100644 index 000000000..262594693 --- /dev/null +++ b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/renderer/RascalEntityRenderer.java @@ -0,0 +1,25 @@ +package com.faboslav.friendsandfoes.client.render.entity.renderer; + +import com.faboslav.friendsandfoes.FriendsAndFoes; +import com.faboslav.friendsandfoes.client.render.entity.model.RascalEntityModel; +import com.faboslav.friendsandfoes.entity.RascalEntity; +import com.faboslav.friendsandfoes.init.FriendsAndFoesEntityModelLayer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.render.entity.EntityRendererFactory; +import net.minecraft.client.render.entity.MobEntityRenderer; +import net.minecraft.util.Identifier; + +@Environment(EnvType.CLIENT) +@SuppressWarnings({"rawtypes", "unchecked"}) +public final class RascalEntityRenderer extends MobEntityRenderer> +{ + public RascalEntityRenderer(EntityRendererFactory.Context context) { + super(context, new RascalEntityModel(context.getPart(FriendsAndFoesEntityModelLayer.RASCAL_LAYER)), 0.5F); + } + + @Override + public Identifier getTexture(RascalEntity entity) { + return FriendsAndFoes.makeID("textures/entity/rascal/rascal.png"); + } +} diff --git a/common/src/main/java/com/faboslav/friendsandfoes/config/FriendsAndFoesConfig.java b/common/src/main/java/com/faboslav/friendsandfoes/config/FriendsAndFoesConfig.java index 1cbf7e65f..0a47a5e8b 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/config/FriendsAndFoesConfig.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/config/FriendsAndFoesConfig.java @@ -132,6 +132,13 @@ public final class FriendsAndFoesConfig implements Config @Description("Enable trap") public boolean enableZombieHorseTrap = true; + @Category("Rascal") + @Description("Enable rascal") + public boolean enableRascal = true; + + @Description("Enable rascal spawn") + public boolean enableRascalSpawn = true; + @Category("Tuff Golem") @Description("Enable tuff golem") public boolean enableTuffGolem = true; diff --git a/common/src/main/java/com/faboslav/friendsandfoes/entity/RascalEntity.java b/common/src/main/java/com/faboslav/friendsandfoes/entity/RascalEntity.java new file mode 100644 index 000000000..ea30f1382 --- /dev/null +++ b/common/src/main/java/com/faboslav/friendsandfoes/entity/RascalEntity.java @@ -0,0 +1,442 @@ +package com.faboslav.friendsandfoes.entity; + +import com.faboslav.friendsandfoes.FriendsAndFoes; +import com.faboslav.friendsandfoes.client.render.entity.animation.KeyframeAnimation; +import com.faboslav.friendsandfoes.client.render.entity.animation.RascalAnimations; +import com.faboslav.friendsandfoes.client.render.entity.animation.animator.context.AnimationContextTracker; +import com.faboslav.friendsandfoes.entity.ai.brain.RascalBrain; +import com.faboslav.friendsandfoes.entity.animation.AnimatedEntity; +import com.faboslav.friendsandfoes.entity.pose.RascalEntityPose; +import com.faboslav.friendsandfoes.init.FriendsAndFoesSoundEvents; +import com.faboslav.friendsandfoes.util.RandomGenerator; +import com.mojang.serialization.Dynamic; +import net.minecraft.block.BlockState; +import net.minecraft.entity.*; +import net.minecraft.entity.ai.brain.Brain; +import net.minecraft.entity.ai.brain.MemoryModuleType; +import net.minecraft.entity.ai.pathing.PathNodeType; +import net.minecraft.entity.attribute.DefaultAttributeContainer; +import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.data.DataTracker; +import net.minecraft.entity.data.TrackedData; +import net.minecraft.entity.data.TrackedDataHandlerRegistry; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.entity.effect.StatusEffects; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.passive.PassiveEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.particle.ParticleEffect; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.registry.tag.StructureTags; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.sound.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.LocalDifficulty; +import net.minecraft.world.ServerWorldAccess; +import net.minecraft.world.World; +import net.minecraft.world.gen.StructureAccessor; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public final class RascalEntity extends PassiveEntity implements AnimatedEntity +{ + private AnimationContextTracker animationContextTracker; + private static final TrackedData POSE_TICKS; + private static final TrackedData CAUGHT_COUNT; + private boolean ambientSounds; + + public RascalEntity(EntityType entityType, World world) { + super(entityType, world); + this.enableAmbientSounds(); + this.setPathfindingPenalty(PathNodeType.RAIL, 0.0F); + this.setPathfindingPenalty(PathNodeType.UNPASSABLE_RAIL, 0.0F); + this.setPathfindingPenalty(PathNodeType.WATER, 0.0F); + this.setPathfindingPenalty(PathNodeType.WATER_BORDER, 0.0F); + } + + @Override + public EntityData initialize( + ServerWorldAccess world, + LocalDifficulty difficulty, + SpawnReason spawnReason, + @Nullable EntityData entityData, + @Nullable NbtCompound entityNbt + ) { + EntityData superEntityData = super.initialize(world, difficulty, spawnReason, entityData, entityNbt); + + this.setPose(RascalEntityPose.DEFAULT); + RascalBrain.setNodCooldown(this); + + return superEntityData; + } + + public static boolean canSpawn( + EntityType rascalEntityType, + ServerWorldAccess serverWorldAccess, + SpawnReason spawnReason, + BlockPos blockPos, + Random random + ) { + if (spawnReason == SpawnReason.NATURAL) { + ServerWorld serverWorld = serverWorldAccess.toServerWorld(); + StructureAccessor structureAccessor = serverWorld.getStructureAccessor(); + + if (structureAccessor.getStructureContaining( + blockPos, + StructureTags.MINESHAFT + ).hasChildren() == false) { + return false; + } + + List nearbyRascals = serverWorld.getEntitiesByClass(RascalEntity.class, new Box(blockPos).expand(32.0F), (rascalEntity) -> true); + + if (nearbyRascals.isEmpty() == false) { + return false; + } + + if (blockPos.getY() < 63 && serverWorldAccess.isSkyVisible(blockPos) == false) { + return true; + } + } + + return false; + } + + @Override + public AnimationContextTracker getAnimationContextTracker() { + if (this.animationContextTracker == null) { + this.animationContextTracker = new AnimationContextTracker(); + + for (KeyframeAnimation keyframeAnimation : this.getAnimations()) { + this.animationContextTracker.add(keyframeAnimation); + } + } + + return this.animationContextTracker; + } + + @Override + public ArrayList getAnimations() { + return RascalAnimations.ANIMATIONS; + } + + @Override + public int getKeyframeAnimationTicks() { + return this.dataTracker.get(POSE_TICKS); + } + + public void setKeyframeAnimationTicks(int keyframeAnimationTicks) { + this.dataTracker.set(POSE_TICKS, keyframeAnimationTicks); + } + + @Override + protected void initDataTracker() { + super.initDataTracker(); + this.dataTracker.startTracking(POSE_TICKS, 0); + this.dataTracker.startTracking(CAUGHT_COUNT, 0); + } + + @Nullable + @Override + public PassiveEntity createChild(ServerWorld world, PassiveEntity entity) { + return null; + } + + @Override + protected Brain deserializeBrain(Dynamic dynamic) { + return RascalBrain.create(dynamic); + } + + @Override + @SuppressWarnings("all") + public Brain getBrain() { + return (Brain) super.getBrain(); + } + + @Override + protected void mobTick() { + this.getWorld().getProfiler().push("rascalBrain"); + this.getBrain().tick((ServerWorld) this.getWorld(), this); + this.getWorld().getProfiler().pop(); + this.getWorld().getProfiler().push("rascalActivityUpdate"); + RascalBrain.updateActivities(this); + this.getWorld().getProfiler().pop(); + + super.mobTick(); + } + + public static DefaultAttributeContainer.Builder createAttributes() { + return MobEntity.createMobAttributes() + .add(EntityAttributes.GENERIC_MAX_HEALTH, 20.0D) + .add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.55D) + .add(EntityAttributes.GENERIC_KNOCKBACK_RESISTANCE, 1.0D); + } + + @Override + public void tick() { + if (FriendsAndFoes.getConfig().enableRascal == false) { + this.discard(); + } + + StatusEffectInstance invisibilityStatusEffect = this.getStatusEffect(StatusEffects.INVISIBILITY); + + if (this.isHidden() && invisibilityStatusEffect != null && invisibilityStatusEffect.getDuration() == 1) { + this.playReappearSound(); + } + + if (this.getWorld().isClient() == false && this.isAnyKeyframeAnimationRunning()) { + this.setKeyframeAnimationTicks(this.getKeyframeAnimationTicks() - 1); + } + + KeyframeAnimation keyframeAnimationToStart = this.getKeyframeAnimationByPose(); + + if ( + keyframeAnimationToStart != null + && this.isKeyframeAnimationRunning(keyframeAnimationToStart) == false + ) { + if (this.getWorld().isClient() == false) { + this.setKeyframeAnimationTicks(keyframeAnimationToStart.getAnimationLengthInTicks()); + } + + this.startKeyframeAnimation(keyframeAnimationToStart); + } + + super.tick(); + } + + @Nullable + private KeyframeAnimation getKeyframeAnimationByPose() { + KeyframeAnimation keyframeAnimation = null; + + if (this.isInPose(RascalEntityPose.DEFAULT)) { + keyframeAnimation = RascalAnimations.DEFAULT; + } else if (this.isInPose(RascalEntityPose.NOD)) { + keyframeAnimation = RascalAnimations.NOD; + } else if (this.isInPose(RascalEntityPose.GIVE_REWARD)) { + keyframeAnimation = RascalAnimations.GIVE_REWARD; + } + + return keyframeAnimation; + } + + private void startKeyframeAnimation(KeyframeAnimation keyframeAnimationToStart) { + for (KeyframeAnimation keyframeAnimation : RascalAnimations.ANIMATIONS) { + if (keyframeAnimation == keyframeAnimationToStart) { + continue; + } + + this.stopKeyframeAnimation(keyframeAnimation); + } + + this.startKeyframeAnimation(keyframeAnimationToStart, this.age); + } + + + @Override + public void setPose(EntityPose pose) { + if (this.getWorld().isClient()) { + return; + } + + super.setPose(pose); + } + + public void setPose(RascalEntityPose pose) { + if (this.getWorld().isClient()) { + return; + } + + super.setPose(pose.get()); + } + + public boolean isInPose(RascalEntityPose pose) { + return this.getPose() == pose.get(); + } + + public void startNodAnimation() { + if (this.isInPose(RascalEntityPose.NOD)) { + return; + } + + this.playNodSound(); + this.setPose(RascalEntityPose.NOD); + } + + public void startGiveRewardAnimation() { + if (this.isInPose(RascalEntityPose.GIVE_REWARD)) { + return; + } + + this.playRewardSound(); + this.setPose(RascalEntityPose.GIVE_REWARD); + } + + @Override + public boolean damage( + DamageSource source, float amount + ) { + Entity attacker = source.getAttacker(); + + if ( + attacker == null + || attacker instanceof PlayerEntity == false + ) { + return super.damage(source, amount); + } + + this.playHurtSound(source); + this.playDisappearSound(); + this.spawnCloudParticles(); + this.discard(); + + return false; + } + + public SoundEvent getNodSound() { + return FriendsAndFoesSoundEvents.ENTITY_RASCAL_NOD.get(); + } + + public void playNodSound() { + this.playSound(this.getNodSound(), 1.0F, RandomGenerator.generateFloat(1.15F, 1.3F)); + } + + public SoundEvent getRewardSound() { + return FriendsAndFoesSoundEvents.ENTITY_RASCAL_REWARD.get(); + } + + public void playRewardSound() { + this.playSound(this.getRewardSound(), 1.0F, RandomGenerator.generateFloat(1.15F, 1.3F)); + } + + public SoundEvent getBadRewardSound() { + return FriendsAndFoesSoundEvents.ENTITY_RASCAL_REWARD_BAD.get(); + } + + public void playBadRewardSound() { + this.playSound(this.getBadRewardSound(), 1.0F, RandomGenerator.generateFloat(1.15F, 1.3F)); + } + + @Override + protected SoundEvent getAmbientSound() { + return FriendsAndFoesSoundEvents.ENTITY_RASCAL_AMBIENT.get(); + } + + @Override + public void playAmbientSound() { + if (this.isHidden() || this.ambientSounds == false) { + return; + } + + SoundEvent soundEvent = this.getAmbientSound(); + this.playSound(soundEvent, 1.5F, RandomGenerator.generateFloat(1.15F, 1.3F)); + } + + @Override + protected SoundEvent getHurtSound(DamageSource source) { + return FriendsAndFoesSoundEvents.ENTITY_RASCAL_HURT.get(); + } + + @Override + protected void playHurtSound(DamageSource source) { + this.ambientSoundChance = -this.getMinAmbientSoundDelay(); + this.playSound(this.getHurtSound(source), 1.0F, RandomGenerator.generateFloat(1.15F, 1.3F)); + } + + public SoundEvent getDisappearSound() { + return FriendsAndFoesSoundEvents.ENTITY_RASCAL_DISAPPEAR.get(); + } + + public void playDisappearSound() { + SoundEvent soundEvent = this.getDisappearSound(); + this.playSound(soundEvent, 1.5F, RandomGenerator.generateFloat(1.5F, 1.6F)); + } + + public SoundEvent getReappearSound() { + return FriendsAndFoesSoundEvents.ENTITY_RASCAL_REAPPEAR.get(); + } + + public void playReappearSound() { + SoundEvent soundEvent = this.getReappearSound(); + this.playSound(soundEvent, 1.5F, RandomGenerator.generateFloat(1.5F, 1.6F)); + } + + @Override + protected void playStepSound( + BlockPos pos, + BlockState state + ) { + if ( + this.isHidden() + || state.isLiquid() + ) { + return; + } + + super.playStepSound(pos, state); + } + + public boolean isHidden() { + return this.getBrain().getOptionalRegisteredMemory(MemoryModuleType.AVOID_TARGET).orElse(null) instanceof PlayerEntity; + } + + public int getCaughtCount() { + return this.dataTracker.get(CAUGHT_COUNT); + } + + public void addToCaughtCount() { + this.dataTracker.set(CAUGHT_COUNT, this.getCaughtCount() + 1); + } + + public boolean shouldGiveReward() { + return this.getCaughtCount() >= 3; + } + + public boolean disableAmbientSounds() { + return this.ambientSounds = false; + } + + public boolean enableAmbientSounds() { + return this.ambientSounds = true; + } + + public void spawnCloudParticles() { + this.spawnParticles(ParticleTypes.CLOUD, 16, 0.1D); + } + + public void spawnParticles( + ParticleEffect particleEffect, + int amount, + double speed + ) { + World world = this.getWorld(); + + if (world.isClient()) { + return; + } + + for (int i = 0; i < amount; i++) { + ((ServerWorld) world).spawnParticles( + particleEffect, + this.getParticleX(1.0D), + this.getRandomBodyY() + 0.5D, + this.getParticleZ(1.0D), + 1, + this.getRandom().nextGaussian() * 0.02D, + this.getRandom().nextGaussian() * 0.02D, + this.getRandom().nextGaussian() * 0.02D, + speed + ); + } + } + + static { + POSE_TICKS = DataTracker.registerData(RascalEntity.class, TrackedDataHandlerRegistry.INTEGER); + CAUGHT_COUNT = DataTracker.registerData(RascalEntity.class, TrackedDataHandlerRegistry.INTEGER); + } +} diff --git a/common/src/main/java/com/faboslav/friendsandfoes/entity/TuffGolemEntity.java b/common/src/main/java/com/faboslav/friendsandfoes/entity/TuffGolemEntity.java index ca572196c..9b810cb71 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/entity/TuffGolemEntity.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/entity/TuffGolemEntity.java @@ -28,11 +28,11 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.particle.ParticleEffect; import net.minecraft.particle.ParticleTypes; +import net.minecraft.registry.tag.BlockTags; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.BlockSoundGroup; import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvents; -import net.minecraft.tag.BlockTags; import net.minecraft.util.ActionResult; import net.minecraft.util.DyeColor; import net.minecraft.util.Hand; @@ -44,6 +44,8 @@ import net.minecraft.world.event.GameEvent; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; + public final class TuffGolemEntity extends GolemEntity implements AnimatedEntity { private static final TrackedData COLOR; @@ -84,7 +86,7 @@ public AnimationContextTracker getAnimationContextTracker() { if (this.animationContextTracker == null) { this.animationContextTracker = new AnimationContextTracker(); - for (KeyframeAnimation keyframeAnimation : TuffGolemAnimations.ANIMATIONS) { + for (KeyframeAnimation keyframeAnimation : this.getAnimations()) { this.animationContextTracker.add(keyframeAnimation); } } @@ -92,6 +94,11 @@ public AnimationContextTracker getAnimationContextTracker() { return this.animationContextTracker; } + @Override + public ArrayList getAnimations() { + return TuffGolemAnimations.ANIMATIONS; + } + @Override public int getKeyframeAnimationTicks() { return this.dataTracker.get(POSE_TICKS); @@ -106,7 +113,6 @@ public TuffGolemEntity( World world ) { super(entityType, world); - this.stepHeight = 1.0F; } @Override @@ -286,7 +292,7 @@ protected void playStepSound( ) { if ( this.isInSleepingPose() - || state.getMaterial().isLiquid() + || state.isLiquid() ) { return; } @@ -701,7 +707,7 @@ public boolean damage( if ( attacker == null || attacker instanceof LightningEntity - || source == DamageSource.SWEET_BERRY_BUSH + || source == this.getDamageSources().sweetBerryBush() ) { return false; } @@ -961,4 +967,3 @@ public static TuffGolemEntity.Color fromWool(Block block) { } } } - diff --git a/common/src/main/java/com/faboslav/friendsandfoes/entity/WildfireShieldDebrisEntity.java b/common/src/main/java/com/faboslav/friendsandfoes/entity/WildfireShieldDebrisEntity.java index 076eef104..73d3f8196 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/entity/WildfireShieldDebrisEntity.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/entity/WildfireShieldDebrisEntity.java @@ -100,7 +100,7 @@ private SoundEvent getImpactSound() { private void playImpactSound() { SoundEvent soundEvent = this.getImpactSound(); - this.playSound(soundEvent, 1.0F, 0.95F + RandomGenerator.generateFloat(0.95F, 1.05F)); + this.playSound(soundEvent, 1.0F, 0.95F + RandomGenerator.generateFloat(0.95F, 1.05F)); } } diff --git a/common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/RascalBrain.java b/common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/RascalBrain.java new file mode 100644 index 000000000..03ca550ab --- /dev/null +++ b/common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/RascalBrain.java @@ -0,0 +1,170 @@ +package com.faboslav.friendsandfoes.entity.ai.brain; + +import com.faboslav.friendsandfoes.entity.RascalEntity; +import com.faboslav.friendsandfoes.entity.ai.brain.task.rascal.RascalFindInteractionTargetTask; +import com.faboslav.friendsandfoes.entity.ai.brain.task.rascal.RascalWaitForPlayerTask; +import com.faboslav.friendsandfoes.init.FriendsAndFoesActivities; +import com.faboslav.friendsandfoes.init.FriendsAndFoesMemoryModuleTypes; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Dynamic; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.Activity; +import net.minecraft.entity.ai.brain.Brain; +import net.minecraft.entity.ai.brain.MemoryModuleType; +import net.minecraft.entity.ai.brain.sensor.Sensor; +import net.minecraft.entity.ai.brain.sensor.SensorType; +import net.minecraft.entity.ai.brain.task.*; +import net.minecraft.util.TimeHelper; +import net.minecraft.util.math.intprovider.UniformIntProvider; + +import java.util.List; + +@SuppressWarnings({"rawtypes", "unchecked"}) +public final class RascalBrain +{ + public static final List> MEMORY_MODULES; + public static final List>> SENSORS; + public final static int NOD_COOLDOWN = 10; + private static final UniformIntProvider NOD_COOLDOWN_PROVIDER; + private static final UniformIntProvider AVOID_MEMORY_DURATION; + + public RascalBrain() { + } + + public static Brain create(Dynamic dynamic) { + Brain.Profile profile = Brain.createProfile(MEMORY_MODULES, SENSORS); + Brain brain = profile.deserialize(dynamic); + + addCoreActivities(brain); + addIdleActivities(brain); + addWaitActivities(brain); + addAvoidActivities(brain); + + brain.setCoreActivities(ImmutableSet.of(Activity.CORE)); + brain.setDefaultActivity(Activity.IDLE); + brain.resetPossibleActivities(); + + return brain; + } + + private static void addCoreActivities(Brain brain) { + brain.setTaskList(Activity.CORE, + 0, + ImmutableList.of( + new StayAboveWaterTask(0.8F), + new LookAroundTask(45, 90), + new WanderAroundTask(), + new TemptationCooldownTask(FriendsAndFoesMemoryModuleTypes.RASCAL_NOD_COOLDOWN.get()) + ) + ); + } + + private static void addIdleActivities(Brain brain) { + brain.setTaskList( + Activity.IDLE, + ImmutableList.of( + Pair.of(0, RascalFindInteractionTargetTask.create(6)), + Pair.of(0, makeRandomWanderTask()) + ) + ); + } + + private static void addWaitActivities( + Brain brain + ) { + brain.setTaskList( + FriendsAndFoesActivities.RASCAL_WAIT.get(), + 10, + ImmutableList.of( + new RascalWaitForPlayerTask() + ), MemoryModuleType.INTERACTION_TARGET + ); + } + + private static void addAvoidActivities(Brain brain) { + brain.setTaskList( + Activity.AVOID, + 10, + ImmutableList.of( + GoToRememberedPositionTask.createEntityBased(MemoryModuleType.AVOID_TARGET, 1.0F, 32, true) + ), + MemoryModuleType.AVOID_TARGET + ); + } + + public static void updateActivities(RascalEntity rascal) { + rascal.getBrain().resetPossibleActivities( + ImmutableList.of( + FriendsAndFoesActivities.RASCAL_WAIT.get(), + Activity.AVOID, + Activity.IDLE + ) + ); + } + + private static RandomTask makeRandomWanderTask() { + return new RandomTask( + ImmutableList.of( + Pair.of(StrollTask.create(0.6F), 2), + Pair.of(new WaitTask(30, 60), 1) + ) + ); + } + + public static void setNodCooldown(RascalEntity rascal) { + rascal.getBrain().remember(FriendsAndFoesMemoryModuleTypes.RASCAL_NOD_COOLDOWN.get(), NOD_COOLDOWN_PROVIDER.get(rascal.getRandom())); + onCooldown(rascal); + } + + public static boolean shouldRunAway(RascalEntity rascal) { + return rascal.getBrain().getOptionalRegisteredMemory(FriendsAndFoesMemoryModuleTypes.RASCAL_NOD_COOLDOWN.get()).isPresent(); + } + + public static void onCooldown(RascalEntity rascal) { + if (shouldRunAway(rascal) == false) { + return; + } + + if (rascal.hasCustomName()) { + return; + } + + LivingEntity nearestTarget = rascal.getBrain().getOptionalRegisteredMemory(MemoryModuleType.INTERACTION_TARGET).orElse(null); + + if (nearestTarget == null) { + return; + } + + runAwayFrom(rascal, nearestTarget); + } + + private static void runAwayFrom(RascalEntity rascal, LivingEntity target) { + rascal.getBrain().forget(MemoryModuleType.LOOK_TARGET); + rascal.getBrain().forget(MemoryModuleType.WALK_TARGET); + rascal.getBrain().forget(MemoryModuleType.INTERACTION_TARGET); + rascal.getBrain().remember(MemoryModuleType.AVOID_TARGET, target, AVOID_MEMORY_DURATION.get(rascal.getRandom())); + } + + static { + SENSORS = List.of( + SensorType.NEAREST_LIVING_ENTITIES, + SensorType.NEAREST_PLAYERS + ); + MEMORY_MODULES = List.of( + MemoryModuleType.VISIBLE_MOBS, + MemoryModuleType.PATH, + MemoryModuleType.LOOK_TARGET, + MemoryModuleType.WALK_TARGET, + MemoryModuleType.AVOID_TARGET, + MemoryModuleType.INTERACTION_TARGET, + MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, + MemoryModuleType.NEAREST_PLAYERS, + MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, + FriendsAndFoesMemoryModuleTypes.RASCAL_NOD_COOLDOWN.get() + ); + NOD_COOLDOWN_PROVIDER = TimeHelper.betweenSeconds(NOD_COOLDOWN, NOD_COOLDOWN); + AVOID_MEMORY_DURATION = TimeHelper.betweenSeconds(NOD_COOLDOWN, NOD_COOLDOWN); + } +} \ No newline at end of file diff --git a/common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/WildfireBrain.java b/common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/WildfireBrain.java index a666e42ba..ad5c2dd62 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/WildfireBrain.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/WildfireBrain.java @@ -63,7 +63,8 @@ private static void addCoreActivities(Brain brain) { new TemptationCooldownTask(FriendsAndFoesMemoryModuleTypes.WILDFIRE_BARRAGE_ATTACK_COOLDOWN.get()), new TemptationCooldownTask(FriendsAndFoesMemoryModuleTypes.WILDFIRE_SHOCKWAVE_ATTACK_COOLDOWN.get()), new TemptationCooldownTask(FriendsAndFoesMemoryModuleTypes.WILDFIRE_SUMMON_BLAZE_COOLDOWN.get()) - )); + ) + ); } private static void addIdleActivities(Brain brain) { diff --git a/common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/task/rascal/RascalFindInteractionTargetTask.java b/common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/task/rascal/RascalFindInteractionTargetTask.java new file mode 100644 index 000000000..76d5c06d4 --- /dev/null +++ b/common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/task/rascal/RascalFindInteractionTargetTask.java @@ -0,0 +1,34 @@ +package com.faboslav.friendsandfoes.entity.ai.brain.task.rascal; + +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.EntityLookTarget; +import net.minecraft.entity.ai.brain.MemoryModuleType; +import net.minecraft.entity.ai.brain.task.Task; +import net.minecraft.entity.player.PlayerEntity; + +import java.util.Optional; + +public final class RascalFindInteractionTargetTask +{ + public static Task create(int maxDistance) { + int squaredMaxDistance = maxDistance * maxDistance; + return TaskTriggerer.task((context) -> { + return context.group(context.queryMemoryOptional(MemoryModuleType.LOOK_TARGET), context.queryMemoryAbsent(MemoryModuleType.INTERACTION_TARGET), context.queryMemoryValue(MemoryModuleType.VISIBLE_MOBS)).apply(context, (lookTarget, interactionTarget, visibleMobs) -> { + return (world, entity, time) -> { + Optional optional = context.getValue(visibleMobs).findFirst((target) -> { + return target.squaredDistanceTo(entity) <= (double) squaredMaxDistance && target instanceof PlayerEntity && !target.isSpectator() && !((PlayerEntity) target).isCreative(); + }); + + if (optional.isEmpty()) { + return false; + } else { + LivingEntity livingEntity = optional.get(); + interactionTarget.remember(livingEntity); + lookTarget.remember(new EntityLookTarget(livingEntity, true)); + return true; + } + }; + }); + }); + } +} \ No newline at end of file diff --git a/common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/task/rascal/RascalWaitForPlayerTask.java b/common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/task/rascal/RascalWaitForPlayerTask.java new file mode 100644 index 000000000..86117edcc --- /dev/null +++ b/common/src/main/java/com/faboslav/friendsandfoes/entity/ai/brain/task/rascal/RascalWaitForPlayerTask.java @@ -0,0 +1,197 @@ +package com.faboslav.friendsandfoes.entity.ai.brain.task.rascal; + +import com.faboslav.friendsandfoes.FriendsAndFoes; +import com.faboslav.friendsandfoes.entity.RascalEntity; +import com.faboslav.friendsandfoes.entity.ai.brain.RascalBrain; +import com.faboslav.friendsandfoes.entity.pose.RascalEntityPose; +import com.faboslav.friendsandfoes.init.FriendsAndFoesCriteria; +import com.faboslav.friendsandfoes.init.FriendsAndFoesMemoryModuleTypes; +import com.faboslav.friendsandfoes.mixin.BundleItemAccessor; +import com.google.common.collect.ImmutableMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.ai.brain.MemoryModuleState; +import net.minecraft.entity.ai.brain.MemoryModuleType; +import net.minecraft.entity.ai.brain.task.LookTargetUtil; +import net.minecraft.entity.ai.brain.task.MultiTickTask; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.entity.effect.StatusEffects; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.loot.LootManager; +import net.minecraft.loot.LootTable; +import net.minecraft.loot.context.LootContextParameterSet; +import net.minecraft.loot.context.LootContextParameters; +import net.minecraft.loot.context.LootContextTypes; +import net.minecraft.registry.tag.StructureTags; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.gen.StructureAccessor; + +public final class RascalWaitForPlayerTask extends MultiTickTask +{ + private final static int NOD_DURATION = 90; + public final static float NOD_RANGE = 4F; + + private int nodTicks; + private LivingEntity nearestTarget; + + public RascalWaitForPlayerTask() { + super(ImmutableMap.of( + MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, MemoryModuleState.REGISTERED, + MemoryModuleType.INTERACTION_TARGET, MemoryModuleState.VALUE_PRESENT, + FriendsAndFoesMemoryModuleTypes.RASCAL_NOD_COOLDOWN.get(), MemoryModuleState.VALUE_ABSENT + ), NOD_DURATION); + } + + @Override + protected boolean shouldRun(ServerWorld world, RascalEntity rascal) { + if (rascal.hasCustomName()) { + return false; + } + + LivingEntity nearestTarget = rascal.getBrain().getOptionalRegisteredMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER).orElse(null); + + if (nearestTarget == null) { + nearestTarget = rascal.getBrain().getOptionalRegisteredMemory(MemoryModuleType.INTERACTION_TARGET).orElse(null); + } + + if ( + nearestTarget == null + || rascal.distanceTo(nearestTarget) > NOD_RANGE + || nearestTarget.isAlive() == false + || ( + nearestTarget instanceof PlayerEntity + && ( + nearestTarget.isSpectator() + || ((PlayerEntity) nearestTarget).isCreative() + ) + ) + ) { + return false; + } + + this.nearestTarget = nearestTarget; + + return true; + } + + @Override + protected void run(ServerWorld world, RascalEntity rascal, long time) { + rascal.getBrain().forget(MemoryModuleType.WALK_TARGET); + rascal.getNavigation().setSpeed(0); + rascal.getNavigation().stop(); + rascal.getNavigation().tick(); + rascal.getMoveControl().tick(); + + rascal.setMovementSpeed(0.0F); + rascal.prevHorizontalSpeed = 0.0F; + rascal.horizontalSpeed = 0.0F; + rascal.sidewaysSpeed = 0.0F; + rascal.upwardSpeed = 0.0F; + + LookTargetUtil.lookAt(rascal, this.nearestTarget); + rascal.getLookControl().lookAt(this.nearestTarget); + rascal.getLookControl().tick(); + + this.nodTicks = 0; + rascal.addToCaughtCount(); + rascal.disableAmbientSounds(); + } + + @Override + protected boolean shouldKeepRunning(ServerWorld world, RascalEntity rascal, long time) { + return this.nodTicks <= NOD_DURATION; + } + + @Override + protected void keepRunning(ServerWorld world, RascalEntity rascal, long time) { + if (nodTicks == 20) { + rascal.startNodAnimation(); + rascal.getLookControl().lookAt(this.nearestTarget); + } + + if (nodTicks == 40 && rascal.shouldGiveReward()) { + rascal.startGiveRewardAnimation(); + } + + if (nodTicks == 62 && rascal.shouldGiveReward()) { + Vec3d targetPos = nearestTarget.getPos().add(0.0, 1.0, 0.0); + LootManager lootManager = world.getServer().getLootManager(); + + if (lootManager != null) { + LootTable rascalGoodItemsLootTable = lootManager.getLootTable( + FriendsAndFoes.makeID("rewards/rascal_good_reward") + ); + LootContextParameterSet lootContextParameterSet = new LootContextParameterSet.Builder(world) + .add(LootContextParameters.ORIGIN, targetPos) + .add(LootContextParameters.THIS_ENTITY, this.nearestTarget) + .build(LootContextTypes.GIFT); + ObjectArrayList rascalGoodRewards = rascalGoodItemsLootTable.generateLoot(lootContextParameterSet); + + for (ItemStack rascalReward : rascalGoodRewards) { + ItemStack bundleItemStack = Items.BUNDLE.getDefaultStack(); + ((BundleItemAccessor) bundleItemStack.getItem()).invokeAddToBundle(bundleItemStack, rascalReward); + LookTargetUtil.give(rascal, bundleItemStack, nearestTarget.getPos().add(0.0, 1.0, 0.0)); + } + } + + FriendsAndFoesCriteria.COMPLETE_HIDE_AND_SEEK_GAME.trigger((ServerPlayerEntity) this.nearestTarget, rascal); + } + + this.nodTicks++; + } + + @Override + protected void finishRunning(ServerWorld world, RascalEntity rascal, long time) { + if (rascal.hasCustomName()) { + RascalBrain.setNodCooldown(rascal); + return; + } + + rascal.spawnCloudParticles(); + rascal.playDisappearSound(); + + if (rascal.shouldGiveReward()) { + rascal.discard(); + return; + } + + rascal.setPose(RascalEntityPose.DEFAULT); + rascal.addStatusEffect(new StatusEffectInstance(StatusEffects.INVISIBILITY, RascalBrain.NOD_COOLDOWN * 20)); + this.tryToTeleport(world, rascal); + RascalBrain.setNodCooldown(rascal); + rascal.enableAmbientSounds(); + } + + private void tryToTeleport(ServerWorld world, RascalEntity rascal) { + StructureAccessor structureAccessor = world.getStructureAccessor(); + + for (int i = 0; i < 32; ++i) { + double x = rascal.getX() + (rascal.getRandom().nextDouble() - 0.5) * 24.0; + double y = MathHelper.clamp(rascal.getY() + (double) (rascal.getRandom().nextInt(16) - 8), world.getBottomY(), world.getBottomY() + world.getLogicalHeight() - 1); + double z = rascal.getZ() + (rascal.getRandom().nextDouble() - 0.5) * 24.0; + + if (structureAccessor.getStructureContaining( + new BlockPos((int) x, (int) y, (int) z), + StructureTags.MINESHAFT + ).hasChildren() == false) { + continue; + } + + if (rascal.hasVehicle()) { + rascal.stopRiding(); + } + + boolean teleportResult = rascal.teleport(x, y, z, false); + + if (teleportResult) { + return; + } + } + } +} \ No newline at end of file diff --git a/common/src/main/java/com/faboslav/friendsandfoes/entity/animation/AnimatedEntity.java b/common/src/main/java/com/faboslav/friendsandfoes/entity/animation/AnimatedEntity.java index 28149315a..1aee62d18 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/entity/animation/AnimatedEntity.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/entity/animation/AnimatedEntity.java @@ -4,10 +4,16 @@ import com.faboslav.friendsandfoes.client.render.entity.animation.animator.context.AnimationContextTracker; import com.faboslav.friendsandfoes.client.render.entity.animation.animator.context.KeyframeAnimationContext; +import java.util.ArrayList; + public interface AnimatedEntity { AnimationContextTracker getAnimationContextTracker(); + default ArrayList getAnimations() { + return new ArrayList<>(); + } + default int getKeyframeAnimationTicks() { return 0; } @@ -33,10 +39,24 @@ default void startKeyframeAnimation(KeyframeAnimation keyframeAnimation, int ini keyframeAnimationContext.getAnimationState().startIfNotRunning(initialTick); } + default void forceStartKeyframeAnimation(KeyframeAnimation keyframeAnimation, int initialTick) { + KeyframeAnimationContext keyframeAnimationContext = this.getAnimationContextTracker().get(keyframeAnimation); + keyframeAnimationContext.setInitialTick(initialTick); + keyframeAnimationContext.getAnimationState().start(initialTick); + } + + default void stopRunningKeyframeAnimations() { + for (KeyframeAnimation keyframeAnimation : this.getAnimations()) { + if (this.getAnimationContextTracker().get(keyframeAnimation).isRunning() == false) { + this.stopKeyframeAnimation(keyframeAnimation); + } + } + } + default void stopKeyframeAnimation(KeyframeAnimation keyframeAnimation) { KeyframeAnimationContext keyframeAnimationContext = this.getAnimationContextTracker().get(keyframeAnimation); keyframeAnimationContext.setInitialTick(0); keyframeAnimationContext.setCurrentTick(0); keyframeAnimationContext.getAnimationState().stop(); } -} +} \ No newline at end of file diff --git a/common/src/main/java/com/faboslav/friendsandfoes/entity/pose/RascalEntityPose.java b/common/src/main/java/com/faboslav/friendsandfoes/entity/pose/RascalEntityPose.java new file mode 100644 index 000000000..fbe2ac074 --- /dev/null +++ b/common/src/main/java/com/faboslav/friendsandfoes/entity/pose/RascalEntityPose.java @@ -0,0 +1,22 @@ +package com.faboslav.friendsandfoes.entity.pose; + +import net.minecraft.entity.EntityPose; + +public enum RascalEntityPose +{ + DEFAULT, + NOD, + GIVE_REWARD; + + public String getName() { + return "RASCAL_" + this.name(); + } + + public EntityPose get() { + return EntityPose.valueOf(this.getName()); + } + + static { + EntityPose.values(); + } +} \ No newline at end of file diff --git a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendAndFoesEntityRenderer.java b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendAndFoesEntityRenderer.java index 96591ce57..58c3ae8f8 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendAndFoesEntityRenderer.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendAndFoesEntityRenderer.java @@ -27,6 +27,7 @@ public static void postInit() { RegistryHelper.registerEntityRenderer(FriendsAndFoesEntityTypes.ICE_CHUNK, IceologerIceChunkRenderer::new); RegistryHelper.registerEntityRenderer(FriendsAndFoesEntityTypes.MAULER, MaulerEntityRenderer::new); RegistryHelper.registerEntityRenderer(FriendsAndFoesEntityTypes.MOOBLOOM, MoobloomEntityRenderer::new); + RegistryHelper.registerEntityRenderer(FriendsAndFoesEntityTypes.RASCAL, RascalEntityRenderer::new); RegistryHelper.registerEntityRenderer(FriendsAndFoesEntityTypes.TUFF_GOLEM, TuffGolemEntityRenderer::new); RegistryHelper.registerEntityRenderer(FriendsAndFoesEntityTypes.WILDFIRE, WildfireEntityRenderer::new); } diff --git a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesActivities.java b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesActivities.java index 954e0d6d8..fbeb021f1 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesActivities.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesActivities.java @@ -11,9 +11,11 @@ public final class FriendsAndFoesActivities { public final static Supplier TUFF_GOLEM_HOME; + public final static Supplier RASCAL_WAIT; static { TUFF_GOLEM_HOME = RegistryHelper.registerActivity("tuff_golem_home", () -> new Activity("tuff_golem_home")); + RASCAL_WAIT = RegistryHelper.registerActivity("rascal_wait", () -> new Activity("rascal_wait")); } public static void init() { diff --git a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesCriteria.java b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesCriteria.java index 2dbc6e032..3f1f7037e 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesCriteria.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesCriteria.java @@ -1,6 +1,7 @@ package com.faboslav.friendsandfoes.init; import com.faboslav.friendsandfoes.advancements.criterion.ActivateZombieHorseTrapCriterion; +import com.faboslav.friendsandfoes.advancements.criterion.CompleteHideAndSeekGameCriterion; import com.faboslav.friendsandfoes.advancements.criterion.TameGlareCriterion; import net.minecraft.advancement.criterion.Criteria; import net.minecraft.advancement.criterion.Criterion; @@ -9,10 +10,12 @@ public final class FriendsAndFoesCriteria { public static final TameGlareCriterion TAME_GLARE; public static final ActivateZombieHorseTrapCriterion ACTIVATE_ZOMBIE_HORSE_TRAP; + public static final CompleteHideAndSeekGameCriterion COMPLETE_HIDE_AND_SEEK_GAME; static { TAME_GLARE = register(new TameGlareCriterion()); ACTIVATE_ZOMBIE_HORSE_TRAP = register(new ActivateZombieHorseTrapCriterion()); + COMPLETE_HIDE_AND_SEEK_GAME = register(new CompleteHideAndSeekGameCriterion()); } private static > T register(T criterion) { diff --git a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesEntityModelLayer.java b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesEntityModelLayer.java index 2a90747e7..0470802f5 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesEntityModelLayer.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesEntityModelLayer.java @@ -22,6 +22,7 @@ public final class FriendsAndFoesEntityModelLayer public static final EntityModelLayer ICEOLOGER_ICE_CHUNK_LAYER; public static final EntityModelLayer MAULER_LAYER; public static final EntityModelLayer MOOBLOOM_LAYER; + public static final EntityModelLayer RASCAL_LAYER; public static final EntityModelLayer TUFF_GOLEM_LAYER; public static final EntityModelLayer WILDFIRE_LAYER; public static final EntityModelLayer PLAYER_ILLUSION_LAYER; @@ -33,6 +34,7 @@ public final class FriendsAndFoesEntityModelLayer ICEOLOGER_ICE_CHUNK_LAYER = new EntityModelLayer(FriendsAndFoes.makeID("iceologer_ice_chunk"), "main"); MAULER_LAYER = new EntityModelLayer(FriendsAndFoes.makeID("mauler"), "main"); MOOBLOOM_LAYER = new EntityModelLayer(FriendsAndFoes.makeID("moobloom"), "main"); + RASCAL_LAYER = new EntityModelLayer(FriendsAndFoes.makeID("rascal"), "main"); TUFF_GOLEM_LAYER = new EntityModelLayer(FriendsAndFoes.makeID("tuff_golem"), "main"); WILDFIRE_LAYER = new EntityModelLayer(FriendsAndFoes.makeID("wildfire"), "main"); PLAYER_ILLUSION_LAYER = new EntityModelLayer(FriendsAndFoes.makeID("player_illusion"), "main"); @@ -45,6 +47,7 @@ public static void init() { RegistryHelper.registerEntityModelLayer(ICEOLOGER_ICE_CHUNK_LAYER, IceologerIceChunkModel::getTexturedModelData); RegistryHelper.registerEntityModelLayer(MAULER_LAYER, MaulerEntityModel::getTexturedModelData); RegistryHelper.registerEntityModelLayer(MOOBLOOM_LAYER, CowEntityModel::getTexturedModelData); + RegistryHelper.registerEntityModelLayer(RASCAL_LAYER, RascalEntityModel::getTexturedModelData); RegistryHelper.registerEntityModelLayer(TUFF_GOLEM_LAYER, TuffGolemEntityModel::getTexturedModelData); RegistryHelper.registerEntityModelLayer(WILDFIRE_LAYER, WildfireEntityModel::getTexturedModelData); } diff --git a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesEntityTypes.java b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesEntityTypes.java index 595090faf..fb9031318 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesEntityTypes.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesEntityTypes.java @@ -31,6 +31,7 @@ public final class FriendsAndFoesEntityTypes public static final Supplier> ICE_CHUNK; public static final Supplier> MAULER; public static final Supplier> MOOBLOOM; + public static final Supplier> RASCAL; public static final Supplier> TUFF_GOLEM; public static final Supplier> WILDFIRE; public static final Supplier> PLAYER_ILLUSION; @@ -43,6 +44,7 @@ public final class FriendsAndFoesEntityTypes ICE_CHUNK = RegistryHelper.registerEntityType("ice_chunk", () -> EntityType.Builder.create(IceologerIceChunkEntity::new, SpawnGroup.MISC).makeFireImmune().setDimensions(2.5F, 1.0F).maxTrackingRange(6).build(FriendsAndFoes.makeStringID("ice_chunk"))); MAULER = RegistryHelper.registerEntityType("mauler", () -> EntityType.Builder.create(MaulerEntity::new, SpawnGroup.CREATURE).setDimensions(0.5625F, 0.5625F).maxTrackingRange(10).build(FriendsAndFoes.makeStringID("mauler"))); MOOBLOOM = RegistryHelper.registerEntityType("moobloom", () -> EntityType.Builder.create(MoobloomEntity::new, SpawnGroup.CREATURE).setDimensions(0.9F, 1.4F).maxTrackingRange(10).build(FriendsAndFoes.makeStringID("moobloom"))); + RASCAL = RegistryHelper.registerEntityType("rascal", () -> EntityType.Builder.create(RascalEntity::new, CustomSpawnGroup.getRascalsCategory()).setDimensions(0.9F, 1.25F).maxTrackingRange(10).build(FriendsAndFoes.makeStringID("rascal"))); TUFF_GOLEM = RegistryHelper.registerEntityType("tuff_golem", () -> EntityType.Builder.create(TuffGolemEntity::new, SpawnGroup.MISC).setDimensions(0.75F, 1.0625F).maxTrackingRange(10).build(FriendsAndFoes.makeStringID("tuff_golem"))); WILDFIRE = RegistryHelper.registerEntityType("wildfire", () -> EntityType.Builder.create(WildfireEntity::new, SpawnGroup.MONSTER).setDimensions(0.7F * WildfireEntityRenderer.SCALE, 1.875F * WildfireEntityRenderer.SCALE).maxTrackingRange(10).makeFireImmune().build(FriendsAndFoes.makeStringID("wildfire"))); PLAYER_ILLUSION = RegistryHelper.registerEntityType("player_illusion", () -> EntityType.Builder.create(PlayerIllusionEntity::new, SpawnGroup.MISC).setDimensions(0.7F, 1.875F).maxTrackingRange(10).makeFireImmune().build(FriendsAndFoes.makeStringID("player_illusion"))); @@ -65,6 +67,7 @@ public static void createMobAttributes() { RegistryHelper.registerEntityAttribute(FriendsAndFoesEntityTypes.ICEOLOGER, IceologerEntity::createAttributes); RegistryHelper.registerEntityAttribute(FriendsAndFoesEntityTypes.MAULER, MaulerEntity::createAttributes); RegistryHelper.registerEntityAttribute(FriendsAndFoesEntityTypes.MOOBLOOM, MoobloomEntity::createCowAttributes); + RegistryHelper.registerEntityAttribute(FriendsAndFoesEntityTypes.RASCAL, RascalEntity::createAttributes); RegistryHelper.registerEntityAttribute(FriendsAndFoesEntityTypes.TUFF_GOLEM, TuffGolemEntity::createAttributes); RegistryHelper.registerEntityAttribute(FriendsAndFoesEntityTypes.WILDFIRE, WildfireEntity::createAttributes); RegistryHelper.registerEntityAttribute(FriendsAndFoesEntityTypes.PLAYER_ILLUSION, PlayerIllusionEntity::createMobAttributes); @@ -75,6 +78,7 @@ public static void initSpawnRestrictions() { SpawnRestrictionAccessor.callRegister(ICEOLOGER.get(), SpawnRestriction.Location.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, IceologerEntity::canSpawn); SpawnRestrictionAccessor.callRegister(MAULER.get(), SpawnRestriction.Location.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, MaulerEntity::canSpawn); SpawnRestrictionAccessor.callRegister(MOOBLOOM.get(), SpawnRestriction.Location.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, MoobloomEntity::canSpawn); + SpawnRestrictionAccessor.callRegister(RASCAL.get(), SpawnRestriction.Location.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, RascalEntity::canSpawn); } public static void addSpawns() { @@ -94,6 +98,10 @@ public static void addSpawns() { BiomeModifications.addMobSpawn(FriendsAndFoesTags.HAS_LESS_MOOBLOOMS, MOOBLOOM.get(), SpawnGroup.CREATURE, config.moobloomFlowerForestSpawnWeight, config.moobloomFlowerForestSpawnMinGroupSize, config.moobloomFlowerForestSpawnMaxGroupSize); BiomeModifications.addMobSpawn(FriendsAndFoesTags.HAS_MORE_MOOBLOOMS, MOOBLOOM.get(), SpawnGroup.CREATURE, config.moobloomMeadowSpawnWeight, config.moobloomMeadowSpawnMinGroupSize, config.moobloomMeadowSpawnMaxGroupSize); } + + if (config.enableRascal && config.enableRascalSpawn) { + BiomeModifications.addMobSpawn(FriendsAndFoesTags.HAS_RASCAL, RASCAL.get(), CustomSpawnGroup.getRascalsCategory(), 4, 1, 1); + } } public static void addMoobloomVariants() { diff --git a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesItems.java b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesItems.java index f31a12d25..14f3e60fb 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesItems.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesItems.java @@ -20,6 +20,7 @@ public final class FriendsAndFoesItems public final static Supplier ILLUSIONER_SPAWN_EGG; public final static Supplier MAULER_SPAWN_EGG; public final static Supplier MOOBLOOM_SPAWN_EGG; + public final static Supplier RASCAL_SPAWN_EGG; public final static Supplier TUFF_GOLEM_SPAWN_EGG; public final static Supplier WILDFIRE_SPAWN_EGG; public static final Supplier BUTTERCUP; @@ -58,6 +59,7 @@ public final class FriendsAndFoesItems ILLUSIONER_SPAWN_EGG = RegistryHelper.registerItem("illusioner_spawn_egg", () -> new SpawnEggItem(EntityType.ILLUSIONER, 0x603E5C, 0x888E8E, new Item.Settings().maxCount(64).group(ItemGroup.MISC))); MAULER_SPAWN_EGG = RegistryHelper.registerItem("mauler_spawn_egg", () -> new SpawnEggItem(FriendsAndFoesEntityTypes.MAULER.get(), 0x534F25, 0x817B39, new Item.Settings().maxCount(64).group(ItemGroup.MISC))); MOOBLOOM_SPAWN_EGG = RegistryHelper.registerItem("moobloom_spawn_egg", () -> new SpawnEggItem(FriendsAndFoesEntityTypes.MOOBLOOM.get(), 0xF7EDC1, 0xFACA00, new Item.Settings().maxCount(64).group(ItemGroup.MISC))); + RASCAL_SPAWN_EGG = RegistryHelper.registerSpawnEggItem("rascal_spawn_egg", FriendsAndFoesEntityTypes.RASCAL, 0x05736A, 0x8A521C, new Item.Settings().maxCount(64)); TUFF_GOLEM_SPAWN_EGG = RegistryHelper.registerItem("tuff_golem_spawn_egg", () -> new SpawnEggItem(FriendsAndFoesEntityTypes.TUFF_GOLEM.get(), 0xA0A297, 0x5D5D52, new Item.Settings().maxCount(64).group(ItemGroup.MISC))); WILDFIRE_SPAWN_EGG = RegistryHelper.registerItem("wildfire_spawn_egg", () -> new SpawnEggItem(FriendsAndFoesEntityTypes.WILDFIRE.get(), 0x6C3100, 0xFFD528, new Item.Settings().maxCount(64).group(ItemGroup.MISC))); BUTTERCUP = RegistryHelper.registerItem("buttercup", () -> new BlockItem(FriendsAndFoesBlocks.BUTTERCUP.get(), new Item.Settings().group(ItemGroup.DECORATIONS).maxCount(64))); diff --git a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesMemoryModuleTypes.java b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesMemoryModuleTypes.java index 75e3f6490..433ef2263 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesMemoryModuleTypes.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesMemoryModuleTypes.java @@ -16,12 +16,14 @@ public final class FriendsAndFoesMemoryModuleTypes public final static Supplier> WILDFIRE_SHOCKWAVE_ATTACK_COOLDOWN; public final static Supplier> WILDFIRE_SUMMON_BLAZE_COOLDOWN; public final static Supplier> TUFF_GOLEM_SLEEP_COOLDOWN; + public final static Supplier> RASCAL_NOD_COOLDOWN; static { WILDFIRE_BARRAGE_ATTACK_COOLDOWN = RegistryHelper.registerMemoryModuleType("wildfire_barrage_attack_cooldown", () -> new MemoryModuleType<>(Optional.of(Codec.INT))); WILDFIRE_SHOCKWAVE_ATTACK_COOLDOWN = RegistryHelper.registerMemoryModuleType("wildfire_shockwave_attack_cooldown", () -> new MemoryModuleType<>(Optional.of(Codec.INT))); WILDFIRE_SUMMON_BLAZE_COOLDOWN = RegistryHelper.registerMemoryModuleType("wildfire_summon_blazes_cooldown", () -> new MemoryModuleType<>(Optional.of(Codec.INT))); TUFF_GOLEM_SLEEP_COOLDOWN = RegistryHelper.registerMemoryModuleType("tuff_golem_sleep_cooldown", () -> new MemoryModuleType<>(Optional.of(Codec.INT))); + RASCAL_NOD_COOLDOWN = RegistryHelper.registerMemoryModuleType("rascal_nod_cooldown", () -> new MemoryModuleType<>(Optional.of(Codec.INT))); } public static void init() { diff --git a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesSoundEvents.java b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesSoundEvents.java index be87fb8b1..c968601ef 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesSoundEvents.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/init/FriendsAndFoesSoundEvents.java @@ -39,6 +39,13 @@ public final class FriendsAndFoesSoundEvents public static final Supplier ENTITY_MAULER_HURT; public static final Supplier ENTITY_MOOBLOOM_CONVERT; public static final Supplier ENTITY_PLAYER_MIRROR_MOVE; + public static final Supplier ENTITY_RASCAL_AMBIENT; + public static final Supplier ENTITY_RASCAL_DISAPPEAR; + public static final Supplier ENTITY_RASCAL_HURT; + public static final Supplier ENTITY_RASCAL_NOD; + public static final Supplier ENTITY_RASCAL_REAPPEAR; + public static final Supplier ENTITY_RASCAL_REWARD; + public static final Supplier ENTITY_RASCAL_REWARD_BAD; public static final Supplier ENTITY_TUFF_GOLEM_GLUE_ON; public static final Supplier ENTITY_TUFF_GOLEM_GLUE_OFF; public static final Supplier ENTITY_TUFF_GOLEM_HURT; @@ -85,6 +92,13 @@ public final class FriendsAndFoesSoundEvents ENTITY_MAULER_HURT = register("entity", "mauler.hurt"); ENTITY_MOOBLOOM_CONVERT = register("entity", "moobloom.convert"); ENTITY_PLAYER_MIRROR_MOVE = register("entity", "player.mirror_move"); + ENTITY_RASCAL_AMBIENT = register("entity", "rascal.ambient"); + ENTITY_RASCAL_DISAPPEAR = register("entity", "rascal.disappear"); + ENTITY_RASCAL_HURT = register("entity", "rascal.hurt"); + ENTITY_RASCAL_NOD = register("entity", "rascal.nod"); + ENTITY_RASCAL_REAPPEAR = register("entity", "rascal.reappear"); + ENTITY_RASCAL_REWARD = register("entity", "rascal.reward"); + ENTITY_RASCAL_REWARD_BAD = register("entity", "rascal.reward_bad"); ENTITY_TUFF_GOLEM_GLUE_ON = register("entity", "tuff_golem.glue_on"); ENTITY_TUFF_GOLEM_GLUE_OFF = register("entity", "tuff_golem.glue_off"); ENTITY_TUFF_GOLEM_HURT = register("entity", "tuff_golem.hurt"); diff --git a/forge/src/main/java/com/faboslav/friendsandfoes/mixin/forge/AddCustomEntityPoseMixin.java b/common/src/main/java/com/faboslav/friendsandfoes/mixin/AddCustomEntityPoseMixin.java similarity index 65% rename from forge/src/main/java/com/faboslav/friendsandfoes/mixin/forge/AddCustomEntityPoseMixin.java rename to common/src/main/java/com/faboslav/friendsandfoes/mixin/AddCustomEntityPoseMixin.java index abcb8458b..094fb9a1c 100644 --- a/forge/src/main/java/com/faboslav/friendsandfoes/mixin/forge/AddCustomEntityPoseMixin.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/mixin/AddCustomEntityPoseMixin.java @@ -1,5 +1,6 @@ -package com.faboslav.friendsandfoes.mixin.forge; +package com.faboslav.friendsandfoes.mixin; +import com.faboslav.friendsandfoes.entity.pose.RascalEntityPose; import com.faboslav.friendsandfoes.entity.pose.TuffGolemEntityPose; import net.minecraft.entity.EntityPose; import org.objectweb.asm.Opcodes; @@ -44,31 +45,26 @@ private static EntityPose newEntityPose( private static void friendsandfoes_addCustomEntityPoses(CallbackInfo ci) { var entityPoses = new ArrayList<>(Arrays.asList(field_18083)); var lastEntityPose = entityPoses.get(entityPoses.size() - 1); + var nextEntityPoseIndex = lastEntityPose.ordinal(); - var tuffGolemStanding = newEntityPose( - TuffGolemEntityPose.STANDING.getName(), - lastEntityPose.ordinal() + 1 - ); - entityPoses.add(tuffGolemStanding); + for (TuffGolemEntityPose tuffGolemEntityPose : TuffGolemEntityPose.values()) { + var newEntityPose = newEntityPose( + tuffGolemEntityPose.getName(), + nextEntityPoseIndex++ + ); - var tuffGolemStandingWithItem = newEntityPose( - TuffGolemEntityPose.STANDING_WITH_ITEM.getName(), - lastEntityPose.ordinal() + 2 - ); - entityPoses.add(tuffGolemStandingWithItem); + entityPoses.add(newEntityPose); + } - var tuffGolemSleeping = newEntityPose( - TuffGolemEntityPose.SLEEPING.getName(), - lastEntityPose.ordinal() + 3 - ); - entityPoses.add(tuffGolemSleeping); + for (RascalEntityPose rascalEntityPose : RascalEntityPose.values()) { + var newEntityPose = newEntityPose( + rascalEntityPose.getName(), + nextEntityPoseIndex++ + ); - var tuffGolemSleepingWithItem = newEntityPose( - TuffGolemEntityPose.SLEEPING_WITH_ITEM.getName(), - lastEntityPose.ordinal() + 4 - ); - entityPoses.add(tuffGolemSleepingWithItem); + entityPoses.add(newEntityPose); + } field_18083 = entityPoses.toArray(new EntityPose[0]); } -} +} \ No newline at end of file diff --git a/common/src/main/java/com/faboslav/friendsandfoes/mixin/BundleItemAccessor.java b/common/src/main/java/com/faboslav/friendsandfoes/mixin/BundleItemAccessor.java new file mode 100644 index 000000000..bceb37526 --- /dev/null +++ b/common/src/main/java/com/faboslav/friendsandfoes/mixin/BundleItemAccessor.java @@ -0,0 +1,16 @@ +package com.faboslav.friendsandfoes.mixin; + +import net.minecraft.item.BundleItem; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(BundleItem.class) +public interface BundleItemAccessor +{ + @Invoker("addToBundle") + int invokeAddToBundle( + ItemStack bundle, + ItemStack stack + ); +} \ No newline at end of file diff --git a/common/src/main/java/com/faboslav/friendsandfoes/mixin/ChunkRegionAccessor.java b/common/src/main/java/com/faboslav/friendsandfoes/mixin/ChunkRegionAccessor.java new file mode 100644 index 000000000..03f3fde0b --- /dev/null +++ b/common/src/main/java/com/faboslav/friendsandfoes/mixin/ChunkRegionAccessor.java @@ -0,0 +1,13 @@ +package com.faboslav.friendsandfoes.mixin; + +import net.minecraft.world.ChunkRegion; +import net.minecraft.world.gen.StructureAccessor; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ChunkRegion.class) +public interface ChunkRegionAccessor +{ + @Accessor("structureAccessor") + StructureAccessor getStructureAccessor(); +} \ No newline at end of file diff --git a/common/src/main/java/com/faboslav/friendsandfoes/mixin/StrongholdGeneratorMixin.java b/common/src/main/java/com/faboslav/friendsandfoes/mixin/StrongholdGeneratorMixin.java index cc05171e0..42e90000f 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/mixin/StrongholdGeneratorMixin.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/mixin/StrongholdGeneratorMixin.java @@ -95,7 +95,7 @@ private void friendsandfoes_generate( ItemStack enchantedItemStack = EnchantmentHelper.enchant( random, itemStack, - random.nextBetween(1, 3), + random.nextBetween(1, 30), true ); diff --git a/common/src/main/java/com/faboslav/friendsandfoes/platform/CustomSpawnGroup.java b/common/src/main/java/com/faboslav/friendsandfoes/platform/CustomSpawnGroup.java index 6d9ad33bf..2828ce98d 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/platform/CustomSpawnGroup.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/platform/CustomSpawnGroup.java @@ -6,17 +6,29 @@ public final class CustomSpawnGroup { public static final String GLARES_INTERNAL_NAME = "GLARES"; - public static final String NAME = "glares"; - public static final int SPAWN_CAP = 15; - public static final boolean PEACEFUL = true; - public static final boolean RARE = false; - public static final int IMMEDIATE_DESPAWN_RANGE = 128; + public static final String GLARES_NAME = "glares"; + public static final int GLARES_SPAWN_CAP = 15; + public static final boolean GLARES_PEACEFUL = true; + public static final boolean GLARES_RARE = false; + public static final int GLARES_IMMEDIATE_DESPAWN_RANGE = 128; + + public static final String RASCALS_INTERNAL_NAME = "RASCALS"; + public static final String RASCALS_NAME = "rascals"; + public static final int RASCALS_SPAWN_CAP = 3; + public static final boolean RASCALS_PEACEFUL = true; + public static final boolean RASCALS_RARE = false; + public static final int RASCALS_IMMEDIATE_DESPAWN_RANGE = 128; @ExpectPlatform public static SpawnGroup getGlaresCategory() { throw new AssertionError(); } + @ExpectPlatform + public static SpawnGroup getRascalsCategory() { + throw new AssertionError(); + } + private CustomSpawnGroup() { } -} +} \ No newline at end of file diff --git a/common/src/main/java/com/faboslav/friendsandfoes/tag/FriendsAndFoesTags.java b/common/src/main/java/com/faboslav/friendsandfoes/tag/FriendsAndFoesTags.java index 14978d4a3..0f7f70c0c 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/tag/FriendsAndFoesTags.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/tag/FriendsAndFoesTags.java @@ -32,6 +32,7 @@ public final class FriendsAndFoesTags public static final TagKey HAS_ILLUSIONER = biomeTag("has_illusioner"); public static final TagKey HAS_LESS_MOOBLOOMS = biomeTag("has_less_mooblooms"); public static final TagKey HAS_MORE_MOOBLOOMS = biomeTag("has_more_mooblooms"); + public static final TagKey HAS_RASCAL = biomeTag("has_rascal"); public static final TagKey HAS_SAVANNA_MAULER = biomeTag("has_savanna_mauler"); private static TagKey blockTag(String name) { diff --git a/common/src/main/java/com/faboslav/friendsandfoes/world/spawner/IceologerSpawner.java b/common/src/main/java/com/faboslav/friendsandfoes/world/spawner/IceologerSpawner.java index 87826b8fa..371146750 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/world/spawner/IceologerSpawner.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/world/spawner/IceologerSpawner.java @@ -43,7 +43,7 @@ public int spawn(ServerWorld world, boolean spawnMonsters, boolean spawnAnimals) if ( l < 5L || world.isDay() == false - || random.nextBetween(0, 1) != 0 + || random.nextBetween(0, 1) != 0 ) { return 0; } diff --git a/common/src/main/resources/assets/friendsandfoes/lang/en_us.json b/common/src/main/resources/assets/friendsandfoes/lang/en_us.json index 4bcf48be7..5e94b9d0c 100644 --- a/common/src/main/resources/assets/friendsandfoes/lang/en_us.json +++ b/common/src/main/resources/assets/friendsandfoes/lang/en_us.json @@ -21,12 +21,16 @@ "advancements.nether.find_citadel.description": "Enter a Nether citadel", "advancements.nether.kill_wildfire.title": "Drop it like it's hot", "advancements.nether.kill_wildfire.description": "Kill the wildfire", - "advancements.nether.obtain_wildfire_crown.title": "Who's da New King of Hell", + "advancements.nether.obtain_wildfire_crown.title": "Who's da New King of Hell?", "advancements.nether.obtain_wildfire_crown.description": "Have a wildfire crown in your inventory", + "advancements.adventure.complete_hide_and_seek_game.title": "Hide and Seek", + "advancements.adventure.complete_hide_and_seek_game.description": "Find a rascal three times in its little game", "block.friendsandfoes.buttercup": "Buttercup", "block.minecraft.beehive": "Oak Beehive", "block.friendsandfoes.acacia_beehive": "Acacia Beehive", + "block.friendsandfoes.bamboo_beehive": "Bamboo Beehive", "block.friendsandfoes.birch_beehive": "Birch Beehive", + "block.friendsandfoes.cherry_beehive": "Cherry Beehive", "block.friendsandfoes.crimson_beehive": "Crimson Beehive", "block.friendsandfoes.dark_oak_beehive": "Dark Oak Beehive", "block.friendsandfoes.jungle_beehive": "Jungle Beehive", @@ -65,6 +69,7 @@ "item.friendsandfoes.illusioner_spawn_egg": "Illusioner Spawn Egg", "item.friendsandfoes.mauler_spawn_egg": "Mauler Spawn Egg", "item.friendsandfoes.moobloom_spawn_egg": "Moobloom Spawn Egg", + "item.friendsandfoes.rascal_spawn_egg": "Rascal Spawn Egg", "item.friendsandfoes.tuff_golem_spawn_egg": "Tuff Golem Spawn Egg", "item.friendsandfoes.wildfire_spawn_egg": "Wildfire Spawn Egg", "item.friendsandfoes.totem_of_freezing": "Totem of Freezing", @@ -98,6 +103,13 @@ "subtitle.entity.friendsandfoes.mauler.hurt": "Mauler hurts", "subtitle.entity.friendsandfoes.moobloom.convert": "Moobloom transforms", "subtitle.entity.friendsandfoes.player.mirror_move": "Player displaces", + "subtitle.entity.friendsandfoes.rascal.ambient": "Rascal taunts", + "subtitle.entity.friendsandfoes.rascal.disappear": "Rascal disappears", + "subtitle.entity.friendsandfoes.rascal.nod": "Rascal nods", + "subtitle.entity.friendsandfoes.rascal.hurt": "Rascal hurts", + "subtitle.entity.friendsandfoes.rascal.reappear": "Rascal appears", + "subtitle.entity.friendsandfoes.rascal.reward": "Rascal gives reward", + "subtitle.entity.friendsandfoes.rascal.reward_bad": "Rascal gives bad reward", "subtitle.entity.friendsandfoes.shield_debris.impact": "Shield debris impacted", "subtitle.entity.friendsandfoes.tuff_golem.glue_on": "Tuff Golem glued", "subtitle.entity.friendsandfoes.tuff_golem.glue_off": "Tuff Golem unglued", diff --git a/common/src/main/resources/assets/friendsandfoes/models/item/ rascal_spawn_egg.json b/common/src/main/resources/assets/friendsandfoes/models/item/ rascal_spawn_egg.json new file mode 100644 index 000000000..debcb565c --- /dev/null +++ b/common/src/main/resources/assets/friendsandfoes/models/item/ rascal_spawn_egg.json @@ -0,0 +1,3 @@ +{ + "parent": "item/template_spawn_egg" +} diff --git a/common/src/main/resources/assets/friendsandfoes/sounds.json b/common/src/main/resources/assets/friendsandfoes/sounds.json index acbea69fd..edf849cd3 100644 --- a/common/src/main/resources/assets/friendsandfoes/sounds.json +++ b/common/src/main/resources/assets/friendsandfoes/sounds.json @@ -181,7 +181,64 @@ "friendsandfoes:entity/player/mirror_move1", "friendsandfoes:entity/player/mirror_move2" ], - "subtitle": "subtitle.entity.friendsandfoes.moobloom.convert" + "subtitle": "subtitle.entity.friendsandfoes.player.mirror_move" + }, + "entity.rascal.ambient": { + "sounds": [ + "friendsandfoes:entity/rascal/ambient1", + "friendsandfoes:entity/rascal/ambient2", + "friendsandfoes:entity/rascal/ambient3", + "friendsandfoes:entity/rascal/ambient4", + "friendsandfoes:entity/rascal/ambient5" + ], + "subtitle": "subtitle.entity.friendsandfoes.rascal.ambient" + }, + "entity.rascal.disappear": { + "sounds": [ + "friendsandfoes:entity/rascal/disappear1", + "friendsandfoes:entity/rascal/disappear2" + ], + "subtitle": "subtitle.entity.friendsandfoes.rascal.disappear" + }, + "entity.rascal.hurt": { + "sounds": [ + "friendsandfoes:entity/rascal/hurt1", + "friendsandfoes:entity/rascal/hurt2", + "friendsandfoes:entity/rascal/hurt3", + "friendsandfoes:entity/rascal/hurt4" + ], + "subtitle": "subtitle.entity.friendsandfoes.rascal.hurt" + }, + "entity.rascal.nod": { + "sounds": [ + "friendsandfoes:entity/rascal/nod1", + "friendsandfoes:entity/rascal/nod2", + "friendsandfoes:entity/rascal/nod3", + "friendsandfoes:entity/rascal/nod4" + ], + "subtitle": "subtitle.entity.friendsandfoes.rascal.nod" + }, + "entity.rascal.reappear": { + "sounds": [ + "friendsandfoes:entity/rascal/reappear1", + "friendsandfoes:entity/rascal/reappear2" + ], + "subtitle": "subtitle.entity.friendsandfoes.rascal.reappear" + }, + "entity.rascal.reward": { + "sounds": [ + "friendsandfoes:entity/rascal/reward1", + "friendsandfoes:entity/rascal/reward2" + ], + "subtitle": "subtitle.entity.friendsandfoes.rascal.reward" + }, + "entity.rascal.reward_bad": { + "sounds": [ + "friendsandfoes:entity/rascal/reward_bad1", + "friendsandfoes:entity/rascal/reward_bad2", + "friendsandfoes:entity/rascal/reward_bad3" + ], + "subtitle": "subtitle.entity.friendsandfoes.rascal.reward_bad" }, "entity.tuff_golem.glue_on": { "sounds": [ diff --git a/common/src/main/resources/friendsandfoes-common.mixins.json b/common/src/main/resources/friendsandfoes-common.mixins.json index 11e7bbfdc..6b15a49dd 100644 --- a/common/src/main/resources/friendsandfoes-common.mixins.json +++ b/common/src/main/resources/friendsandfoes-common.mixins.json @@ -8,6 +8,7 @@ }, "mixins": [ "AbstractButtonBlockMixin", + "AddCustomEntityPoseMixin", "AxeItemMixin", "BeeEntityAccessor", "BeeEntityMixin", @@ -16,6 +17,7 @@ "BlazeEntityMixin", "BlazeLivingEntityMixin", "BlindTargetGoalFactory", + "BundleItemAccessor", "CarvedPumpkinBlockMixin", "ChickenEntityMixin", "HoneycombItemMixin", diff --git a/fabric/src/main/java/com/faboslav/friendsandfoes/mixin/fabric/AddCustomEntityPoseMixin.java b/fabric/src/main/java/com/faboslav/friendsandfoes/mixin/fabric/AddCustomEntityPoseMixin.java deleted file mode 100644 index 77511df9c..000000000 --- a/fabric/src/main/java/com/faboslav/friendsandfoes/mixin/fabric/AddCustomEntityPoseMixin.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.faboslav.friendsandfoes.mixin.fabric; - -import com.faboslav.friendsandfoes.entity.pose.TuffGolemEntityPose; -import net.minecraft.entity.EntityPose; -import org.objectweb.asm.Opcodes; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.gen.Invoker; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.ArrayList; -import java.util.Arrays; - -@Mixin(EntityPose.class) -@SuppressWarnings({"ShadowTarget", "InvokerTarget"}) -public final class AddCustomEntityPoseMixin -{ - @Invoker("") - private static EntityPose newEntityPose( - String internalName, - int internalId - ) { - throw new AssertionError(); - } - - @Shadow - private static @Final - @Mutable - EntityPose[] field_18083; - - @Inject( - method = "", - at = @At( - value = "FIELD", - opcode = Opcodes.PUTSTATIC, - target = "Lnet/minecraft/entity/EntityPose;field_18083:[Lnet/minecraft/entity/EntityPose;", - shift = At.Shift.AFTER - ) - ) - private static void friendsandfoes_addCustomEntityPoses(CallbackInfo ci) { - var entityPoses = new ArrayList<>(Arrays.asList(field_18083)); - var lastEntityPose = entityPoses.get(entityPoses.size() - 1); - - var tuffGolemStanding = newEntityPose( - TuffGolemEntityPose.STANDING.getName(), - lastEntityPose.ordinal() + 1 - ); - entityPoses.add(tuffGolemStanding); - - var tuffGolemStandingWithItem = newEntityPose( - TuffGolemEntityPose.STANDING_WITH_ITEM.getName(), - lastEntityPose.ordinal() + 2 - ); - entityPoses.add(tuffGolemStandingWithItem); - - var tuffGolemSleeping = newEntityPose( - TuffGolemEntityPose.SLEEPING.getName(), - lastEntityPose.ordinal() + 3 - ); - entityPoses.add(tuffGolemSleeping); - - var tuffGolemSleepingWithItem = newEntityPose( - TuffGolemEntityPose.SLEEPING_WITH_ITEM.getName(), - lastEntityPose.ordinal() + 4 - ); - entityPoses.add(tuffGolemSleepingWithItem); - - field_18083 = entityPoses.toArray(new EntityPose[0]); - } -} diff --git a/fabric/src/main/resources/friendsandfoes.mixins.json b/fabric/src/main/resources/friendsandfoes.mixins.json index b3da463ee..9b19e2178 100644 --- a/fabric/src/main/resources/friendsandfoes.mixins.json +++ b/fabric/src/main/resources/friendsandfoes.mixins.json @@ -7,7 +7,6 @@ "defaultRequire": 1 }, "mixins": [ - "AddCustomEntityPoseMixin", "AddCustomRaidMemberMixin", "AddCustomSpawnGroupMixin", "StructureEntityProcessorMixin" diff --git a/forge/src/main/resources/friendsandfoes.mixins.json b/forge/src/main/resources/friendsandfoes.mixins.json index 147f95e2b..d26448435 100644 --- a/forge/src/main/resources/friendsandfoes.mixins.json +++ b/forge/src/main/resources/friendsandfoes.mixins.json @@ -7,7 +7,6 @@ "defaultRequire": 1 }, "mixins": [ - "AddCustomEntityPoseMixin", "FireBlockAccessor" ], "plugin": "com.faboslav.friendsandfoes.util.plugin.MixinExtrasPlugin"