From 833ad32819453394cf34cf2b361f0c40b6749227 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 12 May 2026 18:47:06 +0200 Subject: [PATCH 01/74] stop here (not finished peeled mecanics BUGS) --- .../contents/omc_daily_events/blocks.yml | 31 -- .../contents/omc_daily_events/obese_crops.yml | 317 ++++++++++++++++++ .../obese_baked_potato_bottom.png | Bin 0 -> 224 bytes .../obese_baked_potato_side_1.png | Bin 0 -> 286 bytes .../obese_baked_potato_side_2.png | Bin 0 -> 259 bytes .../baked_potato/obese_baked_potato_top.png | Bin 0 -> 259 bytes .../beetroot/obese_beetroot_bottom.png | Bin .../beetroot/obese_beetroot_side.png | Bin .../beetroot/obese_beetroot_stem.png | Bin .../beetroot/obese_beetroot_top.png | Bin .../carrot/obese_carrot_bottom.png | Bin .../{ => basic}/carrot/obese_carrot_side.png | Bin .../{ => basic}/carrot/obese_carrot_stem.png | Bin .../{ => basic}/carrot/obese_carrot_top.png | Bin .../obese_golden_apple_bottom.png | Bin 0 -> 285 bytes .../golden_apple/obese_golden_apple_side.png | Bin 0 -> 281 bytes .../golden_apple/obese_golden_apple_stem.png | Bin 0 -> 255 bytes .../golden_apple/obese_golden_apple_top.png | Bin 0 -> 270 bytes .../nether_wart/obese_nether_wart_bottom.png | Bin 0 -> 238 bytes .../nether_wart/obese_nether_wart_side.png | Bin 0 -> 252 bytes .../nether_wart/obese_nether_wart_stem.png | Bin 0 -> 246 bytes .../nether_wart/obese_nether_wart_top.png | Bin 0 -> 215 bytes .../basic/onion/obese_onion_bottom.png | Bin 0 -> 221 bytes .../basic/onion/obese_onion_side.png | Bin 0 -> 256 bytes .../basic/onion/obese_onion_top.png | Bin 0 -> 231 bytes .../obese_poisonous_potato_bottom.png | Bin .../obese_poisonous_potato_side.png | Bin .../obese_poisonous_potato_top.png | Bin .../potato/obese_potato_bottom.png | Bin .../{ => basic}/potato/obese_potato_side.png | Bin .../{ => basic}/potato/obese_potato_stem.png | Bin .../{ => basic}/potato/obese_potato_top.png | Bin .../peeled/beetroot/peeled_obese_beetroot.png | Bin 0 -> 255 bytes .../carrot/peeled_obese_carrot_bottom.png | Bin 0 -> 224 bytes .../carrot/peeled_obese_carrot_side.png | Bin 0 -> 220 bytes .../peeled/carrot/peeled_obese_carrot_top.png | Bin 0 -> 222 bytes .../onion/peeled_obese_onion_bottom.png | Bin 0 -> 228 bytes .../peeled/onion/peeled_obese_onion_side.png | Bin 0 -> 244 bytes .../peeled/onion/peeled_obese_onion_top.png | Bin 0 -> 219 bytes .../peeled/potato/peeled_obese_potato.png | Bin 0 -> 249 bytes 40 files changed, 317 insertions(+), 31 deletions(-) delete mode 100644 src/main/resources/contents/omc_daily_events/blocks.yml create mode 100644 src/main/resources/contents/omc_daily_events/obese_crops.yml create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/baked_potato/obese_baked_potato_bottom.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/baked_potato/obese_baked_potato_side_1.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/baked_potato/obese_baked_potato_side_2.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/baked_potato/obese_baked_potato_top.png rename src/main/resources/contents/omc_daily_events/textures/obese_crops/{ => basic}/beetroot/obese_beetroot_bottom.png (100%) rename src/main/resources/contents/omc_daily_events/textures/obese_crops/{ => basic}/beetroot/obese_beetroot_side.png (100%) rename src/main/resources/contents/omc_daily_events/textures/obese_crops/{ => basic}/beetroot/obese_beetroot_stem.png (100%) rename src/main/resources/contents/omc_daily_events/textures/obese_crops/{ => basic}/beetroot/obese_beetroot_top.png (100%) rename src/main/resources/contents/omc_daily_events/textures/obese_crops/{ => basic}/carrot/obese_carrot_bottom.png (100%) rename src/main/resources/contents/omc_daily_events/textures/obese_crops/{ => basic}/carrot/obese_carrot_side.png (100%) rename src/main/resources/contents/omc_daily_events/textures/obese_crops/{ => basic}/carrot/obese_carrot_stem.png (100%) rename src/main/resources/contents/omc_daily_events/textures/obese_crops/{ => basic}/carrot/obese_carrot_top.png (100%) create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/golden_apple/obese_golden_apple_bottom.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/golden_apple/obese_golden_apple_side.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/golden_apple/obese_golden_apple_stem.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/golden_apple/obese_golden_apple_top.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/nether_wart/obese_nether_wart_bottom.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/nether_wart/obese_nether_wart_side.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/nether_wart/obese_nether_wart_stem.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/nether_wart/obese_nether_wart_top.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/onion/obese_onion_bottom.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/onion/obese_onion_side.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/onion/obese_onion_top.png rename src/main/resources/contents/omc_daily_events/textures/obese_crops/{poissonous_potato => basic/poisonous_potato}/obese_poisonous_potato_bottom.png (100%) rename src/main/resources/contents/omc_daily_events/textures/obese_crops/{poissonous_potato => basic/poisonous_potato}/obese_poisonous_potato_side.png (100%) rename src/main/resources/contents/omc_daily_events/textures/obese_crops/{poissonous_potato => basic/poisonous_potato}/obese_poisonous_potato_top.png (100%) rename src/main/resources/contents/omc_daily_events/textures/obese_crops/{ => basic}/potato/obese_potato_bottom.png (100%) rename src/main/resources/contents/omc_daily_events/textures/obese_crops/{ => basic}/potato/obese_potato_side.png (100%) rename src/main/resources/contents/omc_daily_events/textures/obese_crops/{ => basic}/potato/obese_potato_stem.png (100%) rename src/main/resources/contents/omc_daily_events/textures/obese_crops/{ => basic}/potato/obese_potato_top.png (100%) create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/peeled/beetroot/peeled_obese_beetroot.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/peeled/carrot/peeled_obese_carrot_bottom.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/peeled/carrot/peeled_obese_carrot_side.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/peeled/carrot/peeled_obese_carrot_top.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/peeled/onion/peeled_obese_onion_bottom.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/peeled/onion/peeled_obese_onion_side.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/peeled/onion/peeled_obese_onion_top.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/obese_crops/peeled/potato/peeled_obese_potato.png diff --git a/src/main/resources/contents/omc_daily_events/blocks.yml b/src/main/resources/contents/omc_daily_events/blocks.yml deleted file mode 100644 index 7ef63999e..000000000 --- a/src/main/resources/contents/omc_daily_events/blocks.yml +++ /dev/null @@ -1,31 +0,0 @@ -info: - namespace: omc_daily_events -items: - obese_potato: - display_name: Patate obèse - graphics: - textures: - north: obese_crops/potato/obese_potato_side - south: obese_crops/potato/obese_potato_side - east: obese_crops/potato/obese_potato_side - west: obese_crops/potato/obese_potato_side - up: obese_crops/potato/obese_potato_top - down: obese_crops/potato/obese_potato_bottom - behaviours: - block: - placed_model: - type: REAL_NOTE - break_particles: ITEM - up_block: omc_daily_events:obese_potato_stem - - obese_potato_stem: - display_name: Tige de patate obèse - graphics: - icon: obese_crops/potato/obese_potato_stem - parent: block/cross - textures: - cross: obese_crops/potato/obese_potato_stem - behaviours: - block: - placed_model: - type: REAL_WIRE \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/obese_crops.yml b/src/main/resources/contents/omc_daily_events/obese_crops.yml new file mode 100644 index 000000000..e91757962 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/obese_crops.yml @@ -0,0 +1,317 @@ +# assets from https://github.com/0rc1nus/Overweight-Farming + +info: + namespace: omc_daily_events +items: + # --- Potato --- + obese_potato: + display_name: Patate obèse + graphics: + textures: + north: obese_crops/basic/potato/obese_potato_side + south: obese_crops/basic/potato/obese_potato_side + east: obese_crops/basic/potato/obese_potato_side + west: obese_crops/basic/potato/obese_potato_side + up: obese_crops/basic/potato/obese_potato_top + down: obese_crops/basic/potato/obese_potato_bottom + behaviours: + block: + placed_model: + type: REAL_NOTE + break_particles: ITEM + up_block: omc_daily_events:obese_potato_stem + hardness: 5 + break_tools_blacklist: + - WOODEN_HOE + - STONE_HOE + - IRON_HOE + - COPPER_HOE + break_tools_whitelist: + - NETHERITE_HOE + - DIAMOND_HOE + events_tools_whitelist: + - NETHERITE_HOE + - DIAMOND_HOE + events: + placed_block: + interact: + play_sound: + name: item.axe.strip + volume: 1.0 + pitch: 0.6 + category: MASTER + stop_previous: false + replace_block: + delay: 5 + from: omc_daily_events:obese_potato + to: omc_daily_events:peeled_obese_potato + replace_near_blocks: + radius: 2 + delay: 5 + from: omc_daily_events:obese_potato_stem + to: air + + obese_poisonous_potato: + display_name: Patate empoisonnée obèse + graphics: + textures: + north: obese_crops/basic/poisonous_potato/obese_poisonous_potato_side + south: obese_crops/basic/poisonous_potato/obese_poisonous_potato_side + east: obese_crops/basic/poisonous_potato/obese_poisonous_potato_side + west: obese_crops/basic/poisonous_potato/obese_poisonous_potato_side + up: obese_crops/basic/poisonous_potato/obese_poisonous_potato_top + down: obese_crops/basic/poisonous_potato/obese_poisonous_potato_bottom + behaviours: + block: + placed_model: + type: REAL_NOTE + break_particles: ITEM + up_block: omc_daily_events:obese_potato_stem + + obese_potato_stem: + display_name: Tige de patate obèse + graphics: + icon: obese_crops/basic/potato/obese_potato_stem + parent: block/cross + textures: + cross: obese_crops/basic/potato/obese_potato_stem + behaviours: + block: + placed_model: + type: REAL_WIRE + break_particles: ITEM + drop_when_mined: false + + # --- Baked potato --- + obese_baked_potato: + display_name: Patate cuite obèse + graphics: + textures: + north: obese_crops/basic/baked_potato/obese_baked_potato_side_2 + south: obese_crops/basic/baked_potato/obese_baked_potato_side_1 + east: obese_crops/basic/baked_potato/obese_baked_potato_side_2 + west: obese_crops/basic/baked_potato/obese_baked_potato_side_1 + up: obese_crops/basic/baked_potato/obese_baked_potato_top + down: obese_crops/basic/baked_potato/obese_baked_potato_bottom + behaviours: + block: + placed_model: + type: REAL_NOTE + break_particles: ITEM + + + # --- Carrot --- + obese_carrot: + display_name: Carotte obèse + graphics: + textures: + north: obese_crops/basic/carrot/obese_carrot_side + south: obese_crops/basic/carrot/obese_carrot_side + east: obese_crops/basic/carrot/obese_carrot_side + west: obese_crops/basic/carrot/obese_carrot_side + up: obese_crops/basic/carrot/obese_carrot_top + down: obese_crops/basic/carrot/obese_carrot_bottom + behaviours: + block: + placed_model: + type: REAL_NOTE + break_particles: ITEM + up_block: omc_daily_events:obese_carrot_stem + + + + obese_carrot_stem: + display_name: Tige de carotte obèse + graphics: + icon: obese_crops/basic/carrot/obese_carrot_stem + parent: block/cross + textures: + cross: obese_crops/basic/carrot/obese_carrot_stem + behaviours: + block: + placed_model: + type: REAL_WIRE + break_particles: ITEM + drop_when_mined: false + + # --- Beetroot --- + obese_beetroot: + display_name: Bétrave obèse + graphics: + textures: + north: obese_crops/basic/beetroot/obese_beetroot_side + south: obese_crops/basic/beetroot/obese_beetroot_side + east: obese_crops/basic/beetroot/obese_beetroot_side + west: obese_crops/basic/beetroot/obese_beetroot_side + up: obese_crops/basic/beetroot/obese_beetroot_top + down: obese_crops/basic/beetroot/obese_beetroot_bottom + behaviours: + block: + placed_model: + type: REAL_NOTE + break_particles: ITEM + up_block: omc_daily_events:obese_beetroot_stem + + obese_beetroot_stem: + display_name: Tige de bétrave obèse + graphics: + icon: obese_crops/basic/beetroot/obese_beetroot_stem + parent: block/cross + textures: + cross: obese_crops/basic/beetroot/obese_beetroot_stem + behaviours: + block: + placed_model: + type: REAL_WIRE + break_particles: ITEM + drop_when_mined: false + + # --- Nether Wart --- + obese_nether_wart: + display_name: Verrue du nether obèse + graphics: + textures: + north: obese_crops/basic/nether_wart/obese_nether_wart_side + south: obese_crops/basic/nether_wart/obese_nether_wart_side + east: obese_crops/basic/nether_wart/obese_nether_wart_side + west: obese_crops/basic/nether_wart/obese_nether_wart_side + up: obese_crops/basic/nether_wart/obese_nether_wart_top + down: obese_crops/basic/nether_wart/obese_nether_wart_bottom + behaviours: + block: + placed_model: + type: REAL_NOTE + break_particles: ITEM + up_block: omc_daily_events:obese_nether_wart_stem + + obese_nether_wart_stem: + display_name: Tige de verrue du nether obèse + graphics: + icon: obese_crops/basic/nether_wart/obese_nether_wart_stem + parent: block/cross + textures: + cross: obese_crops/basic/nether_wart/obese_nether_wart_stem + behaviours: + block: + placed_model: + type: REAL_WIRE + break_particles: ITEM + drop_when_mined: false + + # --- Onion --- + obese_onion: + display_name: Oignon obèse + graphics: + textures: + north: obese_crops/basic/onion/obese_onion_side + south: obese_crops/basic/onion/obese_onion_side + east: obese_crops/basic/onion/obese_onion_side + west: obese_crops/basic/onion/obese_onion_side + up: obese_crops/basic/onion/obese_onion_top + down: obese_crops/basic/onion/obese_onion_bottom + behaviours: + block: + placed_model: + type: REAL_NOTE + break_particles: ITEM + + # --- Golden Apple --- + obese_golden_apple: + display_name: Pomme dorée obèse + graphics: + textures: + north: obese_crops/basic/golden_apple/obese_golden_apple_side + south: obese_crops/basic/golden_apple/obese_golden_apple_side + east: obese_crops/basic/golden_apple/obese_golden_apple_side + west: obese_crops/basic/golden_apple/obese_golden_apple_side + up: obese_crops/basic/golden_apple/obese_golden_apple_top + down: obese_crops/basic/golden_apple/obese_golden_apple_bottom + behaviours: + block: + placed_model: + type: REAL_NOTE + break_particles: ITEM + up_block: omc_daily_events:obese_golden_apple_stem + + obese_golden_apple_stem: + display_name: Tige de pomme dorée obèse + graphics: + icon: obese_crops/basic/golden_apple/obese_golden_apple_stem + parent: block/cross + textures: + cross: obese_crops/basic/golden_apple/obese_golden_apple_stem + behaviours: + block: + placed_model: + type: REAL_WIRE + break_particles: ITEM + drop_when_mined: false + + # PEELED VERSIONS + # --- Peeled Potato --- + peeled_obese_potato: + display_name: Patate épluchée obèse + graphics: + textures: + north: obese_crops/peeled/potato/peeled_obese_potato + south: obese_crops/peeled/potato/peeled_obese_potato + east: obese_crops/peeled/potato/peeled_obese_potato + west: obese_crops/peeled/potato/peeled_obese_potato + up: obese_crops/peeled/potato/peeled_obese_potato + down: obese_crops/peeled/potato/peeled_obese_potato + behaviours: + block: + placed_model: + type: REAL_NOTE + break_particles: ITEM + + # --- Peeled Beetroot--- + peeled_beetroot_potato: + display_name: Bétrave épluchée obèse + graphics: + textures: + north: obese_crops/peeled/beetroot/peeled_obese_beetroot + south: obese_crops/peeled/beetroot/peeled_obese_beetroot + east: obese_crops/peeled/beetroot/peeled_obese_beetroot + west: obese_crops/peeled/beetroot/peeled_obese_beetroot + up: obese_crops/peeled/beetroot/peeled_obese_beetroot + down: obese_crops/peeled/beetroot/peeled_obese_beetroot + behaviours: + block: + placed_model: + type: REAL_NOTE + break_particles: ITEM + + # --- Peeled Carrot--- + peeled_carrot_potato: + display_name: Carotte épluchée obèse + graphics: + textures: + north: obese_crops/peeled/carrot/peeled_obese_carrot_side + south: obese_crops/peeled/carrot/peeled_obese_carrot_side + east: obese_crops/peeled/carrot/peeled_obese_carrot_side + west: obese_crops/peeled/carrot/peeled_obese_carrot_side + up: obese_crops/peeled/carrot/peeled_obese_carrot_top + down: obese_crops/peeled/carrot/peeled_obese_carrot_bottom + behaviours: + block: + placed_model: + type: REAL_NOTE + break_particles: ITEM + + # --- Peeled Onion--- + peeled_onion_potato: + display_name: Oignon épluché obèse + graphics: + textures: + north: obese_crops/peeled/onion/peeled_obese_onion_side + south: obese_crops/peeled/onion/peeled_obese_onion_side + east: obese_crops/peeled/onion/peeled_obese_onion_side + west: obese_crops/peeled/onion/peeled_obese_onion_side + up: obese_crops/peeled/onion/peeled_obese_onion_top + down: obese_crops/peeled/onion/peeled_obese_onion_bottom + behaviours: + block: + placed_model: + type: REAL_NOTE + break_particles: ITEM \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/baked_potato/obese_baked_potato_bottom.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/baked_potato/obese_baked_potato_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..bfe49e9c93f05ea0b7201d8f0744c0b94cd4b38b GIT binary patch literal 224 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF*?Yc zB5_%^w~_OJ0|&FR-h~>q4Z<4l_D6qqolsCD7&tq{-0ALO)pz&iImrcDGFgT$(`c12 zT_E*MW?Hpy%9`v#9NRla{@=EG;9FU4iNGA>PJ2)(PbvT4gwp@!J(yH}eM ca@XGY?{-@uRnC7^G|*8Dp00i_>zopr0Lr>4$Jw?f7y?wi}B9<+X`W8uJflqePVMzXz(}EbxddW?=}?&|+p*mgg8?NDf?>>^Kwk%4rwd>g|)*zFKCqFVD;gBv}-E%G-Xg`CetDnm{r-UW|ws>G; literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/beetroot/obese_beetroot_bottom.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/beetroot/obese_beetroot_bottom.png similarity index 100% rename from src/main/resources/contents/omc_daily_events/textures/obese_crops/beetroot/obese_beetroot_bottom.png rename to src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/beetroot/obese_beetroot_bottom.png diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/beetroot/obese_beetroot_side.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/beetroot/obese_beetroot_side.png similarity index 100% rename from src/main/resources/contents/omc_daily_events/textures/obese_crops/beetroot/obese_beetroot_side.png rename to src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/beetroot/obese_beetroot_side.png diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/beetroot/obese_beetroot_stem.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/beetroot/obese_beetroot_stem.png similarity index 100% rename from src/main/resources/contents/omc_daily_events/textures/obese_crops/beetroot/obese_beetroot_stem.png rename to src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/beetroot/obese_beetroot_stem.png diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/beetroot/obese_beetroot_top.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/beetroot/obese_beetroot_top.png similarity index 100% rename from src/main/resources/contents/omc_daily_events/textures/obese_crops/beetroot/obese_beetroot_top.png rename to src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/beetroot/obese_beetroot_top.png diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/carrot/obese_carrot_bottom.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/carrot/obese_carrot_bottom.png similarity index 100% rename from src/main/resources/contents/omc_daily_events/textures/obese_crops/carrot/obese_carrot_bottom.png rename to src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/carrot/obese_carrot_bottom.png diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/carrot/obese_carrot_side.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/carrot/obese_carrot_side.png similarity index 100% rename from src/main/resources/contents/omc_daily_events/textures/obese_crops/carrot/obese_carrot_side.png rename to src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/carrot/obese_carrot_side.png diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/carrot/obese_carrot_stem.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/carrot/obese_carrot_stem.png similarity index 100% rename from src/main/resources/contents/omc_daily_events/textures/obese_crops/carrot/obese_carrot_stem.png rename to src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/carrot/obese_carrot_stem.png diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/carrot/obese_carrot_top.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/carrot/obese_carrot_top.png similarity index 100% rename from src/main/resources/contents/omc_daily_events/textures/obese_crops/carrot/obese_carrot_top.png rename to src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/carrot/obese_carrot_top.png diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/golden_apple/obese_golden_apple_bottom.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/golden_apple/obese_golden_apple_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..70dcbb838edb97e433738d9a69bbc9bb49b37213 GIT binary patch literal 285 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF0 zB8wRq_zrn|IcD2bot0OxcZT+^X$3EH z*ykTuxOnyK#r@fH>@C<=J0vCW^u^`+o#FV!Q60~?f3|66u>I{-o)WPaeyr&X#W{tk4)15E>G`5CZygiBC!9T8cDd*u^GcY@#|OX`Q_&S{_j1}sT5K*l@X|hv%n*=n1O-s z5C}7hYIrpO1-m?5977~7^Pbtr*JL2VdVxDC^7o227rNG6a+uS&DqHd5x>*y>rDpu7 zwUsYm2s)OLNS%G|^0G|-oU%y&^{q*>HMfde4g%h1hKw-t&Wo|%S{sj_Kt#+Puxzsw#S zd!_cvuCQ_l*7LX;IYn}U){HIY8l{Ue@(+0Va>_CU%*uCs^3G%bF5ZP4?J^s-YaY3` paPe#X18g4Lc@0|}!gXKPG063^2#d0PNd(%*;OXk;vd$@?2>@y@Q@H>D literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/golden_apple/obese_golden_apple_top.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/golden_apple/obese_golden_apple_top.png new file mode 100644 index 0000000000000000000000000000000000000000..c5a87b6a680d4aa0b35ec64a5ad60158a749215b GIT binary patch literal 270 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF?8FDQgt|sxCXp_dpGIC4m7UL8!n69`mM4pA&TZ3Bx%gLfL0OEr^}=Nak<1mGOV0gZWLqJ*W|Q}aSwN>S Nc)I$ztaD0e0sworX)^!- literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/nether_wart/obese_nether_wart_bottom.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/nether_wart/obese_nether_wart_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..3ed6e6ef16be39637618eaf80384384e37a2ae22 GIT binary patch literal 238 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF?JJNz%MLjerYvOinG8YvY3H^?=T269?xHq0u;>f zba4!kxGdUxQ1FNW57WdsOf7dDd@eP(i^iz^yz;!nIDi+oHF!;n+dGrqwe} zZ!CHz#Cu_lE?dfGjdRP^6uC}+u{QER)1Garb3!iir(}h^IO4Cnz;fU3WitFnb|0;{ dpPpm&@9i$G&n;aq@_=?Sc)I$ztaD0e0sv!#P@(_; literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/nether_wart/obese_nether_wart_side.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/nether_wart/obese_nether_wart_side.png new file mode 100644 index 0000000000000000000000000000000000000000..6c7f1f0626423af0874edd70ca9a1e88c69d317f GIT binary patch literal 252 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFkNt(RUvk_5c-d7I;J!GcfQS24TkI z`72U@f(4!~jv*44WxEdw9yZ`$=|9NYkfHF(K`KLGv5M%8bq9j}tIqhby?QfyQ0NLS zudAzEU+_=zJFmrHpAaj(MabvqC)P(y&gU0+n)yA7v=CSv{+UHq)$ literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/nether_wart/obese_nether_wart_stem.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/nether_wart/obese_nether_wart_stem.png new file mode 100644 index 0000000000000000000000000000000000000000..af3b9e872f77ca3810fef4fdc1705595f9a1cdf1 GIT binary patch literal 246 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G|^0G|-o7;(`Ce&HZi)@B)nDGDk;VYh9pFMt$VNswRge-L2Uyno4lpa^Gy zM`SSr1K(i~W;~w1A_XWI?djqeq7fY0?Vs&LOL#2T}VBy()EgU0(Z7- z-FBskGJ#Ca${e%YJhpV+SX5APWSWoI-0$1luc(zTUvhj#(H>jh@QP!i-=7M){68yk g@tMBW{8_8mMf;iGB`g-Z477&9)78&qol`;+00$URMF0Q* literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/nether_wart/obese_nether_wart_top.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/nether_wart/obese_nether_wart_top.png new file mode 100644 index 0000000000000000000000000000000000000000..b98d71560ef9b4bd81f3794a413c7842892f28eb GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFM1MG8@NHhxLO05{79c!EgXX&^0 x+;hA4t=mM@@WzIBv1UFsJ6|=;TD|+UcxZsg={t*jMS)IW@O1TaS?83{1OQsLUd8|b literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/onion/obese_onion_top.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/basic/onion/obese_onion_top.png new file mode 100644 index 0000000000000000000000000000000000000000..42b9e299faf66805750680348b89c3d35f503448 GIT binary patch literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFanM zpkSG&i(`nyW!|$F8JiV&SS}&%clQYUv)nSB(2+bQ9=G&;!Bs( znWshgOPp;|EGoPn#)+)VPkG*XpzL%%|Fk<-l+=0d^Arodunl`TeQ~5!QL@`yr=2lc uG0N?%N6*Gy+9fb;-}^vOp?imS|6?@0DH#}@b@e0A1q`09elF{r5}E*B!B~_4 literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/peeled/carrot/peeled_obese_carrot_bottom.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/peeled/carrot/peeled_obese_carrot_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..57177b16fe80a450c530ea43ff010a51e22d1f8c GIT binary patch literal 224 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFlBSEK+1V?A9Q zLnJP{_8t^HV8G$DP-nqermH#$lmC{lwwx;bV?M(&=7Q$T?OheCCci$EGXIp=vZ>BB zhHA6-vYriy+$ylBSEK+1BRyRl zLnJQC_8t^uG2}TkWwpW&ErXW|@Ahxs`uV{@9wC9{T2piC?zMDgYPY7$-*qT--iP(O z!&NNOcZttEetFTnJ2Ewk1=c4TZ&`ZSVdXx7*DF`n72Z8uD|VfIOFZv=0V!F3pd}2R Lu6{1-oD!MlBSEK+1qdi?5 zLnJPn`Ze+%P~g!1#IS?iLB8Pe|NCsaCYqS=<}xm@+!@s(dcaL{3#(g?V8o6YDy`O@ zbMN)t+bTInVeYdZCn}yyNPETiu*)wzz1i#L{{yj#ksGbJUVcJf}516KD;C Mr>mdKI;Vst0G*6XQ~&?~ literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/peeled/onion/peeled_obese_onion_bottom.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/peeled/onion/peeled_obese_onion_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..d41faa8c9094d78fe7692337d4157da8de7db861 GIT binary patch literal 228 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF4nJ@ErzW#^d=bQhqLVKq<}wkH}&M2EM}}%y>M1MG8+6?x!-r0;-mw#xI(`j|-Iefd*4jM= k-|tkOZQOW#-eXz$-<7@Hgkw9_I0*}aI1_r*vAk26?e?6|3jgPl9?HM&2)YW$*%J$+3vqc z|Iboqt}VOtDtM=sUMikGHMH}kv%$&pR;7Ncp4!aYI6HE6V6DP#j%ejl%M(C57(8A5 KT-G@yGywqINK9A& literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/obese_crops/peeled/potato/peeled_obese_potato.png b/src/main/resources/contents/omc_daily_events/textures/obese_crops/peeled/potato/peeled_obese_potato.png new file mode 100644 index 0000000000000000000000000000000000000000..219470ad21281958ce15715ac1bd6459ef0b74b7 GIT binary patch literal 249 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF4nJ@ErzW#^d=b zQhnXa({8th;VuKK8P~M$nQ-P@S##&ktm%H2b>CQQm_389y{M*$NBeC4y_uh% qEjm9}EqGN!{1N^6--E6f{^3vP6i5ygEi41t&EV Date: Tue, 2 Jun 2026 18:56:38 +0200 Subject: [PATCH 02/74] add: todos --- src/main/resources/contents/omc_daily_events/obese_crops.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/contents/omc_daily_events/obese_crops.yml b/src/main/resources/contents/omc_daily_events/obese_crops.yml index e91757962..ac69c1eeb 100644 --- a/src/main/resources/contents/omc_daily_events/obese_crops.yml +++ b/src/main/resources/contents/omc_daily_events/obese_crops.yml @@ -1,5 +1,6 @@ # assets from https://github.com/0rc1nus/Overweight-Farming +# todo: obese crops, peeled versions info: namespace: omc_daily_events items: From 58902594ecd19b07bdfc8a6c9c21fb7e6ce4072a Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sun, 7 Jun 2026 18:44:54 +0200 Subject: [PATCH 03/74] feat: base of daily event and DailyEventManager (init events planned) --- src/main/java/fr/openmc/core/OMCPlugin.java | 2 + .../commands/calendar/CalendarManager.java | 1 - .../commands/calendar/CalendarMenu.java | 7 +- .../dailyevents/DailyEventsManager.java | 147 ++++++++++++++++++ .../bloodynight/BloodyNightEvent.java | 50 ++++++ .../goldenharvest/GoldenHarvestEvent.java | 50 ++++++ .../MiraculousFishingEvent.java | 50 ++++++ .../dailyevents/models/DailyEvent.java | 11 ++ .../dailyevents/models/IncomingEventsDB.java | 41 +++++ .../fr/openmc/core/utils/text/DateUtils.java | 5 + .../default/dailyevents.properties | 3 + .../translations/default/events.properties | 3 + 12 files changed, 368 insertions(+), 2 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/DailyEvent.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/IncomingEventsDB.java create mode 100644 src/main/resources/translations/default/dailyevents.properties diff --git a/src/main/java/fr/openmc/core/OMCPlugin.java b/src/main/java/fr/openmc/core/OMCPlugin.java index 09227433b..338cd9fa3 100644 --- a/src/main/java/fr/openmc/core/OMCPlugin.java +++ b/src/main/java/fr/openmc/core/OMCPlugin.java @@ -28,6 +28,7 @@ import fr.openmc.core.features.economy.EconomyManager; import fr.openmc.core.features.economy.TransactionsManager; import fr.openmc.core.features.events.commands.calendar.CalendarManager; +import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; import fr.openmc.core.features.events.contents.halloween.managers.HalloweenManager; import fr.openmc.core.features.events.contents.weeklyevents.WeeklyEventsManager; import fr.openmc.core.features.events.contents.weeklyevents.contents.contest.managers.ContestManager; @@ -107,6 +108,7 @@ public class OMCPlugin extends JavaPlugin { new DynamicCooldownManager(), new ContestManager(), new WeeklyEventsManager(), + new DailyEventsManager(), new CalendarManager(), new DreamManager(), new MultiBlockManager(), diff --git a/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarManager.java b/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarManager.java index 21ad7b216..6a8e531bb 100644 --- a/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarManager.java +++ b/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarManager.java @@ -30,7 +30,6 @@ public static List getUpcomingEvents(int slots) { WeeklyEventsManager.getCurrentEvent() )); - //todo: implement DailyEvent in upcoming events if (events.getLast() instanceof WeeklyEvent we) { for (int i = events.size(); i <= slots; i++) { diff --git a/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarMenu.java b/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarMenu.java index 9df1c238a..2cf74aa66 100644 --- a/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarMenu.java +++ b/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarMenu.java @@ -5,6 +5,7 @@ import fr.openmc.api.menulib.utils.ItemMenuBuilder; import fr.openmc.api.menulib.utils.StaticSlots; import fr.openmc.core.OMCRegistry; +import fr.openmc.core.features.events.contents.dailyevents.models.DailyEvent; import fr.openmc.core.features.events.contents.weeklyevents.models.WeeklyEvent; import fr.openmc.core.features.events.contents.weeklyevents.models.WeeklyEventPhase; import fr.openmc.core.features.events.models.Event; @@ -80,7 +81,11 @@ public Map getButtons() { private List getEventLore(Event event) { List eventLore = new ArrayList<>(event.getDescription()); - if (event instanceof WeeklyEvent we) { + if (event instanceof DailyEvent de) { + eventLore.add(Component.empty()); + eventLore.add(TranslationManager.translation("feature.events.calendar.start_in")); + + } else if (event instanceof WeeklyEvent we) { eventLore.add(Component.empty()); eventLore.add(TranslationManager.translation("feature.events.calendar.phases")); for (WeeklyEventPhase phase : we.getPhases()) { diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java new file mode 100644 index 000000000..e7340631b --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java @@ -0,0 +1,147 @@ +package fr.openmc.core.features.events.contents.dailyevents; + +import com.j256.ormlite.dao.Dao; +import com.j256.ormlite.dao.DaoManager; +import com.j256.ormlite.support.ConnectionSource; +import com.j256.ormlite.table.TableUtils; +import fr.openmc.core.OMCPlugin; +import fr.openmc.core.bootstrap.features.Feature; +import fr.openmc.core.bootstrap.features.annotations.Credit; +import fr.openmc.core.bootstrap.features.types.DatabaseFeature; +import fr.openmc.core.bootstrap.features.types.LoadAfterItemsAdder; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.BloodyNightEvent; +import fr.openmc.core.features.events.contents.dailyevents.contents.goldenharvest.GoldenHarvestEvent; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.MiraculousFishingEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.IncomingEventsDB; +import fr.openmc.core.utils.text.DateUtils; +import org.bukkit.Bukkit; +import org.bukkit.scheduler.BukkitTask; + +import java.sql.SQLException; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@Credit(developers = {"iambibi_"}) +public class DailyEventsManager extends Feature implements LoadAfterItemsAdder, DatabaseFeature { + // * Constantes + public static final List EVENTS = List.of( + new MiraculousFishingEvent(), + new GoldenHarvestEvent(), + new BloodyNightEvent() + ); + + private final List SLOT_HOURS_EVENTS = new ArrayList<>(List.of( + 9, 13, 16, 19, 20 + )); + + // * Données à propos de la gestion des daily event + private DailyEvent outgoingEvent = null; + private BukkitTask nextEventTask; + public static List incomingEvents = new ArrayList<>(); + + private static Dao dao; + + @Override + public void init() { + incomingEvents = loadIncomingEvents(); + nextEventTask = scheduleNextEventTask(); + } + + @Override + public void save() { + saveIncomingEventsDB(new IncomingEventsDB(incomingEvents)); + } + + @Override + public void initDB(ConnectionSource connectionSource) throws SQLException { + dao = DaoManager.createDao(connectionSource, IncomingEventsDB.class); + TableUtils.createTableIfNotExists(connectionSource, IncomingEventsDB.class); + } + + public static IncomingEventsDB loadIncomingEventsDB() { + try { + IncomingEventsDB data = dao.queryForId(1); + if (data == null) { + data = new IncomingEventsDB(List.of()); + dao.create(data); + } + return data; + } catch (SQLException e) { + throw new RuntimeException("Erreur lors du chargement de IncomingEventsDB", e); + } + } + + public static void saveIncomingEventsDB(IncomingEventsDB data) { + try { + dao.createOrUpdate(data); + } catch (SQLException e) { + throw new RuntimeException("Erreur lors de la sauvegarde de IncomingEventsDB", e); + } + } + + /** + * On charge les evenements à venir + * Lors du premier chargement, on remplit directement notre liste de taille identique à nos slots horaires. + * @return la liste prévue des x prochains évenements + */ + private List loadIncomingEvents() { + IncomingEventsDB data = loadIncomingEventsDB(); + List incomingEvent = data.getDailyEventsIncomings(); + + System.out.println("before incomingEvent " + incomingEvent); + + // * Si la liste est vide, soit c'est la premiere fois qu'on lance le plugin, soit que tout les events sont fini + if (incomingEvent.isEmpty()) { + List copyEvents = generateRandomOrder(); + + for (int _ : SLOT_HOURS_EVENTS) { + if (copyEvents.isEmpty()) { + copyEvents = generateRandomOrder(); + } + + incomingEvent.add(copyEvents.removeFirst()); + } + } + + System.out.println("after incomingEvent " + incomingEvent); + return incomingEvent; + } + + private BukkitTask scheduleNextEventTask() { + LocalDateTime now = LocalDateTime.now(); + // * On cherche la prochaine heure + Integer nextHour = SLOT_HOURS_EVENTS.stream() + .filter(hour -> hour > now.getHour()) + .findFirst() + .orElse(null); + + // si c'est null, alors on rempli la file et on schedule pour le premier horaire + LocalDateTime scheduleTime; + if (nextHour == null) { + incomingEvents = loadIncomingEvents(); + scheduleTime = now.toLocalDate().plusDays(1).atTime(SLOT_HOURS_EVENTS.getFirst(), 0); + } else { + scheduleTime = now.toLocalDate().atTime(nextHour, 0); + } + + long delayTicks = DateUtils.getDelayBetweenNow(scheduleTime) * 20; + + System.out.println("Scheduling next daily event in " + delayTicks / 20 + " seconds at " + scheduleTime); + + return Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> { + outgoingEvent = incomingEvents.removeFirst(); + + outgoingEvent.onStart(); + nextEventTask = scheduleNextEventTask(); + }, delayTicks); + } + + private List generateRandomOrder() { + List copyEvents = new ArrayList<>(EVENTS); + Collections.shuffle(copyEvents); + return copyEvents; + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java new file mode 100644 index 000000000..83d051fd6 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java @@ -0,0 +1,50 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight; + +import fr.openmc.core.features.events.contents.dailyevents.models.DailyEvent; +import fr.openmc.core.utils.text.messages.TranslationManager; +import net.kyori.adventure.text.Component; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class BloodyNightEvent extends DailyEvent { + @Override + public String getEventId() { + return "bloody_night"; + } + + @Override + public int getDuration() { + return 20; + } + + @Override + public Runnable onStart() { + return () -> { + System.out.println("BLOODY NIGHT START"); + }; + } + + @Override + public Runnable onEnd() { + return () -> { + System.out.println("BLOODY NIGHT END"); + }; + } + + @Override + public Component getName() { + return TranslationManager.translation("feature.dailyevents.bloodynight.name"); + } + + @Override + public List getDescription() { + return List.of(); + } + + @Override + public ItemStack getIcon() { + return new ItemStack(Material.REDSTONE); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java new file mode 100644 index 000000000..37841345d --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java @@ -0,0 +1,50 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.goldenharvest; + +import fr.openmc.core.features.events.contents.dailyevents.models.DailyEvent; +import fr.openmc.core.utils.text.messages.TranslationManager; +import net.kyori.adventure.text.Component; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class GoldenHarvestEvent extends DailyEvent { + @Override + public String getEventId() { + return "golden_harvest"; + } + + @Override + public int getDuration() { + return 40; + } + + @Override + public Runnable onStart() { + return () -> { + System.out.println("GOLDEN HARVEST START"); + }; + } + + @Override + public Runnable onEnd() { + return () -> { + System.out.println("GOLDEN HARVEST END"); + }; + } + + @Override + public Component getName() { + return TranslationManager.translation("feature.dailyevents.goldenharvest.name"); + } + + @Override + public List getDescription() { + return List.of(); + } + + @Override + public ItemStack getIcon() { + return new ItemStack(Material.GOLDEN_HOE); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java new file mode 100644 index 000000000..a91a806ed --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java @@ -0,0 +1,50 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing; + +import fr.openmc.core.features.events.contents.dailyevents.models.DailyEvent; +import fr.openmc.core.utils.text.messages.TranslationManager; +import net.kyori.adventure.text.Component; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class MiraculousFishingEvent extends DailyEvent { + @Override + public String getEventId() { + return "miraculous_fishing"; + } + + @Override + public int getDuration() { + return 30; + } + + @Override + public Runnable onStart() { + return () -> { + System.out.println("MIRACULOUS FISHING START"); + }; + } + + @Override + public Runnable onEnd() { + return () -> { + System.out.println("MIRACULOUS FISHING END"); + }; + } + + @Override + public Component getName() { + return TranslationManager.translation("feature.dailyevents.miraculousfishing.name"); + } + + @Override + public List getDescription() { + return List.of(); + } + + @Override + public ItemStack getIcon() { + return new ItemStack(Material.FISHING_ROD); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/DailyEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/DailyEvent.java new file mode 100644 index 000000000..92dd2e938 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/DailyEvent.java @@ -0,0 +1,11 @@ +package fr.openmc.core.features.events.contents.dailyevents.models; + +import fr.openmc.core.features.events.models.Event; + +public abstract class DailyEvent extends Event { + public abstract String getEventId(); + + public abstract int getDuration(); + public abstract Runnable onStart(); + public abstract Runnable onEnd(); +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/IncomingEventsDB.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/IncomingEventsDB.java new file mode 100644 index 000000000..1d96b5775 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/IncomingEventsDB.java @@ -0,0 +1,41 @@ +package fr.openmc.core.features.events.contents.dailyevents.models; + +import com.j256.ormlite.field.DataType; +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; +import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; +import lombok.Getter; +import lombok.Setter; + +import java.util.Arrays; +import java.util.List; + +import static java.util.stream.Collectors.toList; + +@Getter +@DatabaseTable(tableName = "daily_event_incoming") +public class IncomingEventsDB { + @DatabaseField(id = true, columnName = "id") + private int id = 1; + + @Setter + @DatabaseField(columnName = "incomings", dataType = DataType.SERIALIZABLE) + private String[] dailyEventsIdIncomings; + + public IncomingEventsDB() {} + + public IncomingEventsDB(List incomingEventsList) { + this.dailyEventsIdIncomings = incomingEventsList.stream() + .map(DailyEvent::getEventId) + .toArray(String[]::new); + } + + public List getDailyEventsIncomings() { + return Arrays.stream(dailyEventsIdIncomings) + .map(id -> DailyEventsManager.EVENTS.stream() + .filter(event -> event.getEventId().equals(id)) + .findFirst() + .orElseThrow(() -> new IllegalStateException("Aucun daily event trouvé pour l'id : " + id))) + .collect(toList()); + } +} diff --git a/src/main/java/fr/openmc/core/utils/text/DateUtils.java b/src/main/java/fr/openmc/core/utils/text/DateUtils.java index 0086dcff8..7e09e839c 100644 --- a/src/main/java/fr/openmc/core/utils/text/DateUtils.java +++ b/src/main/java/fr/openmc/core/utils/text/DateUtils.java @@ -184,4 +184,9 @@ public static long getSecondsUntilDayOfWeekTime(DayOfWeek dayOfWeek, int hour, i return ChronoUnit.SECONDS.between(now, nextDayOfWeekMidnight); } + + public static long getDelayBetweenNow(LocalDateTime time) { + LocalDateTime now = LocalDateTime.now(); + return ChronoUnit.SECONDS.between(now, time); + } } diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties new file mode 100644 index 000000000..74b801f06 --- /dev/null +++ b/src/main/resources/translations/default/dailyevents.properties @@ -0,0 +1,3 @@ +feature.dailyevents.bloodynight.name=Nuit Sanglante +feature.dailyevents.goldenharvest.name=Moisson dorée +feature.dailyevents.miraculousfishing.name=Pêche miraculeuse diff --git a/src/main/resources/translations/default/events.properties b/src/main/resources/translations/default/events.properties index 209220f0e..5ca743dae 100644 --- a/src/main/resources/translations/default/events.properties +++ b/src/main/resources/translations/default/events.properties @@ -1,6 +1,9 @@ feature.events.calendar.unknown_phase=Inconnu feature.events.calendar.title=Calendrier Evenementiel feature.events.calendar.weekend_event_name=Evenement du Weekend +feature.events.calendar.start_in=Commencement dans %1$s +feature.events.calendar.start_date=Date de début : %1$s +feature.events.calendar.end_date=Date de find : %1$s feature.events.calendar.phases=Phases : feature.events.calendar.phase.line=- %1$s le %2$s à %3$s From 972fb5673c97d9387ce3c51e8216c1bfb3ede8c8 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Mon, 8 Jun 2026 18:03:59 +0200 Subject: [PATCH 04/74] feat: make calendar functional --- .../core/features/economy/BankManager.java | 3 +- .../commands/calendar/CalendarManager.java | 7 +-- .../commands/calendar/CalendarMenu.java | 54 ++++++++++++++----- .../dailyevents/DailyEventsManager.java | 51 ++++++++++++------ .../bloodynight/BloodyNightEvent.java | 2 +- .../goldenharvest/GoldenHarvestEvent.java | 2 +- .../MiraculousFishingEvent.java | 2 +- .../dailyevents/models/IncomingEventsDB.java | 4 +- .../models/ScheduleDailyEvent.java | 41 ++++++++++++++ .../features/friend/FriendSQLManager.java | 4 +- .../features/mailboxes/MailboxManager.java | 5 +- .../fr/openmc/core/utils/text/DateUtils.java | 35 +++++++++--- .../default/dailyevents.properties | 19 +++++-- .../translations/default/events.properties | 6 +-- 14 files changed, 179 insertions(+), 56 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/ScheduleDailyEvent.java diff --git a/src/main/java/fr/openmc/core/features/economy/BankManager.java b/src/main/java/fr/openmc/core/features/economy/BankManager.java index 4369d06d7..25392fd2c 100644 --- a/src/main/java/fr/openmc/core/features/economy/BankManager.java +++ b/src/main/java/fr/openmc/core/features/economy/BankManager.java @@ -20,6 +20,7 @@ import fr.openmc.core.features.economy.events.BankDepositEvent; import fr.openmc.core.features.economy.models.Bank; import fr.openmc.core.utils.cache.CacheOfflinePlayer; +import fr.openmc.core.utils.text.DateUtils; import fr.openmc.core.utils.text.InputUtils; import fr.openmc.core.utils.text.messages.MessageType; import fr.openmc.core.utils.text.messages.MessagesManager; @@ -283,7 +284,7 @@ public static void updateInterestTimer() { } public static long getSecondsUntilInterest() { - LocalDateTime now = LocalDateTime.now(); + LocalDateTime now = DateUtils.getLocalDateTime(); LocalDateTime nextMonday = now.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY)).withHour(2).withMinute(0) .withSecond(0); // if it is after 2 AM, get the monday after diff --git a/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarManager.java b/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarManager.java index 6a8e531bb..f065c0627 100644 --- a/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarManager.java +++ b/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarManager.java @@ -3,6 +3,7 @@ import fr.openmc.core.bootstrap.features.Feature; import fr.openmc.core.bootstrap.features.types.HasCommands; import fr.openmc.core.bootstrap.features.types.LoadAfterItemsAdder; +import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; import fr.openmc.core.features.events.contents.weeklyevents.WeeklyEventsManager; import fr.openmc.core.features.events.contents.weeklyevents.models.WeeklyEvent; import fr.openmc.core.features.events.contents.weeklyevents.models.WeeklyEventPhase; @@ -26,10 +27,10 @@ public Set getCommands() { } public static List getUpcomingEvents(int slots) { - List events = new ArrayList<>(List.of( - WeeklyEventsManager.getCurrentEvent() - )); + List events = new ArrayList<>(); + events.addAll(DailyEventsManager.incomingEvents); + events.add(WeeklyEventsManager.getCurrentEvent()); if (events.getLast() instanceof WeeklyEvent we) { for (int i = events.size(); i <= slots; i++) { diff --git a/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarMenu.java b/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarMenu.java index 2cf74aa66..83c15dfb4 100644 --- a/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarMenu.java +++ b/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarMenu.java @@ -5,10 +5,11 @@ import fr.openmc.api.menulib.utils.ItemMenuBuilder; import fr.openmc.api.menulib.utils.StaticSlots; import fr.openmc.core.OMCRegistry; -import fr.openmc.core.features.events.contents.dailyevents.models.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.ScheduleDailyEvent; import fr.openmc.core.features.events.contents.weeklyevents.models.WeeklyEvent; import fr.openmc.core.features.events.contents.weeklyevents.models.WeeklyEventPhase; import fr.openmc.core.features.events.models.Event; +import fr.openmc.core.utils.text.DateUtils; import fr.openmc.core.utils.text.messages.TranslationManager; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -23,9 +24,12 @@ import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.format.TextStyle; +import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalAdjusters; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class CalendarMenu extends PaginatedMenu { public CalendarMenu(Player owner) { @@ -46,10 +50,23 @@ public CalendarMenu(Player owner) { public List getItems() { List items = new ArrayList<>(); for (Event event : CalendarManager.getUpcomingEvents(14)) { - items.add(new ItemMenuBuilder(this, event.getIcon(), meta -> { + ItemMenuBuilder itemBuilder = new ItemMenuBuilder(this, event.getIcon(), meta -> { meta.customName(event.getName().decoration(TextDecoration.ITALIC, false)); meta.lore(getEventLore(event)); - })); + }); + + if (event instanceof ScheduleDailyEvent) { + //todo: add dynamic item +// MenuUtils.runDynamicItem(getOwner(), this, , builder -> { +// ScheduleDailyEvent de = (ScheduleDailyEvent) event; +// builder.getItemMeta().ifPresent(meta -> { +// meta.displayName(de.getName().decoration(TextDecoration.ITALIC, false)); +// meta.lore(getEventLore(de)); +// }); +// }); + } else if (event instanceof WeeklyEvent) { + items.add(itemBuilder); + } } return items; } @@ -81,15 +98,30 @@ public Map getButtons() { private List getEventLore(Event event) { List eventLore = new ArrayList<>(event.getDescription()); - if (event instanceof DailyEvent de) { + if (event instanceof ScheduleDailyEvent de) { + LocalDateTime now = DateUtils.getLocalDateTime(); + LocalDateTime startDate = de.getScheduledStartDate(); + LocalDateTime endDate = de.getScheduledStartDate(); + + eventLore.add(Component.empty()); + eventLore.add(TranslationManager.translation("feature.events.calendar.start_in", + Component.text(DateUtils.convertSecondToTime(ChronoUnit.SECONDS.between(now, startDate)), NamedTextColor.YELLOW) + )); eventLore.add(Component.empty()); - eventLore.add(TranslationManager.translation("feature.events.calendar.start_in")); + eventLore.add(TranslationManager.translation("feature.events.calendar.start_date", + Component.text(DateUtils.formatDate(startDate), NamedTextColor.AQUA), + Component.text(DateUtils.formatHourMinute(endDate.getHour(), endDate.getMinute()), NamedTextColor.AQUA) + )); + eventLore.add(TranslationManager.translation("feature.events.calendar.end_date", + Component.text(DateUtils.formatDate(endDate), NamedTextColor.AQUA), + Component.text(DateUtils.formatHourMinute(endDate.getHour(), endDate.getMinute()), NamedTextColor.AQUA) + )); } else if (event instanceof WeeklyEvent we) { eventLore.add(Component.empty()); eventLore.add(TranslationManager.translation("feature.events.calendar.phases")); for (WeeklyEventPhase phase : we.getPhases()) { - LocalDateTime now = LocalDateTime.now(); + LocalDateTime now = DateUtils.getLocalDateTime(); LocalDate nextDate = now.toLocalDate() .with(TemporalAdjusters.nextOrSame(phase.getStartDay())) @@ -100,10 +132,8 @@ private List getEventLore(Event event) { phase.getStartMinutes() ); - String formattedDate = dateEvent.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.FRANCE) - + " " + dateEvent.getDayOfMonth() + " " - + dateEvent.getMonth().getDisplayName(TextStyle.FULL, Locale.FRANCE); - String formattedTime = phase.getStartHour() + "h" + String.format("%02d", phase.getStartMinutes()); + String formattedDate = DateUtils.formatDate(dateEvent); + String formattedTime = DateUtils.formatHourMinute(phase.getStartHour(), phase.getStartMinutes()); eventLore.add(TranslationManager.translation( "feature.events.calendar.phase.line", diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java index e7340631b..9ab3187d6 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java @@ -14,6 +14,7 @@ import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.MiraculousFishingEvent; import fr.openmc.core.features.events.contents.dailyevents.models.DailyEvent; import fr.openmc.core.features.events.contents.dailyevents.models.IncomingEventsDB; +import fr.openmc.core.features.events.contents.dailyevents.models.ScheduleDailyEvent; import fr.openmc.core.utils.text.DateUtils; import org.bukkit.Bukkit; import org.bukkit.scheduler.BukkitTask; @@ -34,13 +35,13 @@ public class DailyEventsManager extends Feature implements LoadAfterItemsAdder, ); private final List SLOT_HOURS_EVENTS = new ArrayList<>(List.of( - 9, 13, 16, 19, 20 + 9, 13, 16, 20, 21 )); // * Données à propos de la gestion des daily event - private DailyEvent outgoingEvent = null; + private ScheduleDailyEvent outgoingEvent = null; private BukkitTask nextEventTask; - public static List incomingEvents = new ArrayList<>(); + public static List incomingEvents = new ArrayList<>(); private static Dao dao; @@ -87,31 +88,37 @@ public static void saveIncomingEventsDB(IncomingEventsDB data) { * Lors du premier chargement, on remplit directement notre liste de taille identique à nos slots horaires. * @return la liste prévue des x prochains évenements */ - private List loadIncomingEvents() { + private List loadIncomingEvents() { + List scheduledEvents = new ArrayList<>(); + LocalDateTime now = DateUtils.getLocalDateTime(); IncomingEventsDB data = loadIncomingEventsDB(); List incomingEvent = data.getDailyEventsIncomings(); System.out.println("before incomingEvent " + incomingEvent); // * Si la liste est vide, soit c'est la premiere fois qu'on lance le plugin, soit que tout les events sont fini - if (incomingEvent.isEmpty()) { - List copyEvents = generateRandomOrder(); - - for (int _ : SLOT_HOURS_EVENTS) { - if (copyEvents.isEmpty()) { - copyEvents = generateRandomOrder(); - } + List copyEvents = new ArrayList<>(incomingEvent); + for (int hourSlot : SLOT_HOURS_EVENTS) { + if (copyEvents.isEmpty()) { + copyEvents = generateRandomOrder(); + } - incomingEvent.add(copyEvents.removeFirst()); + LocalDateTime scheduledDailyEvent; + if (hourSlot > now.getHour()) { + scheduledDailyEvent=now.withHour(hourSlot).withMinute(0).withSecond(0).withNano(0); + } else { + scheduledDailyEvent=now.plusDays(1) + .withHour(hourSlot).withMinute(0).withSecond(0).withNano(0); } + scheduledEvents.add(new ScheduleDailyEvent(copyEvents.removeFirst(), scheduledDailyEvent)); } - System.out.println("after incomingEvent " + incomingEvent); - return incomingEvent; + System.out.println("after scheduledEvents " + scheduledEvents); + return scheduledEvents; } private BukkitTask scheduleNextEventTask() { - LocalDateTime now = LocalDateTime.now(); + LocalDateTime now = DateUtils.getLocalDateTime(); // * On cherche la prochaine heure Integer nextHour = SLOT_HOURS_EVENTS.stream() .filter(hour -> hour > now.getHour()) @@ -132,10 +139,20 @@ private BukkitTask scheduleNextEventTask() { System.out.println("Scheduling next daily event in " + delayTicks / 20 + " seconds at " + scheduleTime); return Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> { + if (incomingEvents.isEmpty()) { + incomingEvents = loadIncomingEvents(); + } + outgoingEvent = incomingEvents.removeFirst(); - outgoingEvent.onStart(); - nextEventTask = scheduleNextEventTask(); + outgoingEvent.getDailyEvent().onStart().run(); + + //todo: toast + //todo: gestion de fin + + // * 10 secondes d'attente avant de schedule un autre event (evite que plusieurs events se lancent en meme temps) + Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> + nextEventTask = scheduleNextEventTask(), 20L * 10); }, delayTicks); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java index 83d051fd6..925125c9c 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java @@ -40,7 +40,7 @@ public Component getName() { @Override public List getDescription() { - return List.of(); + return TranslationManager.translationLore("feature.dailyevents.bloodynight.lore"); } @Override diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java index 37841345d..1995c9adc 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java @@ -40,7 +40,7 @@ public Component getName() { @Override public List getDescription() { - return List.of(); + return TranslationManager.translationLore("feature.dailyevents.goldenharvest.lore"); } @Override diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java index a91a806ed..c5495a08a 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java @@ -40,7 +40,7 @@ public Component getName() { @Override public List getDescription() { - return List.of(); + return TranslationManager.translationLore("feature.dailyevents.miraculousfishing.lore"); } @Override diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/IncomingEventsDB.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/IncomingEventsDB.java index 1d96b5775..d61f6e0a4 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/IncomingEventsDB.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/IncomingEventsDB.java @@ -24,9 +24,9 @@ public class IncomingEventsDB { public IncomingEventsDB() {} - public IncomingEventsDB(List incomingEventsList) { + public IncomingEventsDB(List incomingEventsList) { this.dailyEventsIdIncomings = incomingEventsList.stream() - .map(DailyEvent::getEventId) + .map(d->d.getDailyEvent().getEventId()) .toArray(String[]::new); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/ScheduleDailyEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/ScheduleDailyEvent.java new file mode 100644 index 000000000..ea695d928 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/ScheduleDailyEvent.java @@ -0,0 +1,41 @@ +package fr.openmc.core.features.events.contents.dailyevents.models; + + +import fr.openmc.core.features.events.models.Event; +import lombok.Getter; +import net.kyori.adventure.text.Component; +import org.bukkit.inventory.ItemStack; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * Wrapper qui combine le DailyEvent et sa date d'execution + */ +@Getter +public class ScheduleDailyEvent extends Event { + private final DailyEvent dailyEvent; + private final LocalDateTime scheduledStartDate; + private final LocalDateTime scheduledEndDate; + + public ScheduleDailyEvent(DailyEvent dailyEvent, LocalDateTime scheduledDate) { + this.dailyEvent = dailyEvent; + this.scheduledStartDate = scheduledDate; + this.scheduledEndDate = scheduledDate.plusMinutes(dailyEvent.getDuration()); + } + + @Override + public Component getName() { + return dailyEvent.getName(); + } + + @Override + public List getDescription() { + return dailyEvent.getDescription(); + } + + @Override + public ItemStack getIcon() { + return dailyEvent.getIcon(); + } +} diff --git a/src/main/java/fr/openmc/core/features/friend/FriendSQLManager.java b/src/main/java/fr/openmc/core/features/friend/FriendSQLManager.java index 3176170b7..1abb25afe 100644 --- a/src/main/java/fr/openmc/core/features/friend/FriendSQLManager.java +++ b/src/main/java/fr/openmc/core/features/friend/FriendSQLManager.java @@ -7,10 +7,10 @@ import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.table.TableUtils; import fr.openmc.core.bootstrap.integration.OMCLogger; +import fr.openmc.core.utils.text.DateUtils; import java.sql.SQLException; import java.sql.Timestamp; -import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -50,7 +50,7 @@ private static Friend getFriendObject(UUID first, UUID second) { public static boolean addInDatabase(UUID first, UUID second) { try { - return friendsDao.create(new Friend(first, second, Timestamp.valueOf(LocalDateTime.now()))) != 0; + return friendsDao.create(new Friend(first, second, Timestamp.valueOf(DateUtils.getLocalDateTime()))) != 0; } catch (SQLException e) { OMCLogger.error("Failed to add Friends in database", e); return false; diff --git a/src/main/java/fr/openmc/core/features/mailboxes/MailboxManager.java b/src/main/java/fr/openmc/core/features/mailboxes/MailboxManager.java index 7224574ed..cef806105 100644 --- a/src/main/java/fr/openmc/core/features/mailboxes/MailboxManager.java +++ b/src/main/java/fr/openmc/core/features/mailboxes/MailboxManager.java @@ -16,6 +16,7 @@ import fr.openmc.core.features.settings.PlayerSettingsManager; import fr.openmc.core.features.settings.SettingType; import fr.openmc.core.utils.bukkit.serializer.BukkitSerializer; +import fr.openmc.core.utils.text.DateUtils; import fr.openmc.core.utils.text.messages.MessageType; import fr.openmc.core.utils.text.messages.MessagesManager; import fr.openmc.core.utils.text.messages.Prefix; @@ -80,7 +81,7 @@ public static boolean sendItems(Player sender, OfflinePlayer receiver, ItemStack private static boolean sendLetter(Player sender, OfflinePlayer receiver, ItemStack[] items) { String receiverName = receiver.getName(); int numItems = Arrays.stream(items).mapToInt(ItemStack::getAmount).sum(); - LocalDateTime sent = LocalDateTime.now(); + LocalDateTime sent = DateUtils.getLocalDateTime(); try { byte[] itemsBytes = BukkitSerializer.serializeItemStacks(items); @@ -122,7 +123,7 @@ public static void sendItemsToAOfflinePlayerBatch(Map 2025-34 - 1 YY-w @@ -133,7 +135,7 @@ private static String formatTime(long millis) { * Renvoie une chaine de caractère en fonction du temps passé */ public static String formatRelativeDate(LocalDateTime dateTime) { - LocalDateTime now = LocalDateTime.now(); + LocalDateTime now = DateUtils.getLocalDateTime(); Duration duration = Duration.between(dateTime, now); long minutes = duration.toMinutes(); @@ -154,13 +156,29 @@ public static String formatRelativeDate(LocalDateTime dateTime) { } } + /** + * Renvoie une chaine de caractère (ex dimanche 7 juin) + */ + public static String formatDate(LocalDateTime dateTime) { + return dateTime.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.FRANCE) + + " " + dateTime.getDayOfMonth() + " " + + dateTime.getMonth().getDisplayName(TextStyle.FULL, Locale.FRANCE); + } + + /** + * Renvoie une chaine de caractère (ex 0h12) + */ + public static String formatHourMinute(int hours, int minutes) { + return hours + "h" + String.format("%02d", minutes); + } + /** * Calcule le temps entre maintenant et lundi par exemple * @param day DayOfWeek * @return format 4h 2m 38s */ public static String getTimeUntilNextDay(DayOfWeek day) { - LocalDateTime now = LocalDateTime.now(); + LocalDateTime now = DateUtils.getLocalDateTime(); LocalDateTime nextDay = now.with(TemporalAdjusters.next(day)).toLocalDate().atStartOfDay(); @@ -174,7 +192,7 @@ public static String getTimeUntilNextDay(DayOfWeek day) { } public static long getSecondsUntilDayOfWeekTime(DayOfWeek dayOfWeek, int hour, int minute, int second) { - LocalDateTime now = LocalDateTime.now(); + LocalDateTime now = DateUtils.getLocalDateTime(); LocalDateTime nextDayOfWeekMidnight = now.with(TemporalAdjusters.nextOrSame(dayOfWeek)) .withHour(hour).withMinute(minute).withSecond(second).withNano(0); @@ -186,7 +204,8 @@ public static long getSecondsUntilDayOfWeekTime(DayOfWeek dayOfWeek, int hour, i } public static long getDelayBetweenNow(LocalDateTime time) { - LocalDateTime now = LocalDateTime.now(); + LocalDateTime now = getLocalDateTime(); + return ChronoUnit.SECONDS.between(now, time); } } diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties index 74b801f06..5033ab904 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -1,3 +1,16 @@ -feature.dailyevents.bloodynight.name=Nuit Sanglante -feature.dailyevents.goldenharvest.name=Moisson dorée -feature.dailyevents.miraculousfishing.name=Pêche miraculeuse +feature.dailyevents.bloodynight.name=Nuit Sanglante +feature.dailyevents.goldenharvest.name=Moisson dorée +feature.dailyevents.miraculousfishing.name=Pêche miraculeuse + +feature.dailyevents.bloodynight.lore=La nuit reste d'être sanglante... \ +
Protégez-vous, battez-vous, vous allez subire différentes vagues \ +
et vous aurez surement un gros boss à battre à plusieurs + +feature.dailyevents.goldenharvest.lore=Ça risque d'être sportif \ +
Attendez vous aux fermes qui tournerons au plein régime ! \ +
Bénéficiez de plusieures nouvelles ressources et de plusieures surprises + +feature.dailyevents.miraculousfishing.lore=Vivez une grande session pêche ! \ +
Attention les Monstres des Mers vous attenderons avec impatience \ +
pour vous sautez dessus! \ +
Mais vous risquerez d'avoir plusieures bonnes surprises si vous êtes chanceux \ No newline at end of file diff --git a/src/main/resources/translations/default/events.properties b/src/main/resources/translations/default/events.properties index 5ca743dae..0c087ed92 100644 --- a/src/main/resources/translations/default/events.properties +++ b/src/main/resources/translations/default/events.properties @@ -1,9 +1,9 @@ feature.events.calendar.unknown_phase=Inconnu feature.events.calendar.title=Calendrier Evenementiel feature.events.calendar.weekend_event_name=Evenement du Weekend -feature.events.calendar.start_in=Commencement dans %1$s -feature.events.calendar.start_date=Date de début : %1$s -feature.events.calendar.end_date=Date de find : %1$s +feature.events.calendar.start_in=Commence dans %1$s +feature.events.calendar.start_date=Date de début : %1$s à %2$s +feature.events.calendar.end_date=Date de fin : %1$s à %2$s feature.events.calendar.phases=Phases : feature.events.calendar.phase.line=- %1$s le %2$s à %3$s From 460289875c72f0afa3f5efe616bd9223ab267df5 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Mon, 8 Jun 2026 20:16:07 +0200 Subject: [PATCH 05/74] change: sort upcoming events --- .../commands/calendar/CalendarManager.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarManager.java b/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarManager.java index f065c0627..bdc69b674 100644 --- a/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarManager.java +++ b/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarManager.java @@ -4,16 +4,20 @@ import fr.openmc.core.bootstrap.features.types.HasCommands; import fr.openmc.core.bootstrap.features.types.LoadAfterItemsAdder; import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; +import fr.openmc.core.features.events.contents.dailyevents.models.ScheduleDailyEvent; import fr.openmc.core.features.events.contents.weeklyevents.WeeklyEventsManager; import fr.openmc.core.features.events.contents.weeklyevents.models.WeeklyEvent; import fr.openmc.core.features.events.contents.weeklyevents.models.WeeklyEventPhase; import fr.openmc.core.features.events.models.Event; +import fr.openmc.core.utils.text.DateUtils; import fr.openmc.core.utils.text.messages.TranslationManager; import net.kyori.adventure.text.Component; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import java.time.DayOfWeek; +import java.time.LocalDateTime; +import java.time.temporal.TemporalAdjusters; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -32,6 +36,15 @@ public static List getUpcomingEvents(int slots) { events.addAll(DailyEventsManager.incomingEvents); events.add(WeeklyEventsManager.getCurrentEvent()); + events.sort((e1, e2) -> { + LocalDateTime d1 = getEventStartDate(e1); + LocalDateTime d2 = getEventStartDate(e2); + if (d1 == null && d2 == null) return 0; + if (d1 == null) return 1; + if (d2 == null) return -1; + return d1.compareTo(d2); + }); + if (events.getLast() instanceof WeeklyEvent we) { for (int i = events.size(); i <= slots; i++) { int weekOffset = i; @@ -98,4 +111,18 @@ public ItemStack getIcon() { return events; } + + private static LocalDateTime getEventStartDate(Event event) { + if (event instanceof ScheduleDailyEvent sde) { + return sde.getScheduledStartDate(); + } else if (event instanceof WeeklyEvent we) { + WeeklyEventPhase firstPhase = we.getPhases().getFirst(); + LocalDateTime now = DateUtils.getLocalDateTime(); + return now.toLocalDate() + .with(TemporalAdjusters.nextOrSame(firstPhase.getStartDay())) + .plusWeeks(we.getWeekOffset()) + .atTime(firstPhase.getStartHour(), firstPhase.getStartMinutes()); + } + return null; + } } From 2d61273b3c1c16114f835ac0fb6e9d9d7e0fe706 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Mon, 8 Jun 2026 20:53:27 +0200 Subject: [PATCH 06/74] fix: dynamic item --- src/main/java/fr/openmc/api/menulib/Menu.java | 7 ++- .../java/fr/openmc/api/menulib/OpenMenu.java | 16 ++++++ .../commands/calendar/CalendarMenu.java | 56 +++++++++++++++---- 3 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 src/main/java/fr/openmc/api/menulib/OpenMenu.java diff --git a/src/main/java/fr/openmc/api/menulib/Menu.java b/src/main/java/fr/openmc/api/menulib/Menu.java index e3953ddd9..ffb758184 100644 --- a/src/main/java/fr/openmc/api/menulib/Menu.java +++ b/src/main/java/fr/openmc/api/menulib/Menu.java @@ -18,8 +18,10 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; @@ -152,7 +154,10 @@ public final void open() { Bukkit.getServer().getPluginManager().callEvent(new OpenMenuEvent(owner, this)); - owner.openInventory(inventory); + InventoryView openedMenu = owner.openInventory(inventory); + + if (this instanceof OpenMenu om) + om.onOpen(new InventoryOpenEvent(openedMenu)); } catch (Exception e) { MessagesManager.sendMessage(owner, TranslationManager.translation("api.menulib.an_error_occurred"), Prefix.OPENMC, MessageType.ERROR, false); owner.closeInventory(); diff --git a/src/main/java/fr/openmc/api/menulib/OpenMenu.java b/src/main/java/fr/openmc/api/menulib/OpenMenu.java new file mode 100644 index 000000000..097ec9dd1 --- /dev/null +++ b/src/main/java/fr/openmc/api/menulib/OpenMenu.java @@ -0,0 +1,16 @@ +package fr.openmc.api.menulib; + +import org.bukkit.event.inventory.InventoryOpenEvent; + +public interface OpenMenu { + /** + * Handles the event that occurs when a player open the menu's inventory. + * This method is called whenever an {@link InventoryOpenEvent} is triggered for a menu + * controlled by this class. Subclasses + * should implement the logic to respond to the inventory being opened, + * such as saving data or cleaning up resources. + * + * @param event The {@link InventoryOpenEvent} containing details about the open action, + */ + void onOpen(InventoryOpenEvent event); +} diff --git a/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarMenu.java b/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarMenu.java index 83c15dfb4..f54464e0f 100644 --- a/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarMenu.java +++ b/src/main/java/fr/openmc/core/features/events/commands/calendar/CalendarMenu.java @@ -1,9 +1,13 @@ package fr.openmc.core.features.events.commands.calendar; +import fr.openmc.api.menulib.MenuLib; +import fr.openmc.api.menulib.OpenMenu; import fr.openmc.api.menulib.PaginatedMenu; import fr.openmc.api.menulib.utils.InventorySize; import fr.openmc.api.menulib.utils.ItemMenuBuilder; +import fr.openmc.api.menulib.utils.MenuUtils; import fr.openmc.api.menulib.utils.StaticSlots; +import fr.openmc.core.OMCPlugin; import fr.openmc.core.OMCRegistry; import fr.openmc.core.features.events.contents.dailyevents.models.ScheduleDailyEvent; import fr.openmc.core.features.events.contents.weeklyevents.models.WeeklyEvent; @@ -11,6 +15,7 @@ import fr.openmc.core.features.events.models.Event; import fr.openmc.core.utils.text.DateUtils; import fr.openmc.core.utils.text.messages.TranslationManager; +import io.papermc.paper.persistence.PersistentDataContainerView; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; @@ -18,7 +23,9 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryOpenEvent; import org.bukkit.inventory.ItemStack; +import org.bukkit.persistence.PersistentDataType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,7 +38,9 @@ import java.util.List; import java.util.Map; -public class CalendarMenu extends PaginatedMenu { +public class CalendarMenu extends PaginatedMenu implements OpenMenu { + private static final HashMap scheduledEventById = new HashMap<>(); + public CalendarMenu(Player owner) { super(owner); } @@ -55,15 +64,10 @@ public List getItems() { meta.lore(getEventLore(event)); }); - if (event instanceof ScheduleDailyEvent) { - //todo: add dynamic item -// MenuUtils.runDynamicItem(getOwner(), this, , builder -> { -// ScheduleDailyEvent de = (ScheduleDailyEvent) event; -// builder.getItemMeta().ifPresent(meta -> { -// meta.displayName(de.getName().decoration(TextDecoration.ITALIC, false)); -// meta.lore(getEventLore(de)); -// }); -// }); + if (event instanceof ScheduleDailyEvent de) { + String itemId = "scheduled_" + de.getScheduledStartDate().toString().toLowerCase(); // .toLowerCase car mc enelve les maj sur les pdc + scheduledEventById.put(itemId, de); + items.add(itemBuilder.setItemId(itemId)); } else if (event instanceof WeeklyEvent) { items.add(itemBuilder); } @@ -71,6 +75,36 @@ public List getItems() { return items; } + @Override + public void onOpen(InventoryOpenEvent event) { + int i = 0; + for (ItemStack itemStack : event.getInventory().getContents()) { + if (itemStack == null) { + i++; + continue; + } + + PersistentDataContainerView pdc = itemStack.getPersistentDataContainer(); + if (!pdc.has(MenuLib.getItemIdKey())) { + i++; + continue; + } + + String itemId = pdc.get(MenuLib.getItemIdKey(), PersistentDataType.STRING); + ScheduleDailyEvent scheduleEvent = scheduledEventById.get(itemId); + + if (scheduleEvent != null) { + MenuUtils.runDynamicItem(getOwner(), this, i, () -> + new ItemMenuBuilder(this, scheduleEvent.getIcon(), meta -> { + meta.customName(scheduleEvent.getName().decoration(TextDecoration.ITALIC, false)); + meta.lore(getEventLore(scheduleEvent)); + }) + ).runTaskTimer(OMCPlugin.getInstance(), 0L, 20L); + } + i++; + } + } + @Override public List getTakableSlot() { return List.of(); @@ -83,7 +117,7 @@ public List getTakableSlot() { @Override public int getSizeOfItems() { - return getItems().size(); + return CalendarManager.getUpcomingEvents(14).size(); } @Override From c3a29730efeeaf2df0c515a0cdd3409de566e7f4 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Mon, 8 Jun 2026 21:08:38 +0200 Subject: [PATCH 07/74] change: logs --- .../events/contents/dailyevents/DailyEventsManager.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java index 9ab3187d6..3d1cca825 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java @@ -9,6 +9,7 @@ import fr.openmc.core.bootstrap.features.annotations.Credit; import fr.openmc.core.bootstrap.features.types.DatabaseFeature; import fr.openmc.core.bootstrap.features.types.LoadAfterItemsAdder; +import fr.openmc.core.bootstrap.integration.OMCLogger; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.BloodyNightEvent; import fr.openmc.core.features.events.contents.dailyevents.contents.goldenharvest.GoldenHarvestEvent; import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.MiraculousFishingEvent; @@ -94,8 +95,6 @@ private List loadIncomingEvents() { IncomingEventsDB data = loadIncomingEventsDB(); List incomingEvent = data.getDailyEventsIncomings(); - System.out.println("before incomingEvent " + incomingEvent); - // * Si la liste est vide, soit c'est la premiere fois qu'on lance le plugin, soit que tout les events sont fini List copyEvents = new ArrayList<>(incomingEvent); for (int hourSlot : SLOT_HOURS_EVENTS) { @@ -113,7 +112,6 @@ private List loadIncomingEvents() { scheduledEvents.add(new ScheduleDailyEvent(copyEvents.removeFirst(), scheduledDailyEvent)); } - System.out.println("after scheduledEvents " + scheduledEvents); return scheduledEvents; } @@ -136,7 +134,8 @@ private BukkitTask scheduleNextEventTask() { long delayTicks = DateUtils.getDelayBetweenNow(scheduleTime) * 20; - System.out.println("Scheduling next daily event in " + delayTicks / 20 + " seconds at " + scheduleTime); + OMCLogger.info("Les prochains evenement : " + incomingEvents); + OMCLogger.info("Prochain Evenement journalier : " + scheduleTime + "s (dans " + DateUtils.convertTime(DateUtils.getDelayBetweenNow(scheduleTime)) + ")"); return Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> { if (incomingEvents.isEmpty()) { From 5e3ef1606c78a23ac687182c344cbfaf51c17987 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Mon, 8 Jun 2026 21:19:12 +0200 Subject: [PATCH 08/74] feat: end event --- .../contents/dailyevents/DailyEventsManager.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java index 3d1cca825..39beeb8b3 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java @@ -36,7 +36,7 @@ public class DailyEventsManager extends Feature implements LoadAfterItemsAdder, ); private final List SLOT_HOURS_EVENTS = new ArrayList<>(List.of( - 9, 13, 16, 20, 21 + 9, 13, 16, 21 )); // * Données à propos de la gestion des daily event @@ -144,10 +144,16 @@ private BukkitTask scheduleNextEventTask() { outgoingEvent = incomingEvents.removeFirst(); + // * Commencement de l'evenement outgoingEvent.getDailyEvent().onStart().run(); //todo: toast - //todo: gestion de fin + + // * Programmation de la fin de l'evenement + Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> { + outgoingEvent.getDailyEvent().onEnd().run(); + outgoingEvent = null; + }, outgoingEvent.getDailyEvent().getDuration() * 20L * 20L); // * 10 secondes d'attente avant de schedule un autre event (evite que plusieurs events se lancent en meme temps) Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> From c8081468c2ab619f5a6a4f6eede3326a4870c121 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Mon, 8 Jun 2026 21:34:18 +0200 Subject: [PATCH 09/74] add: todo pour pas oublier --- .../dailyevents/DailyEventsManager.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java index 39beeb8b3..e33c5b61e 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java @@ -26,6 +26,8 @@ import java.util.Collections; import java.util.List; + +//todo: ajouter des javadocs et commentaires sur certaines parties @Credit(developers = {"iambibi_"}) public class DailyEventsManager extends Feature implements LoadAfterItemsAdder, DatabaseFeature { // * Constantes @@ -115,6 +117,7 @@ private List loadIncomingEvents() { return scheduledEvents; } + //todo: diviser ça en plusieurs sous méthodes private BukkitTask scheduleNextEventTask() { LocalDateTime now = DateUtils.getLocalDateTime(); // * On cherche la prochaine heure @@ -137,6 +140,8 @@ private BukkitTask scheduleNextEventTask() { OMCLogger.info("Les prochains evenement : " + incomingEvents); OMCLogger.info("Prochain Evenement journalier : " + scheduleTime + "s (dans " + DateUtils.convertTime(DateUtils.getDelayBetweenNow(scheduleTime)) + ")"); + //todo: toast 1 min avant commencement + return Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> { if (incomingEvents.isEmpty()) { incomingEvents = loadIncomingEvents(); @@ -147,13 +152,17 @@ private BukkitTask scheduleNextEventTask() { // * Commencement de l'evenement outgoingEvent.getDailyEvent().onStart().run(); - //todo: toast + //todo: setup ambient (interface EventAmbient) // * Programmation de la fin de l'evenement Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> { - outgoingEvent.getDailyEvent().onEnd().run(); - outgoingEvent = null; - }, outgoingEvent.getDailyEvent().getDuration() * 20L * 20L); + outgoingEvent.getDailyEvent().onEnd().run(); + outgoingEvent = null; + + //todo: remove ambient + //todo: end toast + + }, outgoingEvent.getDailyEvent().getDuration() * 20L * 20L); // * 10 secondes d'attente avant de schedule un autre event (evite que plusieurs events se lancent en meme temps) Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> From 0acf5a769cade83aa79e01489a1cbc54b401f039 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 9 Jun 2026 18:06:42 +0200 Subject: [PATCH 10/74] feat: add interface HasToast + use of toast (beginning, start, end) --- .../core/commands/debug/ToastCommand.java | 2 +- .../dailyevents/DailyEventsManager.java | 56 ++++++------------- .../bloodynight/BloodyNightEvent.java | 30 +++++++++- .../goldenharvest/GoldenHarvestEvent.java | 30 +++++++++- .../MiraculousFishingEvent.java | 30 +++++++++- .../dailyevents/models/DailyEvent.java | 11 ---- .../dailyevents/models/IncomingEventsDB.java | 1 + .../models/ScheduleDailyEvent.java | 1 + .../models/dailyevent/DailyEvent.java | 34 +++++++++++ .../models/dailyevent/HasToast.java | 13 +++++ .../tasks/ScheduleNextEventTask.java | 56 +++++++++++++++++++ .../tasks/ShowBeginningEventToastTask.java | 44 +++++++++++++++ .../core/utils/nms/toast/CustomToastData.java | 23 ++++++++ .../utils/nms/{ => toast}/ToastUtils.java | 56 +++++++++++++++++-- .../openmc/core/utils/world/WorldUtils.java | 26 +++++++++ .../default/dailyevents.properties | 16 +++++- .../translations/default/main.properties | 6 ++ 17 files changed, 371 insertions(+), 64 deletions(-) delete mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/DailyEvent.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/DailyEvent.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasToast.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ScheduleNextEventTask.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ShowBeginningEventToastTask.java create mode 100644 src/main/java/fr/openmc/core/utils/nms/toast/CustomToastData.java rename src/main/java/fr/openmc/core/utils/nms/{ => toast}/ToastUtils.java (62%) diff --git a/src/main/java/fr/openmc/core/commands/debug/ToastCommand.java b/src/main/java/fr/openmc/core/commands/debug/ToastCommand.java index d841aa915..11a225bf2 100644 --- a/src/main/java/fr/openmc/core/commands/debug/ToastCommand.java +++ b/src/main/java/fr/openmc/core/commands/debug/ToastCommand.java @@ -1,6 +1,6 @@ package fr.openmc.core.commands.debug; -import fr.openmc.core.utils.nms.ToastUtils; +import fr.openmc.core.utils.nms.toast.ToastUtils; import net.minecraft.advancements.AdvancementType; import org.bukkit.Material; import org.bukkit.entity.Player; diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java index e33c5b61e..8dbae7cb8 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java @@ -13,11 +13,12 @@ import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.BloodyNightEvent; import fr.openmc.core.features.events.contents.dailyevents.contents.goldenharvest.GoldenHarvestEvent; import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.MiraculousFishingEvent; -import fr.openmc.core.features.events.contents.dailyevents.models.DailyEvent; import fr.openmc.core.features.events.contents.dailyevents.models.IncomingEventsDB; import fr.openmc.core.features.events.contents.dailyevents.models.ScheduleDailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.tasks.ScheduleNextEventTask; +import fr.openmc.core.features.events.contents.dailyevents.tasks.ShowBeginningEventToastTask; import fr.openmc.core.utils.text.DateUtils; -import org.bukkit.Bukkit; import org.bukkit.scheduler.BukkitTask; import java.sql.SQLException; @@ -37,13 +38,15 @@ public class DailyEventsManager extends Feature implements LoadAfterItemsAdder, new BloodyNightEvent() ); - private final List SLOT_HOURS_EVENTS = new ArrayList<>(List.of( - 9, 13, 16, 21 + private static final List SLOT_HOURS_EVENTS = new ArrayList<>(List.of( + 9, 13, 16, 19, 21 )); + public static final int SHOW_BEGINNING_TOAST_DELAY = 60; // en secondes + // * Données à propos de la gestion des daily event - private ScheduleDailyEvent outgoingEvent = null; - private BukkitTask nextEventTask; + public static ScheduleDailyEvent outgoingEvent = null; + public static BukkitTask nextEventTask; public static List incomingEvents = new ArrayList<>(); private static Dao dao; @@ -91,7 +94,7 @@ public static void saveIncomingEventsDB(IncomingEventsDB data) { * Lors du premier chargement, on remplit directement notre liste de taille identique à nos slots horaires. * @return la liste prévue des x prochains évenements */ - private List loadIncomingEvents() { + public static List loadIncomingEvents() { List scheduledEvents = new ArrayList<>(); LocalDateTime now = DateUtils.getLocalDateTime(); IncomingEventsDB data = loadIncomingEventsDB(); @@ -117,8 +120,7 @@ private List loadIncomingEvents() { return scheduledEvents; } - //todo: diviser ça en plusieurs sous méthodes - private BukkitTask scheduleNextEventTask() { + public static BukkitTask scheduleNextEventTask() { LocalDateTime now = DateUtils.getLocalDateTime(); // * On cherche la prochaine heure Integer nextHour = SLOT_HOURS_EVENTS.stream() @@ -137,40 +139,16 @@ private BukkitTask scheduleNextEventTask() { long delayTicks = DateUtils.getDelayBetweenNow(scheduleTime) * 20; - OMCLogger.info("Les prochains evenement : " + incomingEvents); - OMCLogger.info("Prochain Evenement journalier : " + scheduleTime + "s (dans " + DateUtils.convertTime(DateUtils.getDelayBetweenNow(scheduleTime)) + ")"); - - //todo: toast 1 min avant commencement - - return Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> { - if (incomingEvents.isEmpty()) { - incomingEvents = loadIncomingEvents(); - } - - outgoingEvent = incomingEvents.removeFirst(); - - // * Commencement de l'evenement - outgoingEvent.getDailyEvent().onStart().run(); - - //todo: setup ambient (interface EventAmbient) - - // * Programmation de la fin de l'evenement - Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> { - outgoingEvent.getDailyEvent().onEnd().run(); - outgoingEvent = null; - - //todo: remove ambient - //todo: end toast + OMCLogger.infoFormatted("Les prochains evenement : " + incomingEvents); + OMCLogger.infoFormatted("Prochain Evenement journalier : " + scheduleTime + "s (dans " + DateUtils.convertSecondToTime(DateUtils.getDelayBetweenNow(scheduleTime)) + ")"); - }, outgoingEvent.getDailyEvent().getDuration() * 20L * 20L); + new ShowBeginningEventToastTask() + .runTaskLater(OMCPlugin.getInstance(), delayTicks - SHOW_BEGINNING_TOAST_DELAY * 20L); - // * 10 secondes d'attente avant de schedule un autre event (evite que plusieurs events se lancent en meme temps) - Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> - nextEventTask = scheduleNextEventTask(), 20L * 10); - }, delayTicks); + return new ScheduleNextEventTask().runTaskLater(OMCPlugin.getInstance(), delayTicks); } - private List generateRandomOrder() { + private static List generateRandomOrder() { List copyEvents = new ArrayList<>(EVENTS); Collections.shuffle(copyEvents); return copyEvents; diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java index 925125c9c..2cfde1ab7 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java @@ -1,19 +1,27 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight; -import fr.openmc.core.features.events.contents.dailyevents.models.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; +import fr.openmc.core.utils.nms.toast.CustomToastData; import fr.openmc.core.utils.text.messages.TranslationManager; import net.kyori.adventure.text.Component; +import net.minecraft.advancements.AdvancementType; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import java.util.List; -public class BloodyNightEvent extends DailyEvent { +public class BloodyNightEvent extends DailyEvent implements HasToast { @Override public String getEventId() { return "bloody_night"; } + @Override + public String getWorldEvent() { + return "world"; + } + @Override public int getDuration() { return 20; @@ -47,4 +55,22 @@ public List getDescription() { public ItemStack getIcon() { return new ItemStack(Material.REDSTONE); } + + @Override + public CustomToastData getStartToastData() { + return new CustomToastData( + this.getIcon(), + "feature.dailyevents.toast.bloodynight.start", + AdvancementType.CHALLENGE + ); + } + + @Override + public CustomToastData getEndToastData() { + return new CustomToastData( + this.getIcon(), + "feature.dailyevents.toast.bloodynight.end", + AdvancementType.GOAL + ); + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java index 1995c9adc..9a2ed382e 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java @@ -1,19 +1,27 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.goldenharvest; -import fr.openmc.core.features.events.contents.dailyevents.models.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; +import fr.openmc.core.utils.nms.toast.CustomToastData; import fr.openmc.core.utils.text.messages.TranslationManager; import net.kyori.adventure.text.Component; +import net.minecraft.advancements.AdvancementType; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import java.util.List; -public class GoldenHarvestEvent extends DailyEvent { +public class GoldenHarvestEvent extends DailyEvent implements HasToast { @Override public String getEventId() { return "golden_harvest"; } + @Override + public String getWorldEvent() { + return "world"; + } + @Override public int getDuration() { return 40; @@ -47,4 +55,22 @@ public List getDescription() { public ItemStack getIcon() { return new ItemStack(Material.GOLDEN_HOE); } + + @Override + public CustomToastData getStartToastData() { + return new CustomToastData( + this.getIcon(), + "feature.dailyevents.toast.goldenharvest.start", + AdvancementType.CHALLENGE + ); + } + + @Override + public CustomToastData getEndToastData() { + return new CustomToastData( + this.getIcon(), + "feature.dailyevents.toast.goldenharvest.end", + AdvancementType.GOAL + ); + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java index c5495a08a..a832fb670 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java @@ -1,19 +1,27 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing; -import fr.openmc.core.features.events.contents.dailyevents.models.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; +import fr.openmc.core.utils.nms.toast.CustomToastData; import fr.openmc.core.utils.text.messages.TranslationManager; import net.kyori.adventure.text.Component; +import net.minecraft.advancements.AdvancementType; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import java.util.List; -public class MiraculousFishingEvent extends DailyEvent { +public class MiraculousFishingEvent extends DailyEvent implements HasToast { @Override public String getEventId() { return "miraculous_fishing"; } + @Override + public String getWorldEvent() { + return "world"; + } + @Override public int getDuration() { return 30; @@ -47,4 +55,22 @@ public List getDescription() { public ItemStack getIcon() { return new ItemStack(Material.FISHING_ROD); } + + @Override + public CustomToastData getStartToastData() { + return new CustomToastData( + this.getIcon(), + "feature.dailyevents.toast.miraculousfishing.start", + AdvancementType.CHALLENGE + ); + } + + @Override + public CustomToastData getEndToastData() { + return new CustomToastData( + this.getIcon(), + "feature.dailyevents.toast.miraculousfishing.end", + AdvancementType.GOAL + ); + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/DailyEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/DailyEvent.java deleted file mode 100644 index 92dd2e938..000000000 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/DailyEvent.java +++ /dev/null @@ -1,11 +0,0 @@ -package fr.openmc.core.features.events.contents.dailyevents.models; - -import fr.openmc.core.features.events.models.Event; - -public abstract class DailyEvent extends Event { - public abstract String getEventId(); - - public abstract int getDuration(); - public abstract Runnable onStart(); - public abstract Runnable onEnd(); -} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/IncomingEventsDB.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/IncomingEventsDB.java index d61f6e0a4..5126b1df1 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/IncomingEventsDB.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/IncomingEventsDB.java @@ -4,6 +4,7 @@ import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/ScheduleDailyEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/ScheduleDailyEvent.java index ea695d928..3ddc1434e 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/ScheduleDailyEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/ScheduleDailyEvent.java @@ -1,6 +1,7 @@ package fr.openmc.core.features.events.contents.dailyevents.models; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; import fr.openmc.core.features.events.models.Event; import lombok.Getter; import net.kyori.adventure.text.Component; diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/DailyEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/DailyEvent.java new file mode 100644 index 000000000..b4a11a19e --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/DailyEvent.java @@ -0,0 +1,34 @@ +package fr.openmc.core.features.events.contents.dailyevents.models.dailyevent; + +import fr.openmc.core.features.events.models.Event; + +public abstract class DailyEvent extends Event { + /** + * L'identifiant de l'evenement afin de le serialize dans la db + * @return un string + */ + public abstract String getEventId(); + + /** + * Le monde où l'evenement est actif + * @return un monde (minecraft:the_nether, minecraft:world, omc_dream:dream, ...) + */ + public abstract String getWorldEvent(); + + /** + * Le temps de durée de l'évenement + * @return un entier représentant les minutes + */ + public abstract int getDuration(); + + /** + * Les procédures à lancer au début de l'évenement + * @return une méthode + */ + public abstract Runnable onStart(); + /** + * Les procédures à lancer à la fin de l'évenement + * @return une méthode + */ + public abstract Runnable onEnd(); +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasToast.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasToast.java new file mode 100644 index 000000000..844a9d91d --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasToast.java @@ -0,0 +1,13 @@ +package fr.openmc.core.features.events.contents.dailyevents.models.dailyevent; + +import fr.openmc.core.utils.nms.toast.CustomToastData; +import org.bukkit.entity.Player; + +public interface HasToast { + CustomToastData getStartToastData(); + CustomToastData getEndToastData(); + + default void runStartToast(Player player) { + + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ScheduleNextEventTask.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ScheduleNextEventTask.java new file mode 100644 index 000000000..18b4946ae --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ScheduleNextEventTask.java @@ -0,0 +1,56 @@ +package fr.openmc.core.features.events.contents.dailyevents.tasks; + +import fr.openmc.core.OMCPlugin; +import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; +import org.bukkit.Bukkit; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.stream.Collectors; + +public class ScheduleNextEventTask extends BukkitRunnable { + @Override + public void run() { + if (DailyEventsManager.incomingEvents.isEmpty()) { + DailyEventsManager.incomingEvents = DailyEventsManager.loadIncomingEvents(); + } + + DailyEventsManager.outgoingEvent = DailyEventsManager.incomingEvents.removeFirst(); + + // * Commencement de l'evenement + DailyEventsManager.outgoingEvent.getDailyEvent().onStart().run(); + + //todo: setup ambient (interface EventAmbient) + + // * Toast de début + DailyEvent outgoingDailyEvent = DailyEventsManager.outgoingEvent.getDailyEvent(); + if (outgoingDailyEvent instanceof HasToast toast) { + toast.getStartToastData().send(Bukkit.getOnlinePlayers() + .stream() + .filter(p -> p.getWorld().getName().equals(outgoingDailyEvent.getWorldEvent())) + .collect(Collectors.toSet())); + } + + + // * Programmation de la fin de l'evenement + Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> { + DailyEventsManager.outgoingEvent.getDailyEvent().onEnd().run(); + DailyEventsManager.outgoingEvent = null; + + //todo: remove ambient + + if (outgoingDailyEvent instanceof HasToast toast) { + toast.getEndToastData().send(Bukkit.getOnlinePlayers() + .stream() + .filter(p -> p.getWorld().getName().equals(outgoingDailyEvent.getWorldEvent())) + .collect(Collectors.toSet())); + } + + }, DailyEventsManager.outgoingEvent.getDailyEvent().getDuration() * 20L * 20L); + + // * 10 secondes d'attente avant de schedule un autre event (evite que plusieurs events se lancent en meme temps) + Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> + DailyEventsManager.nextEventTask = DailyEventsManager.scheduleNextEventTask(), 20L * 10); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ShowBeginningEventToastTask.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ShowBeginningEventToastTask.java new file mode 100644 index 000000000..fcc6e26c0 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ShowBeginningEventToastTask.java @@ -0,0 +1,44 @@ +package fr.openmc.core.features.events.contents.dailyevents.tasks; + +import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; +import fr.openmc.core.features.events.contents.dailyevents.models.ScheduleDailyEvent; +import fr.openmc.core.utils.nms.toast.ToastUtils; +import fr.openmc.core.utils.world.WorldUtils; +import net.minecraft.advancements.AdvancementType; +import net.minecraft.network.chat.Component; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +public class ShowBeginningEventToastTask extends BukkitRunnable { + @Override + public void run() { + ScheduleDailyEvent nextEvent = DailyEventsManager.incomingEvents.getFirst(); + + for (Player onlinePlayer : Bukkit.getOnlinePlayers()) { + String translationKey; + Object[] translationsArgs; + if (nextEvent.getDailyEvent().getWorldEvent().contains(onlinePlayer.getWorld().getName())) { + translationKey = "feature.dailyevents.toast.beginning_event_in_world"; + translationsArgs = new Object[] { + DailyEventsManager.SHOW_BEGINNING_TOAST_DELAY + }; + } else { + translationKey = "feature.dailyevents.toast.beginning_event_out_world"; + translationsArgs = new Object[] { + Component.translatable(WorldUtils.getDisplayedWorldName(nextEvent.getDailyEvent().getWorldEvent())), + DailyEventsManager.SHOW_BEGINNING_TOAST_DELAY + }; + } + + ToastUtils.sendCustomToast( + onlinePlayer, + Material.NOTE_BLOCK, + translationKey, + translationsArgs, + AdvancementType.TASK + ); + } + } +} diff --git a/src/main/java/fr/openmc/core/utils/nms/toast/CustomToastData.java b/src/main/java/fr/openmc/core/utils/nms/toast/CustomToastData.java new file mode 100644 index 000000000..f43e46cfb --- /dev/null +++ b/src/main/java/fr/openmc/core/utils/nms/toast/CustomToastData.java @@ -0,0 +1,23 @@ +package fr.openmc.core.utils.nms.toast; + +import net.minecraft.advancements.AdvancementType; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.Collection; + +public record CustomToastData(ItemStack icon, String translationKey, Object[] translationsArgs, AdvancementType type) { + public CustomToastData(ItemStack icon, String translationKey, AdvancementType type) { + this(icon, translationKey, null, type); + } + + public void send(Player player) { + ToastUtils.sendCustomToast(player, this); + } + + public void send(Collection receivers) { + for (Player receiver : receivers) { + send(receiver); + } + } +} diff --git a/src/main/java/fr/openmc/core/utils/nms/ToastUtils.java b/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java similarity index 62% rename from src/main/java/fr/openmc/core/utils/nms/ToastUtils.java rename to src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java index 8b5723f4a..a194501b8 100644 --- a/src/main/java/fr/openmc/core/utils/nms/ToastUtils.java +++ b/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java @@ -1,4 +1,4 @@ -package fr.openmc.core.utils.nms; +package fr.openmc.core.utils.nms.toast; import net.minecraft.advancements.*; import net.minecraft.network.chat.Component; @@ -27,11 +27,38 @@ public class ToastUtils { * @param type le type du succes */ public static void sendCustomToast(Player player, org.bukkit.inventory.ItemStack item, String translationKey, AdvancementType type) { + sendCustomToast(player, item, translationKey, new Object[]{}, type); + } + + /** + * Affiche un Toast (= pop up lorsqu'on obtient un succes) Customisable + * @param player Le joueur ciblé + * @param material le material utilisé + * @param translationKey la clé de translation du texte + * @param type le type du succes + */ + public static void sendCustomToast(Player player, Material material, String translationKey, AdvancementType type) { + sendCustomToast(player, new org.bukkit.inventory.ItemStack(material), translationKey, type); + } + + /** + * Affiche un Toast (= pop up lorsqu'on obtient un succes) Customisable + * @param player Le joueur ciblé + * @param item l'item utilisé + * @param translationKey la clé de translation du texte + * @param type le type du succes + */ + public static void sendCustomToast( + Player player, + org.bukkit.inventory.ItemStack item, + String translationKey, + Object[] translationsArgs, + AdvancementType type) { Advancement adv = new Advancement( Optional.empty(), Optional.of(new DisplayInfo( ItemStackTemplate.fromNonEmptyStack(ItemStack.fromBukkitCopy(item)), - Component.translatable(translationKey), + Component.translatable(translationKey, translationsArgs), Component.empty(), Optional.empty(), type, @@ -76,7 +103,28 @@ public static void sendCustomToast(Player player, org.bukkit.inventory.ItemStack * @param translationKey la clé de translation du texte * @param type le type du succes */ - public static void sendCustomToast(Player player, Material material, String translationKey, AdvancementType type) { - sendCustomToast(player, new org.bukkit.inventory.ItemStack(material), translationKey, type); + public static void sendCustomToast( + Player player, + Material material, + String translationKey, + Object[] translationsArgs, + AdvancementType type) { + sendCustomToast(player, new org.bukkit.inventory.ItemStack(material), translationKey, translationsArgs, type); + } + + /** + * Affiche un Toast (= pop up lorsqu'on obtient un succes) Customisable + * @param player Le joueur ciblé + * @param toastData wrapper qui contient les données du taost + */ + public static void sendCustomToast( + Player player, + CustomToastData toastData) { + sendCustomToast(player, + toastData.icon(), + toastData.translationKey(), + toastData.translationsArgs(), + toastData.type() + ); } } diff --git a/src/main/java/fr/openmc/core/utils/world/WorldUtils.java b/src/main/java/fr/openmc/core/utils/world/WorldUtils.java index 75a92097e..f7ea7729d 100644 --- a/src/main/java/fr/openmc/core/utils/world/WorldUtils.java +++ b/src/main/java/fr/openmc/core/utils/world/WorldUtils.java @@ -1,11 +1,37 @@ package fr.openmc.core.utils.world; +import fr.openmc.core.features.dream.DreamDimensionManager; import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.entity.Player; public class WorldUtils { + /** + * Renvoie la translation key de l'affichage du nom d'un monde + * @param worldId l'id du monde + * @return la translation key lié au nom de la dimension + */ + public static String getDisplayedWorldName(String worldId) { + switch (worldId) { + case "world" -> { + return "utils.world.overworld"; + } + case "world_nether" -> { + return "utils.world.nether"; + } + case "world_the_end" -> { + return "utils.world.end"; + } + case DreamDimensionManager.DIMENSION_NAME -> { + return "utils.world.dream"; + } + default -> { + return worldId; + } + } + } + public static Yaw getYaw(Player p) { float yaw = p.getLocation().getYaw(); yaw = (yaw % 360 + 360) % 360; // true modulo, as javas modulo is unique for negative values diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties index 5033ab904..4d6e5bf52 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -5,12 +5,22 @@ feature.dailyevents.miraculousfishing.name=Pêche miraculeuseLa nuit reste d'être sanglante... \
Protégez-vous, battez-vous, vous allez subire différentes vagues \
et vous aurez surement un gros boss à battre à plusieurs - feature.dailyevents.goldenharvest.lore=Ça risque d'être sportif \
Attendez vous aux fermes qui tournerons au plein régime ! \
Bénéficiez de plusieures nouvelles ressources et de plusieures surprises - feature.dailyevents.miraculousfishing.lore=Vivez une grande session pêche ! \
Attention les Monstres des Mers vous attenderons avec impatience \
pour vous sautez dessus! \ -
Mais vous risquerez d'avoir plusieures bonnes surprises si vous êtes chanceux \ No newline at end of file +
Mais vous risquerez d'avoir plusieures bonnes surprises si vous êtes chanceux + +feature.dailyevents.toast.bloodynight.start=La Nuit Sanglante a débutée ! +feature.dailyevents.toast.bloodynight.end=Le calvaire de la Nuit Sanglante s'est arrêté + +feature.dailyevents.toast.goldenharvest.start=La Moisson dorée débarque dans vos granges ! +feature.dailyevents.toast.goldenharvest.end=La Moisson dorée s'est arrêtée ! + +feature.dailyevents.toast.miraculousfishing.start=La Pêche miraculeuse est ouverte ! +feature.dailyevents.toast.miraculousfishing.end=La Pêche miraculeuse est partie + +feature.dailyevents.toast.beginning_event_in_world=Un évenement va commencer dans votre monde dans %1$ss ! +feature.dailyevents.toast.beginning_event_out_world=Un évenement va commencer dans dans %1$ss ! \ No newline at end of file diff --git a/src/main/resources/translations/default/main.properties b/src/main/resources/translations/default/main.properties index c18968f81..a7de52a1d 100644 --- a/src/main/resources/translations/default/main.properties +++ b/src/main/resources/translations/default/main.properties @@ -2,6 +2,12 @@ # Native language: French # Do not use color codes in this file if there is an agument +# ** UTILS ** +utils.world.overworld=l'Overworld +utils.world.nether=le Nether +utils.world.end=l'End +utils.world.dream=les Rêves + # ** MESSAGES ** messages.global.cannot_do_this=Vous n'avez pas le droit de faire ceci. messages.global.missing_arg=Vous devez spécifier un argument. From 59a5951075b238b1623c0f9182c03dd77d9e3e1b Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 9 Jun 2026 18:34:08 +0200 Subject: [PATCH 11/74] feat: add interface HasAmbient + use of ambient (start, end) --- .../dailyevents/DailyEventsManager.java | 17 ++++++++- .../bloodynight/BloodyNightEvent.java | 10 ++++- .../goldenharvest/GoldenHarvestEvent.java | 10 ++++- .../MiraculousFishingEvent.java | 12 +++++- .../listeners/DailyEventAmbientListeners.java | 37 +++++++++++++++++++ .../models/dailyevent/HasAmbient.java | 16 ++++++++ .../models/dailyevent/HasToast.java | 5 --- .../tasks/ScheduleNextEventTask.java | 36 ++++++++++++------ .../core/registry/ambient/CustomAmbient.java | 21 +++++++++++ 9 files changed, 143 insertions(+), 21 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/listeners/DailyEventAmbientListeners.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasAmbient.java diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java index 8dbae7cb8..97d637235 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java @@ -8,17 +8,20 @@ import fr.openmc.core.bootstrap.features.Feature; import fr.openmc.core.bootstrap.features.annotations.Credit; import fr.openmc.core.bootstrap.features.types.DatabaseFeature; +import fr.openmc.core.bootstrap.features.types.HasListeners; import fr.openmc.core.bootstrap.features.types.LoadAfterItemsAdder; import fr.openmc.core.bootstrap.integration.OMCLogger; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.BloodyNightEvent; import fr.openmc.core.features.events.contents.dailyevents.contents.goldenharvest.GoldenHarvestEvent; import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.MiraculousFishingEvent; +import fr.openmc.core.features.events.contents.dailyevents.listeners.DailyEventAmbientListeners; import fr.openmc.core.features.events.contents.dailyevents.models.IncomingEventsDB; import fr.openmc.core.features.events.contents.dailyevents.models.ScheduleDailyEvent; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; import fr.openmc.core.features.events.contents.dailyevents.tasks.ScheduleNextEventTask; import fr.openmc.core.features.events.contents.dailyevents.tasks.ShowBeginningEventToastTask; import fr.openmc.core.utils.text.DateUtils; +import org.bukkit.event.Listener; import org.bukkit.scheduler.BukkitTask; import java.sql.SQLException; @@ -26,11 +29,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Set; //todo: ajouter des javadocs et commentaires sur certaines parties @Credit(developers = {"iambibi_"}) -public class DailyEventsManager extends Feature implements LoadAfterItemsAdder, DatabaseFeature { +public class DailyEventsManager extends Feature implements LoadAfterItemsAdder, DatabaseFeature, HasListeners { // * Constantes public static final List EVENTS = List.of( new MiraculousFishingEvent(), @@ -68,6 +72,13 @@ public void initDB(ConnectionSource connectionSource) throws SQLException { TableUtils.createTableIfNotExists(connectionSource, IncomingEventsDB.class); } + @Override + public Set getListeners() { + return Set.of( + new DailyEventAmbientListeners() + ); + } + public static IncomingEventsDB loadIncomingEventsDB() { try { IncomingEventsDB data = dao.queryForId(1); @@ -153,4 +164,8 @@ private static List generateRandomOrder() { Collections.shuffle(copyEvents); return copyEvents; } + + public static boolean isActiveDailyEvent() { + return outgoingEvent != null; + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java index 2cfde1ab7..ff9d2f925 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java @@ -1,7 +1,10 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight; +import fr.openmc.core.OMCRegistry; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasAmbient; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; +import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.utils.nms.toast.CustomToastData; import fr.openmc.core.utils.text.messages.TranslationManager; import net.kyori.adventure.text.Component; @@ -11,7 +14,7 @@ import java.util.List; -public class BloodyNightEvent extends DailyEvent implements HasToast { +public class BloodyNightEvent extends DailyEvent implements HasToast, HasAmbient { @Override public String getEventId() { return "bloody_night"; @@ -73,4 +76,9 @@ public CustomToastData getEndToastData() { AdvancementType.GOAL ); } + + @Override + public CustomAmbient getAmbient() { + return OMCRegistry.CUSTOM_AMBIENTS.DARK; // todo: make new custom ambients + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java index 9a2ed382e..cca825d47 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java @@ -1,7 +1,10 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.goldenharvest; +import fr.openmc.core.OMCRegistry; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasAmbient; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; +import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.utils.nms.toast.CustomToastData; import fr.openmc.core.utils.text.messages.TranslationManager; import net.kyori.adventure.text.Component; @@ -11,7 +14,7 @@ import java.util.List; -public class GoldenHarvestEvent extends DailyEvent implements HasToast { +public class GoldenHarvestEvent extends DailyEvent implements HasToast, HasAmbient { @Override public String getEventId() { return "golden_harvest"; @@ -73,4 +76,9 @@ public CustomToastData getEndToastData() { AdvancementType.GOAL ); } + + @Override + public CustomAmbient getAmbient() { + return OMCRegistry.CUSTOM_AMBIENTS.DARK; // todo: make new custom ambients + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java index a832fb670..5aa93618d 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java @@ -1,7 +1,10 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing; +import fr.openmc.core.OMCRegistry; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasAmbient; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; +import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.utils.nms.toast.CustomToastData; import fr.openmc.core.utils.text.messages.TranslationManager; import net.kyori.adventure.text.Component; @@ -11,7 +14,7 @@ import java.util.List; -public class MiraculousFishingEvent extends DailyEvent implements HasToast { +public class MiraculousFishingEvent extends DailyEvent implements HasToast, HasAmbient { @Override public String getEventId() { return "miraculous_fishing"; @@ -25,7 +28,7 @@ public String getWorldEvent() { @Override public int getDuration() { return 30; - } + } //todo: bug il a duré 10 min @Override public Runnable onStart() { @@ -73,4 +76,9 @@ public CustomToastData getEndToastData() { AdvancementType.GOAL ); } + + @Override + public CustomAmbient getAmbient() { + return OMCRegistry.CUSTOM_AMBIENTS.DARK; // todo: make new custom ambients + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/listeners/DailyEventAmbientListeners.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/listeners/DailyEventAmbientListeners.java new file mode 100644 index 000000000..8fc3af2cf --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/listeners/DailyEventAmbientListeners.java @@ -0,0 +1,37 @@ +package fr.openmc.core.features.events.contents.dailyevents.listeners; + +import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasAmbient; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerTeleportEvent; + +public class DailyEventAmbientListeners implements Listener { + + @EventHandler + public void onJoin(PlayerJoinEvent event) { + if (!DailyEventsManager.isActiveDailyEvent()) return; + + DailyEvent dailyEvent = DailyEventsManager.outgoingEvent.getDailyEvent(); + + if (!(dailyEvent instanceof HasAmbient hasAmbient)) return; + + hasAmbient.apply(event.getPlayer()); + } + + @EventHandler + public void onChangeWorld(PlayerTeleportEvent event) { + if (!DailyEventsManager.isActiveDailyEvent()) return; + + DailyEvent dailyEvent = DailyEventsManager.outgoingEvent.getDailyEvent(); + + if (!(dailyEvent instanceof HasAmbient hasAmbient)) return; + + if (dailyEvent.getWorldEvent().equals(event.getFrom().getWorld().getName())) return; + if (!dailyEvent.getWorldEvent().equals(event.getTo().getWorld().getName())) return; + + hasAmbient.apply(event.getPlayer()); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasAmbient.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasAmbient.java new file mode 100644 index 000000000..bd1b0fa88 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasAmbient.java @@ -0,0 +1,16 @@ +package fr.openmc.core.features.events.contents.dailyevents.models.dailyevent; + +import fr.openmc.core.registry.ambient.CustomAmbient; +import org.bukkit.entity.Player; + +public interface HasAmbient { + CustomAmbient getAmbient(); + + default void apply(Player player) { + this.getAmbient().apply(player); + } + + default void reset(Player player) { + this.getAmbient().reset(player); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasToast.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasToast.java index 844a9d91d..961cf4aab 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasToast.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasToast.java @@ -1,13 +1,8 @@ package fr.openmc.core.features.events.contents.dailyevents.models.dailyevent; import fr.openmc.core.utils.nms.toast.CustomToastData; -import org.bukkit.entity.Player; public interface HasToast { CustomToastData getStartToastData(); CustomToastData getEndToastData(); - - default void runStartToast(Player player) { - - } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ScheduleNextEventTask.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ScheduleNextEventTask.java index 18b4946ae..0abdac24b 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ScheduleNextEventTask.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ScheduleNextEventTask.java @@ -3,10 +3,13 @@ import fr.openmc.core.OMCPlugin; import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasAmbient; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; +import java.util.Collection; import java.util.stream.Collectors; public class ScheduleNextEventTask extends BukkitRunnable { @@ -21,30 +24,41 @@ public void run() { // * Commencement de l'evenement DailyEventsManager.outgoingEvent.getDailyEvent().onStart().run(); - //todo: setup ambient (interface EventAmbient) + DailyEvent outgoingDailyEvent = DailyEventsManager.outgoingEvent.getDailyEvent(); + Collection receivers = Bukkit.getOnlinePlayers() + .stream() + .filter(p -> p.getWorld().getName().equals(outgoingDailyEvent.getWorldEvent())) + .collect(Collectors.toSet()); + + // * Application de l'ambience + if (outgoingDailyEvent instanceof HasAmbient ambient) { + ambient.apply(receivers); + } // * Toast de début - DailyEvent outgoingDailyEvent = DailyEventsManager.outgoingEvent.getDailyEvent(); if (outgoingDailyEvent instanceof HasToast toast) { - toast.getStartToastData().send(Bukkit.getOnlinePlayers() - .stream() - .filter(p -> p.getWorld().getName().equals(outgoingDailyEvent.getWorldEvent())) - .collect(Collectors.toSet())); + toast.getStartToastData().send(receivers); } // * Programmation de la fin de l'evenement Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> { DailyEventsManager.outgoingEvent.getDailyEvent().onEnd().run(); + + Collection receivers2 = Bukkit.getOnlinePlayers() + .stream() + .filter(p -> p.getWorld().getName().equals(outgoingDailyEvent.getWorldEvent())) + .collect(Collectors.toSet()); + DailyEventsManager.outgoingEvent = null; - //todo: remove ambient + + if (outgoingDailyEvent instanceof HasAmbient ambient) { + ambient.reset(receivers2); + } if (outgoingDailyEvent instanceof HasToast toast) { - toast.getEndToastData().send(Bukkit.getOnlinePlayers() - .stream() - .filter(p -> p.getWorld().getName().equals(outgoingDailyEvent.getWorldEvent())) - .collect(Collectors.toSet())); + toast.getEndToastData().send(receivers2); } }, DailyEventsManager.outgoingEvent.getDailyEvent().getDuration() * 20L * 20L); diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java index 19e475510..8b05f4f53 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java @@ -16,6 +16,7 @@ import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.entity.Player; +import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -60,6 +61,16 @@ public void apply(Player player) { ACTIVE_AMBIENTS.put(player.getUniqueId(), this.getId()); } + /** + * Applique l'ambience sur des joueurs + * @param receivers Les joueurs concernés + */ + public void apply(Collection receivers) { + for (Player receiver : receivers) { + apply(receiver); + } + } + /** * Retire l'ambience du Joueur * @param player le joueur ciblé @@ -77,6 +88,16 @@ public void reset(Player player) { ACTIVE_AMBIENTS.remove(player.getUniqueId()); } + /** + * Retire l'ambience des joueurs + * @param receivers le joueur ciblé + */ + public void reset(Collection receivers) { + for (Player receiver : receivers) { + reset(receiver); + } + } + /** * Calcule la dimension de transition appropriée pour le joueur * Si le joueur est en OVERWORLD, on transitionne vers l'ambience From eb1e5b3bc6f31cfc321b2a4e77bebb2973dabe1e Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 9 Jun 2026 18:36:52 +0200 Subject: [PATCH 12/74] build: fix --- .../dailyevents/models/dailyevent/HasAmbient.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasAmbient.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasAmbient.java index bd1b0fa88..17548ba30 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasAmbient.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasAmbient.java @@ -3,6 +3,8 @@ import fr.openmc.core.registry.ambient.CustomAmbient; import org.bukkit.entity.Player; +import java.util.Collection; + public interface HasAmbient { CustomAmbient getAmbient(); @@ -10,7 +12,15 @@ default void apply(Player player) { this.getAmbient().apply(player); } + default void apply(Collection receivers) { + this.getAmbient().apply(receivers); + } + default void reset(Player player) { this.getAmbient().reset(player); } + + default void reset(Collection receivers) { + this.getAmbient().reset(receivers); + } } From 74d4dd996398292fda738464c0bd744832735abc Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 9 Jun 2026 18:39:35 +0200 Subject: [PATCH 13/74] fix: bug with duration --- .../contents/miraculousfishing/MiraculousFishingEvent.java | 2 +- .../contents/dailyevents/tasks/ScheduleNextEventTask.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java index 5aa93618d..73313c925 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java @@ -28,7 +28,7 @@ public String getWorldEvent() { @Override public int getDuration() { return 30; - } //todo: bug il a duré 10 min + } @Override public Runnable onStart() { diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ScheduleNextEventTask.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ScheduleNextEventTask.java index 0abdac24b..66ba370a6 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ScheduleNextEventTask.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ScheduleNextEventTask.java @@ -61,7 +61,7 @@ public void run() { toast.getEndToastData().send(receivers2); } - }, DailyEventsManager.outgoingEvent.getDailyEvent().getDuration() * 20L * 20L); + }, DailyEventsManager.outgoingEvent.getDailyEvent().getDuration() * 60L * 20L); // * 10 secondes d'attente avant de schedule un autre event (evite que plusieurs events se lancent en meme temps) Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> From 69a2f49a0cec879770fb36dac95764e4df660c0e Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 9 Jun 2026 19:58:11 +0200 Subject: [PATCH 14/74] branch; change --- .../core/commands/debug/ToastCommand.java | 3 +- .../dailyevents/DailyEventsManager.java | 3 +- .../bloodynight/BloodyNightEvent.java | 4 +- .../goldenharvest/GoldenHarvestEvent.java | 4 +- .../MiraculousFishingEvent.java | 4 +- .../tasks/ShowBeginningEventToastTask.java | 24 ++++---- .../ambient/contents/GoldenAmbient.java | 36 ++++++++++++ .../core/utils/nms/toast/CustomToastData.java | 7 ++- .../core/utils/nms/toast/ToastUtils.java | 56 ++++++------------- .../default/dailyevents.properties | 4 +- .../translations/default/main.properties | 2 + 11 files changed, 82 insertions(+), 65 deletions(-) create mode 100644 src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java diff --git a/src/main/java/fr/openmc/core/commands/debug/ToastCommand.java b/src/main/java/fr/openmc/core/commands/debug/ToastCommand.java index 11a225bf2..dec46e90a 100644 --- a/src/main/java/fr/openmc/core/commands/debug/ToastCommand.java +++ b/src/main/java/fr/openmc/core/commands/debug/ToastCommand.java @@ -1,6 +1,7 @@ package fr.openmc.core.commands.debug; import fr.openmc.core.utils.nms.toast.ToastUtils; +import net.kyori.adventure.text.Component; import net.minecraft.advancements.AdvancementType; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -14,6 +15,6 @@ public class ToastCommand { @Subcommand("test") @CommandPermission("omc.admins.commands.toast.test") public void test(Player player) { - ToastUtils.sendCustomToast(player, Material.TEST_INSTANCE_BLOCK, "translation.key.fuck", AdvancementType.CHALLENGE); + ToastUtils.sendCustomToast(player, Material.TEST_INSTANCE_BLOCK, Component.text("test debile"), AdvancementType.CHALLENGE); } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java index 97d637235..8cc09b1d2 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java @@ -150,7 +150,8 @@ public static BukkitTask scheduleNextEventTask() { long delayTicks = DateUtils.getDelayBetweenNow(scheduleTime) * 20; - OMCLogger.infoFormatted("Les prochains evenement : " + incomingEvents); + OMCLogger.infoFormatted("Les prochains evenement : " + incomingEvents.stream() + .map(s->s.getDailyEvent().getClass().getSimpleName()).toList()); OMCLogger.infoFormatted("Prochain Evenement journalier : " + scheduleTime + "s (dans " + DateUtils.convertSecondToTime(DateUtils.getDelayBetweenNow(scheduleTime)) + ")"); new ShowBeginningEventToastTask() diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java index ff9d2f925..9242788b9 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java @@ -63,7 +63,7 @@ public ItemStack getIcon() { public CustomToastData getStartToastData() { return new CustomToastData( this.getIcon(), - "feature.dailyevents.toast.bloodynight.start", + TranslationManager.translation("feature.dailyevents.toast.bloodynight.start"), AdvancementType.CHALLENGE ); } @@ -72,7 +72,7 @@ public CustomToastData getStartToastData() { public CustomToastData getEndToastData() { return new CustomToastData( this.getIcon(), - "feature.dailyevents.toast.bloodynight.end", + TranslationManager.translation("feature.dailyevents.toast.bloodynight.end"), AdvancementType.GOAL ); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java index cca825d47..5fce8c1aa 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java @@ -63,7 +63,7 @@ public ItemStack getIcon() { public CustomToastData getStartToastData() { return new CustomToastData( this.getIcon(), - "feature.dailyevents.toast.goldenharvest.start", + TranslationManager.translation("feature.dailyevents.toast.goldenharvest.start"), AdvancementType.CHALLENGE ); } @@ -72,7 +72,7 @@ public CustomToastData getStartToastData() { public CustomToastData getEndToastData() { return new CustomToastData( this.getIcon(), - "feature.dailyevents.toast.goldenharvest.end", + TranslationManager.translation("feature.dailyevents.toast.goldenharvest.end"), AdvancementType.GOAL ); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java index 73313c925..e1008ea14 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java @@ -63,7 +63,7 @@ public ItemStack getIcon() { public CustomToastData getStartToastData() { return new CustomToastData( this.getIcon(), - "feature.dailyevents.toast.miraculousfishing.start", + TranslationManager.translation("feature.dailyevents.toast.miraculousfishing.start"), AdvancementType.CHALLENGE ); } @@ -72,7 +72,7 @@ public CustomToastData getStartToastData() { public CustomToastData getEndToastData() { return new CustomToastData( this.getIcon(), - "feature.dailyevents.toast.miraculousfishing.end", + TranslationManager.translation("feature.dailyevents.toast.miraculousfishing.end"), AdvancementType.GOAL ); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ShowBeginningEventToastTask.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ShowBeginningEventToastTask.java index fcc6e26c0..b43c9c65f 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ShowBeginningEventToastTask.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ShowBeginningEventToastTask.java @@ -3,9 +3,11 @@ import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; import fr.openmc.core.features.events.contents.dailyevents.models.ScheduleDailyEvent; import fr.openmc.core.utils.nms.toast.ToastUtils; +import fr.openmc.core.utils.text.messages.TranslationManager; import fr.openmc.core.utils.world.WorldUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import net.minecraft.advancements.AdvancementType; -import net.minecraft.network.chat.Component; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -17,26 +19,20 @@ public void run() { ScheduleDailyEvent nextEvent = DailyEventsManager.incomingEvents.getFirst(); for (Player onlinePlayer : Bukkit.getOnlinePlayers()) { - String translationKey; - Object[] translationsArgs; + Component name; if (nextEvent.getDailyEvent().getWorldEvent().contains(onlinePlayer.getWorld().getName())) { - translationKey = "feature.dailyevents.toast.beginning_event_in_world"; - translationsArgs = new Object[] { - DailyEventsManager.SHOW_BEGINNING_TOAST_DELAY - }; + name = TranslationManager.translation("feature.dailyevents.toast.beginning_event_in_world", + Component.text(DailyEventsManager.SHOW_BEGINNING_TOAST_DELAY, NamedTextColor.YELLOW)); } else { - translationKey = "feature.dailyevents.toast.beginning_event_out_world"; - translationsArgs = new Object[] { - Component.translatable(WorldUtils.getDisplayedWorldName(nextEvent.getDailyEvent().getWorldEvent())), - DailyEventsManager.SHOW_BEGINNING_TOAST_DELAY - }; + name = TranslationManager.translation("feature.dailyevents.toast.beginning_event_out_world", + TranslationManager.translation(WorldUtils.getDisplayedWorldName(nextEvent.getDailyEvent().getWorldEvent())), + Component.text(DailyEventsManager.SHOW_BEGINNING_TOAST_DELAY, NamedTextColor.YELLOW)); } ToastUtils.sendCustomToast( onlinePlayer, Material.NOTE_BLOCK, - translationKey, - translationsArgs, + name, AdvancementType.TASK ); } diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java new file mode 100644 index 000000000..01455fb5a --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java @@ -0,0 +1,36 @@ +package fr.openmc.core.registry.ambient.contents; + +import fr.openmc.api.datapacks.injectors.DimensionTypesInjector; +import fr.openmc.core.registry.ambient.CustomAmbient; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.dimension.DimensionType; + +public class GoldenAmbient extends CustomAmbient { + @Override + public String getId() { + return "golden_ambient"; + } + + @Override + public DimensionTypesInjector.DimensionTypeBuilder getDimensionTypeBuilder() { + return new DimensionTypesInjector.DimensionTypeBuilder() + .attributes(obj -> { + obj.addProperty("visual/ambient_light_color", "#DD37E6"); + obj.addProperty("visual/sky_color", "#DD37E6"); + obj.addProperty("visual/sky_light_color", "#3B205E"); + obj.addProperty("visual/fog_start_distance", 40); + obj.addProperty("visual/fog_end_distance", 70); + obj.addProperty("visual/sunrise_sunset_color", "#FFBB00FA"); + }) + .defaultClock(null) + .timelines(null) + .skybox(DimensionType.Skybox.OVERWORLD) + .hasSkylight(true); + } + + @Override + public ResourceKey getTransitionDimension() { + return Level.END; + } +} diff --git a/src/main/java/fr/openmc/core/utils/nms/toast/CustomToastData.java b/src/main/java/fr/openmc/core/utils/nms/toast/CustomToastData.java index f43e46cfb..3ce50d88f 100644 --- a/src/main/java/fr/openmc/core/utils/nms/toast/CustomToastData.java +++ b/src/main/java/fr/openmc/core/utils/nms/toast/CustomToastData.java @@ -1,14 +1,15 @@ package fr.openmc.core.utils.nms.toast; +import net.kyori.adventure.text.Component; import net.minecraft.advancements.AdvancementType; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import java.util.Collection; -public record CustomToastData(ItemStack icon, String translationKey, Object[] translationsArgs, AdvancementType type) { - public CustomToastData(ItemStack icon, String translationKey, AdvancementType type) { - this(icon, translationKey, null, type); +public record CustomToastData(ItemStack icon, Component name, Component description, AdvancementType type) { + public CustomToastData(ItemStack icon, Component name, AdvancementType type) { + this(icon, name, Component.empty(), type); } public void send(Player player) { diff --git a/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java b/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java index a194501b8..920fc24b1 100644 --- a/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java +++ b/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java @@ -1,7 +1,8 @@ package fr.openmc.core.utils.nms.toast; +import io.papermc.paper.adventure.PaperAdventure; +import net.kyori.adventure.text.Component; import net.minecraft.advancements.*; -import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundUpdateAdvancementsPacket; import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerPlayer; @@ -19,47 +20,41 @@ public class ToastUtils { private static final Identifier TOAST_IDENTIFIER = Identifier.parse("omc:custom_toast"); private static final AdvancementRequirements ADV_REQUIREMENTS = AdvancementRequirements.allOf(Set.of("c")); - /** - * Affiche un Toast (= pop up lorsqu'on obtient un succes) Customisable - * @param player Le joueur ciblé - * @param item l'item utilisé - * @param translationKey la clé de translation du texte - * @param type le type du succes - */ - public static void sendCustomToast(Player player, org.bukkit.inventory.ItemStack item, String translationKey, AdvancementType type) { - sendCustomToast(player, item, translationKey, new Object[]{}, type); - } - /** * Affiche un Toast (= pop up lorsqu'on obtient un succes) Customisable * @param player Le joueur ciblé * @param material le material utilisé - * @param translationKey la clé de translation du texte + * @param name le component du nom * @param type le type du succes */ - public static void sendCustomToast(Player player, Material material, String translationKey, AdvancementType type) { - sendCustomToast(player, new org.bukkit.inventory.ItemStack(material), translationKey, type); + public static void sendCustomToast( + Player player, + Material material, + Component name, + AdvancementType type) { + sendCustomToast(player, new org.bukkit.inventory.ItemStack(material), name, Component.empty(), type); } /** * Affiche un Toast (= pop up lorsqu'on obtient un succes) Customisable * @param player Le joueur ciblé * @param item l'item utilisé - * @param translationKey la clé de translation du texte + * @param name le Component du nom + * @param description le Component de la description * @param type le type du succes */ public static void sendCustomToast( Player player, org.bukkit.inventory.ItemStack item, - String translationKey, - Object[] translationsArgs, + Component name, + Component description, AdvancementType type) { Advancement adv = new Advancement( Optional.empty(), Optional.of(new DisplayInfo( ItemStackTemplate.fromNonEmptyStack(ItemStack.fromBukkitCopy(item)), - Component.translatable(translationKey, translationsArgs), - Component.empty(), + PaperAdventure.asVanilla(name), + PaperAdventure.asVanilla(description), Optional.empty(), type, true, @@ -78,6 +73,7 @@ public static void sendCustomToast( progress.update(ADV_REQUIREMENTS); progress.grantProgress("c"); + System.out.println(progress.toString()); ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); nmsPlayer.connection.send(new ClientboundUpdateAdvancementsPacket( false, @@ -96,22 +92,6 @@ public static void sendCustomToast( )); } - /** - * Affiche un Toast (= pop up lorsqu'on obtient un succes) Customisable - * @param player Le joueur ciblé - * @param material le material utilisé - * @param translationKey la clé de translation du texte - * @param type le type du succes - */ - public static void sendCustomToast( - Player player, - Material material, - String translationKey, - Object[] translationsArgs, - AdvancementType type) { - sendCustomToast(player, new org.bukkit.inventory.ItemStack(material), translationKey, translationsArgs, type); - } - /** * Affiche un Toast (= pop up lorsqu'on obtient un succes) Customisable * @param player Le joueur ciblé @@ -122,8 +102,8 @@ public static void sendCustomToast( CustomToastData toastData) { sendCustomToast(player, toastData.icon(), - toastData.translationKey(), - toastData.translationsArgs(), + toastData.name(), + toastData.description(), toastData.type() ); } diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties index 4d6e5bf52..9c6409d49 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -22,5 +22,5 @@ feature.dailyevents.toast.goldenharvest.end=La Moisson feature.dailyevents.toast.miraculousfishing.start=La Pêche miraculeuse est ouverte ! feature.dailyevents.toast.miraculousfishing.end=La Pêche miraculeuse est partie -feature.dailyevents.toast.beginning_event_in_world=Un évenement va commencer dans votre monde dans %1$ss ! -feature.dailyevents.toast.beginning_event_out_world=Un évenement va commencer dans dans %1$ss ! \ No newline at end of file +feature.dailyevents.toast.beginning_event_in_world=Un évenement va commencer dans votre monde dans %1$ss ! +feature.dailyevents.toast.beginning_event_out_world=Un évenement va commencer dans dans %1$ss ! \ No newline at end of file diff --git a/src/main/resources/translations/default/main.properties b/src/main/resources/translations/default/main.properties index a7de52a1d..9d00a7b30 100644 --- a/src/main/resources/translations/default/main.properties +++ b/src/main/resources/translations/default/main.properties @@ -1,6 +1,8 @@ # Language file for the plugin # Native language: French # Do not use color codes in this file if there is an agument +# * KEY DE TEST +test=TESTTTT # ** UTILS ** utils.world.overworld=l'Overworld From 4ca54ad5faaefa92250bd160d927eba1d701b118 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 10 Jun 2026 12:21:57 +0200 Subject: [PATCH 15/74] toast cant show (idem for basic advencement) --- src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java b/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java index 920fc24b1..5258b891d 100644 --- a/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java +++ b/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java @@ -73,7 +73,6 @@ public static void sendCustomToast( progress.update(ADV_REQUIREMENTS); progress.grantProgress("c"); - System.out.println(progress.toString()); ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); nmsPlayer.connection.send(new ClientboundUpdateAdvancementsPacket( false, From 020cd2e8762555187870fc0265d9107bf1c76ec5 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 10 Jun 2026 12:26:24 +0200 Subject: [PATCH 16/74] toast todo --- src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java b/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java index 5258b891d..ec17f8f04 100644 --- a/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java +++ b/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java @@ -16,6 +16,8 @@ import java.util.Optional; import java.util.Set; + +// todo: test if toast show with items adder not bugged public class ToastUtils { private static final Identifier TOAST_IDENTIFIER = Identifier.parse("omc:custom_toast"); private static final AdvancementRequirements ADV_REQUIREMENTS = AdvancementRequirements.allOf(Set.of("c")); From b43c3b328890aa21e08ec10e44211235068f71d3 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 11 Jun 2026 10:46:51 +0200 Subject: [PATCH 17/74] update todo --- .../events/contents/dailyevents/DailyEventsManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java index 8cc09b1d2..6eee0067c 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java @@ -33,6 +33,8 @@ //todo: ajouter des javadocs et commentaires sur certaines parties +//todo: tester les toasts lorsqu'ils refonctionneront (before, start, end) +//todo: faire des broadcast like Contest et Mayor, broadcast customisable? (before, start, end) @Credit(developers = {"iambibi_"}) public class DailyEventsManager extends Feature implements LoadAfterItemsAdder, DatabaseFeature, HasListeners { // * Constantes From aafc7305f7594411c0d00b4bcfb15010502c88ac Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 11 Jun 2026 10:53:35 +0200 Subject: [PATCH 18/74] update todo --- src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java b/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java index ec17f8f04..5258b891d 100644 --- a/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java +++ b/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java @@ -16,8 +16,6 @@ import java.util.Optional; import java.util.Set; - -// todo: test if toast show with items adder not bugged public class ToastUtils { private static final Identifier TOAST_IDENTIFIER = Identifier.parse("omc:custom_toast"); private static final AdvancementRequirements ADV_REQUIREMENTS = AdvancementRequirements.allOf(Set.of("c")); From 013135aa081d48c9474a0caf8ebad12b0037885a Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 11 Jun 2026 11:01:08 +0200 Subject: [PATCH 19/74] fix: part (1/2) Environnement Attributes overriden by something. : timelines? no it's biome --- .../fr/openmc/api/datapacks/OMCDatapack.java | 22 +- .../injectors/DimensionTypesInjector.java | 67 +++++- .../datapacks/injectors/TimelineInjector.java | 202 ++++++++++++++++++ .../core/registry/ambient/CustomAmbient.java | 2 + .../ambient/CustomAmbientRegistry.java | 8 +- .../registry/ambient/TimelineAmbient.java | 11 + .../ambient/contents/DarkAmbient.java | 2 +- .../ambient/contents/GoldenAmbient.java | 34 +-- 8 files changed, 324 insertions(+), 24 deletions(-) create mode 100644 src/main/java/fr/openmc/api/datapacks/injectors/TimelineInjector.java create mode 100644 src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java diff --git a/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java b/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java index 2352a1b9b..b617676c8 100644 --- a/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java +++ b/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java @@ -1,6 +1,7 @@ package fr.openmc.api.datapacks; import fr.openmc.api.datapacks.injectors.PackMetadataInjector; +import fr.openmc.core.utils.FilesUtils; import io.papermc.paper.plugin.bootstrap.BootstrapContext; import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; import lombok.Getter; @@ -24,19 +25,30 @@ public OMCDatapack(String packName, String namespace) { this.namespace = namespace; } - public void build(BootstrapContext context) throws IOException { - Path tempDir = Files.createTempDirectory("datapacks-openmc"); + public void build(BootstrapContext context, boolean generateFiles) throws IOException { + String idDatapacks = "datapacks-openmc"; + Path dir; - runInjector(tempDir, new PackMetadataInjector()); + if (generateFiles) { + dir = context.getDataDirectory().resolve(idDatapacks); + + FilesUtils.deleteDirectory(dir.toFile()); + Files.createDirectories(dir); + } else { + dir = Files.createTempDirectory(idDatapacks); + } + + runInjector(dir, new PackMetadataInjector()); for (DatapackInjector injector : injectors) { - runInjector(tempDir, injector); + System.out.println(injector.getClass().getSimpleName()); + runInjector(dir, injector); } context.getLifecycleManager().registerEventHandler(LifecycleEvents.DATAPACK_DISCOVERY.newHandler( event -> { try { - URI uri = tempDir.toUri(); + URI uri = dir.toUri(); event.registrar().discoverPack(uri, "openmc-injected"); } catch (IOException e) { diff --git a/src/main/java/fr/openmc/api/datapacks/injectors/DimensionTypesInjector.java b/src/main/java/fr/openmc/api/datapacks/injectors/DimensionTypesInjector.java index 39a768ae5..b07331b8f 100644 --- a/src/main/java/fr/openmc/api/datapacks/injectors/DimensionTypesInjector.java +++ b/src/main/java/fr/openmc/api/datapacks/injectors/DimensionTypesInjector.java @@ -105,12 +105,19 @@ public static final class DimensionTypeBuilder { public DimensionTypeBuilder attributes(Consumer builder) { JsonObject obj = new JsonObject(); builder.accept(obj); - this.attributes = obj; + + this.attributes = new JsonObject(); + for (var entry : obj.entrySet()) { + this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); + } return this; } public DimensionTypeBuilder attributes(JsonObject attributes) { - this.attributes = attributes; + this.attributes = new JsonObject(); + for (var entry : attributes.entrySet()) { + this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); + } return this; } @@ -127,12 +134,50 @@ public DimensionTypeBuilder ambientParticles(String particleType, double probabi entry.add("particle", particle); entry.addProperty("probability", probability); - if (this.attributes.has("minecraft:visual/ambient_particles") && this.attributes.get("minecraft:visual/ambient_particles").isJsonArray()) { - this.attributes.getAsJsonArray("minecraft:visual/ambient_particles").add(entry); + String key = "minecraft:visual/ambient_particles"; + if (this.attributes.has(key)) { + this.attributes.getAsJsonObject(key) + .getAsJsonArray("argument") + .add(entry); + } else { + JsonArray arr = new JsonArray(); + arr.add(entry); + this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); + } + return this; + } + + /** + * { + * "particle": { + * "type": "minecraft:dust_color_transition", + * "from_color": 16776172, + * "to_color": 16766720, + * "scale": 1 + * }, + * "probability": 0.1 + * } + */ + public DimensionTypeBuilder particleDustColorTransition(int fromColor, int toColor, float scale, double probability) { + if (this.attributes == null) this.attributes = new JsonObject(); + JsonObject entry = new JsonObject(); + JsonObject particle = new JsonObject(); + particle.addProperty("type", "minecraft:dust_color_transition"); + particle.addProperty("from_color", fromColor); + particle.addProperty("to_color", toColor); + particle.addProperty("scale", scale); + entry.add("particle", particle); + entry.addProperty("probability", probability); + + String key = "minecraft:visual/ambient_particles"; + if (this.attributes.has(key)) { + this.attributes.getAsJsonObject(key) + .getAsJsonArray("argument") + .add(entry); } else { JsonArray arr = new JsonArray(); arr.add(entry); - this.attributes.add("minecraft:visual/ambient_particles", arr); + this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); } return this; } @@ -244,6 +289,11 @@ public DimensionTypeBuilder timelines(String timelines) { return this; } + public DimensionTypeBuilder timelines(TimelineInjector injector) { + this.timelines = injector.getNamespace() + ":" + injector.getId(); + return this; + } + private JsonObject toJson() { JsonObject json = new JsonObject(); if (attributes != null) json.add("attributes", attributes); @@ -265,5 +315,12 @@ private JsonObject toJson() { if (timelines != null) json.addProperty("timelines", timelines); return json; } + + private JsonObject toOverridenEnvironnementAttribute(JsonElement value) { + JsonObject obj = new JsonObject(); + obj.addProperty("modifier", "override"); + obj.add("argument", value); + return obj; + } } } diff --git a/src/main/java/fr/openmc/api/datapacks/injectors/TimelineInjector.java b/src/main/java/fr/openmc/api/datapacks/injectors/TimelineInjector.java new file mode 100644 index 000000000..4a5cebb7f --- /dev/null +++ b/src/main/java/fr/openmc/api/datapacks/injectors/TimelineInjector.java @@ -0,0 +1,202 @@ +package fr.openmc.api.datapacks.injectors; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import fr.openmc.api.datapacks.DatapackInjector; +import lombok.Getter; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +@Getter +/** + * Classe qui représente les données trouvable dans une timeline + * Qui injecte directement cela sous forme .json dans le datapack + * https://minecraft.wiki/w/Timeline + */ +public class TimelineInjector implements DatapackInjector { + + private final String namespace; + private String id; + private final Map entries = new LinkedHashMap<>(); + + public TimelineInjector(String namespace) { + this.namespace = namespace; + } + + public TimelineInjector add(String id, Consumer builder) { + TimelineBuilder instance = new TimelineBuilder(); + builder.accept(instance); + entries.put(id, instance); + this.id = id; + return this; + } + + public TimelineInjector add(String id, TimelineBuilder builder) { + entries.put(id, builder); + this.id = id; + return this; + } + + @Override + public void inject(File rootFile) { + if (entries.isEmpty()) return; + + Path root = rootFile.toPath().resolve("data").resolve(namespace).resolve("timeline"); + try { + Files.createDirectories(root); + for (var entry : entries.entrySet()) { + Path file = root.resolve(entry.getKey() + ".json"); + Files.writeString(file, GSON.toJson(entry.getValue().toJson())); + } + } catch (IOException e) { + throw new IllegalStateException("Cannot write timeline files", e); + } + } + + public static final class TimelineBuilder { + private String clock = "minecraft:overworld"; + private Integer periodTicks = null; + private final Map tracks = new LinkedHashMap<>(); + private final Map timeMarkers = new LinkedHashMap<>(); + + public TimelineBuilder clock(String clock) { + this.clock = clock; + return this; + } + + public TimelineBuilder periodTicks(int periodTicks) { + this.periodTicks = periodTicks; + return this; + } + + public TimelineBuilder track(String attributeId, Consumer builder) { + TrackBuilder track = new TrackBuilder(); + builder.accept(track); + tracks.put(attributeId, track); + return this; + } + + public TimelineBuilder timeMarker(String id, int ticks) { + timeMarkers.put(id, ticks); + return this; + } + + public TimelineBuilder timeMarker(String id, int ticks, boolean showInCommands) { + JsonObject marker = new JsonObject(); + marker.addProperty("ticks", ticks); + marker.addProperty("show_in_commands", showInCommands); + timeMarkers.put(id, marker); + return this; + } + + private JsonObject toJson() { + JsonObject json = new JsonObject(); + json.addProperty("clock", clock); + if (periodTicks != null) json.addProperty("period_ticks", periodTicks); + + if (!tracks.isEmpty()) { + JsonObject tracksJson = new JsonObject(); + for (var entry : tracks.entrySet()) { + tracksJson.add(entry.getKey(), entry.getValue().toJson()); + } + json.add("tracks", tracksJson); + } + + if (!timeMarkers.isEmpty()) { + JsonObject markersJson = new JsonObject(); + for (var entry : timeMarkers.entrySet()) { + if (entry.getValue() instanceof Integer i) { + markersJson.addProperty(entry.getKey(), i); + } else if (entry.getValue() instanceof JsonObject obj) { + markersJson.add(entry.getKey(), obj); + } + } + json.add("time_markers", markersJson); + } + + return json; + } + } + + public static final class TrackBuilder { + private String ease = null; + private JsonElement easeObject = null; + private String modifier = null; + private final List keyframes = new ArrayList<>(); + + public TrackBuilder ease(String ease) { + this.ease = ease; + return this; + } + + public TrackBuilder easeCubicBezier(double x1, double y1, double x2, double y2) { + JsonObject obj = new JsonObject(); + JsonArray bezier = new JsonArray(); + bezier.add(x1); bezier.add(y1); bezier.add(x2); bezier.add(y2); + obj.add("cubic_bezier", bezier); + this.easeObject = obj; + return this; + } + + public TrackBuilder modifier(String modifier) { + this.modifier = modifier; + return this; + } + + public TrackBuilder keyframe(int ticks, String value) { + keyframes.add(new KeyframeBuilder(ticks, new JsonPrimitive(value))); + return this; + } + + public TrackBuilder keyframe(int ticks, double value) { + keyframes.add(new KeyframeBuilder(ticks, new JsonPrimitive(value))); + return this; + } + + public TrackBuilder keyframe(int ticks, boolean value) { + keyframes.add(new KeyframeBuilder(ticks, new JsonPrimitive(value))); + return this; + } + + public TrackBuilder keyframe(int ticks, JsonElement value) { + keyframes.add(new KeyframeBuilder(ticks, value)); + return this; + } + + private JsonObject toJson() { + JsonObject json = new JsonObject(); + if (easeObject != null) { + json.add("ease", easeObject); + } else if (ease != null) { + json.addProperty("ease", ease); + } + if (modifier != null) json.addProperty("modifier", modifier); + + JsonArray kfArray = new JsonArray(); + for (KeyframeBuilder kf : keyframes) { + kfArray.add(kf.toJson()); + } + json.add("keyframes", kfArray); + return json; + } + } + + private record KeyframeBuilder(int ticks, JsonElement value) { + private JsonObject toJson() { + JsonObject json = new JsonObject(); + json.addProperty("ticks", ticks); + json.add("value", value); + return json; + } + } +} diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java index 8b05f4f53..255cc47cd 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java @@ -58,6 +58,8 @@ public void apply(Player player) { getTransitionDimensionForPlayer(nmsPlayer) ); + //todo faudrait envoyer un biome + ACTIVE_AMBIENTS.put(player.getUniqueId(), this.getId()); } diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java index bdf5dfafc..9e6c4287d 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java @@ -4,6 +4,7 @@ import fr.openmc.core.bootstrap.registries.KeyedRegistry; import fr.openmc.core.bootstrap.registries.Registry; import fr.openmc.core.registry.ambient.contents.DarkAmbient; +import fr.openmc.core.registry.ambient.contents.GoldenAmbient; import fr.openmc.core.registry.ambient.contents.HellAmbient; import io.papermc.paper.plugin.bootstrap.BootstrapContext; @@ -16,6 +17,7 @@ public class CustomAmbientRegistry extends Registry imple // ** REGISTER AMBIENT ** public final CustomAmbient DARK = register(new DarkAmbient()); public final CustomAmbient HELL = register(new HellAmbient()); + public final CustomAmbient GOLDEN = register(new GoldenAmbient()); @Override public String key(CustomAmbient registryObject) { @@ -26,8 +28,12 @@ public String key(CustomAmbient registryObject) { public void bootstrap(BootstrapContext context) throws IOException { for (CustomAmbient ambient : values()) { ambientDatapack.addInjector(ambient.toDimensionTypeInjector()); + if (ambient instanceof TimelineAmbient timelineAmbient) { + ambientDatapack.addInjector(timelineAmbient.toTimelineInjector( + ambientDatapack.getNamespace(), ambient.getId())); + } } - ambientDatapack.build(context); + ambientDatapack.build(context, true); //todo: remettre ça en false } } diff --git a/src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java new file mode 100644 index 000000000..e158da79a --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java @@ -0,0 +1,11 @@ +package fr.openmc.core.registry.ambient; + +import fr.openmc.api.datapacks.injectors.TimelineInjector; + +public interface TimelineAmbient { + TimelineInjector.TimelineBuilder getTimelineBuilder(); + + default TimelineInjector toTimelineInjector(String namespace, String id) { + return new TimelineInjector(namespace).add(id, getTimelineBuilder()); + } +} diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java index 4e84828fe..08264cc93 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java @@ -24,7 +24,7 @@ public DimensionTypesInjector.DimensionTypeBuilder getDimensionTypeBuilder() { obj.addProperty("visual/sunrise_sunset_color", "#FFBB00FA"); }) .defaultClock(null) - .timelines(null) + .timelines((String) null) .skybox(DimensionType.Skybox.END) .hasSkylight(true); } diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java index 01455fb5a..5780d9fb8 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java @@ -1,12 +1,13 @@ package fr.openmc.core.registry.ambient.contents; import fr.openmc.api.datapacks.injectors.DimensionTypesInjector; +import fr.openmc.api.datapacks.injectors.TimelineInjector; import fr.openmc.core.registry.ambient.CustomAmbient; +import fr.openmc.core.registry.ambient.TimelineAmbient; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; -import net.minecraft.world.level.dimension.DimensionType; -public class GoldenAmbient extends CustomAmbient { +public class GoldenAmbient extends CustomAmbient implements TimelineAmbient { @Override public String getId() { return "golden_ambient"; @@ -16,17 +17,26 @@ public String getId() { public DimensionTypesInjector.DimensionTypeBuilder getDimensionTypeBuilder() { return new DimensionTypesInjector.DimensionTypeBuilder() .attributes(obj -> { - obj.addProperty("visual/ambient_light_color", "#DD37E6"); - obj.addProperty("visual/sky_color", "#DD37E6"); - obj.addProperty("visual/sky_light_color", "#3B205E"); - obj.addProperty("visual/fog_start_distance", 40); - obj.addProperty("visual/fog_end_distance", 70); - obj.addProperty("visual/sunrise_sunset_color", "#FFBB00FA"); + obj.addProperty("visual/ambient_light_color", "#FFE75C"); + obj.addProperty("visual/sky_color", "#FFD700"); + obj.addProperty("visual/sky_light_color", "#FFE02E"); + obj.addProperty("visual/fog_color", "#6D6319"); + obj.addProperty("visual/fog_start_distance", 55); + obj.addProperty("visual/fog_end_distance", 65); + obj.addProperty("visual/sunrise_sunset_color", "#ccff5900"); + obj.addProperty("visual/cloud_height", 100); + obj.addProperty("visual/cloud_color", "#4cffde50"); }) - .defaultClock(null) - .timelines(null) - .skybox(DimensionType.Skybox.OVERWORLD) - .hasSkylight(true); + .hasSkylight(true) + .timelines(toTimelineInjector("omc_ambient", getId())) + .particleDustColorTransition(16776172, 16766720, 2, 0.01); + } + + @Override + public TimelineInjector.TimelineBuilder getTimelineBuilder() { + return new TimelineInjector.TimelineBuilder() + .clock("minecraft:overworld") + .periodTicks(24000); } @Override From e515d10e91f7ae79543dfe061b3d2d3b790d3bee Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 11 Jun 2026 11:10:45 +0200 Subject: [PATCH 20/74] rename TimelinesInjector --- .../api/datapacks/injectors/DimensionTypesInjector.java | 2 +- .../{TimelineInjector.java => TimelinesInjector.java} | 8 ++++---- .../fr/openmc/core/registry/ambient/TimelineAmbient.java | 8 ++++---- .../core/registry/ambient/contents/GoldenAmbient.java | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) rename src/main/java/fr/openmc/api/datapacks/injectors/{TimelineInjector.java => TimelinesInjector.java} (96%) diff --git a/src/main/java/fr/openmc/api/datapacks/injectors/DimensionTypesInjector.java b/src/main/java/fr/openmc/api/datapacks/injectors/DimensionTypesInjector.java index b07331b8f..7f7755cd9 100644 --- a/src/main/java/fr/openmc/api/datapacks/injectors/DimensionTypesInjector.java +++ b/src/main/java/fr/openmc/api/datapacks/injectors/DimensionTypesInjector.java @@ -289,7 +289,7 @@ public DimensionTypeBuilder timelines(String timelines) { return this; } - public DimensionTypeBuilder timelines(TimelineInjector injector) { + public DimensionTypeBuilder timelines(TimelinesInjector injector) { this.timelines = injector.getNamespace() + ":" + injector.getId(); return this; } diff --git a/src/main/java/fr/openmc/api/datapacks/injectors/TimelineInjector.java b/src/main/java/fr/openmc/api/datapacks/injectors/TimelinesInjector.java similarity index 96% rename from src/main/java/fr/openmc/api/datapacks/injectors/TimelineInjector.java rename to src/main/java/fr/openmc/api/datapacks/injectors/TimelinesInjector.java index 4a5cebb7f..a54221424 100644 --- a/src/main/java/fr/openmc/api/datapacks/injectors/TimelineInjector.java +++ b/src/main/java/fr/openmc/api/datapacks/injectors/TimelinesInjector.java @@ -23,17 +23,17 @@ * Qui injecte directement cela sous forme .json dans le datapack * https://minecraft.wiki/w/Timeline */ -public class TimelineInjector implements DatapackInjector { +public class TimelinesInjector implements DatapackInjector { private final String namespace; private String id; private final Map entries = new LinkedHashMap<>(); - public TimelineInjector(String namespace) { + public TimelinesInjector(String namespace) { this.namespace = namespace; } - public TimelineInjector add(String id, Consumer builder) { + public TimelinesInjector add(String id, Consumer builder) { TimelineBuilder instance = new TimelineBuilder(); builder.accept(instance); entries.put(id, instance); @@ -41,7 +41,7 @@ public TimelineInjector add(String id, Consumer builder) { return this; } - public TimelineInjector add(String id, TimelineBuilder builder) { + public TimelinesInjector add(String id, TimelineBuilder builder) { entries.put(id, builder); this.id = id; return this; diff --git a/src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java index e158da79a..cf8a11384 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java @@ -1,11 +1,11 @@ package fr.openmc.core.registry.ambient; -import fr.openmc.api.datapacks.injectors.TimelineInjector; +import fr.openmc.api.datapacks.injectors.TimelinesInjector; public interface TimelineAmbient { - TimelineInjector.TimelineBuilder getTimelineBuilder(); + TimelinesInjector.TimelineBuilder getTimelineBuilder(); - default TimelineInjector toTimelineInjector(String namespace, String id) { - return new TimelineInjector(namespace).add(id, getTimelineBuilder()); + default TimelinesInjector toTimelineInjector(String namespace, String id) { + return new TimelinesInjector(namespace).add(id, getTimelineBuilder()); } } diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java index 5780d9fb8..5bafcdd39 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java @@ -1,7 +1,7 @@ package fr.openmc.core.registry.ambient.contents; import fr.openmc.api.datapacks.injectors.DimensionTypesInjector; -import fr.openmc.api.datapacks.injectors.TimelineInjector; +import fr.openmc.api.datapacks.injectors.TimelinesInjector; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.registry.ambient.TimelineAmbient; import net.minecraft.resources.ResourceKey; @@ -33,8 +33,8 @@ public DimensionTypesInjector.DimensionTypeBuilder getDimensionTypeBuilder() { } @Override - public TimelineInjector.TimelineBuilder getTimelineBuilder() { - return new TimelineInjector.TimelineBuilder() + public TimelinesInjector.TimelineBuilder getTimelineBuilder() { + return new TimelinesInjector.TimelineBuilder() .clock("minecraft:overworld") .periodTicks(24000); } From 84d60280b6c9c8ee7825146f8835c82091ed3aa0 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 11 Jun 2026 12:10:13 +0200 Subject: [PATCH 21/74] feat: BiomeInjector --- .../datapacks/injectors/BiomesInjector.java | 303 ++++++++++++++++++ .../ambient/CustomAmbientRegistry.java | 5 + 2 files changed, 308 insertions(+) create mode 100644 src/main/java/fr/openmc/api/datapacks/injectors/BiomesInjector.java diff --git a/src/main/java/fr/openmc/api/datapacks/injectors/BiomesInjector.java b/src/main/java/fr/openmc/api/datapacks/injectors/BiomesInjector.java new file mode 100644 index 000000000..3a97cf4f9 --- /dev/null +++ b/src/main/java/fr/openmc/api/datapacks/injectors/BiomesInjector.java @@ -0,0 +1,303 @@ +package fr.openmc.api.datapacks.injectors; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import fr.openmc.api.datapacks.DatapackInjector; +import org.bukkit.Particle; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Consumer; + +/** + * Classe qui représente les données trouvable dans un biome + * Qui injecte directement cela sous forme .json dans le datapack + * ... + */ +public class BiomesInjector implements DatapackInjector { + + private final String namespace; + private final Map entries = new LinkedHashMap<>(); + + public BiomesInjector(String namespace) { + this.namespace = namespace; + } + + public BiomesInjector add(String id, Consumer builder) { + BiomeBuilder instance = new BiomeBuilder(); + builder.accept(instance); + entries.put(id, instance); + return this; + } + + public BiomesInjector add(String id, BiomeBuilder builder) { + entries.put(id, builder); + return this; + } + + @Override + public void inject(File rootFile) { + if (entries.isEmpty()) return; + + Path root = rootFile.toPath().resolve("data").resolve(namespace) + .resolve("worldgen").resolve("biome"); + try { + Files.createDirectories(root); + for (var entry : entries.entrySet()) { + Path biomeFile = root.resolve(entry.getKey() + ".json"); + Files.writeString(biomeFile, GSON.toJson(entry.getValue().toJson())); + } + } catch (IOException e) { + throw new IllegalStateException("Cannot write biome files", e); + } + } + + /** + * Exemple simple d'un biome: + * { + * "attributes": {}, + * "carvers": [], + * "creature_spawn_probability": 0.03, + * "downfall": 0, + * "effects": { + * "foliage_color": "#9e814d", + * "grass_color": "#90814d", + * "water_color": "#3f76e4", + * "dry_foliage_color": "", + * "grass_color_modifier": "none" + * }, + * "features": [], + * "has_precipitation": false, + * "spawn_costs": {}, + * "spawners": {}, + * "temperature": 2 + * } + */ + public static final class BiomeBuilder { + private final JsonObject attributes = new JsonObject(); + private final JsonArray carvers = new JsonArray(); + private final JsonObject effects = new JsonObject(); + { + effects.addProperty("water_color", "#3f76e4"); + } + private final JsonArray features = new JsonArray(); + private final JsonObject spawnCosts = new JsonObject(); + private final JsonObject spawners = new JsonObject(); + private String temperatureModifier = "none"; + private Double creatureSpawnProbability = 0.03; + private Double downfall = 0.5; + private Double temperatures = 0.5; + private Boolean hasPrecipitation = true; + + // todo: EnvironnemenAttributeBuilder + public BiomeBuilder attributes(Consumer builder) { + JsonObject obj = new JsonObject(); + builder.accept(obj); + for (var entry : obj.entrySet()) { + this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); + } + return this; + } + + public BiomeBuilder attributes(JsonObject attributes) { + for (var entry : attributes.entrySet()) { + this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); + } + return this; + } + + /** + * Ajoute un attribut "minecraft:visual/ambient_particles" simple. + * Exemple : + * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] + */ + public BiomeBuilder ambientParticles(String particleType, double probability) { + JsonObject entry = new JsonObject(); + JsonObject particle = new JsonObject(); + particle.addProperty("type", particleType); + entry.add("particle", particle); + entry.addProperty("probability", probability); + + String key = "minecraft:visual/ambient_particles"; + if (this.attributes.has(key)) { + this.attributes.getAsJsonObject(key) + .getAsJsonArray("argument") + .add(entry); + } else { + JsonArray arr = new JsonArray(); + arr.add(entry); + this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); + } + return this; + } + + /** + * { + * "particle": { + * "type": "minecraft:dust_color_transition", + * "from_color": 16776172, + * "to_color": 16766720, + * "scale": 1 + * }, + * "probability": 0.1 + * } + */ + public BiomeBuilder particleDustColorTransition(int fromColor, int toColor, float scale, double probability) { + JsonObject entry = new JsonObject(); + JsonObject particle = new JsonObject(); + particle.addProperty("type", "minecraft:dust_color_transition"); + particle.addProperty("from_color", fromColor); + particle.addProperty("to_color", toColor); + particle.addProperty("scale", scale); + entry.add("particle", particle); + entry.addProperty("probability", probability); + + String key = "minecraft:visual/ambient_particles"; + if (this.attributes.has(key)) { + this.attributes.getAsJsonObject(key) + .getAsJsonArray("argument") + .add(entry); + } else { + JsonArray arr = new JsonArray(); + arr.add(entry); + this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); + } + return this; + } + + /** + * Ajoute un attribut "minecraft:visual/ambient_particles" simple. + * Exemple : + * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] + */ + public BiomeBuilder ambientParticles(Particle particle, double probability) { + return ambientParticles(particle.getKey().toString(), probability); + } + + public BiomeBuilder carver(String id) { + this.carvers.add(id); + return this; + } + + public BiomeBuilder features(JsonElement id) { + this.features.add(id); + return this; + } + + public BiomeBuilder temperatureModifier(String id) { + this.temperatureModifier =id; + return this; + } + + public BiomeBuilder creatureSpawnProbability(Double value) { + this.creatureSpawnProbability=value; + return this; + } + + public BiomeBuilder downfall(Double value) { + this.downfall=value; + return this; + } + + public BiomeBuilder effects(Consumer builder) { + JsonObject obj = new JsonObject(); + builder.accept(obj); + for (var entry : obj.entrySet()) { + this.effects.add(entry.getKey(), entry.getValue()); + } + return this; + } + + public BiomeBuilder waterColor(String color) { + this.effects.addProperty("water_color", color); + return this; + } + + public BiomeBuilder grassColor(String color) { + this.effects.addProperty("grass_color", color); + return this; + } + + public BiomeBuilder foliageColor(String color) { + this.effects.addProperty("foliage_color", color); + return this; + } + + public BiomeBuilder dryFoliageColor(String color) { + this.effects.addProperty("dry_foliage_color", color); + return this; + } + + /** + * Set la grass color modifier + * @param id none, dark_forest, swamp + * @return le builder + */ + public BiomeBuilder grassColorModifier(String id) { + this.effects.addProperty("grass_color_modifier", id); + return this; + } + + public BiomeBuilder spawnCosts(Consumer builder) { + JsonObject obj = new JsonObject(); + builder.accept(obj); + for (var entry : obj.entrySet()) { + this.spawnCosts.add(entry.getKey(), entry.getValue()); + } + return this; + } + + public BiomeBuilder spawnCosts(JsonObject spawnCosts) { + for (var entry : spawnCosts.entrySet()) { + this.spawnCosts.add(entry.getKey(), entry.getValue()); + } + return this; + } + + public BiomeBuilder spawners(JsonObject spawners) { + for (var entry : spawners.entrySet()) { + this.spawners.add(entry.getKey(), entry.getValue()); + } + return this; + } + + public BiomeBuilder temperatures(Double value) { + this.temperatures=value; + return this; + } + + public BiomeBuilder temperatures(Boolean bool) { + this.hasPrecipitation=bool; + return this; + } + + private JsonObject toJson() { + JsonObject json = new JsonObject(); + if (attributes != null) json.add("attributes", attributes); + if (temperatureModifier != null) json.addProperty("temperature_modifier", temperatureModifier); + if (creatureSpawnProbability != null) json.addProperty("creature_spawn_probability", creatureSpawnProbability); + if (carvers != null) json.add("carvers", carvers); + if (downfall != null) json.addProperty("downfall", downfall); + if (effects != null) json.add("effects", effects); + if (features != null) json.add("features", features); + if (hasPrecipitation != null) json.addProperty("has_precipitation", hasPrecipitation); + if (spawnCosts != null) json.add("spawn_costs", spawnCosts); + if (spawners != null) json.add("spawners", spawners); + if (temperatures != null) json.addProperty("temperature", temperatures); + + return json; + } + + private JsonObject toOverridenEnvironnementAttribute(JsonElement value) { + JsonObject obj = new JsonObject(); + obj.addProperty("modifier", "override"); + obj.add("argument", value); + return obj; + } + } +} diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java index 9e6c4287d..572ced236 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java @@ -1,6 +1,7 @@ package fr.openmc.core.registry.ambient; import fr.openmc.api.datapacks.OMCDatapack; +import fr.openmc.api.datapacks.injectors.BiomesInjector; import fr.openmc.core.bootstrap.registries.KeyedRegistry; import fr.openmc.core.bootstrap.registries.Registry; import fr.openmc.core.registry.ambient.contents.DarkAmbient; @@ -34,6 +35,10 @@ public void bootstrap(BootstrapContext context) throws IOException { } } + ambientDatapack.addInjector(new BiomesInjector("omc_ambient").add("empty", + new BiomesInjector.BiomeBuilder() + .grassColor("#FFD700"))); + ambientDatapack.build(context, true); //todo: remettre ça en false } } From e9fcac9e02d9a0193aa1c948f82c7efb1d359a76 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 11 Jun 2026 12:18:04 +0200 Subject: [PATCH 22/74] divise builder in package datapacks.builders --- .../api/datapacks/builders/BiomeBuilder.java | 252 ++++++++++++++++ .../builders/DimensionTypeBuilder.java | 278 ++++++++++++++++++ .../datapacks/builders/TimelineBuilder.java | 200 +++++++++++++ .../datapacks/injectors/BiomesInjector.java | 249 +--------------- .../injectors/DimensionTypesInjector.java | 274 +---------------- .../injectors/TimelinesInjector.java | 144 +-------- .../core/registry/ambient/CustomAmbient.java | 3 +- .../ambient/CustomAmbientRegistry.java | 3 +- .../registry/ambient/TimelineAmbient.java | 3 +- .../ambient/contents/DarkAmbient.java | 6 +- .../ambient/contents/GoldenAmbient.java | 12 +- .../ambient/contents/HellAmbient.java | 6 +- 12 files changed, 751 insertions(+), 679 deletions(-) create mode 100644 src/main/java/fr/openmc/api/datapacks/builders/BiomeBuilder.java create mode 100644 src/main/java/fr/openmc/api/datapacks/builders/DimensionTypeBuilder.java create mode 100644 src/main/java/fr/openmc/api/datapacks/builders/TimelineBuilder.java diff --git a/src/main/java/fr/openmc/api/datapacks/builders/BiomeBuilder.java b/src/main/java/fr/openmc/api/datapacks/builders/BiomeBuilder.java new file mode 100644 index 000000000..b76eb2f81 --- /dev/null +++ b/src/main/java/fr/openmc/api/datapacks/builders/BiomeBuilder.java @@ -0,0 +1,252 @@ +package fr.openmc.api.datapacks.builders; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.bukkit.Particle; + +import java.util.function.Consumer; + +/** + * Exemple simple d'un biome: + * { + * "attributes": {}, + * "carvers": [], + * "creature_spawn_probability": 0.03, + * "downfall": 0, + * "effects": { + * "foliage_color": "#9e814d", + * "grass_color": "#90814d", + * "water_color": "#3f76e4", + * "dry_foliage_color": "", + * "grass_color_modifier": "none" + * }, + * "features": [], + * "has_precipitation": false, + * "spawn_costs": {}, + * "spawners": {}, + * "temperature": 2 + * } + */ +public final class BiomeBuilder { + private final JsonObject attributes = new JsonObject(); + private final JsonArray carvers = new JsonArray(); + private final JsonObject effects = new JsonObject(); + { + effects.addProperty("water_color", "#3f76e4"); + } + private final JsonArray features = new JsonArray(); + private final JsonObject spawnCosts = new JsonObject(); + private final JsonObject spawners = new JsonObject(); + private String temperatureModifier = "none"; + private Double creatureSpawnProbability = 0.03; + private Double downfall = 0.5; + private Double temperatures = 0.5; + private Boolean hasPrecipitation = true; + + // todo: EnvironnemenAttributeBuilder + public BiomeBuilder attributes(Consumer builder) { + JsonObject obj = new JsonObject(); + builder.accept(obj); + for (var entry : obj.entrySet()) { + this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); + } + return this; + } + + public BiomeBuilder attributes(JsonObject attributes) { + for (var entry : attributes.entrySet()) { + this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); + } + return this; + } + + /** + * Ajoute un attribut "minecraft:visual/ambient_particles" simple. + * Exemple : + * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] + */ + public BiomeBuilder ambientParticles(String particleType, double probability) { + JsonObject entry = new JsonObject(); + JsonObject particle = new JsonObject(); + particle.addProperty("type", particleType); + entry.add("particle", particle); + entry.addProperty("probability", probability); + + String key = "minecraft:visual/ambient_particles"; + if (this.attributes.has(key)) { + this.attributes.getAsJsonObject(key) + .getAsJsonArray("argument") + .add(entry); + } else { + JsonArray arr = new JsonArray(); + arr.add(entry); + this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); + } + return this; + } + + /** + * { + * "particle": { + * "type": "minecraft:dust_color_transition", + * "from_color": 16776172, + * "to_color": 16766720, + * "scale": 1 + * }, + * "probability": 0.1 + * } + */ + public BiomeBuilder particleDustColorTransition(int fromColor, int toColor, float scale, double probability) { + JsonObject entry = new JsonObject(); + JsonObject particle = new JsonObject(); + particle.addProperty("type", "minecraft:dust_color_transition"); + particle.addProperty("from_color", fromColor); + particle.addProperty("to_color", toColor); + particle.addProperty("scale", scale); + entry.add("particle", particle); + entry.addProperty("probability", probability); + + String key = "minecraft:visual/ambient_particles"; + if (this.attributes.has(key)) { + this.attributes.getAsJsonObject(key) + .getAsJsonArray("argument") + .add(entry); + } else { + JsonArray arr = new JsonArray(); + arr.add(entry); + this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); + } + return this; + } + + /** + * Ajoute un attribut "minecraft:visual/ambient_particles" simple. + * Exemple : + * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] + */ + public BiomeBuilder ambientParticles(Particle particle, double probability) { + return ambientParticles(particle.getKey().toString(), probability); + } + + public BiomeBuilder carver(String id) { + this.carvers.add(id); + return this; + } + + public BiomeBuilder features(JsonElement id) { + this.features.add(id); + return this; + } + + public BiomeBuilder temperatureModifier(String id) { + this.temperatureModifier =id; + return this; + } + + public BiomeBuilder creatureSpawnProbability(Double value) { + this.creatureSpawnProbability=value; + return this; + } + + public BiomeBuilder downfall(Double value) { + this.downfall=value; + return this; + } + + public BiomeBuilder effects(Consumer builder) { + JsonObject obj = new JsonObject(); + builder.accept(obj); + for (var entry : obj.entrySet()) { + this.effects.add(entry.getKey(), entry.getValue()); + } + return this; + } + + public BiomeBuilder waterColor(String color) { + this.effects.addProperty("water_color", color); + return this; + } + + public BiomeBuilder grassColor(String color) { + this.effects.addProperty("grass_color", color); + return this; + } + + public BiomeBuilder foliageColor(String color) { + this.effects.addProperty("foliage_color", color); + return this; + } + + public BiomeBuilder dryFoliageColor(String color) { + this.effects.addProperty("dry_foliage_color", color); + return this; + } + + /** + * Set la grass color modifier + * @param id none, dark_forest, swamp + * @return le builder + */ + public BiomeBuilder grassColorModifier(String id) { + this.effects.addProperty("grass_color_modifier", id); + return this; + } + + public BiomeBuilder spawnCosts(Consumer builder) { + JsonObject obj = new JsonObject(); + builder.accept(obj); + for (var entry : obj.entrySet()) { + this.spawnCosts.add(entry.getKey(), entry.getValue()); + } + return this; + } + + public BiomeBuilder spawnCosts(JsonObject spawnCosts) { + for (var entry : spawnCosts.entrySet()) { + this.spawnCosts.add(entry.getKey(), entry.getValue()); + } + return this; + } + + public BiomeBuilder spawners(JsonObject spawners) { + for (var entry : spawners.entrySet()) { + this.spawners.add(entry.getKey(), entry.getValue()); + } + return this; + } + + public BiomeBuilder temperatures(Double value) { + this.temperatures=value; + return this; + } + + public BiomeBuilder temperatures(Boolean bool) { + this.hasPrecipitation=bool; + return this; + } + + public JsonObject toJson() { + JsonObject json = new JsonObject(); + if (attributes != null) json.add("attributes", attributes); + if (temperatureModifier != null) json.addProperty("temperature_modifier", temperatureModifier); + if (creatureSpawnProbability != null) json.addProperty("creature_spawn_probability", creatureSpawnProbability); + if (carvers != null) json.add("carvers", carvers); + if (downfall != null) json.addProperty("downfall", downfall); + if (effects != null) json.add("effects", effects); + if (features != null) json.add("features", features); + if (hasPrecipitation != null) json.addProperty("has_precipitation", hasPrecipitation); + if (spawnCosts != null) json.add("spawn_costs", spawnCosts); + if (spawners != null) json.add("spawners", spawners); + if (temperatures != null) json.addProperty("temperature", temperatures); + + return json; + } + + private JsonObject toOverridenEnvironnementAttribute(JsonElement value) { + JsonObject obj = new JsonObject(); + obj.addProperty("modifier", "override"); + obj.add("argument", value); + return obj; + } +} diff --git a/src/main/java/fr/openmc/api/datapacks/builders/DimensionTypeBuilder.java b/src/main/java/fr/openmc/api/datapacks/builders/DimensionTypeBuilder.java new file mode 100644 index 000000000..9a954bb08 --- /dev/null +++ b/src/main/java/fr/openmc/api/datapacks/builders/DimensionTypeBuilder.java @@ -0,0 +1,278 @@ +package fr.openmc.api.datapacks.builders; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import fr.openmc.api.datapacks.injectors.TimelinesInjector; +import net.minecraft.world.level.dimension.DimensionType; +import org.bukkit.Particle; + +import java.util.function.Consumer; + +/** + * Exemple simple d'un dimension type : + * { + * "attributes": {}, + * "ambient_light": 0, + * "coordinate_scale": 1, + * "default_clock": "minecraft:overworld", + * "has_ceiling": false, + * "has_ender_dragon_fight": false, + * "has_skylight": true, + * "has_fixed_time": true, + * "skybox": "overworld", + * "cardinal_light": "default", + * "height": 384, + * "infiniburn": "#minecraft:infiniburn_overworld", + * "logical_height": 384, + * "min_y": -64, + * "monster_spawn_block_light_limit": 0, + * "monster_spawn_light_level": { + * "type": "minecraft:uniform", + * "max_inclusive": 7, + * "min_inclusive": 0 + * }, + * "timelines": "#minecraft:in_overworld" + * } + */ +public final class DimensionTypeBuilder { + private JsonObject attributes; + private Double ambientLight = 0.0; + private Double coordinateScale = 1.0; + private String defaultClock = "overworld"; + private Boolean hasCeiling = false; + private Boolean hasEnderDragonFlight = false; + private Boolean hasSkylight = true; + private Boolean hasFixedTime = false; + private String skybox = "overworld"; + private String cardinalLight = "default"; + private Integer height = 384; + private String infiniburn = "#infiniburn_overworld"; + private Integer logicalHeight = 384; + private Integer minY = -64; + private Integer monsterSpawnBlockLightLimit = 0; + private JsonElement monsterSpawnLightLevel = new JsonPrimitive(0); + private String timelines = "#minecraft:in_overworld"; + + public DimensionTypeBuilder attributes(Consumer builder) { + JsonObject obj = new JsonObject(); + builder.accept(obj); + + this.attributes = new JsonObject(); + for (var entry : obj.entrySet()) { + this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); + } + return this; + } + + public DimensionTypeBuilder attributes(JsonObject attributes) { + this.attributes = new JsonObject(); + for (var entry : attributes.entrySet()) { + this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); + } + return this; + } + + /** + * Ajoute un attribut "minecraft:visual/ambient_particles" simple. + * Exemple : + * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] + */ + public DimensionTypeBuilder ambientParticles(String particleType, double probability) { + if (this.attributes == null) this.attributes = new JsonObject(); + JsonObject entry = new JsonObject(); + JsonObject particle = new JsonObject(); + particle.addProperty("type", particleType); + entry.add("particle", particle); + entry.addProperty("probability", probability); + + String key = "minecraft:visual/ambient_particles"; + if (this.attributes.has(key)) { + this.attributes.getAsJsonObject(key) + .getAsJsonArray("argument") + .add(entry); + } else { + JsonArray arr = new JsonArray(); + arr.add(entry); + this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); + } + return this; + } + + /** + * { + * "particle": { + * "type": "minecraft:dust_color_transition", + * "from_color": 16776172, + * "to_color": 16766720, + * "scale": 1 + * }, + * "probability": 0.1 + * } + */ + public DimensionTypeBuilder particleDustColorTransition(int fromColor, int toColor, float scale, double probability) { + if (this.attributes == null) this.attributes = new JsonObject(); + JsonObject entry = new JsonObject(); + JsonObject particle = new JsonObject(); + particle.addProperty("type", "minecraft:dust_color_transition"); + particle.addProperty("from_color", fromColor); + particle.addProperty("to_color", toColor); + particle.addProperty("scale", scale); + entry.add("particle", particle); + entry.addProperty("probability", probability); + + String key = "minecraft:visual/ambient_particles"; + if (this.attributes.has(key)) { + this.attributes.getAsJsonObject(key) + .getAsJsonArray("argument") + .add(entry); + } else { + JsonArray arr = new JsonArray(); + arr.add(entry); + this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); + } + return this; + } + + /** + * Ajoute un attribut "minecraft:visual/ambient_particles" simple. + * Exemple : + * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] + */ + public DimensionTypeBuilder ambientParticles(Particle particle, double probability) { + return ambientParticles(particle.getKey().toString(), probability); + } + + public DimensionTypeBuilder ambientLight(double ambientLight) { + this.ambientLight = ambientLight; + return this; + } + + public DimensionTypeBuilder coordinateScale(double coordinateScale) { + this.coordinateScale = coordinateScale; + return this; + } + + public DimensionTypeBuilder defaultClock(String keyOfClock) { + this.defaultClock = keyOfClock; + return this; + } + + public DimensionTypeBuilder hasCeiling(boolean hasCeiling) { + this.hasCeiling = hasCeiling; + return this; + } + + public DimensionTypeBuilder hasEnderDragonFlight(boolean hasEnderDragonFlight) { + this.hasEnderDragonFlight = hasEnderDragonFlight; + return this; + } + + public DimensionTypeBuilder hasSkylight(boolean hasSkylight) { + this.hasSkylight = hasSkylight; + return this; + } + + public DimensionTypeBuilder hasFixedTime(boolean hasFixedTime) { + this.hasFixedTime = hasFixedTime; + return this; + } + + public DimensionTypeBuilder skybox(String skybox) { + this.skybox = skybox; + return this; + } + + public DimensionTypeBuilder skybox(DimensionType.Skybox skybox) { + return skybox(skybox.getSerializedName()); + } + + public DimensionTypeBuilder cardinalLight(String cardinalLight) { + this.cardinalLight = cardinalLight; + return this; + } + + public DimensionTypeBuilder height(int height) { + this.height = height; + return this; + } + + public DimensionTypeBuilder infiniburn(String infiniburn) { + this.infiniburn = infiniburn; + return this; + } + + public DimensionTypeBuilder logicalHeight(int logicalHeight) { + this.logicalHeight = logicalHeight; + return this; + } + + public DimensionTypeBuilder minY(int minY) { + this.minY = minY; + return this; + } + + public DimensionTypeBuilder monsterSpawnBlockLightLimit(int limit) { + this.monsterSpawnBlockLightLimit = limit; + return this; + } + + public DimensionTypeBuilder monsterSpawnLightLevelUniform(int minInclusive, int maxInclusive) { + JsonObject uniform = new JsonObject(); + uniform.addProperty("type", "minecraft:uniform"); + uniform.addProperty("min_inclusive", minInclusive); + uniform.addProperty("max_inclusive", maxInclusive); + this.monsterSpawnLightLevel = uniform; + return this; + } + + public DimensionTypeBuilder monsterSpawnLightLevel(int level) { + this.monsterSpawnLightLevel = new JsonPrimitive(level); + return this; + } + + public DimensionTypeBuilder monsterSpawnLightLevel(JsonElement monsterSpawnLightLevel) { + this.monsterSpawnLightLevel = monsterSpawnLightLevel; + return this; + } + + public DimensionTypeBuilder timelines(String timelines) { + this.timelines = timelines; + return this; + } + + public DimensionTypeBuilder timelines(TimelinesInjector injector) { + this.timelines = injector.getNamespace() + ":" + injector.getId(); + return this; + } + + public JsonObject toJson() { + JsonObject json = new JsonObject(); + if (attributes != null) json.add("attributes", attributes); + if (ambientLight != null) json.addProperty("ambient_light", ambientLight); + if (coordinateScale != null) json.addProperty("coordinate_scale", coordinateScale); + if (defaultClock != null) json.addProperty("default_clock", defaultClock); + if (hasCeiling != null) json.addProperty("has_ceiling", hasCeiling); + if (hasEnderDragonFlight != null) json.addProperty("has_ender_dragon_fight", hasEnderDragonFlight); + if (hasSkylight != null) json.addProperty("has_skylight", hasSkylight); + if (hasFixedTime != null) json.addProperty("has_fixed_time", hasFixedTime); + if (skybox != null) json.addProperty("skybox", skybox); + if (cardinalLight != null) json.addProperty("cardinal_light", cardinalLight); + if (height != null) json.addProperty("height", height); + if (infiniburn != null) json.addProperty("infiniburn", infiniburn); + if (logicalHeight != null) json.addProperty("logical_height", logicalHeight); + if (minY != null) json.addProperty("min_y", minY); + if (monsterSpawnBlockLightLimit != null) json.addProperty("monster_spawn_block_light_limit", monsterSpawnBlockLightLimit); + if (monsterSpawnLightLevel != null) json.add("monster_spawn_light_level", monsterSpawnLightLevel); + if (timelines != null) json.addProperty("timelines", timelines); + return json; + } + + private JsonObject toOverridenEnvironnementAttribute(JsonElement value) { + JsonObject obj = new JsonObject(); + obj.addProperty("modifier", "override"); + obj.add("argument", value); + return obj; + } +} diff --git a/src/main/java/fr/openmc/api/datapacks/builders/TimelineBuilder.java b/src/main/java/fr/openmc/api/datapacks/builders/TimelineBuilder.java new file mode 100644 index 000000000..bef824a5b --- /dev/null +++ b/src/main/java/fr/openmc/api/datapacks/builders/TimelineBuilder.java @@ -0,0 +1,200 @@ +package fr.openmc.api.datapacks.builders; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +/** + * { + * "clock": "minecraft:overworld", + * "period_ticks": 24000, + * "time_markers": { + * "minecraft:day": { + * "show_in_commands": true, + * "ticks": 1000 + * }, + * "minecraft:midnight": { + * "show_in_commands": true, + * "ticks": 18000 + * }, + * "minecraft:night": { + * "show_in_commands": true, + * "ticks": 13000 + * }, + * "minecraft:noon": { + * "show_in_commands": true, + * "ticks": 6000 + * }, + * "minecraft:roll_village_siege": 18000, + * "minecraft:wake_up_from_sleep": 0 + * }, + * "tracks": { + * "minecraft:visual/sky_color": { + * "keyframes": [ + * { + * "ticks": 133, + * "value": "#ffffff" + * }, + * { + * "ticks": 11867, + * "value": "#ffffff" + * }, + * { + * "ticks": 13670, + * "value": "#000000" + * }, + * { + * "ticks": 22330, + * "value": "#000000" + * } + * ], + * "modifier": "multiply" + * } + * } + * } + */ +public final class TimelineBuilder { + private String clock = "minecraft:overworld"; + private Integer periodTicks = null; + private final Map tracks = new LinkedHashMap<>(); + private final Map timeMarkers = new LinkedHashMap<>(); + + public TimelineBuilder clock(String clock) { + this.clock = clock; + return this; + } + + public TimelineBuilder periodTicks(int periodTicks) { + this.periodTicks = periodTicks; + return this; + } + + public TimelineBuilder track(String attributeId, Consumer builder) { + TrackBuilder track = new TrackBuilder(); + builder.accept(track); + tracks.put(attributeId, track); + return this; + } + + public TimelineBuilder timeMarker(String id, int ticks) { + timeMarkers.put(id, ticks); + return this; + } + + public TimelineBuilder timeMarker(String id, int ticks, boolean showInCommands) { + JsonObject marker = new JsonObject(); + marker.addProperty("ticks", ticks); + marker.addProperty("show_in_commands", showInCommands); + timeMarkers.put(id, marker); + return this; + } + + public JsonObject toJson() { + JsonObject json = new JsonObject(); + json.addProperty("clock", clock); + if (periodTicks != null) json.addProperty("period_ticks", periodTicks); + + if (!tracks.isEmpty()) { + JsonObject tracksJson = new JsonObject(); + for (var entry : tracks.entrySet()) { + tracksJson.add(entry.getKey(), entry.getValue().toJson()); + } + json.add("tracks", tracksJson); + } + + if (!timeMarkers.isEmpty()) { + JsonObject markersJson = new JsonObject(); + for (var entry : timeMarkers.entrySet()) { + if (entry.getValue() instanceof Integer i) { + markersJson.addProperty(entry.getKey(), i); + } else if (entry.getValue() instanceof JsonObject obj) { + markersJson.add(entry.getKey(), obj); + } + } + json.add("time_markers", markersJson); + } + + return json; + } + + public final class TrackBuilder { + private String ease = null; + private JsonElement easeObject = null; + private String modifier = null; + private final List keyframes = new ArrayList<>(); + + public TrackBuilder ease(String ease) { + this.ease = ease; + return this; + } + + public TrackBuilder easeCubicBezier(double x1, double y1, double x2, double y2) { + JsonObject obj = new JsonObject(); + JsonArray bezier = new JsonArray(); + bezier.add(x1); bezier.add(y1); bezier.add(x2); bezier.add(y2); + obj.add("cubic_bezier", bezier); + this.easeObject = obj; + return this; + } + + public TrackBuilder modifier(String modifier) { + this.modifier = modifier; + return this; + } + + public TrackBuilder keyframe(int ticks, String value) { + keyframes.add(new KeyframeBuilder(ticks, new JsonPrimitive(value))); + return this; + } + + public TrackBuilder keyframe(int ticks, double value) { + keyframes.add(new KeyframeBuilder(ticks, new JsonPrimitive(value))); + return this; + } + + public TrackBuilder keyframe(int ticks, boolean value) { + keyframes.add(new KeyframeBuilder(ticks, new JsonPrimitive(value))); + return this; + } + + public TrackBuilder keyframe(int ticks, JsonElement value) { + keyframes.add(new KeyframeBuilder(ticks, value)); + return this; + } + + private JsonObject toJson() { + JsonObject json = new JsonObject(); + if (easeObject != null) { + json.add("ease", easeObject); + } else if (ease != null) { + json.addProperty("ease", ease); + } + if (modifier != null) json.addProperty("modifier", modifier); + + JsonArray kfArray = new JsonArray(); + for (KeyframeBuilder kf : keyframes) { + kfArray.add(kf.toJson()); + } + json.add("keyframes", kfArray); + return json; + } + + + + private record KeyframeBuilder(int ticks, JsonElement value) { + private JsonObject toJson() { + JsonObject json = new JsonObject(); + json.addProperty("ticks", ticks); + json.add("value", value); + return json; + } + } + } +} diff --git a/src/main/java/fr/openmc/api/datapacks/injectors/BiomesInjector.java b/src/main/java/fr/openmc/api/datapacks/injectors/BiomesInjector.java index 3a97cf4f9..c263c41d1 100644 --- a/src/main/java/fr/openmc/api/datapacks/injectors/BiomesInjector.java +++ b/src/main/java/fr/openmc/api/datapacks/injectors/BiomesInjector.java @@ -1,10 +1,7 @@ package fr.openmc.api.datapacks.injectors; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; import fr.openmc.api.datapacks.DatapackInjector; -import org.bukkit.Particle; +import fr.openmc.api.datapacks.builders.BiomeBuilder; import java.io.File; import java.io.IOException; @@ -56,248 +53,4 @@ public void inject(File rootFile) { throw new IllegalStateException("Cannot write biome files", e); } } - - /** - * Exemple simple d'un biome: - * { - * "attributes": {}, - * "carvers": [], - * "creature_spawn_probability": 0.03, - * "downfall": 0, - * "effects": { - * "foliage_color": "#9e814d", - * "grass_color": "#90814d", - * "water_color": "#3f76e4", - * "dry_foliage_color": "", - * "grass_color_modifier": "none" - * }, - * "features": [], - * "has_precipitation": false, - * "spawn_costs": {}, - * "spawners": {}, - * "temperature": 2 - * } - */ - public static final class BiomeBuilder { - private final JsonObject attributes = new JsonObject(); - private final JsonArray carvers = new JsonArray(); - private final JsonObject effects = new JsonObject(); - { - effects.addProperty("water_color", "#3f76e4"); - } - private final JsonArray features = new JsonArray(); - private final JsonObject spawnCosts = new JsonObject(); - private final JsonObject spawners = new JsonObject(); - private String temperatureModifier = "none"; - private Double creatureSpawnProbability = 0.03; - private Double downfall = 0.5; - private Double temperatures = 0.5; - private Boolean hasPrecipitation = true; - - // todo: EnvironnemenAttributeBuilder - public BiomeBuilder attributes(Consumer builder) { - JsonObject obj = new JsonObject(); - builder.accept(obj); - for (var entry : obj.entrySet()) { - this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); - } - return this; - } - - public BiomeBuilder attributes(JsonObject attributes) { - for (var entry : attributes.entrySet()) { - this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); - } - return this; - } - - /** - * Ajoute un attribut "minecraft:visual/ambient_particles" simple. - * Exemple : - * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] - */ - public BiomeBuilder ambientParticles(String particleType, double probability) { - JsonObject entry = new JsonObject(); - JsonObject particle = new JsonObject(); - particle.addProperty("type", particleType); - entry.add("particle", particle); - entry.addProperty("probability", probability); - - String key = "minecraft:visual/ambient_particles"; - if (this.attributes.has(key)) { - this.attributes.getAsJsonObject(key) - .getAsJsonArray("argument") - .add(entry); - } else { - JsonArray arr = new JsonArray(); - arr.add(entry); - this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); - } - return this; - } - - /** - * { - * "particle": { - * "type": "minecraft:dust_color_transition", - * "from_color": 16776172, - * "to_color": 16766720, - * "scale": 1 - * }, - * "probability": 0.1 - * } - */ - public BiomeBuilder particleDustColorTransition(int fromColor, int toColor, float scale, double probability) { - JsonObject entry = new JsonObject(); - JsonObject particle = new JsonObject(); - particle.addProperty("type", "minecraft:dust_color_transition"); - particle.addProperty("from_color", fromColor); - particle.addProperty("to_color", toColor); - particle.addProperty("scale", scale); - entry.add("particle", particle); - entry.addProperty("probability", probability); - - String key = "minecraft:visual/ambient_particles"; - if (this.attributes.has(key)) { - this.attributes.getAsJsonObject(key) - .getAsJsonArray("argument") - .add(entry); - } else { - JsonArray arr = new JsonArray(); - arr.add(entry); - this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); - } - return this; - } - - /** - * Ajoute un attribut "minecraft:visual/ambient_particles" simple. - * Exemple : - * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] - */ - public BiomeBuilder ambientParticles(Particle particle, double probability) { - return ambientParticles(particle.getKey().toString(), probability); - } - - public BiomeBuilder carver(String id) { - this.carvers.add(id); - return this; - } - - public BiomeBuilder features(JsonElement id) { - this.features.add(id); - return this; - } - - public BiomeBuilder temperatureModifier(String id) { - this.temperatureModifier =id; - return this; - } - - public BiomeBuilder creatureSpawnProbability(Double value) { - this.creatureSpawnProbability=value; - return this; - } - - public BiomeBuilder downfall(Double value) { - this.downfall=value; - return this; - } - - public BiomeBuilder effects(Consumer builder) { - JsonObject obj = new JsonObject(); - builder.accept(obj); - for (var entry : obj.entrySet()) { - this.effects.add(entry.getKey(), entry.getValue()); - } - return this; - } - - public BiomeBuilder waterColor(String color) { - this.effects.addProperty("water_color", color); - return this; - } - - public BiomeBuilder grassColor(String color) { - this.effects.addProperty("grass_color", color); - return this; - } - - public BiomeBuilder foliageColor(String color) { - this.effects.addProperty("foliage_color", color); - return this; - } - - public BiomeBuilder dryFoliageColor(String color) { - this.effects.addProperty("dry_foliage_color", color); - return this; - } - - /** - * Set la grass color modifier - * @param id none, dark_forest, swamp - * @return le builder - */ - public BiomeBuilder grassColorModifier(String id) { - this.effects.addProperty("grass_color_modifier", id); - return this; - } - - public BiomeBuilder spawnCosts(Consumer builder) { - JsonObject obj = new JsonObject(); - builder.accept(obj); - for (var entry : obj.entrySet()) { - this.spawnCosts.add(entry.getKey(), entry.getValue()); - } - return this; - } - - public BiomeBuilder spawnCosts(JsonObject spawnCosts) { - for (var entry : spawnCosts.entrySet()) { - this.spawnCosts.add(entry.getKey(), entry.getValue()); - } - return this; - } - - public BiomeBuilder spawners(JsonObject spawners) { - for (var entry : spawners.entrySet()) { - this.spawners.add(entry.getKey(), entry.getValue()); - } - return this; - } - - public BiomeBuilder temperatures(Double value) { - this.temperatures=value; - return this; - } - - public BiomeBuilder temperatures(Boolean bool) { - this.hasPrecipitation=bool; - return this; - } - - private JsonObject toJson() { - JsonObject json = new JsonObject(); - if (attributes != null) json.add("attributes", attributes); - if (temperatureModifier != null) json.addProperty("temperature_modifier", temperatureModifier); - if (creatureSpawnProbability != null) json.addProperty("creature_spawn_probability", creatureSpawnProbability); - if (carvers != null) json.add("carvers", carvers); - if (downfall != null) json.addProperty("downfall", downfall); - if (effects != null) json.add("effects", effects); - if (features != null) json.add("features", features); - if (hasPrecipitation != null) json.addProperty("has_precipitation", hasPrecipitation); - if (spawnCosts != null) json.add("spawn_costs", spawnCosts); - if (spawners != null) json.add("spawners", spawners); - if (temperatures != null) json.addProperty("temperature", temperatures); - - return json; - } - - private JsonObject toOverridenEnvironnementAttribute(JsonElement value) { - JsonObject obj = new JsonObject(); - obj.addProperty("modifier", "override"); - obj.add("argument", value); - return obj; - } - } } diff --git a/src/main/java/fr/openmc/api/datapacks/injectors/DimensionTypesInjector.java b/src/main/java/fr/openmc/api/datapacks/injectors/DimensionTypesInjector.java index 7f7755cd9..c60792d8d 100644 --- a/src/main/java/fr/openmc/api/datapacks/injectors/DimensionTypesInjector.java +++ b/src/main/java/fr/openmc/api/datapacks/injectors/DimensionTypesInjector.java @@ -1,12 +1,7 @@ package fr.openmc.api.datapacks.injectors; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; import fr.openmc.api.datapacks.DatapackInjector; -import net.minecraft.world.level.dimension.DimensionType; -import org.bukkit.Particle; +import fr.openmc.api.datapacks.builders.DimensionTypeBuilder; import java.io.File; import java.io.IOException; @@ -56,271 +51,4 @@ public void inject(File rootFile) { throw new IllegalStateException("Cannot write dimension_type files", e); } } - - /** - * Exemple simple d'un dimension type : - * { - * "attributes": {}, - * "ambient_light": 0, - * "coordinate_scale": 1, - * "default_clock": "minecraft:overworld", - * "has_ceiling": false, - * "has_ender_dragon_fight": false, - * "has_skylight": true, - * "has_fixed_time": true, - * "skybox": "overworld", - * "cardinal_light": "default", - * "height": 384, - * "infiniburn": "#minecraft:infiniburn_overworld", - * "logical_height": 384, - * "min_y": -64, - * "monster_spawn_block_light_limit": 0, - * "monster_spawn_light_level": { - * "type": "minecraft:uniform", - * "max_inclusive": 7, - * "min_inclusive": 0 - * }, - * "timelines": "#minecraft:in_overworld" - * } - */ - public static final class DimensionTypeBuilder { - private JsonObject attributes; - private Double ambientLight = 0.0; - private Double coordinateScale = 1.0; - private String defaultClock = "overworld"; - private Boolean hasCeiling = false; - private Boolean hasEnderDragonFlight = false; - private Boolean hasSkylight = true; - private Boolean hasFixedTime = false; - private String skybox = "overworld"; - private String cardinalLight = "default"; - private Integer height = 384; - private String infiniburn = "#infiniburn_overworld"; - private Integer logicalHeight = 384; - private Integer minY = -64; - private Integer monsterSpawnBlockLightLimit = 0; - private JsonElement monsterSpawnLightLevel = new JsonPrimitive(0); - private String timelines = "#minecraft:in_overworld"; - - public DimensionTypeBuilder attributes(Consumer builder) { - JsonObject obj = new JsonObject(); - builder.accept(obj); - - this.attributes = new JsonObject(); - for (var entry : obj.entrySet()) { - this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); - } - return this; - } - - public DimensionTypeBuilder attributes(JsonObject attributes) { - this.attributes = new JsonObject(); - for (var entry : attributes.entrySet()) { - this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); - } - return this; - } - - /** - * Ajoute un attribut "minecraft:visual/ambient_particles" simple. - * Exemple : - * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] - */ - public DimensionTypeBuilder ambientParticles(String particleType, double probability) { - if (this.attributes == null) this.attributes = new JsonObject(); - JsonObject entry = new JsonObject(); - JsonObject particle = new JsonObject(); - particle.addProperty("type", particleType); - entry.add("particle", particle); - entry.addProperty("probability", probability); - - String key = "minecraft:visual/ambient_particles"; - if (this.attributes.has(key)) { - this.attributes.getAsJsonObject(key) - .getAsJsonArray("argument") - .add(entry); - } else { - JsonArray arr = new JsonArray(); - arr.add(entry); - this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); - } - return this; - } - - /** - * { - * "particle": { - * "type": "minecraft:dust_color_transition", - * "from_color": 16776172, - * "to_color": 16766720, - * "scale": 1 - * }, - * "probability": 0.1 - * } - */ - public DimensionTypeBuilder particleDustColorTransition(int fromColor, int toColor, float scale, double probability) { - if (this.attributes == null) this.attributes = new JsonObject(); - JsonObject entry = new JsonObject(); - JsonObject particle = new JsonObject(); - particle.addProperty("type", "minecraft:dust_color_transition"); - particle.addProperty("from_color", fromColor); - particle.addProperty("to_color", toColor); - particle.addProperty("scale", scale); - entry.add("particle", particle); - entry.addProperty("probability", probability); - - String key = "minecraft:visual/ambient_particles"; - if (this.attributes.has(key)) { - this.attributes.getAsJsonObject(key) - .getAsJsonArray("argument") - .add(entry); - } else { - JsonArray arr = new JsonArray(); - arr.add(entry); - this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); - } - return this; - } - - /** - * Ajoute un attribut "minecraft:visual/ambient_particles" simple. - * Exemple : - * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] - */ - public DimensionTypeBuilder ambientParticles(Particle particle, double probability) { - return ambientParticles(particle.getKey().toString(), probability); - } - - public DimensionTypeBuilder ambientLight(double ambientLight) { - this.ambientLight = ambientLight; - return this; - } - - public DimensionTypeBuilder coordinateScale(double coordinateScale) { - this.coordinateScale = coordinateScale; - return this; - } - - public DimensionTypeBuilder defaultClock(String keyOfClock) { - this.defaultClock = keyOfClock; - return this; - } - - public DimensionTypeBuilder hasCeiling(boolean hasCeiling) { - this.hasCeiling = hasCeiling; - return this; - } - - public DimensionTypeBuilder hasEnderDragonFlight(boolean hasEnderDragonFlight) { - this.hasEnderDragonFlight = hasEnderDragonFlight; - return this; - } - - public DimensionTypeBuilder hasSkylight(boolean hasSkylight) { - this.hasSkylight = hasSkylight; - return this; - } - - public DimensionTypeBuilder hasFixedTime(boolean hasFixedTime) { - this.hasFixedTime = hasFixedTime; - return this; - } - - public DimensionTypeBuilder skybox(String skybox) { - this.skybox = skybox; - return this; - } - - public DimensionTypeBuilder skybox(DimensionType.Skybox skybox) { - return skybox(skybox.getSerializedName()); - } - - public DimensionTypeBuilder cardinalLight(String cardinalLight) { - this.cardinalLight = cardinalLight; - return this; - } - - public DimensionTypeBuilder height(int height) { - this.height = height; - return this; - } - - public DimensionTypeBuilder infiniburn(String infiniburn) { - this.infiniburn = infiniburn; - return this; - } - - public DimensionTypeBuilder logicalHeight(int logicalHeight) { - this.logicalHeight = logicalHeight; - return this; - } - - public DimensionTypeBuilder minY(int minY) { - this.minY = minY; - return this; - } - - public DimensionTypeBuilder monsterSpawnBlockLightLimit(int limit) { - this.monsterSpawnBlockLightLimit = limit; - return this; - } - - public DimensionTypeBuilder monsterSpawnLightLevelUniform(int minInclusive, int maxInclusive) { - JsonObject uniform = new JsonObject(); - uniform.addProperty("type", "minecraft:uniform"); - uniform.addProperty("min_inclusive", minInclusive); - uniform.addProperty("max_inclusive", maxInclusive); - this.monsterSpawnLightLevel = uniform; - return this; - } - - public DimensionTypeBuilder monsterSpawnLightLevel(int level) { - this.monsterSpawnLightLevel = new JsonPrimitive(level); - return this; - } - - public DimensionTypeBuilder monsterSpawnLightLevel(JsonElement monsterSpawnLightLevel) { - this.monsterSpawnLightLevel = monsterSpawnLightLevel; - return this; - } - - public DimensionTypeBuilder timelines(String timelines) { - this.timelines = timelines; - return this; - } - - public DimensionTypeBuilder timelines(TimelinesInjector injector) { - this.timelines = injector.getNamespace() + ":" + injector.getId(); - return this; - } - - private JsonObject toJson() { - JsonObject json = new JsonObject(); - if (attributes != null) json.add("attributes", attributes); - if (ambientLight != null) json.addProperty("ambient_light", ambientLight); - if (coordinateScale != null) json.addProperty("coordinate_scale", coordinateScale); - if (defaultClock != null) json.addProperty("default_clock", defaultClock); - if (hasCeiling != null) json.addProperty("has_ceiling", hasCeiling); - if (hasEnderDragonFlight != null) json.addProperty("has_ender_dragon_fight", hasEnderDragonFlight); - if (hasSkylight != null) json.addProperty("has_skylight", hasSkylight); - if (hasFixedTime != null) json.addProperty("has_fixed_time", hasFixedTime); - if (skybox != null) json.addProperty("skybox", skybox); - if (cardinalLight != null) json.addProperty("cardinal_light", cardinalLight); - if (height != null) json.addProperty("height", height); - if (infiniburn != null) json.addProperty("infiniburn", infiniburn); - if (logicalHeight != null) json.addProperty("logical_height", logicalHeight); - if (minY != null) json.addProperty("min_y", minY); - if (monsterSpawnBlockLightLimit != null) json.addProperty("monster_spawn_block_light_limit", monsterSpawnBlockLightLimit); - if (monsterSpawnLightLevel != null) json.add("monster_spawn_light_level", monsterSpawnLightLevel); - if (timelines != null) json.addProperty("timelines", timelines); - return json; - } - - private JsonObject toOverridenEnvironnementAttribute(JsonElement value) { - JsonObject obj = new JsonObject(); - obj.addProperty("modifier", "override"); - obj.add("argument", value); - return obj; - } - } } diff --git a/src/main/java/fr/openmc/api/datapacks/injectors/TimelinesInjector.java b/src/main/java/fr/openmc/api/datapacks/injectors/TimelinesInjector.java index a54221424..c3b67943f 100644 --- a/src/main/java/fr/openmc/api/datapacks/injectors/TimelinesInjector.java +++ b/src/main/java/fr/openmc/api/datapacks/injectors/TimelinesInjector.java @@ -1,19 +1,14 @@ package fr.openmc.api.datapacks.injectors; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; import fr.openmc.api.datapacks.DatapackInjector; +import fr.openmc.api.datapacks.builders.TimelineBuilder; import lombok.Getter; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.function.Consumer; @@ -62,141 +57,4 @@ public void inject(File rootFile) { throw new IllegalStateException("Cannot write timeline files", e); } } - - public static final class TimelineBuilder { - private String clock = "minecraft:overworld"; - private Integer periodTicks = null; - private final Map tracks = new LinkedHashMap<>(); - private final Map timeMarkers = new LinkedHashMap<>(); - - public TimelineBuilder clock(String clock) { - this.clock = clock; - return this; - } - - public TimelineBuilder periodTicks(int periodTicks) { - this.periodTicks = periodTicks; - return this; - } - - public TimelineBuilder track(String attributeId, Consumer builder) { - TrackBuilder track = new TrackBuilder(); - builder.accept(track); - tracks.put(attributeId, track); - return this; - } - - public TimelineBuilder timeMarker(String id, int ticks) { - timeMarkers.put(id, ticks); - return this; - } - - public TimelineBuilder timeMarker(String id, int ticks, boolean showInCommands) { - JsonObject marker = new JsonObject(); - marker.addProperty("ticks", ticks); - marker.addProperty("show_in_commands", showInCommands); - timeMarkers.put(id, marker); - return this; - } - - private JsonObject toJson() { - JsonObject json = new JsonObject(); - json.addProperty("clock", clock); - if (periodTicks != null) json.addProperty("period_ticks", periodTicks); - - if (!tracks.isEmpty()) { - JsonObject tracksJson = new JsonObject(); - for (var entry : tracks.entrySet()) { - tracksJson.add(entry.getKey(), entry.getValue().toJson()); - } - json.add("tracks", tracksJson); - } - - if (!timeMarkers.isEmpty()) { - JsonObject markersJson = new JsonObject(); - for (var entry : timeMarkers.entrySet()) { - if (entry.getValue() instanceof Integer i) { - markersJson.addProperty(entry.getKey(), i); - } else if (entry.getValue() instanceof JsonObject obj) { - markersJson.add(entry.getKey(), obj); - } - } - json.add("time_markers", markersJson); - } - - return json; - } - } - - public static final class TrackBuilder { - private String ease = null; - private JsonElement easeObject = null; - private String modifier = null; - private final List keyframes = new ArrayList<>(); - - public TrackBuilder ease(String ease) { - this.ease = ease; - return this; - } - - public TrackBuilder easeCubicBezier(double x1, double y1, double x2, double y2) { - JsonObject obj = new JsonObject(); - JsonArray bezier = new JsonArray(); - bezier.add(x1); bezier.add(y1); bezier.add(x2); bezier.add(y2); - obj.add("cubic_bezier", bezier); - this.easeObject = obj; - return this; - } - - public TrackBuilder modifier(String modifier) { - this.modifier = modifier; - return this; - } - - public TrackBuilder keyframe(int ticks, String value) { - keyframes.add(new KeyframeBuilder(ticks, new JsonPrimitive(value))); - return this; - } - - public TrackBuilder keyframe(int ticks, double value) { - keyframes.add(new KeyframeBuilder(ticks, new JsonPrimitive(value))); - return this; - } - - public TrackBuilder keyframe(int ticks, boolean value) { - keyframes.add(new KeyframeBuilder(ticks, new JsonPrimitive(value))); - return this; - } - - public TrackBuilder keyframe(int ticks, JsonElement value) { - keyframes.add(new KeyframeBuilder(ticks, value)); - return this; - } - - private JsonObject toJson() { - JsonObject json = new JsonObject(); - if (easeObject != null) { - json.add("ease", easeObject); - } else if (ease != null) { - json.addProperty("ease", ease); - } - if (modifier != null) json.addProperty("modifier", modifier); - - JsonArray kfArray = new JsonArray(); - for (KeyframeBuilder kf : keyframes) { - kfArray.add(kf.toJson()); - } - json.add("keyframes", kfArray); - return json; - } - } - - private record KeyframeBuilder(int ticks, JsonElement value) { - private JsonObject toJson() { - JsonObject json = new JsonObject(); - json.addProperty("ticks", ticks); - json.add("value", value); - return json; - } - } } diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java index 255cc47cd..faec87876 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java @@ -1,6 +1,7 @@ package fr.openmc.core.registry.ambient; import fr.openmc.api.datapacks.DatapackInjector; +import fr.openmc.api.datapacks.builders.DimensionTypeBuilder; import fr.openmc.api.datapacks.injectors.DimensionTypesInjector; import fr.openmc.core.utils.nms.PlayerRespawnNMS; import net.minecraft.core.Holder; @@ -27,7 +28,7 @@ public abstract class CustomAmbient { private Holder CACHED_DIMENSION_TYPE = null; public abstract String getId(); - public abstract DimensionTypesInjector.DimensionTypeBuilder getDimensionTypeBuilder(); + public abstract DimensionTypeBuilder getDimensionTypeBuilder(); /** * Choix de la transition de dimension lorsque le joueur change d'ambience diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java index 572ced236..e3f6c167c 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java @@ -1,6 +1,7 @@ package fr.openmc.core.registry.ambient; import fr.openmc.api.datapacks.OMCDatapack; +import fr.openmc.api.datapacks.builders.BiomeBuilder; import fr.openmc.api.datapacks.injectors.BiomesInjector; import fr.openmc.core.bootstrap.registries.KeyedRegistry; import fr.openmc.core.bootstrap.registries.Registry; @@ -36,7 +37,7 @@ public void bootstrap(BootstrapContext context) throws IOException { } ambientDatapack.addInjector(new BiomesInjector("omc_ambient").add("empty", - new BiomesInjector.BiomeBuilder() + new BiomeBuilder() .grassColor("#FFD700"))); ambientDatapack.build(context, true); //todo: remettre ça en false diff --git a/src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java index cf8a11384..94f0e3dd1 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java @@ -1,9 +1,10 @@ package fr.openmc.core.registry.ambient; +import fr.openmc.api.datapacks.builders.TimelineBuilder; import fr.openmc.api.datapacks.injectors.TimelinesInjector; public interface TimelineAmbient { - TimelinesInjector.TimelineBuilder getTimelineBuilder(); + TimelineBuilder getTimelineBuilder(); default TimelinesInjector toTimelineInjector(String namespace, String id) { return new TimelinesInjector(namespace).add(id, getTimelineBuilder()); diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java index 08264cc93..fe5844a5e 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java @@ -1,6 +1,6 @@ package fr.openmc.core.registry.ambient.contents; -import fr.openmc.api.datapacks.injectors.DimensionTypesInjector; +import fr.openmc.api.datapacks.builders.DimensionTypeBuilder; import fr.openmc.core.registry.ambient.CustomAmbient; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; @@ -13,8 +13,8 @@ public String getId() { } @Override - public DimensionTypesInjector.DimensionTypeBuilder getDimensionTypeBuilder() { - return new DimensionTypesInjector.DimensionTypeBuilder() + public DimensionTypeBuilder getDimensionTypeBuilder() { + return new DimensionTypeBuilder() .attributes(obj -> { obj.addProperty("visual/ambient_light_color", "#DD37E6"); obj.addProperty("visual/sky_color", "#DD37E6"); diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java index 5bafcdd39..8f55abecd 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java @@ -1,7 +1,7 @@ package fr.openmc.core.registry.ambient.contents; -import fr.openmc.api.datapacks.injectors.DimensionTypesInjector; -import fr.openmc.api.datapacks.injectors.TimelinesInjector; +import fr.openmc.api.datapacks.builders.DimensionTypeBuilder; +import fr.openmc.api.datapacks.builders.TimelineBuilder; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.registry.ambient.TimelineAmbient; import net.minecraft.resources.ResourceKey; @@ -14,8 +14,8 @@ public String getId() { } @Override - public DimensionTypesInjector.DimensionTypeBuilder getDimensionTypeBuilder() { - return new DimensionTypesInjector.DimensionTypeBuilder() + public DimensionTypeBuilder getDimensionTypeBuilder() { + return new DimensionTypeBuilder() .attributes(obj -> { obj.addProperty("visual/ambient_light_color", "#FFE75C"); obj.addProperty("visual/sky_color", "#FFD700"); @@ -33,8 +33,8 @@ public DimensionTypesInjector.DimensionTypeBuilder getDimensionTypeBuilder() { } @Override - public TimelinesInjector.TimelineBuilder getTimelineBuilder() { - return new TimelinesInjector.TimelineBuilder() + public TimelineBuilder getTimelineBuilder() { + return new TimelineBuilder() .clock("minecraft:overworld") .periodTicks(24000); } diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/HellAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/HellAmbient.java index 98aba1cf3..f0a03f91a 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/HellAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/HellAmbient.java @@ -1,6 +1,6 @@ package fr.openmc.core.registry.ambient.contents; -import fr.openmc.api.datapacks.injectors.DimensionTypesInjector; +import fr.openmc.api.datapacks.builders.DimensionTypeBuilder; import fr.openmc.core.registry.ambient.CustomAmbient; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; @@ -14,8 +14,8 @@ public String getId() { } @Override - public DimensionTypesInjector.DimensionTypeBuilder getDimensionTypeBuilder() { - return new DimensionTypesInjector.DimensionTypeBuilder() + public DimensionTypeBuilder getDimensionTypeBuilder() { + return new DimensionTypeBuilder() .attributes(obj -> { obj.addProperty("visual/ambient_light_color", "#A3170B"); obj.addProperty("visual/block_light_tint", "#F53200"); From 3dceaea3a134abd001017b7e48469f602dafa03d Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 11 Jun 2026 13:16:19 +0200 Subject: [PATCH 23/74] chore EnvironnementAttributeBuilder --- .../api/datapacks/builders/BiomeBuilder.java | 94 +----------------- .../builders/DimensionTypeBuilder.java | 92 +----------------- .../EnvironnementAttributeBuilder.java | 95 +++++++++++++++++++ .../ambient/contents/DarkAmbient.java | 18 ++-- .../ambient/contents/GoldenAmbient.java | 28 +++--- .../ambient/contents/HellAmbient.java | 22 +++-- 6 files changed, 137 insertions(+), 212 deletions(-) create mode 100644 src/main/java/fr/openmc/api/datapacks/builders/EnvironnementAttributeBuilder.java diff --git a/src/main/java/fr/openmc/api/datapacks/builders/BiomeBuilder.java b/src/main/java/fr/openmc/api/datapacks/builders/BiomeBuilder.java index b76eb2f81..9d06e9c8a 100644 --- a/src/main/java/fr/openmc/api/datapacks/builders/BiomeBuilder.java +++ b/src/main/java/fr/openmc/api/datapacks/builders/BiomeBuilder.java @@ -3,7 +3,6 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import org.bukkit.Particle; import java.util.function.Consumer; @@ -29,7 +28,7 @@ * } */ public final class BiomeBuilder { - private final JsonObject attributes = new JsonObject(); + private JsonObject attributes = new JsonObject(); private final JsonArray carvers = new JsonArray(); private final JsonObject effects = new JsonObject(); { @@ -44,91 +43,11 @@ public final class BiomeBuilder { private Double temperatures = 0.5; private Boolean hasPrecipitation = true; - // todo: EnvironnemenAttributeBuilder - public BiomeBuilder attributes(Consumer builder) { - JsonObject obj = new JsonObject(); - builder.accept(obj); - for (var entry : obj.entrySet()) { - this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); - } - return this; - } - - public BiomeBuilder attributes(JsonObject attributes) { - for (var entry : attributes.entrySet()) { - this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); - } - return this; - } - - /** - * Ajoute un attribut "minecraft:visual/ambient_particles" simple. - * Exemple : - * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] - */ - public BiomeBuilder ambientParticles(String particleType, double probability) { - JsonObject entry = new JsonObject(); - JsonObject particle = new JsonObject(); - particle.addProperty("type", particleType); - entry.add("particle", particle); - entry.addProperty("probability", probability); - - String key = "minecraft:visual/ambient_particles"; - if (this.attributes.has(key)) { - this.attributes.getAsJsonObject(key) - .getAsJsonArray("argument") - .add(entry); - } else { - JsonArray arr = new JsonArray(); - arr.add(entry); - this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); - } + public BiomeBuilder attributes(EnvironnementAttributeBuilder builder) { + this.attributes = builder.getOutputData(); return this; } - /** - * { - * "particle": { - * "type": "minecraft:dust_color_transition", - * "from_color": 16776172, - * "to_color": 16766720, - * "scale": 1 - * }, - * "probability": 0.1 - * } - */ - public BiomeBuilder particleDustColorTransition(int fromColor, int toColor, float scale, double probability) { - JsonObject entry = new JsonObject(); - JsonObject particle = new JsonObject(); - particle.addProperty("type", "minecraft:dust_color_transition"); - particle.addProperty("from_color", fromColor); - particle.addProperty("to_color", toColor); - particle.addProperty("scale", scale); - entry.add("particle", particle); - entry.addProperty("probability", probability); - - String key = "minecraft:visual/ambient_particles"; - if (this.attributes.has(key)) { - this.attributes.getAsJsonObject(key) - .getAsJsonArray("argument") - .add(entry); - } else { - JsonArray arr = new JsonArray(); - arr.add(entry); - this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); - } - return this; - } - - /** - * Ajoute un attribut "minecraft:visual/ambient_particles" simple. - * Exemple : - * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] - */ - public BiomeBuilder ambientParticles(Particle particle, double probability) { - return ambientParticles(particle.getKey().toString(), probability); - } - public BiomeBuilder carver(String id) { this.carvers.add(id); return this; @@ -242,11 +161,4 @@ public JsonObject toJson() { return json; } - - private JsonObject toOverridenEnvironnementAttribute(JsonElement value) { - JsonObject obj = new JsonObject(); - obj.addProperty("modifier", "override"); - obj.add("argument", value); - return obj; - } } diff --git a/src/main/java/fr/openmc/api/datapacks/builders/DimensionTypeBuilder.java b/src/main/java/fr/openmc/api/datapacks/builders/DimensionTypeBuilder.java index 9a954bb08..d09c5b354 100644 --- a/src/main/java/fr/openmc/api/datapacks/builders/DimensionTypeBuilder.java +++ b/src/main/java/fr/openmc/api/datapacks/builders/DimensionTypeBuilder.java @@ -1,14 +1,10 @@ package fr.openmc.api.datapacks.builders; -import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import fr.openmc.api.datapacks.injectors.TimelinesInjector; import net.minecraft.world.level.dimension.DimensionType; -import org.bukkit.Particle; - -import java.util.function.Consumer; /** * Exemple simple d'un dimension type : @@ -55,95 +51,11 @@ public final class DimensionTypeBuilder { private JsonElement monsterSpawnLightLevel = new JsonPrimitive(0); private String timelines = "#minecraft:in_overworld"; - public DimensionTypeBuilder attributes(Consumer builder) { - JsonObject obj = new JsonObject(); - builder.accept(obj); - - this.attributes = new JsonObject(); - for (var entry : obj.entrySet()) { - this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); - } - return this; - } - - public DimensionTypeBuilder attributes(JsonObject attributes) { - this.attributes = new JsonObject(); - for (var entry : attributes.entrySet()) { - this.attributes.add(entry.getKey(), toOverridenEnvironnementAttribute(entry.getValue())); - } - return this; - } - - /** - * Ajoute un attribut "minecraft:visual/ambient_particles" simple. - * Exemple : - * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] - */ - public DimensionTypeBuilder ambientParticles(String particleType, double probability) { - if (this.attributes == null) this.attributes = new JsonObject(); - JsonObject entry = new JsonObject(); - JsonObject particle = new JsonObject(); - particle.addProperty("type", particleType); - entry.add("particle", particle); - entry.addProperty("probability", probability); - - String key = "minecraft:visual/ambient_particles"; - if (this.attributes.has(key)) { - this.attributes.getAsJsonObject(key) - .getAsJsonArray("argument") - .add(entry); - } else { - JsonArray arr = new JsonArray(); - arr.add(entry); - this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); - } - return this; - } - - /** - * { - * "particle": { - * "type": "minecraft:dust_color_transition", - * "from_color": 16776172, - * "to_color": 16766720, - * "scale": 1 - * }, - * "probability": 0.1 - * } - */ - public DimensionTypeBuilder particleDustColorTransition(int fromColor, int toColor, float scale, double probability) { - if (this.attributes == null) this.attributes = new JsonObject(); - JsonObject entry = new JsonObject(); - JsonObject particle = new JsonObject(); - particle.addProperty("type", "minecraft:dust_color_transition"); - particle.addProperty("from_color", fromColor); - particle.addProperty("to_color", toColor); - particle.addProperty("scale", scale); - entry.add("particle", particle); - entry.addProperty("probability", probability); - - String key = "minecraft:visual/ambient_particles"; - if (this.attributes.has(key)) { - this.attributes.getAsJsonObject(key) - .getAsJsonArray("argument") - .add(entry); - } else { - JsonArray arr = new JsonArray(); - arr.add(entry); - this.attributes.add(key, toOverridenEnvironnementAttribute(arr)); - } + public DimensionTypeBuilder attributesBuilder(EnvironnementAttributeBuilder builder) { + this.attributes = builder.getOutputData(); return this; } - /** - * Ajoute un attribut "minecraft:visual/ambient_particles" simple. - * Exemple : - * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] - */ - public DimensionTypeBuilder ambientParticles(Particle particle, double probability) { - return ambientParticles(particle.getKey().toString(), probability); - } - public DimensionTypeBuilder ambientLight(double ambientLight) { this.ambientLight = ambientLight; return this; diff --git a/src/main/java/fr/openmc/api/datapacks/builders/EnvironnementAttributeBuilder.java b/src/main/java/fr/openmc/api/datapacks/builders/EnvironnementAttributeBuilder.java new file mode 100644 index 000000000..b88b17ebb --- /dev/null +++ b/src/main/java/fr/openmc/api/datapacks/builders/EnvironnementAttributeBuilder.java @@ -0,0 +1,95 @@ +package fr.openmc.api.datapacks.builders; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import org.bukkit.Particle; + +import java.util.function.Consumer; + +public class EnvironnementAttributeBuilder { + private final JsonObject attributes = new JsonObject(); + + public JsonObject getOutputData() { + return attributes; + } + + public EnvironnementAttributeBuilder attributes(Consumer builder) { + JsonObject obj = new JsonObject(); + builder.accept(obj); + for (var entry : obj.entrySet()) { + this.attributes.add(entry.getKey(), entry.getValue()); + } + return this; + } + + public EnvironnementAttributeBuilder attributes(JsonObject attributes) { + for (var entry : attributes.entrySet()) { + this.attributes.add(entry.getKey(), entry.getValue()); + } + return this; + } + + /** + * Ajoute un attribut "minecraft:visual/ambient_particles" simple. + * Exemple : + * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] + */ + public EnvironnementAttributeBuilder ambientParticles(String particleType, double probability) { + JsonObject entry = new JsonObject(); + JsonObject particle = new JsonObject(); + particle.addProperty("type", particleType); + entry.add("particle", particle); + entry.addProperty("probability", probability); + + String key = "minecraft:visual/ambient_particles"; + if (this.attributes.has(key)) { + this.attributes.getAsJsonArray(key).add(entry); + } else { + JsonArray arr = new JsonArray(); + arr.add(entry); + this.attributes.add(key, arr); + } + return this; + } + + /** + * { + * "particle": { + * "type": "minecraft:dust_color_transition", + * "from_color": 16776172, + * "to_color": 16766720, + * "scale": 1 + * }, + * "probability": 0.1 + * } + */ + public EnvironnementAttributeBuilder particleDustColorTransition(int fromColor, int toColor, float scale, double probability) { + JsonObject entry = new JsonObject(); + JsonObject particle = new JsonObject(); + particle.addProperty("type", "minecraft:dust_color_transition"); + particle.addProperty("from_color", fromColor); + particle.addProperty("to_color", toColor); + particle.addProperty("scale", scale); + entry.add("particle", particle); + entry.addProperty("probability", probability); + + String key = "minecraft:visual/ambient_particles"; + if (this.attributes.has(key)) { + this.attributes.getAsJsonArray(key).add(entry); + } else { + JsonArray arr = new JsonArray(); + arr.add(entry); + this.attributes.add(key, arr); + } + return this; + } + + /** + * Ajoute un attribut "minecraft:visual/ambient_particles" simple. + * Exemple : + * "minecraft:visual/ambient_particles": [ { "particle": { "type": "minecraft:crimson_spore" }, "probability": 0.025 } ] + */ + public EnvironnementAttributeBuilder ambientParticles(Particle particle, double probability) { + return ambientParticles(particle.getKey().toString(), probability); + } +} diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java index fe5844a5e..9dff94966 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java @@ -1,6 +1,7 @@ package fr.openmc.core.registry.ambient.contents; import fr.openmc.api.datapacks.builders.DimensionTypeBuilder; +import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; import fr.openmc.core.registry.ambient.CustomAmbient; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; @@ -15,14 +16,15 @@ public String getId() { @Override public DimensionTypeBuilder getDimensionTypeBuilder() { return new DimensionTypeBuilder() - .attributes(obj -> { - obj.addProperty("visual/ambient_light_color", "#DD37E6"); - obj.addProperty("visual/sky_color", "#DD37E6"); - obj.addProperty("visual/sky_light_color", "#3B205E"); - obj.addProperty("visual/fog_start_distance", 40); - obj.addProperty("visual/fog_end_distance", 70); - obj.addProperty("visual/sunrise_sunset_color", "#FFBB00FA"); - }) + .attributesBuilder(new EnvironnementAttributeBuilder() + .attributes(obj -> { + obj.addProperty("visual/ambient_light_color", "#DD37E6"); + obj.addProperty("visual/sky_color", "#DD37E6"); + obj.addProperty("visual/sky_light_color", "#3B205E"); + obj.addProperty("visual/fog_start_distance", 40); + obj.addProperty("visual/fog_end_distance", 70); + obj.addProperty("visual/sunrise_sunset_color", "#FFBB00FA"); + })) .defaultClock(null) .timelines((String) null) .skybox(DimensionType.Skybox.END) diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java index 8f55abecd..8d0707d18 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java @@ -1,6 +1,7 @@ package fr.openmc.core.registry.ambient.contents; import fr.openmc.api.datapacks.builders.DimensionTypeBuilder; +import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; import fr.openmc.api.datapacks.builders.TimelineBuilder; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.registry.ambient.TimelineAmbient; @@ -16,20 +17,21 @@ public String getId() { @Override public DimensionTypeBuilder getDimensionTypeBuilder() { return new DimensionTypeBuilder() - .attributes(obj -> { - obj.addProperty("visual/ambient_light_color", "#FFE75C"); - obj.addProperty("visual/sky_color", "#FFD700"); - obj.addProperty("visual/sky_light_color", "#FFE02E"); - obj.addProperty("visual/fog_color", "#6D6319"); - obj.addProperty("visual/fog_start_distance", 55); - obj.addProperty("visual/fog_end_distance", 65); - obj.addProperty("visual/sunrise_sunset_color", "#ccff5900"); - obj.addProperty("visual/cloud_height", 100); - obj.addProperty("visual/cloud_color", "#4cffde50"); - }) + .attributesBuilder(new EnvironnementAttributeBuilder() + .attributes(obj -> { + obj.addProperty("visual/ambient_light_color", "#FFE75C"); + obj.addProperty("visual/sky_color", "#FFD700"); + obj.addProperty("visual/sky_light_color", "#FFE02E"); + obj.addProperty("visual/fog_color", "#6D6319"); + obj.addProperty("visual/fog_start_distance", 55); + obj.addProperty("visual/fog_end_distance", 65); + obj.addProperty("visual/sunrise_sunset_color", "#ccff5900"); + obj.addProperty("visual/cloud_height", 100); + obj.addProperty("visual/cloud_color", "#4cffde50"); + }) + .particleDustColorTransition(16776172, 16766720, 2, 0.01)) .hasSkylight(true) - .timelines(toTimelineInjector("omc_ambient", getId())) - .particleDustColorTransition(16776172, 16766720, 2, 0.01); + .timelines(toTimelineInjector("omc_ambient", getId())); } @Override diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/HellAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/HellAmbient.java index f0a03f91a..fe24f768e 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/HellAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/HellAmbient.java @@ -1,6 +1,7 @@ package fr.openmc.core.registry.ambient.contents; import fr.openmc.api.datapacks.builders.DimensionTypeBuilder; +import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; import fr.openmc.core.registry.ambient.CustomAmbient; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; @@ -16,16 +17,17 @@ public String getId() { @Override public DimensionTypeBuilder getDimensionTypeBuilder() { return new DimensionTypeBuilder() - .attributes(obj -> { - obj.addProperty("visual/ambient_light_color", "#A3170B"); - obj.addProperty("visual/block_light_tint", "#F53200"); - obj.addProperty("visual/fog_start_distance", 10); - obj.addProperty("visual/fog_end_distance", 96); - obj.addProperty("minecraft:visual/sky_light_color", "#7a7aff"); - obj.addProperty("minecraft:visual/sky_light_factor", 0); - obj.addProperty("visual/fog_color","#5E1414"); - }) - .ambientParticles(Particle.CRIMSON_SPORE, 0.25f) + .attributesBuilder(new EnvironnementAttributeBuilder() + .attributes(obj -> { + obj.addProperty("visual/ambient_light_color", "#A3170B"); + obj.addProperty("visual/block_light_tint", "#F53200"); + obj.addProperty("visual/fog_start_distance", 10); + obj.addProperty("visual/fog_end_distance", 96); + obj.addProperty("minecraft:visual/sky_light_color", "#7a7aff"); + obj.addProperty("minecraft:visual/sky_light_factor", 0); + obj.addProperty("visual/fog_color","#5E1414"); + }) + .ambientParticles(Particle.CRIMSON_SPORE, 0.25f)) .defaultClock(null) .ambientLight(0.1f) .cardinalLight("nether") From 1907a896a59c614693b0c9b73691e408d76d0f20 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 11 Jun 2026 20:48:03 +0200 Subject: [PATCH 24/74] Add BiomeAmbient to CustomAmbient --- .../java/fr/openmc/core/ListenersManager.java | 4 +- .../core/registry/ambient/BiomeAmbient.java | 12 +++ .../core/registry/ambient/CustomAmbient.java | 30 +++++- .../ambient/CustomAmbientRegistry.java | 12 +-- .../ambient/contents/GoldenAmbient.java | 9 +- .../ambient/listeners/BiomesOnChunkLoad.java | 43 +++++++++ .../openmc/core/utils/nms/PlayerBiomeNMS.java | 93 +++++++++++++++++++ 7 files changed, 191 insertions(+), 12 deletions(-) create mode 100644 src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java create mode 100644 src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java create mode 100644 src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java diff --git a/src/main/java/fr/openmc/core/ListenersManager.java b/src/main/java/fr/openmc/core/ListenersManager.java index 5f71dc22c..8df94dfe3 100644 --- a/src/main/java/fr/openmc/core/ListenersManager.java +++ b/src/main/java/fr/openmc/core/ListenersManager.java @@ -5,6 +5,7 @@ import fr.openmc.core.features.itemsadder.SpawnerExtractorListener; import fr.openmc.core.hooks.itemsadder.ItemsAdderHook; import fr.openmc.core.listeners.*; +import fr.openmc.core.registry.ambient.listeners.BiomesOnChunkLoad; import fr.openmc.core.registry.ambient.listeners.CustomAmbientListener; import org.bukkit.Bukkit; import org.bukkit.Server; @@ -35,7 +36,8 @@ public static void init() { new NoMoreRabbit(), new ArmorListener(), new BlockBreakListener(), - new CustomAmbientListener() + new CustomAmbientListener(), + new BiomesOnChunkLoad() ); if (!OMCPlugin.isUnitTestVersion()) { diff --git a/src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java new file mode 100644 index 000000000..4dab04fdc --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java @@ -0,0 +1,12 @@ +package fr.openmc.core.registry.ambient; + +import fr.openmc.api.datapacks.builders.BiomeBuilder; +import fr.openmc.api.datapacks.injectors.BiomesInjector; + +public interface BiomeAmbient { + BiomeBuilder getBiomeBuilder(); + + default BiomesInjector toBiomeInjector(String namespace, String id) { + return new BiomesInjector(namespace).add(id, getBiomeBuilder()); + } +} diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java index faec87876..86f6d7fcc 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java @@ -3,6 +3,7 @@ import fr.openmc.api.datapacks.DatapackInjector; import fr.openmc.api.datapacks.builders.DimensionTypeBuilder; import fr.openmc.api.datapacks.injectors.DimensionTypesInjector; +import fr.openmc.core.utils.nms.PlayerBiomeNMS; import fr.openmc.core.utils.nms.PlayerRespawnNMS; import net.minecraft.core.Holder; import net.minecraft.core.Registry; @@ -13,6 +14,7 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.Level; +import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.dimension.DimensionType; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.entity.Player; @@ -25,7 +27,8 @@ public abstract class CustomAmbient { // ** UUID playerUUID -> String idAmbient public static final Map ACTIVE_AMBIENTS = new HashMap<>(); - private Holder CACHED_DIMENSION_TYPE = null; + public Holder CACHED_DIMENSION_TYPE = null; + public Holder CACHED_BIOME = null; public abstract String getId(); public abstract DimensionTypeBuilder getDimensionTypeBuilder(); @@ -59,7 +62,8 @@ public void apply(Player player) { getTransitionDimensionForPlayer(nmsPlayer) ); - //todo faudrait envoyer un biome + if (this instanceof BiomeAmbient) + PlayerBiomeNMS.sendBiomes(player, getBiome()); ACTIVE_AMBIENTS.put(player.getUniqueId(), this.getId()); } @@ -93,7 +97,7 @@ public void reset(Player player) { /** * Retire l'ambience des joueurs - * @param receivers le joueur ciblé + * @param receivers le joueur ciblé74 */ public void reset(Collection receivers) { for (Player receiver : receivers) { @@ -154,4 +158,22 @@ private Holder getDimensionType() { ); return CACHED_DIMENSION_TYPE; } -} + + private Holder getBiome() { + if (CACHED_BIOME != null) + return CACHED_BIOME; + + ResourceKey key = ResourceKey.create( + Registries.BIOME, + Identifier.fromNamespaceAndPath("omc_ambient", this.getId()) + ); + + Registry biomeRegistry = + MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BIOME); + + CACHED_BIOME = biomeRegistry.get(key).orElseThrow(() -> + new IllegalStateException("Biome omc_ambient:"+ this.getId() +" introuvable") + ); + return CACHED_BIOME; + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java index e3f6c167c..2f0b2e816 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java @@ -1,8 +1,6 @@ package fr.openmc.core.registry.ambient; import fr.openmc.api.datapacks.OMCDatapack; -import fr.openmc.api.datapacks.builders.BiomeBuilder; -import fr.openmc.api.datapacks.injectors.BiomesInjector; import fr.openmc.core.bootstrap.registries.KeyedRegistry; import fr.openmc.core.bootstrap.registries.Registry; import fr.openmc.core.registry.ambient.contents.DarkAmbient; @@ -30,15 +28,17 @@ public String key(CustomAmbient registryObject) { public void bootstrap(BootstrapContext context) throws IOException { for (CustomAmbient ambient : values()) { ambientDatapack.addInjector(ambient.toDimensionTypeInjector()); + if (ambient instanceof TimelineAmbient timelineAmbient) { ambientDatapack.addInjector(timelineAmbient.toTimelineInjector( ambientDatapack.getNamespace(), ambient.getId())); } - } - ambientDatapack.addInjector(new BiomesInjector("omc_ambient").add("empty", - new BiomeBuilder() - .grassColor("#FFD700"))); + if (ambient instanceof BiomeAmbient biomeAmbient) { + ambientDatapack.addInjector(biomeAmbient.toBiomeInjector( + ambientDatapack.getNamespace(), ambient.getId())); + } + } ambientDatapack.build(context, true); //todo: remettre ça en false } diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java index 8d0707d18..ad04906a7 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java @@ -1,14 +1,16 @@ package fr.openmc.core.registry.ambient.contents; +import fr.openmc.api.datapacks.builders.BiomeBuilder; import fr.openmc.api.datapacks.builders.DimensionTypeBuilder; import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; import fr.openmc.api.datapacks.builders.TimelineBuilder; +import fr.openmc.core.registry.ambient.BiomeAmbient; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.registry.ambient.TimelineAmbient; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; -public class GoldenAmbient extends CustomAmbient implements TimelineAmbient { +public class GoldenAmbient extends CustomAmbient implements TimelineAmbient, BiomeAmbient { @Override public String getId() { return "golden_ambient"; @@ -34,6 +36,11 @@ public DimensionTypeBuilder getDimensionTypeBuilder() { .timelines(toTimelineInjector("omc_ambient", getId())); } + @Override + public BiomeBuilder getBiomeBuilder() { + return new BiomeBuilder(); + } + @Override public TimelineBuilder getTimelineBuilder() { return new TimelineBuilder() diff --git a/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java b/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java new file mode 100644 index 000000000..569ad5eb0 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java @@ -0,0 +1,43 @@ +package fr.openmc.core.registry.ambient.listeners; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.ambient.BiomeAmbient; +import fr.openmc.core.registry.ambient.CustomAmbient; +import fr.openmc.core.utils.nms.PlayerBiomeNMS; +import io.papermc.paper.event.packet.PlayerChunkLoadEvent; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.status.ChunkStatus; +import org.bukkit.craftbukkit.CraftChunk; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +/** + * Listener qui va appliquer le biome de l'ambience d'un joueur si : + * - le joueur a une ambience + * - et que l'ambience utilise un biome ou non + */ +public class BiomesOnChunkLoad implements Listener { + + @EventHandler + public void onChunkLoad(PlayerChunkLoadEvent event) { + Player player = event.getPlayer(); + + if (!CustomAmbient.ACTIVE_AMBIENTS.containsKey(player.getUniqueId())) return; + + CustomAmbient ambientApplied = OMCRegistry.CUSTOM_AMBIENTS.getOrThrow( + CustomAmbient.ACTIVE_AMBIENTS.get(player.getUniqueId()) + ); + + if (!(ambientApplied instanceof BiomeAmbient)) return; + + ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); + ChunkAccess chunkAccess = ((CraftChunk) event.getChunk()).getHandle(ChunkStatus.FULL); + if (!(chunkAccess instanceof LevelChunk nmsChunk)) return; + + PlayerBiomeNMS.sendBiome(nmsPlayer, ambientApplied.CACHED_BIOME, nmsChunk); + } +} diff --git a/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java b/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java new file mode 100644 index 000000000..d35664822 --- /dev/null +++ b/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java @@ -0,0 +1,93 @@ +package fr.openmc.core.utils.nms; + +import fr.openmc.core.bootstrap.integration.OMCLogger; +import net.minecraft.core.Holder; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.protocol.game.ClientboundChunksBiomesPacket; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.PalettedContainer; +import net.minecraft.world.level.chunk.Strategy; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +public class PlayerBiomeNMS { + private static Field SECTION_BIOMES; + static { + try { + SECTION_BIOMES = LevelChunkSection.class.getDeclaredField("biomes"); + SECTION_BIOMES.setAccessible(true); + } catch (Exception e) { + OMCLogger.error(e.getMessage()); + } + } + + public static void sendBiome(ServerPlayer nmsPlayer, Holder biome, LevelChunk initialChunk) { + List biomeDataList = new ArrayList<>(); + LevelChunk fakeChunk = PlayerBiomeNMS.getFakeChunk( + nmsPlayer, + initialChunk, + nmsPlayer.level(), + biome + ); + ClientboundChunksBiomesPacket.ChunkBiomeData data = new ClientboundChunksBiomesPacket.ChunkBiomeData(fakeChunk); + biomeDataList.add(data); + ClientboundChunksBiomesPacket packet = new ClientboundChunksBiomesPacket(biomeDataList); + nmsPlayer.connection.send(packet); + } + + public static void sendBiomes(Player player, Holder biome) { + ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); + ServerLevel nmsWorld = nmsPlayer.level(); + + int viewDistance = nmsWorld.getServer().getPlayerList().getViewDistance(); + ChunkPos center = nmsPlayer.chunkPosition(); + List biomeDataList = new ArrayList<>(); + for (int cx = center.x() - viewDistance; cx <= center.x() + viewDistance; cx++) { + for (int cz = center.z() - viewDistance; cz <= center.z() + viewDistance; cz++) { + LevelChunk chunk = nmsWorld.getChunkIfLoaded(cx, cz); + if (chunk == null) continue; + + LevelChunk fakeChunk = PlayerBiomeNMS.getFakeChunk(nmsPlayer, chunk, nmsWorld, biome); + + ClientboundChunksBiomesPacket.ChunkBiomeData data = new ClientboundChunksBiomesPacket.ChunkBiomeData(fakeChunk); + biomeDataList.add(data); + } + } + + ClientboundChunksBiomesPacket packet = new ClientboundChunksBiomesPacket(biomeDataList); + nmsPlayer.connection.send(packet); + } + + public static LevelChunk getFakeChunk(ServerPlayer nmsPlayer, LevelChunk original, ServerLevel level, Holder biome) { + LevelChunk fakeChunk = new LevelChunk(level, original.getPos()); + + LevelChunkSection[] originalSections = original.getSections(); + LevelChunkSection[] fakeSections = fakeChunk.getSections(); + + for (int i = 0; i < originalSections.length; i++) { + PalettedContainer> container = new PalettedContainer<>( + biome, + Strategy.createForBiomes(nmsPlayer.level() + .registryAccess().lookupOrThrow(Registries.BIOME).asHolderIdMap()), + null + ); + + try { + SECTION_BIOMES.set(fakeSections[i], container); + } catch (IllegalAccessException e) { + OMCLogger.error("Erreur d'acces à l'attribut biomes d'un levelChunkSetcion"); + } + } + + return fakeChunk; + } +} From 206d00cd809e9d911fbdf6562f7f407330bb745d Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:50:01 +0200 Subject: [PATCH 25/74] ri1 --- .../fr/openmc/core/hooks/itemsadder/ItemsAdderHook.java | 6 +++--- .../openmc/core/utils/text/messages/TranslationManager.java | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/fr/openmc/core/hooks/itemsadder/ItemsAdderHook.java b/src/main/java/fr/openmc/core/hooks/itemsadder/ItemsAdderHook.java index 8d2145c1b..c7f7b54ff 100644 --- a/src/main/java/fr/openmc/core/hooks/itemsadder/ItemsAdderHook.java +++ b/src/main/java/fr/openmc/core/hooks/itemsadder/ItemsAdderHook.java @@ -87,9 +87,9 @@ public static void loadContents() { */ public static void copyContentsToItemsAdder(BootstrapContext context, String contentsName) { try { - File pluginsDir = context.getDataDirectory().toFile().getParentFile(); // * root/pluigns - File itemsAdderDir = new File(pluginsDir, "ItemsAdder"); // * root/pluigns/ItemsAdder - File contentDir = new File(itemsAdderDir, CONTENTS_FOLDER_NAME); // * root/pluigns/ItemsAdder/contents + File pluginsDir = context.getDataDirectory().toFile().getParentFile(); // * root/plugins + File itemsAdderDir = new File(pluginsDir, "ItemsAdder"); // * root/plugins/ItemsAdder + File contentDir = new File(itemsAdderDir, CONTENTS_FOLDER_NAME); // * root/plugins/ItemsAdder/contents if (!FilesUtils.createDirectoryIfNotExists(contentDir)) { OMCLogger.error("Impossible de créer le dossier {}", contentDir.getAbsolutePath()); diff --git a/src/main/java/fr/openmc/core/utils/text/messages/TranslationManager.java b/src/main/java/fr/openmc/core/utils/text/messages/TranslationManager.java index 4465a54ff..4c92818ab 100644 --- a/src/main/java/fr/openmc/core/utils/text/messages/TranslationManager.java +++ b/src/main/java/fr/openmc/core/utils/text/messages/TranslationManager.java @@ -25,7 +25,6 @@ */ @SuppressWarnings("UnstableApiUsage") public class TranslationManager { - /** Traductions de fallback (langue par défaut du serveur - Français) */ public static Map fallbackTranslations = new HashMap<>(); private static final Gson GSON = new GsonBuilder() @@ -46,7 +45,7 @@ public static void init(BootstrapContext context, Locale defaultLang, Locale... // * Generate resource pack Path resourcePackFolder; try { - resourcePackFolder=ResourcePacksGenerator.generateBase(context, "generated-rp-langs"); + resourcePackFolder = ResourcePacksGenerator.generateBase(context, "generated-rp-langs"); Files.createDirectories(resourcePackFolder.resolve("assets/minecraft/lang")); OMCLogger.successFormatted("Génération du resource pack de langues !"); } catch (Exception e) { From 997236998b1e58596a2d68ec64aef6e108861cd4 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Fri, 12 Jun 2026 16:42:53 +0200 Subject: [PATCH 26/74] part 2 : Fixes Environnement Attribute + Add Effects Attributes (grass_color, water_color, foliage_color, ...) + Datapack loaded in runtime so server restarting for updating registries. --- .../fr/openmc/api/datapacks/OMCDatapack.java | 40 ++++++- .../api/datapacks/builders/BiomeBuilder.java | 35 ++++-- src/main/java/fr/openmc/core/OMCPlugin.java | 3 + src/main/java/fr/openmc/core/OMCRegistry.java | 10 +- .../registries/LifecycleRegistry.java | 4 +- .../core/registry/ambient/BiomeAmbient.java | 55 +++++++++ .../core/registry/ambient/CustomAmbient.java | 13 +- .../ambient/CustomAmbientRegistry.java | 66 ++++++++-- .../ambient/RegistriesLoadConfig.java | 46 +++++++ .../ambient/contents/GoldenAmbient.java | 6 +- .../ambient/listeners/BiomesOnChunkLoad.java | 3 +- .../java/fr/openmc/core/utils/FilesUtils.java | 25 ++-- .../java/fr/openmc/core/utils/MathUtils.java | 9 ++ .../openmc/core/utils/nms/PlayerBiomeNMS.java | 113 +++++++++++++++++- 14 files changed, 381 insertions(+), 47 deletions(-) create mode 100644 src/main/java/fr/openmc/core/registry/ambient/RegistriesLoadConfig.java diff --git a/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java b/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java index b617676c8..fcaff0c9c 100644 --- a/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java +++ b/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java @@ -1,10 +1,13 @@ package fr.openmc.api.datapacks; import fr.openmc.api.datapacks.injectors.PackMetadataInjector; +import fr.openmc.core.OMCPlugin; import fr.openmc.core.utils.FilesUtils; +import io.papermc.paper.datapack.DatapackManager; import io.papermc.paper.plugin.bootstrap.BootstrapContext; import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; import lombok.Getter; +import org.bukkit.Bukkit; import java.io.IOException; import java.net.URI; @@ -20,28 +23,29 @@ public class OMCDatapack { private final String namespace; private final Set injectors = new HashSet<>(); + private final String ID_DATAPACK = "datapacks-openmc"; + private final DatapackManager DATAPACK_MANAGER = OMCPlugin.getInstance().getServer().getDatapackManager(); + public OMCDatapack(String packName, String namespace) { this.packName = packName; this.namespace = namespace; } - public void build(BootstrapContext context, boolean generateFiles) throws IOException { - String idDatapacks = "datapacks-openmc"; + public void buildBootstrap(BootstrapContext context, boolean generateFiles) throws IOException { Path dir; if (generateFiles) { - dir = context.getDataDirectory().resolve(idDatapacks); + dir = context.getDataDirectory().resolve(ID_DATAPACK); FilesUtils.deleteDirectory(dir.toFile()); Files.createDirectories(dir); } else { - dir = Files.createTempDirectory(idDatapacks); + dir = Files.createTempDirectory(ID_DATAPACK); } runInjector(dir, new PackMetadataInjector()); for (DatapackInjector injector : injectors) { - System.out.println(injector.getClass().getSimpleName()); runInjector(dir, injector); } @@ -58,6 +62,32 @@ public void build(BootstrapContext context, boolean generateFiles) throws IOExce )); } + /** + * Dangeureux à utiliser, veillez bien que serveur restart apres, car les registres nms de minecraft + * (pas reloadable, ex worldgen/biome et worldgen/..) ne peuvent pas etre reload. et donc vous pourrez pas acceder à vos valeures + * @param onBuilded execute une action lorsque le datapack est build (par ex redemarrer le serveur si y'a des registres pas reloadable affecté) + * @throws IOException + */ + public void buildRuntime(Runnable onBuilded) throws IOException { + Path dir = OMCPlugin.getInstance().getServer().getLevelDirectory().resolve("datapacks").resolve(ID_DATAPACK); + + cleanup(); + Files.createDirectories(dir); + + runInjector(dir, new PackMetadataInjector()); + + for (DatapackInjector injector : injectors) { + runInjector(dir, injector); + } + + Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), onBuilded, 20L); + } + + public void cleanup() throws IOException { + Path dir = OMCPlugin.getInstance().getServer().getLevelDirectory().resolve("datapacks").resolve(ID_DATAPACK); + FilesUtils.deleteDirectory(dir.toFile()); + } + public void addInjector(DatapackInjector injector) { injectors.add(injector); } diff --git a/src/main/java/fr/openmc/api/datapacks/builders/BiomeBuilder.java b/src/main/java/fr/openmc/api/datapacks/builders/BiomeBuilder.java index 9d06e9c8a..fa577c49f 100644 --- a/src/main/java/fr/openmc/api/datapacks/builders/BiomeBuilder.java +++ b/src/main/java/fr/openmc/api/datapacks/builders/BiomeBuilder.java @@ -3,6 +3,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import lombok.Getter; import java.util.function.Consumer; @@ -30,17 +31,15 @@ public final class BiomeBuilder { private JsonObject attributes = new JsonObject(); private final JsonArray carvers = new JsonArray(); + @Getter private final JsonObject effects = new JsonObject(); - { - effects.addProperty("water_color", "#3f76e4"); - } private final JsonArray features = new JsonArray(); private final JsonObject spawnCosts = new JsonObject(); private final JsonObject spawners = new JsonObject(); private String temperatureModifier = "none"; private Double creatureSpawnProbability = 0.03; - private Double downfall = 0.5; - private Double temperatures = 0.5; + private Float downfall = 0.5f; + private Float temperatures = 0.5f; private Boolean hasPrecipitation = true; public BiomeBuilder attributes(EnvironnementAttributeBuilder builder) { @@ -68,7 +67,7 @@ public BiomeBuilder creatureSpawnProbability(Double value) { return this; } - public BiomeBuilder downfall(Double value) { + public BiomeBuilder downfall(Float value) { this.downfall=value; return this; } @@ -102,6 +101,26 @@ public BiomeBuilder dryFoliageColor(String color) { return this; } + public BiomeBuilder waterColor(Integer color) { + this.effects.addProperty("water_color", color); + return this; + } + + public BiomeBuilder grassColor(Integer color) { + this.effects.addProperty("grass_color", color); + return this; + } + + public BiomeBuilder foliageColor(Integer color) { + this.effects.addProperty("foliage_color", color); + return this; + } + + public BiomeBuilder dryFoliageColor(Integer color) { + this.effects.addProperty("dry_foliage_color", color); + return this; + } + /** * Set la grass color modifier * @param id none, dark_forest, swamp @@ -135,12 +154,12 @@ public BiomeBuilder spawners(JsonObject spawners) { return this; } - public BiomeBuilder temperatures(Double value) { + public BiomeBuilder temperatures(Float value) { this.temperatures=value; return this; } - public BiomeBuilder temperatures(Boolean bool) { + public BiomeBuilder hasPrecipitation(Boolean bool) { this.hasPrecipitation=bool; return this; } diff --git a/src/main/java/fr/openmc/core/OMCPlugin.java b/src/main/java/fr/openmc/core/OMCPlugin.java index 338cd9fa3..d6473bde6 100644 --- a/src/main/java/fr/openmc/core/OMCPlugin.java +++ b/src/main/java/fr/openmc/core/OMCPlugin.java @@ -217,6 +217,9 @@ public void onDisable() { feature.startSave(); } + /* REGISTRIES */ + OMCRegistry.stopAll(); + // - Close all inventories for (Player player : Bukkit.getOnlinePlayers()) { player.closeInventory(); diff --git a/src/main/java/fr/openmc/core/OMCRegistry.java b/src/main/java/fr/openmc/core/OMCRegistry.java index c019a67d4..6a8e80090 100644 --- a/src/main/java/fr/openmc/core/OMCRegistry.java +++ b/src/main/java/fr/openmc/core/OMCRegistry.java @@ -41,7 +41,7 @@ public final class OMCRegistry { RegistryLoadingType.AFTER_IA), new RegistryContext( () -> CUSTOM_AMBIENTS = new CustomAmbientRegistry(), - RegistryLoadingType.BOOTSTRAP), + RegistryLoadingType.RUNTIME), new RegistryContext( () -> CUSTOM_LOOTBOXES = new CustomLootboxRegistry(), RegistryLoadingType.AFTER_IA) @@ -86,4 +86,12 @@ public static void postInitAll() { OMCLogger.successFormatted("Registre {} chargé après ItemsAdder", r.getClass().getSimpleName()); } } + + public static void stopAll() { + for (RegistryContext ctx : OMCRegistry.ALL) { + LifecycleRegistry r = ctx.registry().get(); + r.stop(); + OMCLogger.successFormatted("Registre {} stoppé", r.getClass().getSimpleName()); + } + } } \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/bootstrap/registries/LifecycleRegistry.java b/src/main/java/fr/openmc/core/bootstrap/registries/LifecycleRegistry.java index 541e7a503..506ca7f96 100644 --- a/src/main/java/fr/openmc/core/bootstrap/registries/LifecycleRegistry.java +++ b/src/main/java/fr/openmc/core/bootstrap/registries/LifecycleRegistry.java @@ -7,8 +7,8 @@ @SuppressWarnings("UnstableApiUsage") public interface LifecycleRegistry { default void bootstrap(BootstrapContext context) throws IOException {} - default void init() {} - default void postInit() {} + + default void stop() {} } diff --git a/src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java index 4dab04fdc..b8be15d46 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java @@ -1,7 +1,13 @@ package fr.openmc.core.registry.ambient; +import com.google.gson.JsonObject; import fr.openmc.api.datapacks.builders.BiomeBuilder; import fr.openmc.api.datapacks.injectors.BiomesInjector; +import fr.openmc.core.utils.MathUtils; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.BiomeSpecialEffects; + +import java.util.Optional; public interface BiomeAmbient { BiomeBuilder getBiomeBuilder(); @@ -9,4 +15,53 @@ public interface BiomeAmbient { default BiomesInjector toBiomeInjector(String namespace, String id) { return new BiomesInjector(namespace).add(id, getBiomeBuilder()); } + + /** + * Genere une variante d'un biome en fonction d'une ambience (namespace:id) + * Retourne un injecteur de biome qui prendra une variante de celui ci + * (couleur de l'herbe initial si pas override par l'ambience, idem pour les autres) + * @param initialBiome le biome initial à cloner + * @param namespace le namespace de l'ambience (généralement "omc_ambient") + * @param id l'id de l'ambience + * @return l'injecteur du fichier json + */ + default BiomesInjector toBiomeVariant(Biome initialBiome, String namespace, String id) { + BiomeSpecialEffects initialEffects = initialBiome.getSpecialEffects(); + Biome.ClimateSettings climate = initialBiome.climateSettings; + + JsonObject effects = getBiomeBuilder().getEffects(); + Optional grassColor = hasEffects(effects, "grass_color") ? + Optional.of(MathUtils.hexToInt(effects.get("grass_color").getAsString())) : + initialEffects.grassColorOverride(); + Optional foliageColor = hasEffects(effects, "foliage_color") ? + Optional.of(MathUtils.hexToInt(effects.get("foliage_color").getAsString())) : + initialEffects.foliageColorOverride(); + Integer waterColor = hasEffects(effects, "water_color") ? + MathUtils.hexToInt(effects.get("water_color").getAsString()) : + initialEffects.grassColorOverride().orElse(4159204); + Optional dryFoliageColor = hasEffects(effects, "dry_foliage_color") ? + Optional.of(MathUtils.hexToInt(effects.get("dry_foliage_color").getAsString())) : + initialEffects.foliageColorOverride(); + String grassColorModifier = hasEffects(effects, "grass_color_modifier") ? + effects.get("grass_color_modifier").getAsString() : + initialEffects.grassColorModifier().getName(); + + BiomeBuilder builder = new BiomeBuilder() + .waterColor(waterColor) + .grassColorModifier(grassColorModifier) + .hasPrecipitation(climate.hasPrecipitation()) + .downfall(climate.downfall()) + .temperatures(climate.temperature()) + .temperatureModifier(climate.temperatureModifier().getName()); + + grassColor.ifPresent(builder::grassColor); + foliageColor.ifPresent(builder::foliageColor); + dryFoliageColor.ifPresent(builder::dryFoliageColor); + + return new BiomesInjector(namespace).add(id, builder); + } + + private boolean hasEffects(JsonObject effects, String envKey) { + return effects.get(envKey) != null; + } } diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java index 86f6d7fcc..8357f2c23 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java @@ -27,6 +27,7 @@ public abstract class CustomAmbient { // ** UUID playerUUID -> String idAmbient public static final Map ACTIVE_AMBIENTS = new HashMap<>(); + public Holder CACHED_DIMENSION_TYPE = null; public Holder CACHED_BIOME = null; @@ -45,7 +46,7 @@ public abstract class CustomAmbient { * @return Un datapack injector */ public DatapackInjector toDimensionTypeInjector() { - return new DimensionTypesInjector("omc_ambient").add(getId(), getDimensionTypeBuilder()); + return new DimensionTypesInjector(CustomAmbientRegistry.NAMESPACE).add(getId(), getDimensionTypeBuilder()); } /** @@ -63,7 +64,7 @@ public void apply(Player player) { ); if (this instanceof BiomeAmbient) - PlayerBiomeNMS.sendBiomes(player, getBiome()); + PlayerBiomeNMS.replaceBiomes(nmsPlayer, CustomAmbientRegistry.NAMESPACE, this.getId()); ACTIVE_AMBIENTS.put(player.getUniqueId(), this.getId()); } @@ -147,14 +148,14 @@ private Holder getDimensionType() { ResourceKey key = ResourceKey.create( Registries.DIMENSION_TYPE, - Identifier.fromNamespaceAndPath("omc_ambient", this.getId()) + Identifier.fromNamespaceAndPath(CustomAmbientRegistry.NAMESPACE, this.getId()) ); Registry dimRegistry = MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.DIMENSION_TYPE); CACHED_DIMENSION_TYPE = dimRegistry.get(key).orElseThrow(() -> - new IllegalStateException("DimensionType omc_ambient:"+ this.getId() +" introuvable") + new IllegalStateException("DimensionType " + CustomAmbientRegistry.NAMESPACE + ":"+ this.getId() +" introuvable") ); return CACHED_DIMENSION_TYPE; } @@ -165,14 +166,14 @@ private Holder getBiome() { ResourceKey key = ResourceKey.create( Registries.BIOME, - Identifier.fromNamespaceAndPath("omc_ambient", this.getId()) + Identifier.fromNamespaceAndPath(CustomAmbientRegistry.NAMESPACE, this.getId()) ); Registry biomeRegistry = MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BIOME); CACHED_BIOME = biomeRegistry.get(key).orElseThrow(() -> - new IllegalStateException("Biome omc_ambient:"+ this.getId() +" introuvable") + new IllegalStateException("Biome " + CustomAmbientRegistry.NAMESPACE + ":"+ this.getId() +" introuvable") ); return CACHED_BIOME; } diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java index 2f0b2e816..8b31961ad 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java @@ -1,18 +1,24 @@ package fr.openmc.core.registry.ambient; import fr.openmc.api.datapacks.OMCDatapack; +import fr.openmc.api.datapacks.injectors.BiomesInjector; +import fr.openmc.core.bootstrap.integration.OMCLogger; import fr.openmc.core.bootstrap.registries.KeyedRegistry; import fr.openmc.core.bootstrap.registries.Registry; import fr.openmc.core.registry.ambient.contents.DarkAmbient; import fr.openmc.core.registry.ambient.contents.GoldenAmbient; import fr.openmc.core.registry.ambient.contents.HellAmbient; -import io.papermc.paper.plugin.bootstrap.BootstrapContext; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.level.biome.Biome; +import org.bukkit.Bukkit; import java.io.IOException; -@SuppressWarnings("UnstableApiUsage") public class CustomAmbientRegistry extends Registry implements KeyedRegistry { - private final OMCDatapack ambientDatapack = new OMCDatapack("openmc", "omc_ambient"); + public static final String NAMESPACE = "omc_ambient"; + private final OMCDatapack ambientDatapack = new OMCDatapack("openmc", NAMESPACE); // ** REGISTER AMBIENT ** public final CustomAmbient DARK = register(new DarkAmbient()); @@ -25,7 +31,9 @@ public String key(CustomAmbient registryObject) { } @Override - public void bootstrap(BootstrapContext context) throws IOException { + public void init() { + RegistriesLoadConfig.init(); + for (CustomAmbient ambient : values()) { ambientDatapack.addInjector(ambient.toDimensionTypeInjector()); @@ -35,11 +43,55 @@ public void bootstrap(BootstrapContext context) throws IOException { } if (ambient instanceof BiomeAmbient biomeAmbient) { - ambientDatapack.addInjector(biomeAmbient.toBiomeInjector( - ambientDatapack.getNamespace(), ambient.getId())); + net.minecraft.core.Registry biomeRegistry = + MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BIOME); + + // ** Création de chaque variante des biomes existants. + // * Renvoie simplement un biome ayant les effects (grassColor, waterColor, ...) lié au biome original + // * si ça pas été override par le biome mis par le CustomAmbient + for (var biomeEntry : biomeRegistry.entrySet()) { + ResourceKey key = biomeEntry.getKey(); + if (key.identifier().getNamespace().equals(NAMESPACE)) continue; // * On skip les biomes de notre datapack + + Biome biome = biomeEntry.getValue(); + ambientDatapack.addInjector(biomeAmbient.toBiomeVariant( + biome, ambientDatapack.getNamespace(), + key.identifier().getPath() + "_" + ambient.getId())); + } } } - ambientDatapack.build(context, true); //todo: remettre ça en false + if (RegistriesLoadConfig.isMustRestart() || checkIfAmbientChange()) { + try { + ambientDatapack.buildRuntime(() -> { + OMCLogger.warnFormatted("ATTENTION! Restart du serveur afin d'appliquer les changements dans les registres"); + Bukkit.restart(); + }); + } catch (IOException e) { + OMCLogger.error("Erreur survenue durant le build du datapack lors du runtime {}", e.getMessage()); + } + } else { + OMCLogger.infoFormatted("Aucun ambient rajouté, innutile de redémarrer le serveur"); + } + } + + private boolean checkIfAmbientChange() { + net.minecraft.core.Registry biomeRegistry = + MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BIOME); + + int numberOfAmbient = values().stream() + .filter(ambient -> ambient instanceof BiomeAmbient) + .toList().size(); + int numberOfVanillaBiome = biomeRegistry.keySet().stream() + .filter(key -> !key.getNamespace().equals(NAMESPACE)) + .toList().size(); + + int numberOfBiomeVariant = numberOfAmbient * numberOfVanillaBiome; + int numberOfBiomeVarientInDatapack = ambientDatapack.getInjectors().stream() + .filter(injector -> injector instanceof BiomesInjector).toList().size(); + + // * On regarde si notre nombre de variante de biome, est pas égale aux nombres de variente de biome dans le datapack + // si ça a changé ça veut dire qu'il y a des nouveaux biomes ou des nouvelles ambiences + return numberOfBiomeVariant != numberOfBiomeVarientInDatapack; } } diff --git a/src/main/java/fr/openmc/core/registry/ambient/RegistriesLoadConfig.java b/src/main/java/fr/openmc/core/registry/ambient/RegistriesLoadConfig.java new file mode 100644 index 000000000..539db8dd9 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/ambient/RegistriesLoadConfig.java @@ -0,0 +1,46 @@ +package fr.openmc.core.registry.ambient; + +import fr.openmc.core.OMCPlugin; +import fr.openmc.core.bootstrap.integration.OMCLogger; +import lombok.Getter; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; + +/** + * Cette configuration gère le restart de serveur apres la génération du datapack dans le runtime + *

+ * Explication : + * - Lorsqu'on génère un datapack dans le runtime, les changements ne sont pas appliqués dans les registry de minecraft + * - C'est pourquoi il faut redem le serveur afin que le datapack puisse bien entrer dans le registre. + * - Donc cela nécessite 2 lancements pour faire tourner une premiere fois le plugin. + */ +public class RegistriesLoadConfig { + private static File registriesConfigFile; + private static FileConfiguration registriesConfig; + @Getter + private static boolean mustRestart; + + public static void init() { + registriesConfigFile = new File(OMCPlugin.getInstance().getDataFolder() + "/data/registry", "load.yml"); + registriesConfig = YamlConfiguration.loadConfiguration(registriesConfigFile); + + // * Premier lancement du plugin où suppression du fichier par une classe externe (ex CustomAmbientRegistry) + if (!registriesConfigFile.exists()) { + mustRestart = true; + saveConfig(); + } else { + mustRestart = false; + } + } + + private static void saveConfig() { + try { + registriesConfig.save(registriesConfigFile); + } catch (IOException e) { + OMCLogger.error("Cannot save registriesConfigFile", e); + } + } +} diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java index ad04906a7..0316740a9 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java @@ -6,6 +6,7 @@ import fr.openmc.api.datapacks.builders.TimelineBuilder; import fr.openmc.core.registry.ambient.BiomeAmbient; import fr.openmc.core.registry.ambient.CustomAmbient; +import fr.openmc.core.registry.ambient.CustomAmbientRegistry; import fr.openmc.core.registry.ambient.TimelineAmbient; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; @@ -33,12 +34,13 @@ public DimensionTypeBuilder getDimensionTypeBuilder() { }) .particleDustColorTransition(16776172, 16766720, 2, 0.01)) .hasSkylight(true) - .timelines(toTimelineInjector("omc_ambient", getId())); + .timelines(toTimelineInjector(CustomAmbientRegistry.NAMESPACE, getId())); } @Override public BiomeBuilder getBiomeBuilder() { - return new BiomeBuilder(); + return new BiomeBuilder() + .waterColor("#3f76e4"); } @Override diff --git a/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java b/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java index 569ad5eb0..2265f4b7f 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java +++ b/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java @@ -3,6 +3,7 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.ambient.BiomeAmbient; import fr.openmc.core.registry.ambient.CustomAmbient; +import fr.openmc.core.registry.ambient.CustomAmbientRegistry; import fr.openmc.core.utils.nms.PlayerBiomeNMS; import io.papermc.paper.event.packet.PlayerChunkLoadEvent; import net.minecraft.server.level.ServerPlayer; @@ -38,6 +39,6 @@ public void onChunkLoad(PlayerChunkLoadEvent event) { ChunkAccess chunkAccess = ((CraftChunk) event.getChunk()).getHandle(ChunkStatus.FULL); if (!(chunkAccess instanceof LevelChunk nmsChunk)) return; - PlayerBiomeNMS.sendBiome(nmsPlayer, ambientApplied.CACHED_BIOME, nmsChunk); + PlayerBiomeNMS.remplaceBiome(nmsPlayer, nmsChunk, CustomAmbientRegistry.NAMESPACE, ambientApplied.getId()); } } diff --git a/src/main/java/fr/openmc/core/utils/FilesUtils.java b/src/main/java/fr/openmc/core/utils/FilesUtils.java index ad79f91fd..dc7711f16 100644 --- a/src/main/java/fr/openmc/core/utils/FilesUtils.java +++ b/src/main/java/fr/openmc/core/utils/FilesUtils.java @@ -16,6 +16,7 @@ import java.util.function.Function; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.util.stream.Stream; /** * Utilitaires pour la gestion des fichiers et dossiers @@ -38,17 +39,21 @@ public class FilesUtils { * @throws IOException Si une erreur survient lors de la suppression */ public static void deleteDirectory(File dir) throws IOException { - if (!dir.exists()) return; + if (!dir.exists()) { + OMCLogger.warn("Dossier introuvable : " + dir.getAbsolutePath()); + return; + } - Files.walk(Paths.get(dir.getAbsolutePath())) - .sorted(Comparator.reverseOrder()) - .forEach(path -> { - try { - Files.delete(path); - } catch (IOException e) { - OMCLogger.warn("Impossible de supprimer: {}", path, e); - } - }); + try (Stream stream = Files.walk(dir.toPath())) { + stream.sorted(Comparator.reverseOrder()) + .forEach(path -> { + try { + Files.delete(path); + } catch (IOException e) { + OMCLogger.warn("Impossible de supprimer: {}", path, e); + } + }); + } } /** diff --git a/src/main/java/fr/openmc/core/utils/MathUtils.java b/src/main/java/fr/openmc/core/utils/MathUtils.java index be7462627..89bd43279 100644 --- a/src/main/java/fr/openmc/core/utils/MathUtils.java +++ b/src/main/java/fr/openmc/core/utils/MathUtils.java @@ -26,4 +26,13 @@ public static int lerpColor(int startColor, int endColor, double t) { return (r << 16) | (g << 8) | b; } + /** + * Convertit une hexa en entier, utilise la méthode de Integer + * @param hexa un héxadécimal (ex #000000) + * @return un entier representant l'hexa décimal + */ + public static int hexToInt(String hexa) { + return Integer.parseInt(hexa.replace("#", ""), 16); + } + } diff --git a/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java b/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java index d35664822..20e206ea8 100644 --- a/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java +++ b/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java @@ -2,8 +2,10 @@ import fr.openmc.core.bootstrap.integration.OMCLogger; import net.minecraft.core.Holder; +import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.network.protocol.game.ClientboundChunksBiomesPacket; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.ChunkPos; @@ -30,10 +32,15 @@ public class PlayerBiomeNMS { } } + /** + * Envoie un simple biome sur un chunk + * @param nmsPlayer Le joueur à envoyer les changements + * @param biome le biome a envoyer + * @param initialChunk le chunk a remplacer le biome + */ public static void sendBiome(ServerPlayer nmsPlayer, Holder biome, LevelChunk initialChunk) { List biomeDataList = new ArrayList<>(); LevelChunk fakeChunk = PlayerBiomeNMS.getFakeChunk( - nmsPlayer, initialChunk, nmsPlayer.level(), biome @@ -44,6 +51,11 @@ public static void sendBiome(ServerPlayer nmsPlayer, Holder biome, LevelC nmsPlayer.connection.send(packet); } + /** + * Actualise tout les biomes au alentour (dans la view distance du joueur) + * @param player le joueur a envoyer le changement de biome + * @param biome le biome a afficher + */ public static void sendBiomes(Player player, Holder biome) { ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); ServerLevel nmsWorld = nmsPlayer.level(); @@ -56,7 +68,7 @@ public static void sendBiomes(Player player, Holder biome) { LevelChunk chunk = nmsWorld.getChunkIfLoaded(cx, cz); if (chunk == null) continue; - LevelChunk fakeChunk = PlayerBiomeNMS.getFakeChunk(nmsPlayer, chunk, nmsWorld, biome); + LevelChunk fakeChunk = PlayerBiomeNMS.getFakeChunk(chunk, nmsWorld, biome); ClientboundChunksBiomesPacket.ChunkBiomeData data = new ClientboundChunksBiomesPacket.ChunkBiomeData(fakeChunk); biomeDataList.add(data); @@ -67,7 +79,55 @@ public static void sendBiomes(Player player, Holder biome) { nmsPlayer.connection.send(packet); } - public static LevelChunk getFakeChunk(ServerPlayer nmsPlayer, LevelChunk original, ServerLevel level, Holder biome) { + /** + * Remplace un simple biome par + * @param nmsPlayer Le joueur à envoyer les changements + * @param namespace le namespace du biome a envoyer + * @param id le id du biome a envoyer + * @param initialChunk le chunk a remplacer le biome + */ + public static void remplaceBiome(ServerPlayer nmsPlayer, LevelChunk initialChunk, String namespace, String id) { + List biomeDataList = new ArrayList<>(); + LevelChunk fakeChunk = PlayerBiomeNMS.getFakeChunkWithMapping( + initialChunk, + nmsPlayer.level(), + namespace, + id + ); + ClientboundChunksBiomesPacket.ChunkBiomeData data = new ClientboundChunksBiomesPacket.ChunkBiomeData(fakeChunk); + biomeDataList.add(data); + ClientboundChunksBiomesPacket packet = new ClientboundChunksBiomesPacket(biomeDataList); + nmsPlayer.connection.send(packet); + } + + public static void replaceBiomes(ServerPlayer nmsPlayer, String namespace, String id) { + ServerLevel nmsWorld = nmsPlayer.level(); + + int viewDistance = nmsWorld.getServer().getPlayerList().getViewDistance(); + ChunkPos center = nmsPlayer.chunkPosition(); + List biomeDataList = new ArrayList<>(); + + for (int cx = center.x() - viewDistance; cx <= center.x() + viewDistance; cx++) { + for (int cz = center.z() - viewDistance; cz <= center.z() + viewDistance; cz++) { + LevelChunk chunk = nmsWorld.getChunkIfLoaded(cx, cz); + if (chunk == null) continue; + + LevelChunk fakeChunk = getFakeChunkWithMapping(chunk, nmsWorld, namespace, id); + biomeDataList.add(new ClientboundChunksBiomesPacket.ChunkBiomeData(fakeChunk)); + } + } + + nmsPlayer.connection.send(new ClientboundChunksBiomesPacket(biomeDataList)); + } + + /** + * Crée un faux chunk en se basant sur l'originel et en changeant juste le biome du chunk + * @param original le chunk original + * @param level le monde ou y'a le chunk + * @param biome le biome a injecter dans le faux chunk + * @return le faux chunk avec le biome + */ + public static LevelChunk getFakeChunk(LevelChunk original, ServerLevel level, Holder biome) { LevelChunk fakeChunk = new LevelChunk(level, original.getPos()); LevelChunkSection[] originalSections = original.getSections(); @@ -76,8 +136,7 @@ public static LevelChunk getFakeChunk(ServerPlayer nmsPlayer, LevelChunk origina for (int i = 0; i < originalSections.length; i++) { PalettedContainer> container = new PalettedContainer<>( biome, - Strategy.createForBiomes(nmsPlayer.level() - .registryAccess().lookupOrThrow(Registries.BIOME).asHolderIdMap()), + Strategy.createForBiomes(level.registryAccess().lookupOrThrow(Registries.BIOME).asHolderIdMap()), null ); @@ -90,4 +149,48 @@ public static LevelChunk getFakeChunk(ServerPlayer nmsPlayer, LevelChunk origina return fakeChunk; } + + private static LevelChunk getFakeChunkWithMapping( + LevelChunk original, + ServerLevel nmsWorld, + String namespace, + String id) { + + LevelChunk fake = new LevelChunk(nmsWorld, original.getPos()); + LevelChunkSection[] originalSections = original.getSections(); + LevelChunkSection[] fakeSections = fake.getSections(); + + for (int i = 0; i < originalSections.length; i++) { + LevelChunkSection originalSection = originalSections[i]; + + PalettedContainer> fakeBiomes = new PalettedContainer<>( + originalSection.getNoiseBiome(0,0,0), + Strategy.createForBiomes(nmsWorld.registryAccess().lookupOrThrow(Registries.BIOME).asHolderIdMap()), + null + ); + + Registry registry = nmsWorld.registryAccess().lookupOrThrow(Registries.BIOME); + + for (int x = 0; x < 4; x++) { + for (int y = 0; y < 4; y++) { + for (int z = 0; z < 4; z++) { + Holder originalBiome = originalSection.getNoiseBiome(x, y, z); + // todo: faire directement in Identifier + String keyMapped = namespace + ":" + + originalBiome.unwrapKey().orElseThrow().identifier().getPath() + "_" + id; + + Holder mapped = registry.get(Identifier.parse(keyMapped)).orElseThrow(() -> + new IllegalStateException("Biome " + keyMapped + " introuvable dans le registre") + ); + + fakeBiomes.set(x, y, z, mapped); + } + } + } + + fakeSections[i] = new LevelChunkSection(originalSection.getStates(), fakeBiomes); + } + + return fake; + } } From e55747a77e1fdce4dab1a851b9a12eaf2f8048cc Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Fri, 12 Jun 2026 17:04:33 +0200 Subject: [PATCH 27/74] remplace param namespace and id to Identifier --- .../core/registry/ambient/BiomeAmbient.java | 22 ++++++--- .../core/registry/ambient/CustomAmbient.java | 5 +- .../ambient/CustomAmbientRegistry.java | 3 +- .../ambient/listeners/BiomesOnChunkLoad.java | 8 ++-- .../openmc/core/utils/nms/PlayerBiomeNMS.java | 46 ++++++++++--------- 5 files changed, 50 insertions(+), 34 deletions(-) diff --git a/src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java index b8be15d46..d328143ac 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java @@ -4,6 +4,7 @@ import fr.openmc.api.datapacks.builders.BiomeBuilder; import fr.openmc.api.datapacks.injectors.BiomesInjector; import fr.openmc.core.utils.MathUtils; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeSpecialEffects; @@ -12,8 +13,18 @@ public interface BiomeAmbient { BiomeBuilder getBiomeBuilder(); - default BiomesInjector toBiomeInjector(String namespace, String id) { - return new BiomesInjector(namespace).add(id, getBiomeBuilder()); + default BiomesInjector toBiomeInjector(Identifier ambientId) { + return new BiomesInjector(ambientId.getNamespace()).add(ambientId.getPath(), getBiomeBuilder()); + } + + /** + * Genere la clé de la variente du biome + * @param initialBiomeKey clé du biome initial a changer + * @param ambient l'ambience qui génère la variante + * @return identifiant de la variante du biome (namespace:initialBiomePath_ambientId) + */ + default Identifier toBiomeVariantKey(Identifier initialBiomeKey, CustomAmbient ambient) { + return Identifier.parse(CustomAmbientRegistry.NAMESPACE + ":" + initialBiomeKey.getPath() + "_" + ambient.getId()); } /** @@ -21,11 +32,10 @@ default BiomesInjector toBiomeInjector(String namespace, String id) { * Retourne un injecteur de biome qui prendra une variante de celui ci * (couleur de l'herbe initial si pas override par l'ambience, idem pour les autres) * @param initialBiome le biome initial à cloner - * @param namespace le namespace de l'ambience (généralement "omc_ambient") - * @param id l'id de l'ambience + * @param ambientId l'id de l'ambience * @return l'injecteur du fichier json */ - default BiomesInjector toBiomeVariant(Biome initialBiome, String namespace, String id) { + default BiomesInjector toBiomeVariant(Biome initialBiome, Identifier ambientId) { BiomeSpecialEffects initialEffects = initialBiome.getSpecialEffects(); Biome.ClimateSettings climate = initialBiome.climateSettings; @@ -58,7 +68,7 @@ default BiomesInjector toBiomeVariant(Biome initialBiome, String namespace, Stri foliageColor.ifPresent(builder::foliageColor); dryFoliageColor.ifPresent(builder::dryFoliageColor); - return new BiomesInjector(namespace).add(id, builder); + return new BiomesInjector(ambientId.getNamespace()).add(ambientId.getPath(), builder); } private boolean hasEffects(JsonObject effects, String envKey) { diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java index 8357f2c23..97a63ecc0 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java @@ -63,8 +63,9 @@ public void apply(Player player) { getTransitionDimensionForPlayer(nmsPlayer) ); - if (this instanceof BiomeAmbient) - PlayerBiomeNMS.replaceBiomes(nmsPlayer, CustomAmbientRegistry.NAMESPACE, this.getId()); + if (this instanceof BiomeAmbient biomeAmbient) + PlayerBiomeNMS.replaceBiomes(nmsPlayer, + (biomeVarientKey) -> biomeAmbient.toBiomeVariantKey(biomeVarientKey, this)); ACTIVE_AMBIENTS.put(player.getUniqueId(), this.getId()); } diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java index 8b31961ad..3ee04ab84 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java @@ -55,8 +55,7 @@ public void init() { Biome biome = biomeEntry.getValue(); ambientDatapack.addInjector(biomeAmbient.toBiomeVariant( - biome, ambientDatapack.getNamespace(), - key.identifier().getPath() + "_" + ambient.getId())); + biome, biomeAmbient.toBiomeVariantKey(key.identifier(), ambient))); } } } diff --git a/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java b/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java index 2265f4b7f..08e038870 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java +++ b/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java @@ -3,7 +3,6 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.ambient.BiomeAmbient; import fr.openmc.core.registry.ambient.CustomAmbient; -import fr.openmc.core.registry.ambient.CustomAmbientRegistry; import fr.openmc.core.utils.nms.PlayerBiomeNMS; import io.papermc.paper.event.packet.PlayerChunkLoadEvent; import net.minecraft.server.level.ServerPlayer; @@ -33,12 +32,15 @@ public void onChunkLoad(PlayerChunkLoadEvent event) { CustomAmbient.ACTIVE_AMBIENTS.get(player.getUniqueId()) ); - if (!(ambientApplied instanceof BiomeAmbient)) return; + if (!(ambientApplied instanceof BiomeAmbient biomeAmbient)) return; ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); ChunkAccess chunkAccess = ((CraftChunk) event.getChunk()).getHandle(ChunkStatus.FULL); if (!(chunkAccess instanceof LevelChunk nmsChunk)) return; - PlayerBiomeNMS.remplaceBiome(nmsPlayer, nmsChunk, CustomAmbientRegistry.NAMESPACE, ambientApplied.getId()); + PlayerBiomeNMS.remplaceBiome(nmsPlayer, nmsChunk, (initialBiomeKey) -> biomeAmbient.toBiomeVariantKey( + initialBiomeKey, + ambientApplied + )); } } diff --git a/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java b/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java index 20e206ea8..756730ef6 100644 --- a/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java +++ b/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java @@ -20,6 +20,7 @@ import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; +import java.util.function.Function; public class PlayerBiomeNMS { private static Field SECTION_BIOMES; @@ -80,19 +81,19 @@ public static void sendBiomes(Player player, Holder biome) { } /** - * Remplace un simple biome par + * Remplace un simple biome par un id de biome transformé par identifierModifier * @param nmsPlayer Le joueur à envoyer les changements - * @param namespace le namespace du biome a envoyer - * @param id le id du biome a envoyer + * @param identifierModifier la clé du biome a modifier * @param initialChunk le chunk a remplacer le biome */ - public static void remplaceBiome(ServerPlayer nmsPlayer, LevelChunk initialChunk, String namespace, String id) { + public static void remplaceBiome( + ServerPlayer nmsPlayer, + LevelChunk initialChunk, + Function identifierModifier) { List biomeDataList = new ArrayList<>(); LevelChunk fakeChunk = PlayerBiomeNMS.getFakeChunkWithMapping( initialChunk, - nmsPlayer.level(), - namespace, - id + identifierModifier ); ClientboundChunksBiomesPacket.ChunkBiomeData data = new ClientboundChunksBiomesPacket.ChunkBiomeData(fakeChunk); biomeDataList.add(data); @@ -100,7 +101,7 @@ public static void remplaceBiome(ServerPlayer nmsPlayer, LevelChunk initialChunk nmsPlayer.connection.send(packet); } - public static void replaceBiomes(ServerPlayer nmsPlayer, String namespace, String id) { + public static void replaceBiomes(ServerPlayer nmsPlayer, Function identifierModifier) { ServerLevel nmsWorld = nmsPlayer.level(); int viewDistance = nmsWorld.getServer().getPlayerList().getViewDistance(); @@ -112,7 +113,7 @@ public static void replaceBiomes(ServerPlayer nmsPlayer, String namespace, Strin LevelChunk chunk = nmsWorld.getChunkIfLoaded(cx, cz); if (chunk == null) continue; - LevelChunk fakeChunk = getFakeChunkWithMapping(chunk, nmsWorld, namespace, id); + LevelChunk fakeChunk = getFakeChunkWithMapping(chunk, identifierModifier); biomeDataList.add(new ClientboundChunksBiomesPacket.ChunkBiomeData(fakeChunk)); } } @@ -149,14 +150,18 @@ public static LevelChunk getFakeChunk(LevelChunk original, ServerLevel level, Ho return fakeChunk; } - + /** + * Crée un faux chunk en se basant sur l'originel et en changeant juste le biome du chunk en fonction + * d'un identifierModifier + * @param original le chunk original + * @param identifierModifier le modifier d'identifiant + * @return le faux chunk avec biomes modifiés + */ private static LevelChunk getFakeChunkWithMapping( LevelChunk original, - ServerLevel nmsWorld, - String namespace, - String id) { + Function identifierModifier) { - LevelChunk fake = new LevelChunk(nmsWorld, original.getPos()); + LevelChunk fake = new LevelChunk(original.level, original.getPos()); LevelChunkSection[] originalSections = original.getSections(); LevelChunkSection[] fakeSections = fake.getSections(); @@ -165,22 +170,21 @@ private static LevelChunk getFakeChunkWithMapping( PalettedContainer> fakeBiomes = new PalettedContainer<>( originalSection.getNoiseBiome(0,0,0), - Strategy.createForBiomes(nmsWorld.registryAccess().lookupOrThrow(Registries.BIOME).asHolderIdMap()), + Strategy.createForBiomes(original.level.registryAccess().lookupOrThrow(Registries.BIOME).asHolderIdMap()), null ); - Registry registry = nmsWorld.registryAccess().lookupOrThrow(Registries.BIOME); + Registry registry = original.level.registryAccess().lookupOrThrow(Registries.BIOME); for (int x = 0; x < 4; x++) { for (int y = 0; y < 4; y++) { for (int z = 0; z < 4; z++) { Holder originalBiome = originalSection.getNoiseBiome(x, y, z); - // todo: faire directement in Identifier - String keyMapped = namespace + ":" + - originalBiome.unwrapKey().orElseThrow().identifier().getPath() + "_" + id; - Holder mapped = registry.get(Identifier.parse(keyMapped)).orElseThrow(() -> - new IllegalStateException("Biome " + keyMapped + " introuvable dans le registre") + Identifier keyModified = identifierModifier.apply(originalBiome.unwrapKey().orElseThrow().identifier()); + + Holder mapped = registry.get(keyModified).orElseThrow(() -> + new IllegalStateException("Biome " + keyModified + " introuvable dans le registre") ); fakeBiomes.set(x, y, z, mapped); From 5bd6c8bf62cf92caafda9c048ddddfa1b52eacaa Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Fri, 12 Jun 2026 20:50:06 +0200 Subject: [PATCH 28/74] create AmbientBuild how manage, repartition between (dimension types, timelines, and biomes) --- .../fr/openmc/api/datapacks/OMCDatapack.java | 6 + .../features/dream/DreamDimensionManager.java | 3 + .../core/registry/ambient/BiomeAmbient.java | 77 ------ .../core/registry/ambient/CustomAmbient.java | 108 ++++++--- .../ambient/CustomAmbientRegistry.java | 27 +-- .../registry/ambient/TimelineAmbient.java | 12 - .../ambient/builder/AmbientBuilder.java | 223 ++++++++++++++++++ .../ambient/contents/DarkAmbient.java | 10 +- .../ambient/contents/GoldenAmbient.java | 31 +-- .../ambient/contents/HellAmbient.java | 8 +- .../ambient/listeners/BiomesOnChunkLoad.java | 8 +- 11 files changed, 325 insertions(+), 188 deletions(-) delete mode 100644 src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java delete mode 100644 src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java create mode 100644 src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java diff --git a/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java b/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java index fcaff0c9c..ccb327b8d 100644 --- a/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java +++ b/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java @@ -92,6 +92,12 @@ public void addInjector(DatapackInjector injector) { injectors.add(injector); } + public void addInjector(Iterable injectors) { + for (DatapackInjector injector : injectors) { + addInjector(injector); + } + } + private static void runInjector(Path datapackRoot, DatapackInjector injector) { injector.inject(datapackRoot.toFile()); } diff --git a/src/main/java/fr/openmc/core/features/dream/DreamDimensionManager.java b/src/main/java/fr/openmc/core/features/dream/DreamDimensionManager.java index 02c8bb437..3f4fc3c4b 100644 --- a/src/main/java/fr/openmc/core/features/dream/DreamDimensionManager.java +++ b/src/main/java/fr/openmc/core/features/dream/DreamDimensionManager.java @@ -24,6 +24,9 @@ public class DreamDimensionManager { public static void init() { seedFile = new File(OMCPlugin.getInstance().getDataFolder() + "/data/dream", "seed.yml"); loadSeed(); + for (World world : Bukkit.getWorlds()) { + System.out.println(world.getName()); + } DREAM_WORLD = Bukkit.getWorld(DIMENSION_NAME); setupDimension(); diff --git a/src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java deleted file mode 100644 index d328143ac..000000000 --- a/src/main/java/fr/openmc/core/registry/ambient/BiomeAmbient.java +++ /dev/null @@ -1,77 +0,0 @@ -package fr.openmc.core.registry.ambient; - -import com.google.gson.JsonObject; -import fr.openmc.api.datapacks.builders.BiomeBuilder; -import fr.openmc.api.datapacks.injectors.BiomesInjector; -import fr.openmc.core.utils.MathUtils; -import net.minecraft.resources.Identifier; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSpecialEffects; - -import java.util.Optional; - -public interface BiomeAmbient { - BiomeBuilder getBiomeBuilder(); - - default BiomesInjector toBiomeInjector(Identifier ambientId) { - return new BiomesInjector(ambientId.getNamespace()).add(ambientId.getPath(), getBiomeBuilder()); - } - - /** - * Genere la clé de la variente du biome - * @param initialBiomeKey clé du biome initial a changer - * @param ambient l'ambience qui génère la variante - * @return identifiant de la variante du biome (namespace:initialBiomePath_ambientId) - */ - default Identifier toBiomeVariantKey(Identifier initialBiomeKey, CustomAmbient ambient) { - return Identifier.parse(CustomAmbientRegistry.NAMESPACE + ":" + initialBiomeKey.getPath() + "_" + ambient.getId()); - } - - /** - * Genere une variante d'un biome en fonction d'une ambience (namespace:id) - * Retourne un injecteur de biome qui prendra une variante de celui ci - * (couleur de l'herbe initial si pas override par l'ambience, idem pour les autres) - * @param initialBiome le biome initial à cloner - * @param ambientId l'id de l'ambience - * @return l'injecteur du fichier json - */ - default BiomesInjector toBiomeVariant(Biome initialBiome, Identifier ambientId) { - BiomeSpecialEffects initialEffects = initialBiome.getSpecialEffects(); - Biome.ClimateSettings climate = initialBiome.climateSettings; - - JsonObject effects = getBiomeBuilder().getEffects(); - Optional grassColor = hasEffects(effects, "grass_color") ? - Optional.of(MathUtils.hexToInt(effects.get("grass_color").getAsString())) : - initialEffects.grassColorOverride(); - Optional foliageColor = hasEffects(effects, "foliage_color") ? - Optional.of(MathUtils.hexToInt(effects.get("foliage_color").getAsString())) : - initialEffects.foliageColorOverride(); - Integer waterColor = hasEffects(effects, "water_color") ? - MathUtils.hexToInt(effects.get("water_color").getAsString()) : - initialEffects.grassColorOverride().orElse(4159204); - Optional dryFoliageColor = hasEffects(effects, "dry_foliage_color") ? - Optional.of(MathUtils.hexToInt(effects.get("dry_foliage_color").getAsString())) : - initialEffects.foliageColorOverride(); - String grassColorModifier = hasEffects(effects, "grass_color_modifier") ? - effects.get("grass_color_modifier").getAsString() : - initialEffects.grassColorModifier().getName(); - - BiomeBuilder builder = new BiomeBuilder() - .waterColor(waterColor) - .grassColorModifier(grassColorModifier) - .hasPrecipitation(climate.hasPrecipitation()) - .downfall(climate.downfall()) - .temperatures(climate.temperature()) - .temperatureModifier(climate.temperatureModifier().getName()); - - grassColor.ifPresent(builder::grassColor); - foliageColor.ifPresent(builder::foliageColor); - dryFoliageColor.ifPresent(builder::dryFoliageColor); - - return new BiomesInjector(ambientId.getNamespace()).add(ambientId.getPath(), builder); - } - - private boolean hasEffects(JsonObject effects, String envKey) { - return effects.get(envKey) != null; - } -} diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java index 97a63ecc0..b7affbeeb 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java @@ -1,8 +1,10 @@ package fr.openmc.core.registry.ambient; -import fr.openmc.api.datapacks.DatapackInjector; -import fr.openmc.api.datapacks.builders.DimensionTypeBuilder; -import fr.openmc.api.datapacks.injectors.DimensionTypesInjector; +import com.google.gson.JsonObject; +import fr.openmc.api.datapacks.builders.BiomeBuilder; +import fr.openmc.api.datapacks.injectors.BiomesInjector; +import fr.openmc.core.registry.ambient.builder.AmbientBuilder; +import fr.openmc.core.utils.MathUtils; import fr.openmc.core.utils.nms.PlayerBiomeNMS; import fr.openmc.core.utils.nms.PlayerRespawnNMS; import net.minecraft.core.Holder; @@ -15,24 +17,21 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.Level; import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.BiomeSpecialEffects; import net.minecraft.world.level.dimension.DimensionType; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.entity.Player; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; +import java.util.*; public abstract class CustomAmbient { // ** UUID playerUUID -> String idAmbient public static final Map ACTIVE_AMBIENTS = new HashMap<>(); public Holder CACHED_DIMENSION_TYPE = null; - public Holder CACHED_BIOME = null; public abstract String getId(); - public abstract DimensionTypeBuilder getDimensionTypeBuilder(); + public abstract AmbientBuilder getAmbientBuilder(); /** * Choix de la transition de dimension lorsque le joueur change d'ambience @@ -40,15 +39,6 @@ public abstract class CustomAmbient { */ public abstract ResourceKey getTransitionDimension(); - /** - * Converti notre DimensionTypeBuild en un injecteur de datapack - * et qui mettera les dimension_type sous le namepsace omc_ambient - * @return Un datapack injector - */ - public DatapackInjector toDimensionTypeInjector() { - return new DimensionTypesInjector(CustomAmbientRegistry.NAMESPACE).add(getId(), getDimensionTypeBuilder()); - } - /** * Applique l'ambience sur un Joueur * @param player Le joueur concerné @@ -63,9 +53,8 @@ public void apply(Player player) { getTransitionDimensionForPlayer(nmsPlayer) ); - if (this instanceof BiomeAmbient biomeAmbient) - PlayerBiomeNMS.replaceBiomes(nmsPlayer, - (biomeVarientKey) -> biomeAmbient.toBiomeVariantKey(biomeVarientKey, this)); + if (this.getAmbientBuilder().utilizeBiome()) + PlayerBiomeNMS.replaceBiomes(nmsPlayer, this::toBiomeVariantKey); ACTIVE_AMBIENTS.put(player.getUniqueId(), this.getId()); } @@ -107,6 +96,65 @@ public void reset(Collection receivers) { } } + /** + * Genere la clé de la variente du biome + * @param initialBiomeKey clé du biome initial a changer + * @return identifiant de la variante du biome (namespace:initialBiomePath_ambientId) + */ + public Identifier toBiomeVariantKey(Identifier initialBiomeKey) { + return Identifier.parse(CustomAmbientRegistry.NAMESPACE + ":" + initialBiomeKey.getPath() + "_" + this.getId()); + } + + /** + * Genere une variante d'un biome en fonction d'une ambience (namespace:id) + * Retourne un injecteur de biome qui prendra une variante de celui ci + * (couleur de l'herbe initial si pas override par l'ambience, idem pour les autres) + * @param initialBiome le biome initial à cloner + * @param ambientId l'id de l'ambience + * @return l'injecteur du fichier json + */ + public BiomesInjector toBiomeVariant(Biome initialBiome, Identifier ambientId) { + BiomeSpecialEffects initialEffects = initialBiome.getSpecialEffects(); + Biome.ClimateSettings climate = initialBiome.climateSettings; + + if (!this.getAmbientBuilder().utilizeBiome()) return null; + + JsonObject effects = this.getAmbientBuilder().getBiomeBuilder().getEffects(); + Optional grassColor = hasEffects(effects, "grass_color") ? + Optional.of(MathUtils.hexToInt(effects.get("grass_color").getAsString())) : + initialEffects.grassColorOverride(); + Optional foliageColor = hasEffects(effects, "foliage_color") ? + Optional.of(MathUtils.hexToInt(effects.get("foliage_color").getAsString())) : + initialEffects.foliageColorOverride(); + Integer waterColor = hasEffects(effects, "water_color") ? + MathUtils.hexToInt(effects.get("water_color").getAsString()) : + initialEffects.grassColorOverride().orElse(4159204); + Optional dryFoliageColor = hasEffects(effects, "dry_foliage_color") ? + Optional.of(MathUtils.hexToInt(effects.get("dry_foliage_color").getAsString())) : + initialEffects.foliageColorOverride(); + String grassColorModifier = hasEffects(effects, "grass_color_modifier") ? + effects.get("grass_color_modifier").getAsString() : + initialEffects.grassColorModifier().getName(); + + BiomeBuilder builder = new BiomeBuilder() + .waterColor(waterColor) + .grassColorModifier(grassColorModifier) + .hasPrecipitation(climate.hasPrecipitation()) + .downfall(climate.downfall()) + .temperatures(climate.temperature()) + .temperatureModifier(climate.temperatureModifier().getName()); + + grassColor.ifPresent(builder::grassColor); + foliageColor.ifPresent(builder::foliageColor); + dryFoliageColor.ifPresent(builder::dryFoliageColor); + + return new BiomesInjector(ambientId.getNamespace()).add(ambientId.getPath(), builder); + } + + private boolean hasEffects(JsonObject effects, String envKey) { + return effects.get(envKey) != null; + } + /** * Calcule la dimension de transition appropriée pour le joueur * Si le joueur est en OVERWORLD, on transitionne vers l'ambience @@ -160,22 +208,4 @@ private Holder getDimensionType() { ); return CACHED_DIMENSION_TYPE; } - - private Holder getBiome() { - if (CACHED_BIOME != null) - return CACHED_BIOME; - - ResourceKey key = ResourceKey.create( - Registries.BIOME, - Identifier.fromNamespaceAndPath(CustomAmbientRegistry.NAMESPACE, this.getId()) - ); - - Registry biomeRegistry = - MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BIOME); - - CACHED_BIOME = biomeRegistry.get(key).orElseThrow(() -> - new IllegalStateException("Biome " + CustomAmbientRegistry.NAMESPACE + ":"+ this.getId() +" introuvable") - ); - return CACHED_BIOME; - } } \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java index 3ee04ab84..8365d03cb 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java @@ -9,7 +9,6 @@ import fr.openmc.core.registry.ambient.contents.GoldenAmbient; import fr.openmc.core.registry.ambient.contents.HellAmbient; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.world.level.biome.Biome; import org.bukkit.Bukkit; @@ -35,29 +34,7 @@ public void init() { RegistriesLoadConfig.init(); for (CustomAmbient ambient : values()) { - ambientDatapack.addInjector(ambient.toDimensionTypeInjector()); - - if (ambient instanceof TimelineAmbient timelineAmbient) { - ambientDatapack.addInjector(timelineAmbient.toTimelineInjector( - ambientDatapack.getNamespace(), ambient.getId())); - } - - if (ambient instanceof BiomeAmbient biomeAmbient) { - net.minecraft.core.Registry biomeRegistry = - MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BIOME); - - // ** Création de chaque variante des biomes existants. - // * Renvoie simplement un biome ayant les effects (grassColor, waterColor, ...) lié au biome original - // * si ça pas été override par le biome mis par le CustomAmbient - for (var biomeEntry : biomeRegistry.entrySet()) { - ResourceKey key = biomeEntry.getKey(); - if (key.identifier().getNamespace().equals(NAMESPACE)) continue; // * On skip les biomes de notre datapack - - Biome biome = biomeEntry.getValue(); - ambientDatapack.addInjector(biomeAmbient.toBiomeVariant( - biome, biomeAmbient.toBiomeVariantKey(key.identifier(), ambient))); - } - } + ambient.getAmbientBuilder().runInjectors(ambient, ambientDatapack); } if (RegistriesLoadConfig.isMustRestart() || checkIfAmbientChange()) { @@ -79,7 +56,7 @@ private boolean checkIfAmbientChange() { MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BIOME); int numberOfAmbient = values().stream() - .filter(ambient -> ambient instanceof BiomeAmbient) + .filter(ambient -> ambient.getAmbientBuilder().utilizeBiome()) .toList().size(); int numberOfVanillaBiome = biomeRegistry.keySet().stream() .filter(key -> !key.getNamespace().equals(NAMESPACE)) diff --git a/src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java deleted file mode 100644 index 94f0e3dd1..000000000 --- a/src/main/java/fr/openmc/core/registry/ambient/TimelineAmbient.java +++ /dev/null @@ -1,12 +0,0 @@ -package fr.openmc.core.registry.ambient; - -import fr.openmc.api.datapacks.builders.TimelineBuilder; -import fr.openmc.api.datapacks.injectors.TimelinesInjector; - -public interface TimelineAmbient { - TimelineBuilder getTimelineBuilder(); - - default TimelinesInjector toTimelineInjector(String namespace, String id) { - return new TimelinesInjector(namespace).add(id, getTimelineBuilder()); - } -} diff --git a/src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java b/src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java new file mode 100644 index 000000000..4f1b4e1fe --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java @@ -0,0 +1,223 @@ +package fr.openmc.core.registry.ambient.builder; + +import com.google.gson.JsonObject; +import fr.openmc.api.datapacks.OMCDatapack; +import fr.openmc.api.datapacks.builders.BiomeBuilder; +import fr.openmc.api.datapacks.builders.DimensionTypeBuilder; +import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; +import fr.openmc.api.datapacks.builders.TimelineBuilder; +import fr.openmc.api.datapacks.injectors.DimensionTypesInjector; +import fr.openmc.api.datapacks.injectors.TimelinesInjector; +import fr.openmc.core.registry.ambient.CustomAmbient; +import fr.openmc.core.registry.ambient.CustomAmbientRegistry; +import lombok.Getter; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.dimension.DimensionType; + +import java.util.function.Consumer; + +public class AmbientBuilder { + private final String namespace; + private final String id; + + @Getter + private final DimensionTypeBuilder dimTypeBuilder = new DimensionTypeBuilder(); + @Getter + private TimelineBuilder timelineBuilder = null; + @Getter + private BiomeBuilder biomeBuilder = null; + + public AmbientBuilder(String namepace, String id) { + this.namespace = namepace; + this.id = id; + } + + public boolean utilizeBiome() { + return biomeBuilder != null; + } + + + public AmbientBuilder ambientLight(double ambientLight) { + this.dimTypeBuilder.ambientLight(ambientLight); + return this; + } + + public AmbientBuilder attributesBuilder(EnvironnementAttributeBuilder builder) { + this.dimTypeBuilder.attributesBuilder(builder); + return this; + } + + public AmbientBuilder defaultClock(String keyOfClock) { + this.dimTypeBuilder.defaultClock(keyOfClock); + return this; + } + + public AmbientBuilder hasCeiling(boolean hasCeiling) { + this.dimTypeBuilder.hasCeiling(hasCeiling); + return this; + } + + public AmbientBuilder hasSkylight(boolean hasSkylight) { + this.dimTypeBuilder.hasSkylight(hasSkylight); + return this; + } + + public AmbientBuilder hasFixedTime(boolean hasFixedTime) { + this.dimTypeBuilder.hasFixedTime(hasFixedTime); + return this; + } + + public AmbientBuilder skybox(String skybox) { + this.dimTypeBuilder.skybox(skybox); + return this; + } + + public AmbientBuilder skybox(DimensionType.Skybox skybox) { + return skybox(skybox.getSerializedName()); + } + + public AmbientBuilder cardinalLight(String cardinalLight) { + this.dimTypeBuilder.cardinalLight(cardinalLight); + return this; + } + + public AmbientBuilder timelines(String timelines) { + this.dimTypeBuilder.timelines(timelines); + return this; + } + + public AmbientBuilder timelines(TimelineBuilder builder) { + this.dimTypeBuilder.timelines(new TimelinesInjector(namespace).add(id, builder)); + this.timelineBuilder = builder; + return this; + } + + public AmbientBuilder biomes(BiomeBuilder builder) { + this.biomeBuilder = builder; + return this; + } + + public AmbientBuilder downfall(Float value) { + if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); + this.biomeBuilder.downfall(value); + return this; + } + + public AmbientBuilder temperatures(Float value) { + if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); + this.biomeBuilder.temperatures(value); + return this; + } + + public AmbientBuilder temperatureModifier(String id) { + if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); + this.biomeBuilder.temperatureModifier(id); + return this; + } + + public AmbientBuilder hasPrecipitation(Boolean bool) { + if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); + this.biomeBuilder.hasPrecipitation(bool); + return this; + } + + public AmbientBuilder effects(Consumer builder) { + if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); + this.biomeBuilder.effects(builder); + return this; + } + + public AmbientBuilder waterColor(String color) { + if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); + this.biomeBuilder.waterColor(color); + return this; + } + + public AmbientBuilder grassColor(String color) { + if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); + this.biomeBuilder.grassColor(color); + return this; + } + + public AmbientBuilder foliageColor(String color) { + if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); + this.biomeBuilder.foliageColor(color); + return this; + } + + public AmbientBuilder dryFoliageColor(String color) { + if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); + this.biomeBuilder.dryFoliageColor(color); + return this; + } + + public AmbientBuilder waterColor(Integer color) { + if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); + this.biomeBuilder.waterColor(color); + return this; + } + + public AmbientBuilder grassColor(Integer color) { + if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); + this.biomeBuilder.grassColor(color); + return this; + } + + public AmbientBuilder foliageColor(Integer color) { + if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); + this.biomeBuilder.foliageColor(color); + return this; + } + + public AmbientBuilder dryFoliageColor(Integer color) { + if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); + this.biomeBuilder.dryFoliageColor(color); + return this; + } + + /** + * Set la grass color modifier + * @param id none, dark_forest, swamp + * @return le builder + */ + public AmbientBuilder grassColorModifier(String id) { + if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); + this.biomeBuilder.grassColorModifier(id); + return this; + } + + public void runInjectors(CustomAmbient ambient, OMCDatapack datapack) { + // ** DimensionType Injector + DimensionTypesInjector dimensionTypesInjector = new DimensionTypesInjector(namespace).add(id, dimTypeBuilder); + datapack.addInjector(dimensionTypesInjector); + + // ** Timeline Injector + if (timelineBuilder != null) { + TimelinesInjector timelinesInjector = new TimelinesInjector(namespace).add(id, timelineBuilder); + datapack.addInjector(timelinesInjector); + } + + // ** Biome Injector + if (this.utilizeBiome()) { + net.minecraft.core.Registry biomeRegistry = + MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BIOME); + + // ** Création de chaque variante des biomes existants. + // * Renvoie simplement un biome ayant les effects (grassColor, waterColor, ...) lié au biome original + // * si ça pas été override par le biome mis par le CustomAmbient + for (var biomeEntry : biomeRegistry.entrySet()) { + ResourceKey key = biomeEntry.getKey(); + if (key.identifier().getNamespace().equals(CustomAmbientRegistry.NAMESPACE)) continue; // * On skip les biomes de notre datapack + + Biome biome = biomeEntry.getValue(); + + datapack.addInjector(ambient.toBiomeVariant( + biome, ambient.toBiomeVariantKey(key.identifier()))); + } + } + } + +} diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java index 9dff94966..1a4c9ac5a 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/DarkAmbient.java @@ -1,8 +1,9 @@ package fr.openmc.core.registry.ambient.contents; -import fr.openmc.api.datapacks.builders.DimensionTypeBuilder; import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; import fr.openmc.core.registry.ambient.CustomAmbient; +import fr.openmc.core.registry.ambient.CustomAmbientRegistry; +import fr.openmc.core.registry.ambient.builder.AmbientBuilder; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; import net.minecraft.world.level.dimension.DimensionType; @@ -14,8 +15,8 @@ public String getId() { } @Override - public DimensionTypeBuilder getDimensionTypeBuilder() { - return new DimensionTypeBuilder() + public AmbientBuilder getAmbientBuilder() { + return new AmbientBuilder(CustomAmbientRegistry.NAMESPACE, this.getId()) .attributesBuilder(new EnvironnementAttributeBuilder() .attributes(obj -> { obj.addProperty("visual/ambient_light_color", "#DD37E6"); @@ -24,7 +25,8 @@ public DimensionTypeBuilder getDimensionTypeBuilder() { obj.addProperty("visual/fog_start_distance", 40); obj.addProperty("visual/fog_end_distance", 70); obj.addProperty("visual/sunrise_sunset_color", "#FFBB00FA"); - })) + }) + ) .defaultClock(null) .timelines((String) null) .skybox(DimensionType.Skybox.END) diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java index 0316740a9..3c5eac42b 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java @@ -1,25 +1,23 @@ package fr.openmc.core.registry.ambient.contents; import fr.openmc.api.datapacks.builders.BiomeBuilder; -import fr.openmc.api.datapacks.builders.DimensionTypeBuilder; import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; import fr.openmc.api.datapacks.builders.TimelineBuilder; -import fr.openmc.core.registry.ambient.BiomeAmbient; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.registry.ambient.CustomAmbientRegistry; -import fr.openmc.core.registry.ambient.TimelineAmbient; +import fr.openmc.core.registry.ambient.builder.AmbientBuilder; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; -public class GoldenAmbient extends CustomAmbient implements TimelineAmbient, BiomeAmbient { +public class GoldenAmbient extends CustomAmbient { @Override public String getId() { return "golden_ambient"; } @Override - public DimensionTypeBuilder getDimensionTypeBuilder() { - return new DimensionTypeBuilder() + public AmbientBuilder getAmbientBuilder() { + return new AmbientBuilder(CustomAmbientRegistry.NAMESPACE, this.getId()) .attributesBuilder(new EnvironnementAttributeBuilder() .attributes(obj -> { obj.addProperty("visual/ambient_light_color", "#FFE75C"); @@ -32,22 +30,13 @@ public DimensionTypeBuilder getDimensionTypeBuilder() { obj.addProperty("visual/cloud_height", 100); obj.addProperty("visual/cloud_color", "#4cffde50"); }) - .particleDustColorTransition(16776172, 16766720, 2, 0.01)) + .particleDustColorTransition(16776172, 16766720, 2, 0.01) + ) .hasSkylight(true) - .timelines(toTimelineInjector(CustomAmbientRegistry.NAMESPACE, getId())); - } - - @Override - public BiomeBuilder getBiomeBuilder() { - return new BiomeBuilder() - .waterColor("#3f76e4"); - } - - @Override - public TimelineBuilder getTimelineBuilder() { - return new TimelineBuilder() - .clock("minecraft:overworld") - .periodTicks(24000); + .timelines(new TimelineBuilder() + .clock("minecraft:overworld") + .periodTicks(24000)) + .biomes(new BiomeBuilder()); } @Override diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/HellAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/HellAmbient.java index fe24f768e..786bb65fb 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/HellAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/HellAmbient.java @@ -1,8 +1,9 @@ package fr.openmc.core.registry.ambient.contents; -import fr.openmc.api.datapacks.builders.DimensionTypeBuilder; import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; import fr.openmc.core.registry.ambient.CustomAmbient; +import fr.openmc.core.registry.ambient.CustomAmbientRegistry; +import fr.openmc.core.registry.ambient.builder.AmbientBuilder; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; import net.minecraft.world.level.dimension.DimensionType; @@ -15,8 +16,8 @@ public String getId() { } @Override - public DimensionTypeBuilder getDimensionTypeBuilder() { - return new DimensionTypeBuilder() + public AmbientBuilder getAmbientBuilder() { + return new AmbientBuilder(CustomAmbientRegistry.NAMESPACE, this.getId()) .attributesBuilder(new EnvironnementAttributeBuilder() .attributes(obj -> { obj.addProperty("visual/ambient_light_color", "#A3170B"); @@ -33,7 +34,6 @@ public DimensionTypeBuilder getDimensionTypeBuilder() { .cardinalLight("nether") .timelines("#minecraft:in_nether") .skybox(DimensionType.Skybox.NONE) - .infiniburn("#minecraft:infiniburn_nether") .hasSkylight(false) .hasCeiling(true) .hasFixedTime(true); diff --git a/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java b/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java index 08e038870..cfc625589 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java +++ b/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java @@ -1,7 +1,6 @@ package fr.openmc.core.registry.ambient.listeners; import fr.openmc.core.OMCRegistry; -import fr.openmc.core.registry.ambient.BiomeAmbient; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.utils.nms.PlayerBiomeNMS; import io.papermc.paper.event.packet.PlayerChunkLoadEvent; @@ -32,15 +31,12 @@ public void onChunkLoad(PlayerChunkLoadEvent event) { CustomAmbient.ACTIVE_AMBIENTS.get(player.getUniqueId()) ); - if (!(ambientApplied instanceof BiomeAmbient biomeAmbient)) return; + if (!ambientApplied.getAmbientBuilder().utilizeBiome()) return; ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); ChunkAccess chunkAccess = ((CraftChunk) event.getChunk()).getHandle(ChunkStatus.FULL); if (!(chunkAccess instanceof LevelChunk nmsChunk)) return; - PlayerBiomeNMS.remplaceBiome(nmsPlayer, nmsChunk, (initialBiomeKey) -> biomeAmbient.toBiomeVariantKey( - initialBiomeKey, - ambientApplied - )); + PlayerBiomeNMS.remplaceBiome(nmsPlayer, nmsChunk, ambientApplied::toBiomeVariantKey); } } From 3c75a5e3cf4e0b30d6ed1c0db49df1dd0528536d Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Fri, 12 Jun 2026 22:39:21 +0200 Subject: [PATCH 29/74] fix: water color problem --- .../java/fr/openmc/core/registry/ambient/CustomAmbient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java index b7affbeeb..cd611741b 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java @@ -128,7 +128,7 @@ public BiomesInjector toBiomeVariant(Biome initialBiome, Identifier ambientId) { initialEffects.foliageColorOverride(); Integer waterColor = hasEffects(effects, "water_color") ? MathUtils.hexToInt(effects.get("water_color").getAsString()) : - initialEffects.grassColorOverride().orElse(4159204); + initialEffects.waterColor(); Optional dryFoliageColor = hasEffects(effects, "dry_foliage_color") ? Optional.of(MathUtils.hexToInt(effects.get("dry_foliage_color").getAsString())) : initialEffects.foliageColorOverride(); From 7b6925efe48efc93d1626dddd3b9640ddd4064df Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Fri, 12 Jun 2026 22:42:50 +0200 Subject: [PATCH 30/74] chore: optimize getFakeChunkWithMapping before : https://spark.lucko.me/GpOtMS4wct after : https://spark.lucko.me/3Rq29FTAWR --- .../features/dream/DreamDimensionManager.java | 3 -- .../core/registry/ambient/CustomAmbient.java | 2 +- .../openmc/core/utils/nms/PlayerBiomeNMS.java | 29 ++++++++++++++----- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/dream/DreamDimensionManager.java b/src/main/java/fr/openmc/core/features/dream/DreamDimensionManager.java index 3f4fc3c4b..02c8bb437 100644 --- a/src/main/java/fr/openmc/core/features/dream/DreamDimensionManager.java +++ b/src/main/java/fr/openmc/core/features/dream/DreamDimensionManager.java @@ -24,9 +24,6 @@ public class DreamDimensionManager { public static void init() { seedFile = new File(OMCPlugin.getInstance().getDataFolder() + "/data/dream", "seed.yml"); loadSeed(); - for (World world : Bukkit.getWorlds()) { - System.out.println(world.getName()); - } DREAM_WORLD = Bukkit.getWorld(DIMENSION_NAME); setupDimension(); diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java index cd611741b..25fa2eea1 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java @@ -102,7 +102,7 @@ public void reset(Collection receivers) { * @return identifiant de la variante du biome (namespace:initialBiomePath_ambientId) */ public Identifier toBiomeVariantKey(Identifier initialBiomeKey) { - return Identifier.parse(CustomAmbientRegistry.NAMESPACE + ":" + initialBiomeKey.getPath() + "_" + this.getId()); + return Identifier.fromNamespaceAndPath(CustomAmbientRegistry.NAMESPACE, initialBiomeKey.getPath() + "_" + this.getId()); } /** diff --git a/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java b/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java index 756730ef6..c2cd0380d 100644 --- a/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java +++ b/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java @@ -19,7 +19,9 @@ import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.function.Function; public class PlayerBiomeNMS { @@ -150,6 +152,9 @@ public static LevelChunk getFakeChunk(LevelChunk original, ServerLevel level, Ho return fakeChunk; } + + private static final Map, Holder> BIOME_CACHE = new HashMap<>(); + /** * Crée un faux chunk en se basant sur l'originel et en changeant juste le biome du chunk en fonction * d'un identifierModifier @@ -162,6 +167,9 @@ private static LevelChunk getFakeChunkWithMapping( Function identifierModifier) { LevelChunk fake = new LevelChunk(original.level, original.getPos()); + + Registry registry = original.level.registryAccess().lookupOrThrow(Registries.BIOME); + Strategy> idMap = Strategy.createForBiomes(original.level.registryAccess().lookupOrThrow(Registries.BIOME).asHolderIdMap()); LevelChunkSection[] originalSections = original.getSections(); LevelChunkSection[] fakeSections = fake.getSections(); @@ -170,29 +178,36 @@ private static LevelChunk getFakeChunkWithMapping( PalettedContainer> fakeBiomes = new PalettedContainer<>( originalSection.getNoiseBiome(0,0,0), - Strategy.createForBiomes(original.level.registryAccess().lookupOrThrow(Registries.BIOME).asHolderIdMap()), + idMap, null ); - Registry registry = original.level.registryAccess().lookupOrThrow(Registries.BIOME); for (int x = 0; x < 4; x++) { for (int y = 0; y < 4; y++) { for (int z = 0; z < 4; z++) { Holder originalBiome = originalSection.getNoiseBiome(x, y, z); - Identifier keyModified = identifierModifier.apply(originalBiome.unwrapKey().orElseThrow().identifier()); + Holder mapped = BIOME_CACHE.computeIfAbsent(originalBiome, cacheMappedBiome -> { + Identifier keyModified = identifierModifier.apply( + cacheMappedBiome.unwrapKey().orElseThrow().identifier() + ); - Holder mapped = registry.get(keyModified).orElseThrow(() -> - new IllegalStateException("Biome " + keyModified + " introuvable dans le registre") - ); + return registry.get(keyModified).orElseThrow(() -> + new IllegalStateException("Biome " + keyModified + " introuvable dans le registre") + ); + }); fakeBiomes.set(x, y, z, mapped); } } } - fakeSections[i] = new LevelChunkSection(originalSection.getStates(), fakeBiomes); + try { + SECTION_BIOMES.set(fakeSections[i], fakeBiomes); + } catch (IllegalAccessException e) { + OMCLogger.error("Erreur d'acces à l'attribut biomes d'un levelChunkSetcion"); + } } return fake; From 7e225216c1847024cd601badc7630e335caa0073 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Fri, 12 Jun 2026 23:28:13 +0200 Subject: [PATCH 31/74] chore: optimize for chunk who contains one biome before : https://spark.lucko.me/erQyjQgpfi after : https://spark.lucko.me/Osbqugo0mR --- .../openmc/core/utils/nms/PlayerBiomeNMS.java | 56 ++++++++++++++----- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java b/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java index c2cd0380d..257a6cf4c 100644 --- a/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java +++ b/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java @@ -133,13 +133,15 @@ public static void replaceBiomes(ServerPlayer nmsPlayer, Function biome) { LevelChunk fakeChunk = new LevelChunk(level, original.getPos()); + Strategy> idMap = Strategy.createForBiomes(original.level.registryAccess().lookupOrThrow(Registries.BIOME).asHolderIdMap()); + LevelChunkSection[] originalSections = original.getSections(); LevelChunkSection[] fakeSections = fakeChunk.getSections(); for (int i = 0; i < originalSections.length; i++) { PalettedContainer> container = new PalettedContainer<>( biome, - Strategy.createForBiomes(level.registryAccess().lookupOrThrow(Registries.BIOME).asHolderIdMap()), + idMap, null ); @@ -154,6 +156,7 @@ public static LevelChunk getFakeChunk(LevelChunk original, ServerLevel level, Ho } private static final Map, Holder> BIOME_CACHE = new HashMap<>(); + private static final Map, Identifier> ID_MAPPED_BIOME_CACHE = new HashMap<>(); /** * Crée un faux chunk en se basant sur l'originel et en changeant juste le biome du chunk en fonction @@ -165,7 +168,6 @@ public static LevelChunk getFakeChunk(LevelChunk original, ServerLevel level, Ho private static LevelChunk getFakeChunkWithMapping( LevelChunk original, Function identifierModifier) { - LevelChunk fake = new LevelChunk(original.level, original.getPos()); Registry registry = original.level.registryAccess().lookupOrThrow(Registries.BIOME); @@ -175,6 +177,30 @@ private static LevelChunk getFakeChunkWithMapping( for (int i = 0; i < originalSections.length; i++) { LevelChunkSection originalSection = originalSections[i]; + PalettedContainer> originalBiomes = null; + + try { + originalBiomes = + (PalettedContainer>) SECTION_BIOMES.get(originalSection); + } catch (IllegalAccessException e) { + OMCLogger.error("Erreur d'acces à l'attribut biomes d'un levelChunkSetcion"); + } + + if (originalBiomes == null) continue; + + // ** Si le chunk contient qu'un biome + if (originalBiomes.data.palette().getSize() == 1) { + Holder single = originalBiomes.data.palette().valueFor(0); + Holder mapped = getMapped(single, registry, identifierModifier); + + PalettedContainer> fakeBiomes1 = new PalettedContainer<>(mapped, idMap, null); + try { + SECTION_BIOMES.set(fakeSections[i], fakeBiomes1); + } catch (IllegalAccessException e) { + OMCLogger.error("Erreur d'acces à l'attribut biomes d'un levelChunkSetcion"); + } + continue; + } PalettedContainer> fakeBiomes = new PalettedContainer<>( originalSection.getNoiseBiome(0,0,0), @@ -182,21 +208,11 @@ private static LevelChunk getFakeChunkWithMapping( null ); - for (int x = 0; x < 4; x++) { for (int y = 0; y < 4; y++) { for (int z = 0; z < 4; z++) { Holder originalBiome = originalSection.getNoiseBiome(x, y, z); - - Holder mapped = BIOME_CACHE.computeIfAbsent(originalBiome, cacheMappedBiome -> { - Identifier keyModified = identifierModifier.apply( - cacheMappedBiome.unwrapKey().orElseThrow().identifier() - ); - - return registry.get(keyModified).orElseThrow(() -> - new IllegalStateException("Biome " + keyModified + " introuvable dans le registre") - ); - }); + Holder mapped = getMapped(originalBiome, registry, identifierModifier); fakeBiomes.set(x, y, z, mapped); } @@ -212,4 +228,18 @@ private static LevelChunk getFakeChunkWithMapping( return fake; } + + private static Holder getMapped( + Holder original, + Registry registry, + Function identifierModifier) { + return BIOME_CACHE.computeIfAbsent(original, b -> { + Identifier keyModified = ID_MAPPED_BIOME_CACHE.computeIfAbsent(original, m -> + identifierModifier.apply( + m.unwrapKey().orElseThrow().identifier() + ) + ); + return registry.get(keyModified).orElseThrow(); + }); + } } From 40f9787063a313a854620d5b4e41b7eba4cd8415 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 13 Jun 2026 12:14:31 +0200 Subject: [PATCH 32/74] fix: if datapack crash the registries, someone must delete OpenMC/data/registry --- .../fr/openmc/api/datapacks/OMCDatapack.java | 40 ++++++++++++++----- src/main/java/fr/openmc/core/OMCRegistry.java | 2 +- .../ambient/CustomAmbientRegistry.java | 16 +++++++- .../ambient/RegistriesLoadConfig.java | 5 +-- 4 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java b/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java index ccb327b8d..f81f8a335 100644 --- a/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java +++ b/src/main/java/fr/openmc/api/datapacks/OMCDatapack.java @@ -3,7 +3,6 @@ import fr.openmc.api.datapacks.injectors.PackMetadataInjector; import fr.openmc.core.OMCPlugin; import fr.openmc.core.utils.FilesUtils; -import io.papermc.paper.datapack.DatapackManager; import io.papermc.paper.plugin.bootstrap.BootstrapContext; import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; import lombok.Getter; @@ -23,8 +22,8 @@ public class OMCDatapack { private final String namespace; private final Set injectors = new HashSet<>(); - private final String ID_DATAPACK = "datapacks-openmc"; - private final DatapackManager DATAPACK_MANAGER = OMCPlugin.getInstance().getServer().getDatapackManager(); + public final String ID_DATAPACK_INJECTED = "openmc-injected"; + private final String ID_TEMP_DATAPACK_FOLDER = "datapacks-openmc"; public OMCDatapack(String packName, String namespace) { this.packName = packName; @@ -35,12 +34,12 @@ public void buildBootstrap(BootstrapContext context, boolean generateFiles) thro Path dir; if (generateFiles) { - dir = context.getDataDirectory().resolve(ID_DATAPACK); + dir = context.getDataDirectory().resolve(ID_TEMP_DATAPACK_FOLDER); FilesUtils.deleteDirectory(dir.toFile()); Files.createDirectories(dir); } else { - dir = Files.createTempDirectory(ID_DATAPACK); + dir = Files.createTempDirectory(ID_TEMP_DATAPACK_FOLDER); } runInjector(dir, new PackMetadataInjector()); @@ -54,7 +53,7 @@ public void buildBootstrap(BootstrapContext context, boolean generateFiles) thro try { URI uri = dir.toUri(); - event.registrar().discoverPack(uri, "openmc-injected"); + event.registrar().discoverPack(uri, ID_DATAPACK_INJECTED); } catch (IOException e) { throw new RuntimeException(e); } @@ -69,9 +68,12 @@ public void buildBootstrap(BootstrapContext context, boolean generateFiles) thro * @throws IOException */ public void buildRuntime(Runnable onBuilded) throws IOException { - Path dir = OMCPlugin.getInstance().getServer().getLevelDirectory().resolve("datapacks").resolve(ID_DATAPACK); + Path dir = OMCPlugin.getInstance().getServer() + .getLevelDirectory() + .resolve("datapacks") + .resolve(ID_TEMP_DATAPACK_FOLDER); - cleanup(); + cleanupRumtime(); Files.createDirectories(dir); runInjector(dir, new PackMetadataInjector()); @@ -83,8 +85,26 @@ public void buildRuntime(Runnable onBuilded) throws IOException { Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), onBuilded, 20L); } - public void cleanup() throws IOException { - Path dir = OMCPlugin.getInstance().getServer().getLevelDirectory().resolve("datapacks").resolve(ID_DATAPACK); + public void cleanupBootstrap(BootstrapContext context) throws IOException { + Path dataDir = context.getDataDirectory().toFile() + .toPath() + .toAbsolutePath() + .normalize(); // * ex /home/container/plugins/OpenMC + + Path serverRoot = dataDir.getParent() // * plugins/ + .getParent(); // * /container + + Path dir = serverRoot + .resolve("world") // * /container/world + .resolve("datapacks") // * /container/datapacks + .resolve(ID_TEMP_DATAPACK_FOLDER); + FilesUtils.deleteDirectory(dir.toFile()); + } + + public void cleanupRumtime() throws IOException { + Path dir = OMCPlugin.getInstance().getServer().getLevelDirectory() + .resolve("datapacks") + .resolve(ID_TEMP_DATAPACK_FOLDER); FilesUtils.deleteDirectory(dir.toFile()); } diff --git a/src/main/java/fr/openmc/core/OMCRegistry.java b/src/main/java/fr/openmc/core/OMCRegistry.java index 6a8e80090..7ea353762 100644 --- a/src/main/java/fr/openmc/core/OMCRegistry.java +++ b/src/main/java/fr/openmc/core/OMCRegistry.java @@ -41,7 +41,7 @@ public final class OMCRegistry { RegistryLoadingType.AFTER_IA), new RegistryContext( () -> CUSTOM_AMBIENTS = new CustomAmbientRegistry(), - RegistryLoadingType.RUNTIME), + RegistryLoadingType.BOOTSTRAP, RegistryLoadingType.RUNTIME), new RegistryContext( () -> CUSTOM_LOOTBOXES = new CustomLootboxRegistry(), RegistryLoadingType.AFTER_IA) diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java index 8365d03cb..f9f6b3519 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java @@ -8,6 +8,7 @@ import fr.openmc.core.registry.ambient.contents.DarkAmbient; import fr.openmc.core.registry.ambient.contents.GoldenAmbient; import fr.openmc.core.registry.ambient.contents.HellAmbient; +import io.papermc.paper.plugin.bootstrap.BootstrapContext; import net.minecraft.core.registries.Registries; import net.minecraft.server.MinecraftServer; import net.minecraft.world.level.biome.Biome; @@ -15,6 +16,7 @@ import java.io.IOException; +@SuppressWarnings("UnstableApiUsage") public class CustomAmbientRegistry extends Registry implements KeyedRegistry { public static final String NAMESPACE = "omc_ambient"; private final OMCDatapack ambientDatapack = new OMCDatapack("openmc", NAMESPACE); @@ -30,9 +32,19 @@ public String key(CustomAmbient registryObject) { } @Override - public void init() { - RegistriesLoadConfig.init(); + public void bootstrap(BootstrapContext context) throws IOException { + // * On check si la config à été enlevé, + // on l'eneleve avant le démarrage des datapacks (utile si y'a une erreur avec celui ci) + RegistriesLoadConfig.init(context.getDataDirectory().toFile()); + + if (RegistriesLoadConfig.isMustRestart()) { + OMCLogger.infoFormatted("Suppression du datapack/" + ambientDatapack.ID_DATAPACK_INJECTED); + ambientDatapack.cleanupBootstrap(context); + } + } + @Override + public void init() { for (CustomAmbient ambient : values()) { ambient.getAmbientBuilder().runInjectors(ambient, ambientDatapack); } diff --git a/src/main/java/fr/openmc/core/registry/ambient/RegistriesLoadConfig.java b/src/main/java/fr/openmc/core/registry/ambient/RegistriesLoadConfig.java index 539db8dd9..ace14e441 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/RegistriesLoadConfig.java +++ b/src/main/java/fr/openmc/core/registry/ambient/RegistriesLoadConfig.java @@ -1,6 +1,5 @@ package fr.openmc.core.registry.ambient; -import fr.openmc.core.OMCPlugin; import fr.openmc.core.bootstrap.integration.OMCLogger; import lombok.Getter; import org.bukkit.configuration.file.FileConfiguration; @@ -23,8 +22,8 @@ public class RegistriesLoadConfig { @Getter private static boolean mustRestart; - public static void init() { - registriesConfigFile = new File(OMCPlugin.getInstance().getDataFolder() + "/data/registry", "load.yml"); + public static void init(File dataFolder) { + registriesConfigFile = new File(dataFolder + "/data/registry", "load.yml"); registriesConfig = YamlConfiguration.loadConfiguration(registriesConfigFile); // * Premier lancement du plugin où suppression du fichier par une classe externe (ex CustomAmbientRegistry) From 5a420e27043a5256c7f77fcb77cab102fc1ad8b4 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 13 Jun 2026 12:29:35 +0200 Subject: [PATCH 33/74] change: golden ambient --- .../ambient/contents/GoldenAmbient.java | 18 +++++++++++------- .../core/utils/nms/toast/ToastUtils.java | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java index 3c5eac42b..d170d562e 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java @@ -8,6 +8,7 @@ import fr.openmc.core.registry.ambient.builder.AmbientBuilder; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; +import net.minecraft.world.level.dimension.DimensionType; public class GoldenAmbient extends CustomAmbient { @Override @@ -20,23 +21,26 @@ public AmbientBuilder getAmbientBuilder() { return new AmbientBuilder(CustomAmbientRegistry.NAMESPACE, this.getId()) .attributesBuilder(new EnvironnementAttributeBuilder() .attributes(obj -> { - obj.addProperty("visual/ambient_light_color", "#FFE75C"); + obj.addProperty("visual/block_light_tint", "#FFE02E"); + obj.addProperty("visual/ambient_light_color", "#FFE02E"); obj.addProperty("visual/sky_color", "#FFD700"); - obj.addProperty("visual/sky_light_color", "#FFE02E"); - obj.addProperty("visual/fog_color", "#6D6319"); - obj.addProperty("visual/fog_start_distance", 55); - obj.addProperty("visual/fog_end_distance", 65); - obj.addProperty("visual/sunrise_sunset_color", "#ccff5900"); + obj.addProperty("visual/sky_light_color", "#FFDE17"); + obj.addProperty("visual/fog_color", "#AA9B27"); + obj.addProperty("visual/fog_start_distance", 70); + obj.addProperty("visual/fog_end_distance", 80); + obj.addProperty("visual/sunrise_sunset_color", "#ccfa6f25"); obj.addProperty("visual/cloud_height", 100); obj.addProperty("visual/cloud_color", "#4cffde50"); }) .particleDustColorTransition(16776172, 16766720, 2, 0.01) ) + .skybox(DimensionType.Skybox.OVERWORLD) .hasSkylight(true) .timelines(new TimelineBuilder() .clock("minecraft:overworld") .periodTicks(24000)) - .biomes(new BiomeBuilder()); + .biomes(new BiomeBuilder() + .hasPrecipitation(false)); } @Override diff --git a/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java b/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java index 5258b891d..25e7f211b 100644 --- a/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java +++ b/src/main/java/fr/openmc/core/utils/nms/toast/ToastUtils.java @@ -17,7 +17,7 @@ import java.util.Set; public class ToastUtils { - private static final Identifier TOAST_IDENTIFIER = Identifier.parse("omc:custom_toast"); + private static final Identifier TOAST_IDENTIFIER = Identifier.fromNamespaceAndPath("omc", "custom_toast"); private static final AdvancementRequirements ADV_REQUIREMENTS = AdvancementRequirements.allOf(Set.of("c")); /** From 221139df146308db6913dc220cfab01c1eaadaf0 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 13 Jun 2026 18:02:33 +0200 Subject: [PATCH 34/74] feat: Bloody Ambient (need feedback) + SetTimeNMS --- .../core/registry/ambient/CustomAmbient.java | 5 ++ .../ambient/CustomAmbientRegistry.java | 2 + .../ambient/builder/AmbientBuilder.java | 9 ++- .../ambient/contents/BloodyAmbient.java | 60 +++++++++++++++++++ .../core/utils/nms/PlayerSetTimeNMS.java | 43 +++++++++++++ 5 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java create mode 100644 src/main/java/fr/openmc/core/utils/nms/PlayerSetTimeNMS.java diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java index 25fa2eea1..e5a4a1222 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java @@ -7,6 +7,7 @@ import fr.openmc.core.utils.MathUtils; import fr.openmc.core.utils.nms.PlayerBiomeNMS; import fr.openmc.core.utils.nms.PlayerRespawnNMS; +import fr.openmc.core.utils.nms.PlayerSetTimeNMS; import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; @@ -56,6 +57,10 @@ public void apply(Player player) { if (this.getAmbientBuilder().utilizeBiome()) PlayerBiomeNMS.replaceBiomes(nmsPlayer, this::toBiomeVariantKey); + if (this.getAmbientBuilder().getTimeFixed() != null) { + PlayerSetTimeNMS.sendPacketSetTime(player, this.getAmbientBuilder().getTimeFixed()); + } + ACTIVE_AMBIENTS.put(player.getUniqueId(), this.getId()); } diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java index f9f6b3519..08e71faf6 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java @@ -5,6 +5,7 @@ import fr.openmc.core.bootstrap.integration.OMCLogger; import fr.openmc.core.bootstrap.registries.KeyedRegistry; import fr.openmc.core.bootstrap.registries.Registry; +import fr.openmc.core.registry.ambient.contents.BloodyAmbient; import fr.openmc.core.registry.ambient.contents.DarkAmbient; import fr.openmc.core.registry.ambient.contents.GoldenAmbient; import fr.openmc.core.registry.ambient.contents.HellAmbient; @@ -25,6 +26,7 @@ public class CustomAmbientRegistry extends Registry imple public final CustomAmbient DARK = register(new DarkAmbient()); public final CustomAmbient HELL = register(new HellAmbient()); public final CustomAmbient GOLDEN = register(new GoldenAmbient()); + public final CustomAmbient BLOODY = register(new BloodyAmbient()); @Override public String key(CustomAmbient registryObject) { diff --git a/src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java b/src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java index 4f1b4e1fe..50dd10b50 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java +++ b/src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java @@ -29,6 +29,8 @@ public class AmbientBuilder { private TimelineBuilder timelineBuilder = null; @Getter private BiomeBuilder biomeBuilder = null; + @Getter + private Integer timeFixed = null; public AmbientBuilder(String namepace, String id) { this.namespace = namepace; @@ -65,11 +67,16 @@ public AmbientBuilder hasSkylight(boolean hasSkylight) { return this; } - public AmbientBuilder hasFixedTime(boolean hasFixedTime) { + public AmbientBuilder hasFixedTime(boolean hasFixedTime, int timeSet) { this.dimTypeBuilder.hasFixedTime(hasFixedTime); + this.timeFixed = timeSet; return this; } + public AmbientBuilder hasFixedTime(boolean hasFixedTime) { + this.dimTypeBuilder.hasFixedTime(hasFixedTime); + return this; + } public AmbientBuilder skybox(String skybox) { this.dimTypeBuilder.skybox(skybox); return this; diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java new file mode 100644 index 000000000..3009bedcb --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java @@ -0,0 +1,60 @@ +package fr.openmc.core.registry.ambient.contents; + +import fr.openmc.api.datapacks.builders.BiomeBuilder; +import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; +import fr.openmc.core.registry.ambient.CustomAmbient; +import fr.openmc.core.registry.ambient.CustomAmbientRegistry; +import fr.openmc.core.registry.ambient.builder.AmbientBuilder; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.dimension.DimensionType; +import org.bukkit.Particle; + +public class BloodyAmbient extends CustomAmbient { + @Override + public String getId() { + return "bloody_ambient"; + } + + @Override + public AmbientBuilder getAmbientBuilder() { + return new AmbientBuilder(CustomAmbientRegistry.NAMESPACE, this.getId()) + .attributesBuilder(new EnvironnementAttributeBuilder() + .attributes(obj -> { + obj.addProperty("visual/block_light_tint", "#F53200"); + obj.addProperty("visual/ambient_light_color", "#FF5C57"); + obj.addProperty("minecraft:visual/sky_light_factor", 0.7); + + obj.addProperty("visual/fog_start_distance", 40); + obj.addProperty("visual/fog_end_distance", 70); + obj.addProperty("visual/fog_color","#800000"); + + obj.addProperty("visual/moon_angle", 67); + obj.addProperty("visual/star_brightness", 0.7); + + obj.addProperty("visual/cloud_height", 70); + obj.addProperty("visual/cloud_color", "#e58c2b2b"); + + obj.addProperty("visual/water_fog_color", "#330505"); + }) + .ambientParticles(Particle.CRIMSON_SPORE, 0.01f) + .ambientParticles(Particle.RAID_OMEN, 0.002f)) + .ambientLight(0f) + .cardinalLight("nether") + .skybox(DimensionType.Skybox.OVERWORLD) + .hasSkylight(false) + .hasCeiling(true) + .biomes(new BiomeBuilder() + .hasPrecipitation(false) + .waterColor("#F24545")) + + .defaultClock("overworld") + .timelines("#minecraft:in_overworld") + .hasFixedTime(true, 21000); + } + + @Override + public ResourceKey getTransitionDimension() { + return Level.NETHER; + } +} diff --git a/src/main/java/fr/openmc/core/utils/nms/PlayerSetTimeNMS.java b/src/main/java/fr/openmc/core/utils/nms/PlayerSetTimeNMS.java new file mode 100644 index 000000000..660a58a20 --- /dev/null +++ b/src/main/java/fr/openmc/core/utils/nms/PlayerSetTimeNMS.java @@ -0,0 +1,43 @@ +package fr.openmc.core.utils.nms; + +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.protocol.game.ClientboundSetTimePacket; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.clock.ClockNetworkState; +import net.minecraft.world.clock.WorldClock; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; + +public class PlayerSetTimeNMS { + + /** + * Envoie un packet au joueur pour définir l'heure du monde + * @param player le joueur a qui envoyé le packet + * @param time le temps envoyé + */ + public static void sendPacketSetTime(Player player, int time) { + ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle(); + + Registry clockRegistry = MinecraftServer.getServer() + .registryAccess() + .lookupOrThrow(Registries.WORLD_CLOCK); + + Map, ClockNetworkState> clockUpdates = new HashMap<>(); + + clockRegistry.listElements().forEach(clockHolder -> { + ClockNetworkState state = new ClockNetworkState(time, 0.0F, 0.0F); + clockUpdates.put(clockHolder, state); + }); + + long gameTime = serverPlayer.level().getGameTime(); + ClientboundSetTimePacket packet = new ClientboundSetTimePacket(gameTime, clockUpdates); + + serverPlayer.connection.send(packet); + } +} From 9da5ca4f4d3090cd139e4478e4e264d22b1d4c62 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sun, 14 Jun 2026 12:31:42 +0200 Subject: [PATCH 35/74] BloodyAmbient + blood moon --- .../registry/ambient/contents/BloodyAmbient.java | 9 +++++---- .../full_moon.png | Bin 0 -> 6954 bytes 2 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 src/main/resources/contents/omc_daily_events/resourcepack.assets.minecraft.textures.environment.celestial.moon/full_moon.png diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java index 3009bedcb..22a8d8432 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java @@ -29,16 +29,17 @@ public AmbientBuilder getAmbientBuilder() { obj.addProperty("visual/fog_end_distance", 70); obj.addProperty("visual/fog_color","#800000"); + obj.addProperty("visual/moon_phase", "full_moon"); obj.addProperty("visual/moon_angle", 67); obj.addProperty("visual/star_brightness", 0.7); - obj.addProperty("visual/cloud_height", 70); - obj.addProperty("visual/cloud_color", "#e58c2b2b"); + obj.addProperty("visual/cloud_height", 65); + obj.addProperty("visual/cloud_color", "#7e8c2b2b"); obj.addProperty("visual/water_fog_color", "#330505"); }) .ambientParticles(Particle.CRIMSON_SPORE, 0.01f) - .ambientParticles(Particle.RAID_OMEN, 0.002f)) + .ambientParticles(Particle.RAID_OMEN, 0.001f)) .ambientLight(0f) .cardinalLight("nether") .skybox(DimensionType.Skybox.OVERWORLD) @@ -46,7 +47,7 @@ public AmbientBuilder getAmbientBuilder() { .hasCeiling(true) .biomes(new BiomeBuilder() .hasPrecipitation(false) - .waterColor("#F24545")) + .waterColor("#700000")) .defaultClock("overworld") .timelines("#minecraft:in_overworld") diff --git a/src/main/resources/contents/omc_daily_events/resourcepack.assets.minecraft.textures.environment.celestial.moon/full_moon.png b/src/main/resources/contents/omc_daily_events/resourcepack.assets.minecraft.textures.environment.celestial.moon/full_moon.png new file mode 100644 index 0000000000000000000000000000000000000000..a97e7272f6574ae896d030768da88c6d103a3813 GIT binary patch literal 6954 zcmeI1ZBSEJ8pm(aKq=HE6s)flYCDoGR-m=Q3M6Su>q`|_hefcJptOjq11w@g0^~*4 zm(?zIhZa%5gsBd#P@uk)LV|(D6BSfmVw#6<`ZFoXbkyUE?>p3HvtLuYo~$*1Jx zK67&JbAQkO`JZ$DlAO4CiSJ5Z48xXe-IA~q!>I6;iuriM$9&O0?HIPwv^C+~lp@NE zChAI!eyLYqu~t^F*Yt@u?Wj-xCBNls=#Bl~sY2g6{$ki`TgrFV?70*0`-dx*e{zda znc};CpTV&9&tK?RM`x5721Rjix`R7<`>$#RKEKFci5m;rR>*rTxliBYIDpLt&f z);=t&CI_dzf<*tCtw|KYpq=W=&Rbj`#uj1XeH1TgOi5i}C|ksC5>flA+Phz%hq9$< zYzpHyS_9389@-Z!#pbh(1u!F>@p3YDTFKq?t4^QaTAdxN>nxCUPvh2wbK}JC>{a8A z2twW3rO+CvEi&Tpypp)!NXc`#w}foim1uU+set6i$ql2 zD)@l=JP!A{cQSD;8u*Ix$lqu_L6DW>wXx^XfPvj4f1`&cGo)D1i6@_;ffTcPdnSIC zQjyP#jI&>rzlWRr6(PPwiJ46u^~;(p>j`a-BwpCYClt6rU2hTM!^%O2(6(4N=#Vf~ z_c<a6gWNph$q{#h8W%b~TP)cyGB#is zJTp|k;^KonsYYV*jCz-mn6?cJI`TL!lSVlc)-XyGTyyyUa^$C*!snXp<{NQHYGT$( zvDJsor;+|NfS#sy?dPFd%iqqX#7s;qMPX@xU_+UD4za1L6jAe4J>e*L!5x8p7j!bJWOF-7gNf#%R)wbg|A!vqU(mW3f*I3 zRp~2@MlE(JaDxPKNdrQ#w!a~&LV?6ffsvjIo|J^LpB9GoEqZg#^sFuC$F918a+%)= zDcO*Z4d}lqWgS-DjgaGuJ&#&j-WQvD!jzmlOht{;#s3LVwO>AT7KD zmMvX4fCP`7z^0sPUbPMB&{gQW_qByc7U==W*qZ4RFCkHD5K+Heh^|2_CjiSnvRXIG z;AKB`?(qD@|8t^x6|Ig(o6eV{XS^zKOx}BhTSxY*CAYab89K6KtAz#J^mbx#TtT=( zMv~In368L&g-=*QvZo>lbA0URK?GFa8&d50T4OFb_!j!~l`$@Ac-Mi(@9)a0NVu** zi+pSiM$Pkkfbrnm6LPyDhIT96B|t( z@q;yj*ka}dXVfdKV%K~YzI{4+w8XjN(2t$}QNC{?nEr{9vx3>dZrfR!@F8?x?>hBn z&PgFLu}UR)D6m?F6qHI^G1^SfQUS2=tZN&P_Emx-dz;ndHhbH^#eH_D!o8z?8wL~l zcie9Ax8N4P=;=oymkAD2h0EPh;XvruKcrtkQm6tcJTGzYcQP-7S$u2bM{cutUPO&F zo83_jL10R6XCFXS5DC67Tae+7`Wn3AKYm%~US>87RBCsvH17mYx}xf`dzs*4D{VZ_ z&5#L9`>#J4T|vBL^BLjt_Fk4tzbnH0(Tf|cBQ1H}P3EK!ZM-UC@39+H{|dtF=w~VJ zCGthe6-I4+gS(N)a!fgxqe*;bBx!_5O5B(`&5SyD=rTI0g z_H|8kg=4z>u5Gl!4|j4{jV~9KSn?NK6=9J9*14Iaa=od=$Wo=Ic@Aelv^_^lprTK8 z?goG{0kG9X=A3o^?BZ29bx&?D>$$&=g+HkNP@*+;h8V_e@)6>-s9S;wzQ*airDOK% z9OF1~lh{J9mGGjgWw=^9%U8QM8sEX;-Aeg2}u6?;P7TLl!Xu41EJ;)Yb23vSwwwLV2;#{zWvBDu_3q8{V-OqY*&ROdG zl>_Ivrwq3D+YRO^p51TQqCfb#tI$4EKp30`3wlw*vpip@h!b%Q{zWlDyQSF1G1gwx zBeNz=fj2EnMu*8kADpxl>WzF7Ee0GrZ#%}_NTO8;?N(!xp@X<>fL6b*2AL}jpv84H zl5JSL6VTdFv>&0>0y~Zx#S|j<*P32TU~z8<`VO5rwGZBbVOu{)OlW*B^XR_;KIN5F literal 0 HcmV?d00001 From d0ff2ff03037d5609d811fa77e91dc25092a25bc Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sun, 14 Jun 2026 20:21:38 +0200 Subject: [PATCH 36/74] fix: swapping between 2 ambient (biomes arent applied) --- .../core/registry/ambient/CustomAmbient.java | 5 +-- .../ambient/listeners/BiomesOnChunkLoad.java | 2 +- .../registry/lootboxes/LootboxOpenMenu.java | 1 - .../openmc/core/utils/nms/PlayerBiomeNMS.java | 32 +++++++++++-------- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java index e5a4a1222..8a38e550b 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java @@ -54,8 +54,9 @@ public void apply(Player player) { getTransitionDimensionForPlayer(nmsPlayer) ); - if (this.getAmbientBuilder().utilizeBiome()) - PlayerBiomeNMS.replaceBiomes(nmsPlayer, this::toBiomeVariantKey); + if (this.getAmbientBuilder().utilizeBiome()) { + PlayerBiomeNMS.replaceBiomes(nmsPlayer, this.getId(), this::toBiomeVariantKey); + } if (this.getAmbientBuilder().getTimeFixed() != null) { PlayerSetTimeNMS.sendPacketSetTime(player, this.getAmbientBuilder().getTimeFixed()); diff --git a/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java b/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java index cfc625589..da5876232 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java +++ b/src/main/java/fr/openmc/core/registry/ambient/listeners/BiomesOnChunkLoad.java @@ -37,6 +37,6 @@ public void onChunkLoad(PlayerChunkLoadEvent event) { ChunkAccess chunkAccess = ((CraftChunk) event.getChunk()).getHandle(ChunkStatus.FULL); if (!(chunkAccess instanceof LevelChunk nmsChunk)) return; - PlayerBiomeNMS.remplaceBiome(nmsPlayer, nmsChunk, ambientApplied::toBiomeVariantKey); + PlayerBiomeNMS.remplaceBiome(nmsPlayer, nmsChunk, ambientApplied.getId(), ambientApplied::toBiomeVariantKey); } } diff --git a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java index c6063823b..40182a97b 100644 --- a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java +++ b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java @@ -179,7 +179,6 @@ private void finishAnimation(boolean withLatency) { @Override public void run() { boolean cancelled = giveReward(winningItem); - System.out.println(cancelled); if (cancelled) { cancel(); return; diff --git a/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java b/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java index 257a6cf4c..9407bd618 100644 --- a/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java +++ b/src/main/java/fr/openmc/core/utils/nms/PlayerBiomeNMS.java @@ -91,10 +91,12 @@ public static void sendBiomes(Player player, Holder biome) { public static void remplaceBiome( ServerPlayer nmsPlayer, LevelChunk initialChunk, + String keyMappedBiome, Function identifierModifier) { List biomeDataList = new ArrayList<>(); LevelChunk fakeChunk = PlayerBiomeNMS.getFakeChunkWithMapping( initialChunk, + keyMappedBiome, identifierModifier ); ClientboundChunksBiomesPacket.ChunkBiomeData data = new ClientboundChunksBiomesPacket.ChunkBiomeData(fakeChunk); @@ -103,7 +105,10 @@ public static void remplaceBiome( nmsPlayer.connection.send(packet); } - public static void replaceBiomes(ServerPlayer nmsPlayer, Function identifierModifier) { + public static void replaceBiomes( + ServerPlayer nmsPlayer, + String keyMappedBiome, + Function identifierModifier) { ServerLevel nmsWorld = nmsPlayer.level(); int viewDistance = nmsWorld.getServer().getPlayerList().getViewDistance(); @@ -115,7 +120,7 @@ public static void replaceBiomes(ServerPlayer nmsPlayer, Function, Holder> BIOME_CACHE = new HashMap<>(); - private static final Map, Identifier> ID_MAPPED_BIOME_CACHE = new HashMap<>(); - + private static final Map> BIOME_CACHE = new HashMap<>(); /** * Crée un faux chunk en se basant sur l'originel et en changeant juste le biome du chunk en fonction * d'un identifierModifier @@ -167,6 +170,7 @@ public static LevelChunk getFakeChunk(LevelChunk original, ServerLevel level, Ho */ private static LevelChunk getFakeChunkWithMapping( LevelChunk original, + String keyMappedBiome, Function identifierModifier) { LevelChunk fake = new LevelChunk(original.level, original.getPos()); @@ -191,7 +195,7 @@ private static LevelChunk getFakeChunkWithMapping( // ** Si le chunk contient qu'un biome if (originalBiomes.data.palette().getSize() == 1) { Holder single = originalBiomes.data.palette().valueFor(0); - Holder mapped = getMapped(single, registry, identifierModifier); + Holder mapped = getMapped(single, registry, keyMappedBiome, identifierModifier); PalettedContainer> fakeBiomes1 = new PalettedContainer<>(mapped, idMap, null); try { @@ -212,7 +216,7 @@ private static LevelChunk getFakeChunkWithMapping( for (int y = 0; y < 4; y++) { for (int z = 0; z < 4; z++) { Holder originalBiome = originalSection.getNoiseBiome(x, y, z); - Holder mapped = getMapped(originalBiome, registry, identifierModifier); + Holder mapped = getMapped(originalBiome, registry, keyMappedBiome, identifierModifier); fakeBiomes.set(x, y, z, mapped); } @@ -232,14 +236,14 @@ private static LevelChunk getFakeChunkWithMapping( private static Holder getMapped( Holder original, Registry registry, + String keyMappedBiome, Function identifierModifier) { - return BIOME_CACHE.computeIfAbsent(original, b -> { - Identifier keyModified = ID_MAPPED_BIOME_CACHE.computeIfAbsent(original, m -> - identifierModifier.apply( - m.unwrapKey().orElseThrow().identifier() - ) - ); - return registry.get(keyModified).orElseThrow(); + Identifier originalId = original.unwrapKey().orElseThrow().identifier(); + String cacheKey = keyMappedBiome + "/" + originalId; + + return BIOME_CACHE.computeIfAbsent(cacheKey, k -> { + Identifier mappedId = identifierModifier.apply(originalId); + return registry.get(mappedId).orElseThrow(); }); } } From 7c91878f75761176b6a7bf34fe9ed71a356021f2 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Mon, 15 Jun 2026 12:23:43 +0200 Subject: [PATCH 37/74] =?UTF-8?q?fix:=20golden=20ambient=20moon/sun/blood?= =?UTF-8?q?=5F=C3=B9moon=20weird?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ambient/contents/GoldenAmbient.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java index d170d562e..214aeae3b 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java @@ -2,7 +2,6 @@ import fr.openmc.api.datapacks.builders.BiomeBuilder; import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; -import fr.openmc.api.datapacks.builders.TimelineBuilder; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.registry.ambient.CustomAmbientRegistry; import fr.openmc.core.registry.ambient.builder.AmbientBuilder; @@ -22,13 +21,16 @@ public AmbientBuilder getAmbientBuilder() { .attributesBuilder(new EnvironnementAttributeBuilder() .attributes(obj -> { obj.addProperty("visual/block_light_tint", "#FFE02E"); - obj.addProperty("visual/ambient_light_color", "#FFE02E"); - obj.addProperty("visual/sky_color", "#FFD700"); + obj.addProperty("visual/ambient_light_color", "#211D07"); obj.addProperty("visual/sky_light_color", "#FFDE17"); + + obj.addProperty("visual/sky_color", "#E3AA00"); + obj.addProperty("visual/sunrise_sunset_color", "#ccfa6f25"); + obj.addProperty("visual/fog_color", "#AA9B27"); obj.addProperty("visual/fog_start_distance", 70); obj.addProperty("visual/fog_end_distance", 80); - obj.addProperty("visual/sunrise_sunset_color", "#ccfa6f25"); + obj.addProperty("visual/cloud_height", 100); obj.addProperty("visual/cloud_color", "#4cffde50"); }) @@ -36,11 +38,11 @@ public AmbientBuilder getAmbientBuilder() { ) .skybox(DimensionType.Skybox.OVERWORLD) .hasSkylight(true) - .timelines(new TimelineBuilder() - .clock("minecraft:overworld") - .periodTicks(24000)) .biomes(new BiomeBuilder() - .hasPrecipitation(false)); + .hasPrecipitation(false)) + .defaultClock("overworld") + .timelines("#minecraft:in_overworld") + .hasFixedTime(true, 6000); } @Override From 215bb4d278d604070f83227670acdc37d0f4bd43 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Mon, 15 Jun 2026 13:10:19 +0200 Subject: [PATCH 38/74] add BlessedAmbient --- .../ambient/CustomAmbientRegistry.java | 6 +-- .../ambient/contents/BlessedAmbient.java | 54 +++++++++++++++++++ 2 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java index 08e71faf6..01243c4fa 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java @@ -5,10 +5,7 @@ import fr.openmc.core.bootstrap.integration.OMCLogger; import fr.openmc.core.bootstrap.registries.KeyedRegistry; import fr.openmc.core.bootstrap.registries.Registry; -import fr.openmc.core.registry.ambient.contents.BloodyAmbient; -import fr.openmc.core.registry.ambient.contents.DarkAmbient; -import fr.openmc.core.registry.ambient.contents.GoldenAmbient; -import fr.openmc.core.registry.ambient.contents.HellAmbient; +import fr.openmc.core.registry.ambient.contents.*; import io.papermc.paper.plugin.bootstrap.BootstrapContext; import net.minecraft.core.registries.Registries; import net.minecraft.server.MinecraftServer; @@ -27,6 +24,7 @@ public class CustomAmbientRegistry extends Registry imple public final CustomAmbient HELL = register(new HellAmbient()); public final CustomAmbient GOLDEN = register(new GoldenAmbient()); public final CustomAmbient BLOODY = register(new BloodyAmbient()); + public final CustomAmbient BLESSED = register(new BlessedAmbient()); @Override public String key(CustomAmbient registryObject) { diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java new file mode 100644 index 000000000..fc50dcf4e --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java @@ -0,0 +1,54 @@ +package fr.openmc.core.registry.ambient.contents; + +import fr.openmc.api.datapacks.builders.BiomeBuilder; +import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; +import fr.openmc.core.registry.ambient.CustomAmbient; +import fr.openmc.core.registry.ambient.CustomAmbientRegistry; +import fr.openmc.core.registry.ambient.builder.AmbientBuilder; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.dimension.DimensionType; +import org.bukkit.Particle; + +public class BlessedAmbient extends CustomAmbient { + @Override + public String getId() { + return "blessed_ambient"; + } + + @Override + public AmbientBuilder getAmbientBuilder() { + return new AmbientBuilder(CustomAmbientRegistry.NAMESPACE, this.getId()) + .attributesBuilder(new EnvironnementAttributeBuilder() + .attributes(obj -> { + obj.addProperty("visual/sky_light_color", "#FFEB1F"); + obj.addProperty("visual/ambient_light_color", "#001A19"); + + obj.addProperty("visual/sunrise_sunset_color", "#e540e58b"); + obj.addProperty("visual/sky_color", "#92E6FC"); + + obj.addProperty("visual/fog_start_distance", 0); + obj.addProperty("visual/fog_end_distance", 512); + obj.addProperty("visual/fog_color", "#5CFFD3"); + obj.addProperty("visual/water_fog_color", "#75FFD1"); + + obj.addProperty("visual/cloud_height", 240); + }) + .ambientParticles(Particle.OMINOUS_SPAWNING, 0.01) + .ambientParticles(Particle.FISHING, 0.004) + ) + .ambientLight(0.2f) + .skybox(DimensionType.Skybox.OVERWORLD) + .hasSkylight(true) + .biomes(new BiomeBuilder() + .waterColor("#43C6EE")) + .defaultClock("overworld") + .timelines("#minecraft:in_overworld") + .hasFixedTime(true, 200); + } + + @Override + public ResourceKey getTransitionDimension() { + return Level.END; + } +} From 353c91d14bc6336496e0e265898f8aac9f3740a1 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Mon, 15 Jun 2026 16:08:05 +0200 Subject: [PATCH 39/74] add ambient sound builder + applied to BloodyAmbient --- .../EnvironnementAttributeBuilder.java | 6 + .../builders/sounds/AmbientSoundBuilder.java | 124 ++++++++++++++++++ .../builders/sounds/SoundEventBuilder.java | 31 +++++ .../ambient/builder/AmbientBuilder.java | 3 + .../ambient/contents/BlessedAmbient.java | 4 +- .../ambient/contents/BloodyAmbient.java | 17 ++- 6 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 src/main/java/fr/openmc/api/datapacks/builders/sounds/AmbientSoundBuilder.java create mode 100644 src/main/java/fr/openmc/api/datapacks/builders/sounds/SoundEventBuilder.java diff --git a/src/main/java/fr/openmc/api/datapacks/builders/EnvironnementAttributeBuilder.java b/src/main/java/fr/openmc/api/datapacks/builders/EnvironnementAttributeBuilder.java index b88b17ebb..e32588f98 100644 --- a/src/main/java/fr/openmc/api/datapacks/builders/EnvironnementAttributeBuilder.java +++ b/src/main/java/fr/openmc/api/datapacks/builders/EnvironnementAttributeBuilder.java @@ -2,6 +2,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import fr.openmc.api.datapacks.builders.sounds.AmbientSoundBuilder; import org.bukkit.Particle; import java.util.function.Consumer; @@ -92,4 +93,9 @@ public EnvironnementAttributeBuilder particleDustColorTransition(int fromColor, public EnvironnementAttributeBuilder ambientParticles(Particle particle, double probability) { return ambientParticles(particle.getKey().toString(), probability); } + + public EnvironnementAttributeBuilder ambientSounds(AmbientSoundBuilder ambientBuilder) { + this.attributes.add("audio/ambient_sounds", ambientBuilder.toJson()); + return this; + } } diff --git a/src/main/java/fr/openmc/api/datapacks/builders/sounds/AmbientSoundBuilder.java b/src/main/java/fr/openmc/api/datapacks/builders/sounds/AmbientSoundBuilder.java new file mode 100644 index 000000000..7ded7a833 --- /dev/null +++ b/src/main/java/fr/openmc/api/datapacks/builders/sounds/AmbientSoundBuilder.java @@ -0,0 +1,124 @@ +package fr.openmc.api.datapacks.builders.sounds; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +/** Environnement Attribute de son + * "minecraft:audio/ambient_sounds": { + * "loop": "minecraft:ambient.crimson_forest.loop", + * "mood": { + * "sound": "minecraft:ambient.basalt_deltas.additions", + * "tick_delay": 0, + * "block_search_extent": 0, + * "offset": 0 + * }, + * "additions": [ + * { + * "sound": "minecraft:ambient.basalt_deltas.loop", + * "tick_chance": 0 + * } + * ] + * } + */ +public class AmbientSoundBuilder { + private JsonElement loop; + private JsonObject mood; + private JsonObject additions; + + public AmbientSoundBuilder mood(MoodBuilder moodBuilder) { + this.mood = moodBuilder.toJson(); + return this; + } + + public AmbientSoundBuilder additions(AdditionsBuilder additionsBuilder) { + this.additions = additionsBuilder.toJson(); + return this; + } + + public AmbientSoundBuilder loop(String soundId) { + this.loop = new JsonPrimitive(soundId); + return this; + } + + public AmbientSoundBuilder loop(SoundEventBuilder soundEventBuilder) { + this.loop = soundEventBuilder.toJson(); + return this; + } + + public JsonObject toJson() { + JsonObject json = new JsonObject(); + if (mood != null) json.add("mood", mood); + if (additions != null) json.add("additions", additions); + if (loop != null) json.add("loop", loop); + return json; + } + + public static class MoodBuilder { + private Integer blockSearchExtent; + private Integer offset; + private JsonElement sound; + private Integer tickDelay; + + public MoodBuilder blockSearchExtent(int value) { + this.blockSearchExtent = value; + return this; + } + + public MoodBuilder offset(int value) { + this.offset = value; + return this; + } + + public MoodBuilder tickDelay(int value) { + this.tickDelay = value; + return this; + } + + public MoodBuilder sound(String soundId) { + this.sound = new JsonPrimitive(soundId); + return this; + } + + public MoodBuilder sound(SoundEventBuilder soundEventBuilder) { + this.sound = soundEventBuilder.toJson(); + return this; + } + + public JsonObject toJson() { + JsonObject json = new JsonObject(); + if (blockSearchExtent != null) json.addProperty("block_search_extent", blockSearchExtent); + if (offset != null) json.addProperty("offset", offset); + if (sound != null) json.add("sound", sound); + if (tickDelay != null) json.addProperty("tick_delay", tickDelay); + return json; + } + } + + public static class AdditionsBuilder { + private JsonElement sound; + private Double tickChance; + + public AdditionsBuilder sound(String soundId) { + this.sound = new JsonPrimitive(soundId); + return this; + } + + public AdditionsBuilder sound(SoundEventBuilder soundEventBuilder) { + this.sound = soundEventBuilder.toJson(); + return this; + } + + public AdditionsBuilder tickChance(double value) { + this.tickChance = value; + return this; + } + + public JsonObject toJson() { + JsonObject json = new JsonObject(); + if (sound != null) json.add("sound", sound); + if (tickChance != null) json.addProperty("tick_chance", tickChance); + return json; + } + } +} diff --git a/src/main/java/fr/openmc/api/datapacks/builders/sounds/SoundEventBuilder.java b/src/main/java/fr/openmc/api/datapacks/builders/sounds/SoundEventBuilder.java new file mode 100644 index 000000000..bba0a6667 --- /dev/null +++ b/src/main/java/fr/openmc/api/datapacks/builders/sounds/SoundEventBuilder.java @@ -0,0 +1,31 @@ +package fr.openmc.api.datapacks.builders.sounds; + +import com.google.gson.JsonObject; + +/** + * { + * "sound_id": "minecraft:music.game", + * "range": 1 + * } + */ +public class SoundEventBuilder { + private String soundId; + private Integer range; + + public SoundEventBuilder soundId(String id) { + this.soundId = id; + return this; + } + + public SoundEventBuilder range(int range) { + this.range = range; + return this; + } + + public JsonObject toJson() { + JsonObject json = new JsonObject(); + if (soundId != null) json.addProperty("sound_id", soundId); + if (range != null) json.addProperty("range", range); + return json; + } +} diff --git a/src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java b/src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java index 50dd10b50..4937b98c1 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java +++ b/src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java @@ -32,6 +32,9 @@ public class AmbientBuilder { @Getter private Integer timeFixed = null; + // todo attribut weatherFixed (bool) + // todo attribut weather (str) (si true) + public AmbientBuilder(String namepace, String id) { this.namespace = namepace; this.id = id; diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java index fc50dcf4e..44a99456d 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java @@ -21,7 +21,7 @@ public AmbientBuilder getAmbientBuilder() { return new AmbientBuilder(CustomAmbientRegistry.NAMESPACE, this.getId()) .attributesBuilder(new EnvironnementAttributeBuilder() .attributes(obj -> { - obj.addProperty("visual/sky_light_color", "#FFEB1F"); + obj.addProperty("visual/sky_light_color", "#FAED5C"); obj.addProperty("visual/ambient_light_color", "#001A19"); obj.addProperty("visual/sunrise_sunset_color", "#e540e58b"); @@ -41,7 +41,7 @@ public AmbientBuilder getAmbientBuilder() { .skybox(DimensionType.Skybox.OVERWORLD) .hasSkylight(true) .biomes(new BiomeBuilder() - .waterColor("#43C6EE")) + .waterColor("#43d5ee")) .defaultClock("overworld") .timelines("#minecraft:in_overworld") .hasFixedTime(true, 200); diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java index 22a8d8432..39486ca1f 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java @@ -2,6 +2,7 @@ import fr.openmc.api.datapacks.builders.BiomeBuilder; import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; +import fr.openmc.api.datapacks.builders.sounds.AmbientSoundBuilder; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.registry.ambient.CustomAmbientRegistry; import fr.openmc.core.registry.ambient.builder.AmbientBuilder; @@ -39,7 +40,21 @@ public AmbientBuilder getAmbientBuilder() { obj.addProperty("visual/water_fog_color", "#330505"); }) .ambientParticles(Particle.CRIMSON_SPORE, 0.01f) - .ambientParticles(Particle.RAID_OMEN, 0.001f)) + .ambientParticles(Particle.RAID_OMEN, 0.001f) + .ambientSounds(new AmbientSoundBuilder() + .loop("minecraft:ambient.soul_sand_valley.loop") + .mood(new AmbientSoundBuilder.MoodBuilder() + .sound("minecraft:ambient.soul_sand_valley.mood") + .tickDelay(2000) + .offset(2) + .blockSearchExtent(8) + ) + .additions(new AmbientSoundBuilder.AdditionsBuilder() + .sound("minecraft:ambient.cave") + .tickChance(0.001) + ) + ) + ) .ambientLight(0f) .cardinalLight("nether") .skybox(DimensionType.Skybox.OVERWORLD) From 3964c60ba271af6dd43db74826ae12770a7cf3ec Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 16 Jun 2026 13:39:25 +0200 Subject: [PATCH 40/74] add weather type to builder --- .../java/fr/openmc/core/ListenersManager.java | 4 ++- .../core/registry/ambient/CustomAmbient.java | 5 +++ .../ambient/builder/AmbientBuilder.java | 12 +++++-- .../ambient/contents/BlessedAmbient.java | 4 ++- .../ambient/contents/BloodyAmbient.java | 4 ++- .../ambient/contents/GoldenAmbient.java | 7 +++-- .../listeners/AmbientWeatherListener.java | 27 ++++++++++++++++ .../core/utils/nms/PlayerWeatherNMS.java | 31 +++++++++++++++++++ .../fr/openmc/core/utils/nms/WeatherType.java | 7 +++++ 9 files changed, 93 insertions(+), 8 deletions(-) create mode 100644 src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientWeatherListener.java create mode 100644 src/main/java/fr/openmc/core/utils/nms/PlayerWeatherNMS.java create mode 100644 src/main/java/fr/openmc/core/utils/nms/WeatherType.java diff --git a/src/main/java/fr/openmc/core/ListenersManager.java b/src/main/java/fr/openmc/core/ListenersManager.java index 8df94dfe3..3e6547eb0 100644 --- a/src/main/java/fr/openmc/core/ListenersManager.java +++ b/src/main/java/fr/openmc/core/ListenersManager.java @@ -5,6 +5,7 @@ import fr.openmc.core.features.itemsadder.SpawnerExtractorListener; import fr.openmc.core.hooks.itemsadder.ItemsAdderHook; import fr.openmc.core.listeners.*; +import fr.openmc.core.registry.ambient.listeners.AmbientWeatherListener; import fr.openmc.core.registry.ambient.listeners.BiomesOnChunkLoad; import fr.openmc.core.registry.ambient.listeners.CustomAmbientListener; import org.bukkit.Bukkit; @@ -37,7 +38,8 @@ public static void init() { new ArmorListener(), new BlockBreakListener(), new CustomAmbientListener(), - new BiomesOnChunkLoad() + new BiomesOnChunkLoad(), + new AmbientWeatherListener() ); if (!OMCPlugin.isUnitTestVersion()) { diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java index 8a38e550b..2b54f46ce 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java @@ -8,6 +8,7 @@ import fr.openmc.core.utils.nms.PlayerBiomeNMS; import fr.openmc.core.utils.nms.PlayerRespawnNMS; import fr.openmc.core.utils.nms.PlayerSetTimeNMS; +import fr.openmc.core.utils.nms.PlayerWeatherNMS; import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; @@ -62,6 +63,10 @@ public void apply(Player player) { PlayerSetTimeNMS.sendPacketSetTime(player, this.getAmbientBuilder().getTimeFixed()); } + if (this.getAmbientBuilder().getWeatherFixed() != null) { + PlayerWeatherNMS.setWeather(player, this.getAmbientBuilder().getWeatherFixed()); + } + ACTIVE_AMBIENTS.put(player.getUniqueId(), this.getId()); } diff --git a/src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java b/src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java index 4937b98c1..470f067b9 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java +++ b/src/main/java/fr/openmc/core/registry/ambient/builder/AmbientBuilder.java @@ -10,6 +10,7 @@ import fr.openmc.api.datapacks.injectors.TimelinesInjector; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.registry.ambient.CustomAmbientRegistry; +import fr.openmc.core.utils.nms.WeatherType; import lombok.Getter; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; @@ -32,8 +33,8 @@ public class AmbientBuilder { @Getter private Integer timeFixed = null; - // todo attribut weatherFixed (bool) - // todo attribut weather (str) (si true) + @Getter + private WeatherType weatherFixed = null; public AmbientBuilder(String namepace, String id) { this.namespace = namepace; @@ -134,6 +135,13 @@ public AmbientBuilder hasPrecipitation(Boolean bool) { return this; } + public AmbientBuilder hasPrecipitation(Boolean bool, WeatherType type) { + if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); + this.biomeBuilder.hasPrecipitation(bool); + this.weatherFixed = type; + return this; + } + public AmbientBuilder effects(Consumer builder) { if (biomeBuilder == null) biomeBuilder = new BiomeBuilder(); this.biomeBuilder.effects(builder); diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java index 44a99456d..29c3a64a5 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java @@ -5,6 +5,7 @@ import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.registry.ambient.CustomAmbientRegistry; import fr.openmc.core.registry.ambient.builder.AmbientBuilder; +import fr.openmc.core.utils.nms.WeatherType; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; import net.minecraft.world.level.dimension.DimensionType; @@ -44,7 +45,8 @@ public AmbientBuilder getAmbientBuilder() { .waterColor("#43d5ee")) .defaultClock("overworld") .timelines("#minecraft:in_overworld") - .hasFixedTime(true, 200); + .hasFixedTime(true, 200) + .hasPrecipitation(true, WeatherType.NONE); } @Override diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java index 39486ca1f..dde6dc0e4 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java @@ -6,6 +6,7 @@ import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.registry.ambient.CustomAmbientRegistry; import fr.openmc.core.registry.ambient.builder.AmbientBuilder; +import fr.openmc.core.utils.nms.WeatherType; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; import net.minecraft.world.level.dimension.DimensionType; @@ -66,7 +67,8 @@ public AmbientBuilder getAmbientBuilder() { .defaultClock("overworld") .timelines("#minecraft:in_overworld") - .hasFixedTime(true, 21000); + .hasFixedTime(true, 21000) + .hasPrecipitation(false, WeatherType.NONE); } @Override diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java index 214aeae3b..5a2822a28 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java @@ -5,6 +5,7 @@ import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.registry.ambient.CustomAmbientRegistry; import fr.openmc.core.registry.ambient.builder.AmbientBuilder; +import fr.openmc.core.utils.nms.WeatherType; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; import net.minecraft.world.level.dimension.DimensionType; @@ -38,11 +39,11 @@ public AmbientBuilder getAmbientBuilder() { ) .skybox(DimensionType.Skybox.OVERWORLD) .hasSkylight(true) - .biomes(new BiomeBuilder() - .hasPrecipitation(false)) + .biomes(new BiomeBuilder()) .defaultClock("overworld") .timelines("#minecraft:in_overworld") - .hasFixedTime(true, 6000); + .hasFixedTime(true, 6000) + .hasPrecipitation(false, WeatherType.NONE); } @Override diff --git a/src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientWeatherListener.java b/src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientWeatherListener.java new file mode 100644 index 000000000..d79e483e7 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientWeatherListener.java @@ -0,0 +1,27 @@ +package fr.openmc.core.registry.ambient.listeners; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.ambient.CustomAmbient; +import fr.openmc.core.utils.nms.PlayerWeatherNMS; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.weather.WeatherChangeEvent; + +public class AmbientWeatherListener implements Listener { + + @EventHandler + public void onWeatherChange(WeatherChangeEvent event) { + for (Player player : event.getWorld().getPlayers()) { + if (!CustomAmbient.ACTIVE_AMBIENTS.containsKey(player.getUniqueId())) continue; + + CustomAmbient ambientApplied = OMCRegistry.CUSTOM_AMBIENTS.getOrThrow( + CustomAmbient.ACTIVE_AMBIENTS.get(player.getUniqueId()) + ); + + if (ambientApplied.getAmbientBuilder().getWeatherFixed() == null) continue; + + PlayerWeatherNMS.setWeather(player, ambientApplied.getAmbientBuilder().getWeatherFixed()); + } + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/utils/nms/PlayerWeatherNMS.java b/src/main/java/fr/openmc/core/utils/nms/PlayerWeatherNMS.java new file mode 100644 index 000000000..80e7be005 --- /dev/null +++ b/src/main/java/fr/openmc/core/utils/nms/PlayerWeatherNMS.java @@ -0,0 +1,31 @@ +package fr.openmc.core.utils.nms; + +import net.minecraft.network.protocol.game.ClientboundGameEventPacket; +import net.minecraft.server.level.ServerPlayer; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Player; + +public class PlayerWeatherNMS { + public static void setWeather(Player player, WeatherType type) { + ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); + + switch (type) { + case NONE -> + send(nmsPlayer, ClientboundGameEventPacket.STOP_RAINING, 0.0f); + case RAIN -> { + send(nmsPlayer, ClientboundGameEventPacket.START_RAINING, 0.0f); + send(nmsPlayer, ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, 1.0f); + send(nmsPlayer, ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, 0.0f); + } + case STORM -> { + send(nmsPlayer, ClientboundGameEventPacket.START_RAINING, 0.0f); + send(nmsPlayer, ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, 1.0f); + send(nmsPlayer, ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, 1.0f); + } + } + } + + private static void send(ServerPlayer nmsPlayer, ClientboundGameEventPacket.Type event, float value) { + nmsPlayer.connection.send(new ClientboundGameEventPacket(event, value)); + } +} diff --git a/src/main/java/fr/openmc/core/utils/nms/WeatherType.java b/src/main/java/fr/openmc/core/utils/nms/WeatherType.java new file mode 100644 index 000000000..5aaa2c92f --- /dev/null +++ b/src/main/java/fr/openmc/core/utils/nms/WeatherType.java @@ -0,0 +1,7 @@ +package fr.openmc.core.utils.nms; + +public enum WeatherType { + NONE, + RAIN, + STORM +} From 9ee85329229c48e9577bf659219281b7c34c9202 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 16 Jun 2026 14:49:31 +0200 Subject: [PATCH 41/74] better ambience (sound) + fix weather clear --- .../registry/ambient/contents/BlessedAmbient.java | 13 +++++++++---- .../registry/ambient/contents/GoldenAmbient.java | 9 +++++++-- .../fr/openmc/core/utils/nms/PlayerWeatherNMS.java | 5 ++++- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java index 29c3a64a5..017d0899a 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java @@ -1,7 +1,7 @@ package fr.openmc.core.registry.ambient.contents; -import fr.openmc.api.datapacks.builders.BiomeBuilder; import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; +import fr.openmc.api.datapacks.builders.sounds.AmbientSoundBuilder; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.registry.ambient.CustomAmbientRegistry; import fr.openmc.core.registry.ambient.builder.AmbientBuilder; @@ -37,16 +37,21 @@ public AmbientBuilder getAmbientBuilder() { }) .ambientParticles(Particle.OMINOUS_SPAWNING, 0.01) .ambientParticles(Particle.FISHING, 0.004) + .ambientSounds(new AmbientSoundBuilder() + .additions(new AmbientSoundBuilder.AdditionsBuilder() + .sound("minecraft:ambient.underwater.loop.additions.rare") + .tickChance(0.001) + ) + ) ) .ambientLight(0.2f) .skybox(DimensionType.Skybox.OVERWORLD) .hasSkylight(true) - .biomes(new BiomeBuilder() - .waterColor("#43d5ee")) + .waterColor("#43d5ee") .defaultClock("overworld") .timelines("#minecraft:in_overworld") .hasFixedTime(true, 200) - .hasPrecipitation(true, WeatherType.NONE); + .hasPrecipitation(true, WeatherType.RAIN); } @Override diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java index 5a2822a28..72173ff22 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java @@ -1,7 +1,7 @@ package fr.openmc.core.registry.ambient.contents; -import fr.openmc.api.datapacks.builders.BiomeBuilder; import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; +import fr.openmc.api.datapacks.builders.sounds.AmbientSoundBuilder; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.registry.ambient.CustomAmbientRegistry; import fr.openmc.core.registry.ambient.builder.AmbientBuilder; @@ -36,10 +36,15 @@ public AmbientBuilder getAmbientBuilder() { obj.addProperty("visual/cloud_color", "#4cffde50"); }) .particleDustColorTransition(16776172, 16766720, 2, 0.01) + .ambientSounds(new AmbientSoundBuilder() + .additions(new AmbientSoundBuilder.AdditionsBuilder() + .sound("minecraft:block.amethyst_block.step") + .tickChance(0.1) + ) + ) ) .skybox(DimensionType.Skybox.OVERWORLD) .hasSkylight(true) - .biomes(new BiomeBuilder()) .defaultClock("overworld") .timelines("#minecraft:in_overworld") .hasFixedTime(true, 6000) diff --git a/src/main/java/fr/openmc/core/utils/nms/PlayerWeatherNMS.java b/src/main/java/fr/openmc/core/utils/nms/PlayerWeatherNMS.java index 80e7be005..89720ba6d 100644 --- a/src/main/java/fr/openmc/core/utils/nms/PlayerWeatherNMS.java +++ b/src/main/java/fr/openmc/core/utils/nms/PlayerWeatherNMS.java @@ -10,8 +10,11 @@ public static void setWeather(Player player, WeatherType type) { ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); switch (type) { - case NONE -> + case NONE -> { send(nmsPlayer, ClientboundGameEventPacket.STOP_RAINING, 0.0f); + send(nmsPlayer, ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, 0.0f); + send(nmsPlayer, ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, 0.0f); + } case RAIN -> { send(nmsPlayer, ClientboundGameEventPacket.START_RAINING, 0.0f); send(nmsPlayer, ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, 1.0f); From a1ab85ad7e23c29eddece16292f853e855421a63 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 16 Jun 2026 19:19:42 +0200 Subject: [PATCH 42/74] add broadcast --- .../dailyevents/DailyEventsManager.java | 15 ++--- .../bloodynight/BloodyNightEvent.java | 19 +++++-- .../goldenharvest/GoldenHarvestEvent.java | 19 +++++-- .../MiraculousFishingEvent.java | 19 +++++-- .../models/dailyevent/HasBroadcast.java | 23 ++++++++ .../dailyevents/tasks/EndEventTask.java | 49 +++++++++++++++++ ...eNextEventTask.java => NextEventTask.java} | 38 ++++--------- ...tTask.java => ShowBeginningEventTask.java} | 20 +++++-- .../default/dailyevents.properties | 55 ++++++++++++++++--- 9 files changed, 200 insertions(+), 57 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasBroadcast.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/EndEventTask.java rename src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/{ScheduleNextEventTask.java => NextEventTask.java} (69%) rename src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/{ShowBeginningEventToastTask.java => ShowBeginningEventTask.java} (66%) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java index 6eee0067c..c4ac910f6 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java @@ -18,8 +18,8 @@ import fr.openmc.core.features.events.contents.dailyevents.models.IncomingEventsDB; import fr.openmc.core.features.events.contents.dailyevents.models.ScheduleDailyEvent; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; -import fr.openmc.core.features.events.contents.dailyevents.tasks.ScheduleNextEventTask; -import fr.openmc.core.features.events.contents.dailyevents.tasks.ShowBeginningEventToastTask; +import fr.openmc.core.features.events.contents.dailyevents.tasks.NextEventTask; +import fr.openmc.core.features.events.contents.dailyevents.tasks.ShowBeginningEventTask; import fr.openmc.core.utils.text.DateUtils; import org.bukkit.event.Listener; import org.bukkit.scheduler.BukkitTask; @@ -34,7 +34,6 @@ //todo: ajouter des javadocs et commentaires sur certaines parties //todo: tester les toasts lorsqu'ils refonctionneront (before, start, end) -//todo: faire des broadcast like Contest et Mayor, broadcast customisable? (before, start, end) @Credit(developers = {"iambibi_"}) public class DailyEventsManager extends Feature implements LoadAfterItemsAdder, DatabaseFeature, HasListeners { // * Constantes @@ -48,7 +47,7 @@ public class DailyEventsManager extends Feature implements LoadAfterItemsAdder, 9, 13, 16, 19, 21 )); - public static final int SHOW_BEGINNING_TOAST_DELAY = 60; // en secondes + public static final int SHOW_BEGINNING_DELAY = 60; // en secondes // * Données à propos de la gestion des daily event public static ScheduleDailyEvent outgoingEvent = null; @@ -156,10 +155,12 @@ public static BukkitTask scheduleNextEventTask() { .map(s->s.getDailyEvent().getClass().getSimpleName()).toList()); OMCLogger.infoFormatted("Prochain Evenement journalier : " + scheduleTime + "s (dans " + DateUtils.convertSecondToTime(DateUtils.getDelayBetweenNow(scheduleTime)) + ")"); - new ShowBeginningEventToastTask() - .runTaskLater(OMCPlugin.getInstance(), delayTicks - SHOW_BEGINNING_TOAST_DELAY * 20L); + // * Programation de la tâche qui s'executera peu avant le commencement + new ShowBeginningEventTask() + .runTaskLater(OMCPlugin.getInstance(), delayTicks - SHOW_BEGINNING_DELAY * 20L); - return new ScheduleNextEventTask().runTaskLater(OMCPlugin.getInstance(), delayTicks); + // * Renvoie la tache qui executera le début de l'evenement + return new NextEventTask().runTaskLater(OMCPlugin.getInstance(), delayTicks); } private static List generateRandomOrder() { diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java index 9242788b9..c246af449 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java @@ -3,6 +3,7 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasAmbient; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasBroadcast; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.utils.nms.toast.CustomToastData; @@ -14,7 +15,7 @@ import java.util.List; -public class BloodyNightEvent extends DailyEvent implements HasToast, HasAmbient { +public class BloodyNightEvent extends DailyEvent implements HasToast, HasAmbient, HasBroadcast { @Override public String getEventId() { return "bloody_night"; @@ -63,7 +64,7 @@ public ItemStack getIcon() { public CustomToastData getStartToastData() { return new CustomToastData( this.getIcon(), - TranslationManager.translation("feature.dailyevents.toast.bloodynight.start"), + TranslationManager.translation("feature.dailyevents.bloodynight.toast.start"), AdvancementType.CHALLENGE ); } @@ -72,13 +73,23 @@ public CustomToastData getStartToastData() { public CustomToastData getEndToastData() { return new CustomToastData( this.getIcon(), - TranslationManager.translation("feature.dailyevents.toast.bloodynight.end"), + TranslationManager.translation("feature.dailyevents.bloodynight.toast.end"), AdvancementType.GOAL ); } @Override public CustomAmbient getAmbient() { - return OMCRegistry.CUSTOM_AMBIENTS.DARK; // todo: make new custom ambients + return OMCRegistry.CUSTOM_AMBIENTS.BLOODY; + } + + @Override + public Component getStartBroadcast() { + return TranslationManager.translation("feature.dailyevents.bloodynight.broadcast.start"); + } + + @Override + public Component getEndBroadcast() { + return TranslationManager.translation("feature.dailyevents.bloodynight.broadcast.end"); } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java index 5fce8c1aa..b03553c91 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/GoldenHarvestEvent.java @@ -3,6 +3,7 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasAmbient; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasBroadcast; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.utils.nms.toast.CustomToastData; @@ -14,7 +15,7 @@ import java.util.List; -public class GoldenHarvestEvent extends DailyEvent implements HasToast, HasAmbient { +public class GoldenHarvestEvent extends DailyEvent implements HasToast, HasAmbient, HasBroadcast { @Override public String getEventId() { return "golden_harvest"; @@ -63,7 +64,7 @@ public ItemStack getIcon() { public CustomToastData getStartToastData() { return new CustomToastData( this.getIcon(), - TranslationManager.translation("feature.dailyevents.toast.goldenharvest.start"), + TranslationManager.translation("feature.dailyevents.goldenharvest.toast.start"), AdvancementType.CHALLENGE ); } @@ -72,13 +73,23 @@ public CustomToastData getStartToastData() { public CustomToastData getEndToastData() { return new CustomToastData( this.getIcon(), - TranslationManager.translation("feature.dailyevents.toast.goldenharvest.end"), + TranslationManager.translation("feature.dailyevents.goldenharvest.toast.end"), AdvancementType.GOAL ); } @Override public CustomAmbient getAmbient() { - return OMCRegistry.CUSTOM_AMBIENTS.DARK; // todo: make new custom ambients + return OMCRegistry.CUSTOM_AMBIENTS.GOLDEN; + } + + @Override + public Component getStartBroadcast() { + return TranslationManager.translation("feature.dailyevents.goldenharvest.broadcast.start"); + } + + @Override + public Component getEndBroadcast() { + return TranslationManager.translation("feature.dailyevents.goldenharvest.broadcast.end"); } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java index e1008ea14..6b2b89a43 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java @@ -3,6 +3,7 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasAmbient; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasBroadcast; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.utils.nms.toast.CustomToastData; @@ -14,7 +15,7 @@ import java.util.List; -public class MiraculousFishingEvent extends DailyEvent implements HasToast, HasAmbient { +public class MiraculousFishingEvent extends DailyEvent implements HasToast, HasAmbient, HasBroadcast { @Override public String getEventId() { return "miraculous_fishing"; @@ -63,7 +64,7 @@ public ItemStack getIcon() { public CustomToastData getStartToastData() { return new CustomToastData( this.getIcon(), - TranslationManager.translation("feature.dailyevents.toast.miraculousfishing.start"), + TranslationManager.translation("feature.dailyevents.miraculousfishing.toast.start"), AdvancementType.CHALLENGE ); } @@ -72,13 +73,23 @@ public CustomToastData getStartToastData() { public CustomToastData getEndToastData() { return new CustomToastData( this.getIcon(), - TranslationManager.translation("feature.dailyevents.toast.miraculousfishing.end"), + TranslationManager.translation("feature.dailyevents.miraculousfishing.toast.end"), AdvancementType.GOAL ); } @Override public CustomAmbient getAmbient() { - return OMCRegistry.CUSTOM_AMBIENTS.DARK; // todo: make new custom ambients + return OMCRegistry.CUSTOM_AMBIENTS.BLESSED; + } + + @Override + public Component getStartBroadcast() { + return TranslationManager.translation("feature.dailyevents.miraculousfishing.broadcast.start"); + } + + @Override + public Component getEndBroadcast() { + return TranslationManager.translation("feature.dailyevents.miraculousfishing.broadcast.end"); } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasBroadcast.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasBroadcast.java new file mode 100644 index 000000000..5d00eae6f --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasBroadcast.java @@ -0,0 +1,23 @@ +package fr.openmc.core.features.events.contents.dailyevents.models.dailyevent; + +import net.kyori.adventure.text.Component; +import org.bukkit.entity.Player; + +import java.util.Collection; + +public interface HasBroadcast { + Component getStartBroadcast(); + Component getEndBroadcast(); + + default void sendStartBroadcast(Collection receivers) { + for (Player receiver : receivers) { + receiver.sendMessage(getStartBroadcast()); + } + } + + default void sendEndBroadcast(Collection receivers) { + for (Player receiver : receivers) { + receiver.sendMessage(getEndBroadcast()); + } + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/EndEventTask.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/EndEventTask.java new file mode 100644 index 000000000..325ac7943 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/EndEventTask.java @@ -0,0 +1,49 @@ +package fr.openmc.core.features.events.contents.dailyevents.tasks; + +import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; +import fr.openmc.core.features.events.contents.dailyevents.models.ScheduleDailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasAmbient; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasBroadcast; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.Collection; +import java.util.stream.Collectors; + +public class EndEventTask extends BukkitRunnable { + private final DailyEvent outgoingEvent; + + public EndEventTask(ScheduleDailyEvent outgoing) { + this.outgoingEvent = outgoing.getDailyEvent(); + } + + @Override + public void run() { + DailyEventsManager.outgoingEvent.getDailyEvent().onEnd().run(); + + Collection receivers = Bukkit.getOnlinePlayers() + .stream() + .filter(p -> p.getWorld().getName().equals(outgoingEvent.getWorldEvent())) + .collect(Collectors.toSet()); + + DailyEventsManager.outgoingEvent = null; + + // * Suppression de la l'ambience + if (outgoingEvent instanceof HasAmbient ambient) { + ambient.reset(receivers); + } + + // * Message de fin + if (outgoingEvent instanceof HasBroadcast broadcast) { + broadcast.sendEndBroadcast(receivers); + } + + // * Toast de fin + if (outgoingEvent instanceof HasToast toast) { + toast.getEndToastData().send(receivers); + } + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ScheduleNextEventTask.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/NextEventTask.java similarity index 69% rename from src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ScheduleNextEventTask.java rename to src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/NextEventTask.java index 66ba370a6..0890e847b 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ScheduleNextEventTask.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/NextEventTask.java @@ -4,6 +4,7 @@ import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasAmbient; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasBroadcast; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -12,19 +13,17 @@ import java.util.Collection; import java.util.stream.Collectors; -public class ScheduleNextEventTask extends BukkitRunnable { +public class NextEventTask extends BukkitRunnable { @Override public void run() { + // * Commencement de l'evenement if (DailyEventsManager.incomingEvents.isEmpty()) { DailyEventsManager.incomingEvents = DailyEventsManager.loadIncomingEvents(); } - DailyEventsManager.outgoingEvent = DailyEventsManager.incomingEvents.removeFirst(); - - // * Commencement de l'evenement DailyEventsManager.outgoingEvent.getDailyEvent().onStart().run(); - DailyEvent outgoingDailyEvent = DailyEventsManager.outgoingEvent.getDailyEvent(); + Collection receivers = Bukkit.getOnlinePlayers() .stream() .filter(p -> p.getWorld().getName().equals(outgoingDailyEvent.getWorldEvent())) @@ -35,33 +34,20 @@ public void run() { ambient.apply(receivers); } + // * Message de début + if (outgoingDailyEvent instanceof HasBroadcast broadcast) { + broadcast.sendStartBroadcast(receivers); + } + // * Toast de début if (outgoingDailyEvent instanceof HasToast toast) { toast.getStartToastData().send(receivers); } - // * Programmation de la fin de l'evenement - Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> { - DailyEventsManager.outgoingEvent.getDailyEvent().onEnd().run(); - - Collection receivers2 = Bukkit.getOnlinePlayers() - .stream() - .filter(p -> p.getWorld().getName().equals(outgoingDailyEvent.getWorldEvent())) - .collect(Collectors.toSet()); - - DailyEventsManager.outgoingEvent = null; - - - if (outgoingDailyEvent instanceof HasAmbient ambient) { - ambient.reset(receivers2); - } - - if (outgoingDailyEvent instanceof HasToast toast) { - toast.getEndToastData().send(receivers2); - } - - }, DailyEventsManager.outgoingEvent.getDailyEvent().getDuration() * 60L * 20L); + new EndEventTask(DailyEventsManager.outgoingEvent) + .runTaskLater(OMCPlugin.getInstance(), + DailyEventsManager.outgoingEvent.getDailyEvent().getDuration() * 60L * 20L); // * 10 secondes d'attente avant de schedule un autre event (evite que plusieurs events se lancent en meme temps) Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ShowBeginningEventToastTask.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ShowBeginningEventTask.java similarity index 66% rename from src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ShowBeginningEventToastTask.java rename to src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ShowBeginningEventTask.java index b43c9c65f..ec4600367 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ShowBeginningEventToastTask.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/ShowBeginningEventTask.java @@ -2,6 +2,7 @@ import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; import fr.openmc.core.features.events.contents.dailyevents.models.ScheduleDailyEvent; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; import fr.openmc.core.utils.nms.toast.ToastUtils; import fr.openmc.core.utils.text.messages.TranslationManager; import fr.openmc.core.utils.world.WorldUtils; @@ -13,20 +14,29 @@ import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; -public class ShowBeginningEventToastTask extends BukkitRunnable { +public class ShowBeginningEventTask extends BukkitRunnable { @Override public void run() { ScheduleDailyEvent nextEvent = DailyEventsManager.incomingEvents.getFirst(); + DailyEvent dailyEvent = nextEvent.getDailyEvent(); for (Player onlinePlayer : Bukkit.getOnlinePlayers()) { Component name; - if (nextEvent.getDailyEvent().getWorldEvent().contains(onlinePlayer.getWorld().getName())) { + + // ** Affichage d'un message dans le chat + if (dailyEvent.getWorldEvent().contains(onlinePlayer.getWorld().getName())) { + onlinePlayer.sendMessage( + TranslationManager.translation("feature.dailyevents.broadcast.soon")); + } + + // ** Affichage du Toast + if (dailyEvent.getWorldEvent().contains(onlinePlayer.getWorld().getName())) { name = TranslationManager.translation("feature.dailyevents.toast.beginning_event_in_world", - Component.text(DailyEventsManager.SHOW_BEGINNING_TOAST_DELAY, NamedTextColor.YELLOW)); + Component.text(DailyEventsManager.SHOW_BEGINNING_DELAY, NamedTextColor.YELLOW)); } else { name = TranslationManager.translation("feature.dailyevents.toast.beginning_event_out_world", - TranslationManager.translation(WorldUtils.getDisplayedWorldName(nextEvent.getDailyEvent().getWorldEvent())), - Component.text(DailyEventsManager.SHOW_BEGINNING_TOAST_DELAY, NamedTextColor.YELLOW)); + TranslationManager.translation(WorldUtils.getDisplayedWorldName(dailyEvent.getWorldEvent())), + Component.text(DailyEventsManager.SHOW_BEGINNING_DELAY, NamedTextColor.YELLOW)); } ToastUtils.sendCustomToast( diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties index 9c6409d49..b1b8ae9dd 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -13,14 +13,55 @@ feature.dailyevents.miraculousfishing.lore=Vivez une grande ses
pour vous sautez dessus! \
Mais vous risquerez d'avoir plusieures bonnes surprises si vous êtes chanceux -feature.dailyevents.toast.bloodynight.start=La Nuit Sanglante a débutée ! -feature.dailyevents.toast.bloodynight.end=Le calvaire de la Nuit Sanglante s'est arrêté +feature.dailyevents.bloodynight.toast.start=La Nuit Sanglante a débutée ! +feature.dailyevents.bloodynight.toast.end=Le calvaire de la Nuit Sanglante s'est arrêté -feature.dailyevents.toast.goldenharvest.start=La Moisson dorée débarque dans vos granges ! -feature.dailyevents.toast.goldenharvest.end=La Moisson dorée s'est arrêtée ! +feature.dailyevents.goldenharvest.toast.start=La Moisson dorée débarque dans vos granges ! +feature.dailyevents.goldenharvest.toast.end=La Moisson dorée s'est arrêtée ! -feature.dailyevents.toast.miraculousfishing.start=La Pêche miraculeuse est ouverte ! -feature.dailyevents.toast.miraculousfishing.end=La Pêche miraculeuse est partie +feature.dailyevents.miraculousfishing.toast.start=La Pêche miraculeuse est ouverte ! +feature.dailyevents.miraculousfishing.toast.end=La Pêche miraculeuse est partie feature.dailyevents.toast.beginning_event_in_world=Un évenement va commencer dans votre monde dans %1$ss ! -feature.dailyevents.toast.beginning_event_out_world=Un évenement va commencer dans dans %1$ss ! \ No newline at end of file +feature.dailyevents.toast.beginning_event_out_world=Un évenement va commencer dans dans %1$ss ! + +feature.dailyevents.broadcast.soon=*un évènement commence à se rapprocher de notre monde...* + +feature.dailyevents.miraculousfishing.broadcast.start= \ +
\ +
PËCHE MIRACLEUSE ! La grande session a commencé !\ +
*sortez vous canne à pêche et découvrez les mystères des lacs*\ +
\ +
+feature.dailyevents.miraculousfishing.broadcast.end= \ +
\ +
PËCHE MIRACLEUSE ! La bénédiction est finie! \ +
*réjouissez vous de vos captures!*\ +
\ +
+ +feature.dailyevents.bloodynight.broadcast.start= \ +
\ +
NUIT SANGLANTE ! Le bain de sang commence !\ +
*sortez vos armes et combattez les vagues de monstres*\ +
\ +
+feature.dailyevents.bloodynight.broadcast.end= \ +
\ +
NUIT SANGLANTE ! La calamité a pris fin ! \ +
*retour à un monde calme et paisible*\ +
\ +
+ +feature.dailyevents.goldenharvest.broadcast.start= \ +
\ +
MOISSON DOREE ! Les cultures sont désormais bénie !\ +
*trouvez des mutations de cultures, et d'autres surprises...*\ +
\ +
+feature.dailyevents.goldenharvest.broadcast.end= \ +
\ +
MOISSON DOREE ! La productivité des cultures s'arretent ! \ +
*stocker, vendez vos ressources que vous avec pu farmer*\ +
\ +
From 37f408869036f10795f65a2e15113983cc154799 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 16 Jun 2026 20:04:49 +0200 Subject: [PATCH 43/74] add javadocs --- .../dailyevents/DailyEventsManager.java | 30 +++++++++++++------ .../fr/openmc/core/utils/RandomUtils.java | 14 +++++++++ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java index c4ac910f6..67274090b 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java @@ -20,6 +20,7 @@ import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; import fr.openmc.core.features.events.contents.dailyevents.tasks.NextEventTask; import fr.openmc.core.features.events.contents.dailyevents.tasks.ShowBeginningEventTask; +import fr.openmc.core.utils.RandomUtils; import fr.openmc.core.utils.text.DateUtils; import org.bukkit.event.Listener; import org.bukkit.scheduler.BukkitTask; @@ -27,12 +28,10 @@ import java.sql.SQLException; import java.time.LocalDateTime; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Set; -//todo: ajouter des javadocs et commentaires sur certaines parties //todo: tester les toasts lorsqu'ils refonctionneront (before, start, end) @Credit(developers = {"iambibi_"}) public class DailyEventsManager extends Feature implements LoadAfterItemsAdder, DatabaseFeature, HasListeners { @@ -80,6 +79,10 @@ public Set getListeners() { ); } + /** + * Charge les données de la DB, généralement pdt le démarrage + * @return les données des daily event (ordre actuel) + */ public static IncomingEventsDB loadIncomingEventsDB() { try { IncomingEventsDB data = dao.queryForId(1); @@ -93,6 +96,10 @@ public static IncomingEventsDB loadIncomingEventsDB() { } } + /** + * Sauvegarde les données des Daily Event dans la DB, généralement pdt l'arrêt du serveur + * @param data les données des daily events + */ public static void saveIncomingEventsDB(IncomingEventsDB data) { try { dao.createOrUpdate(data); @@ -116,7 +123,7 @@ public static List loadIncomingEvents() { List copyEvents = new ArrayList<>(incomingEvent); for (int hourSlot : SLOT_HOURS_EVENTS) { if (copyEvents.isEmpty()) { - copyEvents = generateRandomOrder(); + copyEvents = RandomUtils.generateRandomOrder(EVENTS); } LocalDateTime scheduledDailyEvent; @@ -132,6 +139,13 @@ public static List loadIncomingEvents() { return scheduledEvents; } + /** + * On schedule le prochain événement à venir. + * - On cherche la prochaine heure, en faisant gaffe si l'heure est passée, dans ce cas on schedule pour demain + * - Apres la prochaine heure on lance les taches associés à l'événement (tache pour avant le commencement, + * et pour le lancement de l'événement et la planification du prochain + * @return la tache de lancement de l'événement, qui sera executé à l'heure exacte du début de l'événement + */ public static BukkitTask scheduleNextEventTask() { LocalDateTime now = DateUtils.getLocalDateTime(); // * On cherche la prochaine heure @@ -163,12 +177,10 @@ public static BukkitTask scheduleNextEventTask() { return new NextEventTask().runTaskLater(OMCPlugin.getInstance(), delayTicks); } - private static List generateRandomOrder() { - List copyEvents = new ArrayList<>(EVENTS); - Collections.shuffle(copyEvents); - return copyEvents; - } - + /** + * Méthode plus claire afin de dire s'il y a un evenement journalier actif ou non + * @return un boolean + */ public static boolean isActiveDailyEvent() { return outgoingEvent != null; } diff --git a/src/main/java/fr/openmc/core/utils/RandomUtils.java b/src/main/java/fr/openmc/core/utils/RandomUtils.java index 81c533abc..c35f583ac 100644 --- a/src/main/java/fr/openmc/core/utils/RandomUtils.java +++ b/src/main/java/fr/openmc/core/utils/RandomUtils.java @@ -1,5 +1,8 @@ package fr.openmc.core.utils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Random; public class RandomUtils { @@ -25,4 +28,15 @@ public static float randomBetween(float min, float max) { public static int randomBetween(int min, int max) { return min + random.nextInt((max - min) + 1); } + + /** + * Prends une liste initial et mélange la liste en en retournant une nouvelle liste. + * @param inital la liste initial + * @return la liste mélangé + */ + public static List generateRandomOrder(List inital) { + List shuffle = new ArrayList<>(inital); + Collections.shuffle(shuffle); + return shuffle; + } } \ No newline at end of file From 7c2b4e5b142f602040fb6289ca7dd9e8a523b65b Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:27:13 +0200 Subject: [PATCH 44/74] add javadocs --- .../loottable/MiraculousFIshLootTable.java | 22 +++++++ .../core/registry/loottable/CustomLoot.java | 58 +----------------- .../core/registry/loottable/LootItem.java | 59 +++++++++++++++++++ .../core/registry/loottable/LootMethod.java | 9 +++ .../core/registry/loottable/LootMoney.java | 9 +++ .../contents/MachineBallLootTable.java | 15 ++--- 6 files changed, 108 insertions(+), 64 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/loottable/MiraculousFIshLootTable.java create mode 100644 src/main/java/fr/openmc/core/registry/loottable/LootItem.java create mode 100644 src/main/java/fr/openmc/core/registry/loottable/LootMethod.java create mode 100644 src/main/java/fr/openmc/core/registry/loottable/LootMoney.java diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/loottable/MiraculousFIshLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/loottable/MiraculousFIshLootTable.java new file mode 100644 index 000000000..4dbd8c73c --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/loottable/MiraculousFIshLootTable.java @@ -0,0 +1,22 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.loottable; + +import fr.openmc.core.registry.loottable.CustomLoot; +import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.LootMoney; + +import java.util.Set; + +public class MiraculousFIshLootTable extends CustomLootTable { + @Override + public String getNamespace() { + return "omc_daily_events:miraculous_fishing"; + } + + // todo stop here + @Override + public Set getLoots() { + return Set.of( + new LootMoney(50, 250) + ); + } +} diff --git a/src/main/java/fr/openmc/core/registry/loottable/CustomLoot.java b/src/main/java/fr/openmc/core/registry/loottable/CustomLoot.java index b2edc7cb3..36c7cd21e 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/CustomLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/CustomLoot.java @@ -1,59 +1,3 @@ package fr.openmc.core.registry.loottable; -import fr.openmc.core.registry.items.CustomItem; -import org.bukkit.inventory.ItemStack; - -import java.util.Collections; -import java.util.Set; - -public record CustomLoot(Set items, ItemStack displayedItem, double chance, int minAmount, int maxAmount) { - - public CustomLoot(ItemStack item, double chance, int minAmount, int maxAmount) { - this(Collections.singleton(item), - null, - chance, - minAmount, - maxAmount); - } - - public CustomLoot(CustomItem item, double chance, int minAmount, int maxAmount) { - if (item == null) { - throw new IllegalArgumentException("CustomItem cannot be null"); - } - this(Collections.singleton(item.getBest()), - null, - chance, - minAmount, - maxAmount); - } - - public CustomLoot(ItemStack item, ItemStack displayedItem, double chance, int minAmount, int maxAmount) { - this(Collections.singleton(item), - displayedItem, - chance, - minAmount, - maxAmount); - } - - public CustomLoot(CustomItem item, ItemStack displayedItem, double chance, int minAmount, int maxAmount) { - if (item == null) { - throw new IllegalArgumentException("CustomItem cannot be null"); - } - this(Collections.singleton(item.getBest()), - displayedItem, - chance, - minAmount, - maxAmount); - } - - public ItemStack getFirstLoot() { - if (items.size() == 1) { - return items.iterator().next(); - } - return items.stream().findFirst().orElse(null); - } - - public int getRandomAmount() { - return minAmount + (int) (Math.random() * (maxAmount - minAmount + 1)); - } -} \ No newline at end of file +public interface CustomLoot {} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/loottable/LootItem.java b/src/main/java/fr/openmc/core/registry/loottable/LootItem.java new file mode 100644 index 000000000..24c6aa2b6 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/loottable/LootItem.java @@ -0,0 +1,59 @@ +package fr.openmc.core.registry.loottable; + +import fr.openmc.core.registry.items.CustomItem; +import org.bukkit.inventory.ItemStack; + +import java.util.Collections; +import java.util.Set; + +public record LootItem(Set items, ItemStack displayedItem, double chance, int minAmount, int maxAmount) implements CustomLoot { + + public LootItem(ItemStack item, double chance, int minAmount, int maxAmount) { + this(Collections.singleton(item), + null, + chance, + minAmount, + maxAmount); + } + + public LootItem(CustomItem item, double chance, int minAmount, int maxAmount) { + if (item == null) { + throw new IllegalArgumentException("CustomItem cannot be null"); + } + this(Collections.singleton(item.getBest()), + null, + chance, + minAmount, + maxAmount); + } + + public LootItem(ItemStack item, ItemStack displayedItem, double chance, int minAmount, int maxAmount) { + this(Collections.singleton(item), + displayedItem, + chance, + minAmount, + maxAmount); + } + + public LootItem(CustomItem item, ItemStack displayedItem, double chance, int minAmount, int maxAmount) { + if (item == null) { + throw new IllegalArgumentException("CustomItem cannot be null"); + } + this(Collections.singleton(item.getBest()), + displayedItem, + chance, + minAmount, + maxAmount); + } + + public ItemStack getFirstLoot() { + if (items.size() == 1) { + return items.iterator().next(); + } + return items.stream().findFirst().orElse(null); + } + + public int getRandomAmount() { + return minAmount + (int) (Math.random() * (maxAmount - minAmount + 1)); + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/loottable/LootMethod.java b/src/main/java/fr/openmc/core/registry/loottable/LootMethod.java new file mode 100644 index 000000000..296bba7c9 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/loottable/LootMethod.java @@ -0,0 +1,9 @@ +package fr.openmc.core.registry.loottable; + +import org.bukkit.entity.Player; + +import java.util.function.Consumer; + +public record LootMethod(Consumer receiver) implements CustomLoot { + +} diff --git a/src/main/java/fr/openmc/core/registry/loottable/LootMoney.java b/src/main/java/fr/openmc/core/registry/loottable/LootMoney.java new file mode 100644 index 000000000..09bdf432b --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/loottable/LootMoney.java @@ -0,0 +1,9 @@ +package fr.openmc.core.registry.loottable; + +import fr.openmc.core.utils.RandomUtils; + +public record LootMoney(double money) implements CustomLoot { + public LootMoney(double minMoney, double maxMoney) { + this(RandomUtils.randomBetween(minMoney, maxMoney)); + } +} diff --git a/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java b/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java index e28396608..6b35279ef 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java +++ b/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java @@ -3,6 +3,7 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.loottable.CustomLoot; import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.LootItem; import fr.openmc.core.utils.bukkit.ItemBuilder; import net.kyori.adventure.text.Component; import org.bukkit.Material; @@ -20,7 +21,7 @@ public String getNamespace() { @Override public Set getLoots() { return Set.of( - new CustomLoot( + new LootItem( Set.of(OMCRegistry.CUSTOM_ITEMS.PELUCHE_SEINYY.getBest()), new ItemBuilder( OMCRegistry.CUSTOM_ITEMS.PELUCHE_SEINYY, @@ -33,7 +34,7 @@ public Set getLoots() { 1, 1 ), - new CustomLoot( + new LootItem( Set.of(new ItemStack(Material.DIAMOND, 3)), new ItemBuilder( Material.DIAMOND, @@ -46,7 +47,7 @@ public Set getLoots() { 1, 1 ), - new CustomLoot( + new LootItem( Set.of(new ItemStack(Material.IRON_INGOT, 10)), new ItemBuilder( Material.IRON_INGOT, @@ -59,7 +60,7 @@ public Set getLoots() { 1, 1 ), - new CustomLoot( + new LootItem( Set.of(new ItemStack(Material.NETHERITE_INGOT)), new ItemBuilder( Material.NETHERITE_INGOT, @@ -72,7 +73,7 @@ public Set getLoots() { 1, 1 ), - new CustomLoot( + new LootItem( Set.of(new ItemStack(Material.OAK_LOG, 32)), new ItemBuilder( Material.OAK_LOG, @@ -85,7 +86,7 @@ public Set getLoots() { 1, 1 ), - new CustomLoot( + new LootItem( Set.of(new ItemStack(Material.COOKED_BEEF, 16)), new ItemBuilder( Material.COOKED_BEEF, @@ -98,7 +99,7 @@ public Set getLoots() { 1, 1 ), - new CustomLoot( + new LootItem( Set.of(new ItemStack(Material.COAL, 16)), new ItemBuilder( Material.COAL, From 7b17a9109e52563fd5929f96219980061c1e0c05 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 17 Jun 2026 19:00:32 +0200 Subject: [PATCH 45/74] beginning of MiraculousFishLootTable but missing CustomLoot, and... its a review --- .../core/events/LootboxRewardEvent.java | 2 +- .../dream/events/MetalDetectorLootEvent.java | 8 +-- .../listeners/dream/PlayerObtainOrb.java | 24 ++++--- .../mecanism/cloudcastle/CloudVault.java | 17 ++++- .../cloudfishing/PlayerFishListener.java | 7 ++- .../quests/CrystallizedPickaxeQuest.java | 21 +++++-- .../dream/milestone/quests/MudOrbQuest.java | 21 +++++-- .../dream/models/registry/DreamMob.java | 4 +- .../registries/items/tools/MetalDetector.java | 7 ++- .../loottable/CloudFishingLootTable.java | 15 ++--- .../loottable/CloudVaultLootTable.java | 17 ++--- .../loottable/MetalDetectorLootTable.java | 25 ++++---- .../dream/registries/mobs/CrazyFrog.java | 4 +- .../dream/registries/mobs/DreamSpider.java | 4 +- .../features/dream/registries/mobs/Soul.java | 16 ++--- ...able.java => MiraculousFishLootTable.java} | 9 ++- .../core/features/tickets/TicketListener.java | 5 +- .../registry/lootboxes/LootboxOpenMenu.java | 60 +++++++++++------- .../core/registry/loottable/CustomLoot.java | 3 - .../registry/loottable/CustomLootTable.java | 62 ++++++++----------- .../loottable/CustomLootTableRegistry.java | 3 + .../core/registry/loottable/LootMethod.java | 9 --- .../core/registry/loottable/LootMoney.java | 9 --- .../contents/MachineBallLootTable.java | 18 +++--- .../registry/loottable/loots/CustomLoot.java | 8 +++ .../{LootItem.java => loots/ItemLoot.java} | 37 +++++++++-- .../registry/loottable/loots/MethodLoot.java | 22 +++++++ .../registry/loottable/loots/MoneyLoot.java | 17 +++++ .../registry/loottable/loots/TableLoot.java | 21 +++++++ .../openmc/core/registry/mobs/CustomMob.java | 8 +-- .../listeners/CustomMobDeathListener.java | 8 +-- 31 files changed, 306 insertions(+), 185 deletions(-) rename src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/loottable/{MiraculousFIshLootTable.java => MiraculousFishLootTable.java} (62%) delete mode 100644 src/main/java/fr/openmc/core/registry/loottable/CustomLoot.java delete mode 100644 src/main/java/fr/openmc/core/registry/loottable/LootMethod.java delete mode 100644 src/main/java/fr/openmc/core/registry/loottable/LootMoney.java create mode 100644 src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java rename src/main/java/fr/openmc/core/registry/loottable/{LootItem.java => loots/ItemLoot.java} (55%) create mode 100644 src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java create mode 100644 src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java create mode 100644 src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java diff --git a/src/main/java/fr/openmc/core/events/LootboxRewardEvent.java b/src/main/java/fr/openmc/core/events/LootboxRewardEvent.java index 8b46ef73d..4bac1ea6d 100644 --- a/src/main/java/fr/openmc/core/events/LootboxRewardEvent.java +++ b/src/main/java/fr/openmc/core/events/LootboxRewardEvent.java @@ -1,7 +1,7 @@ package fr.openmc.core.events; import fr.openmc.core.registry.lootboxes.CustomLootbox; -import fr.openmc.core.registry.loottable.CustomLoot; +import fr.openmc.core.registry.loottable.loots.CustomLoot; import lombok.Getter; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; diff --git a/src/main/java/fr/openmc/core/features/dream/events/MetalDetectorLootEvent.java b/src/main/java/fr/openmc/core/features/dream/events/MetalDetectorLootEvent.java index 6ca9b70c2..2cde281ac 100644 --- a/src/main/java/fr/openmc/core/features/dream/events/MetalDetectorLootEvent.java +++ b/src/main/java/fr/openmc/core/features/dream/events/MetalDetectorLootEvent.java @@ -1,10 +1,10 @@ package fr.openmc.core.features.dream.events; +import fr.openmc.core.registry.loottable.loots.CustomLoot; import lombok.Getter; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.bukkit.event.player.PlayerEvent; -import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -12,13 +12,13 @@ @Getter public class MetalDetectorLootEvent extends PlayerEvent { private static final HandlerList HANDLERS = new HandlerList(); - private final List loot; + private final List loot; /** * @param player The player who found the loot. - * @param loot The list of ItemStack representing the loot found. + * @param loot The list of CustomLoot representing the loot found. */ - public MetalDetectorLootEvent(Player player, List loot) { + public MetalDetectorLootEvent(Player player, List loot) { super(player); this.loot = loot; } diff --git a/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerObtainOrb.java b/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerObtainOrb.java index e87f980b0..a920a9765 100644 --- a/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerObtainOrb.java +++ b/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerObtainOrb.java @@ -11,6 +11,8 @@ import fr.openmc.core.features.dream.models.registry.items.DreamItem; import fr.openmc.core.features.dream.registries.DreamBiome; import fr.openmc.core.features.dream.registries.DreamItemRegistry; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import fr.openmc.core.utils.bukkit.ParticleUtils; import fr.openmc.core.utils.text.messages.MessageType; import fr.openmc.core.utils.text.messages.MessagesManager; @@ -86,18 +88,22 @@ public void onCloudOrbDispense(EntityPickupItemEvent event) { public void onMetalDetectorLoot(MetalDetectorLootEvent event) { Player player = event.getPlayer(); - for (ItemStack item : event.getLoot()) { - DreamItem dreamItem = DreamItemRegistry.getByItemStack(item); + for (CustomLoot loot : event.getLoot()) { + if (!(loot instanceof ItemLoot itemLoot)) continue; - if (dreamItem == null) continue; - if (!dreamItem.getId().equals(DreamItemRegistry.MUD_ORB.getId())) continue; + for (ItemStack item : itemLoot.getItems()) { + DreamItem dreamItem = DreamItemRegistry.getByItemStack(item); - setProgressionOrb(player, MUD_BEACH_ORB, DreamBiome.GLACITE_GROTTO); + if (dreamItem == null) continue; + if (!dreamItem.getId().equals(DreamItemRegistry.MUD_ORB.getId())) continue; - // * SFX - player.getWorld().playSound(player.getLocation(), "minecraft:entity.wither.spawn", 1f, 2f); - ParticleUtils.spawnDispersingParticles(player.getLocation(), Particle.ASH, 15, 15, 0.5, null); - break; + setProgressionOrb(player, MUD_BEACH_ORB, DreamBiome.GLACITE_GROTTO); + + // * SFX + player.getWorld().playSound(player.getLocation(), "minecraft:entity.wither.spawn", 1f, 2f); + ParticleUtils.spawnDispersingParticles(player.getLocation(), Particle.ASH, 15, 15, 0.5, null); + break; + } } } diff --git a/src/main/java/fr/openmc/core/features/dream/mecanism/cloudcastle/CloudVault.java b/src/main/java/fr/openmc/core/features/dream/mecanism/cloudcastle/CloudVault.java index 20799e897..24e7ce35a 100644 --- a/src/main/java/fr/openmc/core/features/dream/mecanism/cloudcastle/CloudVault.java +++ b/src/main/java/fr/openmc/core/features/dream/mecanism/cloudcastle/CloudVault.java @@ -6,6 +6,7 @@ import fr.openmc.core.features.dream.registries.DreamItemRegistry; import fr.openmc.core.features.dream.registries.DreamLootTableRegistry; import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; @@ -17,6 +18,7 @@ import org.bukkit.inventory.ItemStack; import java.util.List; +import java.util.Set; public class CloudVault implements Listener { private final CustomLootTable CLOUD_VAULT_LOOT_TABLE = DreamLootTableRegistry.CLOUD_VAULT; @@ -43,10 +45,19 @@ public void onLootGenerate(BlockDispenseLootEvent event) { if (CLOUD_VAULT_LOOT_TABLE == null) return; - List loot = CLOUD_VAULT_LOOT_TABLE.rollLootsWithAmount(3); - event.setDispensedLoot(loot); + List itemLoots = CLOUD_VAULT_LOOT_TABLE.rollLootsWithAmount(player, 3) + .stream() + .filter(loot -> loot instanceof ItemLoot) + .map(item -> (ItemLoot) item).toList(); - for (ItemStack item : loot) { + List itemStacks = itemLoots.stream() + .map(ItemLoot::getItems) + .flatMap(Set::stream) + .toList(); + + event.setDispensedLoot(itemStacks); + + for (ItemStack item : itemStacks) { Bukkit.getScheduler().runTask(OMCPlugin.getInstance(), () -> Bukkit.getServer().getPluginManager().callEvent(new DreamRngLootEvent(player, item, item.getAmount(), CLOUD_VAULT_LOOT_TABLE.getChanceOf(item))) ); diff --git a/src/main/java/fr/openmc/core/features/dream/mecanism/cloudfishing/PlayerFishListener.java b/src/main/java/fr/openmc/core/features/dream/mecanism/cloudfishing/PlayerFishListener.java index 5a5eb958d..6b9d32da6 100644 --- a/src/main/java/fr/openmc/core/features/dream/mecanism/cloudfishing/PlayerFishListener.java +++ b/src/main/java/fr/openmc/core/features/dream/mecanism/cloudfishing/PlayerFishListener.java @@ -4,6 +4,7 @@ import fr.openmc.core.features.dream.DreamUtils; import fr.openmc.core.features.dream.mecanism.rng.DreamRngLootEvent; import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.loots.CustomLoot; import fr.openmc.core.utils.bukkit.ItemUtils; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -65,10 +66,10 @@ public void run() { CustomLootTable lootTable = CloudFishingManager.FISHING_LOOT_TABLE; if (lootTable == null) return; - List rewards = lootTable.rollLoots(); + List rewards = lootTable.rollLoots(player); - for (ItemStack item : rewards) { - player.getInventory().addItem(item); + for (CustomLoot loot : rewards) { + if (!(loot instanceof ItemStack item)) continue; Bukkit.getScheduler().runTask(OMCPlugin.getInstance(), () -> Bukkit.getServer().getPluginManager().callEvent(new DreamRngLootEvent(player, item, item.getAmount(), lootTable.getChanceOf(item))) diff --git a/src/main/java/fr/openmc/core/features/dream/milestone/quests/CrystallizedPickaxeQuest.java b/src/main/java/fr/openmc/core/features/dream/milestone/quests/CrystallizedPickaxeQuest.java index a8e37e7fd..9e9c6eb78 100644 --- a/src/main/java/fr/openmc/core/features/dream/milestone/quests/CrystallizedPickaxeQuest.java +++ b/src/main/java/fr/openmc/core/features/dream/milestone/quests/CrystallizedPickaxeQuest.java @@ -13,12 +13,15 @@ import fr.openmc.core.features.milestones.models.MilestoneType; import fr.openmc.core.features.milestones.quests.MilestoneQuest; import fr.openmc.core.features.quests.objects.QuestTier; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import fr.openmc.core.utils.text.DirectionUtils; import net.kyori.adventure.text.Component; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitRunnable; import java.util.List; @@ -71,12 +74,18 @@ public void run() { public void onPickUp(MetalDetectorLootEvent e) { Player player = e.getPlayer(); if (!DreamUtils.isInDreamWorld(player)) return; - - DreamItem item = DreamItemRegistry.getByItemStack(e.getLoot().getFirst()); - if (item == null) return; - if (item instanceof CrystalizedPickaxe) { - if (MilestonesManager.getPlayerStep(getType(), player) != getStep().ordinal()) return; - this.incrementProgressInDream(player.getUniqueId()); + + for (CustomLoot loot : e.getLoot()) { + if (!(loot instanceof ItemLoot itemLoot)) continue; + + for (ItemStack item : itemLoot.getItems()) { + DreamItem dreamItem = DreamItemRegistry.getByItemStack(item); + if (dreamItem == null) return; + if (dreamItem instanceof CrystalizedPickaxe) { + if (MilestonesManager.getPlayerStep(getType(), player) != getStep().ordinal()) continue; + this.incrementProgressInDream(player.getUniqueId()); + } + } } } diff --git a/src/main/java/fr/openmc/core/features/dream/milestone/quests/MudOrbQuest.java b/src/main/java/fr/openmc/core/features/dream/milestone/quests/MudOrbQuest.java index 8d1114154..b23b59c06 100644 --- a/src/main/java/fr/openmc/core/features/dream/milestone/quests/MudOrbQuest.java +++ b/src/main/java/fr/openmc/core/features/dream/milestone/quests/MudOrbQuest.java @@ -10,9 +10,12 @@ import fr.openmc.core.features.milestones.models.MilestoneType; import fr.openmc.core.features.milestones.quests.MilestoneQuest; import fr.openmc.core.features.quests.objects.QuestTier; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; import java.util.List; @@ -50,12 +53,18 @@ public MudOrbQuest() { public void onGetOrb(MetalDetectorLootEvent e) { Player player = e.getPlayer(); if (!DreamUtils.isInDreamWorld(player)) return; - - DreamItem item = DreamItemRegistry.getByItemStack(e.getLoot().getFirst()); - if (item == null) return; - if (item instanceof MudOrb) { - if (MilestonesManager.getPlayerStep(getType(), player) != getStep().ordinal()) return; - this.incrementProgressInDream(player.getUniqueId()); + + for (CustomLoot loot : e.getLoot()) { + if (!(loot instanceof ItemLoot itemLoot)) continue; + + for (ItemStack item : itemLoot.getItems()) { + DreamItem dreamItem = DreamItemRegistry.getByItemStack(item); + if (dreamItem == null) return; + if (dreamItem instanceof MudOrb) { + if (MilestonesManager.getPlayerStep(getType(), player) != getStep().ordinal()) return; + this.incrementProgressInDream(player.getUniqueId()); + } + } } } } diff --git a/src/main/java/fr/openmc/core/features/dream/models/registry/DreamMob.java b/src/main/java/fr/openmc/core/features/dream/models/registry/DreamMob.java index cf3df6b4e..265e9bd7f 100644 --- a/src/main/java/fr/openmc/core/features/dream/models/registry/DreamMob.java +++ b/src/main/java/fr/openmc/core/features/dream/models/registry/DreamMob.java @@ -1,6 +1,6 @@ package fr.openmc.core.features.dream.models.registry; -import fr.openmc.core.registry.loottable.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import fr.openmc.core.registry.mobs.CustomMob; import fr.openmc.core.registry.mobs.CustomMobAttribute; import lombok.Getter; @@ -19,7 +19,7 @@ public DreamMob(String id, String name, Class entityClass, double health, Lon this.damageTime = damageTime; } - public DreamMob(String id, String name, Class entityClass, double health, Long damageTime, double speed, double scale, List loots) { + public DreamMob(String id, String name, Class entityClass, double health, Long damageTime, double speed, double scale, List loots) { super(id, name, entityClass, health, 0f, speed, loots, new CustomMobAttribute(Attribute.SCALE, scale)); this.damageTime = damageTime; diff --git a/src/main/java/fr/openmc/core/features/dream/registries/items/tools/MetalDetector.java b/src/main/java/fr/openmc/core/features/dream/registries/items/tools/MetalDetector.java index b4ca0c918..dc325024b 100644 --- a/src/main/java/fr/openmc/core/features/dream/registries/items/tools/MetalDetector.java +++ b/src/main/java/fr/openmc/core/features/dream/registries/items/tools/MetalDetector.java @@ -11,6 +11,7 @@ import fr.openmc.core.features.dream.models.registry.items.DreamRarity; import fr.openmc.core.registry.items.options.UsableItem; import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.loots.CustomLoot; import fr.openmc.core.utils.text.messages.MessageType; import fr.openmc.core.utils.text.messages.MessagesManager; import fr.openmc.core.utils.text.messages.Prefix; @@ -68,10 +69,10 @@ public void onRightClick(Player player, PlayerInteractEvent event) { CustomLootTable lootTable = MetalDetectorManager.METAL_DETECTOR_LOOT_TABLE; if (lootTable == null) return; - List rewards = lootTable.rollLoots(); + List rewards = lootTable.rollLoots(player); - for (ItemStack item : rewards) { - player.getInventory().addItem(item); + for (CustomLoot loot : rewards) { + if (!(loot instanceof ItemStack item)) continue; Bukkit.getScheduler().runTask(OMCPlugin.getInstance(), () -> Bukkit.getServer().getPluginManager().callEvent(new DreamRngLootEvent(player, item, item.getAmount(), lootTable.getChanceOf(item))) diff --git a/src/main/java/fr/openmc/core/features/dream/registries/loottable/CloudFishingLootTable.java b/src/main/java/fr/openmc/core/features/dream/registries/loottable/CloudFishingLootTable.java index dab19af94..020875aec 100644 --- a/src/main/java/fr/openmc/core/features/dream/registries/loottable/CloudFishingLootTable.java +++ b/src/main/java/fr/openmc/core/features/dream/registries/loottable/CloudFishingLootTable.java @@ -1,8 +1,9 @@ package fr.openmc.core.features.dream.registries.loottable; import fr.openmc.core.features.dream.registries.DreamItemRegistry; -import fr.openmc.core.registry.loottable.CustomLoot; import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import java.util.Set; @@ -13,37 +14,37 @@ public class CloudFishingLootTable extends CustomLootTable { @Override public Set getLoots() { return Set.of( - new CustomLoot( + new ItemLoot( DreamItemRegistry.METEO_WAND, 0.05, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.POISSONION, 0.5, 1, 2 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.MOON_FISH, 0.5, 1, 2 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.SUN_FISH, 0.5, 1, 2 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.DOCKER_FISH, 0.1, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.SOMNIFERE, 0.4, 1, diff --git a/src/main/java/fr/openmc/core/features/dream/registries/loottable/CloudVaultLootTable.java b/src/main/java/fr/openmc/core/features/dream/registries/loottable/CloudVaultLootTable.java index 8467d7eb8..d5019748e 100644 --- a/src/main/java/fr/openmc/core/features/dream/registries/loottable/CloudVaultLootTable.java +++ b/src/main/java/fr/openmc/core/features/dream/registries/loottable/CloudVaultLootTable.java @@ -2,8 +2,9 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.features.dream.registries.DreamItemRegistry; -import fr.openmc.core.registry.loottable.CustomLoot; import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import java.util.Set; @@ -14,43 +15,43 @@ public class CloudVaultLootTable extends CustomLootTable { @Override public Set getLoots() { return Set.of( - new CustomLoot( + new ItemLoot( DreamItemRegistry.CLOUD_HELMET, 0.125, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.CLOUD_CHESTPLATE, 0.125, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.CLOUD_LEGGINGS, 0.125, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.CLOUD_BOOTS, 0.125, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.SOMNIFERE, 0.45, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.CLOUD_FISHING_ROD, 0.08, 1, 1 ), - new CustomLoot( + new ItemLoot( OMCRegistry.CUSTOM_ENCHANTS.DREAM_SLEEPER.getEnchantedBookItem(2).getBest(), 0.10, 1, diff --git a/src/main/java/fr/openmc/core/features/dream/registries/loottable/MetalDetectorLootTable.java b/src/main/java/fr/openmc/core/features/dream/registries/loottable/MetalDetectorLootTable.java index c2f5f26b4..cb1140b11 100644 --- a/src/main/java/fr/openmc/core/features/dream/registries/loottable/MetalDetectorLootTable.java +++ b/src/main/java/fr/openmc/core/features/dream/registries/loottable/MetalDetectorLootTable.java @@ -2,8 +2,9 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.features.dream.registries.DreamItemRegistry; -import fr.openmc.core.registry.loottable.CustomLoot; import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import java.util.Set; @@ -14,67 +15,67 @@ public class MetalDetectorLootTable extends CustomLootTable { @Override public Set getLoots() { return Set.of( - new CustomLoot( + new ItemLoot( DreamItemRegistry.CHIPS_DIHYDROGENE, 0.4, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.CHIPS_JIMMY, 0.2, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.CHIPS_TERRE, 0.4, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.CHIPS_SANS_PLOMB, 0.4, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.CHIPS_NATURE, 0.4, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.CHIPS_AYWEN, 0.1, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.CHIPS_LAIT_2_MARGOUTA, 0.005, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.SOMNIFERE, 0.4, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.MUD_ORB, 0.05, 1, 1 ), - new CustomLoot( + new ItemLoot( OMCRegistry.CUSTOM_ENCHANTS.EXPERIENTASTIC.getEnchantedBookItem(1), 0.03, 1, 1 ), - new CustomLoot( + new ItemLoot( DreamItemRegistry.CRYSTALIZED_PICKAXE, 0.1, 1, diff --git a/src/main/java/fr/openmc/core/features/dream/registries/mobs/CrazyFrog.java b/src/main/java/fr/openmc/core/features/dream/registries/mobs/CrazyFrog.java index a142e5f9a..6e00de037 100644 --- a/src/main/java/fr/openmc/core/features/dream/registries/mobs/CrazyFrog.java +++ b/src/main/java/fr/openmc/core/features/dream/registries/mobs/CrazyFrog.java @@ -4,7 +4,7 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.features.dream.models.registry.DreamMob; import fr.openmc.core.features.dream.registries.DreamItemRegistry; -import fr.openmc.core.registry.loottable.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import fr.openmc.core.utils.RandomUtils; import fr.openmc.core.utils.world.LocationUtils; import org.bukkit.Bukkit; @@ -41,7 +41,7 @@ public CrazyFrog(String id) { 0L, RandomUtils.randomBetween(0.2, 0.4), RandomUtils.randomBetween(3, 2.3), - List.of(new CustomLoot( + List.of(new ItemLoot( DreamItemRegistry.METAL_DETECTOR, 0.5, 1, diff --git a/src/main/java/fr/openmc/core/features/dream/registries/mobs/DreamSpider.java b/src/main/java/fr/openmc/core/features/dream/registries/mobs/DreamSpider.java index dd8e8387c..439fd9153 100644 --- a/src/main/java/fr/openmc/core/features/dream/registries/mobs/DreamSpider.java +++ b/src/main/java/fr/openmc/core/features/dream/registries/mobs/DreamSpider.java @@ -2,7 +2,7 @@ import fr.openmc.core.features.dream.models.registry.DreamMob; import fr.openmc.core.features.dream.registries.DreamItemRegistry; -import fr.openmc.core.registry.loottable.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import fr.openmc.core.utils.RandomUtils; import org.bukkit.Location; import org.bukkit.entity.Spider; @@ -19,7 +19,7 @@ public DreamSpider(String id) { 1L, RandomUtils.randomBetween(0.2, 0.3), RandomUtils.randomBetween(1.5, 2.0), - List.of(new CustomLoot( + List.of(new ItemLoot( DreamItemRegistry.CORRUPTED_STRING, 0.80, 1, diff --git a/src/main/java/fr/openmc/core/features/dream/registries/mobs/Soul.java b/src/main/java/fr/openmc/core/features/dream/registries/mobs/Soul.java index 5c6ddb389..444450981 100644 --- a/src/main/java/fr/openmc/core/features/dream/registries/mobs/Soul.java +++ b/src/main/java/fr/openmc/core/features/dream/registries/mobs/Soul.java @@ -3,7 +3,7 @@ import fr.openmc.core.OMCPlugin; import fr.openmc.core.features.dream.models.registry.DreamMob; import fr.openmc.core.features.dream.registries.DreamItemRegistry; -import fr.openmc.core.registry.loottable.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import fr.openmc.core.registry.mobs.CustomMobRegistry; import fr.openmc.core.utils.RandomUtils; import fr.openmc.core.utils.bukkit.EntityUtils; @@ -92,7 +92,7 @@ public Vex spawn(Location location) { return vex; } - private final List loots = List.of(new CustomLoot( + private final List loots = List.of(new ItemLoot( DreamItemRegistry.SOUL, 0.70, 1, @@ -121,19 +121,19 @@ private void registerSoulLink(Vex vex, ArmorStand stand) { Entity dead = e.getEntity(); if (dead.equals(vex) && stand.isValid()) { stand.remove(); - for (CustomLoot loot : loots) { - if (Math.random() >= loot.chance()) return; + for (ItemLoot loot : loots) { + if (Math.random() >= loot.getChance()) return; - int amount = loot.minAmount() + (int) (Math.random() * (loot.maxAmount() - loot.minAmount() + 1)); + int amount = loot.getMinAmount() + (int) (Math.random() * (loot.getMaxAmount() - loot.getMinAmount() + 1)); ItemStack drop = loot.getFirstLoot().asQuantity(amount); dead.getWorld().dropItemNaturally(dead.getLocation(), drop); } } else if (dead.equals(stand) && vex.isValid()) { vex.remove(); - for (CustomLoot loot : loots) { - if (Math.random() >= loot.chance()) return; + for (ItemLoot loot : loots) { + if (Math.random() >= loot.getChance()) return; - int amount = loot.minAmount() + (int) (Math.random() * (loot.maxAmount() - loot.minAmount() + 1)); + int amount = loot.getMinAmount() + (int) (Math.random() * (loot.getMaxAmount() - loot.getMinAmount() + 1)); ItemStack drop = loot.getFirstLoot().asQuantity(amount); dead.getWorld().dropItemNaturally(dead.getLocation(), drop); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/loottable/MiraculousFIshLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/loottable/MiraculousFishLootTable.java similarity index 62% rename from src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/loottable/MiraculousFIshLootTable.java rename to src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/loottable/MiraculousFishLootTable.java index 4dbd8c73c..b9e7ee421 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/loottable/MiraculousFIshLootTable.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/loottable/MiraculousFishLootTable.java @@ -1,22 +1,21 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.loottable; -import fr.openmc.core.registry.loottable.CustomLoot; import fr.openmc.core.registry.loottable.CustomLootTable; -import fr.openmc.core.registry.loottable.LootMoney; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.MoneyLoot; import java.util.Set; -public class MiraculousFIshLootTable extends CustomLootTable { +public class MiraculousFishLootTable extends CustomLootTable { @Override public String getNamespace() { return "omc_daily_events:miraculous_fishing"; } - // todo stop here @Override public Set getLoots() { return Set.of( - new LootMoney(50, 250) + new MoneyLoot(50, 250) ); } } diff --git a/src/main/java/fr/openmc/core/features/tickets/TicketListener.java b/src/main/java/fr/openmc/core/features/tickets/TicketListener.java index 5e0ff2854..ca26daea4 100644 --- a/src/main/java/fr/openmc/core/features/tickets/TicketListener.java +++ b/src/main/java/fr/openmc/core/features/tickets/TicketListener.java @@ -9,6 +9,7 @@ import fr.openmc.core.features.displays.holograms.Hologram; import fr.openmc.core.features.displays.holograms.HologramLoader; import fr.openmc.core.features.tickets.menus.MachineBallsMenu; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import fr.openmc.core.utils.text.messages.MessageType; import fr.openmc.core.utils.text.messages.MessagesManager; import fr.openmc.core.utils.text.messages.Prefix; @@ -37,7 +38,9 @@ public void onGetRewardLootBox(LootboxRewardEvent event) { String pelushKey = "omc_plush:peluche_seinyy"; - boolean hasLootPelucheSeinyy = event.getLoot().items().stream() + if (!(event.getLoot() instanceof ItemLoot itemLoot)) return; + + boolean hasLootPelucheSeinyy = itemLoot.getItems().stream() .filter(loot -> OMCRegistry.CUSTOM_ITEMS.get(loot).isPresent()) .anyMatch(loot -> OMCRegistry.CUSTOM_ITEMS.getOrThrow(loot).getId().equals(pelushKey)); diff --git a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java index 40182a97b..0409cfe85 100644 --- a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java +++ b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java @@ -5,7 +5,8 @@ import fr.openmc.api.menulib.utils.ItemMenuBuilder; import fr.openmc.core.OMCPlugin; import fr.openmc.core.events.LootboxRewardEvent; -import fr.openmc.core.registry.loottable.CustomLoot; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import fr.openmc.core.utils.text.messages.MessageType; import fr.openmc.core.utils.text.messages.MessagesManager; import fr.openmc.core.utils.text.messages.Prefix; @@ -45,7 +46,7 @@ public class LootboxOpenMenu extends Menu { private final CustomLootbox box; private int itemOffset = 0; - private CustomLoot winningItem = null; + private ItemLoot winningItem = null; private boolean finished = false; public LootboxOpenMenu(@NotNull Player owner, CustomLootbox box) { @@ -83,14 +84,14 @@ public String getTexture() { startAnimation(); if (finished && winningItem != null) { - items.put(22, new ItemMenuBuilder(this, winningItem.displayedItem().getType(), meta -> { + items.put(22, new ItemMenuBuilder(this, winningItem.getDisplayedItem().getType(), meta -> { meta.displayName(Component.text("§6§l✦ ") - .append(winningItem.displayedItem().effectiveName()) + .append(winningItem.getDisplayedItem().effectiveName()) .append(Component.text(" §6§l✦"))); List lore = new ArrayList<>(); lore.add(Component.text("§e§lFÉLICITATIONS !")); lore.add(Component.text(" ")); - lore.addAll(winningItem.displayedItem().lore()); + lore.addAll(winningItem.getDisplayedItem().lore()); meta.lore(lore); })); return items; @@ -99,11 +100,13 @@ public String getTexture() { List weightedPool = box.getLootTable().generateWeightedPool(); for (int i = 0; i < displaySlots.size(); i++) { int lootIndex = (itemOffset + i) % weightedPool.size(); - CustomLoot lootItem = weightedPool.get(lootIndex); + CustomLoot loot = weightedPool.get(lootIndex); - items.put(displaySlots.get(i), new ItemMenuBuilder(this, lootItem.displayedItem().getType(), meta -> { - meta.displayName(winningItem.displayedItem().effectiveName()); - meta.lore(lootItem.displayedItem().lore()); + if (!(loot instanceof ItemLoot itemLoot)) continue; + + items.put(displaySlots.get(i), new ItemMenuBuilder(this, itemLoot.getDisplayedItem().getType(), meta -> { + meta.displayName(winningItem.getDisplayedItem().effectiveName()); + meta.lore(itemLoot.getDisplayedItem().lore()); })); } @@ -141,8 +144,16 @@ public void startAnimation() { getOwner().playSound(Sound.sound(Key.key("minecraft", "block.note_block.pling"), Sound.Source.BLOCK, 1f, 1f)); - winningItem = box.getLootTable().selectRandomLoot(); - List weightedPool = box.getLootTable().generateWeightedPool(); + if (box.getLootTable().selectRandomLoot() instanceof ItemLoot itemLoot) { + winningItem = itemLoot; + } else { + winningItem = null; + } + + List weightedPool = box.getLootTable().generateWeightedPool() + .stream() + .filter(item -> item instanceof ItemLoot) + .map(item -> (ItemLoot) item).toList(); animationTask = new BukkitRunnable() { @Override @@ -167,7 +178,12 @@ public void run() { } private void finishAnimation(boolean withLatency) { - winningItem = box.getLootTable().selectRandomLoot(); + if (box.getLootTable().selectRandomLoot() instanceof ItemLoot itemLoot) { + winningItem = itemLoot; + } else { + winningItem = null; + } + finished = true; getOwner().playSound(Sound.sound(Key.key("minecraft", "entity.player.levelup"), @@ -184,7 +200,7 @@ public void run() { return; } getOwner().closeInventory(); - if (winningItem.chance() <= 10.0) { + if (winningItem.getChance() <= 10.0) { getOwner().playSound(Sound.sound(Key.key("minecraft", "entity.firework_rocket.launch"), Sound.Source.BLOCK, 1f, 1f)); @@ -203,7 +219,7 @@ public void run() { Component.text("§6§l✦ §e§lFÉLICITATIONS §r§eà ") .append(Component.text(getOwner().getName())) .append(Component.text(" §equi vient de gagner ")) - .append(winningItem.displayedItem().effectiveName()) + .append(winningItem.getDisplayedItem().effectiveName()) .append(Component.text(" §eà ")) .append(box.getName()) .append(Component.text(" §e! §6§l✦")), @@ -213,12 +229,12 @@ public void run() { }.runTaskLater(OMCPlugin.getInstance(), withLatency ? 60L : 0L); } - private boolean giveReward(CustomLoot wonItem) { + private boolean giveReward(ItemLoot wonItem) { LootboxRewardEvent rewardEvent = new LootboxRewardEvent(getOwner(), box, wonItem); Bukkit.getPluginManager().callEvent(rewardEvent); if (rewardEvent.isCancelled()) return true; - for (ItemStack reward : wonItem.items()) { + for (ItemStack reward : wonItem.getItems()) { if (getOwner().getInventory().firstEmpty() != -1) { getOwner().getInventory().addItem(reward); } else { @@ -228,19 +244,19 @@ private boolean giveReward(CustomLoot wonItem) { MessagesManager.sendMessage(getOwner(), Component.text("§aVous avez gagné : ") - .append(wonItem.displayedItem().displayName()) + .append(wonItem.getDisplayedItem().displayName()) .append(Component.text(" §a!")), Prefix.OPENMC, MessageType.SUCCESS, true); return false; } - private void refreshAnimated(List pool) { + private void refreshAnimated(List pool) { if (!(getOwner().getOpenInventory().getTopInventory().getHolder() instanceof LootboxOpenMenu)) return; Inventory inv = getOwner().getOpenInventory().getTopInventory(); for (int i = 0; i < displaySlots.size(); i++) { int index; - CustomLoot itemToShow; + ItemLoot itemToShow; if (animationTick > maxAnimationTicks - 10 && i == displaySlots.indexOf(box.getOptions().rewardSlot())) { itemToShow = winningItem; @@ -249,9 +265,9 @@ private void refreshAnimated(List pool) { itemToShow = pool.get(index); } - inv.setItem(displaySlots.get(i), new ItemMenuBuilder(this, itemToShow.displayedItem().getType(), meta -> { - meta.displayName(itemToShow.displayedItem().effectiveName()); - meta.lore(itemToShow.displayedItem().lore()); + inv.setItem(displaySlots.get(i), new ItemMenuBuilder(this, itemToShow.getDisplayedItem().getType(), meta -> { + meta.displayName(itemToShow.getDisplayedItem().effectiveName()); + meta.lore(itemToShow.getDisplayedItem().lore()); })); } diff --git a/src/main/java/fr/openmc/core/registry/loottable/CustomLoot.java b/src/main/java/fr/openmc/core/registry/loottable/CustomLoot.java deleted file mode 100644 index 36c7cd21e..000000000 --- a/src/main/java/fr/openmc/core/registry/loottable/CustomLoot.java +++ /dev/null @@ -1,3 +0,0 @@ -package fr.openmc.core.registry.loottable; - -public interface CustomLoot {} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/loottable/CustomLootTable.java b/src/main/java/fr/openmc/core/registry/loottable/CustomLootTable.java index 6f182870b..a004d0bde 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/CustomLootTable.java +++ b/src/main/java/fr/openmc/core/registry/loottable/CustomLootTable.java @@ -1,6 +1,9 @@ package fr.openmc.core.registry.loottable; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import fr.openmc.core.utils.bukkit.ItemUtils; +import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import java.util.ArrayList; @@ -15,62 +18,47 @@ public abstract class CustomLootTable { public double getChanceOf(ItemStack item) { return this.getLoots().stream() - .filter(loot -> loot.items().stream() + .filter(loot -> loot instanceof ItemLoot) + .map(loot -> (ItemLoot) loot) + .filter(loot -> loot.getItems().stream() .anyMatch(lootItem -> ItemUtils.isSimilar(lootItem, item))) - .mapToDouble(CustomLoot::chance) + .mapToDouble(CustomLoot::getChance) .sum(); } - /** - * Rolls the loot table and returns a list of ItemStacks based on the defined chances. - * The method calculates the total chance of all loots, generates a random number, - * and iterates through the loots to determine which one(s) to drop based on their chances. - * @return A list of ItemStacks representing the rolled loot. - */ - public List rollLoots() { - List result = new ArrayList<>(); + public List rollLoots(Player receiver) { + List result = new ArrayList<>(); double totalChance = this.getLoots().stream() - .mapToDouble(CustomLoot::chance) + .mapToDouble(CustomLoot::getChance) .sum(); double roll = Math.random() * totalChance; double sumChance = 0.0; for (CustomLoot loot : this.getLoots()) { - sumChance += loot.chance(); + sumChance += loot.getChance(); if (roll <= sumChance) { - for (ItemStack lootItem : loot.items()) { - ItemStack item = lootItem.clone(); - item.setAmount(loot.getRandomAmount()); - result.add(item); - } + loot.run(receiver); + result.add(loot); break; } } if (result.isEmpty()) { CustomLoot next = this.getLoots().iterator().next(); - for (ItemStack lootItem : next.items()) { - ItemStack item = lootItem.clone(); - item.setAmount(next.getRandomAmount()); - result.add(item); - } + next.run(receiver); + result.add(next); } return result; } - /** - * Rolls the loot table and returns a list of ItemStacks based on the defined chances, but with a specified amount for each loot. - * @param amountRoll The amount to set for each rolled loot. This will override the random amount defined in the CustomLoot. - * @return A list of ItemStacks representing the rolled loot with the specified amount. - */ - public List rollLootsWithAmount(int amountRoll) { - List loot = new ArrayList<>(); + public List rollLootsWithAmount(Player receiver, int amountRoll) { + List loot = new ArrayList<>(); for (int i = 0; i < amountRoll; i++) { - loot.addAll(rollLoots()); + loot.addAll(rollLoots(receiver)); } return loot; @@ -78,17 +66,17 @@ public List rollLootsWithAmount(int amountRoll) { public CustomLoot selectRandomLoot() { double totalChance = this.getLoots().stream() - .mapToDouble(CustomLoot::chance) + .mapToDouble(CustomLoot::getChance) .sum(); double random = ThreadLocalRandom.current().nextDouble(totalChance); double cumulative = 0; - for (CustomLoot item : this.getLoots()) { - cumulative += item.chance(); + for (CustomLoot loot : this.getLoots()) { + cumulative += loot.getChance(); if (random <= cumulative) { - return item; + return loot; } } @@ -97,10 +85,10 @@ public CustomLoot selectRandomLoot() { public List generateWeightedPool() { List pool = new ArrayList<>(); - for (CustomLoot item : this.getLoots()) { - int count = Math.max(1, (int) (item.chance() * 2)); + for (CustomLoot loot : this.getLoots()) { + int count = Math.max(1, (int) (loot.getChance() * 2)); for (int i = 0; i < count; i++) { - pool.add(item); + pool.add(loot); } } Collections.shuffle(pool); diff --git a/src/main/java/fr/openmc/core/registry/loottable/CustomLootTableRegistry.java b/src/main/java/fr/openmc/core/registry/loottable/CustomLootTableRegistry.java index ef052ec63..c20acdd68 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/CustomLootTableRegistry.java +++ b/src/main/java/fr/openmc/core/registry/loottable/CustomLootTableRegistry.java @@ -2,6 +2,7 @@ import fr.openmc.core.bootstrap.registries.KeyedRegistry; import fr.openmc.core.bootstrap.registries.Registry; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.loottable.MiraculousFishLootTable; import fr.openmc.core.registry.loottable.contents.MachineBallLootTable; public class CustomLootTableRegistry extends Registry implements KeyedRegistry { @@ -9,6 +10,8 @@ public class CustomLootTableRegistry extends Registry i // ** REGISTER LOOT TABLE ** public final CustomLootTable MACHINE_BALL = register(new MachineBallLootTable()); + public final CustomLootTable MIRACULOUS_FISHING = register(new MiraculousFishLootTable()); + @Override public String key(CustomLootTable registryObject) { return registryObject.getNamespace(); diff --git a/src/main/java/fr/openmc/core/registry/loottable/LootMethod.java b/src/main/java/fr/openmc/core/registry/loottable/LootMethod.java deleted file mode 100644 index 296bba7c9..000000000 --- a/src/main/java/fr/openmc/core/registry/loottable/LootMethod.java +++ /dev/null @@ -1,9 +0,0 @@ -package fr.openmc.core.registry.loottable; - -import org.bukkit.entity.Player; - -import java.util.function.Consumer; - -public record LootMethod(Consumer receiver) implements CustomLoot { - -} diff --git a/src/main/java/fr/openmc/core/registry/loottable/LootMoney.java b/src/main/java/fr/openmc/core/registry/loottable/LootMoney.java deleted file mode 100644 index 09bdf432b..000000000 --- a/src/main/java/fr/openmc/core/registry/loottable/LootMoney.java +++ /dev/null @@ -1,9 +0,0 @@ -package fr.openmc.core.registry.loottable; - -import fr.openmc.core.utils.RandomUtils; - -public record LootMoney(double money) implements CustomLoot { - public LootMoney(double minMoney, double maxMoney) { - this(RandomUtils.randomBetween(minMoney, maxMoney)); - } -} diff --git a/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java b/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java index 6b35279ef..7ad1f0b06 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java +++ b/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java @@ -1,9 +1,9 @@ package fr.openmc.core.registry.loottable.contents; import fr.openmc.core.OMCRegistry; -import fr.openmc.core.registry.loottable.CustomLoot; import fr.openmc.core.registry.loottable.CustomLootTable; -import fr.openmc.core.registry.loottable.LootItem; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import fr.openmc.core.utils.bukkit.ItemBuilder; import net.kyori.adventure.text.Component; import org.bukkit.Material; @@ -21,7 +21,7 @@ public String getNamespace() { @Override public Set getLoots() { return Set.of( - new LootItem( + new ItemLoot( Set.of(OMCRegistry.CUSTOM_ITEMS.PELUCHE_SEINYY.getBest()), new ItemBuilder( OMCRegistry.CUSTOM_ITEMS.PELUCHE_SEINYY, @@ -34,7 +34,7 @@ public Set getLoots() { 1, 1 ), - new LootItem( + new ItemLoot( Set.of(new ItemStack(Material.DIAMOND, 3)), new ItemBuilder( Material.DIAMOND, @@ -47,7 +47,7 @@ public Set getLoots() { 1, 1 ), - new LootItem( + new ItemLoot( Set.of(new ItemStack(Material.IRON_INGOT, 10)), new ItemBuilder( Material.IRON_INGOT, @@ -60,7 +60,7 @@ public Set getLoots() { 1, 1 ), - new LootItem( + new ItemLoot( Set.of(new ItemStack(Material.NETHERITE_INGOT)), new ItemBuilder( Material.NETHERITE_INGOT, @@ -73,7 +73,7 @@ public Set getLoots() { 1, 1 ), - new LootItem( + new ItemLoot( Set.of(new ItemStack(Material.OAK_LOG, 32)), new ItemBuilder( Material.OAK_LOG, @@ -86,7 +86,7 @@ public Set getLoots() { 1, 1 ), - new LootItem( + new ItemLoot( Set.of(new ItemStack(Material.COOKED_BEEF, 16)), new ItemBuilder( Material.COOKED_BEEF, @@ -99,7 +99,7 @@ public Set getLoots() { 1, 1 ), - new LootItem( + new ItemLoot( Set.of(new ItemStack(Material.COAL, 16)), new ItemBuilder( Material.COAL, diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java new file mode 100644 index 000000000..065734709 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java @@ -0,0 +1,8 @@ +package fr.openmc.core.registry.loottable.loots; + +import org.bukkit.entity.Player; + +public interface CustomLoot { + double getChance(); + void run(Player receiver); +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/loottable/LootItem.java b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java similarity index 55% rename from src/main/java/fr/openmc/core/registry/loottable/LootItem.java rename to src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java index 24c6aa2b6..3f0a66c23 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/LootItem.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java @@ -1,14 +1,30 @@ -package fr.openmc.core.registry.loottable; +package fr.openmc.core.registry.loottable.loots; import fr.openmc.core.registry.items.CustomItem; +import lombok.Getter; +import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import java.util.Collections; import java.util.Set; -public record LootItem(Set items, ItemStack displayedItem, double chance, int minAmount, int maxAmount) implements CustomLoot { +@Getter +public class ItemLoot implements CustomLoot { + private final double chance; + private final Set items; + private final ItemStack displayedItem; + private final int minAmount; + private final int maxAmount; - public LootItem(ItemStack item, double chance, int minAmount, int maxAmount) { + public ItemLoot(Set items, ItemStack displayedItem, double chance, int minAmount, int maxAmount) { + this.chance = chance; + this.items = items; + this.displayedItem = displayedItem; + this.minAmount = minAmount; + this.maxAmount = maxAmount; + } + + public ItemLoot(ItemStack item, double chance, int minAmount, int maxAmount) { this(Collections.singleton(item), null, chance, @@ -16,7 +32,7 @@ public LootItem(ItemStack item, double chance, int minAmount, int maxAmount) { maxAmount); } - public LootItem(CustomItem item, double chance, int minAmount, int maxAmount) { + public ItemLoot(CustomItem item, double chance, int minAmount, int maxAmount) { if (item == null) { throw new IllegalArgumentException("CustomItem cannot be null"); } @@ -27,7 +43,7 @@ public LootItem(CustomItem item, double chance, int minAmount, int maxAmount) { maxAmount); } - public LootItem(ItemStack item, ItemStack displayedItem, double chance, int minAmount, int maxAmount) { + public ItemLoot(ItemStack item, ItemStack displayedItem, double chance, int minAmount, int maxAmount) { this(Collections.singleton(item), displayedItem, chance, @@ -35,7 +51,7 @@ public LootItem(ItemStack item, ItemStack displayedItem, double chance, int minA maxAmount); } - public LootItem(CustomItem item, ItemStack displayedItem, double chance, int minAmount, int maxAmount) { + public ItemLoot(CustomItem item, ItemStack displayedItem, double chance, int minAmount, int maxAmount) { if (item == null) { throw new IllegalArgumentException("CustomItem cannot be null"); } @@ -56,4 +72,13 @@ public ItemStack getFirstLoot() { public int getRandomAmount() { return minAmount + (int) (Math.random() * (maxAmount - minAmount + 1)); } + + @Override + public void run(Player receiver) { + for (ItemStack lootItem : this.getItems()) { + ItemStack item = lootItem.clone(); + item.setAmount(this.getRandomAmount()); + receiver.getInventory().addItem(item); + } + } } \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java new file mode 100644 index 000000000..24b153c6f --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java @@ -0,0 +1,22 @@ +package fr.openmc.core.registry.loottable.loots; + +import lombok.Getter; +import org.bukkit.entity.Player; + +import java.util.function.Consumer; + +@Getter +public class MethodLoot implements CustomLoot { + private final double chance; + private final Consumer receiverAction; + + public MethodLoot(Consumer receiverAction, double chance) { + this.chance = chance; + this.receiverAction = receiverAction; + } + + @Override + public void run(Player receiver) { + receiverAction.accept(receiver); + } +} diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java new file mode 100644 index 000000000..ec96bbe04 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java @@ -0,0 +1,17 @@ +package fr.openmc.core.registry.loottable.loots; + +import fr.openmc.core.features.economy.EconomyManager; +import fr.openmc.core.utils.RandomUtils; +import org.bukkit.entity.Player; + + +public record MoneyLoot(double money, double getChance) implements CustomLoot { + public MoneyLoot(double minMoney, double maxMoney, double chance) { + this(RandomUtils.randomBetween(minMoney, maxMoney), chance); + } + + @Override + public void run(Player receiver) { + EconomyManager.addBalance(receiver.getUniqueId(), money); + } +} diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java new file mode 100644 index 000000000..4a1c91be3 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java @@ -0,0 +1,21 @@ +package fr.openmc.core.registry.loottable.loots; + +import fr.openmc.core.registry.loottable.CustomLootTable; +import lombok.Getter; +import org.bukkit.entity.Player; + +@Getter +public class TableLoot implements CustomLoot { + private final double chance; + private final CustomLootTable lootTable; + + public TableLoot(CustomLootTable lootTable, double chance) { + this.chance = chance; + this.lootTable = lootTable; + } + + @Override + public void run(Player receiver) { + lootTable.rollLoots(receiver); + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/mobs/CustomMob.java b/src/main/java/fr/openmc/core/registry/mobs/CustomMob.java index a2e162ca1..9cb1b4a8b 100644 --- a/src/main/java/fr/openmc/core/registry/mobs/CustomMob.java +++ b/src/main/java/fr/openmc/core/registry/mobs/CustomMob.java @@ -1,6 +1,6 @@ package fr.openmc.core.registry.mobs; -import fr.openmc.core.registry.loottable.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import lombok.Getter; import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; @@ -21,7 +21,7 @@ public abstract class CustomMob { private final String name; private final Class entityClass; private final Set baseAttributes = new HashSet<>(); - private final List loots = new ArrayList<>(); + private final List loots = new ArrayList<>(); public CustomMob(String id, String name, Class entityClass, double health, double damage, CustomMobAttribute... baseAttributes) { this.id = id; @@ -42,7 +42,7 @@ public CustomMob(String id, String name, Class entityClass, double health, do this.baseAttributes.addAll(Arrays.stream(baseAttributes).toList()); } - public CustomMob(String id, String name, Class entityClass, double health, double damage, double speed, List loots, CustomMobAttribute... baseAttributes) { + public CustomMob(String id, String name, Class entityClass, double health, double damage, double speed, List loots, CustomMobAttribute... baseAttributes) { this.id = id; this.name = name; this.entityClass = entityClass; @@ -53,7 +53,7 @@ public CustomMob(String id, String name, Class entityClass, double health, do this.loots.addAll(loots); } - public CustomMob(String id, String name, Class entityClass, double health, double damage, List loots, CustomMobAttribute... baseAttributes) { + public CustomMob(String id, String name, Class entityClass, double health, double damage, List loots, CustomMobAttribute... baseAttributes) { this.id = id; this.name = name; this.entityClass = entityClass; diff --git a/src/main/java/fr/openmc/core/registry/mobs/listeners/CustomMobDeathListener.java b/src/main/java/fr/openmc/core/registry/mobs/listeners/CustomMobDeathListener.java index 6172d7b85..2d885a342 100644 --- a/src/main/java/fr/openmc/core/registry/mobs/listeners/CustomMobDeathListener.java +++ b/src/main/java/fr/openmc/core/registry/mobs/listeners/CustomMobDeathListener.java @@ -1,7 +1,7 @@ package fr.openmc.core.registry.mobs.listeners; import fr.openmc.core.OMCRegistry; -import fr.openmc.core.registry.loottable.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import fr.openmc.core.registry.mobs.CustomMob; import fr.openmc.core.registry.mobs.CustomMobRegistry; import org.bukkit.damage.DamageSource; @@ -33,10 +33,10 @@ public void onEntityDeath(EntityDeathEvent event) { customMob.onDeath(customMob, event); if (customMob.getLoots() == null) return; - for (CustomLoot loot : customMob.getLoots()) { - if (Math.random() >= loot.chance()) return; + for (ItemLoot loot : customMob.getLoots()) { + if (Math.random() >= loot.getChance()) return; - int amount = loot.minAmount() + (int) (Math.random() * (loot.maxAmount() - loot.minAmount() + 1)); + int amount = loot.getMinAmount() + (int) (Math.random() * (loot.getMaxAmount() - loot.getMinAmount() + 1)); ItemStack drop = loot.getFirstLoot().asQuantity(amount); entity.getWorld().dropItemNaturally(entity.getLocation(), drop); } From 549f8db78a0f0a729ce5f192f05f8d69bc041216 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 18 Jun 2026 11:59:04 +0200 Subject: [PATCH 46/74] add all loot table for MiraculousFishing --- .../dream/registries/DreamItemRegistry.java | 1 + .../registries/items/blocks/EweniteBlock.java | 24 ++++++++ .../lootboxes/EpicFishingTreasureLootbox.java | 26 ++++++++ .../lootboxes/FishingFurnitureLootbox.java | 26 ++++++++ .../LegendaryFishingTreasureLootbox.java | 26 ++++++++ .../lootboxes/RareFishingTreasureLootbox.java | 26 ++++++++ .../loottable/fishing/BasicFishLootTable.java | 25 ++++++++ .../fishing/MiraculousFishLootTable.java | 29 +++++++++ .../lootbox/EpicFishingTreasureLootTable.java | 61 +++++++++++++++++++ .../lootbox/FishingFurnitureLootTable.java} | 11 ++-- .../LegendaryFishingTreasureLootTable.java | 24 ++++++++ .../lootbox/RareFishingTreasureLootTable.java | 31 ++++++++++ .../lootboxes/CustomLootboxRegistry.java | 9 +++ .../loottable/CustomLootTableRegistry.java | 13 +++- .../registry/loottable/loots/ItemLoot.java | 28 +++++++++ .../registry/loottable/loots/LootboxLoot.java | 21 +++++++ .../default/dailyevents.properties | 6 ++ 17 files changed, 380 insertions(+), 7 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/dream/registries/items/blocks/EweniteBlock.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/EpicFishingTreasureLootbox.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/FishingFurnitureLootbox.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/LegendaryFishingTreasureLootbox.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/RareFishingTreasureLootbox.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/fishing/BasicFishLootTable.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/fishing/MiraculousFishLootTable.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/EpicFishingTreasureLootTable.java rename src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/{loottable/MiraculousFishLootTable.java => contents/loottable/lootbox/FishingFurnitureLootTable.java} (58%) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/LegendaryFishingTreasureLootTable.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/RareFishingTreasureLootTable.java create mode 100644 src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java diff --git a/src/main/java/fr/openmc/core/features/dream/registries/DreamItemRegistry.java b/src/main/java/fr/openmc/core/features/dream/registries/DreamItemRegistry.java index 57c1ac892..72aa61381 100644 --- a/src/main/java/fr/openmc/core/features/dream/registries/DreamItemRegistry.java +++ b/src/main/java/fr/openmc/core/features/dream/registries/DreamItemRegistry.java @@ -64,6 +64,7 @@ public class DreamItemRegistry { public static final DreamItem CRAFTING_TABLE = create(new CraftingTable()); public static final DreamItem ETERNAL_CAMPFIRE = create(new EternalCampFire()); public static final DreamItem EWENITE = create(new Ewenite()); + public static final DreamItem EWENITE_BLOCK = create(new EweniteBlock()); public static final DreamItem SOMNIFERE = create(new Somnifere()); public static final DreamItem CHIPS_AYWEN = create(new ChipsAywen()); diff --git a/src/main/java/fr/openmc/core/features/dream/registries/items/blocks/EweniteBlock.java b/src/main/java/fr/openmc/core/features/dream/registries/items/blocks/EweniteBlock.java new file mode 100644 index 000000000..6043cff17 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/dream/registries/items/blocks/EweniteBlock.java @@ -0,0 +1,24 @@ +package fr.openmc.core.features.dream.registries.items.blocks; + +import fr.openmc.core.features.dream.models.registry.items.DreamItem; +import fr.openmc.core.features.dream.models.registry.items.DreamItemMeta; +import fr.openmc.core.features.dream.models.registry.items.DreamRarity; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +public class EweniteBlock extends DreamItem { + public EweniteBlock() { + super(new DreamItemMeta( + "omc_dream:ewenite_block", + "Bloc d'ewenite", + DreamRarity.ONIRISIME, + Material.NETHERITE_BLOCK, + false + )); + } + + @Override + public ItemStack getTransferableItem() { + return new ItemStack(Material.SCULK); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/EpicFishingTreasureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/EpicFishingTreasureLootbox.java new file mode 100644 index 000000000..e955ed240 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/EpicFishingTreasureLootbox.java @@ -0,0 +1,26 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.lootboxes; + +import fr.openmc.api.menulib.utils.InventorySize; +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.lootboxes.CustomLootbox; +import fr.openmc.core.registry.lootboxes.LootboxOptions; +import fr.openmc.core.utils.text.messages.TranslationManager; + +import java.util.stream.IntStream; + +public class EpicFishingTreasureLootbox extends CustomLootbox { + public EpicFishingTreasureLootbox() { + super( + "omc_daily_events:epic_fishing_treasure", + TranslationManager.translation("feature.dailyevents.miraculousfishing.lootbox.epic_fishing_treasure.name"), + OMCRegistry.CUSTOM_LOOT_TABLES.EPIC_FISHING_TREASURE, + new LootboxOptions( + InventorySize.NORMAL, + 60, + IntStream.range(10, 17).boxed().toList(), + 13 + ) + ); + } +} + diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/FishingFurnitureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/FishingFurnitureLootbox.java new file mode 100644 index 000000000..79e228298 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/FishingFurnitureLootbox.java @@ -0,0 +1,26 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.lootboxes; + +import fr.openmc.api.menulib.utils.InventorySize; +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.lootboxes.CustomLootbox; +import fr.openmc.core.registry.lootboxes.LootboxOptions; +import fr.openmc.core.utils.text.messages.TranslationManager; + +import java.util.stream.IntStream; + +public class FishingFurnitureLootbox extends CustomLootbox { + public FishingFurnitureLootbox() { + super( + "omc_daily_events:fishing_furniture", + TranslationManager.translation("feature.dailyevents.miraculousfishing.lootbox.fishing_furniture.name"), + OMCRegistry.CUSTOM_LOOT_TABLES.FISHING_FURNITURE, + new LootboxOptions( + InventorySize.NORMAL, + 60, + IntStream.range(10, 17).boxed().toList(), + 13 + ) + ); + } +} + diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/LegendaryFishingTreasureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/LegendaryFishingTreasureLootbox.java new file mode 100644 index 000000000..741b97d20 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/LegendaryFishingTreasureLootbox.java @@ -0,0 +1,26 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.lootboxes; + +import fr.openmc.api.menulib.utils.InventorySize; +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.lootboxes.CustomLootbox; +import fr.openmc.core.registry.lootboxes.LootboxOptions; +import fr.openmc.core.utils.text.messages.TranslationManager; + +import java.util.stream.IntStream; + +public class LegendaryFishingTreasureLootbox extends CustomLootbox { + public LegendaryFishingTreasureLootbox() { + super( + "omc_daily_events:legendary_fishing_treasure", + TranslationManager.translation("feature.dailyevents.miraculousfishing.lootbox.legendary_fishing_treasure.name"), + OMCRegistry.CUSTOM_LOOT_TABLES.LEGENDARY_FISHING_TREASURE, + new LootboxOptions( + InventorySize.NORMAL, + 60, + IntStream.range(10, 17).boxed().toList(), + 13 + ) + ); + } +} + diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/RareFishingTreasureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/RareFishingTreasureLootbox.java new file mode 100644 index 000000000..bd206b6c2 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/RareFishingTreasureLootbox.java @@ -0,0 +1,26 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.lootboxes; + +import fr.openmc.api.menulib.utils.InventorySize; +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.lootboxes.CustomLootbox; +import fr.openmc.core.registry.lootboxes.LootboxOptions; +import fr.openmc.core.utils.text.messages.TranslationManager; + +import java.util.stream.IntStream; + +public class RareFishingTreasureLootbox extends CustomLootbox { + public RareFishingTreasureLootbox() { + super( + "omc_daily_events:rare_fishing_treasure", + TranslationManager.translation("feature.dailyevents.miraculousfishing.lootbox.rare_fishing_treasure.name"), + OMCRegistry.CUSTOM_LOOT_TABLES.RARE_FISHING_TREASURE, + new LootboxOptions( + InventorySize.NORMAL, + 60, + IntStream.range(10, 17).boxed().toList(), + 13 + ) + ); + } +} + diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/fishing/BasicFishLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/fishing/BasicFishLootTable.java new file mode 100644 index 000000000..ee6b9f33c --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/fishing/BasicFishLootTable.java @@ -0,0 +1,25 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.fishing; + +import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; +import org.bukkit.Material; + +import java.util.Set; + +public class BasicFishLootTable extends CustomLootTable { + @Override + public String getNamespace() { + return "omc_daily_events:basic_fishing"; + } + + @Override + public Set getLoots() { + return Set.of( + new ItemLoot(Material.COD, Material.COD, 0.6, 2, 4), + new ItemLoot(Material.SALMON, Material.SALMON, 0.25, 2, 4), + new ItemLoot(Material.TROPICAL_FISH, Material.TROPICAL_FISH, 0.02, 2, 4), + new ItemLoot(Material.PUFFERFISH, Material.PUFFERFISH, 0.13, 2, 4) + ); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/fishing/MiraculousFishLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/fishing/MiraculousFishLootTable.java new file mode 100644 index 000000000..c634f2e09 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/fishing/MiraculousFishLootTable.java @@ -0,0 +1,29 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.fishing; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.LootboxLoot; +import fr.openmc.core.registry.loottable.loots.MoneyLoot; +import fr.openmc.core.registry.loottable.loots.TableLoot; + +import java.util.Set; + +public class MiraculousFishLootTable extends CustomLootTable { + @Override + public String getNamespace() { + return "omc_daily_events:miraculous_fishing"; + } + + @Override + public Set getLoots() { + return Set.of( + new TableLoot(OMCRegistry.CUSTOM_LOOT_TABLES.BASIC_FISHING, 0.4), + new MoneyLoot(50, 250, 0.3), + // new ItemLoot(OMCRegistry.CUSTOM_ITEMS.BOB_SPONGE, 0.1, 1, 1), + new LootboxLoot(OMCRegistry.CUSTOM_LOOTBOXES.FISHING_FURNITURE, 0.08), + new LootboxLoot(OMCRegistry.CUSTOM_LOOTBOXES.RARE_FISHING_TREASURE, 0.1) + // new TableLoot(OMCRegistry.CUSTOM_LOOT_TABLES.SEA_CREATURE, 0.2) + ); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/EpicFishingTreasureLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/EpicFishingTreasureLootTable.java new file mode 100644 index 000000000..4abd1e9ec --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/EpicFishingTreasureLootTable.java @@ -0,0 +1,61 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.lootbox; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; +import fr.openmc.core.registry.loottable.loots.LootboxLoot; +import fr.openmc.core.utils.RandomUtils; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.EnchantmentStorageMeta; + +import java.util.List; +import java.util.Set; + +public class EpicFishingTreasureLootTable extends CustomLootTable { + @Override + public String getNamespace() { + return "omc_daily_events:epic_fishing_treasure"; + } + + @Override + public Set getLoots() { + return Set.of( + new ItemLoot(generateEnchantedBook(), Material.ENCHANTED_BOOK, 0.2, 1, 2), + //new ItemLoot(OMCRegistry.CUSTOM_ITEMS.KEBAB_FERMENTED, OMCRegistry.CUSTOM_ITEMS.KEBAB_FERMENTED, 0.1, 1, 3), + new ItemLoot(OMCRegistry.CUSTOM_ITEMS.AYWENITE_BLOCK, OMCRegistry.CUSTOM_ITEMS.AYWENITE_BLOCK, 0.07, 2, 6), + new LootboxLoot(OMCRegistry.CUSTOM_LOOTBOXES.LEGENDARY_FISHING_TREASURE, 0.1) + ); + } + + private final List ENCHANTMENT_AVAILABLE = List.of( + Enchantment.DEPTH_STRIDER, + Enchantment.LURE, + Enchantment.MENDING, + Enchantment.LOOTING, + Enchantment.UNBREAKING, + Enchantment.LUCK_OF_THE_SEA + ); + + private ItemStack generateEnchantedBook() { + ItemStack enchantedBook = new ItemStack(Material.ENCHANTED_BOOK); + EnchantmentStorageMeta meta = (EnchantmentStorageMeta) enchantedBook.getItemMeta(); + if (meta != null) { + for (Enchantment enchantment : selectEnchantment(RandomUtils.randomBetween(2, 5))) { + int level = RandomUtils.randomBetween(enchantment.getStartLevel(), enchantment.getMaxLevel()); + meta.addStoredEnchant(enchantment, level, true); + } + + enchantedBook.setItemMeta(meta); + } + return enchantedBook; + } + + private List selectEnchantment(int number) { + List randomOrder = RandomUtils.generateRandomOrder(ENCHANTMENT_AVAILABLE); + + return randomOrder.subList(0, Math.min(number, randomOrder.size())); + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/loottable/MiraculousFishLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/FishingFurnitureLootTable.java similarity index 58% rename from src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/loottable/MiraculousFishLootTable.java rename to src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/FishingFurnitureLootTable.java index b9e7ee421..ef989fdf5 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/loottable/MiraculousFishLootTable.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/FishingFurnitureLootTable.java @@ -1,21 +1,20 @@ -package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.loottable; +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.lootbox; import fr.openmc.core.registry.loottable.CustomLootTable; import fr.openmc.core.registry.loottable.loots.CustomLoot; -import fr.openmc.core.registry.loottable.loots.MoneyLoot; import java.util.Set; -public class MiraculousFishLootTable extends CustomLootTable { +public class FishingFurnitureLootTable extends CustomLootTable { @Override public String getNamespace() { - return "omc_daily_events:miraculous_fishing"; + return "omc_daily_events:fishing_furniture"; } @Override public Set getLoots() { return Set.of( - new MoneyLoot(50, 250) + // todo: put furniture in contents item adders ); } -} +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/LegendaryFishingTreasureLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/LegendaryFishingTreasureLootTable.java new file mode 100644 index 000000000..35ef67095 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/LegendaryFishingTreasureLootTable.java @@ -0,0 +1,24 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.lootbox; + +import fr.openmc.core.features.dream.registries.DreamItemRegistry; +import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; + +import java.util.Set; + +public class LegendaryFishingTreasureLootTable extends CustomLootTable { + @Override + public String getNamespace() { + return "omc_daily_events:legendary_fishing_treasure"; + } + + @Override + public Set getLoots() { + return Set.of( + //new ItemLoot(OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_HELMET, OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_HELMET, 0.20, 1, 1), + //new ItemLoot(OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_BOOTS, OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_BOOTS, 0.20, 1, 1), + new ItemLoot(DreamItemRegistry.EWENITE_BLOCK, DreamItemRegistry.EWENITE_BLOCK, 0.006, 1, 1) + ); + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/RareFishingTreasureLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/RareFishingTreasureLootTable.java new file mode 100644 index 000000000..39bbb0f8b --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/RareFishingTreasureLootTable.java @@ -0,0 +1,31 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.lootbox; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; +import fr.openmc.core.registry.loottable.loots.LootboxLoot; +import org.bukkit.Material; + +import java.util.Set; + +public class RareFishingTreasureLootTable extends CustomLootTable { + @Override + public String getNamespace() { + return "omc_daily_events:rare_fishing_treasure"; + } + + @Override + public Set getLoots() { + return Set.of( + new ItemLoot(Material.COD, Material.COD, 0.3, 32, 64), + new ItemLoot(Material.SALMON, Material.SALMON, 0.3, 32, 64), + new ItemLoot(Material.TROPICAL_FISH, Material.TROPICAL_FISH, 0.3, 32, 64), + new ItemLoot(Material.PUFFERFISH, Material.PUFFERFISH, 0.3, 15, 32), + new ItemLoot(Material.NAUTILUS_SHELL, Material.NAUTILUS_SHELL, 0.15, 2, 4), + // todo add ampoule + new LootboxLoot(OMCRegistry.CUSTOM_LOOTBOXES.EPIC_FISHING_TREASURE, 0.1) + + ); + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/lootboxes/CustomLootboxRegistry.java b/src/main/java/fr/openmc/core/registry/lootboxes/CustomLootboxRegistry.java index 9004cbdab..cb0efc260 100644 --- a/src/main/java/fr/openmc/core/registry/lootboxes/CustomLootboxRegistry.java +++ b/src/main/java/fr/openmc/core/registry/lootboxes/CustomLootboxRegistry.java @@ -2,6 +2,10 @@ import fr.openmc.core.bootstrap.registries.KeyedRegistry; import fr.openmc.core.bootstrap.registries.Registry; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.lootboxes.EpicFishingTreasureLootbox; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.lootboxes.FishingFurnitureLootbox; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.lootboxes.LegendaryFishingTreasureLootbox; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.lootboxes.RareFishingTreasureLootbox; import fr.openmc.core.registry.lootboxes.contents.MachineBallLootbox; public class CustomLootboxRegistry extends Registry implements KeyedRegistry { @@ -9,6 +13,11 @@ public class CustomLootboxRegistry extends Registry imple // ** REGISTER LOOTBOX ** public final CustomLootbox MACHINE_BALL = register(new MachineBallLootbox()); + public final CustomLootbox FISHING_FURNITURE = register(new FishingFurnitureLootbox()); + public final CustomLootbox RARE_FISHING_TREASURE = register(new RareFishingTreasureLootbox()); + public final CustomLootbox EPIC_FISHING_TREASURE = register(new EpicFishingTreasureLootbox()); + public final CustomLootbox LEGENDARY_FISHING_TREASURE = register(new LegendaryFishingTreasureLootbox()); + @Override public String key(CustomLootbox registryObject) { return registryObject.getNamespace(); diff --git a/src/main/java/fr/openmc/core/registry/loottable/CustomLootTableRegistry.java b/src/main/java/fr/openmc/core/registry/loottable/CustomLootTableRegistry.java index c20acdd68..9928a0557 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/CustomLootTableRegistry.java +++ b/src/main/java/fr/openmc/core/registry/loottable/CustomLootTableRegistry.java @@ -2,7 +2,12 @@ import fr.openmc.core.bootstrap.registries.KeyedRegistry; import fr.openmc.core.bootstrap.registries.Registry; -import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.loottable.MiraculousFishLootTable; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.fishing.BasicFishLootTable; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.fishing.MiraculousFishLootTable; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.lootbox.EpicFishingTreasureLootTable; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.lootbox.FishingFurnitureLootTable; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.lootbox.LegendaryFishingTreasureLootTable; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.lootbox.RareFishingTreasureLootTable; import fr.openmc.core.registry.loottable.contents.MachineBallLootTable; public class CustomLootTableRegistry extends Registry implements KeyedRegistry { @@ -11,6 +16,12 @@ public class CustomLootTableRegistry extends Registry i public final CustomLootTable MACHINE_BALL = register(new MachineBallLootTable()); public final CustomLootTable MIRACULOUS_FISHING = register(new MiraculousFishLootTable()); + public final CustomLootTable BASIC_FISHING = register(new BasicFishLootTable()); + + public final CustomLootTable FISHING_FURNITURE = register(new FishingFurnitureLootTable()); + public final CustomLootTable RARE_FISHING_TREASURE = register(new RareFishingTreasureLootTable()); + public final CustomLootTable EPIC_FISHING_TREASURE = register(new EpicFishingTreasureLootTable()); + public final CustomLootTable LEGENDARY_FISHING_TREASURE = register(new LegendaryFishingTreasureLootTable()); @Override public String key(CustomLootTable registryObject) { diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java index 3f0a66c23..0babdb289 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java @@ -2,6 +2,7 @@ import fr.openmc.core.registry.items.CustomItem; import lombok.Getter; +import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -43,6 +44,22 @@ public ItemLoot(CustomItem item, double chance, int minAmount, int maxAmount) { maxAmount); } + public ItemLoot(Material item, Material displayedItem, double chance, int minAmount, int maxAmount) { + this(ItemStack.of(item), + ItemStack.of(displayedItem), + chance, + minAmount, + maxAmount); + } + + public ItemLoot(ItemStack item, Material displayedItem, double chance, int minAmount, int maxAmount) { + this(item, + ItemStack.of(displayedItem), + chance, + minAmount, + maxAmount); + } + public ItemLoot(ItemStack item, ItemStack displayedItem, double chance, int minAmount, int maxAmount) { this(Collections.singleton(item), displayedItem, @@ -62,6 +79,17 @@ public ItemLoot(CustomItem item, ItemStack displayedItem, double chance, int min maxAmount); } + public ItemLoot(CustomItem item, CustomItem displayedItem, double chance, int minAmount, int maxAmount) { + if (item == null) throw new IllegalArgumentException("CustomItem cannot be null"); + if (displayedItem == null) throw new IllegalArgumentException("CustomItem cannot be null"); + + this(Collections.singleton(item.getBest()), + displayedItem.getBest(), + chance, + minAmount, + maxAmount); + } + public ItemStack getFirstLoot() { if (items.size() == 1) { return items.iterator().next(); diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java new file mode 100644 index 000000000..06d866d79 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java @@ -0,0 +1,21 @@ +package fr.openmc.core.registry.loottable.loots; + +import fr.openmc.core.registry.lootboxes.CustomLootbox; +import lombok.Getter; +import org.bukkit.entity.Player; + +@Getter +public class LootboxLoot implements CustomLoot { + private final double chance; + private final CustomLootbox lootbox; + + public LootboxLoot(CustomLootbox lootbox, double chance) { + this.chance = chance; + this.lootbox = lootbox; + } + + @Override + public void run(Player receiver) { + lootbox.open(receiver); + } +} \ No newline at end of file diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties index b1b8ae9dd..7a686c362 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -65,3 +65,9 @@ feature.dailyevents.goldenharvest.broadcast.end=
*stocker, vendez vos ressources que vous avec pu farmer*\
\
+ +# ** Pêche miraculeuse ** +feature.dailyevents.miraculousfishing.lootbox.fishing_furniture.name=Boîte d'équipement de pêche +feature.dailyevents.miraculousfishing.lootbox.rare_fishing_treasure.name=Trésor de pêche rare +feature.dailyevents.miraculousfishing.lootbox.epic_fishing_treasure.name=Trésor de pêche épique +feature.dailyevents.miraculousfishing.lootbox.legendary_fishing_treasure.name=Trésor de pêche légendaire \ No newline at end of file From 3563456e8ce59601ec80c6e91453ae149815f1cf Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 18 Jun 2026 13:48:08 +0200 Subject: [PATCH 47/74] add base of PlayerFishListener --- .../dailyevents/DailyEventsManager.java | 20 ++++- .../MiraculousFishingEvent.java | 15 +++- .../MiraculousFishingManager.java | 77 +++++++++++++++++++ .../listeners/PlayerFishListener.java | 57 ++++++++++++++ .../listeners/PlayerNotPickUpListener.java | 18 +++++ .../registry/lootboxes/CustomLootbox.java | 19 +++++ .../registry/loottable/CustomLootTable.java | 12 ++- 7 files changed, 212 insertions(+), 6 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerNotPickUpListener.java diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java index 67274090b..dd3ea2898 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java @@ -28,6 +28,7 @@ import java.sql.SQLException; import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -74,9 +75,16 @@ public void initDB(ConnectionSource connectionSource) throws SQLException { @Override public Set getListeners() { - return Set.of( + Set listeners = new HashSet<>(Set.of( new DailyEventAmbientListeners() - ); + )); + + for (DailyEvent event : EVENTS) { + if (!(event instanceof HasListeners hasListeners)) continue; + listeners.addAll(hasListeners.getListeners()); + } + + return listeners; } /** @@ -184,4 +192,12 @@ public static BukkitTask scheduleNextEventTask() { public static boolean isActiveDailyEvent() { return outgoingEvent != null; } + + /** + * Méthode plus claire afin de dire renvoyer l'evenement journalier actif + * @return un daily event + */ + public static DailyEvent getActiveDailyEvent() { + return outgoingEvent.getDailyEvent(); + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java index 6b2b89a43..f8cd96fbd 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java @@ -1,6 +1,9 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing; import fr.openmc.core.OMCRegistry; +import fr.openmc.core.bootstrap.features.types.HasListeners; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.listeners.PlayerFishListener; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.listeners.PlayerNotPickUpListener; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasAmbient; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasBroadcast; @@ -11,11 +14,13 @@ import net.kyori.adventure.text.Component; import net.minecraft.advancements.AdvancementType; import org.bukkit.Material; +import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; import java.util.List; +import java.util.Set; -public class MiraculousFishingEvent extends DailyEvent implements HasToast, HasAmbient, HasBroadcast { +public class MiraculousFishingEvent extends DailyEvent implements HasToast, HasAmbient, HasBroadcast, HasListeners { @Override public String getEventId() { return "miraculous_fishing"; @@ -92,4 +97,12 @@ public Component getStartBroadcast() { public Component getEndBroadcast() { return TranslationManager.translation("feature.dailyevents.miraculousfishing.broadcast.end"); } + + @Override + public Set getListeners() { + return Set.of( + new PlayerFishListener(), + new PlayerNotPickUpListener() + ); + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java new file mode 100644 index 000000000..7886e1ee1 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java @@ -0,0 +1,77 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing; + +import fr.openmc.core.OMCPlugin; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; +import fr.openmc.core.registry.loottable.loots.LootboxLoot; +import fr.openmc.core.registry.loottable.loots.MoneyLoot; +import fr.openmc.core.utils.bukkit.SkullUtils; +import org.bukkit.Location; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.FishHook; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.persistence.PersistentDataType; +import org.bukkit.util.Vector; + +public class MiraculousFishingManager { + + public static final NamespacedKey NOT_PICKUP_KEY = new NamespacedKey(OMCPlugin.getInstance(), "not_pickup"); + public static final double FISHING_SPEED_MODIFIER = 0.4; + + /** + * Applique un modificateur de vitesse de pêche à un FishHook. + * @param hook le hook qui aura son temps réduit + */ + public static void applyFishingSpeedModifier(FishHook hook) { + hook.setWaitTime((int) (hook.getMinWaitTime() * FISHING_SPEED_MODIFIER), + (int) (hook.getMaxWaitTime() * FISHING_SPEED_MODIFIER)); + } + + /** + * Simule un item qui est lancé du bouchon de pêche jusqu'au joueur, via un CustomLoot. + * @param player le joueur visé + * @param hookLocation la position du bouchon, position de spawn de l'item + * @param loot le CustomLoot qui sera utilisé pour déterminer l'item à lancer + */ + public static void simulateLaunchLoot(Player player, Location hookLocation, CustomLoot loot) { + ItemStack displayItem = getLaunchedItem(loot); + + if (displayItem == null) return; + + // * Spawn de l'entité Item + Item itemEntity = hookLocation.getWorld().dropItem(hookLocation, displayItem); + itemEntity.setPickupDelay(Integer.MAX_VALUE); + itemEntity.setGlowing(true); + + // * Revient à faire le vecteur vitesse entre 2 vecteur (xp - xh, yp - yh, zp - zh) + Vector velocity = player.getEyeLocation().toVector().subtract(hookLocation.toVector()); + velocity.multiply(0.1); + itemEntity.setVelocity(velocity); + } + + /** + * L'item décidé en fonction du CustomLoot + * @param loot le custom loot + * @return un item stack en fonction du loot + */ + private static ItemStack getLaunchedItem(CustomLoot loot) { + if (loot instanceof ItemLoot itemLoot) { + return itemLoot.getItems().iterator().next(); + } else if (loot instanceof MoneyLoot) { + ItemStack base = SkullUtils.getCustomHead( + "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWFmMGQ4ZDc5NGEzYTRhNWUyMGE1MjkyZWQyNTUxMzRmNzZkNGYzYTU1NTZmYzdmNDI2ZDI3YjI0NzQ3NGQ2NyJ9fX0=", + "§6§lAywenito"); + if (base != null) + base.editPersistentDataContainer(c -> + c.set(NOT_PICKUP_KEY, PersistentDataType.BOOLEAN, true)); + return base; + } else if (loot instanceof LootboxLoot lootboxLoot + && lootboxLoot.getLootbox().getItemDisplayed() != null) { + return lootboxLoot.getLootbox().getItemDisplayed(); + } + + return null; + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java new file mode 100644 index 000000000..e9c757215 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java @@ -0,0 +1,57 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.listeners; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.MiraculousFishingEvent; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.MiraculousFishingManager; +import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import org.bukkit.Sound; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FishHook; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerFishEvent; + +import java.util.List; + +public class PlayerFishListener implements Listener { + + @EventHandler + public void onStartFishing(PlayerFishEvent event) { + if (!DailyEventsManager.isActiveDailyEvent() + || !(DailyEventsManager.getActiveDailyEvent() instanceof MiraculousFishingEvent)) return; + + Player player = event.getPlayer(); + FishHook hook = event.getHook(); + + MiraculousFishingManager.applyFishingSpeedModifier(hook); + + switch (event.getState()) { + case FISHING -> { + // * SFX + // todo sfx + player.playSound(player.getLocation(), Sound.ENTITY_FISHING_BOBBER_SPLASH, 1f, 0.3f); + } + + case CAUGHT_FISH -> { + Entity caughtEntity = event.getCaught(); + if (caughtEntity instanceof Item caughtItem) { + caughtItem.remove(); + } + + CustomLootTable fishingLootTable = OMCRegistry.CUSTOM_LOOT_TABLES.MIRACULOUS_FISHING; + + List loots = fishingLootTable.rollLoots(player, false); + + // * SFX + // todo: sfx particle + for (CustomLoot loot : loots) { + MiraculousFishingManager.simulateLaunchLoot(player, hook.getLocation(), loot); + } + } + } + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerNotPickUpListener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerNotPickUpListener.java new file mode 100644 index 000000000..e026f2c16 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerNotPickUpListener.java @@ -0,0 +1,18 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.listeners; + +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.MiraculousFishingManager; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityPickupItemEvent; + +public class PlayerNotPickUpListener implements Listener { + @EventHandler + public void onPickUp(EntityPickupItemEvent event) { + if (!(event.getEntity() instanceof Player)) return; + if (event.getItem().getItemStack().getPersistentDataContainer().has(MiraculousFishingManager.NOT_PICKUP_KEY)) { + event.getItem().remove(); + } + + } +} diff --git a/src/main/java/fr/openmc/core/registry/lootboxes/CustomLootbox.java b/src/main/java/fr/openmc/core/registry/lootboxes/CustomLootbox.java index 8e5cd420c..1fae53a2c 100644 --- a/src/main/java/fr/openmc/core/registry/lootboxes/CustomLootbox.java +++ b/src/main/java/fr/openmc/core/registry/lootboxes/CustomLootbox.java @@ -5,11 +5,13 @@ import lombok.Getter; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import java.util.stream.IntStream; @Getter public abstract class CustomLootbox { + private final ItemStack itemDisplayed; private final String namespace; private final Component name; private final CustomLootTable lootTable; @@ -20,13 +22,30 @@ public abstract class CustomLootbox { 22 ); + public CustomLootbox(ItemStack itemDisplayed, String namespace, Component name, CustomLootTable lootTable) { + this.itemDisplayed = itemDisplayed; + this.namespace = namespace; + this.name = name; + this.lootTable = lootTable; + } + public CustomLootbox(String namespace, Component name, CustomLootTable lootTable) { + this.itemDisplayed = null; this.namespace = namespace; this.name = name; this.lootTable = lootTable; } + public CustomLootbox(ItemStack itemDisplayed, String namespace, Component name, CustomLootTable lootTable, LootboxOptions options) { + this.itemDisplayed = itemDisplayed; + this.namespace = namespace; + this.name = name; + this.lootTable = lootTable; + this.options = options; + } + public CustomLootbox(String namespace, Component name, CustomLootTable lootTable, LootboxOptions options) { + this.itemDisplayed = null; this.namespace = namespace; this.name = name; this.lootTable = lootTable; diff --git a/src/main/java/fr/openmc/core/registry/loottable/CustomLootTable.java b/src/main/java/fr/openmc/core/registry/loottable/CustomLootTable.java index a004d0bde..7af559cbd 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/CustomLootTable.java +++ b/src/main/java/fr/openmc/core/registry/loottable/CustomLootTable.java @@ -26,7 +26,7 @@ public double getChanceOf(ItemStack item) { .sum(); } - public List rollLoots(Player receiver) { + public List rollLoots(Player receiver, boolean giveLoots) { List result = new ArrayList<>(); double totalChance = this.getLoots().stream() @@ -39,7 +39,8 @@ public List rollLoots(Player receiver) { for (CustomLoot loot : this.getLoots()) { sumChance += loot.getChance(); if (roll <= sumChance) { - loot.run(receiver); + if (giveLoots) + loot.run(receiver); result.add(loot); break; } @@ -47,13 +48,18 @@ public List rollLoots(Player receiver) { if (result.isEmpty()) { CustomLoot next = this.getLoots().iterator().next(); - next.run(receiver); + if (giveLoots) + next.run(receiver); result.add(next); } return result; } + public List rollLoots(Player receiver) { + return rollLoots(receiver, true); + } + public List rollLootsWithAmount(Player receiver, int amountRoll) { List loot = new ArrayList<>(); From e9a4ee9540be427f1d2a67d41ba9222d7e54a7bb Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 18 Jun 2026 14:31:34 +0200 Subject: [PATCH 48/74] add command to forceStart of daily event --- .../dailyevents/DailyEventsManager.java | 33 ++++++++-- .../commands/DailyEventCommand.java | 32 ++++++++++ .../autocomplete/DailyEventAutoComplete.java | 20 ++++++ .../models/dailyevent/DailyEvent.java | 61 +++++++++++++++++++ .../dailyevents/tasks/EndEventTask.java | 40 +----------- .../dailyevents/tasks/NextEventTask.java | 38 +----------- 6 files changed, 145 insertions(+), 79 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/DailyEventCommand.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/autocomplete/DailyEventAutoComplete.java diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java index dd3ea2898..922a54220 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java @@ -8,9 +8,11 @@ import fr.openmc.core.bootstrap.features.Feature; import fr.openmc.core.bootstrap.features.annotations.Credit; import fr.openmc.core.bootstrap.features.types.DatabaseFeature; +import fr.openmc.core.bootstrap.features.types.HasCommands; import fr.openmc.core.bootstrap.features.types.HasListeners; import fr.openmc.core.bootstrap.features.types.LoadAfterItemsAdder; import fr.openmc.core.bootstrap.integration.OMCLogger; +import fr.openmc.core.features.events.contents.dailyevents.commands.DailyEventCommand; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.BloodyNightEvent; import fr.openmc.core.features.events.contents.dailyevents.contents.goldenharvest.GoldenHarvestEvent; import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.MiraculousFishingEvent; @@ -35,10 +37,10 @@ //todo: tester les toasts lorsqu'ils refonctionneront (before, start, end) @Credit(developers = {"iambibi_"}) -public class DailyEventsManager extends Feature implements LoadAfterItemsAdder, DatabaseFeature, HasListeners { +public class DailyEventsManager extends Feature implements LoadAfterItemsAdder, DatabaseFeature, HasListeners, HasCommands { // * Constantes public static final List EVENTS = List.of( - new MiraculousFishingEvent(), + new MiraculousFishingEvent(), new GoldenHarvestEvent(), new BloodyNightEvent() ); @@ -51,6 +53,7 @@ public class DailyEventsManager extends Feature implements LoadAfterItemsAdder, // * Données à propos de la gestion des daily event public static ScheduleDailyEvent outgoingEvent = null; + public static BukkitTask endEventTask = null; public static BukkitTask nextEventTask; public static List incomingEvents = new ArrayList<>(); @@ -87,8 +90,16 @@ public Set getListeners() { return listeners; } + @Override + public Set getCommands() { + return Set.of( + new DailyEventCommand() + ); + } + /** * Charge les données de la DB, généralement pdt le démarrage + * * @return les données des daily event (ordre actuel) */ public static IncomingEventsDB loadIncomingEventsDB() { @@ -106,6 +117,7 @@ public static IncomingEventsDB loadIncomingEventsDB() { /** * Sauvegarde les données des Daily Event dans la DB, généralement pdt l'arrêt du serveur + * * @param data les données des daily events */ public static void saveIncomingEventsDB(IncomingEventsDB data) { @@ -119,6 +131,7 @@ public static void saveIncomingEventsDB(IncomingEventsDB data) { /** * On charge les evenements à venir * Lors du premier chargement, on remplit directement notre liste de taille identique à nos slots horaires. + * * @return la liste prévue des x prochains évenements */ public static List loadIncomingEvents() { @@ -136,9 +149,9 @@ public static List loadIncomingEvents() { LocalDateTime scheduledDailyEvent; if (hourSlot > now.getHour()) { - scheduledDailyEvent=now.withHour(hourSlot).withMinute(0).withSecond(0).withNano(0); + scheduledDailyEvent = now.withHour(hourSlot).withMinute(0).withSecond(0).withNano(0); } else { - scheduledDailyEvent=now.plusDays(1) + scheduledDailyEvent = now.plusDays(1) .withHour(hourSlot).withMinute(0).withSecond(0).withNano(0); } scheduledEvents.add(new ScheduleDailyEvent(copyEvents.removeFirst(), scheduledDailyEvent)); @@ -152,6 +165,7 @@ public static List loadIncomingEvents() { * - On cherche la prochaine heure, en faisant gaffe si l'heure est passée, dans ce cas on schedule pour demain * - Apres la prochaine heure on lance les taches associés à l'événement (tache pour avant le commencement, * et pour le lancement de l'événement et la planification du prochain + * * @return la tache de lancement de l'événement, qui sera executé à l'heure exacte du début de l'événement */ public static BukkitTask scheduleNextEventTask() { @@ -174,7 +188,7 @@ public static BukkitTask scheduleNextEventTask() { long delayTicks = DateUtils.getDelayBetweenNow(scheduleTime) * 20; OMCLogger.infoFormatted("Les prochains evenement : " + incomingEvents.stream() - .map(s->s.getDailyEvent().getClass().getSimpleName()).toList()); + .map(s -> s.getDailyEvent().getClass().getSimpleName()).toList()); OMCLogger.infoFormatted("Prochain Evenement journalier : " + scheduleTime + "s (dans " + DateUtils.convertSecondToTime(DateUtils.getDelayBetweenNow(scheduleTime)) + ")"); // * Programation de la tâche qui s'executera peu avant le commencement @@ -187,6 +201,7 @@ public static BukkitTask scheduleNextEventTask() { /** * Méthode plus claire afin de dire s'il y a un evenement journalier actif ou non + * * @return un boolean */ public static boolean isActiveDailyEvent() { @@ -195,9 +210,17 @@ public static boolean isActiveDailyEvent() { /** * Méthode plus claire afin de dire renvoyer l'evenement journalier actif + * * @return un daily event */ public static DailyEvent getActiveDailyEvent() { return outgoingEvent.getDailyEvent(); } + + public static DailyEvent getDailyEvent(String id) { + return EVENTS.stream() + .filter(event -> event.getEventId().equals(id)) + .findFirst() + .orElse(null); + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/DailyEventCommand.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/DailyEventCommand.java new file mode 100644 index 000000000..e7f0a4bee --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/DailyEventCommand.java @@ -0,0 +1,32 @@ +package fr.openmc.core.features.events.contents.dailyevents.commands; + +import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; +import fr.openmc.core.features.events.contents.dailyevents.commands.autocomplete.DailyEventAutoComplete; +import fr.openmc.core.features.events.contents.dailyevents.models.ScheduleDailyEvent; +import fr.openmc.core.utils.text.DateUtils; +import org.bukkit.entity.Player; +import revxrsal.commands.annotation.Command; +import revxrsal.commands.annotation.Description; +import revxrsal.commands.annotation.Subcommand; +import revxrsal.commands.annotation.SuggestWith; +import revxrsal.commands.bukkit.annotation.CommandPermission; + +@Command({"events", "dailyevents"}) +@Description("Ouvre l'interface des événements") +public class DailyEventCommand { + @Subcommand("forceStart") + @CommandPermission("omc.admins.commands.dailyevent.forcestart") + public static void forceStartCommand(Player player, + @SuggestWith(DailyEventAutoComplete.class) String dailyEvent) { + if (DailyEventsManager.outgoingEvent != null) { + // * On arrete l'evenement en cours + DailyEventsManager.endEventTask.cancel(); + DailyEventsManager.outgoingEvent.getDailyEvent().end(); + } + + // * on lance le evenement rentré en param + DailyEventsManager.outgoingEvent = new ScheduleDailyEvent( + DailyEventsManager.getDailyEvent(dailyEvent), DateUtils.getLocalDateTime()); + DailyEventsManager.outgoingEvent.getDailyEvent().start(); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/autocomplete/DailyEventAutoComplete.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/autocomplete/DailyEventAutoComplete.java new file mode 100644 index 000000000..ce9776b55 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/autocomplete/DailyEventAutoComplete.java @@ -0,0 +1,20 @@ +package fr.openmc.core.features.events.contents.dailyevents.commands.autocomplete; + +import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; +import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; +import org.jetbrains.annotations.NotNull; +import revxrsal.commands.autocomplete.SuggestionProvider; +import revxrsal.commands.bukkit.actor.BukkitCommandActor; +import revxrsal.commands.node.ExecutionContext; + +import java.util.List; + +public class DailyEventAutoComplete implements SuggestionProvider { + + @Override + public @NotNull List getSuggestions(@NotNull ExecutionContext context) { + return DailyEventsManager.EVENTS.stream() + .map(DailyEvent::getEventId) + .toList(); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/DailyEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/DailyEvent.java index b4a11a19e..791be57b3 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/DailyEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/DailyEvent.java @@ -1,6 +1,14 @@ package fr.openmc.core.features.events.contents.dailyevents.models.dailyevent; +import fr.openmc.core.OMCPlugin; +import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; +import fr.openmc.core.features.events.contents.dailyevents.tasks.EndEventTask; import fr.openmc.core.features.events.models.Event; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.Collection; +import java.util.stream.Collectors; public abstract class DailyEvent extends Event { /** @@ -26,9 +34,62 @@ public abstract class DailyEvent extends Event { * @return une méthode */ public abstract Runnable onStart(); + /** * Les procédures à lancer à la fin de l'évenement * @return une méthode */ public abstract Runnable onEnd(); + + public void start() { + Collection receivers = Bukkit.getOnlinePlayers() + .stream() + .filter(p -> p.getWorld().getName().equals(this.getWorldEvent())) + .collect(Collectors.toSet()); + + // * Application de l'ambience + if (this instanceof HasAmbient ambient) { + ambient.apply(receivers); + } + + // * Message de début + if (this instanceof HasBroadcast broadcast) { + broadcast.sendStartBroadcast(receivers); + } + + // * Toast de début + if (this instanceof HasToast toast) { + toast.getStartToastData().send(receivers); + } + + // * Programmation de la fin de l'evenement + DailyEventsManager.endEventTask = new EndEventTask() + .runTaskLater(OMCPlugin.getInstance(), + DailyEventsManager.outgoingEvent.getDailyEvent().getDuration() * 60L * 20L); + } + + public void end() { + Collection receivers = Bukkit.getOnlinePlayers() + .stream() + .filter(p -> p.getWorld().getName().equals(this.getWorldEvent())) + .collect(Collectors.toSet()); + + DailyEventsManager.outgoingEvent = null; + DailyEventsManager.endEventTask = null; + + // * Suppression de la l'ambience + if (this instanceof HasAmbient ambient) { + ambient.reset(receivers); + } + + // * Message de fin + if (this instanceof HasBroadcast broadcast) { + broadcast.sendEndBroadcast(receivers); + } + + // * Toast de fin + if (this instanceof HasToast toast) { + toast.getEndToastData().send(receivers); + } + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/EndEventTask.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/EndEventTask.java index 325ac7943..6e63cb654 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/EndEventTask.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/EndEventTask.java @@ -1,49 +1,11 @@ package fr.openmc.core.features.events.contents.dailyevents.tasks; import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; -import fr.openmc.core.features.events.contents.dailyevents.models.ScheduleDailyEvent; -import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; -import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasAmbient; -import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasBroadcast; -import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; -import java.util.Collection; -import java.util.stream.Collectors; - public class EndEventTask extends BukkitRunnable { - private final DailyEvent outgoingEvent; - - public EndEventTask(ScheduleDailyEvent outgoing) { - this.outgoingEvent = outgoing.getDailyEvent(); - } - @Override public void run() { - DailyEventsManager.outgoingEvent.getDailyEvent().onEnd().run(); - - Collection receivers = Bukkit.getOnlinePlayers() - .stream() - .filter(p -> p.getWorld().getName().equals(outgoingEvent.getWorldEvent())) - .collect(Collectors.toSet()); - - DailyEventsManager.outgoingEvent = null; - - // * Suppression de la l'ambience - if (outgoingEvent instanceof HasAmbient ambient) { - ambient.reset(receivers); - } - - // * Message de fin - if (outgoingEvent instanceof HasBroadcast broadcast) { - broadcast.sendEndBroadcast(receivers); - } - - // * Toast de fin - if (outgoingEvent instanceof HasToast toast) { - toast.getEndToastData().send(receivers); - } + DailyEventsManager.outgoingEvent.getDailyEvent().end(); } } \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/NextEventTask.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/NextEventTask.java index 0890e847b..d4bd3f396 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/NextEventTask.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/tasks/NextEventTask.java @@ -2,52 +2,20 @@ import fr.openmc.core.OMCPlugin; import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; -import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; -import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasAmbient; -import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasBroadcast; -import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; import org.bukkit.Bukkit; -import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; -import java.util.Collection; -import java.util.stream.Collectors; - public class NextEventTask extends BukkitRunnable { @Override public void run() { - // * Commencement de l'evenement + // * Choix de l'evenement à lancer if (DailyEventsManager.incomingEvents.isEmpty()) { DailyEventsManager.incomingEvents = DailyEventsManager.loadIncomingEvents(); } DailyEventsManager.outgoingEvent = DailyEventsManager.incomingEvents.removeFirst(); - DailyEventsManager.outgoingEvent.getDailyEvent().onStart().run(); - DailyEvent outgoingDailyEvent = DailyEventsManager.outgoingEvent.getDailyEvent(); - - Collection receivers = Bukkit.getOnlinePlayers() - .stream() - .filter(p -> p.getWorld().getName().equals(outgoingDailyEvent.getWorldEvent())) - .collect(Collectors.toSet()); - - // * Application de l'ambience - if (outgoingDailyEvent instanceof HasAmbient ambient) { - ambient.apply(receivers); - } - - // * Message de début - if (outgoingDailyEvent instanceof HasBroadcast broadcast) { - broadcast.sendStartBroadcast(receivers); - } - - // * Toast de début - if (outgoingDailyEvent instanceof HasToast toast) { - toast.getStartToastData().send(receivers); - } - // * Programmation de la fin de l'evenement - new EndEventTask(DailyEventsManager.outgoingEvent) - .runTaskLater(OMCPlugin.getInstance(), - DailyEventsManager.outgoingEvent.getDailyEvent().getDuration() * 60L * 20L); + // * Lancement de l'evenement + DailyEventsManager.outgoingEvent.getDailyEvent().start(); // * 10 secondes d'attente avant de schedule un autre event (evite que plusieurs events se lancent en meme temps) Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> From dbf15467d39beacb3f0abe170c1baf7bd879b9e2 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 18 Jun 2026 14:34:42 +0200 Subject: [PATCH 49/74] fix DailyEventCommand --- .../events/contents/dailyevents/commands/DailyEventCommand.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/DailyEventCommand.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/DailyEventCommand.java index e7f0a4bee..655fa44b3 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/DailyEventCommand.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/DailyEventCommand.java @@ -21,6 +21,7 @@ public static void forceStartCommand(Player player, if (DailyEventsManager.outgoingEvent != null) { // * On arrete l'evenement en cours DailyEventsManager.endEventTask.cancel(); + DailyEventsManager.endEventTask = null; DailyEventsManager.outgoingEvent.getDailyEvent().end(); } From 5670401d75b16c5e718533ccb272198fa8302c07 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 18 Jun 2026 17:28:53 +0200 Subject: [PATCH 50/74] branch; change --- .../MiraculousFishingEvent.java | 1 + .../MiraculousFishingManager.java | 17 +++++++++------ .../listeners/PlayerFishListener.java | 21 +++++++++++++++++++ .../registry/loottable/loots/CustomLoot.java | 2 ++ .../registry/loottable/loots/ItemLoot.java | 7 +++++++ .../registry/loottable/loots/LootboxLoot.java | 6 ++++++ .../registry/loottable/loots/MethodLoot.java | 10 ++++++++- .../registry/loottable/loots/MoneyLoot.java | 13 ++++++++++-- .../registry/loottable/loots/TableLoot.java | 6 ++++++ .../core/utils/text/messages/Prefix.java | 3 ++- .../default/dailyevents.properties | 6 ++++-- 11 files changed, 80 insertions(+), 12 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java index f8cd96fbd..713c7d96d 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java @@ -88,6 +88,7 @@ public CustomAmbient getAmbient() { return OMCRegistry.CUSTOM_AMBIENTS.BLESSED; } + //todo marquer effets de la peche miraculeuse ds broadcast @Override public Component getStartBroadcast() { return TranslationManager.translation("feature.dailyevents.miraculousfishing.broadcast.start"); diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java index 7886e1ee1..b212e3116 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java @@ -1,10 +1,7 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing; import fr.openmc.core.OMCPlugin; -import fr.openmc.core.registry.loottable.loots.CustomLoot; -import fr.openmc.core.registry.loottable.loots.ItemLoot; -import fr.openmc.core.registry.loottable.loots.LootboxLoot; -import fr.openmc.core.registry.loottable.loots.MoneyLoot; +import fr.openmc.core.registry.loottable.loots.*; import fr.openmc.core.utils.bukkit.SkullUtils; import org.bukkit.Location; import org.bukkit.NamespacedKey; @@ -15,6 +12,8 @@ import org.bukkit.persistence.PersistentDataType; import org.bukkit.util.Vector; +import java.util.List; + public class MiraculousFishingManager { public static final NamespacedKey NOT_PICKUP_KEY = new NamespacedKey(OMCPlugin.getInstance(), "not_pickup"); @@ -42,7 +41,8 @@ public static void simulateLaunchLoot(Player player, Location hookLocation, Cust // * Spawn de l'entité Item Item itemEntity = hookLocation.getWorld().dropItem(hookLocation, displayItem); - itemEntity.setPickupDelay(Integer.MAX_VALUE); + itemEntity.setCanPlayerPickup(true); + itemEntity.setCanMobPickup(true); itemEntity.setGlowing(true); // * Revient à faire le vecteur vitesse entre 2 vecteur (xp - xh, yp - yh, zp - zh) @@ -58,7 +58,9 @@ public static void simulateLaunchLoot(Player player, Location hookLocation, Cust */ private static ItemStack getLaunchedItem(CustomLoot loot) { if (loot instanceof ItemLoot itemLoot) { - return itemLoot.getItems().iterator().next(); + ItemStack item = itemLoot.getItems().iterator().next(); + item.setAmount(itemLoot.getRandomAmount()); + return item; } else if (loot instanceof MoneyLoot) { ItemStack base = SkullUtils.getCustomHead( "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWFmMGQ4ZDc5NGEzYTRhNWUyMGE1MjkyZWQyNTUxMzRmNzZkNGYzYTU1NTZmYzdmNDI2ZDI3YjI0NzQ3NGQ2NyJ9fX0=", @@ -70,6 +72,9 @@ private static ItemStack getLaunchedItem(CustomLoot loot) { } else if (loot instanceof LootboxLoot lootboxLoot && lootboxLoot.getLootbox().getItemDisplayed() != null) { return lootboxLoot.getLootbox().getItemDisplayed(); + } else if (loot instanceof TableLoot tableLoot) { + List loots = tableLoot.getLootTable().rollLoots(null, false); + return getLaunchedItem(loots.getFirst()); } return null; diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java index e9c757215..05f17a8bd 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java @@ -6,6 +6,15 @@ import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.MiraculousFishingManager; import fr.openmc.core.registry.loottable.CustomLootTable; import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.MethodLoot; +import fr.openmc.core.registry.loottable.loots.MoneyLoot; +import fr.openmc.core.registry.loottable.loots.TableLoot; +import fr.openmc.core.utils.text.messages.MessageType; +import fr.openmc.core.utils.text.messages.MessagesManager; +import fr.openmc.core.utils.text.messages.Prefix; +import fr.openmc.core.utils.text.messages.TranslationManager; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Sound; import org.bukkit.entity.Entity; import org.bukkit.entity.FishHook; @@ -48,8 +57,20 @@ public void onStartFishing(PlayerFishEvent event) { // * SFX // todo: sfx particle + MessagesManager.sendMessage(player, TranslationManager.translation( + "feature.dailyevents.miraculousfishing.loottable.get", + Component.text(loots.size()).color(NamedTextColor.YELLOW) + ), Prefix.MIRACULOUS_FISHING, MessageType.INFO, false); + for (CustomLoot loot : loots) { + if (loot.getDisplayText() != null) + player.sendMessage(Component.text(" - ", NamedTextColor.GRAY) + .append(loot.getDisplayText())); MiraculousFishingManager.simulateLaunchLoot(player, hook.getLocation(), loot); + + if (loot instanceof MoneyLoot || loot instanceof MethodLoot || loot instanceof TableLoot) { + loot.run(player); + } } } } diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java index 065734709..d0a8b07c2 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java @@ -1,8 +1,10 @@ package fr.openmc.core.registry.loottable.loots; +import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; public interface CustomLoot { + Component getDisplayText(); double getChance(); void run(Player receiver); } \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java index 0babdb289..aff111a85 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java @@ -2,6 +2,7 @@ import fr.openmc.core.registry.items.CustomItem; import lombok.Getter; +import net.kyori.adventure.text.Component; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -101,6 +102,12 @@ public int getRandomAmount() { return minAmount + (int) (Math.random() * (maxAmount - minAmount + 1)); } + @Override + public Component getDisplayText() { + System.out.println(getFirstLoot()); + return getFirstLoot().displayName(); + } + @Override public void run(Player receiver) { for (ItemStack lootItem : this.getItems()) { diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java index 06d866d79..8189edaa6 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java @@ -2,6 +2,7 @@ import fr.openmc.core.registry.lootboxes.CustomLootbox; import lombok.Getter; +import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; @Getter @@ -14,6 +15,11 @@ public LootboxLoot(CustomLootbox lootbox, double chance) { this.lootbox = lootbox; } + @Override + public Component getDisplayText() { + return lootbox.getName(); + } + @Override public void run(Player receiver) { lootbox.open(receiver); diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java index 24b153c6f..93f1e6efd 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java @@ -1,20 +1,28 @@ package fr.openmc.core.registry.loottable.loots; import lombok.Getter; +import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; import java.util.function.Consumer; @Getter public class MethodLoot implements CustomLoot { + private final Component text; private final double chance; private final Consumer receiverAction; - public MethodLoot(Consumer receiverAction, double chance) { + public MethodLoot(Component text, Consumer receiverAction, double chance) { + this.text = text; this.chance = chance; this.receiverAction = receiverAction; } + @Override + public Component getDisplayText() { + return text; + } + @Override public void run(Player receiver) { receiverAction.accept(receiver); diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java index ec96bbe04..4f15df698 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java @@ -2,14 +2,23 @@ import fr.openmc.core.features.economy.EconomyManager; import fr.openmc.core.utils.RandomUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; -public record MoneyLoot(double money, double getChance) implements CustomLoot { - public MoneyLoot(double minMoney, double maxMoney, double chance) { +public record MoneyLoot(int money, double getChance) implements CustomLoot { + public MoneyLoot(int minMoney, int maxMoney, double chance) { this(RandomUtils.randomBetween(minMoney, maxMoney), chance); } + @Override + public Component getDisplayText() { + return Component.text(money, NamedTextColor.GOLD) + .appendSpace() + .append(Component.text(EconomyManager.getEconomyIcon())); + } + @Override public void run(Player receiver) { EconomyManager.addBalance(receiver.getUniqueId(), money); diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java index 4a1c91be3..7bb2ad4e4 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java @@ -2,6 +2,7 @@ import fr.openmc.core.registry.loottable.CustomLootTable; import lombok.Getter; +import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; @Getter @@ -14,6 +15,11 @@ public TableLoot(CustomLootTable lootTable, double chance) { this.lootTable = lootTable; } + @Override + public Component getDisplayText() { + return null; + } + @Override public void run(Player receiver) { lootTable.rollLoots(receiver); diff --git a/src/main/java/fr/openmc/core/utils/text/messages/Prefix.java b/src/main/java/fr/openmc/core/utils/text/messages/Prefix.java index 9e2e50c2c..e60be5e98 100644 --- a/src/main/java/fr/openmc/core/utils/text/messages/Prefix.java +++ b/src/main/java/fr/openmc/core/utils/text/messages/Prefix.java @@ -31,7 +31,8 @@ public enum Prefix { MILLESTONE("ᴍɪʟʟᴇѕᴛᴏɴᴇ"), DREAM("ᴅʀᴇᴀᴍ"), MAILBOX("ᴍᴀɪʟʙᴏx"), - HALLOWEEN("ʜᴀʟʟᴏᴡᴇᴇɴ") + HALLOWEEN("ʜᴀʟʟᴏᴡᴇᴇɴ"), + MIRACULOUS_FISHING("ᴘᴇᴄʜᴇ ᴍɪʀᴀᴄᴜʟᴇᴜѕᴇ") ; @Getter diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties index 7a686c362..ca8e7e39a 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -23,7 +23,7 @@ feature.dailyevents.miraculousfishing.toast.start=La La Pêche miraculeuse est partie feature.dailyevents.toast.beginning_event_in_world=Un évenement va commencer dans votre monde dans %1$ss ! -feature.dailyevents.toast.beginning_event_out_world=Un évenement va commencer dans dans %1$ss ! +feature.dailyevents.toast.beginning_event_out_world=Un évenement va commencer dans %1$ss ! feature.dailyevents.broadcast.soon=*un évènement commence à se rapprocher de notre monde...* @@ -70,4 +70,6 @@ feature.dailyevents.goldenharvest.broadcast.end= feature.dailyevents.miraculousfishing.lootbox.fishing_furniture.name=Boîte d'équipement de pêche feature.dailyevents.miraculousfishing.lootbox.rare_fishing_treasure.name=Trésor de pêche rare feature.dailyevents.miraculousfishing.lootbox.epic_fishing_treasure.name=Trésor de pêche épique -feature.dailyevents.miraculousfishing.lootbox.legendary_fishing_treasure.name=Trésor de pêche légendaire \ No newline at end of file +feature.dailyevents.miraculousfishing.lootbox.legendary_fishing_treasure.name=Trésor de pêche légendaire + +feature.dailyevents.miraculousfishing.loottable.get=Vous avez pêché %1$s objets ! \ No newline at end of file From c43ff674d091e2fdd5432614dfecc42cc4956acf Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Fri, 19 Jun 2026 12:17:29 +0200 Subject: [PATCH 51/74] feat: add items for miraculous fishing --- .../fishing/MiraculousFishLootTable.java | 7 +- .../lootbox/EpicFishingTreasureLootTable.java | 16 +- .../lootbox/FishingFurnitureLootTable.java | 122 +- .../LegendaryFishingTreasureLootTable.java | 5 +- .../lootbox/RareFishingTreasureLootTable.java | 1 - .../registry/items/CustomItemRegistry.java | 33 + .../contents/omc_daily_events/armor.yml | 71 + .../contents/omc_daily_events/category.yml | 2 +- .../omc_daily_events/fishing_furniture.yml | 520 ++++++ .../contents/omc_daily_events/items.yml | 36 + .../contents/omc_daily_events/lootbox.yml | 82 + .../fisherman_props/fisherman_blue_fish.json | 333 ++++ .../fisherman_props/fisherman_boat.json | 1 + .../fisherman_props/fisherman_chair.json | 1 + .../fisherman_props/fisherman_cyan_fish.json | 1 + .../fisherman_props/fisherman_fish_box.json | 1 + .../fisherman_props/fisherman_fish_rack.json | 1 + .../fisherman_fishing_pole.json | 1 + .../fisherman_fishingpole_rack.json | 1 + .../fisherman_props/fisherman_floatie.json | 1 + .../fisherman_hanging_fish.json | 1 + .../fisherman_landing_net.json | 1 + .../fisherman_large_fishnet.json | 1 + .../fisherman_lobster_trap.json | 1 + .../fisherman_orange_fish.json | 1 + .../fisherman_props/fisherman_red_fish.json | 1 + .../fisherman_props/fisherman_stand.json | 1 + .../fisherman_props/fisherman_table.json | 1 + .../models/lootbox/epic_box.json | 1173 +++++++++++++ .../lootbox/fishing_furniture_chest.json | 950 +++++++++++ .../models/lootbox/legendary_box.json | 1485 +++++++++++++++++ .../models/lootbox/rare_box.json | 714 ++++++++ .../ancient_fishing/ancient_armor_layer_1.png | Bin 0 -> 1377 bytes .../ancient_fishing/ancient_armor_layer_2.png | Bin 0 -> 508 bytes .../armor/ancient_fishing/ancient_boots.png | Bin 0 -> 250 bytes .../ancient_fishing/ancient_chestplate.png | Bin 0 -> 280 bytes .../armor/ancient_fishing/ancient_helmet.png | Bin 0 -> 271 bytes .../ancient_fishing/ancient_leggings.png | Bin 0 -> 253 bytes .../textures/fisherman_props/fisherman.png | Bin 0 -> 7805 bytes .../textures/lootbox/epic_box.png | Bin 0 -> 4180 bytes .../fishing_furniture_animation.png | Bin 0 -> 827 bytes .../fishing_furniture_animation.png.mcmeta | 20 + .../fishing_furniture_animation_2.png | Bin 0 -> 360 bytes .../fishing_furniture_animation_2.png.mcmeta | 25 + .../fishing_furniture_chest.png | Bin 0 -> 3821 bytes .../textures/lootbox/legendary_box.png | Bin 0 -> 4109 bytes .../textures/lootbox/rare_box.png | Bin 0 -> 4042 bytes .../textures/other/tenders.png | Bin 0 -> 497 bytes 48 files changed, 5599 insertions(+), 12 deletions(-) create mode 100644 src/main/resources/contents/omc_daily_events/armor.yml create mode 100644 src/main/resources/contents/omc_daily_events/fishing_furniture.yml create mode 100644 src/main/resources/contents/omc_daily_events/items.yml create mode 100644 src/main/resources/contents/omc_daily_events/lootbox.yml create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_blue_fish.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_boat.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_chair.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_cyan_fish.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fish_box.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fish_rack.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fishing_pole.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fishingpole_rack.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_floatie.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_hanging_fish.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_landing_net.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_large_fishnet.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_lobster_trap.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_orange_fish.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_red_fish.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_stand.json create mode 100644 src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_table.json create mode 100644 src/main/resources/contents/omc_daily_events/models/lootbox/epic_box.json create mode 100644 src/main/resources/contents/omc_daily_events/models/lootbox/fishing_furniture_chest.json create mode 100644 src/main/resources/contents/omc_daily_events/models/lootbox/legendary_box.json create mode 100644 src/main/resources/contents/omc_daily_events/models/lootbox/rare_box.json create mode 100644 src/main/resources/contents/omc_daily_events/textures/armor/ancient_fishing/ancient_armor_layer_1.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/armor/ancient_fishing/ancient_armor_layer_2.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/armor/ancient_fishing/ancient_boots.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/armor/ancient_fishing/ancient_chestplate.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/armor/ancient_fishing/ancient_helmet.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/armor/ancient_fishing/ancient_leggings.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/fisherman_props/fisherman.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/lootbox/epic_box.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_animation.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_animation.png.mcmeta create mode 100644 src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_animation_2.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_animation_2.png.mcmeta create mode 100644 src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_chest.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/lootbox/legendary_box.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/lootbox/rare_box.png create mode 100644 src/main/resources/contents/omc_daily_events/textures/other/tenders.png diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/fishing/MiraculousFishLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/fishing/MiraculousFishLootTable.java index c634f2e09..9a418fe34 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/fishing/MiraculousFishLootTable.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/fishing/MiraculousFishLootTable.java @@ -2,10 +2,7 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.loottable.CustomLootTable; -import fr.openmc.core.registry.loottable.loots.CustomLoot; -import fr.openmc.core.registry.loottable.loots.LootboxLoot; -import fr.openmc.core.registry.loottable.loots.MoneyLoot; -import fr.openmc.core.registry.loottable.loots.TableLoot; +import fr.openmc.core.registry.loottable.loots.*; import java.util.Set; @@ -20,7 +17,7 @@ public Set getLoots() { return Set.of( new TableLoot(OMCRegistry.CUSTOM_LOOT_TABLES.BASIC_FISHING, 0.4), new MoneyLoot(50, 250, 0.3), - // new ItemLoot(OMCRegistry.CUSTOM_ITEMS.BOB_SPONGE, 0.1, 1, 1), + new ItemLoot(OMCRegistry.CUSTOM_ITEMS.SPONGE_BOB, 0.1, 1, 1), new LootboxLoot(OMCRegistry.CUSTOM_LOOTBOXES.FISHING_FURNITURE, 0.08), new LootboxLoot(OMCRegistry.CUSTOM_LOOTBOXES.RARE_FISHING_TREASURE, 0.1) // new TableLoot(OMCRegistry.CUSTOM_LOOT_TABLES.SEA_CREATURE, 0.2) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/EpicFishingTreasureLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/EpicFishingTreasureLootTable.java index 4abd1e9ec..a7285921f 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/EpicFishingTreasureLootTable.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/EpicFishingTreasureLootTable.java @@ -24,8 +24,20 @@ public String getNamespace() { public Set getLoots() { return Set.of( new ItemLoot(generateEnchantedBook(), Material.ENCHANTED_BOOK, 0.2, 1, 2), - //new ItemLoot(OMCRegistry.CUSTOM_ITEMS.KEBAB_FERMENTED, OMCRegistry.CUSTOM_ITEMS.KEBAB_FERMENTED, 0.1, 1, 3), - new ItemLoot(OMCRegistry.CUSTOM_ITEMS.AYWENITE_BLOCK, OMCRegistry.CUSTOM_ITEMS.AYWENITE_BLOCK, 0.07, 2, 6), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.KEBAB_FERMENTED, + OMCRegistry.CUSTOM_ITEMS.KEBAB_FERMENTED, + 0.1, + 1, + 3 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.AYWENITE_BLOCK, + OMCRegistry.CUSTOM_ITEMS.AYWENITE_BLOCK, + 0.07, + 2, + 6 + ), new LootboxLoot(OMCRegistry.CUSTOM_LOOTBOXES.LEGENDARY_FISHING_TREASURE, 0.1) ); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/FishingFurnitureLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/FishingFurnitureLootTable.java index ef989fdf5..7e2867be4 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/FishingFurnitureLootTable.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/FishingFurnitureLootTable.java @@ -1,7 +1,9 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.lootbox; +import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.loottable.CustomLootTable; import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; import java.util.Set; @@ -14,7 +16,125 @@ public String getNamespace() { @Override public Set getLoots() { return Set.of( - // todo: put furniture in contents item adders + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_BLUE_FISH, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_BLUE_FISH, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_CYAN_FISH, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_CYAN_FISH, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_ORANGE_FISH, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_ORANGE_FISH, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_RED_FISH, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_RED_FISH, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_BOAT, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_BOAT, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_CHAIR, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_CHAIR, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISH_BOX, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISH_BOX, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISH_RACK, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISH_RACK, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISHING_POLE, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISHING_POLE, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISHINGPOLE_RACK, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISHINGPOLE_RACK, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FLOATIE, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FLOATIE, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_HANGING_FISH, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_HANGING_FISH, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_LANDING_NET, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_LANDING_NET, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_LARGE_FISHNET, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_LARGE_FISHNET, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_LOBSTER_TRAP, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_LOBSTER_TRAP, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_STAND, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_STAND, + 0.1, + 1, + 1 + ), + new ItemLoot( + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_TABLE, + OMCRegistry.CUSTOM_ITEMS.FISHERMAN_TABLE, + 0.1, + 1, + 1 + ) ); } } \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/LegendaryFishingTreasureLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/LegendaryFishingTreasureLootTable.java index 35ef67095..0de478e1b 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/LegendaryFishingTreasureLootTable.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/LegendaryFishingTreasureLootTable.java @@ -1,5 +1,6 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.lootbox; +import fr.openmc.core.OMCRegistry; import fr.openmc.core.features.dream.registries.DreamItemRegistry; import fr.openmc.core.registry.loottable.CustomLootTable; import fr.openmc.core.registry.loottable.loots.CustomLoot; @@ -16,8 +17,8 @@ public String getNamespace() { @Override public Set getLoots() { return Set.of( - //new ItemLoot(OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_HELMET, OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_HELMET, 0.20, 1, 1), - //new ItemLoot(OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_BOOTS, OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_BOOTS, 0.20, 1, 1), + new ItemLoot(OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_HELMET, OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_HELMET, 0.20, 1, 1), + new ItemLoot(OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_BOOTS, OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_BOOTS, 0.20, 1, 1), new ItemLoot(DreamItemRegistry.EWENITE_BLOCK, DreamItemRegistry.EWENITE_BLOCK, 0.006, 1, 1) ); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/RareFishingTreasureLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/RareFishingTreasureLootTable.java index 39bbb0f8b..de7fce132 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/RareFishingTreasureLootTable.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/RareFishingTreasureLootTable.java @@ -23,7 +23,6 @@ public Set getLoots() { new ItemLoot(Material.TROPICAL_FISH, Material.TROPICAL_FISH, 0.3, 32, 64), new ItemLoot(Material.PUFFERFISH, Material.PUFFERFISH, 0.3, 15, 32), new ItemLoot(Material.NAUTILUS_SHELL, Material.NAUTILUS_SHELL, 0.15, 2, 4), - // todo add ampoule new LootboxLoot(OMCRegistry.CUSTOM_LOOTBOXES.EPIC_FISHING_TREASURE, 0.1) ); diff --git a/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java b/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java index 84dd8d737..b5314a033 100644 --- a/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java +++ b/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java @@ -86,6 +86,39 @@ public class CustomItemRegistry extends Registry implements public final CustomItem DIAMOND_HAMMER = register(new Hammer("omc_items:diamond_hammer", Material.DIAMOND_PICKAXE, 1, 1)); public final CustomItem NETHERITE_HAMMER = register(new Hammer("omc_items:netherite_hammer", Material.NETHERITE_PICKAXE, 1, 2)); + /* Daily Event */ + public final CustomItem TENDERS = register("omc_daily_events:tenders", Material.COOKED_CHICKEN); + public final CustomItem SPONGE_BOB = register("omc_daily_events:bob_sponge", Material.SPONGE); + public final CustomItem KEBAB_FERMENTED = register("omc_daily_events:kebab_fermented", Material.COOKED_BEEF); + + public final CustomItem ANCIENT_FISHER_HELMET = register("omc_daily_events:ancient_fishing_helmet", Material.IRON_HELMET); + public final CustomItem ANCIENT_FISHER_CHESTPLATE = register("omc_daily_events:ancient_fishing_chestplate", Material.IRON_CHESTPLATE); + public final CustomItem ANCIENT_FISHER_LEGGINGS = register("omc_daily_events:ancient_fishing_leggings", Material.IRON_LEGGINGS); + public final CustomItem ANCIENT_FISHER_BOOTS = register("omc_daily_events:ancient_fishing_boots", Material.IRON_BOOTS); + + public final CustomItem FISHERMAN_BLUE_FISH = register("omc_daily_events:fisherman_blue_fish", Material.PAPER); + public final CustomItem FISHERMAN_CYAN_FISH = register("omc_daily_events:fisherman_cyan_fish", Material.PAPER); + public final CustomItem FISHERMAN_ORANGE_FISH = register("omc_daily_events:fisherman_orange_fish", Material.PAPER); + public final CustomItem FISHERMAN_RED_FISH = register("omc_daily_events:fisherman_red_fish", Material.PAPER); + public final CustomItem FISHERMAN_BOAT = register("omc_daily_events:fisherman_boat", Material.PAPER); + public final CustomItem FISHERMAN_CHAIR = register("omc_daily_events:fisherman_chair", Material.PAPER); + public final CustomItem FISHERMAN_FISH_BOX = register("omc_daily_events:fisherman_fish_box", Material.PAPER); + public final CustomItem FISHERMAN_FISH_RACK = register("omc_daily_events:fisherman_fish_rack", Material.PAPER); + public final CustomItem FISHERMAN_FISHING_POLE = register("omc_daily_events:fisherman_fishing_pole", Material.PAPER); + public final CustomItem FISHERMAN_FISHINGPOLE_RACK = register("omc_daily_events:fisherman_fishingpole_rack", Material.PAPER); + public final CustomItem FISHERMAN_FLOATIE = register("omc_daily_events:fisherman_floatie", Material.PAPER); + public final CustomItem FISHERMAN_HANGING_FISH = register("omc_daily_events:fisherman_hanging_fish", Material.PAPER); + public final CustomItem FISHERMAN_LANDING_NET = register("omc_daily_events:fisherman_landing_net", Material.PAPER); + public final CustomItem FISHERMAN_LARGE_FISHNET = register("omc_daily_events:fisherman_large_fishnet", Material.PAPER); + public final CustomItem FISHERMAN_LOBSTER_TRAP = register("omc_daily_events:fisherman_lobster_trap", Material.PAPER); + public final CustomItem FISHERMAN_STAND = register("omc_daily_events:fisherman_stand", Material.PAPER); + public final CustomItem FISHERMAN_TABLE = register("omc_daily_events:fisherman_table", Material.PAPER); + + public final CustomItem RARE_FISHING_TREASURE = register("omc_daily_events:rare_fishing_treasure_lootbox", Material.GLASS); + public final CustomItem EPIC_FISHING_TREASURE = register("omc_daily_events:epic_fishing_treasure_lootbox", Material.GLASS); + public final CustomItem LEGENDARY_FISHING_TREASURE = register("omc_daily_events:legendary_fishing_treasure_lootbox", Material.GLASS); + public final CustomItem FISHING_FURNITURE_BOX = register("omc_daily_events:fishing_furniture_lootbox", Material.GLASS); + @Override public void postInit() { CommandsManager.getHandler().register(new CustomItemsDebugCommand()); diff --git a/src/main/resources/contents/omc_daily_events/armor.yml b/src/main/resources/contents/omc_daily_events/armor.yml new file mode 100644 index 000000000..c8dfa6db4 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/armor.yml @@ -0,0 +1,71 @@ +info: + namespace: omc_daily_events +equipments: + ancient_fishing: + type: armor + layer_1: armor/ancient_fishing/ancient_armor_layer_1 + layer_2: armor/ancient_fishing/ancient_armor_layer_2 + +items: + ancient_fishing_helmet: + display_name: "Casque du pêcheur antique" + resource: + generate: true + textures: + - armor/ancient_fishing/ancient_helmet + material: LEATHER_HELMET + lore: + - "§7§oUn casque trouvé dans les abysses des mers" + durability: + unbreakable: true + equipment: + id: omc_daily_events:ancient_fishing + slot_attribute_modifiers: + armor: 3 + + ancient_fishing_chestplate: + display_name: "Plastron du pêcheur antique" + resource: + generate: true + textures: + - armor/ancient_fishing/ancient_chestplate + material: LEATHER_CHESTPLATE + lore: + - "§7§oUn plastron trouvé dans les abysses des mers" + durability: + unbreakable: true + equipment: + id: omc_daily_events:ancient_fishing + slot_attribute_modifiers: + armor: 5 + ancient_fishing_leggings: + display_name: "Jambière du pêcheur antique" + resource: + generate: true + textures: + - armor/ancient_fishing/ancient_leggings + material: LEATHER_LEGGINGS + lore: + - "§7§oUne jambière trouvé dans les abysses des mers" + durability: + unbreakable: true + equipment: + id: omc_daily_events:ancient_fishing + slot_attribute_modifiers: + armor: 5 + + ancient_fishing_boots: + display_name: "Bottes du pêcheur antique" + resource: + generate: true + textures: + - armor/ancient_fishing/ancient_boots + material: LEATHER_BOOTS + lore: + - "§7§oDes bottes trouvées dans les abysses des mers" + durability: + unbreakable: true + equipment: + id: omc_daily_events:ancient_fishing + slot_attribute_modifiers: + armor: 3 \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/category.yml b/src/main/resources/contents/omc_daily_events/category.yml index a3b4e3055..b7b4f48fd 100644 --- a/src/main/resources/contents/omc_daily_events/category.yml +++ b/src/main/resources/contents/omc_daily_events/category.yml @@ -4,7 +4,7 @@ categories: omc_daily_events: enabled: true skip_if_already: false - icon: omc_daily_events:aywenite_block + icon: omc_daily_events:obese_golden_apple name: "OpenMC Daily Events" items: - omc_daily_events:* \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/fishing_furniture.yml b/src/main/resources/contents/omc_daily_events/fishing_furniture.yml new file mode 100644 index 000000000..51bf24c71 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/fishing_furniture.yml @@ -0,0 +1,520 @@ +info: + namespace: omc_daily_events + +items: + fisherman_blue_fish: + enabled: true + permission: "" + display_name: "Blue fish" + behaviours: + furniture: + entity: item_frame + small: false + solid: false + fixed_rotation: false + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: false + sound: + place: + name: block.wood.place + break: + name: block.wood.break + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_blue_fish + model_id: 2510051 + fisherman_cyan_fish: + enabled: true + permission: "" + display_name: "Cyan fish" + behaviours: + furniture: + entity: item_frame + small: false + solid: false + fixed_rotation: false + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: false + sound: + place: + name: block.wood.place + break: + name: block.wood.break + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_cyan_fish + model_id: 2510052 + fisherman_orange_fish: + enabled: true + permission: "" + display_name: "Orange fish" + behaviours: + furniture: + entity: item_frame + small: false + solid: false + fixed_rotation: false + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: false + sound: + place: + name: block.wood.place + break: + name: block.wood.break + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_orange_fish + model_id: 2510053 + fisherman_red_fish: + enabled: true + permission: "" + display_name: "Red fish" + behaviours: + furniture: + entity: item_frame + small: false + solid: false + fixed_rotation: false + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: false + sound: + place: + name: block.wood.place + break: + name: block.wood.break + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_red_fish + model_id: 2510054 + fisherman_boat: + enabled: true + permission: "" + display_name: "Boat" + behaviours: + furniture: + entity: item_display + small: false + solid: true + fixed_rotation: true + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: false + hitbox: + height: 1 + width: 3 + sound: + place: + name: block.wood.place + break: + name: block.wood.break + display_transformation: + transform: FIXED + translation: + x: 0 + y: -0.5 + z: 0 + scale: + x: 1 + y: 1 + z: 1 + right_rotation: + axis_angle: + angle: -90 + axis: + x: 1 + y: 0 + z: 0 + furniture_sit: + sit_height: 0.7 + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_boat + model_id: 2510055 + fisherman_chair: + enabled: true + permission: "" + display_name: "Fisherman stool" + behaviours: + furniture: + entity: item_frame + small: false + solid: true + fixed_rotation: false + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: false + sound: + place: + name: block.wood.place + break: + name: block.wood.break + furniture_sit: + sit_height: 1 + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_chair + model_id: 2510056 + fisherman_fish_box: + enabled: true + permission: "" + display_name: "Fish box" + behaviours: + furniture: + entity: item_frame + small: false + solid: true + fixed_rotation: false + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: false + sound: + place: + name: block.wood.place + break: + name: block.wood.break + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_fish_box + model_id: 2510057 + fisherman_fish_rack: + enabled: true + permission: "" + display_name: "Fish rack" + behaviours: + furniture: + entity: item_frame + small: false + solid: true + fixed_rotation: true + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: false + hitbox: + height: 1 + width: 2 + width_offset: -0.5 + sound: + place: + name: block.wood.place + break: + name: block.wood.break + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_fish_rack + model_id: 2510058 + fisherman_fishing_pole: + enabled: true + permission: "" + display_name: "Fishing pole" + behaviours: + furniture: + entity: item_frame + small: false + solid: false + fixed_rotation: true + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: false + sound: + place: + name: block.wood.place + break: + name: block.wood.break + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_fishing_pole + model_id: 2510059 + fisherman_fishingpole_rack: + enabled: true + permission: "" + display_name: "Fishing pole rack" + behaviours: + furniture: + entity: item_frame + small: false + solid: true + fixed_rotation: false + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: false + sound: + place: + name: block.wood.place + break: + name: block.wood.break + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_fishingpole_rack + model_id: 2510060 + fisherman_floatie: + enabled: true + permission: "" + display_name: "Floatie" + behaviours: + furniture: + entity: item_frame + small: false + solid: false + fixed_rotation: false + placeable_on: + floor: true + ceiling: false + walls: true + opposite_direction: false + sound: + place: + name: block.wood.place + break: + name: block.wood.break + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_floatie + model_id: 2510061 + fisherman_hanging_fish: + enabled: true + permission: "" + display_name: "Hanging fish" + behaviours: + furniture: + entity: item_display + small: false + solid: true + fixed_rotation: true + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: true + hitbox: + height: 1 + width: 3 + length: 1 + height_offset: 2 + sound: + place: + name: block.wood.place + break: + name: block.wood.break + display_transformation: + transform: FIXED + translation: + x: 0 + y: -0.5 + z: 0 + scale: + x: 1 + y: 1 + z: 1 + right_rotation: + axis_angle: + angle: -90 + axis: + x: 1 + y: 0 + z: 0 + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_hanging_fish + model_id: 2510062 + fisherman_landing_net: + enabled: true + permission: "" + display_name: "Landing net" + behaviours: + furniture: + entity: item_frame + small: false + solid: false + fixed_rotation: false + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: false + sound: + place: + name: block.wood.place + break: + name: block.wood.break + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_landing_net + model_id: 2510063 + fisherman_large_fishnet: + enabled: true + permission: "" + display_name: "Large fishnet" + behaviours: + furniture: + entity: item_display + small: false + solid: true + fixed_rotation: true + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: true + hitbox: + height: 3 + width: 3 + length: 1 + sound: + place: + name: block.wood.place + break: + name: block.wood.break + display_transformation: + transform: FIXED + translation: + x: 0 + y: -0.5 + z: 0 + scale: + x: 1 + y: 1 + z: 1 + right_rotation: + axis_angle: + angle: -90 + axis: + x: 1 + y: 0 + z: 0 + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_large_fishnet + model_id: 2510064 + fisherman_lobster_trap: + enabled: true + permission: "" + display_name: "Lobster trap" + behaviours: + furniture: + entity: item_frame + small: false + solid: false + fixed_rotation: false + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: false + sound: + place: + name: block.wood.place + break: + name: block.wood.break + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_lobster_trap + model_id: 2510065 + fisherman_stand: + enabled: true + permission: "" + display_name: "Fisherman stand" + behaviours: + furniture: + entity: item_display + small: false + solid: false + fixed_rotation: true + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: true + sound: + place: + name: block.wood.place + break: + name: block.wood.break + display_transformation: + transform: FIXED + translation: + x: 0 + y: -0.5 + z: 0 + scale: + x: 1 + y: 1 + z: 1 + right_rotation: + axis_angle: + angle: -90 + axis: + x: 1 + y: 0 + z: 0 + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_stand + model_id: 2510066 + fisherman_table: + enabled: true + permission: "" + display_name: "Table" + behaviours: + furniture: + entity: item_frame + small: false + solid: true + fixed_rotation: false + placeable_on: + floor: true + ceiling: false + walls: false + opposite_direction: false + hitbox: + width: 2 + width_offset: -0.5 + sound: + place: + name: block.wood.place + break: + name: block.wood.break + resource: + material: PAPER + generate: false + model_path: fisherman_props/fisherman_table + model_id: 2510067 \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/items.yml b/src/main/resources/contents/omc_daily_events/items.yml new file mode 100644 index 000000000..5b446cb80 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/items.yml @@ -0,0 +1,36 @@ +info: + namespace: omc_daily_events + +items: + tenders: + display_name: "Cuisse de poulet" + resource: + generate: true + textures: + - other/tenders + material: COOKED_CHICKEN + lore: + - "§7§oMhh le poulet eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeett" + + bob_sponge: + display_name: "Bob l'éponge" + resource: + material: PAPER + generate: false + model_path: "minecraft:item/sponge" + lore: + - "§7§oBOB L'ÉPONGE CARRÉ" + glint: true + + kebab_fermented: + display_name: "Kebab fermenté" + resource: + material: SPONGE + generate: false + model_path: "omc_foods:items/kebab" + lore: + - "§7§ol'originel, une légende raconte qu'il existait avant la kebaberie" + glint: true + attribute_modifiers: + mainhand: + luck: 1.1 \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/lootbox.yml b/src/main/resources/contents/omc_daily_events/lootbox.yml new file mode 100644 index 000000000..5a7c8fd99 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/lootbox.yml @@ -0,0 +1,82 @@ +info: + namespace: omc_daily_events +items: + rare_fishing_treasure_lootbox: + display_name: Trésor de pêche rare + resource: + material: PAPER + generate: false + model_path: lootbox/rare_box + behaviours: + furniture: + small: false + solid: true + entity: armor_stand + hitbox: + length: 1 + width: 1 + height: 1 + length_offset: 0 + width_offset: 0 + height_offset: 0 + + epic_fishing_treasure_lootbox: + display_name: Trésor de pêche épique + resource: + material: PAPER + generate: false + model_path: lootbox/epic_box + behaviours: + furniture: + small: false + solid: true + entity: armor_stand + hitbox: + length: 1 + width: 1 + height: 1 + length_offset: 0 + width_offset: 0 + height_offset: 0 + + legendary_fishing_treasure_lootbox: + display_name: Trésor de pêche légendaire + resource: + material: PAPER + generate: false + model_path: lootbox/legendary_box + behaviours: + furniture: + small: false + solid: true + entity: armor_stand + hitbox: + length: 1 + width: 1 + height: 1 + length_offset: 0 + width_offset: 0 + height_offset: 0 + + fishing_furniture_lootbox: + display_name: Boîte d'équipement de pêche + resource: + material: PAPER + generate: false + model_path: lootbox/fishing_furniture_chest + behaviours: + furniture: + solid: true + fixed_rotation: true + entity: item_frame + hitbox: + length: 1 + width: 1 + height: 1 + length_offset: 0 + width_offset: 0 + height_offset: 0 + placeable_on: + walls: false + ceiling: false + floor: true diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_blue_fish.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_blue_fish.json new file mode 100644 index 000000000..55a6ccf1f --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_blue_fish.json @@ -0,0 +1,333 @@ +{ + "credit": "Made with Blockbench", + "textures": { + "0": "omc_daily_events:fisherman_props/fisherman", + "particle": "omc_daily_events:fisherman_props/fisherman" + }, + "elements": [ + { + "from": [ + 6.1106, + 0.04828, + 4.1196 + ], + "to": [ + 10.1106, + 2.04828, + 13.1196 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + 8.1106, + 1.04828, + 7.8696 + ] + }, + "faces": { + "north": { + "uv": [ + 0.375, + 2.5625, + 0.4375, + 2.3125 + ], + "rotation": 90, + "texture": "#0" + }, + "east": { + "uv": [ + 0.375, + 2.3125, + 0.9375, + 2.375 + ], + "rotation": 180, + "texture": "#0" + }, + "south": { + "uv": [ + 0.875, + 2.5625, + 0.9375, + 2.3125 + ], + "rotation": 270, + "texture": "#0" + }, + "west": { + "uv": [ + 0.375, + 2.5, + 0.9375, + 2.5625 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 0.375, + 2.3125, + 0.9375, + 2.5625 + ], + "rotation": 90, + "texture": "#0" + }, + "down": { + "uv": [ + 0.375, + 2.5625, + 0.9375, + 2.3125 + ], + "rotation": 270, + "texture": "#0" + } + } + }, + { + "from": [ + 6.1106, + 1.04828, + 1.1196 + ], + "to": [ + 11.1106, + 1.04828, + 13.1196 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + 8.1106, + 1.04828, + 7.8696 + ] + }, + "faces": { + "up": { + "uv": [ + 0.1875, + 2.25, + 0.9375, + 2.5625 + ], + "rotation": 90, + "texture": "#0" + }, + "down": { + "uv": [ + 0.1875, + 2.5625, + 0.9375, + 2.25 + ], + "rotation": 270, + "texture": "#0" + } + } + }, + { + "from": [ + 7.6106, + -1.95172, + 7.6196 + ], + "to": [ + 7.6106, + 4.04828, + 9.6196 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + 8.1106, + 1.04828, + 7.8696 + ] + }, + "faces": { + "east": { + "uv": [ + 0.5, + 2.625, + 0.625, + 3 + ], + "rotation": 180, + "texture": "#0" + }, + "west": { + "uv": [ + 0.5, + 2.625, + 0.625, + 3 + ], + "texture": "#0" + } + } + } + ], + "gui_light": "front", + "display": { + "thirdperson_righthand": { + "rotation": [ + -91, + 0, + 0 + ], + "translation": [ + 0, + 4.75, + -5.75 + ], + "scale": [ + 1.03828, + 1.03828, + 1.03828 + ] + }, + "thirdperson_lefthand": { + "rotation": [ + -91, + 0, + 0 + ], + "translation": [ + 0.25, + 4.75, + -5.75 + ], + "scale": [ + 1.03828, + 1.03828, + 1.03828 + ] + }, + "firstperson_righthand": { + "rotation": [ + -145, + -13, + -180 + ], + "translation": [ + 7.75, + 4.25, + -0.5 + ], + "scale": [ + 0.75352, + 0.75352, + 0.75352 + ] + }, + "firstperson_lefthand": { + "rotation": [ + -145, + -13, + -180 + ], + "translation": [ + 7.75, + 4.25, + -0.5 + ], + "scale": [ + 0.75352, + 0.75352, + 0.75352 + ] + }, + "ground": { + "translation": [ + 0, + 4.5, + 0 + ], + "scale": [ + 0.41406, + 0.41406, + 0.41406 + ] + }, + "gui": { + "rotation": [ + -142.73, + 39.63, + -89.3 + ], + "translation": [ + 7, + -3, + 0 + ], + "scale": [ + 1.36914, + 1.36914, + 1.36914 + ] + }, + "head": { + "translation": [ + 0, + 12.75, + 0 + ], + "scale": [ + 0.79492, + 0.79492, + 0.79492 + ] + }, + "fixed": { + "rotation": [ + -90, + 0, + 0 + ], + "translation": [ + 0, + 0, + -16 + ], + "scale": [ + 2.00195, + 2.00195, + 2.00195 + ] + } + }, + "groups": [ + { + "name": "group", + "origin": [ + 8, + 8, + 8 + ], + "color": 0, + "children": [ + { + "name": "group", + "origin": [ + 8, + 8, + 8 + ], + "color": 0, + "children": [ + 0, + 1, + 2 + ] + } + ] + } + ], + "mcmodels": "47e9fc11ef703093a1d6a70bdf75f953" +} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_boat.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_boat.json new file mode 100644 index 000000000..8d01b87d9 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_boat.json @@ -0,0 +1 @@ +{"credit":"Made with Blockbench","texture_size":[256,256],"textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[1.72358,4.0293,2.96186],"to":[19.71186,10.0293,12.96186],"rotation":{"angle":0,"axis":"y","origin":[4,8.97328,7.96186]},"faces":{"north":{"uv":[0,8.125,2.24854,8.875],"rotation":180,"texture":"#0"},"east":{"uv":[0,8.9375,1.25,9.6875],"rotation":180,"texture":"#0"},"south":{"uv":[0,8.125,2.24854,8.875],"rotation":180,"texture":"#0"},"down":{"uv":[0,9.75,2.24854,11],"rotation":180,"texture":"#0"}}},{"from":[-1.24106,4.05469,5.97687],"to":[5.83511,10.0293,13.04328],"rotation":{"angle":-45,"axis":"y","origin":[3.88153,8.97228,8.04894]},"faces":{"south":{"uv":[0,8.9375,0.88452,9.6875],"rotation":180,"texture":"#0"},"west":{"uv":[0,9.6875,0.86719,8.9375],"texture":"#0"},"down":{"uv":[2.3335,9.77393,3.1665,10.60693],"rotation":270,"texture":"#0"}}},{"name":"cube inverted","from":[19.71186,10.0293,12.96186],"to":[1.72358,4.25,2.96186],"rotation":{"angle":0,"axis":"y","origin":[4,8.97328,7.96186]},"faces":{"north":{"uv":[0,8.875,2.24854,8.125],"rotation":180,"texture":"#0"},"south":{"uv":[0,8.875,2.24854,8.125],"rotation":180,"texture":"#0"},"west":{"uv":[0,9.6875,1.25,8.9375],"rotation":180,"texture":"#0"},"up":{"uv":[2.24854,9.75,0,11],"rotation":180,"texture":"#0"}}},{"name":"cube inverted","from":[5.83511,10.0293,13.04328],"to":[-1.24106,4.23828,5.97687],"rotation":{"angle":-45,"axis":"y","origin":[3.88153,8.97228,8.04894]},"faces":{"north":{"uv":[0,9.6875,0.88452,8.9375],"rotation":180,"texture":"#0"},"east":{"uv":[0,8.9375,0.86719,9.6875],"texture":"#0"},"up":{"uv":[2.3335,10.60693,3.1665,9.77393],"rotation":270,"texture":"#0"}}},{"from":[13,6.5293,3],"to":[16.5,7.0293,12.94922],"rotation":{"angle":0,"axis":"y","origin":[13.5,6.0293,3]},"faces":{"east":{"uv":[0,11.0625,1.24365,11.125],"texture":"#0"},"west":{"uv":[0,11.0625,1.24365,11.125],"texture":"#0"},"up":{"uv":[0,11.0625,1.24365,11.5],"rotation":90,"texture":"#0"},"down":{"uv":[0,11.0625,1.24365,11.5],"rotation":90,"texture":"#0"}}},{"from":[4.5,6.5293,3],"to":[8,7.0293,12.94922],"rotation":{"angle":0,"axis":"y","origin":[5,6.0293,3]},"faces":{"east":{"uv":[0,11.0625,1.24365,11.125],"texture":"#0"},"west":{"uv":[0,11.0625,1.24365,11.125],"texture":"#0"},"up":{"uv":[0,11.0625,1.24365,11.5],"rotation":90,"texture":"#0"},"down":{"uv":[0,11.0625,1.24365,11.5],"rotation":90,"texture":"#0"}}},{"from":[-1.44884,8.0293,12.58502],"to":[5.97303,10.0293,13.58502],"rotation":{"angle":-45,"axis":"y","origin":[4.29289,8.97328,8.25475]},"faces":{"north":{"uv":[0.9375,7.125,0.6875,8.05273],"rotation":90,"texture":"#0"},"east":{"uv":[0.6875,7.125,0.8125,7.375],"rotation":180,"texture":"#0"},"south":{"uv":[0.6875,7.125,0.9375,8.05273],"rotation":270,"texture":"#0"},"west":{"uv":[0.9375,7.125,0.6875,7.1875],"rotation":90,"texture":"#0"},"up":{"uv":[1,7.125,1.125,8.05273],"rotation":270,"texture":"#0"},"down":{"uv":[1.1875,7.125,1.3125,8.05273],"rotation":270,"texture":"#0"}}},{"from":[-1.14093,8.0293,2.68794],"to":[6.10907,10.03125,3.68794],"rotation":{"angle":45,"axis":"y","origin":[3.93934,8.97328,8.0078]},"faces":{"north":{"uv":[0.9375,7.125,0.6875,8],"rotation":90,"texture":"#0"},"south":{"uv":[0.6875,7.125,0.9375,8],"rotation":270,"texture":"#0"},"west":{"uv":[0.8125,7.125,0.6875,7.375],"texture":"#0"},"up":{"uv":[1.125,7.125,1,8],"rotation":270,"texture":"#0"},"down":{"uv":[1.3125,7.125,1.1875,8],"rotation":270,"texture":"#0"}}},{"from":[1.71186,8.0293,2.71186],"to":[19.96186,10.0293,3.71186],"rotation":{"angle":0,"axis":"y","origin":[4,8.97328,6.96186]},"faces":{"north":{"uv":[0.25,5.8125,0,8.0625],"rotation":90,"texture":"#0"},"east":{"uv":[0,5.9375,0.25,5.8125],"rotation":270,"texture":"#0"},"south":{"uv":[0,5.8125,0.25,8.0625],"rotation":270,"texture":"#0"},"west":{"uv":[0,0,0.125,0.25],"texture":"#0"},"up":{"uv":[0.3125,5.8125,0.4375,8.0625],"rotation":270,"texture":"#0"},"down":{"uv":[0.5,5.8125,0.625,8.0625],"rotation":270,"texture":"#0"}}},{"from":[1.71186,8.0293,12.21186],"to":[19.96186,10.0293,13.21186],"rotation":{"angle":0,"axis":"y","origin":[17.67372,8.97328,16.46186]},"faces":{"north":{"uv":[0.25,5.8125,0,8.0625],"rotation":90,"texture":"#0"},"east":{"uv":[0.25,5.9375,0,5.8125],"rotation":90,"texture":"#0"},"south":{"uv":[0,5.8125,0.25,8.0625],"rotation":270,"texture":"#0"},"west":{"uv":[0,5.8125,0.25,5.9375],"rotation":270,"texture":"#0"},"up":{"uv":[0.3125,5.8125,0.4375,8.0625],"rotation":270,"texture":"#0"},"down":{"uv":[0.5,5.8125,0.625,8.0625],"rotation":270,"texture":"#0"}}},{"from":[18.96186,8.0293,3.71186],"to":[19.96186,10.0293,12.21186],"rotation":{"angle":0,"axis":"y","origin":[11.75,8.97328,7.96186]},"faces":{"north":{"uv":[0,0,0.25,0.125],"rotation":90,"texture":"#0"},"east":{"uv":[0.6875,6,0.9375,7.0625],"rotation":270,"texture":"#0"},"south":{"uv":[0,0,0.25,0.125],"rotation":270,"texture":"#0"},"west":{"uv":[0.9375,6,0.6875,7.0625],"rotation":90,"texture":"#0"},"up":{"uv":[1,6,1.125,7.0625],"rotation":180,"texture":"#0"},"down":{"uv":[1.1875,6,1.3125,7.0625],"texture":"#0"}}},{"from":[-4.57772,4.39478,7.46922],"to":[-1.07772,5.39478,8.46922],"rotation":{"angle":-45,"axis":"z","origin":[4,8.97328,7.96186]},"faces":{"north":{"uv":[0.9375,5.3125,1.0625,5.75],"rotation":90,"texture":"#0"},"south":{"uv":[0.9375,5.3125,1.0625,5.75],"rotation":270,"texture":"#0"},"west":{"uv":[0.9375,5.3125,1.0625,5.375],"texture":"#0"},"up":{"uv":[0.9375,5.3125,1.0625,5.75],"rotation":270,"texture":"#0"},"down":{"uv":[0.9375,5.3125,1.0625,5.75],"rotation":270,"texture":"#0"}}},{"from":[14.21186,10.0293,2.96186],"to":[15.71186,11.0293,3.46186],"rotation":{"angle":0,"axis":"y","origin":[12.5,8.97328,6.96186]},"faces":{"north":{"uv":[0.1875,5.75,0.375,5.625],"rotation":180,"texture":"#0"},"east":{"uv":[0.1875,5.75,0.25,5.625],"rotation":180,"texture":"#0"},"south":{"uv":[0.1875,5.625,0.375,5.75],"texture":"#0"},"west":{"uv":[0.1875,5.625,0.25,5.75],"texture":"#0"},"up":{"uv":[0.375,5.625,0.1875,5.6875],"rotation":180,"texture":"#0"}}},{"from":[5.71186,10.0293,2.96186],"to":[7.21186,11.0293,3.46186],"rotation":{"angle":0,"axis":"y","origin":[4,8.97328,6.96186]},"faces":{"north":{"uv":[0.1875,5.75,0.375,5.625],"rotation":180,"texture":"#0"},"east":{"uv":[0.1875,5.75,0.25,5.625],"rotation":180,"texture":"#0"},"south":{"uv":[0.1875,5.625,0.375,5.75],"texture":"#0"},"west":{"uv":[0.1875,5.625,0.25,5.75],"texture":"#0"},"up":{"uv":[0.375,5.625,0.1875,5.6875],"rotation":180,"texture":"#0"}}},{"from":[5.71186,10.0293,12.46186],"to":[7.21186,11.0293,12.96186],"rotation":{"angle":0,"axis":"y","origin":[4,8.97328,16.46186]},"faces":{"north":{"uv":[0.1875,5.75,0.375,5.625],"rotation":180,"texture":"#0"},"east":{"uv":[0.1875,5.75,0.25,5.625],"rotation":180,"texture":"#0"},"south":{"uv":[0.1875,5.625,0.375,5.75],"texture":"#0"},"west":{"uv":[0.1875,5.625,0.25,5.75],"texture":"#0"},"up":{"uv":[0.375,5.625,0.1875,5.6875],"rotation":180,"texture":"#0"}}},{"from":[14.21186,10.0293,12.46186],"to":[15.71186,11.0293,12.96186],"rotation":{"angle":0,"axis":"y","origin":[12.5,8.97328,16.46186]},"faces":{"north":{"uv":[0.1875,5.75,0.375,5.625],"rotation":180,"texture":"#0"},"east":{"uv":[0.1875,5.75,0.25,5.625],"rotation":180,"texture":"#0"},"south":{"uv":[0.1875,5.625,0.375,5.75],"texture":"#0"},"west":{"uv":[0.1875,5.625,0.25,5.75],"texture":"#0"},"up":{"uv":[0.375,5.625,0.1875,5.6875],"rotation":180,"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[90,-90,0],"translation":[0.25,4,2.25],"scale":[0.375,0.375,0.375]},"thirdperson_lefthand":{"rotation":[90,90,0],"translation":[0.25,4,2.25],"scale":[0.375,0.375,0.375]},"firstperson_righthand":{"rotation":[0,-86,0],"translation":[5.25,2.75,1.5],"scale":[0.4,0.4,0.4]},"firstperson_lefthand":{"rotation":[0,75.75,0],"translation":[5.25,2.75,2],"scale":[0.4,0.4,0.4]},"ground":{"translation":[0,3,0],"scale":[0.25,0.25,0.25]},"gui":{"rotation":[30,225,0],"translation":[0.5,-0.25,0],"scale":[0.625,0.625,0.625]},"head":{"translation":[0,12.75,0],"scale":[0.79492,0.79492,0.79492]},"fixed":{"rotation":[-90,0,0],"translation":[0,0,-16],"scale":[2.00195,2.00195,2.00195]}},"groups":[{"name":"group","origin":[8,8,8],"color":0,"children":[{"name":"group","origin":[8,8,8],"color":0,"children":[0,1,2,3]},{"name":"group","origin":[8,8,8],"color":0,"children":[4,5]},{"name":"group","origin":[0,0,0],"color":0,"children":[6,7,8,9,10,11]},{"name":"group","origin":[8,8,8],"color":0,"children":[12,13,14,15]}]}],"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_chair.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_chair.json new file mode 100644 index 000000000..f31b6adb6 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_chair.json @@ -0,0 +1 @@ +{"credit":"Made with Blockbench","texture_size":[256,256],"textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[7,-1,1],"to":[9,15,15],"rotation":{"angle":45,"axis":"z","origin":[8,4.5,8]},"faces":{"north":{"uv":[2.5,5.75,2.5625,6.75],"texture":"#0"},"east":{"uv":[2.5,5.75,3.375,6.75],"texture":"#0"},"south":{"uv":[3.3125,5.75,3.375,6.75],"texture":"#0"},"west":{"uv":[3.375,5.75,2.5,6.75],"texture":"#0"},"up":{"uv":[2.5,5.75,3.375,5.8125],"rotation":90,"texture":"#0"},"down":{"uv":[2.5,6.6875,3.375,6.75],"rotation":90,"texture":"#0"}}},{"from":[7,0,14],"to":[9,14,2],"rotation":{"angle":45,"axis":"z","origin":[8,4.5,21]},"faces":{"north":{"uv":[2.5,5.8125,2.5625,6.6875],"texture":"#0"},"south":{"uv":[2.5,5.8125,2.5625,6.6875],"texture":"#0"},"up":{"uv":[2.5625,5.75,3.3125,5.8125],"rotation":90,"texture":"#0"},"down":{"uv":[3.3125,6.6875,2.5625,6.75],"rotation":90,"texture":"#0"}}},{"from":[8.76777,-1.73223,1],"to":[10.76777,14.26777,15],"rotation":{"angle":-45,"axis":"z","origin":[9.76777,6.26777,8]},"faces":{"north":{"uv":[2.5625,5.75,2.5,6.75],"texture":"#0"},"east":{"uv":[2.5,5.75,3.375,6.75],"texture":"#0"},"south":{"uv":[3.375,5.75,3.3125,6.75],"texture":"#0"},"west":{"uv":[3.375,5.75,2.5,6.75],"texture":"#0"},"up":{"uv":[2.5,5.8125,3.375,5.75],"rotation":90,"texture":"#0"},"down":{"uv":[2.5,6.75,3.375,6.6875],"rotation":90,"texture":"#0"}}},{"from":[8.76777,-0.73223,14],"to":[10.76777,13.26777,2],"rotation":{"angle":-45,"axis":"z","origin":[9.76777,6.26777,8]},"faces":{"north":{"uv":[2.5625,5.8125,2.5,6.6875],"texture":"#0"},"south":{"uv":[2.5625,5.8125,2.5,6.6875],"texture":"#0"},"up":{"uv":[2.5625,5.8125,3.3125,5.75],"rotation":90,"texture":"#0"},"down":{"uv":[3.3125,6.75,2.5625,6.6875],"rotation":90,"texture":"#0"}}},{"from":[-0.5,10,2],"to":[2.5,13,14],"rotation":{"angle":0,"axis":"z","origin":[1,11.5,8]},"faces":{"east":{"uv":[3.4375,7,4.1875,6.8125],"rotation":180,"texture":"#0"},"west":{"uv":[4.1875,6.8125,3.4375,7],"rotation":180,"texture":"#0"},"up":{"uv":[4.1875,6.8125,3.4375,7],"rotation":90,"texture":"#0"},"down":{"uv":[4.1875,7,3.4375,6.8125],"rotation":90,"texture":"#0"}}},{"from":[13.5,10,2],"to":[16.5,13,14],"rotation":{"angle":0,"axis":"z","origin":[15,11.5,8]},"faces":{"east":{"uv":[3.4375,6.8125,4.1875,7],"rotation":180,"texture":"#0"},"west":{"uv":[4.1875,7,3.4375,6.8125],"rotation":180,"texture":"#0"},"up":{"uv":[4.1875,7,3.4375,6.8125],"rotation":90,"texture":"#0"},"down":{"uv":[4.1875,6.8125,3.4375,7],"rotation":90,"texture":"#0"}}},{"from":[2.5,12,2],"to":[13.5,12,14],"rotation":{"angle":0,"axis":"y","origin":[11.5,10,2]},"faces":{"up":{"uv":[3.4375,6.0625,4.1875,6.75],"rotation":90,"texture":"#0"},"down":{"uv":[3.4375,6.0625,4.1875,6.75],"rotation":90,"texture":"#0"}}},{"name":"cube inverted","from":[16.5,13,14],"to":[13.5,10,2],"rotation":{"angle":0,"axis":"z","origin":[15,11.5,8]},"faces":{"east":{"uv":[4.1875,6.8125,3.4375,7],"rotation":180,"texture":"#0"},"west":{"uv":[3.4375,7,4.1875,6.8125],"rotation":180,"texture":"#0"},"up":{"uv":[4.1875,7,3.4375,6.8125],"rotation":90,"texture":"#0"},"down":{"uv":[4.1875,6.8125,3.4375,7],"rotation":90,"texture":"#0"}}},{"name":"cube inverted","from":[2.5,13,14],"to":[-0.5,10,2],"rotation":{"angle":0,"axis":"z","origin":[1,11.5,8]},"faces":{"east":{"uv":[4.1875,7,3.4375,6.8125],"rotation":180,"texture":"#0"},"west":{"uv":[3.4375,6.8125,4.1875,7],"rotation":180,"texture":"#0"},"up":{"uv":[4.1875,6.8125,3.4375,7],"rotation":90,"texture":"#0"},"down":{"uv":[4.1875,7,3.4375,6.8125],"rotation":90,"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[75,45,0],"translation":[0,2.75,3.25],"scale":[0.375,0.375,0.375]},"thirdperson_lefthand":{"rotation":[75,45,0],"translation":[-0.5,3,3.25],"scale":[0.375,0.375,0.375]},"firstperson_righthand":{"rotation":[0,75.75,0],"translation":[5.25,2.25,1.5],"scale":[0.4,0.4,0.4]},"firstperson_lefthand":{"rotation":[0,75.75,0],"translation":[5.25,2.75,2],"scale":[0.4,0.4,0.4]},"ground":{"translation":[0,3,0],"scale":[0.25,0.25,0.25]},"gui":{"rotation":[30,225,0],"translation":[0.25,-0.25,0],"scale":[0.625,0.625,0.625]},"head":{"translation":[0,12.75,0],"scale":[0.79492,0.79492,0.79492]},"fixed":{"rotation":[-90,0,0],"translation":[0,0,-16],"scale":[2.00195,2.00195,2.00195]}},"groups":[{"name":"group","origin":[8,8,8],"color":0,"boneType":"","children":[0,1,2,3,{"name":"group","origin":[8,8,8],"color":0,"boneType":"","children":[4,5,6,7,8]}]}],"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_cyan_fish.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_cyan_fish.json new file mode 100644 index 000000000..4a6b6a9fa --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_cyan_fish.json @@ -0,0 +1 @@ +{"credit":"Made with Blockbench","textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[6.1106,0.04828,4.1196],"to":[10.1106,2.04828,13.1196],"rotation":{"angle":0,"axis":"y","origin":[8.1106,1.04828,7.8696]},"faces":{"north":{"uv":[0.375,3.5,0.4375,3.25],"rotation":90,"texture":"#0"},"east":{"uv":[0.375,3.25,0.9375,3.3125],"rotation":180,"texture":"#0"},"south":{"uv":[0.875,3.5,0.9375,3.25],"rotation":270,"texture":"#0"},"west":{"uv":[0.375,3.4375,0.9375,3.5],"texture":"#0"},"up":{"uv":[0.375,3.25,0.9375,3.5],"rotation":90,"texture":"#0"},"down":{"uv":[0.375,3.5,0.9375,3.25],"rotation":270,"texture":"#0"}}},{"from":[6.1106,1.04828,1.1196],"to":[11.1106,1.04828,13.1196],"rotation":{"angle":0,"axis":"y","origin":[8.1106,1.04828,7.8696]},"faces":{"up":{"uv":[0.1875,3.1875,0.9375,3.5],"rotation":90,"texture":"#0"},"down":{"uv":[0.1875,3.5,0.9375,3.1875],"rotation":270,"texture":"#0"}}},{"from":[7.6106,-1.95172,7.6196],"to":[7.6106,4.04828,9.6196],"rotation":{"angle":0,"axis":"y","origin":[8.1106,1.04828,7.8696]},"faces":{"east":{"uv":[0.5,3.5625,0.625,3.9375],"rotation":180,"texture":"#0"},"west":{"uv":[0.5,3.5625,0.625,3.9375],"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[-91,0,0],"translation":[0,4.75,-5.75],"scale":[1.03828,1.03828,1.03828]},"thirdperson_lefthand":{"rotation":[-91,0,0],"translation":[0.25,4.75,-5.75],"scale":[1.03828,1.03828,1.03828]},"firstperson_righthand":{"rotation":[-145,-13,-180],"translation":[7.75,4.25,-0.5],"scale":[0.75352,0.75352,0.75352]},"firstperson_lefthand":{"rotation":[-145,-13,-180],"translation":[7.75,4.25,-0.5],"scale":[0.75352,0.75352,0.75352]},"ground":{"translation":[0,4.5,0],"scale":[0.41406,0.41406,0.41406]},"gui":{"rotation":[-142.73,39.63,-89.3],"translation":[7,-3,0],"scale":[1.36914,1.36914,1.36914]},"head":{"translation":[0,12.75,0],"scale":[0.79492,0.79492,0.79492]},"fixed":{"rotation":[-90,0,0],"translation":[0,0,-16],"scale":[2.00195,2.00195,2.00195]}},"groups":[{"name":"group","origin":[8,8,8],"color":0,"children":[{"name":"group","origin":[8,8,8],"color":0,"children":[0,1,2]}]}],"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fish_box.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fish_box.json new file mode 100644 index 000000000..be290dd1d --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fish_box.json @@ -0,0 +1 @@ +{"credit":"132818 / 18007B1J3WA9PZIDHN","texture_size":[256,256],"textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[0,0,0],"to":[16,16,16],"faces":{"north":{"uv":[4.25,6.3125,5.25,7.3125],"texture":"#0"},"east":{"uv":[4.25,6.3125,5.25,7.3125],"texture":"#0"},"south":{"uv":[4.25,6.3125,5.25,7.3125],"texture":"#0"},"west":{"uv":[4.25,6.3125,5.25,7.3125],"texture":"#0"},"up":{"uv":[4.25,7.375,5.25,8.375],"texture":"#0"},"down":{"uv":[3.1875,7.0625,4.1875,8.0625],"texture":"#0"}}},{"from":[2.1106,16.04828,5.1196],"to":[6.1106,18.04828,14.1196],"rotation":{"angle":22.5,"axis":"y","origin":[4.1106,17.04828,8.8696]},"faces":{"north":{"uv":[0.375,2.5625,0.4375,2.3125],"rotation":90,"texture":"#0"},"east":{"uv":[0.375,2.3125,0.9375,2.375],"rotation":180,"texture":"#0"},"south":{"uv":[0.875,2.5625,0.9375,2.3125],"rotation":270,"texture":"#0"},"west":{"uv":[0.375,2.5,0.9375,2.5625],"texture":"#0"},"up":{"uv":[0.375,2.3125,0.9375,2.5625],"rotation":90,"texture":"#0"},"down":{"uv":[0.375,2.5625,0.9375,2.3125],"rotation":270,"texture":"#0"}}},{"from":[2.1106,17.04828,2.1196],"to":[7.1106,17.04828,14.1196],"rotation":{"angle":22.5,"axis":"y","origin":[4.1106,17.04828,8.8696]},"faces":{"up":{"uv":[0.1875,2.25,0.9375,2.5625],"rotation":90,"texture":"#0"},"down":{"uv":[0.1875,2.5625,0.9375,2.25],"rotation":270,"texture":"#0"}}},{"from":[3.6106,14.04828,8.6196],"to":[3.6106,20.04828,10.6196],"rotation":{"angle":22.5,"axis":"y","origin":[4.1106,17.04828,8.8696]},"faces":{"east":{"uv":[0.5,2.625,0.625,3],"rotation":180,"texture":"#0"},"west":{"uv":[0.5,2.625,0.625,3],"texture":"#0"}}},{"from":[7.87622,16.04828,1.42429],"to":[11.87622,18.04828,10.42429],"rotation":{"angle":45,"axis":"y","origin":[9.87622,17.04828,5.17429]},"faces":{"north":{"uv":[1.3125,2.5625,1.375,2.3125],"rotation":90,"texture":"#0"},"east":{"uv":[1.3125,2.3125,1.875,2.375],"rotation":180,"texture":"#0"},"south":{"uv":[1.8125,2.5625,1.875,2.3125],"rotation":270,"texture":"#0"},"west":{"uv":[1.3125,2.5,1.875,2.5625],"texture":"#0"},"up":{"uv":[1.3125,2.3125,1.875,2.5625],"rotation":90,"texture":"#0"},"down":{"uv":[1.3125,2.5625,1.875,2.3125],"rotation":270,"texture":"#0"}}},{"from":[7.87622,17.04828,-1.57571],"to":[12.87622,17.04828,10.42429],"rotation":{"angle":45,"axis":"y","origin":[9.87622,17.04828,5.17429]},"faces":{"up":{"uv":[1.125,2.25,1.875,2.5625],"rotation":90,"texture":"#0"},"down":{"uv":[1.125,2.5625,1.875,2.25],"rotation":270,"texture":"#0"}}},{"from":[9.37622,14.04828,4.92429],"to":[9.37622,20.04828,6.92429],"rotation":{"angle":45,"axis":"y","origin":[9.87622,17.04828,5.17429]},"faces":{"east":{"uv":[1.4375,2.625,1.5625,3],"rotation":180,"texture":"#0"},"west":{"uv":[1.4375,2.625,1.5625,3],"texture":"#0"}}},{"from":[9.1106,12.79828,12.8696],"to":[13.1106,21.79828,14.8696],"rotation":{"angle":22.5,"axis":"x","origin":[11.1106,18.04828,13.8696]},"faces":{"north":{"uv":[1.3125,3.5,1.875,3.25],"rotation":90,"texture":"#0"},"east":{"uv":[1.3125,3.25,1.875,3.3125],"rotation":90,"texture":"#0"},"south":{"uv":[1.3125,3.25,1.875,3.5],"rotation":90,"texture":"#0"},"west":{"uv":[1.3125,3.4375,1.875,3.5],"rotation":90,"texture":"#0"},"up":{"uv":[1.3125,3.5,1.375,3.25],"rotation":270,"texture":"#0"},"down":{"uv":[1.8125,3.5,1.875,3.25],"rotation":270,"texture":"#0"}}},{"from":[9.1106,12.79828,13.8696],"to":[14.1106,24.79828,13.8696],"rotation":{"angle":22.5,"axis":"x","origin":[11.1106,18.04828,13.8696]},"faces":{"north":{"uv":[1.125,3.5,1.875,3.1875],"rotation":90,"texture":"#0"},"south":{"uv":[1.125,3.1875,1.875,3.5],"rotation":90,"texture":"#0"}}},{"from":[10.6106,16.29828,10.8696],"to":[10.6106,18.29828,16.8696],"rotation":{"angle":22.5,"axis":"x","origin":[11.1106,18.04828,13.8696]},"faces":{"east":{"uv":[1.4375,3.5625,1.5625,3.9375],"rotation":90,"texture":"#0"},"west":{"uv":[1.4375,3.5625,1.5625,3.9375],"rotation":90,"texture":"#0"}}},{"from":[4.1106,18.04828,1.6196],"to":[8.1106,20.04828,10.6196],"rotation":{"angle":-45,"axis":"y","origin":[6.1106,19.04828,6.8696]},"faces":{"north":{"uv":[0.875,3.5,0.9375,3.25],"rotation":90,"texture":"#0"},"east":{"uv":[0.375,3.25,0.9375,3.3125],"texture":"#0"},"south":{"uv":[0.375,3.5,0.4375,3.25],"rotation":270,"texture":"#0"},"west":{"uv":[0.375,3.4375,0.9375,3.5],"rotation":180,"texture":"#0"},"up":{"uv":[0.375,3.5,0.9375,3.25],"rotation":270,"texture":"#0"},"down":{"uv":[0.375,3.25,0.9375,3.5],"rotation":90,"texture":"#0"}}},{"from":[4.1106,19.04828,1.6196],"to":[9.1106,19.04828,13.6196],"rotation":{"angle":-45,"axis":"y","origin":[6.1106,19.04828,6.8696]},"faces":{"up":{"uv":[0.1875,3.5,0.9375,3.1875],"rotation":270,"texture":"#0"},"down":{"uv":[0.1875,3.1875,0.9375,3.5],"rotation":90,"texture":"#0"}}},{"from":[5.6106,16.04828,5.1196],"to":[5.6106,22.04828,7.1196],"rotation":{"angle":-45,"axis":"y","origin":[6.1106,19.04828,6.8696]},"faces":{"east":{"uv":[0.5,3.5625,0.625,3.9375],"texture":"#0"},"west":{"uv":[0.5,3.5625,0.625,3.9375],"rotation":180,"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[75,45,0],"translation":[2.75,2.5,2],"scale":[0.375,0.375,0.375]},"thirdperson_lefthand":{"rotation":[75,45,0],"translation":[2.25,2,1.75],"scale":[0.375,0.375,0.375]},"firstperson_righthand":{"rotation":[0,75.75,0],"translation":[5.25,-0.75,1.5],"scale":[0.4,0.4,0.4]},"firstperson_lefthand":{"rotation":[0,75.75,0],"translation":[5.25,-0.5,2],"scale":[0.4,0.4,0.4]},"ground":{"translation":[0,3,0],"scale":[0.25,0.25,0.25]},"gui":{"rotation":[30,225,0],"translation":[0.25,-0.25,0],"scale":[0.49219,0.49219,0.49219]},"head":{"translation":[0,12.75,0],"scale":[0.79492,0.79492,0.79492]},"fixed":{"rotation":[-90,0,0],"translation":[0,0,-16],"scale":[2.00195,2.00195,2.00195]}},"groups":[{"name":"group","origin":[8,8,8],"color":0,"boneType":"","children":[0]},{"name":"fisherman_hanging_fish","origin":[8,8,8],"color":0,"boneType":"","children":[{"name":"group","origin":[8,8,8],"color":0,"boneType":"","children":[{"name":"group","origin":[8,8,8],"color":0,"boneType":"","children":[1,2,3]},{"name":"group","origin":[8,8,8],"color":0,"boneType":"","children":[4,5,6]},{"name":"group","origin":[8,8,8],"color":0,"boneType":"","children":[7,8,9]},{"name":"group","origin":[8,8,8],"color":0,"boneType":"","children":[10,11,12]}]}]}],"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fish_rack.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fish_rack.json new file mode 100644 index 000000000..cbb5e887c --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fish_rack.json @@ -0,0 +1 @@ +{"credit":"Made with Blockbench","texture_size":[256,256],"textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[14,0,-5],"to":[16,14,-3],"rotation":{"angle":0,"axis":"x","origin":[15,7.5,-4]},"faces":{"north":{"uv":[0.125,12.9375,0.0625,13.8125],"texture":"#0"},"east":{"uv":[0,12.9375,0.125,13.8125],"texture":"#0"},"south":{"uv":[0.0625,12.9375,0,13.8125],"texture":"#0"},"west":{"uv":[0.125,12.9375,0,13.8125],"texture":"#0"},"down":{"uv":[0,13.875,0.125,14],"rotation":90,"texture":"#0"}}},{"from":[-16,0,-5],"to":[-14,14,-3],"rotation":{"angle":0,"axis":"x","origin":[-15,7,-4]},"faces":{"north":{"uv":[0.0625,12.9375,0.125,13.8125],"texture":"#0"},"east":{"uv":[0,12.9375,0.125,13.8125],"texture":"#0"},"south":{"uv":[0,12.9375,0.0625,13.8125],"texture":"#0"},"west":{"uv":[0.125,12.9375,0,13.8125],"texture":"#0"},"down":{"uv":[0,14,0.125,13.875],"rotation":90,"texture":"#0"}}},{"from":[-16,0,14],"to":[-14,14,16],"rotation":{"angle":0,"axis":"x","origin":[-15,7,15]},"faces":{"north":{"uv":[0.0625,12.9375,0,13.8125],"texture":"#0"},"east":{"uv":[0.125,12.9375,0,13.8125],"texture":"#0"},"south":{"uv":[0.125,12.9375,0.0625,13.8125],"texture":"#0"},"west":{"uv":[0,12.9375,0.125,13.8125],"texture":"#0"},"down":{"uv":[0.125,14,0,13.875],"rotation":90,"texture":"#0"}}},{"from":[14,0,14],"to":[16,14,16],"rotation":{"angle":0,"axis":"x","origin":[15,7.5,15]},"faces":{"north":{"uv":[0,12.9375,0.0625,13.8125],"texture":"#0"},"east":{"uv":[0.125,12.9375,0,13.8125],"texture":"#0"},"south":{"uv":[0.0625,12.9375,0.125,13.8125],"texture":"#0"},"west":{"uv":[0,12.9375,0.125,13.8125],"texture":"#0"},"down":{"uv":[0.125,13.875,0,14],"rotation":90,"texture":"#0"}}},{"from":[-16,4,-3],"to":[-14,6,14],"rotation":{"angle":0,"axis":"x","origin":[-15,5,4]},"faces":{"east":{"uv":[0.1875,13.125,1.25,13.25],"rotation":180,"texture":"#0"},"west":{"uv":[0.1875,13.125,1.25,13.25],"rotation":180,"texture":"#0"},"up":{"uv":[0.1875,13.1875,1.25,13.25],"rotation":270,"texture":"#0"},"down":{"uv":[0.1875,13.125,1.25,13.1875],"rotation":270,"texture":"#0"}}},{"from":[14,4,-3],"to":[16,6,14],"rotation":{"angle":0,"axis":"x","origin":[15,5,4]},"faces":{"east":{"uv":[0.1875,13.125,1.25,13.25],"rotation":180,"texture":"#0"},"west":{"uv":[0.1875,13.125,1.25,13.25],"rotation":180,"texture":"#0"},"up":{"uv":[0.1875,13.1875,1.25,13.25],"rotation":270,"texture":"#0"},"down":{"uv":[0.1875,13.125,1.25,13.1875],"rotation":270,"texture":"#0"}}},{"from":[-14,4,-5],"to":[14,6,-3],"rotation":{"angle":0,"axis":"y","origin":[5.5,5,-4]},"faces":{"north":{"uv":[0.1875,12.9375,1.9375,13.0625],"rotation":180,"texture":"#0"},"south":{"uv":[0.1875,12.9375,1.9375,13.0625],"rotation":180,"texture":"#0"},"up":{"uv":[0.1875,13,1.9375,13.0625],"rotation":180,"texture":"#0"},"down":{"uv":[0.1875,12.9375,1.9375,13],"rotation":180,"texture":"#0"}}},{"from":[-14,4,14],"to":[14,6,16],"rotation":{"angle":0,"axis":"y","origin":[5.5,5,15]},"faces":{"north":{"uv":[0.1875,12.9375,1.9375,13.0625],"rotation":180,"texture":"#0"},"south":{"uv":[0.1875,12.9375,1.9375,13.0625],"rotation":180,"texture":"#0"},"up":{"uv":[0.1875,13,1.9375,13.0625],"rotation":180,"texture":"#0"},"down":{"uv":[0.1875,12.9375,1.9375,13],"rotation":180,"texture":"#0"}}},{"from":[-13,9,-4],"to":[13,11,-4],"rotation":{"angle":22.5,"axis":"z","origin":[0,10,-4]},"faces":{"north":{"uv":[1.3125,11.375,2.9375,11.5],"texture":"#0"},"south":{"uv":[1.3125,11.375,2.9375,11.5],"texture":"#0"}}},{"from":[-13,9,-3.94531],"to":[13,11,-3.94531],"rotation":{"angle":-22.5,"axis":"z","origin":[0,10,-3.94531]},"faces":{"north":{"uv":[1.3125,11.375,2.9375,11.5],"texture":"#0"},"south":{"uv":[1.3125,11.375,2.9375,11.5],"texture":"#0"}}},{"from":[-13,9,15],"to":[13,11,15],"rotation":{"angle":22.5,"axis":"z","origin":[0,10,15]},"faces":{"north":{"uv":[2.9375,11.375,1.3125,11.5],"texture":"#0"},"south":{"uv":[2.9375,11.375,1.3125,11.5],"texture":"#0"}}},{"from":[-13,9,14.94531],"to":[13,11,14.94531],"rotation":{"angle":-22.5,"axis":"z","origin":[0,10,14.94531]},"faces":{"north":{"uv":[2.9375,11.375,1.3125,11.5],"texture":"#0"},"south":{"uv":[2.9375,11.375,1.3125,11.5],"texture":"#0"}}},{"from":[-16,14,-5],"to":[-14,16,16],"rotation":{"angle":0,"axis":"x","origin":[0,15,5.5]},"faces":{"north":{"uv":[1.8125,11.5625,1.9375,11.625],"rotation":90,"texture":"#0"},"east":{"uv":[1.8125,11.5625,1.875,12.875],"rotation":270,"texture":"#0"},"south":{"uv":[1.8125,11.5625,1.9375,11.625],"rotation":90,"texture":"#0"},"west":{"uv":[1.875,11.5625,1.9375,12.875],"rotation":90,"texture":"#0"},"up":{"uv":[1.8125,11.5625,1.9375,12.875],"rotation":180,"texture":"#0"},"down":{"uv":[1.9375,11.5625,1.8125,12.875],"texture":"#0"}}},{"from":[14,14,-5],"to":[16,16,16],"rotation":{"angle":0,"axis":"x","origin":[0,15,5.5]},"faces":{"north":{"uv":[1.8125,11.625,1.9375,11.5625],"rotation":90,"texture":"#0"},"east":{"uv":[1.875,12.875,1.9375,11.5625],"rotation":90,"texture":"#0"},"south":{"uv":[1.8125,11.625,1.9375,11.5625],"rotation":90,"texture":"#0"},"west":{"uv":[1.8125,12.875,1.875,11.5625],"rotation":270,"texture":"#0"},"up":{"uv":[1.9375,11.5625,1.8125,12.875],"rotation":180,"texture":"#0"},"down":{"uv":[1.8125,11.5625,1.9375,12.875],"texture":"#0"}}},{"from":[-14,14.999,-3.5],"to":[14,14.999,14.5],"rotation":{"angle":0,"axis":"x","origin":[0,15.35255,5.35355]},"faces":{"up":{"uv":[0,11.5625,1.75,12.6875],"rotation":180,"texture":"#0"},"down":{"uv":[0,11.5625,1.75,12.6875],"texture":"#0"}}},{"from":[-14,14,-5],"to":[14,16,-3],"rotation":{"angle":0,"axis":"x","origin":[0,15,5.5]},"faces":{"north":{"uv":[0,12.8125,1.75,12.875],"rotation":180,"texture":"#0"},"south":{"uv":[0,12.75,1.75,12.8125],"texture":"#0"},"up":{"uv":[0,12.75,1.75,12.875],"rotation":180,"texture":"#0"},"down":{"uv":[0,12.75,1.75,12.875],"texture":"#0"}}},{"from":[-14,14,14],"to":[14,16,16],"rotation":{"angle":0,"axis":"x","origin":[0,15,5.5]},"faces":{"north":{"uv":[0,12.8125,1.75,12.75],"rotation":180,"texture":"#0"},"south":{"uv":[0,12.875,1.75,12.8125],"texture":"#0"},"up":{"uv":[1.75,12.75,0,12.875],"texture":"#0"},"down":{"uv":[1.75,12.75,0,12.875],"rotation":180,"texture":"#0"}}},{"from":[8.6106,15.54828,2.1196],"to":[12.6106,17.54828,11.1196],"rotation":{"angle":0,"axis":"y","origin":[-0.3894,16.54828,4.3696]},"faces":{"north":{"uv":[0.375,2.5625,0.4375,2.3125],"rotation":90,"texture":"#0"},"east":{"uv":[0.375,2.3125,0.9375,2.375],"rotation":180,"texture":"#0"},"south":{"uv":[0.875,2.5625,0.9375,2.3125],"rotation":270,"texture":"#0"},"west":{"uv":[0.375,2.5,0.9375,2.5625],"texture":"#0"},"up":{"uv":[0.375,2.3125,0.9375,2.5625],"rotation":90,"texture":"#0"},"down":{"uv":[0.375,2.5625,0.9375,2.3125],"rotation":270,"texture":"#0"}}},{"from":[8.6106,16.54828,-0.8804],"to":[13.6106,16.54828,11.1196],"rotation":{"angle":0,"axis":"y","origin":[-0.3894,16.54828,4.3696]},"faces":{"up":{"uv":[0.1875,2.25,0.9375,2.5625],"rotation":90,"texture":"#0"},"down":{"uv":[0.1875,2.5625,0.9375,2.25],"rotation":270,"texture":"#0"}}},{"from":[10.1106,13.54828,5.6196],"to":[10.1106,19.54828,7.6196],"rotation":{"angle":0,"axis":"y","origin":[-0.3894,16.54828,4.3696]},"faces":{"east":{"uv":[0.5,2.625,0.625,3],"rotation":180,"texture":"#0"},"west":{"uv":[0.5,2.625,0.625,3],"texture":"#0"}}},{"from":[-6.3894,15.54828,3.1196],"to":[-2.3894,17.54828,12.1196],"rotation":{"angle":0,"axis":"y","origin":[-0.3894,16.54828,8.3696]},"faces":{"north":{"uv":[1.3125,2.5625,1.375,2.3125],"rotation":90,"texture":"#0"},"east":{"uv":[1.3125,2.3125,1.875,2.375],"rotation":180,"texture":"#0"},"south":{"uv":[1.8125,2.5625,1.875,2.3125],"rotation":270,"texture":"#0"},"west":{"uv":[1.3125,2.5,1.875,2.5625],"texture":"#0"},"up":{"uv":[1.3125,2.3125,1.875,2.5625],"rotation":90,"texture":"#0"},"down":{"uv":[1.3125,2.5625,1.875,2.3125],"rotation":270,"texture":"#0"}}},{"from":[-6.3894,16.54828,0.1196],"to":[-1.3894,16.54828,12.1196],"rotation":{"angle":0,"axis":"y","origin":[-0.3894,16.54828,8.3696]},"faces":{"up":{"uv":[1.125,2.25,1.875,2.5625],"rotation":90,"texture":"#0"},"down":{"uv":[1.125,2.5625,1.875,2.25],"rotation":270,"texture":"#0"}}},{"from":[-4.8894,13.54828,6.6196],"to":[-4.8894,19.54828,8.6196],"rotation":{"angle":0,"axis":"y","origin":[-0.3894,16.54828,8.3696]},"faces":{"east":{"uv":[1.4375,2.625,1.5625,3],"rotation":180,"texture":"#0"},"west":{"uv":[1.4375,2.625,1.5625,3],"texture":"#0"}}},{"from":[1.6106,15.54828,-0.8804],"to":[5.6106,17.54828,8.1196],"rotation":{"angle":0,"axis":"y","origin":[-0.3894,16.54828,4.3696]},"faces":{"north":{"uv":[1.3125,3.5,1.375,3.25],"rotation":90,"texture":"#0"},"east":{"uv":[1.3125,3.25,1.875,3.3125],"rotation":180,"texture":"#0"},"south":{"uv":[1.8125,3.5,1.875,3.25],"rotation":270,"texture":"#0"},"west":{"uv":[1.3125,3.4375,1.875,3.5],"texture":"#0"},"up":{"uv":[1.3125,3.25,1.875,3.5],"rotation":90,"texture":"#0"},"down":{"uv":[1.3125,3.5,1.875,3.25],"rotation":270,"texture":"#0"}}},{"from":[1.6106,16.54828,-3.8804],"to":[6.6106,16.54828,8.1196],"rotation":{"angle":0,"axis":"y","origin":[-0.3894,16.54828,4.3696]},"faces":{"up":{"uv":[1.125,3.1875,1.875,3.5],"rotation":90,"texture":"#0"},"down":{"uv":[1.125,3.5,1.875,3.1875],"rotation":270,"texture":"#0"}}},{"from":[3.1106,13.54828,2.6196],"to":[3.1106,19.54828,4.6196],"rotation":{"angle":0,"axis":"y","origin":[-0.3894,16.54828,4.3696]},"faces":{"east":{"uv":[1.4375,3.5625,1.5625,3.9375],"rotation":180,"texture":"#0"},"west":{"uv":[1.4375,3.5625,1.5625,3.9375],"texture":"#0"}}},{"from":[-13.3894,15.54828,0.1196],"to":[-9.3894,17.54828,9.1196],"rotation":{"angle":0,"axis":"y","origin":[-0.3894,16.54828,2.3696]},"faces":{"north":{"uv":[0.375,3.5,0.4375,3.25],"rotation":90,"texture":"#0"},"east":{"uv":[0.375,3.25,0.9375,3.3125],"rotation":180,"texture":"#0"},"south":{"uv":[0.875,3.5,0.9375,3.25],"rotation":270,"texture":"#0"},"west":{"uv":[0.375,3.4375,0.9375,3.5],"texture":"#0"},"up":{"uv":[0.375,3.25,0.9375,3.5],"rotation":90,"texture":"#0"},"down":{"uv":[0.375,3.5,0.9375,3.25],"rotation":270,"texture":"#0"}}},{"from":[-13.3894,16.54828,-2.8804],"to":[-8.3894,16.54828,9.1196],"rotation":{"angle":0,"axis":"y","origin":[-0.3894,16.54828,2.3696]},"faces":{"up":{"uv":[0.1875,3.1875,0.9375,3.5],"rotation":90,"texture":"#0"},"down":{"uv":[0.1875,3.5,0.9375,3.1875],"rotation":270,"texture":"#0"}}},{"from":[-11.8894,13.54828,3.6196],"to":[-11.8894,19.54828,5.6196],"rotation":{"angle":0,"axis":"y","origin":[-0.3894,16.54828,2.3696]},"faces":{"east":{"uv":[0.5,3.5625,0.625,3.9375],"rotation":180,"texture":"#0"},"west":{"uv":[0.5,3.5625,0.625,3.9375],"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[75,45,0],"translation":[4.5,6.75,1.25],"scale":[0.375,0.375,0.375]},"thirdperson_lefthand":{"rotation":[75,45,0],"translation":[0.75,3.75,2.75],"scale":[0.375,0.375,0.375]},"firstperson_righthand":{"rotation":[0,75.75,0],"translation":[3,1.75,1.5],"scale":[0.18906,0.18906,0.18906]},"firstperson_lefthand":{"rotation":[0,75.75,0],"translation":[3,1.75,4.5],"scale":[0.18906,0.18906,0.18906]},"ground":{"translation":[2.25,3,0],"scale":[0.25,0.25,0.25]},"gui":{"rotation":[30,225,0],"translation":[-3,-0.75,0],"scale":[0.4082,0.4082,0.4082]},"head":{"translation":[0,12.75,0],"scale":[0.79492,0.79492,0.79492]},"fixed":{"rotation":[-90,0,0],"translation":[0,0,-16],"scale":[2.00195,2.00195,2.00195]}},"groups":[{"name":"group","origin":[-15,-4.91852,14.49569],"color":0,"boneType":"","children":[0,1,2,3,4,5,6,7,8,9,10,11]},{"name":"group","origin":[8,8,8],"color":0,"boneType":"","children":[12,13,14,15,16]},{"name":"fisherman_hanging_fish","origin":[8,8,8],"color":0,"boneType":"","children":[{"name":"group","origin":[8,8,8],"color":0,"boneType":"","children":[17,18,19]},{"name":"group","origin":[8,8,8],"color":0,"boneType":"","children":[20,21,22]},{"name":"group","origin":[8,8,8],"color":0,"boneType":"","children":[23,24,25]},{"name":"group","origin":[8,8,8],"color":0,"boneType":"","children":[26,27,28]}]}],"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fishing_pole.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fishing_pole.json new file mode 100644 index 000000000..ca1286381 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fishing_pole.json @@ -0,0 +1 @@ +{"credit":"Made with Blockbench","textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[-2.22266,1.02734,6.5],"to":[16.77734,2.02734,7.5],"rotation":{"angle":0,"axis":"y","origin":[5.27734,1.27734,7]},"faces":{"north":{"uv":[2.6875,4.4375,2.75,5.625],"rotation":270,"texture":"#0"},"east":{"uv":[2.6875,4.4375,2.75,4.5],"texture":"#0"},"south":{"uv":[2.6875,4.4375,2.75,5.625],"rotation":90,"texture":"#0"},"west":{"uv":[2.6875,5.5625,2.75,5.625],"texture":"#0"},"up":{"uv":[2.6875,4.4375,2.75,5.625],"rotation":90,"texture":"#0"},"down":{"uv":[2.6875,4.4375,2.75,5.625],"rotation":90,"texture":"#0"}}},{"from":[1.77734,1.52734,7.5],"to":[17.77734,1.52734,9.5],"rotation":{"angle":0,"axis":"y","origin":[9.67159,1.57734,9]},"faces":{"up":{"uv":[3.0625,4.4375,3.1875,5.4375],"rotation":90,"texture":"#0"},"down":{"uv":[3.1875,4.4375,3.0625,5.4375],"rotation":90,"texture":"#0"}}},{"from":[1.77734,0.57421,6],"to":[2.77734,2.57421,8],"rotation":{"angle":0,"axis":"y","origin":[2.27734,1.53905,7]},"faces":{"north":{"uv":[2.8125,4.4375,2.93311,4.5],"rotation":270,"texture":"#0"},"east":{"uv":[2.9375,4.4375,2.8125,4.49561],"texture":"#0"},"south":{"uv":[2.875,4.4375,2.93311,4.5],"rotation":90,"texture":"#0"},"west":{"uv":[2.9375,4.4375,2.8125,4.49561],"rotation":180,"texture":"#0"},"up":{"uv":[2.8125,4.4375,2.9375,4.5],"rotation":90,"texture":"#0"},"down":{"uv":[2.9375,4.4375,2.8125,4.5],"rotation":90,"texture":"#0"}}},{"from":[6.77734,0.57421,6],"to":[7.77734,2.57421,8],"rotation":{"angle":0,"axis":"y","origin":[7.27734,1.53905,7]},"faces":{"north":{"uv":[2.8125,4.4375,2.87061,4.5],"rotation":270,"texture":"#0"},"east":{"uv":[2.9375,4.4375,2.8125,4.49561],"texture":"#0"},"south":{"uv":[2.875,4.4375,2.93311,4.5],"rotation":90,"texture":"#0"},"west":{"uv":[2.9375,4.4375,2.8125,4.49561],"rotation":180,"texture":"#0"},"up":{"uv":[2.8125,4.4375,2.9375,4.5],"rotation":90,"texture":"#0"},"down":{"uv":[2.9375,4.4375,2.8125,4.5],"rotation":90,"texture":"#0"}}},{"from":[11.77734,0.57421,6],"to":[12.77734,2.57421,8],"rotation":{"angle":0,"axis":"y","origin":[12.27734,1.53905,7]},"faces":{"north":{"uv":[2.8125,4.4375,2.87061,4.5],"rotation":270,"texture":"#0"},"east":{"uv":[2.9375,4.4375,2.8125,4.49561],"texture":"#0"},"south":{"uv":[2.875,4.4375,2.93311,4.5],"rotation":90,"texture":"#0"},"west":{"uv":[2.9375,4.4375,2.8125,4.49561],"rotation":180,"texture":"#0"},"up":{"uv":[2.8125,4.4375,2.9375,4.5],"rotation":90,"texture":"#0"},"down":{"uv":[2.9375,4.4375,2.8125,4.5],"rotation":90,"texture":"#0"}}},{"from":[16.77734,0.57421,6],"to":[17.77734,2.57421,8],"rotation":{"angle":0,"axis":"y","origin":[17.27734,1.53905,7]},"faces":{"north":{"uv":[2.8125,4.4375,2.87061,4.5],"rotation":270,"texture":"#0"},"east":{"uv":[2.9375,4.4375,2.8125,4.49561],"texture":"#0"},"south":{"uv":[2.875,4.4375,2.93311,4.5],"rotation":90,"texture":"#0"},"west":{"uv":[2.9375,4.4375,2.8125,4.49561],"rotation":180,"texture":"#0"},"up":{"uv":[2.8125,4.4375,2.9375,4.5],"rotation":90,"texture":"#0"},"down":{"uv":[2.9375,4.4375,2.8125,4.5],"rotation":90,"texture":"#0"}}},{"from":[1.16488,0.02734,5.06127],"to":[3.16488,3.02734,7.06127],"rotation":{"angle":22.5,"axis":"y","origin":[2.16488,1.52734,6.06127]},"faces":{"north":{"uv":[2.8125,4.6875,3,4.5625],"rotation":90,"texture":"#0"},"east":{"uv":[2.8125,4.6875,3,4.5625],"rotation":270,"texture":"#0"},"south":{"uv":[2.8125,4.625,3,4.6875],"rotation":270,"texture":"#0"},"west":{"uv":[2.8125,4.625,3,4.6875],"rotation":270,"texture":"#0"},"up":{"uv":[2.8125,5.125,2.9375,5.25],"rotation":90,"texture":"#0"},"down":{"uv":[2.8125,5.125,2.9375,5.25],"rotation":180,"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[180,0,-90],"translation":[5.75,6.75,0.25],"scale":[0.85,0.85,0.85]},"thirdperson_lefthand":{"rotation":[180,0,90],"translation":[-5.25,6.75,0.25],"scale":[0.85,0.85,0.85]},"firstperson_righthand":{"rotation":[136.13,-13.99,-92.36],"translation":[8.38,3.2,-4.12],"scale":[0.68,0.68,0.68]},"firstperson_lefthand":{"rotation":[134.26,-1.41,79.34],"translation":[0.88,3.2,-3.62],"scale":[0.68,0.68,0.68]},"ground":{"translation":[0,5,0],"scale":[0.43945,0.43945,0.43945]},"gui":{"rotation":[112.78,36.47,-23.17],"translation":[2.25,-1.5,0],"scale":[0.9668,0.9668,0.9668]},"head":{"translation":[0,12.75,0],"scale":[0.79492,0.79492,0.79492]},"fixed":{"rotation":[-90,0,0],"translation":[0,0,-16],"scale":[2.00195,2.00195,2.00195]}},"groups":[{"name":"group","origin":[8,19.50355,8],"color":0,"children":[0,1,2,3,4,5,6]}],"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fishingpole_rack.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fishingpole_rack.json new file mode 100644 index 000000000..02565735a --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_fishingpole_rack.json @@ -0,0 +1 @@ +{"credit":"Made with Blockbench","texture_size":[256,256],"textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[11.52734,3,8.5],"to":[12.52734,22,9.5],"rotation":{"angle":0,"axis":"y","origin":[12.27734,10.5,9]},"faces":{"north":{"uv":[2.6875,4.4375,2.75,5.625],"texture":"#0"},"east":{"uv":[2.6875,4.4375,2.75,5.625],"texture":"#0"},"south":{"uv":[2.6875,4.4375,2.75,5.625],"texture":"#0"},"west":{"uv":[2.6875,4.4375,2.75,5.625],"texture":"#0"},"up":{"uv":[2.6875,4.4375,2.75,4.5],"rotation":270,"texture":"#0"},"down":{"uv":[2.6875,5.5625,2.75,5.625],"rotation":270,"texture":"#0"}}},{"from":[12.02734,7,9.5],"to":[12.02734,23,11.5],"rotation":{"angle":0,"axis":"y","origin":[11.97734,14.89425,11]},"faces":{"east":{"uv":[3.1875,4.4375,3.0625,5.4375],"texture":"#0"},"west":{"uv":[3.0625,4.4375,3.1875,5.4375],"texture":"#0"}}},{"from":[10.98047,7,8],"to":[12.98047,8,10],"rotation":{"angle":0,"axis":"y","origin":[12.01563,7.5,9]},"faces":{"north":{"uv":[2.8125,4.4375,2.93311,4.5],"texture":"#0"},"east":{"uv":[2.9375,4.4375,2.8125,4.5],"texture":"#0"},"south":{"uv":[2.875,4.4375,2.93311,4.5],"texture":"#0"},"west":{"uv":[2.8125,4.4375,2.9375,4.5],"texture":"#0"},"up":{"uv":[2.9375,4.4375,2.8125,4.49561],"rotation":270,"texture":"#0"},"down":{"uv":[2.9375,4.4375,2.8125,4.49561],"rotation":90,"texture":"#0"}}},{"from":[10.98047,12,8],"to":[12.98047,13,10],"rotation":{"angle":0,"axis":"y","origin":[12.01563,12.5,9]},"faces":{"north":{"uv":[2.8125,4.4375,2.87061,4.5],"texture":"#0"},"east":{"uv":[2.9375,4.4375,2.8125,4.5],"texture":"#0"},"south":{"uv":[2.875,4.4375,2.93311,4.5],"texture":"#0"},"west":{"uv":[2.8125,4.4375,2.9375,4.5],"texture":"#0"},"up":{"uv":[2.9375,4.4375,2.8125,4.49561],"rotation":270,"texture":"#0"},"down":{"uv":[2.9375,4.4375,2.8125,4.49561],"rotation":90,"texture":"#0"}}},{"from":[10.98047,17,8],"to":[12.98047,18,10],"rotation":{"angle":0,"axis":"y","origin":[12.01563,17.5,9]},"faces":{"north":{"uv":[2.8125,4.4375,2.87061,4.5],"texture":"#0"},"east":{"uv":[2.9375,4.4375,2.8125,4.5],"texture":"#0"},"south":{"uv":[2.875,4.4375,2.93311,4.5],"texture":"#0"},"west":{"uv":[2.8125,4.4375,2.9375,4.5],"texture":"#0"},"up":{"uv":[2.9375,4.4375,2.8125,4.49561],"rotation":270,"texture":"#0"},"down":{"uv":[2.9375,4.4375,2.8125,4.49561],"rotation":90,"texture":"#0"}}},{"from":[10.98047,22,8],"to":[12.98047,23,10],"rotation":{"angle":0,"axis":"y","origin":[12.01563,22.5,9]},"faces":{"north":{"uv":[2.8125,4.4375,2.87061,4.5],"texture":"#0"},"east":{"uv":[2.9375,4.4375,2.8125,4.5],"texture":"#0"},"south":{"uv":[2.875,4.4375,2.93311,4.5],"texture":"#0"},"west":{"uv":[2.8125,4.4375,2.9375,4.5],"texture":"#0"},"up":{"uv":[2.9375,4.4375,2.8125,4.49561],"rotation":270,"texture":"#0"},"down":{"uv":[2.9375,4.4375,2.8125,4.49561],"rotation":90,"texture":"#0"}}},{"from":[10.52734,6.38754,7.06127],"to":[13.52734,8.38754,9.06127],"rotation":{"angle":22.5,"axis":"x","origin":[12.02734,7.38754,8.06127]},"faces":{"north":{"uv":[2.8125,4.6875,3,4.5625],"rotation":180,"texture":"#0"},"east":{"uv":[2.8125,5.125,2.9375,5.25],"rotation":90,"texture":"#0"},"south":{"uv":[2.8125,4.625,3,4.6875],"rotation":180,"texture":"#0"},"west":{"uv":[2.8125,5.125,2.9375,5.25],"texture":"#0"},"up":{"uv":[2.8125,4.6875,3,4.5625],"rotation":180,"texture":"#0"},"down":{"uv":[2.8125,4.625,3,4.6875],"rotation":180,"texture":"#0"}}},{"from":[3.52734,3,8.5],"to":[4.52734,22,9.5],"rotation":{"angle":0,"axis":"y","origin":[4.27734,10.5,9]},"faces":{"north":{"uv":[2.6875,4.4375,2.75,5.625],"texture":"#0"},"east":{"uv":[2.6875,4.4375,2.75,5.625],"texture":"#0"},"south":{"uv":[2.6875,4.4375,2.75,5.625],"texture":"#0"},"west":{"uv":[2.6875,4.4375,2.75,5.625],"texture":"#0"},"up":{"uv":[2.6875,4.4375,2.75,4.5],"rotation":270,"texture":"#0"},"down":{"uv":[2.6875,5.5625,2.75,5.625],"rotation":270,"texture":"#0"}}},{"from":[4.02734,7,9.5],"to":[4.02734,23,11.5],"rotation":{"angle":0,"axis":"y","origin":[3.97734,14.89425,11]},"faces":{"east":{"uv":[3.1875,4.4375,3.0625,5.4375],"texture":"#0"},"west":{"uv":[3.0625,4.4375,3.1875,5.4375],"texture":"#0"}}},{"from":[2.98047,7,8],"to":[4.98047,8,10],"rotation":{"angle":0,"axis":"y","origin":[4.01563,7.5,9]},"faces":{"north":{"uv":[2.8125,4.4375,2.93311,4.5],"texture":"#0"},"east":{"uv":[2.9375,4.4375,2.8125,4.5],"texture":"#0"},"south":{"uv":[2.875,4.4375,2.93311,4.5],"texture":"#0"},"west":{"uv":[2.8125,4.4375,2.9375,4.5],"texture":"#0"},"up":{"uv":[2.9375,4.4375,2.8125,4.49561],"rotation":270,"texture":"#0"},"down":{"uv":[2.9375,4.4375,2.8125,4.49561],"rotation":90,"texture":"#0"}}},{"from":[2.98047,12,8],"to":[4.98047,13,10],"rotation":{"angle":0,"axis":"y","origin":[4.01563,12.5,9]},"faces":{"north":{"uv":[2.8125,4.1875,2.87061,4.25],"texture":"#0"},"east":{"uv":[2.9375,4.1875,2.8125,4.25],"texture":"#0"},"south":{"uv":[2.875,4.1875,2.93311,4.25],"texture":"#0"},"west":{"uv":[2.8125,4.1875,2.9375,4.25],"texture":"#0"},"up":{"uv":[2.9375,4.1875,2.8125,4.24561],"rotation":270,"texture":"#0"},"down":{"uv":[2.9375,4.1875,2.8125,4.24561],"rotation":90,"texture":"#0"}}},{"from":[2.98047,17,8],"to":[4.98047,18,10],"rotation":{"angle":0,"axis":"y","origin":[4.01563,17.5,9]},"faces":{"north":{"uv":[2.8125,4.1875,2.87061,4.25],"texture":"#0"},"east":{"uv":[2.9375,4.1875,2.8125,4.25],"texture":"#0"},"south":{"uv":[2.875,4.1875,2.93311,4.25],"texture":"#0"},"west":{"uv":[2.8125,4.1875,2.9375,4.25],"texture":"#0"},"up":{"uv":[2.9375,4.1875,2.8125,4.24561],"rotation":270,"texture":"#0"},"down":{"uv":[2.9375,4.1875,2.8125,4.24561],"rotation":90,"texture":"#0"}}},{"from":[2.98047,22,8],"to":[4.98047,23,10],"rotation":{"angle":0,"axis":"y","origin":[4.01563,22.5,9]},"faces":{"north":{"uv":[2.8125,4.1875,2.87061,4.25],"texture":"#0"},"east":{"uv":[2.9375,4.1875,2.8125,4.25],"texture":"#0"},"south":{"uv":[2.875,4.1875,2.93311,4.25],"texture":"#0"},"west":{"uv":[2.8125,4.1875,2.9375,4.25],"texture":"#0"},"up":{"uv":[2.9375,4.1875,2.8125,4.24561],"rotation":270,"texture":"#0"},"down":{"uv":[2.9375,4.1875,2.8125,4.24561],"rotation":90,"texture":"#0"}}},{"from":[2.52734,6.38754,7.06127],"to":[5.52734,8.38754,9.06127],"rotation":{"angle":22.5,"axis":"x","origin":[4.02734,7.38754,8.06127]},"faces":{"north":{"uv":[2.8125,5.0625,3,4.9375],"rotation":180,"texture":"#0"},"east":{"uv":[2.8125,5.125,2.9375,5.25],"rotation":90,"texture":"#0"},"south":{"uv":[2.8125,5,3,5.0625],"rotation":180,"texture":"#0"},"west":{"uv":[2.8125,5.125,2.9375,5.25],"texture":"#0"},"up":{"uv":[2.8125,5.0625,3,4.9375],"rotation":180,"texture":"#0"},"down":{"uv":[2.8125,5,3,5.0625],"rotation":180,"texture":"#0"}}},{"from":[7.52734,3,8.5],"to":[8.52734,22,9.5],"rotation":{"angle":0,"axis":"y","origin":[8.27734,10.5,9]},"faces":{"north":{"uv":[2.6875,4.4375,2.75,5.625],"texture":"#0"},"east":{"uv":[2.6875,4.4375,2.75,5.625],"texture":"#0"},"south":{"uv":[2.6875,4.4375,2.75,5.625],"texture":"#0"},"west":{"uv":[2.6875,4.4375,2.75,5.625],"texture":"#0"},"up":{"uv":[2.6875,4.4375,2.75,4.5],"rotation":270,"texture":"#0"},"down":{"uv":[2.6875,5.5625,2.75,5.625],"rotation":270,"texture":"#0"}}},{"from":[8.02734,7,9.5],"to":[8.02734,23,11.5],"rotation":{"angle":0,"axis":"y","origin":[7.97734,14.89425,11]},"faces":{"east":{"uv":[3.1875,4.4375,3.0625,5.4375],"texture":"#0"},"west":{"uv":[3.0625,4.4375,3.1875,5.4375],"texture":"#0"}}},{"from":[6.98047,7,8],"to":[8.98047,8,10],"rotation":{"angle":0,"axis":"y","origin":[8.01563,7.5,9]},"faces":{"north":{"uv":[2.8125,4.3125,2.93311,4.375],"texture":"#0"},"east":{"uv":[2.9375,4.3125,2.8125,4.375],"texture":"#0"},"south":{"uv":[2.875,4.3125,2.93311,4.375],"texture":"#0"},"west":{"uv":[2.8125,4.3125,2.9375,4.375],"texture":"#0"},"up":{"uv":[2.9375,4.3125,2.8125,4.37061],"rotation":270,"texture":"#0"},"down":{"uv":[2.9375,4.3125,2.8125,4.37061],"rotation":90,"texture":"#0"}}},{"from":[6.98047,12,8],"to":[8.98047,13,10],"rotation":{"angle":0,"axis":"y","origin":[8.01563,12.5,9]},"faces":{"north":{"uv":[2.8125,4.3125,2.87061,4.375],"texture":"#0"},"east":{"uv":[2.9375,4.3125,2.8125,4.375],"texture":"#0"},"south":{"uv":[2.875,4.3125,2.93311,4.375],"texture":"#0"},"west":{"uv":[2.8125,4.3125,2.9375,4.375],"texture":"#0"},"up":{"uv":[2.9375,4.3125,2.8125,4.37061],"rotation":270,"texture":"#0"},"down":{"uv":[2.9375,4.3125,2.8125,4.37061],"rotation":90,"texture":"#0"}}},{"from":[6.98047,17,8],"to":[8.98047,18,10],"rotation":{"angle":0,"axis":"y","origin":[8.01563,17.5,9]},"faces":{"north":{"uv":[2.8125,4.3125,2.87061,4.375],"texture":"#0"},"east":{"uv":[2.9375,4.3125,2.8125,4.375],"texture":"#0"},"south":{"uv":[2.875,4.3125,2.93311,4.375],"texture":"#0"},"west":{"uv":[2.8125,4.3125,2.9375,4.375],"texture":"#0"},"up":{"uv":[2.9375,4.3125,2.8125,4.37061],"rotation":270,"texture":"#0"},"down":{"uv":[2.9375,4.3125,2.8125,4.37061],"rotation":90,"texture":"#0"}}},{"from":[6.98047,22,8],"to":[8.98047,23,10],"rotation":{"angle":0,"axis":"y","origin":[8.01563,22.5,9]},"faces":{"north":{"uv":[2.8125,4.3125,2.87061,4.375],"texture":"#0"},"east":{"uv":[2.9375,4.3125,2.8125,4.375],"texture":"#0"},"south":{"uv":[2.875,4.3125,2.93311,4.375],"texture":"#0"},"west":{"uv":[2.8125,4.3125,2.9375,4.375],"texture":"#0"},"up":{"uv":[2.9375,4.3125,2.8125,4.37061],"rotation":270,"texture":"#0"},"down":{"uv":[2.9375,4.3125,2.8125,4.37061],"rotation":90,"texture":"#0"}}},{"from":[6.52734,6.38754,7.06127],"to":[9.52734,8.38754,9.06127],"rotation":{"angle":22.5,"axis":"x","origin":[8.02734,7.38754,8.06127]},"faces":{"north":{"uv":[2.8125,4.875,3,4.75],"rotation":180,"texture":"#0"},"east":{"uv":[2.8125,5.125,2.9375,5.25],"rotation":90,"texture":"#0"},"south":{"uv":[2.8125,4.8125,3,4.875],"rotation":180,"texture":"#0"},"west":{"uv":[2.8125,5.125,2.9375,5.25],"texture":"#0"},"up":{"uv":[2.8125,4.875,3,4.75],"rotation":180,"texture":"#0"},"down":{"uv":[2.8125,4.8125,3,4.875],"rotation":180,"texture":"#0"}}},{"from":[13,0,3],"to":[16,2,15],"rotation":{"angle":0,"axis":"y","origin":[14,0,8]},"faces":{"north":{"uv":[3.4375,5.25,3.625,5.375],"texture":"#0"},"east":{"uv":[4.25,4.4375,4.125,5.1875],"rotation":90,"texture":"#0"},"south":{"uv":[3.625,5.25,3.4375,5.375],"texture":"#0"},"west":{"uv":[4.0625,4.4375,3.9375,5.1875],"rotation":90,"texture":"#0"},"up":{"uv":[3.625,4.4375,3.4375,5.1875],"texture":"#0"},"down":{"uv":[3.6875,4.4375,3.875,5.1875],"texture":"#0"}}},{"from":[0,0,3],"to":[3,2,15],"rotation":{"angle":0,"axis":"y","origin":[2,0,8]},"faces":{"north":{"uv":[3.625,5.25,3.4375,5.375],"texture":"#0"},"east":{"uv":[4.0625,5.1875,3.9375,4.4375],"rotation":90,"texture":"#0"},"south":{"uv":[3.4375,5.25,3.625,5.375],"texture":"#0"},"west":{"uv":[4.25,5.1875,4.125,4.4375],"rotation":90,"texture":"#0"},"up":{"uv":[3.4375,4.4375,3.625,5.1875],"texture":"#0"},"down":{"uv":[3.875,4.4375,3.6875,5.1875],"texture":"#0"}}},{"from":[0.5,2,5],"to":[2.5,12,13],"rotation":{"angle":0,"axis":"y","origin":[0.5,2,8]},"faces":{"north":{"uv":[5.5625,4.4375,5.4375,5.0625],"texture":"#0"},"east":{"uv":[4.875,4.4375,5.375,5.0625],"texture":"#0"},"south":{"uv":[5.4375,4.4375,5.5625,5.0625],"texture":"#0"},"west":{"uv":[4.3125,4.4375,4.8125,5.0625],"texture":"#0"},"up":{"uv":[4.3125,5.25,4.8125,5.125],"rotation":90,"texture":"#0"}}},{"from":[13.5,2,5],"to":[15.5,12,13],"rotation":{"angle":0,"axis":"y","origin":[15.5,2,8]},"faces":{"north":{"uv":[5.4375,4.4375,5.5625,5.0625],"texture":"#0"},"east":{"uv":[4.8125,4.4375,4.3125,5.0625],"texture":"#0"},"south":{"uv":[5.5625,4.4375,5.4375,5.0625],"texture":"#0"},"west":{"uv":[5.375,4.4375,4.875,5.0625],"texture":"#0"},"up":{"uv":[4.3125,5.125,4.8125,5.25],"rotation":90,"texture":"#0"}}},{"from":[2.5,2,6],"to":[13.5,3,12],"rotation":{"angle":0,"axis":"y","origin":[10,9,11]},"faces":{"north":{"uv":[3.6875,5.3125,4.375,5.375],"texture":"#0"},"south":{"uv":[3.6875,5.3125,4.375,5.375],"texture":"#0"},"up":{"uv":[3.6875,5.3125,4.375,5.6875],"texture":"#0"},"down":{"uv":[3.6875,5.3125,4.375,5.6875],"texture":"#0"}}},{"from":[2.5,9,6.5],"to":[13.5,11,7.5],"rotation":{"angle":0,"axis":"x","origin":[8,9.5,7]},"faces":{"north":{"uv":[3.6875,5.875,4.375,5.75],"rotation":180,"texture":"#0"},"south":{"uv":[3.6875,5.75,4.375,5.875],"texture":"#0"},"up":{"uv":[3.6875,5.75,4.375,5.8125],"rotation":180,"texture":"#0"},"down":{"uv":[3.6875,5.8125,4.375,5.875],"texture":"#0"}}},{"from":[2.5,9,10.5],"to":[13.5,11,11.5],"rotation":{"angle":0,"axis":"x","origin":[8,9.5,11]},"faces":{"north":{"uv":[3.6875,5.875,4.375,5.75],"rotation":180,"texture":"#0"},"south":{"uv":[3.6875,5.75,4.375,5.875],"texture":"#0"},"up":{"uv":[3.6875,5.75,4.375,5.8125],"rotation":180,"texture":"#0"},"down":{"uv":[3.6875,5.8125,4.375,5.875],"texture":"#0"}}},{"from":[2.5,5,6],"to":[13.5,6,9],"rotation":{"angle":0,"axis":"y","origin":[10,8,4]},"faces":{"north":{"uv":[4.375,5.875,3.6875,5.9375],"texture":"#0"},"east":{"uv":[3.875,5.75,3.6875,5.8125],"texture":"#0"},"south":{"uv":[4.375,5.75,3.6875,5.8125],"texture":"#0"},"west":{"uv":[3.875,5.75,3.6875,5.8125],"texture":"#0"},"up":{"uv":[3.6875,5.9375,4.375,5.75],"texture":"#0"},"down":{"uv":[3.6875,5.75,4.375,5.9375],"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[75,45,0],"translation":[1.25,3.75,3.25],"scale":[0.375,0.375,0.375]},"thirdperson_lefthand":{"rotation":[75,45,0],"translation":[0,4,3.25],"scale":[0.375,0.375,0.375]},"firstperson_righthand":{"rotation":[0,75.75,0],"translation":[5.25,2.75,1.5],"scale":[0.4,0.4,0.4]},"firstperson_lefthand":{"rotation":[0,75.75,0],"translation":[5.25,2.75,2],"scale":[0.4,0.4,0.4]},"ground":{"translation":[0,3,0],"scale":[0.25,0.25,0.25]},"gui":{"rotation":[30,225,0],"translation":[0.25,-1,0],"scale":[0.56445,0.56445,0.56445]},"head":{"translation":[0,12.75,0],"scale":[0.79492,0.79492,0.79492]},"fixed":{"rotation":[-90,0,0],"translation":[0,0,-16],"scale":[2.00195,2.00195,2.00195]}},"groups":[{"name":"group","origin":[8,19.50355,8],"color":0,"boneType":"","children":[0,1,2,3,4,5,6,{"name":"group","origin":[8,19.50355,8],"color":0,"boneType":"","children":[7,8,9,10,11,12,13]},{"name":"group","origin":[8,19.50355,8],"color":0,"boneType":"","children":[14,15,16,17,18,19,20]}]},{"name":"group","origin":[8,8,8],"color":0,"boneType":"","children":[21,22,23,24,25,26,27,28]}],"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_floatie.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_floatie.json new file mode 100644 index 000000000..8043f4d3e --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_floatie.json @@ -0,0 +1 @@ +{"credit":"Made with Blockbench by ShizuArt","texture_size":[256,256],"textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[0,0,0],"to":[16,3,16],"faces":{"north":{"uv":[1.0625,5.1875,1.25,4.1875],"rotation":90,"texture":"#0"},"east":{"uv":[1.0625,4.1875,1.25,5.1875],"rotation":90,"texture":"#0"},"south":{"uv":[1.0625,5.1875,1.25,4.1875],"rotation":90,"texture":"#0"},"west":{"uv":[1.0625,4.1875,1.25,5.1875],"rotation":90,"texture":"#0"},"up":{"uv":[0,4.1875,1,5.1875],"texture":"#0"},"down":{"uv":[0,4.1875,1,5.1875],"rotation":90,"texture":"#0"}}},{"from":[12,0,4],"to":[4,3,12],"faces":{"north":{"uv":[0.125,4.9375,0.25,4.4375],"rotation":90,"texture":"#0"},"east":{"uv":[0.125,4.4375,0.25,4.9375],"rotation":90,"texture":"#0"},"south":{"uv":[0.125,4.9375,0.25,4.4375],"rotation":90,"texture":"#0"},"west":{"uv":[0.125,4.4375,0.25,4.9375],"rotation":90,"texture":"#0"}}},{"from":[-2,1.5,-2],"to":[18,1.5,18],"faces":{"up":{"uv":[1.3125,4.0625,2.5625,5.3125],"texture":"#0"},"down":{"uv":[2.5625,4.0625,1.3125,5.3125],"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[75,45,0],"translation":[0,2.5,3.25],"scale":[0.375,0.375,0.375]},"thirdperson_lefthand":{"rotation":[75,45,0],"translation":[0,2.5,3.25],"scale":[0.375,0.375,0.375]},"firstperson_righthand":{"rotation":[0,-0.25,0],"translation":[5.25,2.75,0],"scale":[0.4,0.4,0.4]},"firstperson_lefthand":{"rotation":[0,2.75,0],"translation":[5.25,2.75,0],"scale":[0.4,0.4,0.4]},"ground":{"translation":[0,3,0],"scale":[0.43555,0.43555,0.43555]},"gui":{"rotation":[-141.25,-45,180],"translation":[0,3.5,0],"scale":[0.56641,0.56641,0.56641]},"head":{"translation":[0,12.75,0],"scale":[0.79492,0.79492,0.79492]},"fixed":{"rotation":[-90,0,0],"translation":[0,0,-16],"scale":[2.00195,2.00195,2.00195]}},"groups":[{"name":"group","origin":[8,8,8],"color":0,"children":[0,1,2]}],"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_hanging_fish.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_hanging_fish.json new file mode 100644 index 000000000..75e76a52a --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_hanging_fish.json @@ -0,0 +1 @@ +{"credit":"Made with Blockbench","texture_size":[256,256],"textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[15.97656,2.75,9.25],"to":[17.47706,26.75,10.75],"rotation":{"angle":-22.5,"axis":"x","origin":[16.72656,14.75,10]},"faces":{"north":{"uv":[5.875,0.375,5.6875,3.375],"texture":"#0"},"east":{"uv":[6.1875,0.375,6.375,3.375],"texture":"#0"},"south":{"uv":[5.6875,0.375,5.875,3.375],"texture":"#0"},"west":{"uv":[5.9375,0.375,6.125,3.375],"texture":"#0"},"up":{"uv":[5.6875,0.3125,5.875,0.125],"rotation":90,"texture":"#0"},"down":{"uv":[5.4375,0.3125,5.625,0.125],"rotation":90,"texture":"#0"}}},{"from":[16,2.75,5.25],"to":[17.5,26.75,6.75],"rotation":{"angle":22.5,"axis":"x","origin":[16.75,14.75,6]},"faces":{"north":{"uv":[5.875,0.375,5.6875,3.375],"texture":"#0"},"east":{"uv":[6.1875,0.375,6.375,3.375],"texture":"#0"},"south":{"uv":[5.6875,0.375,5.875,3.375],"texture":"#0"},"west":{"uv":[5.9375,0.375,6.125,3.375],"texture":"#0"},"up":{"uv":[5.6875,0.3125,5.875,0.125],"rotation":90,"texture":"#0"},"down":{"uv":[5.4375,0.3125,5.625,0.125],"rotation":90,"texture":"#0"}}},{"from":[-1.49414,2.75,9.25],"to":[0.00636,26.75,10.75],"rotation":{"angle":-22.5,"axis":"x","origin":[-0.74419,14.75,10]},"faces":{"north":{"uv":[5.6875,0.375,5.875,3.375],"texture":"#0"},"east":{"uv":[6.125,0.375,5.9375,3.375],"texture":"#0"},"south":{"uv":[5.875,0.375,5.6875,3.375],"texture":"#0"},"west":{"uv":[6.375,0.375,6.1875,3.375],"texture":"#0"},"up":{"uv":[5.6875,0.125,5.875,0.3125],"rotation":90,"texture":"#0"},"down":{"uv":[5.4375,0.125,5.625,0.3125],"rotation":90,"texture":"#0"}}},{"from":[-1.5,2.75,5.25],"to":[0,26.75,6.75],"rotation":{"angle":22.5,"axis":"x","origin":[-0.75,14.75,6]},"faces":{"north":{"uv":[5.6875,0.375,5.875,3.375],"texture":"#0"},"east":{"uv":[6.125,0.375,5.9375,3.375],"texture":"#0"},"south":{"uv":[5.875,0.375,5.6875,3.375],"texture":"#0"},"west":{"uv":[6.375,0.375,6.1875,3.375],"texture":"#0"},"up":{"uv":[5.6875,0.125,5.875,0.3125],"rotation":90,"texture":"#0"},"down":{"uv":[5.4375,0.125,5.625,0.3125],"rotation":90,"texture":"#0"}}},{"from":[-2.5,22.5,7.5],"to":[18.5,23.5,8.5],"rotation":{"angle":-45,"axis":"x","origin":[0,23,8]},"faces":{"north":{"uv":[2.875,3.4375,5.5,3.5625],"texture":"#0"},"east":{"uv":[2.6875,3.4375,2.8125,3.5625],"texture":"#0"},"south":{"uv":[5.5,3.5625,2.875,3.4375],"texture":"#0"},"west":{"uv":[2.6875,3.4375,2.8125,3.5625],"rotation":90,"texture":"#0"},"up":{"uv":[5.5,3.4375,2.875,3.5625],"texture":"#0"},"down":{"uv":[5.5,3.4375,2.875,3.5625],"texture":"#0"}}},{"from":[1.9,22.4,7.4],"to":[13.6,23.6,8.6],"rotation":{"angle":-45,"axis":"x","origin":[0,23,8]},"faces":{"north":{"uv":[2.875,3.1875,4.3125,3.3125],"texture":"#0"},"south":{"uv":[4.3125,3.3125,2.875,3.1875],"texture":"#0"},"up":{"uv":[4.3125,3.1875,2.875,3.3125],"texture":"#0"},"down":{"uv":[4.3125,3.1875,2.875,3.3125],"texture":"#0"}}},{"from":[2,17.29289,8],"to":[13.5,22.29289,8],"rotation":{"angle":0,"axis":"y","origin":[2.5,21.29289,7]},"faces":{"north":{"uv":[3.5,3.625,4.9375,4.25],"texture":"#0"},"south":{"uv":[3.5,3.625,4.9375,4.25],"texture":"#0"}}},{"from":[-1.85,18.9,6.9],"to":[0.35,20.1,9.1],"rotation":{"angle":0,"axis":"y","origin":[-0.75,19,7]},"faces":{"north":{"uv":[4.4375,3.1875,4.6875,3.3125],"texture":"#0"},"east":{"uv":[4.6875,3.1875,4.4375,3.3125],"texture":"#0"},"south":{"uv":[4.4375,3.1875,4.6875,3.3125],"texture":"#0"},"west":{"uv":[4.6875,3.1875,4.4375,3.3125],"texture":"#0"}}},{"name":"cube inverted","from":[0.35,20.1,9.1],"to":[-1.85,18.9,6.9],"rotation":{"angle":0,"axis":"y","origin":[-0.75,19,7]},"faces":{"north":{"uv":[4.4375,3.3125,4.6875,3.1875],"texture":"#0"},"east":{"uv":[4.6875,3.3125,4.4375,3.1875],"texture":"#0"},"south":{"uv":[4.4375,3.3125,4.6875,3.1875],"texture":"#0"},"west":{"uv":[4.6875,3.3125,4.4375,3.1875],"texture":"#0"}}},{"from":[15.65,18.9,6.9],"to":[17.85,20.1,9.1],"rotation":{"angle":0,"axis":"y","origin":[16.75,19,7]},"faces":{"north":{"uv":[4.4375,3.1875,4.6875,3.3125],"texture":"#0"},"east":{"uv":[4.6875,3.1875,4.4375,3.3125],"texture":"#0"},"south":{"uv":[4.4375,3.1875,4.6875,3.3125],"texture":"#0"},"west":{"uv":[4.6875,3.1875,4.4375,3.3125],"texture":"#0"}}},{"name":"cube inverted","from":[17.85,20.1,9.1],"to":[15.65,18.9,6.9],"rotation":{"angle":0,"axis":"y","origin":[16.75,19,7]},"faces":{"north":{"uv":[4.4375,3.3125,4.6875,3.1875],"texture":"#0"},"east":{"uv":[4.6875,3.3125,4.4375,3.1875],"texture":"#0"},"south":{"uv":[4.4375,3.3125,4.6875,3.1875],"texture":"#0"},"west":{"uv":[4.6875,3.3125,4.4375,3.1875],"texture":"#0"}}},{"from":[12.5553,14.64914,7.4348],"to":[14.5553,19.14914,8.4348],"rotation":{"angle":0,"axis":"y","origin":[13.5553,16.52414,7.9348]},"faces":{"north":{"uv":[0.375,2.3125,0.9375,2.5625],"rotation":270,"texture":"#0"},"east":{"uv":[0.375,2.3125,0.9375,2.375],"rotation":270,"texture":"#0"},"south":{"uv":[0.375,2.5625,0.9375,2.3125],"rotation":270,"texture":"#0"},"west":{"uv":[0.375,2.5,0.9375,2.5625],"rotation":270,"texture":"#0"},"up":{"uv":[0.875,2.5625,0.9375,2.3125],"rotation":270,"texture":"#0"},"down":{"uv":[0.375,2.5625,0.4375,2.3125],"rotation":270,"texture":"#0"}}},{"from":[12.5553,13.14914,7.9348],"to":[15.0553,19.14914,7.9348],"rotation":{"angle":0,"axis":"y","origin":[13.5553,16.52414,7.9348]},"faces":{"north":{"uv":[0.1875,2.25,0.9375,2.5625],"rotation":270,"texture":"#0"},"south":{"uv":[0.1875,2.5625,0.9375,2.25],"rotation":270,"texture":"#0"}}},{"from":[13.3053,16.39914,6.4348],"to":[13.3053,17.39914,9.4348],"rotation":{"angle":0,"axis":"y","origin":[13.5553,16.52414,7.9348]},"faces":{"east":{"uv":[0.5,2.625,0.625,3],"rotation":270,"texture":"#0"},"west":{"uv":[0.5,2.625,0.625,3],"rotation":270,"texture":"#0"}}},{"from":[5.0553,13.14914,7.4348],"to":[7.0553,17.64914,8.4348],"rotation":{"angle":0,"axis":"y","origin":[6.0553,15.02414,7.9348]},"faces":{"north":{"uv":[1.3125,2.3125,1.875,2.5625],"rotation":270,"texture":"#0"},"east":{"uv":[1.3125,2.3125,1.875,2.375],"rotation":270,"texture":"#0"},"south":{"uv":[1.3125,2.5625,1.875,2.3125],"rotation":270,"texture":"#0"},"west":{"uv":[1.3125,2.5,1.875,2.5625],"rotation":270,"texture":"#0"},"up":{"uv":[1.8125,2.5625,1.875,2.3125],"rotation":270,"texture":"#0"},"down":{"uv":[1.3125,2.5625,1.375,2.3125],"rotation":270,"texture":"#0"}}},{"from":[5.0553,11.64914,7.9348],"to":[7.5553,17.64914,7.9348],"rotation":{"angle":0,"axis":"y","origin":[6.0553,15.02414,7.9348]},"faces":{"north":{"uv":[1.125,2.25,1.875,2.5625],"rotation":270,"texture":"#0"},"south":{"uv":[1.125,2.5625,1.875,2.25],"rotation":270,"texture":"#0"}}},{"from":[5.8053,14.89914,6.4348],"to":[5.8053,15.89914,9.4348],"rotation":{"angle":0,"axis":"y","origin":[6.0553,15.02414,7.9348]},"faces":{"east":{"uv":[1.4375,2.625,1.5625,3],"rotation":270,"texture":"#0"},"west":{"uv":[1.4375,2.625,1.5625,3],"rotation":270,"texture":"#0"}}},{"from":[9.0553,13.14914,7.4348],"to":[11.0553,17.64914,8.4348],"rotation":{"angle":0,"axis":"y","origin":[10.0553,15.02414,7.9348]},"faces":{"north":{"uv":[1.3125,3.25,1.875,3.5],"rotation":270,"texture":"#0"},"east":{"uv":[1.3125,3.25,1.875,3.3125],"rotation":270,"texture":"#0"},"south":{"uv":[1.3125,3.5,1.875,3.25],"rotation":270,"texture":"#0"},"west":{"uv":[1.3125,3.4375,1.875,3.5],"rotation":270,"texture":"#0"},"up":{"uv":[1.8125,3.5,1.875,3.25],"rotation":270,"texture":"#0"},"down":{"uv":[1.3125,3.5,1.375,3.25],"rotation":270,"texture":"#0"}}},{"from":[9.0553,11.64914,7.9348],"to":[11.5553,17.64914,7.9348],"rotation":{"angle":0,"axis":"y","origin":[10.0553,15.02414,7.9348]},"faces":{"north":{"uv":[1.125,3.1875,1.875,3.5],"rotation":270,"texture":"#0"},"south":{"uv":[1.125,3.5,1.875,3.1875],"rotation":270,"texture":"#0"}}},{"from":[9.8053,14.89914,6.4348],"to":[9.8053,15.89914,9.4348],"rotation":{"angle":0,"axis":"y","origin":[10.0553,15.02414,7.9348]},"faces":{"east":{"uv":[1.4375,3.5625,1.5625,3.9375],"rotation":270,"texture":"#0"},"west":{"uv":[1.4375,3.5625,1.5625,3.9375],"rotation":270,"texture":"#0"}}},{"from":[1.5553,14.64914,7.4348],"to":[3.5553,19.14914,8.4348],"rotation":{"angle":0,"axis":"y","origin":[2.5553,16.52414,7.9348]},"faces":{"north":{"uv":[0.375,3.25,0.9375,3.5],"rotation":270,"texture":"#0"},"east":{"uv":[0.375,3.25,0.9375,3.3125],"rotation":270,"texture":"#0"},"south":{"uv":[0.375,3.5,0.9375,3.25],"rotation":270,"texture":"#0"},"west":{"uv":[0.375,3.4375,0.9375,3.5],"rotation":270,"texture":"#0"},"up":{"uv":[0.875,3.5,0.9375,3.25],"rotation":270,"texture":"#0"},"down":{"uv":[0.375,3.5,0.4375,3.25],"rotation":270,"texture":"#0"}}},{"from":[1.5553,13.14914,7.9348],"to":[4.0553,19.14914,7.9348],"rotation":{"angle":0,"axis":"y","origin":[2.5553,16.52414,7.9348]},"faces":{"north":{"uv":[0.1875,3.1875,0.9375,3.5],"rotation":270,"texture":"#0"},"south":{"uv":[0.1875,3.5,0.9375,3.1875],"rotation":270,"texture":"#0"}}},{"from":[2.3053,16.39914,6.4348],"to":[2.3053,17.39914,9.4348],"rotation":{"angle":0,"axis":"y","origin":[2.5553,16.52414,7.9348]},"faces":{"east":{"uv":[0.5,3.5625,0.625,3.9375],"rotation":270,"texture":"#0"},"west":{"uv":[0.5,3.5625,0.625,3.9375],"rotation":270,"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[75,45,0],"translation":[2.75,2.5,2],"scale":[0.375,0.375,0.375]},"thirdperson_lefthand":{"rotation":[75,45,0],"translation":[2.25,2,1.75],"scale":[0.375,0.375,0.375]},"firstperson_righthand":{"rotation":[0,75.75,0],"translation":[5.25,-0.75,1.5],"scale":[0.4,0.4,0.4]},"firstperson_lefthand":{"rotation":[0,75.75,0],"translation":[5.25,-0.5,2],"scale":[0.4,0.4,0.4]},"ground":{"translation":[0,3,0],"scale":[0.25,0.25,0.25]},"gui":{"rotation":[30,225,0],"translation":[0.25,-3.25,0],"scale":[0.49219,0.49219,0.49219]},"head":{"translation":[0,12.75,0],"scale":[0.79492,0.79492,0.79492]},"fixed":{"rotation":[-90,0,0],"translation":[0,0,-16],"scale":[2.00195,2.00195,2.00195]}},"groups":[{"name":"group","origin":[8,8,8],"color":0,"children":[0,1,2,3,4,5,6,7,8,9,10,{"name":"group","origin":[8,8,8],"color":0,"children":[11,12,13]},{"name":"group","origin":[8,8,8],"color":0,"children":[14,15,16]},{"name":"group","origin":[8,8,8],"color":0,"children":[17,18,19]},{"name":"group","origin":[8,8,8],"color":0,"children":[20,21,22]}]}],"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_landing_net.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_landing_net.json new file mode 100644 index 000000000..fe1d01331 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_landing_net.json @@ -0,0 +1 @@ +{"credit":"Made with Blockbench","texture_size":[256,256],"textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[7.5,5.54297,-4.5],"to":[8.5,6.54297,12.5],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"east":{"uv":[5.625,4.4375,5.6875,5.5],"rotation":90,"texture":"#0"},"west":{"uv":[5.625,5.5,5.6875,4.4375],"rotation":90,"texture":"#0"},"up":{"uv":[5.625,4.4375,5.6875,5.5],"texture":"#0"},"down":{"uv":[5.625,5.5,5.6875,4.4375],"texture":"#0"}}},{"from":[7,5.04297,11.5],"to":[9,7.04297,12.5],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[5.1875,6,5.3125,6.125],"rotation":270,"texture":"#0"},"east":{"uv":[5.3125,6,5.1875,6.0625],"rotation":90,"texture":"#0"},"west":{"uv":[5.3125,6,5.1875,6.0625],"rotation":90,"texture":"#0"},"up":{"uv":[5.25,6,5.3125,6.0625],"texture":"#0"},"down":{"uv":[5.1875,6,5.25,6.0625],"texture":"#0"}}},{"from":[7,5.04297,2.5],"to":[9,7.04297,3.5],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[5.1875,6,5.3125,6.125],"rotation":270,"texture":"#0"},"east":{"uv":[5.3125,6,5.1875,6.0625],"rotation":90,"texture":"#0"},"south":{"uv":[5.1875,6,5.3125,6.125],"rotation":270,"texture":"#0"},"west":{"uv":[5.3125,6,5.1875,6.0625],"rotation":90,"texture":"#0"},"up":{"uv":[5.25,6,5.3125,6.0625],"texture":"#0"},"down":{"uv":[5.1875,6,5.25,6.0625],"texture":"#0"}}},{"from":[7,5.04297,-5.5],"to":[9,7.04297,-4.5],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[5.1875,6,5.3125,6.125],"rotation":270,"texture":"#0"},"east":{"uv":[5.3125,6,5.1875,6.0625],"rotation":90,"texture":"#0"},"south":{"uv":[5.1875,6,5.3125,6.125],"rotation":270,"texture":"#0"},"west":{"uv":[5.3125,6,5.1875,6.0625],"rotation":90,"texture":"#0"},"up":{"uv":[5.25,6,5.3125,6.0625],"texture":"#0"},"down":{"uv":[5.1875,6,5.25,6.0625],"texture":"#0"}}},{"from":[4,5.04297,12.5],"to":[12,7.04297,13.5],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[5.375,5.8125,5.25,5.3125],"rotation":90,"texture":"#0"},"south":{"uv":[5.375,5.8125,5.25,5.3125],"rotation":90,"texture":"#0"},"up":{"uv":[5.3125,5.3125,5.375,5.8125],"rotation":270,"texture":"#0"},"down":{"uv":[5.25,5.3125,5.3125,5.8125],"rotation":90,"texture":"#0"}}},{"from":[4,5.04297,21.5],"to":[12,7.04297,22.5],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[5.375,5.3125,5.25,5.8125],"rotation":90,"texture":"#0"},"south":{"uv":[5.375,5.8125,5.25,5.3125],"rotation":90,"texture":"#0"},"up":{"uv":[5.3125,5.3125,5.375,5.8125],"rotation":270,"texture":"#0"},"down":{"uv":[5.25,5.3125,5.3125,5.8125],"rotation":90,"texture":"#0"}}},{"from":[12,5.04297,12.5],"to":[13,7.04297,22.5],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[5.1875,5.3125,5.0625,5.375],"rotation":90,"texture":"#0"},"east":{"uv":[5.1875,5.3125,5.0625,5.9375],"rotation":90,"texture":"#0"},"south":{"uv":[5.1875,5.3125,5.0625,5.375],"rotation":90,"texture":"#0"},"west":{"uv":[5.1875,5.9375,5.0625,5.3125],"rotation":90,"texture":"#0"},"up":{"uv":[5.125,5.3125,5.1875,5.9375],"texture":"#0"},"down":{"uv":[5.0625,5.3125,5.125,5.9375],"texture":"#0"}}},{"from":[3,5.04297,12.5],"to":[4,7.04297,22.5],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[5.1875,5.3125,5.0625,5.375],"rotation":90,"texture":"#0"},"east":{"uv":[5.1875,5.3125,5.0625,5.9375],"rotation":90,"texture":"#0"},"south":{"uv":[5.1875,5.3125,5.0625,5.375],"rotation":90,"texture":"#0"},"west":{"uv":[5.1875,5.9375,5.0625,5.3125],"rotation":90,"texture":"#0"},"up":{"uv":[5.125,5.3125,5.1875,5.9375],"texture":"#0"},"down":{"uv":[5.0625,5.3125,5.125,5.9375],"texture":"#0"}}},{"from":[3.5,0.04297,13],"to":[12.5,5.04297,22],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[4.4375,5.3125,5,5.625],"texture":"#0"},"east":{"uv":[4.4375,5.3125,5,5.625],"texture":"#0"},"south":{"uv":[4.4375,5.3125,5,5.625],"texture":"#0"},"west":{"uv":[4.4375,5.3125,5,5.625],"texture":"#0"},"down":{"uv":[4.4375,5.6875,5,6.25],"texture":"#0"}}},{"name":"cube inverted","from":[12.5,5.04297,22],"to":[3.5,0.04297,13],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[4.4375,5.625,5,5.3125],"texture":"#0"},"east":{"uv":[4.4375,5.625,5,5.3125],"texture":"#0"},"south":{"uv":[4.4375,5.625,5,5.3125],"texture":"#0"},"west":{"uv":[4.4375,5.625,5,5.3125],"texture":"#0"},"up":{"uv":[5,5.6875,4.4375,6.25],"texture":"#0"}}},{"name":"cube inverted","from":[4.1,7.14297,15.1],"to":[2.9,4.94297,13.9],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"east":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"west":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"up":{"uv":[5.125,6.0625,5.0625,6.125],"texture":"#0"},"down":{"uv":[5.125,6,5.0625,6.0625],"texture":"#0"}}},{"from":[2.9,4.94297,13.9],"to":[4.1,7.14297,15.1],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"east":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"west":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"up":{"uv":[5.0625,6,5.125,6.0625],"texture":"#0"},"down":{"uv":[5.0625,6.0625,5.125,6.125],"texture":"#0"}}},{"from":[10.4,4.94297,21.4],"to":[11.6,7.14297,22.6],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"south":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"up":{"uv":[5.0625,6,5.125,6.0625],"rotation":90,"texture":"#0"},"down":{"uv":[5.0625,6.0625,5.125,6.125],"rotation":270,"texture":"#0"}}},{"name":"cube inverted","from":[11.6,7.14297,22.6],"to":[10.4,4.94297,21.4],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"south":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"up":{"uv":[5.125,6.0625,5.0625,6.125],"rotation":90,"texture":"#0"},"down":{"uv":[5.125,6,5.0625,6.0625],"rotation":270,"texture":"#0"}}},{"from":[4.4,4.94297,21.4],"to":[5.6,7.14297,22.6],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"south":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"up":{"uv":[5.0625,6,5.125,6.0625],"rotation":90,"texture":"#0"},"down":{"uv":[5.0625,6.0625,5.125,6.125],"rotation":270,"texture":"#0"}}},{"name":"cube inverted","from":[5.6,7.14297,22.6],"to":[4.4,4.94297,21.4],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"south":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"up":{"uv":[5.125,6.0625,5.0625,6.125],"rotation":90,"texture":"#0"},"down":{"uv":[5.125,6,5.0625,6.0625],"rotation":270,"texture":"#0"}}},{"from":[4.4,4.94297,12.4],"to":[5.6,7.14297,13.6],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"south":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"up":{"uv":[5.0625,6,5.125,6.0625],"rotation":90,"texture":"#0"},"down":{"uv":[5.0625,6.0625,5.125,6.125],"rotation":270,"texture":"#0"}}},{"name":"cube inverted","from":[5.6,7.14297,13.6],"to":[4.4,4.94297,12.4],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"south":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"up":{"uv":[5.125,6.0625,5.0625,6.125],"rotation":90,"texture":"#0"},"down":{"uv":[5.125,6,5.0625,6.0625],"rotation":270,"texture":"#0"}}},{"from":[10.4,4.94297,12.4],"to":[11.6,7.14297,13.6],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"south":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"up":{"uv":[5.0625,6,5.125,6.0625],"rotation":90,"texture":"#0"},"down":{"uv":[5.0625,6.0625,5.125,6.125],"rotation":270,"texture":"#0"}}},{"name":"cube inverted","from":[11.6,7.14297,13.6],"to":[10.4,4.94297,12.4],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"north":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"south":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"up":{"uv":[5.125,6.0625,5.0625,6.125],"rotation":90,"texture":"#0"},"down":{"uv":[5.125,6,5.0625,6.0625],"rotation":270,"texture":"#0"}}},{"from":[2.9,4.94297,19.9],"to":[4.1,7.14297,21.1],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"east":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"west":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"up":{"uv":[5.0625,6,5.125,6.0625],"texture":"#0"},"down":{"uv":[5.0625,6.0625,5.125,6.125],"texture":"#0"}}},{"name":"cube inverted","from":[4.1,7.14297,21.1],"to":[2.9,4.94297,19.9],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"east":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"west":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"up":{"uv":[5.125,6.0625,5.0625,6.125],"texture":"#0"},"down":{"uv":[5.125,6,5.0625,6.0625],"texture":"#0"}}},{"name":"cube inverted","from":[13.1,7.14297,15.1],"to":[11.9,4.94297,13.9],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"east":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"west":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"up":{"uv":[5.125,6.0625,5.0625,6.125],"texture":"#0"},"down":{"uv":[5.125,6,5.0625,6.0625],"texture":"#0"}}},{"from":[11.9,4.94297,13.9],"to":[13.1,7.14297,15.1],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"east":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"west":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"up":{"uv":[5.0625,6,5.125,6.0625],"texture":"#0"},"down":{"uv":[5.0625,6.0625,5.125,6.125],"texture":"#0"}}},{"from":[11.9,4.94297,19.9],"to":[13.1,7.14297,21.1],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"east":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"west":{"uv":[5.0625,6,5.125,6.125],"texture":"#0"},"up":{"uv":[5.0625,6,5.125,6.0625],"texture":"#0"},"down":{"uv":[5.0625,6.0625,5.125,6.125],"texture":"#0"}}},{"name":"cube inverted","from":[13.1,7.14297,21.1],"to":[11.9,4.94297,19.9],"rotation":{"angle":0,"axis":"x","origin":[8,4.29297,8.5]},"faces":{"east":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"west":{"uv":[5.0625,6.125,5.125,6],"texture":"#0"},"up":{"uv":[5.125,6.0625,5.0625,6.125],"texture":"#0"},"down":{"uv":[5.125,6,5.0625,6.0625],"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[-90,0,180],"translation":[0,7.5,3.5]},"thirdperson_lefthand":{"rotation":[-90,0,180],"translation":[0,6.75,3.25]},"firstperson_righthand":{"rotation":[-155.49,-5.92,164.48],"translation":[17.5,0,-12.5]},"firstperson_lefthand":{"rotation":[-155.49,-5.92,164.48],"translation":[17.5,0,-12.5]},"ground":{"translation":[0.25,6.25,-1.5],"scale":[0.46875,0.46875,0.46875]},"gui":{"rotation":[-140.22,33.97,176.22],"translation":[-1,1.25,0],"scale":[0.66211,0.66211,0.66211]},"head":{"translation":[0,19.75,0]},"fixed":{"rotation":[-90,0,0],"translation":[0,9.5,-16.25],"scale":[2.00195,2.00195,2.00195]}},"groups":[{"name":"group","origin":[8,8,8],"color":0,"children":[0,1,2,3,4,5,6,7,8,9,{"name":"cube inverted","origin":[2,-0.5,14.5],"color":0,"children":[10,11,12,13,14,15,16,17,18,19,20,21]},{"name":"cube inverted","origin":[2,-0.5,14.5],"color":0,"children":[22,23,24,25]}]}],"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_large_fishnet.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_large_fishnet.json new file mode 100644 index 000000000..bd0025d9a --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_large_fishnet.json @@ -0,0 +1 @@ +{"credit":"Made with Blockbench","texture_size":[256,256],"textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[0,10.5,8],"to":[16,26.5,8],"rotation":{"angle":0,"axis":"y","origin":[8,10.5,7]},"faces":{"north":{"uv":[2.4375,0.5625,4.4375,2.5625],"texture":"#0"},"south":{"uv":[2.4375,0.5625,4.4375,2.5625],"texture":"#0"}}},{"from":[11.0553,19.14914,6.9348],"to":[13.0553,23.64914,7.9348],"rotation":{"angle":0,"axis":"y","origin":[12.0553,21.02414,7.4348]},"faces":{"north":{"uv":[0.375,2.3125,0.9375,2.5625],"rotation":270,"texture":"#0"},"east":{"uv":[0.375,2.3125,0.9375,2.375],"rotation":270,"texture":"#0"},"south":{"uv":[0.375,2.5625,0.9375,2.3125],"rotation":270,"texture":"#0"},"west":{"uv":[0.375,2.5,0.9375,2.5625],"rotation":270,"texture":"#0"},"up":{"uv":[0.875,2.5625,0.9375,2.3125],"rotation":270,"texture":"#0"},"down":{"uv":[0.375,2.5625,0.4375,2.3125],"rotation":270,"texture":"#0"}}},{"from":[11.0553,17.64914,7.4348],"to":[13.5553,23.64914,7.4348],"rotation":{"angle":0,"axis":"y","origin":[12.0553,21.02414,7.4348]},"faces":{"north":{"uv":[0.1875,2.25,0.9375,2.5625],"rotation":270,"texture":"#0"},"south":{"uv":[0.1875,2.5625,0.9375,2.25],"rotation":270,"texture":"#0"}}},{"from":[11.8053,20.89914,5.9348],"to":[11.8053,21.89914,8.9348],"rotation":{"angle":0,"axis":"y","origin":[12.0553,21.02414,7.4348]},"faces":{"east":{"uv":[0.5,2.625,0.625,3],"rotation":270,"texture":"#0"},"west":{"uv":[0.5,2.625,0.625,3],"rotation":270,"texture":"#0"}}},{"from":[7.0553,14.14914,6.9348],"to":[9.0553,18.64914,7.9348],"rotation":{"angle":0,"axis":"y","origin":[8.0553,16.02414,7.4348]},"faces":{"north":{"uv":[1.3125,2.3125,1.875,2.5625],"rotation":270,"texture":"#0"},"east":{"uv":[1.3125,2.3125,1.875,2.375],"rotation":270,"texture":"#0"},"south":{"uv":[1.3125,2.5625,1.875,2.3125],"rotation":270,"texture":"#0"},"west":{"uv":[1.3125,2.5,1.875,2.5625],"rotation":270,"texture":"#0"},"up":{"uv":[1.8125,2.5625,1.875,2.3125],"rotation":270,"texture":"#0"},"down":{"uv":[1.3125,2.5625,1.375,2.3125],"rotation":270,"texture":"#0"}}},{"from":[7.0553,12.64914,7.4348],"to":[9.5553,18.64914,7.4348],"rotation":{"angle":0,"axis":"y","origin":[8.0553,16.02414,7.4348]},"faces":{"north":{"uv":[1.125,2.25,1.875,2.5625],"rotation":270,"texture":"#0"},"south":{"uv":[1.125,2.5625,1.875,2.25],"rotation":270,"texture":"#0"}}},{"from":[7.8053,15.89914,5.9348],"to":[7.8053,16.89914,8.9348],"rotation":{"angle":0,"axis":"y","origin":[8.0553,16.02414,7.4348]},"faces":{"east":{"uv":[1.4375,2.625,1.5625,3],"rotation":270,"texture":"#0"},"west":{"uv":[1.4375,2.625,1.5625,3],"rotation":270,"texture":"#0"}}},{"from":[2.0553,17.14914,6.9348],"to":[4.0553,21.64914,7.9348],"rotation":{"angle":0,"axis":"y","origin":[3.0553,19.02414,7.4348]},"faces":{"north":{"uv":[0.375,3.25,0.9375,3.5],"rotation":270,"texture":"#0"},"east":{"uv":[0.375,3.25,0.9375,3.3125],"rotation":270,"texture":"#0"},"south":{"uv":[0.375,3.5,0.9375,3.25],"rotation":270,"texture":"#0"},"west":{"uv":[0.375,3.4375,0.9375,3.5],"rotation":270,"texture":"#0"},"up":{"uv":[0.875,3.5,0.9375,3.25],"rotation":270,"texture":"#0"},"down":{"uv":[0.375,3.5,0.4375,3.25],"rotation":270,"texture":"#0"}}},{"from":[2.0553,15.64914,7.4348],"to":[4.5553,21.64914,7.4348],"rotation":{"angle":0,"axis":"y","origin":[3.0553,19.02414,7.4348]},"faces":{"north":{"uv":[0.1875,3.1875,0.9375,3.5],"rotation":270,"texture":"#0"},"south":{"uv":[0.1875,3.5,0.9375,3.1875],"rotation":270,"texture":"#0"}}},{"from":[2.8053,18.89914,5.9348],"to":[2.8053,19.89914,8.9348],"rotation":{"angle":0,"axis":"y","origin":[3.0553,19.02414,7.4348]},"faces":{"east":{"uv":[0.5,3.5625,0.625,3.9375],"rotation":270,"texture":"#0"},"west":{"uv":[0.5,3.5625,0.625,3.9375],"rotation":270,"texture":"#0"}}},{"from":[16,4,7.25],"to":[17.5,28,8.75],"rotation":{"angle":0,"axis":"y","origin":[18.5,4,7.25]},"faces":{"north":{"uv":[5.0625,0.375,4.875,3.375],"texture":"#0"},"east":{"uv":[5.375,0.375,5.5625,3.375],"texture":"#0"},"south":{"uv":[4.875,0.375,5.0625,3.375],"texture":"#0"},"west":{"uv":[5.125,0.375,5.3125,3.375],"texture":"#0"},"up":{"uv":[5.6875,0.3125,5.875,0.125],"rotation":90,"texture":"#0"},"down":{"uv":[5.4375,0.3125,5.625,0.125],"rotation":90,"texture":"#0"}}},{"from":[15.95,12.95,7.2],"to":[17.55,26.55,8.8],"rotation":{"angle":0,"axis":"y","origin":[18.5,13,7.25]},"faces":{"north":{"uv":[6.625,2,6.4375,3.6875],"texture":"#0"},"east":{"uv":[6.9375,2,7.125,3.6875],"texture":"#0"},"south":{"uv":[6.4375,2,6.625,3.6875],"texture":"#0"},"west":{"uv":[6.6875,2,6.875,3.6875],"texture":"#0"},"up":{"uv":[5.6875,0.3125,5.875,0.125],"rotation":90,"texture":"#0"},"down":{"uv":[5.4375,0.3125,5.625,0.125],"rotation":90,"texture":"#0"}}},{"from":[-1.55,12.95,7.2],"to":[0.05,26.55,8.8],"rotation":{"angle":0,"axis":"y","origin":[1,13,7.25]},"faces":{"north":{"uv":[6.625,2,6.4375,3.6875],"texture":"#0"},"east":{"uv":[6.9375,2,7.125,3.6875],"texture":"#0"},"south":{"uv":[6.4375,2,6.625,3.6875],"texture":"#0"},"west":{"uv":[6.6875,2,6.875,3.6875],"texture":"#0"},"up":{"uv":[5.6875,0.3125,5.875,0.125],"rotation":90,"texture":"#0"},"down":{"uv":[5.4375,0.3125,5.625,0.125],"rotation":90,"texture":"#0"}}},{"from":[-1.5,4,7.25],"to":[0,28,8.75],"rotation":{"angle":0,"axis":"y","origin":[-2.5,4,7.25]},"faces":{"north":{"uv":[4.875,0.375,5.0625,3.375],"texture":"#0"},"east":{"uv":[5.3125,0.375,5.125,3.375],"texture":"#0"},"south":{"uv":[5.0625,0.375,4.875,3.375],"texture":"#0"},"west":{"uv":[5.5625,0.375,5.375,3.375],"texture":"#0"},"up":{"uv":[5.6875,0.125,5.875,0.3125],"rotation":90,"texture":"#0"},"down":{"uv":[5.4375,0.125,5.625,0.3125],"rotation":90,"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[75,45,0],"translation":[2.75,2.5,2],"scale":[0.375,0.375,0.375]},"thirdperson_lefthand":{"rotation":[75,45,0],"translation":[2.25,2,1.75],"scale":[0.375,0.375,0.375]},"firstperson_righthand":{"rotation":[0,75.75,0],"translation":[5.25,-0.75,1.5],"scale":[0.4,0.4,0.4]},"firstperson_lefthand":{"rotation":[0,75.75,0],"translation":[5.25,-0.5,2],"scale":[0.4,0.4,0.4]},"ground":{"translation":[0,3,0],"scale":[0.25,0.25,0.25]},"gui":{"rotation":[30,225,0],"translation":[0.25,-3.25,0],"scale":[0.49219,0.49219,0.49219]},"head":{"translation":[0,12.75,0],"scale":[0.79492,0.79492,0.79492]},"fixed":{"rotation":[-90,0,0],"translation":[0,0,-16],"scale":[2.00195,2.00195,2.00195]}},"groups":[{"name":"group","origin":[8,8,8],"color":0,"children":[0,{"name":"group","origin":[8,8,8],"color":0,"children":[1,2,3]},{"name":"group","origin":[8,8,8],"color":0,"children":[4,5,6]},{"name":"group","origin":[8,8,8],"color":0,"children":[7,8,9]},10,11,12,13]}],"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_lobster_trap.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_lobster_trap.json new file mode 100644 index 000000000..a87f4eb78 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_lobster_trap.json @@ -0,0 +1 @@ +{"credit":"Made with Blockbench","texture_size":[256,256],"textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[2,0,3.5],"to":[14,2,13.5],"rotation":{"angle":0,"axis":"y","origin":[2,0,3.5]},"faces":{"north":{"uv":[5.375,8.5625,6.125,8.6875],"texture":"#0"},"east":{"uv":[6.1875,7.875,6.3125,8.5],"rotation":90,"texture":"#0"},"south":{"uv":[5.375,8.5625,6.125,8.6875],"texture":"#0"},"west":{"uv":[6.1875,8.5,6.3125,7.875],"rotation":90,"texture":"#0"},"up":{"uv":[5.375,7.875,6.125,8.5],"texture":"#0"},"down":{"uv":[6.125,9.375,5.375,8.75],"texture":"#0"}}},{"from":[2,8,3.5],"to":[14,10,13.5],"rotation":{"angle":0,"axis":"y","origin":[2,8,3.5]},"faces":{"north":{"uv":[5.375,8.5625,6.125,8.6875],"texture":"#0"},"east":{"uv":[6.1875,7.875,6.3125,8.5],"rotation":90,"texture":"#0"},"south":{"uv":[5.375,8.5625,6.125,8.6875],"texture":"#0"},"west":{"uv":[6.1875,8.5,6.3125,7.875],"rotation":90,"texture":"#0"},"up":{"uv":[5.3125,8.625,4.5625,9.25],"texture":"#0"},"down":{"uv":[6.125,9.375,5.375,8.75],"texture":"#0"}}},{"from":[2.5,2,4],"to":[13.5,8,13],"rotation":{"angle":0,"axis":"y","origin":[1.5,2,3]},"faces":{"north":{"uv":[5.375,7.4375,6.0625,7.8125],"texture":"#0"},"east":{"uv":[5.375,7.4375,5.9375,7.8125],"texture":"#0"},"south":{"uv":[5.375,7.4375,6.0625,7.8125],"texture":"#0"},"west":{"uv":[5.375,7.4375,5.9375,7.8125],"texture":"#0"}}},{"name":"cube inverted","from":[13.5,8,13],"to":[2.5,2,4],"rotation":{"angle":0,"axis":"y","origin":[1.5,2,3]},"faces":{"north":{"uv":[5.375,7.8125,6.0625,7.4375],"texture":"#0"},"east":{"uv":[5.375,7.8125,5.9375,7.4375],"texture":"#0"},"south":{"uv":[5.375,7.8125,6.0625,7.4375],"texture":"#0"},"west":{"uv":[5.375,7.8125,5.9375,7.4375],"texture":"#0"}}},{"from":[5,9,6.5],"to":[11,10,10.5],"rotation":{"angle":45,"axis":"z","origin":[5,9.5,8.5]},"faces":{"north":{"uv":[4.75,9.3125,5.125,9.375],"texture":"#0"},"east":{"uv":[4.75,9.3125,4.8125,9.5625],"rotation":90,"texture":"#0"},"south":{"uv":[4.75,9.5,5.125,9.5625],"texture":"#0"},"west":{"uv":[4.75,9.3125,5,9.375],"texture":"#0"},"up":{"uv":[5.125,9.3125,4.75,9.5625],"texture":"#0"},"down":{"uv":[5.125,9.5625,4.75,9.3125],"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[75,45,0],"translation":[0,3.75,3.25],"scale":[0.375,0.375,0.375]},"thirdperson_lefthand":{"rotation":[75,45,0],"translation":[0,4,3.25],"scale":[0.375,0.375,0.375]},"firstperson_righthand":{"rotation":[0,75.75,0],"translation":[5.25,2.75,1.5],"scale":[0.4,0.4,0.4]},"firstperson_lefthand":{"rotation":[0,75.75,0],"translation":[5.25,2.75,2],"scale":[0.4,0.4,0.4]},"ground":{"translation":[0,3,0],"scale":[0.25,0.25,0.25]},"gui":{"rotation":[30,225,0],"translation":[0.25,1.75,0],"scale":[0.87305,0.87305,0.87305]},"head":{"translation":[0,12.75,0],"scale":[0.79492,0.79492,0.79492]},"fixed":{"rotation":[-90,0,0],"translation":[0,0,-16],"scale":[2.00195,2.00195,2.00195]}},"groups":[{"name":"group","origin":[8,8,8],"color":0,"children":[0,1,2,3,4]}],"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_orange_fish.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_orange_fish.json new file mode 100644 index 000000000..1ff3df591 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_orange_fish.json @@ -0,0 +1 @@ +{"credit":"Made with Blockbench","textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[6.1106,0.04828,4.1196],"to":[10.1106,2.04828,13.1196],"rotation":{"angle":0,"axis":"y","origin":[8.1106,1.04828,7.8696]},"faces":{"north":{"uv":[1.3125,2.5625,1.375,2.3125],"rotation":90,"texture":"#0"},"east":{"uv":[1.3125,2.3125,1.875,2.375],"rotation":180,"texture":"#0"},"south":{"uv":[1.8125,2.5625,1.875,2.3125],"rotation":270,"texture":"#0"},"west":{"uv":[1.3125,2.5,1.875,2.5625],"texture":"#0"},"up":{"uv":[1.3125,2.3125,1.875,2.5625],"rotation":90,"texture":"#0"},"down":{"uv":[1.3125,2.5625,1.875,2.3125],"rotation":270,"texture":"#0"}}},{"from":[6.1106,1.04828,1.1196],"to":[11.1106,1.04828,13.1196],"rotation":{"angle":0,"axis":"y","origin":[8.1106,1.04828,7.8696]},"faces":{"up":{"uv":[1.125,2.25,1.875,2.5625],"rotation":90,"texture":"#0"},"down":{"uv":[1.125,2.5625,1.875,2.25],"rotation":270,"texture":"#0"}}},{"from":[7.6106,-1.95172,7.6196],"to":[7.6106,4.04828,9.6196],"rotation":{"angle":0,"axis":"y","origin":[8.1106,1.04828,7.8696]},"faces":{"east":{"uv":[1.4375,2.625,1.5625,3],"rotation":180,"texture":"#0"},"west":{"uv":[1.4375,2.625,1.5625,3],"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[-91,0,0],"translation":[0,4.75,-5.75],"scale":[1.03828,1.03828,1.03828]},"thirdperson_lefthand":{"rotation":[-91,0,0],"translation":[0.25,4.75,-5.75],"scale":[1.03828,1.03828,1.03828]},"firstperson_righthand":{"rotation":[-145,-13,-180],"translation":[7.75,4.25,-0.5],"scale":[0.75352,0.75352,0.75352]},"firstperson_lefthand":{"rotation":[-145,-13,-180],"translation":[7.75,4.25,-0.5],"scale":[0.75352,0.75352,0.75352]},"ground":{"translation":[0,4.5,0],"scale":[0.41406,0.41406,0.41406]},"gui":{"rotation":[-142.73,39.63,-89.3],"translation":[7,-3,0],"scale":[1.36914,1.36914,1.36914]},"head":{"translation":[0,12.75,0],"scale":[0.79492,0.79492,0.79492]},"fixed":{"rotation":[-90,0,0],"translation":[0,0,-16],"scale":[2.00195,2.00195,2.00195]}},"groups":[{"name":"group","origin":[8,8,8],"color":0,"children":[{"name":"group","origin":[8,8,8],"color":0,"children":[0,1,2]}]}],"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_red_fish.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_red_fish.json new file mode 100644 index 000000000..229802567 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_red_fish.json @@ -0,0 +1 @@ +{"credit":"Made with Blockbench","textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[6.1106,0.04828,4.1196],"to":[10.1106,2.04828,13.1196],"rotation":{"angle":0,"axis":"y","origin":[8.1106,1.04828,7.8696]},"faces":{"north":{"uv":[1.3125,3.5,1.375,3.25],"rotation":90,"texture":"#0"},"east":{"uv":[1.3125,3.25,1.875,3.3125],"rotation":180,"texture":"#0"},"south":{"uv":[1.8125,3.5,1.875,3.25],"rotation":270,"texture":"#0"},"west":{"uv":[1.3125,3.4375,1.875,3.5],"texture":"#0"},"up":{"uv":[1.3125,3.25,1.875,3.5],"rotation":90,"texture":"#0"},"down":{"uv":[1.3125,3.5,1.875,3.25],"rotation":270,"texture":"#0"}}},{"from":[6.1106,1.04828,1.1196],"to":[11.1106,1.04828,13.1196],"rotation":{"angle":0,"axis":"y","origin":[8.1106,1.04828,7.8696]},"faces":{"up":{"uv":[1.125,3.1875,1.875,3.5],"rotation":90,"texture":"#0"},"down":{"uv":[1.125,3.5,1.875,3.1875],"rotation":270,"texture":"#0"}}},{"from":[7.6106,-1.95172,7.6196],"to":[7.6106,4.04828,9.6196],"rotation":{"angle":0,"axis":"y","origin":[8.1106,1.04828,7.8696]},"faces":{"east":{"uv":[1.4375,3.5625,1.5625,3.9375],"rotation":180,"texture":"#0"},"west":{"uv":[1.4375,3.5625,1.5625,3.9375],"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[-91,0,0],"translation":[0,4.75,-5.75],"scale":[1.03828,1.03828,1.03828]},"thirdperson_lefthand":{"rotation":[-91,0,0],"translation":[0.25,4.75,-5.75],"scale":[1.03828,1.03828,1.03828]},"firstperson_righthand":{"rotation":[-145,-13,-180],"translation":[7.75,4.25,-0.5],"scale":[0.75352,0.75352,0.75352]},"firstperson_lefthand":{"rotation":[-145,-13,-180],"translation":[7.75,4.25,-0.5],"scale":[0.75352,0.75352,0.75352]},"ground":{"translation":[0,4.5,0],"scale":[0.41406,0.41406,0.41406]},"gui":{"rotation":[-142.73,39.63,-89.3],"translation":[7,-3,0],"scale":[1.36914,1.36914,1.36914]},"head":{"translation":[0,12.75,0],"scale":[0.79492,0.79492,0.79492]},"fixed":{"rotation":[-90,0,0],"translation":[0,0,-16],"scale":[2.00195,2.00195,2.00195]}},"groups":[{"name":"group","origin":[8,8,8],"color":0,"children":[{"name":"group","origin":[8,8,8],"color":0,"children":[0,1,2]}]}],"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_stand.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_stand.json new file mode 100644 index 000000000..56fa33049 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_stand.json @@ -0,0 +1 @@ +{"credit":"Made with Blockbench","texture_size":[256,256],"textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[20,4,1],"to":[22,28,3],"rotation":{"angle":0,"axis":"y","origin":[20,4,1]},"faces":{"north":{"uv":[15.75,0,16,3],"texture":"#0"},"east":{"uv":[16,0,15.75,3],"texture":"#0"},"south":{"uv":[15.75,0,16,3],"texture":"#0"},"west":{"uv":[16,0,15.75,3],"texture":"#0"},"up":{"uv":[15.75,3.0625,16,3.3125],"texture":"#0"},"down":{"uv":[15.75,3.375,16,3.625],"texture":"#0"}}},{"from":[-6,4,1],"to":[-4,28,3],"rotation":{"angle":0,"axis":"y","origin":[-4,4,1]},"faces":{"north":{"uv":[16,0,15.75,3],"texture":"#0"},"east":{"uv":[15.75,0,16,3],"texture":"#0"},"south":{"uv":[16,0,15.75,3],"texture":"#0"},"west":{"uv":[15.75,0,16,3],"texture":"#0"},"up":{"uv":[16,3.0625,15.75,3.3125],"texture":"#0"},"down":{"uv":[16,3.375,15.75,3.625],"texture":"#0"}}},{"from":[-7,19,15.5],"to":[23,20.5,17],"rotation":{"angle":0,"axis":"z","origin":[10,19.5,16]},"faces":{"north":{"uv":[11.625,0.5,15.375,0.6875],"texture":"#0"},"east":{"uv":[12.875,0,13.0625,0.1875],"texture":"#0"},"south":{"uv":[11.625,0.75,15.375,0.9375],"texture":"#0"},"west":{"uv":[12.875,0,13.0625,0.1875],"texture":"#0"},"up":{"uv":[11.625,0.5,15.375,0.6875],"texture":"#0"},"down":{"uv":[15.375,0.5,11.625,0.6875],"texture":"#0"}}},{"from":[-7,24.93159,1.17987],"to":[23,26.43159,2.67987],"rotation":{"angle":0,"axis":"z","origin":[6,25.43159,2.17987]},"faces":{"north":{"uv":[11.625,0.75,15.375,0.9375],"texture":"#0"},"east":{"uv":[12.875,0,13.0625,0.1875],"texture":"#0"},"south":{"uv":[11.625,0.5,15.375,0.6875],"texture":"#0"},"west":{"uv":[12.875,0,13.0625,0.1875],"texture":"#0"},"up":{"uv":[15.375,1.1875,11.625,1],"texture":"#0"},"down":{"uv":[11.625,0.6875,15.375,0.5],"texture":"#0"}}},{"from":[20.25,19,0],"to":[21.75,20.5,18],"rotation":{"angle":0,"axis":"y","origin":[21,19.75,3]},"faces":{"north":{"uv":[12.875,0,13.0625,0.1875],"rotation":180,"texture":"#0"},"east":{"uv":[13.125,0,15.375,0.1875],"rotation":180,"texture":"#0"},"south":{"uv":[12.625,0,12.8125,0.1875],"rotation":180,"texture":"#0"},"west":{"uv":[15.375,0,13.125,0.1875],"rotation":180,"texture":"#0"},"up":{"uv":[15.375,0,13.125,0.1875],"rotation":270,"texture":"#0"},"down":{"uv":[13.125,0,15.375,0.1875],"rotation":270,"texture":"#0"}}},{"from":[-5.75,19,0],"to":[-4.25,20.5,18],"rotation":{"angle":0,"axis":"y","origin":[-5,19.75,3]},"faces":{"north":{"uv":[12.875,0,13.0625,0.1875],"rotation":180,"texture":"#0"},"east":{"uv":[13.125,0,15.375,0.1875],"rotation":180,"texture":"#0"},"south":{"uv":[12.625,0,12.8125,0.1875],"rotation":180,"texture":"#0"},"west":{"uv":[15.375,0,13.125,0.1875],"rotation":180,"texture":"#0"},"up":{"uv":[15.375,0,13.125,0.1875],"rotation":270,"texture":"#0"},"down":{"uv":[13.125,0,15.375,0.1875],"rotation":270,"texture":"#0"}}},{"from":[20.25,22.11294,2.0279],"to":[21.75,23.61294,16.0279],"rotation":{"angle":22.5,"axis":"x","origin":[21,22.86294,11.0279]},"faces":{"north":{"uv":[15.5625,0,15.75,0.1875],"rotation":180,"texture":"#0"},"east":{"uv":[13.625,0.25,15.375,0.4375],"rotation":180,"texture":"#0"},"south":{"uv":[15.5625,0,15.75,0.1875],"rotation":180,"texture":"#0"},"west":{"uv":[15.375,0.25,13.625,0.4375],"rotation":180,"texture":"#0"},"up":{"uv":[15.375,0.25,13.625,0.4375],"rotation":270,"texture":"#0"},"down":{"uv":[13.625,0.25,15.375,0.4375],"rotation":270,"texture":"#0"}}},{"from":[-5.75,22.11294,2.0279],"to":[-4.25,23.61294,16.0279],"rotation":{"angle":22.5,"axis":"x","origin":[-5,22.86294,11.0279]},"faces":{"north":{"uv":[15.5625,0,15.75,0.1875],"rotation":180,"texture":"#0"},"east":{"uv":[13.625,0.25,15.375,0.4375],"rotation":180,"texture":"#0"},"south":{"uv":[15.5625,0,15.75,0.1875],"rotation":180,"texture":"#0"},"west":{"uv":[15.375,0.25,13.625,0.4375],"rotation":180,"texture":"#0"},"up":{"uv":[15.375,0.25,13.625,0.4375],"rotation":270,"texture":"#0"},"down":{"uv":[13.625,0.25,15.375,0.4375],"rotation":270,"texture":"#0"}}},{"from":[20,4,15],"to":[22,23,17],"rotation":{"angle":0,"axis":"y","origin":[20,4,15]},"faces":{"north":{"uv":[15.4375,0,15.6875,2.375],"texture":"#0"},"east":{"uv":[15.6875,0,15.4375,2.375],"texture":"#0"},"south":{"uv":[15.4375,0,15.6875,2.375],"texture":"#0"},"west":{"uv":[15.6875,0,15.4375,2.375],"texture":"#0"},"up":{"uv":[15.75,3.0625,16,3.3125],"texture":"#0"},"down":{"uv":[15.75,3.375,16,3.625],"texture":"#0"}}},{"from":[-6,4,15],"to":[-4,23,17],"rotation":{"angle":0,"axis":"y","origin":[-4,4,15]},"faces":{"north":{"uv":[15.6875,0,15.4375,2.375],"texture":"#0"},"east":{"uv":[15.4375,0,15.6875,2.375],"texture":"#0"},"south":{"uv":[15.6875,0,15.4375,2.375],"texture":"#0"},"west":{"uv":[15.4375,0,15.6875,2.375],"texture":"#0"},"up":{"uv":[16,3.0625,15.75,3.3125],"texture":"#0"},"down":{"uv":[16,3.375,15.75,3.625],"texture":"#0"}}},{"from":[-4.5,23.15668,2.1278],"to":[20.5,23.65668,17.6278],"rotation":{"angle":22.5,"axis":"x","origin":[10,23.65668,9.3778]},"faces":{"east":{"uv":[8.4375,2.3125,8.5,4.25],"rotation":90,"texture":"#0"},"west":{"uv":[8.4375,2.3125,8.5,4.25],"rotation":90,"texture":"#0"},"up":{"uv":[8.4375,2.3125,11.5625,4.25],"texture":"#0"},"down":{"uv":[8.4375,4.25,11.5625,2.3125],"texture":"#0"}}},{"from":[-4,9.5,16.9995],"to":[20,20.5,16.9995],"rotation":{"angle":0,"axis":"x","origin":[10,11.25,16.9995]},"faces":{"north":{"uv":[11.625,4.25,14.625,2.875],"rotation":180,"texture":"#0"},"south":{"uv":[11.625,2.875,14.625,4.25],"texture":"#0"}}},{"from":[-4,21.93159,1.17987],"to":[20,26.43159,1.17987],"rotation":{"angle":0,"axis":"x","origin":[11,17.18159,1.17987]},"faces":{"north":{"uv":[11.625,2.8125,14.625,2.25],"rotation":180,"texture":"#0"},"south":{"uv":[11.625,2.25,14.625,2.8125],"texture":"#0"}}},{"from":[-4,18.93159,1.15448],"to":[20,26.93159,1.15448],"rotation":{"angle":0,"axis":"x","origin":[11,17.68159,1.15448]},"faces":{"north":{"uv":[8.4375,1,11.4375,0],"rotation":180,"texture":"#0"},"south":{"uv":[8.4375,0,11.4375,1],"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[75,45,0],"translation":[1.75,5.5,1],"scale":[0.375,0.375,0.375]},"thirdperson_lefthand":{"rotation":[75,45,0],"translation":[1,5.25,2.25],"scale":[0.375,0.375,0.375]},"firstperson_righthand":{"rotation":[0,86.25,0],"translation":[0.5,1.25,3.25],"scale":[0.4,0.4,0.4]},"firstperson_lefthand":{"rotation":[0,84.25,0],"translation":[0.5,1.25,3.5],"scale":[0.4,0.4,0.4]},"ground":{"translation":[0,3,-0.25],"scale":[0.25,0.25,0.25]},"gui":{"rotation":[30,225,0],"translation":[0.5,-2.5,0],"scale":[0.42578,0.42578,0.42578]},"head":{"translation":[0,12.75,-11.25],"scale":[0.79492,0.79492,0.79492]},"fixed":{"rotation":[-90,0,0],"translation":[0,-17,-16],"scale":[2.00195,2.00195,2.00195]}},"groups":[{"name":"group","origin":[-16,0,28],"color":0,"children":[{"name":"group","origin":[8,8,8],"color":0,"children":[0,1,2,3,4,5,6,7,8,9]},{"name":"group","origin":[-16,0,28],"color":0,"children":[10,11,12,13]}]}],"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_table.json b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_table.json new file mode 100644 index 000000000..cef25b468 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/fisherman_props/fisherman_table.json @@ -0,0 +1 @@ +{"credit":"Made with Blockbench","texture_size":[256,256],"textures":{"0":"omc_daily_events:fisherman_props/fisherman","particle":"omc_daily_events:fisherman_props/fisherman"},"elements":[{"from":[16,0,0],"to":[32,12,16],"rotation":{"angle":0,"axis":"y","origin":[16,0,0]},"faces":{"north":{"uv":[4.25,6.5,5.25,7.25],"texture":"#0"},"east":{"uv":[4.25,6.5,5.25,7.25],"texture":"#0"},"south":{"uv":[4.25,6.5,5.25,7.25],"texture":"#0"},"west":{"uv":[4.25,6.5,5.25,7.25],"texture":"#0"},"up":{"uv":[3.1875,8.125,4.1875,9.125],"texture":"#0"},"down":{"uv":[3.1875,7.0625,4.1875,8.0625],"texture":"#0"}}},{"from":[-16,0,0],"to":[0,12,16],"rotation":{"angle":0,"axis":"y","origin":[-16,0,0]},"faces":{"north":{"uv":[4.25,6.5,5.25,7.25],"texture":"#0"},"east":{"uv":[4.25,6.5,5.25,7.25],"texture":"#0"},"south":{"uv":[4.25,6.5,5.25,7.25],"texture":"#0"},"west":{"uv":[4.25,6.5,5.25,7.25],"texture":"#0"},"up":{"uv":[3.1875,8.125,4.1875,9.125],"texture":"#0"},"down":{"uv":[3.1875,7.0625,4.1875,8.0625],"texture":"#0"}}},{"from":[-16,14,0],"to":[32,16,16],"rotation":{"angle":0,"axis":"y","origin":[-32,10,0]},"faces":{"north":{"uv":[5.375,6.3125,8.375,6.375],"texture":"#0"},"east":{"uv":[5.375,6.3125,5.4375,7.3125],"rotation":90,"texture":"#0"},"south":{"uv":[5.375,6.3125,8.375,6.375],"texture":"#0"},"west":{"uv":[5.375,6.3125,5.4375,7.3125],"rotation":90,"texture":"#0"},"up":{"uv":[8.375,7.3125,5.375,6.3125],"texture":"#0"},"down":{"uv":[5.375,6.3125,8.375,7.3125],"texture":"#0"}}},{"from":[17,12,1],"to":[31,14,15],"rotation":{"angle":0,"axis":"y","origin":[-32,8,0]},"faces":{"north":{"uv":[4.25,8.4375,5.125,8.5625],"texture":"#0"},"east":{"uv":[4.25,8.4375,5.125,8.5625],"texture":"#0"},"south":{"uv":[4.25,8.4375,5.125,8.5625],"texture":"#0"},"west":{"uv":[4.25,8.4375,5.125,8.5625],"texture":"#0"}}},{"from":[-15,12,1],"to":[-1,14,15],"rotation":{"angle":0,"axis":"y","origin":[-64,8,0]},"faces":{"north":{"uv":[4.25,8.4375,5.125,8.5625],"texture":"#0"},"east":{"uv":[4.25,8.4375,5.125,8.5625],"texture":"#0"},"south":{"uv":[4.25,8.4375,5.125,8.5625],"texture":"#0"},"west":{"uv":[4.25,8.4375,5.125,8.5625],"texture":"#0"}}}],"gui_light":"front","display":{"thirdperson_righthand":{"rotation":[75,45,0],"translation":[5.5,7.25,3.25],"scale":[0.375,0.375,0.375]},"thirdperson_lefthand":{"rotation":[75,45,0],"translation":[5.5,7.25,1.5],"scale":[0.375,0.375,0.375]},"firstperson_righthand":{"rotation":[0,75.75,0],"translation":[5.25,2.75,1.5],"scale":[0.4,0.4,0.4]},"firstperson_lefthand":{"rotation":[0,75.75,0],"translation":[5.25,2.75,2],"scale":[0.4,0.4,0.4]},"ground":{"translation":[0,3,0],"scale":[0.25,0.25,0.25]},"gui":{"rotation":[30,225,0],"translation":[0,-0.25,0],"scale":[0.33398,0.33398,0.33398]},"head":{"translation":[0,12.75,0],"scale":[0.79492,0.79492,0.79492]},"fixed":{"rotation":[-90,0,0],"translation":[0,0,-16],"scale":[2.00195,2.00195,2.00195]}},"mcmodels":"47e9fc11ef703093a1d6a70bdf75f953"} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/lootbox/epic_box.json b/src/main/resources/contents/omc_daily_events/models/lootbox/epic_box.json new file mode 100644 index 000000000..8016a24a1 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/lootbox/epic_box.json @@ -0,0 +1,1173 @@ +{ + "texture_size": [128, 128], + "textures": { + "0": "omc_daily_events:lootbox/epic_box", + "particle": "omc_daily_events:lootbox/epic_box" + }, + "elements": [ + { + "from": [-2, 0, 2], + "to": [18, 15, 14], + "faces": { + "north": {"uv": [3, 3.75, 5.5, 5.625], "texture": "#0"}, + "east": {"uv": [0, 5.875, 1.5, 7.75], "texture": "#0"}, + "south": {"uv": [0, 4, 2.5, 5.875], "texture": "#0"}, + "west": {"uv": [5.5, 6, 7, 7.875], "texture": "#0"}, + "up": {"uv": [8, 4.5, 5.5, 3], "texture": "#0"}, + "down": {"uv": [8, 4.5, 5.5, 6], "texture": "#0"} + } + }, + { + "from": [3, 15, 2], + "to": [13, 17, 14], + "faces": { + "north": {"uv": [0.625, 4, 1.875, 4.25], "texture": "#0"}, + "east": {"uv": [0, 5.875, 1.5, 6.125], "texture": "#0"}, + "south": {"uv": [0.625, 4, 1.875, 4.25], "texture": "#0"}, + "west": {"uv": [5.5, 6, 7, 6.25], "texture": "#0"}, + "up": {"uv": [7.375, 4.5, 6.125, 3], "texture": "#0"}, + "down": {"uv": [6.75, 4.5, 5.5, 6], "texture": "#0"} + } + }, + { + "from": [-2, 0, 13.8], + "to": [18, 2.8, 14.8], + "faces": { + "north": {"uv": [3, 3.75, 5.5, 4], "texture": "#0"}, + "east": {"uv": [0, 5.875, 0.125, 6.125], "texture": "#0"}, + "south": {"uv": [0, 5.5, 2.5, 5.875], "texture": "#0"}, + "west": {"uv": [5.5, 6, 5.625, 6.25], "texture": "#0"}, + "up": {"uv": [5.5, 3.5, 3, 3.375], "texture": "#0"}, + "down": {"uv": [8, 4.5, 5.5, 4.625], "texture": "#0"} + } + }, + { + "from": [-2, 0, 1.2], + "to": [18, 2.8, 2.2], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 16]}, + "faces": { + "north": {"uv": [2.5, 5.5, 0, 5.875], "texture": "#0"}, + "east": {"uv": [0.125, 5.875, 0, 6.125], "texture": "#0"}, + "south": {"uv": [5.5, 3.75, 3, 4], "texture": "#0"}, + "west": {"uv": [5.625, 6, 5.5, 6.25], "texture": "#0"}, + "up": {"uv": [5.5, 3.375, 3, 3.5], "texture": "#0"}, + "down": {"uv": [8, 4.625, 5.5, 4.5], "texture": "#0"} + } + }, + { + "from": [17.5, 0, 2.7], + "to": [18.5, 2.8, 13.7], + "rotation": {"angle": 0, "axis": "y", "origin": [22, 1.4, 1.7]}, + "faces": { + "north": {"uv": [5.625, 6, 5.5, 6.35], "texture": "#0"}, + "east": {"uv": [1.875, 5.5, 0.5, 5.85], "texture": "#0"}, + "south": {"uv": [0.125, 5.875, 0, 6.125], "texture": "#0"}, + "west": {"uv": [5.5, 3.75, 3, 4], "texture": "#0"}, + "up": {"uv": [5.5, 3.375, 3, 3.5], "rotation": 90, "texture": "#0"}, + "down": {"uv": [8, 4.625, 5.5, 4.5], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [-2.5, 0, 2.7], + "to": [-1.5, 2.8, 13.7], + "rotation": {"angle": 0, "axis": "y", "origin": [-6, 1.4, 1.7]}, + "faces": { + "north": {"uv": [5.5, 6, 5.625, 6.35], "texture": "#0"}, + "east": {"uv": [3, 3.75, 5.5, 4], "texture": "#0"}, + "south": {"uv": [0, 5.875, 0.125, 6.125], "texture": "#0"}, + "west": {"uv": [0.5, 5.5, 1.875, 5.85], "texture": "#0"}, + "up": {"uv": [5.5, 3.5, 3, 3.375], "rotation": 90, "texture": "#0"}, + "down": {"uv": [8, 4.5, 5.5, 4.625], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [17.2, 10.3, 2], + "to": [19.2, 15.3, 14], + "rotation": {"angle": 22.5, "axis": "z", "origin": [18.5, 12.5, 8]}, + "faces": { + "north": {"uv": [3, 3.75, 3.25, 4.375], "texture": "#0"}, + "east": {"uv": [0, 5.875, 1.5, 6.5], "texture": "#0"}, + "south": {"uv": [0, 4, 0.25, 4.625], "texture": "#0"}, + "west": {"uv": [5.5, 6, 7, 6.625], "texture": "#0"}, + "up": {"uv": [5.75, 4.5, 5.5, 3], "texture": "#0"}, + "down": {"uv": [5.75, 4.5, 5.5, 6], "texture": "#0"} + } + }, + { + "from": [-3.2, 10.3, 2], + "to": [-1.2, 15.3, 14], + "rotation": {"angle": -22.5, "axis": "z", "origin": [-2.5, 12.5, 8]}, + "faces": { + "north": {"uv": [3.25, 3.75, 3, 4.375], "texture": "#0"}, + "east": {"uv": [7, 6, 5.5, 6.625], "texture": "#0"}, + "south": {"uv": [0.25, 4, 0, 4.625], "texture": "#0"}, + "west": {"uv": [1.5, 5.875, 0, 6.5], "texture": "#0"}, + "up": {"uv": [5.5, 4.5, 5.75, 3], "texture": "#0"}, + "down": {"uv": [5.5, 4.5, 5.75, 6], "texture": "#0"} + } + }, + { + "from": [17.30803, 10.86236, 13.3], + "to": [19.30803, 15.26236, 15.3], + "rotation": {"angle": 0, "axis": "z", "origin": [18.10803, 13.36236, 14.5]}, + "faces": { + "north": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "east": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "south": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "west": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "up": {"uv": [5.75, 4.5, 5.5, 3], "texture": "#0"}, + "down": {"uv": [5.75, 4.5, 5.5, 6], "texture": "#0"} + } + }, + { + "from": [17.40803, 14.56236, 13.2], + "to": [19.40803, 16.56236, 15.4], + "shade": false, + "rotation": {"angle": -45, "axis": "z", "origin": [18.40803, 15.76236, 14.3]}, + "faces": { + "north": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "east": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "up": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"} + } + }, + { + "from": [-3.30803, 10.86236, 13.3], + "to": [-1.30803, 15.26236, 15.3], + "rotation": {"angle": 0, "axis": "z", "origin": [-2.10803, 13.36236, 14.5]}, + "faces": { + "north": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "east": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "south": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "west": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "up": {"uv": [5.5, 4.5, 5.75, 3], "texture": "#0"}, + "down": {"uv": [5.5, 4.5, 5.75, 6], "texture": "#0"} + } + }, + { + "from": [-3.40803, 14.56236, 13.2], + "to": [-1.40803, 16.56236, 15.4], + "rotation": {"angle": 45, "axis": "z", "origin": [-2.40803, 15.76236, 14.3]}, + "faces": { + "north": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "east": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "up": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"} + } + }, + { + "from": [17.30803, 10.86236, 1.3], + "to": [19.30803, 15.26236, 3.3], + "rotation": {"angle": 0, "axis": "z", "origin": [18.10803, 13.36236, 2.5]}, + "faces": { + "north": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "east": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "south": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "west": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "up": {"uv": [5.75, 4.5, 5.5, 3], "texture": "#0"}, + "down": {"uv": [5.75, 4.5, 5.5, 6], "texture": "#0"} + } + }, + { + "from": [17.40803, 14.56236, 1.2], + "to": [19.40803, 16.56236, 3.4], + "rotation": {"angle": -45, "axis": "z", "origin": [18.40803, 15.76236, 2.3]}, + "faces": { + "north": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "east": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "up": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"} + } + }, + { + "from": [-3.30803, 10.86236, 1.3], + "to": [-1.30803, 15.26236, 3.3], + "rotation": {"angle": 0, "axis": "z", "origin": [-2.10803, 13.36236, 2.5]}, + "faces": { + "north": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "east": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "south": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "west": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "up": {"uv": [5.5, 4.5, 5.75, 3], "texture": "#0"}, + "down": {"uv": [5.5, 4.5, 5.75, 6], "texture": "#0"} + } + }, + { + "from": [-3.40803, 14.56236, 1.2], + "to": [-1.40803, 16.56236, 3.4], + "rotation": {"angle": 45, "axis": "z", "origin": [-2.40803, 15.76236, 2.3]}, + "faces": { + "north": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "east": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "up": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"} + } + }, + { + "from": [-2.1, 10, 15], + "to": [18.1, 15, 17], + "rotation": {"angle": -22.5, "axis": "x", "origin": [8, 7.5, 14.5]}, + "faces": { + "north": {"uv": [3, 3.75, 5.5, 4.375], "texture": "#0"}, + "east": {"uv": [0, 5.875, 0.25, 6.5], "texture": "#0"}, + "south": {"uv": [0, 4, 2.5, 4.625], "texture": "#0"}, + "west": {"uv": [5.5, 6, 5.75, 6.625], "texture": "#0"}, + "up": {"uv": [8, 3.25, 5.5, 3], "texture": "#0"}, + "down": {"uv": [8, 4.5, 5.5, 4.75], "texture": "#0"} + } + }, + { + "from": [-2.1, 10, -1], + "to": [18.1, 15, 1], + "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 7.5, 1.5]}, + "faces": { + "north": {"uv": [2.5, 4, 0, 4.625], "texture": "#0"}, + "east": {"uv": [0.25, 5.875, 0, 6.5], "texture": "#0"}, + "south": {"uv": [5.5, 3.75, 3, 4.375], "texture": "#0"}, + "west": {"uv": [5.75, 6, 5.5, 6.625], "texture": "#0"}, + "up": {"uv": [8, 3, 5.5, 3.25], "texture": "#0"}, + "down": {"uv": [8, 4.75, 5.5, 4.5], "texture": "#0"} + } + }, + { + "from": [-4, 0, 0], + "to": [1, 1, 5], + "faces": { + "north": {"uv": [1.5, 7.375, 2.125, 7.5], "texture": "#0"}, + "east": {"uv": [4.75, 7.75, 5.375, 7.875], "texture": "#0"}, + "south": {"uv": [8, 5.875, 8.625, 6], "texture": "#0"}, + "west": {"uv": [8.375, 3.875, 9, 4], "texture": "#0"}, + "up": {"uv": [0.625, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [2.125, 6.5, 1.5, 7.125], "texture": "#0"} + } + }, + { + "from": [-3, 1, 1], + "to": [0, 8, 4], + "faces": { + "north": {"uv": [2.5, 4, 2.875, 4.875], "texture": "#0"}, + "east": {"uv": [2.125, 5.875, 2.5, 6.75], "texture": "#0"}, + "south": {"uv": [1.875, 8, 2.25, 8.875], "texture": "#0"}, + "west": {"uv": [8, 1.875, 8.375, 2.75], "texture": "#0"}, + "up": {"uv": [5.25, 8.625, 4.875, 8.25], "texture": "#0"}, + "down": {"uv": [5.625, 8.25, 5.25, 8.625], "texture": "#0"} + } + }, + { + "from": [-3, 1, 12], + "to": [0, 8, 15], + "faces": { + "north": {"uv": [2.25, 8, 2.625, 8.875], "texture": "#0"}, + "east": {"uv": [2.625, 8, 3, 8.875], "texture": "#0"}, + "south": {"uv": [8, 2.75, 8.375, 3.625], "texture": "#0"}, + "west": {"uv": [3, 8, 3.375, 8.875], "texture": "#0"}, + "up": {"uv": [6, 8.625, 5.625, 8.25], "texture": "#0"}, + "down": {"uv": [6.375, 8.25, 6, 8.625], "texture": "#0"} + } + }, + { + "from": [-4, 0, 11], + "to": [1, 1, 16], + "faces": { + "north": {"uv": [8.375, 4, 9, 4.125], "texture": "#0"}, + "east": {"uv": [8.375, 4.125, 9, 4.25], "texture": "#0"}, + "south": {"uv": [8.375, 4.25, 9, 4.375], "texture": "#0"}, + "west": {"uv": [8.375, 4.375, 9, 4.5], "texture": "#0"}, + "up": {"uv": [0.625, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 0.625, 8.375], "texture": "#0"} + } + }, + { + "from": [16, 1, 12], + "to": [19, 8, 15], + "faces": { + "north": {"uv": [3.375, 8, 3.75, 8.875], "texture": "#0"}, + "east": {"uv": [8, 3.625, 8.375, 4.5], "texture": "#0"}, + "south": {"uv": [3.75, 8, 4.125, 8.875], "texture": "#0"}, + "west": {"uv": [4.125, 8, 4.5, 8.875], "texture": "#0"}, + "up": {"uv": [6.75, 8.625, 6.375, 8.25], "texture": "#0"}, + "down": {"uv": [0.375, 8.375, 0, 8.75], "texture": "#0"} + } + }, + { + "from": [15, 0, 11], + "to": [20, 1, 16], + "faces": { + "north": {"uv": [8.375, 4.5, 9, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 9, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [0.625, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [8.625, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [20, 0, 11], + "to": [21, 1, 16], + "faces": { + "north": {"uv": [8.375, 4.5, 8.5, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 8.5, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [0.125, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [8.125, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [20, 0, 0], + "to": [21, 1, 5], + "faces": { + "north": {"uv": [8.375, 4.5, 8.5, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 8.5, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [0.125, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [8.125, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [-5, 0, 0], + "to": [-4, 1, 5], + "faces": { + "north": {"uv": [8.375, 4.5, 8.5, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 8.5, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [0.125, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [8.125, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [-5, 0, 11], + "to": [-4, 1, 16], + "faces": { + "north": {"uv": [8.375, 4.5, 8.5, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 8.5, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [0.125, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [8.125, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [16, 1, 1], + "to": [19, 8, 4], + "faces": { + "north": {"uv": [8, 4.5, 8.375, 5.375], "texture": "#0"}, + "east": {"uv": [6.75, 8.125, 7.125, 9], "texture": "#0"}, + "south": {"uv": [7.125, 8.125, 7.5, 9], "texture": "#0"}, + "west": {"uv": [7.5, 8.125, 7.875, 9], "texture": "#0"}, + "up": {"uv": [0.75, 8.75, 0.375, 8.375], "texture": "#0"}, + "down": {"uv": [1.125, 8.375, 0.75, 8.75], "texture": "#0"} + } + }, + { + "from": [15, 0, 0], + "to": [20, 1, 5], + "faces": { + "north": {"uv": [8.375, 5, 9, 5.125], "texture": "#0"}, + "east": {"uv": [8.375, 5.125, 9, 5.25], "texture": "#0"}, + "south": {"uv": [8.375, 5.25, 9, 5.375], "texture": "#0"}, + "west": {"uv": [8.5, 8.125, 9.125, 8.25], "texture": "#0"}, + "up": {"uv": [0.625, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [8.625, 1.25, 8, 1.875], "texture": "#0"} + } + }, + { + "from": [15, 2, 11], + "to": [20, 3, 16], + "faces": { + "north": {"uv": [8.375, 4.5, 9, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 9, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [8.625, 0.625, 8, 0], "texture": "#0"}, + "down": {"uv": [8.625, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [-4, 2, 11], + "to": [1, 3, 16], + "faces": { + "north": {"uv": [8.375, 4, 9, 4.125], "texture": "#0"}, + "east": {"uv": [8.375, 4.125, 9, 4.25], "texture": "#0"}, + "south": {"uv": [8.375, 4.25, 9, 4.375], "texture": "#0"}, + "west": {"uv": [8.375, 4.375, 9, 4.5], "texture": "#0"}, + "up": {"uv": [0.625, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 0.625, 8.375], "texture": "#0"} + } + }, + { + "from": [-4, 2, 0], + "to": [1, 3, 5], + "faces": { + "north": {"uv": [1.5, 7.375, 2.125, 7.5], "texture": "#0"}, + "east": {"uv": [4.75, 7.75, 5.375, 7.875], "texture": "#0"}, + "south": {"uv": [8, 5.875, 8.625, 6], "texture": "#0"}, + "west": {"uv": [8.375, 3.875, 9, 4], "texture": "#0"}, + "up": {"uv": [2.125, 6.5, 1.5, 5.875], "texture": "#0"}, + "down": {"uv": [2.125, 6.5, 1.5, 7.125], "texture": "#0"} + } + }, + { + "from": [15, 2, 0], + "to": [20, 3, 5], + "faces": { + "north": {"uv": [8.375, 5, 9, 5.125], "texture": "#0"}, + "east": {"uv": [8.375, 5.125, 9, 5.25], "texture": "#0"}, + "south": {"uv": [8.375, 5.25, 9, 5.375], "texture": "#0"}, + "west": {"uv": [8.5, 8.125, 9.125, 8.25], "texture": "#0"}, + "up": {"uv": [1.875, 8.625, 1.25, 8], "texture": "#0"}, + "down": {"uv": [8.625, 1.25, 8, 1.875], "texture": "#0"} + } + }, + { + "from": [15, 6, 11], + "to": [20, 7, 16], + "faces": { + "north": {"uv": [8.375, 4.5, 9, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 9, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [8.625, 0.625, 8, 0], "texture": "#0"}, + "down": {"uv": [8.625, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [-4, 6, 11], + "to": [1, 7, 16], + "faces": { + "north": {"uv": [8.375, 4, 9, 4.125], "texture": "#0"}, + "east": {"uv": [8.375, 4.125, 9, 4.25], "texture": "#0"}, + "south": {"uv": [8.375, 4.25, 9, 4.375], "texture": "#0"}, + "west": {"uv": [8.375, 4.375, 9, 4.5], "texture": "#0"}, + "up": {"uv": [0.625, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 0.625, 8.375], "texture": "#0"} + } + }, + { + "from": [-4, 6, 0], + "to": [1, 7, 5], + "faces": { + "north": {"uv": [1.5, 7.375, 2.125, 7.5], "texture": "#0"}, + "east": {"uv": [4.75, 7.75, 5.375, 7.875], "texture": "#0"}, + "south": {"uv": [8, 5.875, 8.625, 6], "texture": "#0"}, + "west": {"uv": [8.375, 3.875, 9, 4], "texture": "#0"}, + "up": {"uv": [2.125, 6.5, 1.5, 5.875], "texture": "#0"}, + "down": {"uv": [2.125, 6.5, 1.5, 7.125], "texture": "#0"} + } + }, + { + "from": [15, 6, 0], + "to": [20, 7, 5], + "faces": { + "north": {"uv": [8.375, 5, 9, 5.125], "texture": "#0"}, + "east": {"uv": [8.375, 5.125, 9, 5.25], "texture": "#0"}, + "south": {"uv": [8.375, 5.25, 9, 5.375], "texture": "#0"}, + "west": {"uv": [8.5, 8.125, 9.125, 8.25], "texture": "#0"}, + "up": {"uv": [1.875, 8.625, 1.25, 8], "texture": "#0"}, + "down": {"uv": [8.625, 1.25, 8, 1.875], "texture": "#0"} + } + }, + { + "from": [5.5, 4, 14], + "to": [10.5, 8, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [4.5, 0, 0]}, + "faces": { + "north": {"uv": [8, 5.375, 8.625, 5.875], "texture": "#0"}, + "east": {"uv": [8.375, 1.875, 8.625, 2.375], "texture": "#0"}, + "south": {"uv": [7.875, 8.125, 8.5, 8.625], "texture": "#0"}, + "west": {"uv": [8.375, 2.375, 8.625, 2.875], "texture": "#0"}, + "up": {"uv": [2.125, 7.375, 1.5, 7.125], "texture": "#0"}, + "down": {"uv": [5.375, 7.5, 4.75, 7.75], "texture": "#0"} + } + }, + { + "from": [6.5, 5, 15], + "to": [9.5, 9, 17], + "shade": false, + "rotation": {"angle": 0, "axis": "y", "origin": [4.5, 0, 0]}, + "faces": { + "north": {"uv": [2.5, 4.875, 2.875, 5.375], "texture": "#0"}, + "east": {"uv": [8.375, 2.875, 8.625, 3.375], "texture": "#0"}, + "south": {"uv": [2.125, 6.75, 2.5, 7.25], "texture": "#0"}, + "west": {"uv": [8.375, 3.375, 8.625, 3.875], "texture": "#0"}, + "up": {"uv": [2.875, 5.625, 2.5, 5.375], "texture": "#0"}, + "down": {"uv": [2.5, 7.25, 2.125, 7.5], "texture": "#0"} + } + }, + { + "from": [7.2, 13.85, 13.85], + "to": [9.2, 15.85, 14.85], + "rotation": {"angle": -22.5, "axis": "x", "origin": [8.05, 14.9, 17.55]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [7.2, 11.85, 13.85], + "to": [9.2, 13.85, 14.85], + "rotation": {"angle": -22.5, "axis": "x", "origin": [8.05, 14.9, 17.55]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [7.2, 11.82922, 14.81272], + "to": [9.2, 13.82922, 15.81272], + "rotation": {"angle": -45, "axis": "z", "origin": [8.2, 12.82922, 14.61272]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [7.2, 3.12922, 15.21272], + "to": [9.2, 5.12922, 16.21272], + "rotation": {"angle": -45, "axis": "z", "origin": [8.2, 4.12922, 15.01272]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [12.6, 11.62922, 14.51272], + "to": [14.6, 13.62922, 15.51272], + "rotation": {"angle": -45, "axis": "z", "origin": [13.6, 12.62922, 14.31272]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [1.6, 11.62922, 14.51272], + "to": [3.6, 13.62922, 15.51272], + "rotation": {"angle": -45, "axis": "z", "origin": [2.6, 12.62922, 14.31272]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [13, 11, 1.3], + "to": [14, 16, 14.8], + "rotation": {"angle": 0, "axis": "y", "origin": [4.5, 0, 0]}, + "faces": { + "north": {"uv": [8.625, 0, 8.75, 0.5], "texture": "#0"}, + "east": {"uv": [1.5, 7.5, 3.125, 8], "texture": "#0"}, + "south": {"uv": [8.625, 0.5, 8.75, 1], "texture": "#0"}, + "west": {"uv": [3.125, 7.5, 4.75, 8], "texture": "#0"}, + "up": {"uv": [4.75, 9.625, 4.625, 8], "texture": "#0"}, + "down": {"uv": [4.875, 8.25, 4.75, 9.875], "texture": "#0"} + } + }, + { + "from": [13, 10, 14.8], + "to": [14, 15.5, 15.8], + "rotation": {"angle": -22.5, "axis": "x", "origin": [13.5, 13.25, 14.3]}, + "faces": { + "north": {"uv": [8.625, 0, 8.75, 0.5], "texture": "#0"}, + "east": {"uv": [1.5, 7.5, 3.125, 8], "texture": "#0"}, + "south": {"uv": [8.625, 0.5, 8.75, 1], "texture": "#0"}, + "west": {"uv": [3.125, 7.5, 4.75, 8], "texture": "#0"}, + "up": {"uv": [4.75, 9.625, 4.625, 8], "texture": "#0"}, + "down": {"uv": [4.875, 8.25, 4.75, 9.875], "texture": "#0"} + } + }, + { + "from": [2, 10, 14.8], + "to": [3, 15.5, 15.8], + "rotation": {"angle": -22.5, "axis": "x", "origin": [13.5, 13.25, 14.3]}, + "faces": { + "north": {"uv": [8.625, 0, 8.75, 0.5], "texture": "#0"}, + "east": {"uv": [1.5, 7.5, 3.125, 8], "texture": "#0"}, + "south": {"uv": [8.625, 0.5, 8.75, 1], "texture": "#0"}, + "west": {"uv": [3.125, 7.5, 4.75, 8], "texture": "#0"}, + "up": {"uv": [4.75, 9.625, 4.625, 8], "texture": "#0"}, + "down": {"uv": [4.875, 8.25, 4.75, 9.875], "texture": "#0"} + } + }, + { + "from": [2, 11, 1.3], + "to": [3, 16, 14.8], + "rotation": {"angle": 0, "axis": "y", "origin": [4.5, 0, 0]}, + "faces": { + "north": {"uv": [1.125, 8.375, 1.25, 8.875], "texture": "#0"}, + "east": {"uv": [7, 6.75, 8.625, 7.25], "texture": "#0"}, + "south": {"uv": [8.5, 8.25, 8.625, 8.75], "texture": "#0"}, + "west": {"uv": [7, 7.25, 8.625, 7.75], "texture": "#0"}, + "up": {"uv": [3, 5.625, 2.875, 4], "texture": "#0"}, + "down": {"uv": [4.625, 8, 4.5, 9.625], "texture": "#0"} + } + }, + { + "from": [-4, 8, 0], + "to": [20, 11, 16], + "faces": { + "north": {"uv": [7, 6, 10, 6.375], "texture": "#0"}, + "east": {"uv": [7, 7.75, 9, 8.125], "texture": "#0"}, + "south": {"uv": [7, 6.375, 10, 6.75], "texture": "#0"}, + "west": {"uv": [4.75, 7.875, 6.75, 8.25], "texture": "#0"}, + "up": {"uv": [3, 2, 0, 0], "texture": "#0"}, + "down": {"uv": [3, 2, 0, 4], "texture": "#0"} + } + }, + { + "from": [10.8, 16.6725, 8.5], + "to": [11.8, 17.7725, 9.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.5, 2.125, 8.625], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [11.8, 16.6725, 7.5], + "to": [12.8, 17.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.625, 2.125, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [10.8, 16.6725, 6.5], + "to": [11.8, 17.7725, 7.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [8.99289, 16.6725, 9.02132], + "to": [9.99289, 17.7725, 10.02132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 17.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [7.49289, 16.6725, 11.42132], + "to": [8.49289, 17.7725, 12.42132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 17.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [7.49289, 16.6725, 3.42132], + "to": [8.49289, 17.7725, 4.42132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 17.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [11.49289, 16.6725, 7.42132], + "to": [12.49289, 17.7725, 8.42132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 17.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [3.69289, 16.6725, 7.42132], + "to": [4.69289, 17.7725, 8.42132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 17.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [10.99289, 16.4725, 11.02132], + "to": [11.99289, 17.5725, 12.02132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 17.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [3.99289, 16.4725, 11.02132], + "to": [4.99289, 17.5725, 12.02132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 17.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [3.99289, 16.4725, 4.02132], + "to": [4.99289, 17.5725, 5.02132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 17.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [10.99289, 16.4725, 4.02132], + "to": [11.99289, 17.5725, 5.02132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 17.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [8.5, 16.6725, 7.5], + "to": [9.5, 17.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [7.5, 16.6725, 7.5], + "to": [8.5, 17.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [7.5, 16.6725, 6.5], + "to": [8.5, 17.7725, 7.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [7.5, 16.6725, 8.5], + "to": [8.5, 17.7725, 9.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [6.5, 16.6725, 7.5], + "to": [7.5, 17.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [5.99289, 16.6725, 5.92132], + "to": [6.99289, 17.7725, 6.92132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 17.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [4.2, 16.6725, 6.5], + "to": [5.2, 17.7725, 7.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "east": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "west": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2.75, 8.375, 2.875, 8.5], "texture": "#0"}, + "down": {"uv": [6.75, 8, 6.875, 7.875], "texture": "#0"} + } + }, + { + "from": [4.2, 16.6725, 7.5], + "to": [5.2, 17.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "east": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "west": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 8, 6.875, 7.875], "texture": "#0"} + } + }, + { + "from": [4.2, 16.6725, 8.5], + "to": [5.2, 17.7725, 9.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "east": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "west": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 8, 6.875, 7.875], "texture": "#0"} + } + }, + { + "from": [3.2, 16.6725, 7.5], + "to": [4.2, 17.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "east": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "west": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.625, 2.125, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 8, 6.875, 7.875], "texture": "#0"} + } + }, + { + "from": [8.99289, 16.6725, 5.92132], + "to": [9.99289, 17.7725, 6.92132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 17.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [10.8, 16.6725, 6.5], + "to": [11.8, 17.7725, 7.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "east": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "west": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 8, 6.75, 7.875], "texture": "#0"} + } + }, + { + "from": [10.8, 16.6725, 8.5], + "to": [11.8, 17.7725, 9.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "east": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "west": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 8, 6.75, 7.875], "texture": "#0"} + } + }, + { + "from": [10.8, 16.6725, 7.5], + "to": [11.8, 17.7725, 8.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "east": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "west": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 8, 6.75, 7.875], "texture": "#0"} + } + }, + { + "from": [11.8, 16.6725, 7.5], + "to": [12.8, 17.7725, 8.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "east": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "west": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.625, 2.125, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 8, 6.75, 7.875], "texture": "#0"} + } + }, + { + "from": [5.99289, 16.6725, 9.02132], + "to": [6.99289, 17.7725, 10.02132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 17.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [4.2, 16.6725, 8.5], + "to": [5.2, 17.7725, 9.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 7.875, 6.875, 8], "texture": "#0"} + } + }, + { + "from": [4.2, 16.6725, 7.5], + "to": [5.2, 17.7725, 8.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.5, 2.125, 8.625], "texture": "#0"}, + "down": {"uv": [6.75, 7.875, 6.875, 8], "texture": "#0"} + } + }, + { + "from": [3.2, 16.6725, 7.5], + "to": [4.2, 17.7725, 8.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.625, 2.125, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 7.875, 6.875, 8], "texture": "#0"} + } + }, + { + "from": [4.2, 16.6725, 6.5], + "to": [5.2, 17.7725, 7.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 7.875, 6.875, 8], "texture": "#0"} + } + }, + { + "from": [10.8, 16.6725, 7.5], + "to": [11.8, 17.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 17.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + } + ], + "display": { + "thirdperson_righthand": { + "translation": [0, 1.75, 0], + "scale": [0.21875, 0.21875, 0.21875] + }, + "thirdperson_lefthand": { + "translation": [0, 1.75, 0], + "scale": [0.21875, 0.21875, 0.21875] + }, + "firstperson_righthand": { + "translation": [2, 1.75, 0], + "scale": [0.21875, 0.21875, 0.21875] + }, + "firstperson_lefthand": { + "translation": [2, 1.75, 0], + "scale": [0.21875, 0.21875, 0.21875] + }, + "ground": { + "scale": [0.40039, 0.40039, 0.40039] + }, + "gui": { + "rotation": [22.75, -30.5, 0], + "scale": [0.49609, 0.49609, 0.49609] + }, + "head": { + "translation": [0, -30.35, 0], + "scale": [1.6, 1.6, 1.6] + }, + "fixed": { + "rotation": [-90, 0, 0], + "translation": [0, 0, -13.75], + "scale": [1.6, 1.6, 1.6] + } + }, + "groups": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + { + "name": "group", + "origin": [8, 15.2225, 8], + "color": 0, + "boneType": "", + "children": [51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/lootbox/fishing_furniture_chest.json b/src/main/resources/contents/omc_daily_events/models/lootbox/fishing_furniture_chest.json new file mode 100644 index 000000000..f83545d68 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/lootbox/fishing_furniture_chest.json @@ -0,0 +1,950 @@ +{ + "textures": { + "0": "omc_daily_events:lootbox/fishing_furniture/fishing_furniture_chest", + "1": "omc_daily_events:lootbox/fishing_furniture/fishing_furniture_animation", + "2": "omc_daily_events:lootbox/fishing_furniture/fishing_furniture_animation_2", + "particle": "omc_daily_events:lootbox/fishing_furniture/fishing_furniture_chest" + }, + "elements": [ + { + "from": [0, 2, 3], + "to": [16, 6, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [16, -11, -6]}, + "faces": { + "north": {"uv": [9, 8.25, 13, 9.25], "texture": "#0"}, + "east": {"uv": [10, 2.25, 12.75, 3.25], "texture": "#0"}, + "south": {"uv": [9, 9.25, 13, 10.25], "texture": "#0"}, + "west": {"uv": [10, 3.25, 12.75, 4.25], "texture": "#0"} + } + }, + { + "from": [-3, 0, 2], + "to": [19, 2, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 5, 14]}, + "faces": { + "north": {"uv": [10, 4.25, 15.5, 4.75], "texture": "#0"}, + "east": {"uv": [3.25, 11.25, 6.5, 11.75], "texture": "#0"}, + "south": {"uv": [10, 4.75, 15.5, 5.25], "texture": "#0"}, + "west": {"uv": [10, 11.25, 13.25, 11.75], "texture": "#0"}, + "up": {"uv": [5.5, 3.25, 0, 0], "texture": "#0"}, + "down": {"uv": [5.5, 3.25, 0, 6.5], "texture": "#0"} + } + }, + { + "from": [-1, 6, 2], + "to": [17, 8, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 6, 14]}, + "faces": { + "north": {"uv": [10, 5.25, 14.5, 5.75], "texture": "#0"}, + "east": {"uv": [10, 10.75, 13.25, 11.25], "texture": "#0"}, + "south": {"uv": [10, 5.75, 14.5, 6.25], "texture": "#0"}, + "west": {"uv": [0, 11.25, 3.25, 11.75], "texture": "#0"}, + "up": {"uv": [10, 3.25, 5.5, 0], "texture": "#0"}, + "down": {"uv": [10, 3.25, 5.5, 6.5], "texture": "#0"} + } + }, + { + "from": [-1, 11, 2], + "to": [17, 13, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 6, 14]}, + "faces": { + "north": {"uv": [8, 10.25, 12.5, 10.75], "texture": "#0"}, + "east": {"uv": [6.5, 11.5, 9.75, 12], "texture": "#0"}, + "south": {"uv": [0, 10.75, 4.5, 11.25], "texture": "#0"}, + "west": {"uv": [0, 11.75, 3.25, 12.25], "texture": "#0"}, + "up": {"uv": [4.5, 9.75, 0, 6.5], "texture": "#0"}, + "down": {"uv": [9, 6.5, 4.5, 9.75], "texture": "#0"} + } + }, + { + "from": [0, 8, 3], + "to": [16, 11, 14], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 6, 14]}, + "faces": { + "north": {"uv": [10, 0.75, 14, 1.5], "texture": "#0"}, + "east": {"uv": [4.5, 10.5, 7.25, 11.25], "texture": "#0"}, + "south": {"uv": [10, 1.5, 14, 2.25], "texture": "#0"}, + "west": {"uv": [7.25, 10.75, 10, 11.5], "texture": "#0"} + } + }, + { + "from": [0, 12, 5], + "to": [16, 15, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 6, 14]}, + "faces": { + "north": {"uv": [4, 9.75, 8, 10.5], "texture": "#0"}, + "east": {"uv": [3.25, 11.75, 5, 12.5], "texture": "#0"}, + "south": {"uv": [10, 0, 14, 0.75], "texture": "#0"}, + "west": {"uv": [3.25, 11.75, 5, 12.5], "texture": "#0"}, + "up": {"uv": [13, 8.25, 9, 6.5], "texture": "#0"} + } + }, + { + "from": [0, 11, 5], + "to": [16, 15, 8], + "rotation": {"angle": 45, "axis": "x", "origin": [8, 15, 5]}, + "faces": { + "north": {"uv": [0, 9.75, 4, 10.75], "texture": "#0"}, + "east": {"uv": [13.75, 8.5, 13, 9.5], "texture": "#0"}, + "west": {"uv": [13, 8.5, 13.75, 9.5], "texture": "#0"} + } + }, + { + "from": [0, 12, 12], + "to": [16, 15, 16], + "rotation": {"angle": 45, "axis": "x", "origin": [8, 15, 12]}, + "faces": { + "east": {"uv": [13, 8.5, 13.75, 9.5], "rotation": 90, "texture": "#0"}, + "west": {"uv": [13.75, 8.5, 13, 9.5], "rotation": 270, "texture": "#0"}, + "up": {"uv": [4, 9.75, 0, 10.75], "texture": "#0"} + } + }, + { + "from": [7, 5, 1], + "to": [9, 9, 3], + "faces": { + "north": {"uv": [12.75, 13.75, 13.25, 14.75], "texture": "#0"}, + "east": {"uv": [13.25, 13.75, 13.75, 14.75], "texture": "#0"}, + "south": {"uv": [13.75, 13.25, 14.25, 14.25], "texture": "#0"}, + "west": {"uv": [14, 0, 14.5, 1], "texture": "#0"}, + "up": {"uv": [3, 14.75, 2.5, 14.25], "texture": "#0"}, + "down": {"uv": [9.25, 14.25, 8.75, 14.75], "texture": "#0"} + } + }, + { + "from": [3, 2, 1], + "to": [8, 3.5, 3], + "rotation": {"angle": -22.5, "axis": "z", "origin": [8, 2, 2]}, + "faces": { + "north": {"uv": [0, 14.25, 1.25, 14.625], "texture": "#0"}, + "east": {"uv": [14.5, 14.25, 15, 14.625], "texture": "#0"}, + "south": {"uv": [1.25, 14.25, 2.5, 14.625], "texture": "#0"}, + "west": {"uv": [0, 14.75, 0.5, 15.125], "texture": "#0"}, + "up": {"uv": [5.75, 14.25, 4.5, 13.75], "texture": "#0"}, + "down": {"uv": [15, 6.25, 13.75, 6.75], "texture": "#0"} + } + }, + { + "from": [2, 2, 1.5], + "to": [3, 5.5, 2.5], + "rotation": {"angle": -22.5, "axis": "z", "origin": [8, 2, 2]}, + "faces": { + "north": {"uv": [14.5, 7.75, 14.75, 8.625], "texture": "#0"}, + "east": {"uv": [9.25, 14.5, 9.5, 15.375], "texture": "#0"}, + "south": {"uv": [9.5, 14.5, 9.75, 15.375], "texture": "#0"}, + "west": {"uv": [9.75, 14.5, 10, 15.375], "texture": "#0"}, + "up": {"uv": [7, 11.5, 6.75, 11.25], "texture": "#0"}, + "down": {"uv": [7.25, 11.25, 7, 11.5], "texture": "#0"} + } + }, + { + "from": [3, 5, 1.5], + "to": [4, 5.5, 2.5], + "rotation": {"angle": -22.5, "axis": "z", "origin": [8, 2, 2]}, + "faces": { + "north": {"uv": [13.25, 10, 13.5, 10.125], "texture": "#0"}, + "east": {"uv": [12.75, 13.25, 13, 13.375], "texture": "#0"}, + "south": {"uv": [13.5, 4, 13.75, 4.125], "texture": "#0"}, + "west": {"uv": [9.25, 13.5, 9.5, 13.625], "texture": "#0"}, + "up": {"uv": [11.75, 6.5, 11.5, 6.25], "texture": "#0"}, + "down": {"uv": [10, 11.5, 9.75, 11.75], "texture": "#0"} + } + }, + { + "from": [8, 2, 1], + "to": [13, 3.5, 3], + "rotation": {"angle": 22.5, "axis": "z", "origin": [8, 2, 2]}, + "faces": { + "north": {"uv": [1.25, 14.25, 0, 14.625], "texture": "#0"}, + "east": {"uv": [0.5, 14.75, 0, 15.125], "texture": "#0"}, + "south": {"uv": [2.5, 14.25, 1.25, 14.625], "texture": "#0"}, + "west": {"uv": [15, 14.25, 14.5, 14.625], "texture": "#0"}, + "up": {"uv": [4.5, 14.25, 5.75, 13.75], "texture": "#0"}, + "down": {"uv": [13.75, 6.25, 15, 6.75], "texture": "#0"} + } + }, + { + "from": [13, 2, 1.5], + "to": [14, 5.5, 2.5], + "rotation": {"angle": 22.5, "axis": "z", "origin": [8, 2, 2]}, + "faces": { + "north": {"uv": [14.75, 7.75, 14.5, 8.625], "texture": "#0"}, + "east": {"uv": [10, 14.5, 9.75, 15.375], "texture": "#0"}, + "south": {"uv": [9.75, 14.5, 9.5, 15.375], "texture": "#0"}, + "west": {"uv": [9.5, 14.5, 9.25, 15.375], "texture": "#0"}, + "up": {"uv": [6.75, 11.5, 7, 11.25], "texture": "#0"}, + "down": {"uv": [7, 11.25, 7.25, 11.5], "texture": "#0"} + } + }, + { + "from": [12, 5, 1.5], + "to": [13, 5.5, 2.5], + "rotation": {"angle": 22.5, "axis": "z", "origin": [8, 2, 2]}, + "faces": { + "north": {"uv": [13.5, 10, 13.25, 10.125], "texture": "#0"}, + "east": {"uv": [9.5, 13.5, 9.25, 13.625], "texture": "#0"}, + "south": {"uv": [13.75, 4, 13.5, 4.125], "texture": "#0"}, + "west": {"uv": [13, 13.25, 12.75, 13.375], "texture": "#0"}, + "up": {"uv": [11.5, 6.5, 11.75, 6.25], "texture": "#0"}, + "down": {"uv": [9.75, 11.5, 10, 11.75], "texture": "#0"} + } + }, + { + "from": [2.1, 16.6, -0.5], + "to": [4.9, 21.6, 2.5], + "rotation": {"angle": 22.5, "axis": "x", "origin": [3.5, 16.6, -0.5]}, + "faces": { + "north": {"uv": [9.5, 12.5, 10.25, 13.75], "texture": "#0"}, + "east": {"uv": [10.25, 12.5, 11, 13.75], "texture": "#0"}, + "south": {"uv": [12.75, 2.25, 13.5, 3.5], "texture": "#0"}, + "west": {"uv": [0, 13, 0.75, 14.25], "texture": "#0"}, + "up": {"uv": [9.25, 14.25, 8.5, 13.5], "texture": "#0"}, + "down": {"uv": [14.5, 6.75, 13.75, 7.5], "texture": "#0"} + } + }, + { + "from": [2, 12, 3], + "to": [5, 18, 6], + "rotation": {"angle": -45, "axis": "x", "origin": [3.5, 13, 3]}, + "faces": { + "north": {"uv": [11.5, 11.75, 12.25, 13.25], "texture": "#0"}, + "east": {"uv": [6.5, 12, 7.25, 13.5], "texture": "#0"}, + "south": {"uv": [7.25, 12, 8, 13.5], "texture": "#0"}, + "west": {"uv": [8, 12, 8.75, 13.5], "texture": "#0"}, + "up": {"uv": [14.5, 8.25, 13.75, 7.5], "texture": "#0"}, + "down": {"uv": [14.5, 8.25, 13.75, 9], "texture": "#0"} + } + }, + { + "from": [2.2, 19.25, 1.4], + "to": [4.8, 21.25, 7.4], + "rotation": {"angle": 0, "axis": "y", "origin": [3.5, 16.6, -0.5]}, + "faces": { + "north": {"uv": [3.5, 14, 4.25, 14.5], "texture": "#0"}, + "east": {"uv": [12.5, 10.25, 14, 10.75], "texture": "#0"}, + "south": {"uv": [14.25, 3.5, 15, 4], "texture": "#0"}, + "west": {"uv": [12.75, 3.5, 14.25, 4], "texture": "#0"}, + "up": {"uv": [5.75, 13.25, 5, 11.75], "texture": "#0"}, + "down": {"uv": [6.5, 11.75, 5.75, 13.25], "texture": "#0"} + } + }, + { + "from": [2.5, 17, 8.85], + "to": [4.5, 18.5, 13.85], + "rotation": {"angle": 22.5, "axis": "x", "origin": [3.5, 21.2, 7.32855]}, + "faces": { + "north": {"uv": [14.5, 9.5, 15, 9.875], "texture": "#0"}, + "east": {"uv": [14, 3, 15.25, 3.375], "texture": "#0"}, + "south": {"uv": [10, 14.5, 10.5, 14.875], "texture": "#0"}, + "west": {"uv": [14, 10, 15.25, 10.375], "texture": "#0"}, + "up": {"uv": [6.5, 14.5, 6, 13.25], "texture": "#0"}, + "down": {"uv": [12.25, 13.25, 11.75, 14.5], "texture": "#0"} + } + }, + { + "from": [3, 17, 13.85], + "to": [4, 20.5, 14.85], + "rotation": {"angle": 22.5, "axis": "x", "origin": [3.5, 21.2, 7.32855]}, + "faces": { + "north": {"uv": [5.75, 13.75, 6, 14.625], "texture": "#0"}, + "east": {"uv": [11.5, 14.25, 11.75, 15.125], "texture": "#0"}, + "south": {"uv": [14.25, 13.75, 14.5, 14.625], "texture": "#0"}, + "west": {"uv": [14.5, 0, 14.75, 0.875], "texture": "#0"}, + "up": {"uv": [10.25, 6.5, 10, 6.25], "texture": "#0"}, + "down": {"uv": [10.5, 6.25, 10.25, 6.5], "texture": "#0"} + } + }, + { + "from": [3, 20, 12.85], + "to": [4, 20.5, 13.85], + "rotation": {"angle": 22.5, "axis": "x", "origin": [3.5, 21.2, 7.32855]}, + "faces": { + "north": {"uv": [11.75, 6.25, 12, 6.375], "texture": "#0"}, + "east": {"uv": [12, 6.25, 12.25, 6.375], "texture": "#0"}, + "south": {"uv": [9.5, 12, 9.75, 12.125], "texture": "#0"}, + "west": {"uv": [3, 12.25, 3.25, 12.375], "texture": "#0"}, + "up": {"uv": [4.25, 10.75, 4, 10.5], "texture": "#0"}, + "down": {"uv": [4.5, 10.5, 4.25, 10.75], "texture": "#0"} + } + }, + { + "from": [2.3, 17.18483, 5.41443], + "to": [4.7, 21.18483, 7.41443], + "rotation": {"angle": -22.5, "axis": "x", "origin": [3.5, 21.2, 7.32855]}, + "faces": { + "north": {"uv": [13.75, 12.75, 13, 13.75], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8, 9.75, 9, 10.25], "rotation": 270, "texture": "#0"}, + "south": {"uv": [13.75, 12.75, 13, 11.75], "texture": "#0"}, + "west": {"uv": [13.75, 9, 14.75, 9.5], "rotation": 90, "texture": "#0"}, + "up": {"uv": [4.25, 14.25, 5, 14.75], "rotation": 180, "texture": "#0"}, + "down": {"uv": [5, 14.25, 5.75, 14.75], "texture": "#0"} + } + }, + { + "from": [-3, 4.55645, 2.63747], + "to": [0, 9.55645, 5.63747], + "rotation": {"angle": -22.5, "axis": "x", "origin": [-1.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [0.75, 13, 1.5, 14.25], "texture": "#0"}, + "east": {"uv": [1.5, 13, 2.25, 14.25], "texture": "#0"}, + "south": {"uv": [2.25, 13, 3, 14.25], "texture": "#0"}, + "west": {"uv": [13, 6.25, 13.75, 7.5], "texture": "#0"}, + "up": {"uv": [10, 14.5, 9.25, 13.75], "texture": "#0"}, + "down": {"uv": [10.75, 13.75, 10, 14.5], "texture": "#0"} + } + }, + { + "from": [-2.9, 1.97057, 4.93092], + "to": [0, 4.97057, 10.93092], + "rotation": {"angle": 0, "axis": "y", "origin": [-1.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [13.75, 11.75, 14.5, 12.5], "texture": "#0"}, + "east": {"uv": [0, 12.25, 1.5, 13], "texture": "#0"}, + "south": {"uv": [13.75, 12.5, 14.5, 13.25], "texture": "#0"}, + "west": {"uv": [1.5, 12.25, 3, 13], "texture": "#0"}, + "up": {"uv": [9.5, 13.5, 8.75, 12], "texture": "#0"}, + "down": {"uv": [13, 11.75, 12.25, 13.25], "texture": "#0"} + } + }, + { + "from": [-2.9, 10.4, 3.4], + "to": [0, 12.4, 9.4], + "rotation": {"angle": -45, "axis": "x", "origin": [-1.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [6.5, 14.25, 7.25, 14.75], "texture": "#0"}, + "east": {"uv": [13, 9.5, 14.5, 10], "texture": "#0"}, + "south": {"uv": [7.25, 14.25, 8, 14.75], "texture": "#0"}, + "west": {"uv": [4.5, 13.25, 6, 13.75], "texture": "#0"}, + "up": {"uv": [3.75, 14, 3, 12.5], "texture": "#0"}, + "down": {"uv": [4.5, 12.5, 3.75, 14], "texture": "#0"} + } + }, + { + "from": [-2.5, 8.15, 10.85], + "to": [-0.5, 9.65, 15.85], + "rotation": {"angle": -45, "axis": "x", "origin": [-1.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [14.5, 11.5, 15, 11.875], "texture": "#0"}, + "east": {"uv": [14, 10.5, 15.25, 10.875], "texture": "#0"}, + "south": {"uv": [11.75, 14.5, 12.25, 14.875], "texture": "#0"}, + "west": {"uv": [14, 11, 15.25, 11.375], "texture": "#0"}, + "up": {"uv": [12.75, 14.5, 12.25, 13.25], "texture": "#0"}, + "down": {"uv": [14, 2.25, 13.5, 3.5], "texture": "#0"} + } + }, + { + "from": [-2, 8.15, 15.85], + "to": [-1, 11.65, 16.85], + "rotation": {"angle": -45, "axis": "x", "origin": [-1.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [14.5, 2, 14.75, 2.875], "texture": "#0"}, + "east": {"uv": [3.5, 14.5, 3.75, 15.375], "texture": "#0"}, + "south": {"uv": [3.75, 14.5, 4, 15.375], "texture": "#0"}, + "west": {"uv": [4, 14.5, 4.25, 15.375], "texture": "#0"}, + "up": {"uv": [10.75, 6.5, 10.5, 6.25], "texture": "#0"}, + "down": {"uv": [7.5, 10.5, 7.25, 10.75], "texture": "#0"} + } + }, + { + "from": [-2, 11.15, 14.85], + "to": [-1, 11.65, 15.85], + "rotation": {"angle": -45, "axis": "x", "origin": [-1.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [12.25, 6.25, 12.5, 6.375], "texture": "#0"}, + "east": {"uv": [9.5, 12.25, 9.75, 12.375], "texture": "#0"}, + "south": {"uv": [12.5, 6.25, 12.75, 6.375], "texture": "#0"}, + "west": {"uv": [12.75, 4, 13, 4.125], "texture": "#0"}, + "up": {"uv": [7.75, 10.75, 7.5, 10.5], "texture": "#0"}, + "down": {"uv": [8, 10.5, 7.75, 10.75], "texture": "#0"} + } + }, + { + "from": [-2.5, 2.5, 5.6], + "to": [-0.5, 5, 9.6], + "rotation": {"angle": -45, "axis": "x", "origin": [-1.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [4.5, 12.5, 5, 13.125], "texture": "#0"}, + "east": {"uv": [6.5, 13.5, 7.5, 14.125], "texture": "#0"}, + "south": {"uv": [11, 12.5, 11.5, 13.125], "texture": "#0"}, + "west": {"uv": [7.5, 13.5, 8.5, 14.125], "texture": "#0"}, + "up": {"uv": [14.5, 3, 14, 2], "texture": "#0"}, + "down": {"uv": [3.5, 14, 3, 15], "texture": "#0"} + } + }, + { + "from": [-2.5, 3, 9.6], + "to": [-0.5, 4.5, 11.6], + "rotation": {"angle": -45, "axis": "x", "origin": [-1.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [14.5, 12, 15, 12.375], "texture": "#0"}, + "east": {"uv": [12.25, 14.5, 12.75, 14.875], "texture": "#0"}, + "south": {"uv": [14.5, 12.5, 15, 12.875], "texture": "#0"}, + "west": {"uv": [14.5, 13.75, 15, 14.125], "texture": "#0"}, + "up": {"uv": [14.75, 13.75, 14.25, 13.25], "texture": "#0"}, + "down": {"uv": [14.25, 14.25, 13.75, 14.75], "texture": "#0"} + } + }, + { + "from": [-2, 3, 11.6], + "to": [-1, 6.5, 12.6], + "rotation": {"angle": -45, "axis": "x", "origin": [-1.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [14.5, 5.25, 14.75, 6.125], "texture": "#0"}, + "east": {"uv": [6, 14.5, 6.25, 15.375], "texture": "#0"}, + "south": {"uv": [6.25, 14.5, 6.5, 15.375], "texture": "#0"}, + "west": {"uv": [14.5, 6.75, 14.75, 7.625], "texture": "#0"}, + "up": {"uv": [11.5, 6.5, 11.25, 6.25], "texture": "#0"}, + "down": {"uv": [6.75, 11.25, 6.5, 11.5], "texture": "#0"} + } + }, + { + "from": [-2, 6, 10.6], + "to": [-1, 6.5, 11.6], + "rotation": {"angle": -45, "axis": "x", "origin": [-1.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [12.75, 6.25, 13, 6.375], "texture": "#0"}, + "east": {"uv": [13, 4, 13.25, 4.125], "texture": "#0"}, + "south": {"uv": [13, 10, 13.25, 10.125], "texture": "#0"}, + "west": {"uv": [13.25, 4, 13.5, 4.125], "texture": "#0"}, + "up": {"uv": [11, 6.5, 10.75, 6.25], "texture": "#0"}, + "down": {"uv": [11.25, 6.25, 11, 6.5], "texture": "#0"} + } + }, + { + "from": [-2.8, 8.91547, 7.20856], + "to": [0, 10.91547, 11.20856], + "rotation": {"angle": 0, "axis": "y", "origin": [-1.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [8, 14.25, 8.75, 14.75], "texture": "#0"}, + "east": {"uv": [14, 1, 15, 1.5], "texture": "#0"}, + "south": {"uv": [10.75, 14.25, 11.5, 14.75], "texture": "#0"}, + "west": {"uv": [14, 1.5, 15, 2], "texture": "#0"}, + "up": {"uv": [14, 11.75, 13.25, 10.75], "texture": "#0"}, + "down": {"uv": [11.75, 13.25, 11, 14.25], "texture": "#0"} + } + }, + { + "from": [11.1, 16.6, -0.5], + "to": [13.9, 21.6, 2.5], + "rotation": {"angle": 22.5, "axis": "x", "origin": [12.5, 16.6, -0.5]}, + "faces": { + "north": {"uv": [10.25, 12.5, 9.5, 13.75], "texture": "#0"}, + "east": {"uv": [0.75, 13, 0, 14.25], "texture": "#0"}, + "south": {"uv": [13.5, 2.25, 12.75, 3.5], "texture": "#0"}, + "west": {"uv": [11, 12.5, 10.25, 13.75], "texture": "#0"}, + "up": {"uv": [8.5, 14.25, 9.25, 13.5], "texture": "#0"}, + "down": {"uv": [13.75, 6.75, 14.5, 7.5], "texture": "#0"} + } + }, + { + "from": [0, 15, 8.5], + "to": [16, 31, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 23, 8.5]}, + "faces": { + "north": {"uv": [0, 0, 16, 16], "texture": "#1"}, + "south": {"uv": [16, 0, 0, 16], "texture": "#1"} + } + }, + { + "from": [0, 15, 8.5], + "to": [16, 31, 8.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 23, 8.5]}, + "faces": { + "north": {"uv": [16, 0, 0, 16], "texture": "#1"}, + "south": {"uv": [0, 0, 16, 16], "texture": "#1"} + } + }, + { + "from": [12, 13, 9.5], + "to": [22, 23, 9.5], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 23, 8.5]}, + "faces": { + "north": {"uv": [16, 0, 0, 16], "texture": "#2"}, + "south": {"uv": [0, 0, 16, 16], "texture": "#2"} + } + }, + { + "from": [-1, 4, 16.5], + "to": [9, 14, 16.5], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 23, 8.5]}, + "faces": { + "north": {"uv": [16, 0, 0, 16], "texture": "#2"}, + "south": {"uv": [0, 0, 16, 16], "texture": "#2"} + } + }, + { + "from": [-6, 0, 3.5], + "to": [-6, 10, 13.5], + "rotation": {"angle": -45, "axis": "y", "origin": [-6, 5, 10.5]}, + "faces": { + "east": {"uv": [16, 0, 0, 16], "texture": "#2"}, + "west": {"uv": [0, 0, 16, 16], "texture": "#2"} + } + }, + { + "from": [18, 0, 5.5], + "to": [28, 10, 5.5], + "rotation": {"angle": -45, "axis": "y", "origin": [23, 5, 3.5]}, + "faces": { + "north": {"uv": [0, 0, 16, 16], "texture": "#2"}, + "south": {"uv": [16, 0, 0, 16], "texture": "#2"} + } + }, + { + "from": [11, 12, 3], + "to": [14, 18, 6], + "rotation": {"angle": -45, "axis": "x", "origin": [12.5, 13, 3]}, + "faces": { + "north": {"uv": [12.25, 11.75, 11.5, 13.25], "texture": "#0"}, + "east": {"uv": [8.75, 12, 8, 13.5], "texture": "#0"}, + "south": {"uv": [8, 12, 7.25, 13.5], "texture": "#0"}, + "west": {"uv": [7.25, 12, 6.5, 13.5], "texture": "#0"}, + "up": {"uv": [13.75, 8.25, 14.5, 7.5], "texture": "#0"}, + "down": {"uv": [13.75, 8.25, 14.5, 9], "texture": "#0"} + } + }, + { + "from": [11.2, 19.25, 1.4], + "to": [13.8, 21.25, 7.4], + "rotation": {"angle": 0, "axis": "y", "origin": [12.5, 16.6, -0.5]}, + "faces": { + "north": {"uv": [4.25, 14, 3.5, 14.5], "texture": "#0"}, + "east": {"uv": [14.25, 3.5, 12.75, 4], "texture": "#0"}, + "south": {"uv": [15, 3.5, 14.25, 4], "texture": "#0"}, + "west": {"uv": [14, 10.25, 12.5, 10.75], "texture": "#0"}, + "up": {"uv": [5, 13.25, 5.75, 11.75], "texture": "#0"}, + "down": {"uv": [5.75, 11.75, 6.5, 13.25], "texture": "#0"} + } + }, + { + "from": [11.5, 17, 8.85], + "to": [13.5, 18.5, 13.85], + "rotation": {"angle": -22.5, "axis": "x", "origin": [12.5, 17, 8.85]}, + "faces": { + "north": {"uv": [15, 9.5, 14.5, 9.875], "texture": "#0"}, + "east": {"uv": [15.25, 10, 14, 10.375], "texture": "#0"}, + "south": {"uv": [10.5, 14.5, 10, 14.875], "texture": "#0"}, + "west": {"uv": [15.25, 3, 14, 3.375], "texture": "#0"}, + "up": {"uv": [6, 14.5, 6.5, 13.25], "texture": "#0"}, + "down": {"uv": [11.75, 13.25, 12.25, 14.5], "texture": "#0"} + } + }, + { + "from": [12, 17, 13.85], + "to": [13, 20.5, 14.85], + "rotation": {"angle": -22.5, "axis": "x", "origin": [12.5, 17, 8.85]}, + "faces": { + "north": {"uv": [6, 13.75, 5.75, 14.625], "texture": "#0"}, + "east": {"uv": [14.75, 0, 14.5, 0.875], "texture": "#0"}, + "south": {"uv": [14.5, 13.75, 14.25, 14.625], "texture": "#0"}, + "west": {"uv": [11.75, 14.25, 11.5, 15.125], "texture": "#0"}, + "up": {"uv": [10, 6.5, 10.25, 6.25], "texture": "#0"}, + "down": {"uv": [10.25, 6.25, 10.5, 6.5], "texture": "#0"} + } + }, + { + "from": [12, 20, 12.85], + "to": [13, 20.5, 13.85], + "rotation": {"angle": -22.5, "axis": "x", "origin": [12.5, 17, 8.85]}, + "faces": { + "north": {"uv": [12, 6.25, 11.75, 6.375], "texture": "#0"}, + "east": {"uv": [3.25, 12.25, 3, 12.375], "texture": "#0"}, + "south": {"uv": [9.75, 12, 9.5, 12.125], "texture": "#0"}, + "west": {"uv": [12.25, 6.25, 12, 6.375], "texture": "#0"}, + "up": {"uv": [4, 10.75, 4.25, 10.5], "texture": "#0"}, + "down": {"uv": [4.25, 10.5, 4.5, 10.75], "texture": "#0"} + } + }, + { + "from": [11.3, 19.25, 7.4], + "to": [13.7, 21.25, 11.4], + "rotation": {"angle": 45, "axis": "x", "origin": [12.5, 21.25, 7.4]}, + "faces": { + "north": {"uv": [5, 14.25, 4.25, 14.75], "texture": "#0"}, + "east": {"uv": [14.75, 9, 13.75, 9.5], "texture": "#0"}, + "south": {"uv": [5.75, 14.25, 5, 14.75], "texture": "#0"}, + "west": {"uv": [9, 9.75, 8, 10.25], "texture": "#0"}, + "up": {"uv": [13, 12.75, 13.75, 11.75], "texture": "#0"}, + "down": {"uv": [13, 12.75, 13.75, 13.75], "texture": "#0"} + } + }, + { + "from": [16, 4.55645, 2.63747], + "to": [19, 9.55645, 5.63747], + "rotation": {"angle": -22.5, "axis": "x", "origin": [17.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [1.5, 13, 0.75, 14.25], "texture": "#0"}, + "east": {"uv": [13.75, 6.25, 13, 7.5], "texture": "#0"}, + "south": {"uv": [3, 13, 2.25, 14.25], "texture": "#0"}, + "west": {"uv": [2.25, 13, 1.5, 14.25], "texture": "#0"}, + "up": {"uv": [9.25, 14.5, 10, 13.75], "texture": "#0"}, + "down": {"uv": [10, 13.75, 10.75, 14.5], "texture": "#0"} + } + }, + { + "from": [16, 1.97057, 4.93092], + "to": [18.9, 4.97057, 10.93092], + "rotation": {"angle": 0, "axis": "y", "origin": [17.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [14.5, 11.75, 13.75, 12.5], "texture": "#0"}, + "east": {"uv": [3, 12.25, 1.5, 13], "texture": "#0"}, + "south": {"uv": [14.5, 12.5, 13.75, 13.25], "texture": "#0"}, + "west": {"uv": [1.5, 12.25, 0, 13], "texture": "#0"}, + "up": {"uv": [8.75, 13.5, 9.5, 12], "texture": "#0"}, + "down": {"uv": [12.25, 11.75, 13, 13.25], "texture": "#0"} + } + }, + { + "from": [16, 10.4, 3.4], + "to": [18.9, 12.4, 9.4], + "rotation": {"angle": -45, "axis": "x", "origin": [17.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [7.25, 14.25, 6.5, 14.75], "texture": "#0"}, + "east": {"uv": [6, 13.25, 4.5, 13.75], "texture": "#0"}, + "south": {"uv": [8, 14.25, 7.25, 14.75], "texture": "#0"}, + "west": {"uv": [14.5, 9.5, 13, 10], "texture": "#0"}, + "up": {"uv": [3, 14, 3.75, 12.5], "texture": "#0"}, + "down": {"uv": [3.75, 12.5, 4.5, 14], "texture": "#0"} + } + }, + { + "from": [16.5, 8.15, 10.85], + "to": [18.5, 9.65, 15.85], + "rotation": {"angle": -45, "axis": "x", "origin": [17.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [15, 11.5, 14.5, 11.875], "texture": "#0"}, + "east": {"uv": [15.25, 11, 14, 11.375], "texture": "#0"}, + "south": {"uv": [12.25, 14.5, 11.75, 14.875], "texture": "#0"}, + "west": {"uv": [15.25, 10.5, 14, 10.875], "texture": "#0"}, + "up": {"uv": [12.25, 14.5, 12.75, 13.25], "texture": "#0"}, + "down": {"uv": [13.5, 2.25, 14, 3.5], "texture": "#0"} + } + }, + { + "from": [17, 8.15, 15.85], + "to": [18, 11.65, 16.85], + "rotation": {"angle": -45, "axis": "x", "origin": [17.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [14.75, 2, 14.5, 2.875], "texture": "#0"}, + "east": {"uv": [4.25, 14.5, 4, 15.375], "texture": "#0"}, + "south": {"uv": [4, 14.5, 3.75, 15.375], "texture": "#0"}, + "west": {"uv": [3.75, 14.5, 3.5, 15.375], "texture": "#0"}, + "up": {"uv": [10.5, 6.5, 10.75, 6.25], "texture": "#0"}, + "down": {"uv": [7.25, 10.5, 7.5, 10.75], "texture": "#0"} + } + }, + { + "from": [17, 11.15, 14.85], + "to": [18, 11.65, 15.85], + "rotation": {"angle": -45, "axis": "x", "origin": [17.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [12.5, 6.25, 12.25, 6.375], "texture": "#0"}, + "east": {"uv": [13, 4, 12.75, 4.125], "texture": "#0"}, + "south": {"uv": [12.75, 6.25, 12.5, 6.375], "texture": "#0"}, + "west": {"uv": [9.75, 12.25, 9.5, 12.375], "texture": "#0"}, + "up": {"uv": [7.5, 10.75, 7.75, 10.5], "texture": "#0"}, + "down": {"uv": [7.75, 10.5, 8, 10.75], "texture": "#0"} + } + }, + { + "from": [16.5, 2.5, 5.6], + "to": [18.5, 5, 9.6], + "rotation": {"angle": -45, "axis": "x", "origin": [17.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [5, 12.5, 4.5, 13.125], "texture": "#0"}, + "east": {"uv": [8.5, 13.5, 7.5, 14.125], "texture": "#0"}, + "south": {"uv": [11.5, 12.5, 11, 13.125], "texture": "#0"}, + "west": {"uv": [7.5, 13.5, 6.5, 14.125], "texture": "#0"}, + "up": {"uv": [14, 3, 14.5, 2], "texture": "#0"}, + "down": {"uv": [3, 14, 3.5, 15], "texture": "#0"} + } + }, + { + "from": [16.5, 3, 9.6], + "to": [18.5, 4.5, 11.6], + "rotation": {"angle": -45, "axis": "x", "origin": [17.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [15, 12, 14.5, 12.375], "texture": "#0"}, + "east": {"uv": [15, 13.75, 14.5, 14.125], "texture": "#0"}, + "south": {"uv": [15, 12.5, 14.5, 12.875], "texture": "#0"}, + "west": {"uv": [12.75, 14.5, 12.25, 14.875], "texture": "#0"}, + "up": {"uv": [14.25, 13.75, 14.75, 13.25], "texture": "#0"}, + "down": {"uv": [13.75, 14.25, 14.25, 14.75], "texture": "#0"} + } + }, + { + "from": [17, 3, 11.6], + "to": [18, 6.5, 12.6], + "rotation": {"angle": -45, "axis": "x", "origin": [17.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [14.75, 5.25, 14.5, 6.125], "texture": "#0"}, + "east": {"uv": [14.75, 6.75, 14.5, 7.625], "texture": "#0"}, + "south": {"uv": [6.5, 14.5, 6.25, 15.375], "texture": "#0"}, + "west": {"uv": [6.25, 14.5, 6, 15.375], "texture": "#0"}, + "up": {"uv": [11.25, 6.5, 11.5, 6.25], "texture": "#0"}, + "down": {"uv": [6.5, 11.25, 6.75, 11.5], "texture": "#0"} + } + }, + { + "from": [17, 6, 10.6], + "to": [18, 6.5, 11.6], + "rotation": {"angle": -45, "axis": "x", "origin": [17.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [13, 6.25, 12.75, 6.375], "texture": "#0"}, + "east": {"uv": [13.5, 4, 13.25, 4.125], "texture": "#0"}, + "south": {"uv": [13.25, 10, 13, 10.125], "texture": "#0"}, + "west": {"uv": [13.25, 4, 13, 4.125], "texture": "#0"}, + "up": {"uv": [10.75, 6.5, 11, 6.25], "texture": "#0"}, + "down": {"uv": [11, 6.25, 11.25, 6.5], "texture": "#0"} + } + }, + { + "from": [16, 8.91547, 7.20856], + "to": [18.8, 10.91547, 11.20856], + "rotation": {"angle": 0, "axis": "y", "origin": [17.5, 9.01244, 10.09626]}, + "faces": { + "north": {"uv": [8.75, 14.25, 8, 14.75], "texture": "#0"}, + "east": {"uv": [15, 1.5, 14, 2], "texture": "#0"}, + "south": {"uv": [11.5, 14.25, 10.75, 14.75], "texture": "#0"}, + "west": {"uv": [15, 1, 14, 1.5], "texture": "#0"}, + "up": {"uv": [13.25, 11.75, 14, 10.75], "texture": "#0"}, + "down": {"uv": [11, 13.25, 11.75, 14.25], "texture": "#0"} + } + }, + { + "from": [6.6, 12.49304, -2.92721], + "to": [9.4, 17.49304, 0.07279], + "rotation": {"angle": -45, "axis": "x", "origin": [8, 18, 4.09626]}, + "faces": { + "north": {"uv": [9.5, 12.5, 10.25, 13.75], "texture": "#0"}, + "east": {"uv": [10.25, 12.5, 11, 13.75], "texture": "#0"}, + "south": {"uv": [12.75, 2.25, 13.5, 3.5], "texture": "#0"}, + "west": {"uv": [0, 13, 0.75, 14.25], "texture": "#0"}, + "up": {"uv": [9.25, 14.25, 8.5, 13.5], "texture": "#0"}, + "down": {"uv": [14.5, 6.75, 13.75, 7.5], "texture": "#0"} + } + }, + { + "from": [6.7, 11.30374, 1.84626], + "to": [9.3, 17.30374, 3.84626], + "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 18, 4.09626]}, + "faces": { + "north": {"uv": [5.75, 13.25, 5, 11.75], "rotation": 180, "texture": "#0"}, + "east": {"uv": [12.5, 10.25, 14, 10.75], "rotation": 90, "texture": "#0"}, + "south": {"uv": [6.5, 11.75, 5.75, 13.25], "texture": "#0"}, + "west": {"uv": [12.75, 3.5, 14.25, 4], "rotation": 270, "texture": "#0"}, + "up": {"uv": [14.25, 3.5, 15, 4], "texture": "#0"}, + "down": {"uv": [3.5, 14, 4.25, 14.5], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [7, 18.75374, 4.59626], + "to": [9, 23.75374, 6.09626], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 18, 4.09626]}, + "faces": { + "north": {"uv": [6.5, 14.5, 6, 13.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [14, 3, 15.25, 3.375], "rotation": 90, "texture": "#0"}, + "south": {"uv": [12.25, 13.25, 11.75, 14.5], "texture": "#0"}, + "west": {"uv": [14, 10, 15.25, 10.375], "rotation": 270, "texture": "#0"}, + "up": {"uv": [10, 14.5, 10.5, 14.875], "texture": "#0"}, + "down": {"uv": [14.5, 9.5, 15, 9.875], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [7.5, 23.75374, 2.59626], + "to": [8.5, 24.75374, 6.09626], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 18, 4.09626]}, + "faces": { + "north": {"uv": [10.25, 6.5, 10, 6.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [11.5, 14.25, 11.75, 15.125], "rotation": 90, "texture": "#0"}, + "south": {"uv": [10.5, 6.25, 10.25, 6.5], "texture": "#0"}, + "west": {"uv": [14.5, 0, 14.75, 0.875], "rotation": 270, "texture": "#0"}, + "up": {"uv": [14.25, 13.75, 14.5, 14.625], "texture": "#0"}, + "down": {"uv": [5.75, 13.75, 6, 14.625], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [7.5, 22.75374, 2.59626], + "to": [8.5, 23.75374, 3.09626], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 18, 4.09626]}, + "faces": { + "north": {"uv": [4.25, 10.75, 4, 10.5], "rotation": 180, "texture": "#0"}, + "east": {"uv": [12, 6.25, 12.25, 6.375], "rotation": 90, "texture": "#0"}, + "south": {"uv": [4.5, 10.5, 4.25, 10.75], "texture": "#0"}, + "west": {"uv": [3, 12.25, 3.25, 12.375], "rotation": 270, "texture": "#0"}, + "up": {"uv": [9.5, 12, 9.75, 12.125], "texture": "#0"}, + "down": {"uv": [11.75, 6.25, 12, 6.375], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [6.8, 17.09866, 2.01294], + "to": [9.2, 19.09866, 6.01294], + "rotation": {"angle": -22.5, "axis": "x", "origin": [8, 18, 4.09626]}, + "faces": { + "north": {"uv": [4.25, 14.25, 5, 14.75], "texture": "#0"}, + "east": {"uv": [8, 9.75, 9, 10.25], "texture": "#0"}, + "south": {"uv": [5, 14.25, 5.75, 14.75], "texture": "#0"}, + "west": {"uv": [13.75, 9, 14.75, 9.5], "texture": "#0"}, + "up": {"uv": [13.75, 12.75, 13, 11.75], "texture": "#0"}, + "down": {"uv": [13.75, 12.75, 13, 13.75], "texture": "#0"} + } + } + ], + "gui_light": "front", + "display": { + "thirdperson_righthand": { + "rotation": [62, 0, 0], + "translation": [0, 0, 1.75], + "scale": [0.38, 0.38, 0.38] + }, + "thirdperson_lefthand": { + "rotation": [62, 0, 0], + "translation": [0, 0, 1.75], + "scale": [0.38, 0.38, 0.38] + }, + "firstperson_righthand": { + "rotation": [5, 1, 3], + "translation": [-1.5, 4, 2.25], + "scale": [0.34, 0.34, 0.34] + }, + "firstperson_lefthand": { + "rotation": [5, 1, 3], + "translation": [-1.5, 4, 2.25], + "scale": [0.34, 0.34, 0.34] + }, + "ground": { + "scale": [0.5, 0.5, 0.5] + }, + "gui": { + "rotation": [30, -135, 0], + "translation": [0.25, -0.25, 0], + "scale": [0.55164, 0.55164, 0.55164] + }, + "head": { + "translation": [0, -33, -1.5], + "scale": [1.56, 1.56, 1.56] + }, + "fixed": { + "rotation": [-90, 0, 0], + "translation": [0, -1.25, -19.75], + "scale": [2.46484, 2.46484, 2.46484] + } + }, + "groups": [ + 0, + 1, + { + "name": "group", + "origin": [8, 5, 14], + "color": 0, + "children": [2, 3, 4, 5, 6, 7, 8] + }, + { + "name": "group", + "origin": [2.5, 16.6, -0.5], + "color": 0, + "children": [9, 10, 11] + }, + { + "name": "group", + "origin": [2.5, 16.6, -0.5], + "color": 0, + "children": [12, 13, 14] + }, + { + "name": "group", + "origin": [2.5, 21.25, 7.4], + "color": 0, + "children": [ + 15, + 16, + 17, + { + "name": "group", + "origin": [2.5, 16.6, -0.5], + "color": 0, + "children": [18, 19, 20, 21] + } + ] + }, + { + "name": "group", + "origin": [2.5, 21.25, 7.4], + "color": 0, + "children": [ + 22, + 23, + 24, + 25, + 26, + 27, + { + "name": "group", + "origin": [-1.5, 9.01244, 10.09626], + "color": 0, + "children": [28, 29, 30, 31] + }, + 32 + ] + }, + { + "name": "group", + "origin": [2.5, 21.25, 7.4], + "color": 0, + "children": [ + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + { + "name": "group", + "origin": [2.5, 16.6, -0.5], + "color": 0, + "children": [42, 43, 44] + }, + 45 + ] + }, + { + "name": "group", + "origin": [2.5, 21.25, 7.4], + "color": 0, + "children": [ + 46, + 47, + 48, + 49, + 50, + 51, + { + "name": "group", + "origin": [-1.5, 9.01244, 10.09626], + "color": 0, + "children": [52, 53, 54, 55] + }, + 56 + ] + }, + { + "name": "group", + "origin": [2.5, 21.25, 7.4], + "color": 0, + "children": [ + 57, + 58, + { + "name": "group", + "origin": [2.5, 16.6, -0.5], + "color": 0, + "children": [59, 60, 61] + }, + 62 + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/lootbox/legendary_box.json b/src/main/resources/contents/omc_daily_events/models/lootbox/legendary_box.json new file mode 100644 index 000000000..69eca40f3 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/lootbox/legendary_box.json @@ -0,0 +1,1485 @@ +{ + "texture_size": [128, 128], + "textures": { + "0": "omc_daily_events:lootbox/legendary_box", + "particle": "omc_daily_events:lootbox/legendary_box" + }, + "elements": [ + { + "from": [-2, 0, 2], + "to": [18, 15, 14], + "faces": { + "north": {"uv": [3, 3.75, 5.5, 5.625], "texture": "#0"}, + "east": {"uv": [0, 5.875, 1.5, 7.75], "texture": "#0"}, + "south": {"uv": [0, 4, 2.5, 5.875], "texture": "#0"}, + "west": {"uv": [5.5, 6, 7, 7.875], "texture": "#0"}, + "up": {"uv": [8, 4.5, 5.5, 3], "texture": "#0"}, + "down": {"uv": [8, 4.5, 5.5, 6], "texture": "#0"} + } + }, + { + "from": [3, 14.4, 2], + "to": [13, 19.4, 14], + "faces": { + "north": {"uv": [0.625, 4, 1.875, 4.625], "texture": "#0"}, + "east": {"uv": [0, 5.875, 1.5, 6.5], "texture": "#0"}, + "south": {"uv": [0.625, 4, 1.875, 4.625], "texture": "#0"}, + "west": {"uv": [5.5, 6, 7, 6.625], "texture": "#0"}, + "up": {"uv": [7.375, 4.5, 6.125, 3], "texture": "#0"}, + "down": {"uv": [6.75, 4.5, 5.5, 6], "texture": "#0"} + } + }, + { + "from": [-2, 0, 13.8], + "to": [18, 2.8, 14.8], + "faces": { + "north": {"uv": [3, 3.75, 5.5, 4], "texture": "#0"}, + "east": {"uv": [0, 5.875, 0.125, 6.125], "texture": "#0"}, + "south": {"uv": [0, 5.5, 2.5, 5.875], "texture": "#0"}, + "west": {"uv": [5.5, 6, 5.625, 6.25], "texture": "#0"}, + "up": {"uv": [5.5, 3.5, 3, 3.375], "texture": "#0"}, + "down": {"uv": [8, 4.5, 5.5, 4.625], "texture": "#0"} + } + }, + { + "from": [-2, 0, 1.2], + "to": [18, 2.8, 2.2], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 16]}, + "faces": { + "north": {"uv": [2.5, 5.5, 0, 5.875], "texture": "#0"}, + "east": {"uv": [0.125, 5.875, 0, 6.125], "texture": "#0"}, + "south": {"uv": [5.5, 3.75, 3, 4], "texture": "#0"}, + "west": {"uv": [5.625, 6, 5.5, 6.25], "texture": "#0"}, + "up": {"uv": [5.5, 3.375, 3, 3.5], "texture": "#0"}, + "down": {"uv": [8, 4.625, 5.5, 4.5], "texture": "#0"} + } + }, + { + "from": [17.5, 0, 2.7], + "to": [18.5, 2.8, 13.7], + "rotation": {"angle": 0, "axis": "y", "origin": [22, 1.4, 1.7]}, + "faces": { + "north": {"uv": [5.625, 6, 5.5, 6.35], "texture": "#0"}, + "east": {"uv": [1.875, 5.5, 0.5, 5.85], "texture": "#0"}, + "south": {"uv": [0.125, 5.875, 0, 6.125], "texture": "#0"}, + "west": {"uv": [5.5, 3.75, 3, 4], "texture": "#0"}, + "up": {"uv": [5.5, 3.375, 3, 3.5], "rotation": 90, "texture": "#0"}, + "down": {"uv": [8, 4.625, 5.5, 4.5], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [-2.5, 0, 2.7], + "to": [-1.5, 2.8, 13.7], + "rotation": {"angle": 0, "axis": "y", "origin": [-6, 1.4, 1.7]}, + "faces": { + "north": {"uv": [5.5, 6, 5.625, 6.35], "texture": "#0"}, + "east": {"uv": [3, 3.75, 5.5, 4], "texture": "#0"}, + "south": {"uv": [0, 5.875, 0.125, 6.125], "texture": "#0"}, + "west": {"uv": [0.5, 5.5, 1.875, 5.85], "texture": "#0"}, + "up": {"uv": [5.5, 3.5, 3, 3.375], "rotation": 90, "texture": "#0"}, + "down": {"uv": [8, 4.5, 5.5, 4.625], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [17.2, 10.3, 2], + "to": [19.2, 15.3, 14], + "rotation": {"angle": 22.5, "axis": "z", "origin": [18.5, 12.5, 8]}, + "faces": { + "north": {"uv": [3, 3.75, 3.25, 4.375], "texture": "#0"}, + "east": {"uv": [0, 5.875, 1.5, 6.5], "texture": "#0"}, + "south": {"uv": [0, 4, 0.25, 4.625], "texture": "#0"}, + "west": {"uv": [5.5, 6, 7, 6.625], "texture": "#0"}, + "up": {"uv": [5.75, 4.5, 5.5, 3], "texture": "#0"}, + "down": {"uv": [5.75, 4.5, 5.5, 6], "texture": "#0"} + } + }, + { + "from": [14.2, 16, 2.1], + "to": [16.2, 21, 13.9], + "rotation": {"angle": 22.5, "axis": "z", "origin": [18.5, 12.5, 8]}, + "faces": { + "north": {"uv": [3, 3.75, 3.25, 4.375], "texture": "#0"}, + "east": {"uv": [0, 5.875, 1.5, 6.5], "texture": "#0"}, + "south": {"uv": [0, 4, 0.25, 4.625], "texture": "#0"}, + "west": {"uv": [5.5, 6, 7, 6.625], "texture": "#0"}, + "up": {"uv": [5.75, 4.5, 5.5, 3], "texture": "#0"}, + "down": {"uv": [5.75, 4.5, 5.5, 6], "texture": "#0"} + } + }, + { + "from": [-0.2, 16, 2.1], + "to": [1.8, 21, 13.9], + "rotation": {"angle": -22.5, "axis": "z", "origin": [-2.5, 12.5, 8]}, + "faces": { + "north": {"uv": [3.25, 3.75, 3, 4.375], "texture": "#0"}, + "east": {"uv": [7, 6, 5.5, 6.625], "texture": "#0"}, + "south": {"uv": [0.25, 4, 0, 4.625], "texture": "#0"}, + "west": {"uv": [1.5, 5.875, 0, 6.5], "texture": "#0"}, + "up": {"uv": [5.5, 4.5, 5.75, 3], "texture": "#0"}, + "down": {"uv": [5.5, 4.5, 5.75, 6], "texture": "#0"} + } + }, + { + "from": [-3.2, 10.3, 2], + "to": [-1.2, 15.3, 14], + "rotation": {"angle": -22.5, "axis": "z", "origin": [-2.5, 12.5, 8]}, + "faces": { + "north": {"uv": [3.25, 3.75, 3, 4.375], "texture": "#0"}, + "east": {"uv": [7, 6, 5.5, 6.625], "texture": "#0"}, + "south": {"uv": [0.25, 4, 0, 4.625], "texture": "#0"}, + "west": {"uv": [1.5, 5.875, 0, 6.5], "texture": "#0"}, + "up": {"uv": [5.5, 4.5, 5.75, 3], "texture": "#0"}, + "down": {"uv": [5.5, 4.5, 5.75, 6], "texture": "#0"} + } + }, + { + "from": [17.30803, 10.86236, 13.3], + "to": [19.30803, 15.26236, 15.3], + "rotation": {"angle": 0, "axis": "z", "origin": [18.10803, 13.36236, 14.5]}, + "faces": { + "north": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "east": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "south": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "west": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "up": {"uv": [5.75, 4.5, 5.5, 3], "texture": "#0"}, + "down": {"uv": [5.75, 4.5, 5.5, 6], "texture": "#0"} + } + }, + { + "from": [17.80803, 12.86236, 13.8], + "to": [18.80803, 17.26236, 14.8], + "rotation": {"angle": 0, "axis": "z", "origin": [18.10803, 13.36236, 14.5]}, + "faces": { + "north": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "east": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "south": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "west": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "up": {"uv": [5.625, 3.125, 5.5, 3], "texture": "#0"}, + "down": {"uv": [5.625, 4.5, 5.5, 4.625], "texture": "#0"} + } + }, + { + "from": [17.80803, 12.86236, 1.8], + "to": [18.80803, 17.26236, 2.8], + "rotation": {"angle": 0, "axis": "z", "origin": [18.10803, 13.36236, 14.5]}, + "faces": { + "north": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "east": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "south": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "west": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "up": {"uv": [5.625, 3.125, 5.5, 3], "texture": "#0"}, + "down": {"uv": [5.625, 4.5, 5.5, 4.625], "texture": "#0"} + } + }, + { + "from": [-2.89197, 12.86236, 1.8], + "to": [-1.89197, 17.26236, 2.8], + "rotation": {"angle": 0, "axis": "z", "origin": [18.10803, 13.36236, 14.5]}, + "faces": { + "north": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "east": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "south": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "west": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "up": {"uv": [5.625, 3.125, 5.5, 3], "texture": "#0"}, + "down": {"uv": [5.625, 4.5, 5.5, 4.625], "texture": "#0"} + } + }, + { + "from": [-2.89197, 12.86236, 13.9], + "to": [-1.89197, 17.26236, 14.9], + "rotation": {"angle": 0, "axis": "z", "origin": [18.10803, 13.36236, 14.5]}, + "faces": { + "north": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "east": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "south": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "west": {"uv": [0, 5.875, 0.125, 6.425], "texture": "#0"}, + "up": {"uv": [5.625, 3.125, 5.5, 3], "texture": "#0"}, + "down": {"uv": [5.625, 4.5, 5.5, 4.625], "texture": "#0"} + } + }, + { + "from": [17.40803, 16.36236, 13.2], + "to": [19.40803, 18.36236, 15.4], + "shade": false, + "rotation": {"angle": -45, "axis": "z", "origin": [18.40803, 17.56236, 14.3]}, + "faces": { + "north": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "east": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "up": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"} + } + }, + { + "from": [-3.30803, 10.86236, 13.3], + "to": [-1.30803, 15.26236, 15.3], + "rotation": {"angle": 0, "axis": "z", "origin": [-2.10803, 13.36236, 14.5]}, + "faces": { + "north": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "east": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "south": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "west": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "up": {"uv": [5.5, 4.5, 5.75, 3], "texture": "#0"}, + "down": {"uv": [5.5, 4.5, 5.75, 6], "texture": "#0"} + } + }, + { + "from": [-3.40803, 16.36236, 13.2], + "to": [-1.40803, 18.36236, 15.4], + "rotation": {"angle": 45, "axis": "z", "origin": [-2.40803, 17.56236, 14.3]}, + "faces": { + "north": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "east": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "up": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"} + } + }, + { + "from": [17.30803, 10.86236, 1.3], + "to": [19.30803, 15.26236, 3.3], + "rotation": {"angle": 0, "axis": "z", "origin": [18.10803, 13.36236, 2.5]}, + "faces": { + "north": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "east": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "south": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "west": {"uv": [0, 5.875, 0.25, 6.425], "texture": "#0"}, + "up": {"uv": [5.75, 4.5, 5.5, 3], "texture": "#0"}, + "down": {"uv": [5.75, 4.5, 5.5, 6], "texture": "#0"} + } + }, + { + "from": [17.40803, 16.36236, 1.2], + "to": [19.40803, 18.36236, 3.4], + "rotation": {"angle": -45, "axis": "z", "origin": [18.40803, 17.56236, 2.3]}, + "faces": { + "north": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "east": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "up": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"} + } + }, + { + "from": [-3.30803, 10.86236, 1.3], + "to": [-1.30803, 15.26236, 3.3], + "rotation": {"angle": 0, "axis": "z", "origin": [-2.10803, 13.36236, 2.5]}, + "faces": { + "north": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "east": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "south": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "west": {"uv": [0.25, 5.875, 0, 6.425], "texture": "#0"}, + "up": {"uv": [5.5, 4.5, 5.75, 3], "texture": "#0"}, + "down": {"uv": [5.5, 4.5, 5.75, 6], "texture": "#0"} + } + }, + { + "from": [-3.40803, 16.36236, 1.2], + "to": [-1.40803, 18.36236, 3.4], + "rotation": {"angle": 45, "axis": "z", "origin": [-2.40803, 17.56236, 2.3]}, + "faces": { + "north": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "east": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "up": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"} + } + }, + { + "from": [-2.1, 10, 15], + "to": [18.1, 15, 17], + "rotation": {"angle": -22.5, "axis": "x", "origin": [8, 7.5, 14.5]}, + "faces": { + "north": {"uv": [3, 3.75, 5.5, 4.375], "texture": "#0"}, + "east": {"uv": [0, 5.875, 0.25, 6.5], "texture": "#0"}, + "south": {"uv": [0, 4, 2.5, 4.625], "texture": "#0"}, + "west": {"uv": [5.5, 6, 5.75, 6.625], "texture": "#0"}, + "up": {"uv": [8, 3.25, 5.5, 3], "texture": "#0"}, + "down": {"uv": [8, 4.5, 5.5, 4.75], "texture": "#0"} + } + }, + { + "from": [-2.1, 10, -1], + "to": [18.1, 15, 1], + "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 7.5, 1.5]}, + "faces": { + "north": {"uv": [2.5, 4, 0, 4.625], "texture": "#0"}, + "east": {"uv": [0.25, 5.875, 0, 6.5], "texture": "#0"}, + "south": {"uv": [5.5, 3.75, 3, 4.375], "texture": "#0"}, + "west": {"uv": [5.75, 6, 5.5, 6.625], "texture": "#0"}, + "up": {"uv": [8, 3, 5.5, 3.25], "texture": "#0"}, + "down": {"uv": [8, 4.75, 5.5, 4.5], "texture": "#0"} + } + }, + { + "from": [-4, 0, 0], + "to": [1, 1, 5], + "faces": { + "north": {"uv": [1.5, 7.375, 2.125, 7.5], "texture": "#0"}, + "east": {"uv": [4.75, 7.75, 5.375, 7.875], "texture": "#0"}, + "south": {"uv": [8, 5.875, 8.625, 6], "texture": "#0"}, + "west": {"uv": [8.375, 3.875, 9, 4], "texture": "#0"}, + "up": {"uv": [0.625, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [2.125, 6.5, 1.5, 7.125], "texture": "#0"} + } + }, + { + "from": [-3, 1, 1], + "to": [0, 8, 4], + "faces": { + "north": {"uv": [2.5, 4, 2.875, 4.875], "texture": "#0"}, + "east": {"uv": [2.125, 5.875, 2.5, 6.75], "texture": "#0"}, + "south": {"uv": [1.875, 8, 2.25, 8.875], "texture": "#0"}, + "west": {"uv": [8, 1.875, 8.375, 2.75], "texture": "#0"}, + "up": {"uv": [5.25, 8.625, 4.875, 8.25], "texture": "#0"}, + "down": {"uv": [5.625, 8.25, 5.25, 8.625], "texture": "#0"} + } + }, + { + "from": [-3, 1, 12], + "to": [0, 8, 15], + "faces": { + "north": {"uv": [2.25, 8, 2.625, 8.875], "texture": "#0"}, + "east": {"uv": [2.625, 8, 3, 8.875], "texture": "#0"}, + "south": {"uv": [8, 2.75, 8.375, 3.625], "texture": "#0"}, + "west": {"uv": [3, 8, 3.375, 8.875], "texture": "#0"}, + "up": {"uv": [6, 8.625, 5.625, 8.25], "texture": "#0"}, + "down": {"uv": [6.375, 8.25, 6, 8.625], "texture": "#0"} + } + }, + { + "from": [-4, 0, 11], + "to": [1, 1, 16], + "faces": { + "north": {"uv": [8.375, 4, 9, 4.125], "texture": "#0"}, + "east": {"uv": [8.375, 4.125, 9, 4.25], "texture": "#0"}, + "south": {"uv": [8.375, 4.25, 9, 4.375], "texture": "#0"}, + "west": {"uv": [8.375, 4.375, 9, 4.5], "texture": "#0"}, + "up": {"uv": [0.625, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 0.625, 8.375], "texture": "#0"} + } + }, + { + "from": [16, 1, 12], + "to": [19, 8, 15], + "faces": { + "north": {"uv": [3.375, 8, 3.75, 8.875], "texture": "#0"}, + "east": {"uv": [8, 3.625, 8.375, 4.5], "texture": "#0"}, + "south": {"uv": [3.75, 8, 4.125, 8.875], "texture": "#0"}, + "west": {"uv": [4.125, 8, 4.5, 8.875], "texture": "#0"}, + "up": {"uv": [6.75, 8.625, 6.375, 8.25], "texture": "#0"}, + "down": {"uv": [0.375, 8.375, 0, 8.75], "texture": "#0"} + } + }, + { + "from": [15, 0, 11], + "to": [20, 1, 16], + "faces": { + "north": {"uv": [8.375, 4.5, 9, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 9, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [0.625, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [8.625, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [20, 0, 11], + "to": [21, 1, 16], + "faces": { + "north": {"uv": [8.375, 4.5, 8.5, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 8.5, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [0.125, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [8.125, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [20, 0, 0], + "to": [21, 1, 5], + "faces": { + "north": {"uv": [8.375, 4.5, 8.5, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 8.5, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [0.125, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [8.125, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [-5, 0, 0], + "to": [-4, 1, 5], + "faces": { + "north": {"uv": [8.375, 4.5, 8.5, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 8.5, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [0.125, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [8.125, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [-5, 0, 11], + "to": [-4, 1, 16], + "faces": { + "north": {"uv": [8.375, 4.5, 8.5, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 8.5, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [0.125, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [8.125, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [16, 1, 1], + "to": [19, 8, 4], + "faces": { + "north": {"uv": [8, 4.5, 8.375, 5.375], "texture": "#0"}, + "east": {"uv": [6.75, 8.125, 7.125, 9], "texture": "#0"}, + "south": {"uv": [7.125, 8.125, 7.5, 9], "texture": "#0"}, + "west": {"uv": [7.5, 8.125, 7.875, 9], "texture": "#0"}, + "up": {"uv": [0.75, 8.75, 0.375, 8.375], "texture": "#0"}, + "down": {"uv": [1.125, 8.375, 0.75, 8.75], "texture": "#0"} + } + }, + { + "from": [15, 0, 0], + "to": [20, 1, 5], + "faces": { + "north": {"uv": [8.375, 5, 9, 5.125], "texture": "#0"}, + "east": {"uv": [8.375, 5.125, 9, 5.25], "texture": "#0"}, + "south": {"uv": [8.375, 5.25, 9, 5.375], "texture": "#0"}, + "west": {"uv": [8.5, 8.125, 9.125, 8.25], "texture": "#0"}, + "up": {"uv": [0.625, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [8.625, 1.25, 8, 1.875], "texture": "#0"} + } + }, + { + "from": [15, 2, 11], + "to": [20, 3, 16], + "faces": { + "north": {"uv": [8.375, 4.5, 9, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 9, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [8.625, 0.625, 8, 0], "texture": "#0"}, + "down": {"uv": [8.625, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [-4, 2, 11], + "to": [1, 3, 16], + "faces": { + "north": {"uv": [8.375, 4, 9, 4.125], "texture": "#0"}, + "east": {"uv": [8.375, 4.125, 9, 4.25], "texture": "#0"}, + "south": {"uv": [8.375, 4.25, 9, 4.375], "texture": "#0"}, + "west": {"uv": [8.375, 4.375, 9, 4.5], "texture": "#0"}, + "up": {"uv": [0.625, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 0.625, 8.375], "texture": "#0"} + } + }, + { + "from": [-4, 2, 0], + "to": [1, 3, 5], + "faces": { + "north": {"uv": [1.5, 7.375, 2.125, 7.5], "texture": "#0"}, + "east": {"uv": [4.75, 7.75, 5.375, 7.875], "texture": "#0"}, + "south": {"uv": [8, 5.875, 8.625, 6], "texture": "#0"}, + "west": {"uv": [8.375, 3.875, 9, 4], "texture": "#0"}, + "up": {"uv": [2.125, 6.5, 1.5, 5.875], "texture": "#0"}, + "down": {"uv": [2.125, 6.5, 1.5, 7.125], "texture": "#0"} + } + }, + { + "from": [15, 2, 0], + "to": [20, 3, 5], + "faces": { + "north": {"uv": [8.375, 5, 9, 5.125], "texture": "#0"}, + "east": {"uv": [8.375, 5.125, 9, 5.25], "texture": "#0"}, + "south": {"uv": [8.375, 5.25, 9, 5.375], "texture": "#0"}, + "west": {"uv": [8.5, 8.125, 9.125, 8.25], "texture": "#0"}, + "up": {"uv": [1.875, 8.625, 1.25, 8], "texture": "#0"}, + "down": {"uv": [8.625, 1.25, 8, 1.875], "texture": "#0"} + } + }, + { + "from": [15, 6, 11], + "to": [20, 7, 16], + "faces": { + "north": {"uv": [8.375, 4.5, 9, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 9, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [8.625, 0.625, 8, 0], "texture": "#0"}, + "down": {"uv": [8.625, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [-4, 6, 11], + "to": [1, 7, 16], + "faces": { + "north": {"uv": [8.375, 4, 9, 4.125], "texture": "#0"}, + "east": {"uv": [8.375, 4.125, 9, 4.25], "texture": "#0"}, + "south": {"uv": [8.375, 4.25, 9, 4.375], "texture": "#0"}, + "west": {"uv": [8.375, 4.375, 9, 4.5], "texture": "#0"}, + "up": {"uv": [0.625, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 0.625, 8.375], "texture": "#0"} + } + }, + { + "from": [-4, 6, 0], + "to": [1, 7, 5], + "faces": { + "north": {"uv": [1.5, 7.375, 2.125, 7.5], "texture": "#0"}, + "east": {"uv": [4.75, 7.75, 5.375, 7.875], "texture": "#0"}, + "south": {"uv": [8, 5.875, 8.625, 6], "texture": "#0"}, + "west": {"uv": [8.375, 3.875, 9, 4], "texture": "#0"}, + "up": {"uv": [2.125, 6.5, 1.5, 5.875], "texture": "#0"}, + "down": {"uv": [2.125, 6.5, 1.5, 7.125], "texture": "#0"} + } + }, + { + "from": [15, 6, 0], + "to": [20, 7, 5], + "faces": { + "north": {"uv": [8.375, 5, 9, 5.125], "texture": "#0"}, + "east": {"uv": [8.375, 5.125, 9, 5.25], "texture": "#0"}, + "south": {"uv": [8.375, 5.25, 9, 5.375], "texture": "#0"}, + "west": {"uv": [8.5, 8.125, 9.125, 8.25], "texture": "#0"}, + "up": {"uv": [1.875, 8.625, 1.25, 8], "texture": "#0"}, + "down": {"uv": [8.625, 1.25, 8, 1.875], "texture": "#0"} + } + }, + { + "from": [5.5, 4, 14], + "to": [10.5, 8, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [4.5, 0, 0]}, + "faces": { + "north": {"uv": [8, 5.375, 8.625, 5.875], "texture": "#0"}, + "east": {"uv": [8.375, 1.875, 8.625, 2.375], "texture": "#0"}, + "south": {"uv": [7.875, 8.125, 8.5, 8.625], "texture": "#0"}, + "west": {"uv": [8.375, 2.375, 8.625, 2.875], "texture": "#0"}, + "up": {"uv": [2.125, 7.375, 1.5, 7.125], "texture": "#0"}, + "down": {"uv": [5.375, 7.5, 4.75, 7.75], "texture": "#0"} + } + }, + { + "from": [6.5, 5, 15], + "to": [9.5, 8, 17], + "shade": false, + "rotation": {"angle": 0, "axis": "y", "origin": [4.5, 0, 0]}, + "faces": { + "north": {"uv": [2.5, 4.875, 2.875, 5.375], "texture": "#0"}, + "east": {"uv": [8.375, 2.875, 8.625, 3.375], "texture": "#0"}, + "south": {"uv": [2.125, 6.875, 2.5, 7.25], "texture": "#0"}, + "west": {"uv": [8.375, 3.375, 8.625, 3.875], "texture": "#0"}, + "up": {"uv": [2.875, 5.625, 2.5, 5.375], "texture": "#0"}, + "down": {"uv": [2.5, 7.25, 2.125, 7.5], "texture": "#0"} + } + }, + { + "from": [6.5, 8, 15], + "to": [9.5, 11, 17], + "shade": false, + "rotation": {"angle": 0, "axis": "y", "origin": [4.5, 0, 0]}, + "faces": { + "north": {"uv": [2.5, 4.875, 2.875, 5.375], "texture": "#0"}, + "east": {"uv": [8.375, 2.875, 8.625, 3.375], "texture": "#0"}, + "south": {"uv": [2.125, 6.75, 2.5, 7.125], "texture": "#0"}, + "west": {"uv": [8.375, 3.375, 8.625, 3.875], "texture": "#0"}, + "up": {"uv": [2.875, 5.625, 2.5, 5.375], "texture": "#0"}, + "down": {"uv": [2.5, 7.25, 2.125, 7.5], "texture": "#0"} + } + }, + { + "from": [7, 13.85, 13.85], + "to": [9, 15.85, 14.85], + "rotation": {"angle": -22.5, "axis": "x", "origin": [7.85, 14.9, 17.55]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [7, 15.85, 13.85], + "to": [9, 17.85, 14.85], + "rotation": {"angle": -22.5, "axis": "x", "origin": [7.85, 14.9, 17.55]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [7, 11.85, 13.85], + "to": [9, 13.85, 14.85], + "rotation": {"angle": -22.5, "axis": "x", "origin": [7.85, 14.9, 17.55]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [7, 11.82922, 14.81272], + "to": [9, 13.82922, 15.81272], + "rotation": {"angle": -45, "axis": "z", "origin": [8, 12.82922, 14.61272]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [7.2, 3.12922, 15.21272], + "to": [9.2, 5.12922, 16.21272], + "rotation": {"angle": -45, "axis": "z", "origin": [8.2, 4.12922, 15.01272]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [9.7, 9.82922, 15.21272], + "to": [11.7, 11.82922, 16.21272], + "rotation": {"angle": -45, "axis": "z", "origin": [10.7, 6.82922, 15.01272]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [-1.3, 9.82922, 15.21272], + "to": [0.7, 11.82922, 16.21272], + "rotation": {"angle": -45, "axis": "z", "origin": [-0.3, 6.82922, 15.01272]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [12.6, 11.62922, 14.51272], + "to": [14.6, 13.62922, 15.51272], + "rotation": {"angle": -45, "axis": "z", "origin": [13.6, 12.62922, 14.31272]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [1.6, 11.62922, 14.51272], + "to": [3.6, 13.62922, 15.51272], + "rotation": {"angle": -45, "axis": "z", "origin": [2.6, 12.62922, 14.31272]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [13, 11, 1.3], + "to": [14, 16, 14.8], + "rotation": {"angle": 0, "axis": "y", "origin": [4.5, 0, 0]}, + "faces": { + "north": {"uv": [8.625, 0, 8.75, 0.5], "texture": "#0"}, + "east": {"uv": [1.5, 7.5, 3.125, 8], "texture": "#0"}, + "south": {"uv": [8.625, 0.5, 8.75, 1], "texture": "#0"}, + "west": {"uv": [3.125, 7.5, 4.75, 8], "texture": "#0"}, + "up": {"uv": [4.75, 9.625, 4.625, 8], "texture": "#0"}, + "down": {"uv": [4.875, 8.25, 4.75, 9.875], "texture": "#0"} + } + }, + { + "from": [13, 10, 14.8], + "to": [14, 15.5, 15.8], + "rotation": {"angle": -22.5, "axis": "x", "origin": [13.5, 13.25, 14.3]}, + "faces": { + "north": {"uv": [8.625, 0, 8.75, 0.5], "texture": "#0"}, + "east": {"uv": [1.5, 7.5, 3.125, 8], "texture": "#0"}, + "south": {"uv": [8.625, 0.5, 8.75, 1], "texture": "#0"}, + "west": {"uv": [3.125, 7.5, 4.75, 8], "texture": "#0"}, + "up": {"uv": [4.75, 9.625, 4.625, 8], "texture": "#0"}, + "down": {"uv": [4.875, 8.25, 4.75, 9.875], "texture": "#0"} + } + }, + { + "from": [2, 10, 14.8], + "to": [3, 15.5, 15.8], + "rotation": {"angle": -22.5, "axis": "x", "origin": [13.5, 13.25, 14.3]}, + "faces": { + "north": {"uv": [8.625, 0, 8.75, 0.5], "texture": "#0"}, + "east": {"uv": [1.5, 7.5, 3.125, 8], "texture": "#0"}, + "south": {"uv": [8.625, 0.5, 8.75, 1], "texture": "#0"}, + "west": {"uv": [3.125, 7.5, 4.75, 8], "texture": "#0"}, + "up": {"uv": [4.75, 9.625, 4.625, 8], "texture": "#0"}, + "down": {"uv": [4.875, 8.25, 4.75, 9.875], "texture": "#0"} + } + }, + { + "from": [2, 11, 1.3], + "to": [3, 16, 14.8], + "rotation": {"angle": 0, "axis": "y", "origin": [4.5, 0, 0]}, + "faces": { + "north": {"uv": [1.125, 8.375, 1.25, 8.875], "texture": "#0"}, + "east": {"uv": [7, 6.75, 8.625, 7.25], "texture": "#0"}, + "south": {"uv": [8.5, 8.25, 8.625, 8.75], "texture": "#0"}, + "west": {"uv": [7, 7.25, 8.625, 7.75], "texture": "#0"}, + "up": {"uv": [3, 5.625, 2.875, 4], "texture": "#0"}, + "down": {"uv": [4.625, 8, 4.5, 9.625], "texture": "#0"} + } + }, + { + "from": [-4, 8, 0], + "to": [20, 11, 16], + "faces": { + "north": {"uv": [7, 6, 10, 6.375], "texture": "#0"}, + "east": {"uv": [7, 7.75, 9, 8.125], "texture": "#0"}, + "south": {"uv": [7, 6.375, 10, 6.75], "texture": "#0"}, + "west": {"uv": [4.75, 7.875, 6.75, 8.25], "texture": "#0"}, + "up": {"uv": [3, 2, 0, 0], "texture": "#0"}, + "down": {"uv": [3, 2, 0, 4], "texture": "#0"} + } + }, + { + "from": [17.85614, 0.22209, 4], + "to": [18.85614, 3.22209, 12], + "rotation": {"angle": 22.5, "axis": "z", "origin": [19.35614, 4.72209, 8]}, + "faces": { + "north": {"uv": [7, 6, 7.125, 6.375], "texture": "#0"}, + "east": {"uv": [7.25, 7.75, 8.25, 8.125], "texture": "#0"}, + "south": {"uv": [7, 6.375, 7.125, 6.75], "texture": "#0"}, + "west": {"uv": [4.75, 7.875, 6.75, 8.25], "texture": "#0"}, + "up": {"uv": [0.125, 2, 0, 0], "texture": "#0"}, + "down": {"uv": [0.125, 2, 0, 4], "texture": "#0"} + } + }, + { + "from": [-2.85614, 0.22209, 4], + "to": [-1.85614, 3.22209, 12], + "rotation": {"angle": -22.5, "axis": "z", "origin": [-3.35614, 4.72209, 8]}, + "faces": { + "north": {"uv": [7.125, 6, 7, 6.375], "texture": "#0"}, + "east": {"uv": [6.75, 7.875, 4.75, 8.25], "texture": "#0"}, + "south": {"uv": [7.125, 6.375, 7, 6.75], "texture": "#0"}, + "west": {"uv": [8.25, 7.75, 7.25, 8.125], "texture": "#0"}, + "up": {"uv": [0, 2, 0.125, 0], "texture": "#0"}, + "down": {"uv": [0, 2, 0.125, 4], "texture": "#0"} + } + }, + { + "from": [-2.6, 12.4, 1.6], + "to": [18.6, 13.4, 15.2], + "faces": { + "north": {"uv": [7, 6.5, 10, 6.625], "texture": "#0"}, + "east": {"uv": [7, 7.875, 9, 8], "texture": "#0"}, + "south": {"uv": [7, 6.125, 10, 6.25], "texture": "#0"}, + "west": {"uv": [4.75, 8, 6.75, 8.125], "texture": "#0"}, + "up": {"uv": [7, 6.125, 10, 6.25], "texture": "#0"}, + "down": {"uv": [3, 2, 0, 4], "texture": "#0"} + } + }, + { + "from": [10.8, 18.6725, 8.5], + "to": [11.8, 19.7725, 9.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.5, 2.125, 8.625], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [11.8, 18.6725, 7.5], + "to": [12.8, 19.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.625, 2.125, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [10.8, 18.6725, 6.5], + "to": [11.8, 19.7725, 7.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [8.99289, 18.6725, 9.02132], + "to": [9.99289, 19.7725, 10.02132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 19.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [7.49289, 18.6725, 11.42132], + "to": [8.49289, 19.7725, 12.42132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 19.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [7.49289, 16.2725, 13.42132], + "to": [8.49289, 17.3725, 14.42132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 19.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [7.49289, 18.4725, 13.42132], + "to": [8.49289, 19.5725, 14.42132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 19.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [7.49289, 12.2725, 15.22132], + "to": [8.49289, 13.3725, 16.22132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 19.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.625, 0.5, 8.75, 0.6375], "texture": "#0"}, + "east": {"uv": [8.625, 0.5, 8.75, 0.6375], "texture": "#0"}, + "south": {"uv": [8.625, 0.5, 8.75, 0.6375], "texture": "#0"}, + "west": {"uv": [8.625, 0.5, 8.75, 0.6375], "texture": "#0"}, + "up": {"uv": [8.625, 0.5, 8.75, 0.625], "texture": "#0"}, + "down": {"uv": [8.625, 0.5, 8.75, 0.625], "texture": "#0"} + } + }, + { + "from": [7.49289, 17.3725, 13.52132], + "to": [8.49289, 18.4725, 14.52132], + "rotation": {"angle": -45, "axis": "z", "origin": [7.99289, 17.9225, 13.92132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [7.49289, 18.6725, 3.42132], + "to": [8.49289, 19.7725, 4.42132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 19.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [11.49289, 18.6725, 7.42132], + "to": [12.49289, 19.7725, 8.42132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 19.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [3.69289, 18.6725, 7.42132], + "to": [4.69289, 19.7725, 8.42132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 19.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [10.99289, 18.4725, 11.02132], + "to": [11.99289, 19.5725, 12.02132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 19.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [3.99289, 18.4725, 11.02132], + "to": [4.99289, 19.5725, 12.02132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 19.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [3.99289, 18.4725, 4.02132], + "to": [4.99289, 19.5725, 5.02132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 19.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [10.99289, 18.4725, 4.02132], + "to": [11.99289, 19.5725, 5.02132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 19.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [8.5, 18.6725, 7.5], + "to": [9.5, 19.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [7.5, 18.6725, 7.5], + "to": [8.5, 19.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [7.5, 19.8725, 7.5], + "to": [8.5, 20.9725, 8.5], + "rotation": {"angle": -45, "axis": "z", "origin": [8, 20.4225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [7.5, 18.6725, 6.5], + "to": [8.5, 19.7725, 7.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [7.5, 18.6725, 8.5], + "to": [8.5, 19.7725, 9.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [6.5, 18.6725, 7.5], + "to": [7.5, 19.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [5.99289, 18.6725, 5.92132], + "to": [6.99289, 19.7725, 6.92132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 19.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [4.2, 18.6725, 6.5], + "to": [5.2, 19.7725, 7.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "east": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "west": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2.75, 8.375, 2.875, 8.5], "texture": "#0"}, + "down": {"uv": [6.75, 8, 6.875, 7.875], "texture": "#0"} + } + }, + { + "from": [4.2, 18.6725, 7.5], + "to": [5.2, 19.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "east": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "west": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 8, 6.875, 7.875], "texture": "#0"} + } + }, + { + "from": [4.2, 18.6725, 8.5], + "to": [5.2, 19.7725, 9.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "east": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "west": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 8, 6.875, 7.875], "texture": "#0"} + } + }, + { + "from": [3.2, 18.6725, 7.5], + "to": [4.2, 19.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "east": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "west": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.625, 2.125, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 8, 6.875, 7.875], "texture": "#0"} + } + }, + { + "from": [8.99289, 18.6725, 5.92132], + "to": [9.99289, 19.7725, 6.92132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 19.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [10.8, 18.6725, 6.5], + "to": [11.8, 19.7725, 7.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "east": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "west": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 8, 6.75, 7.875], "texture": "#0"} + } + }, + { + "from": [10.8, 18.6725, 8.5], + "to": [11.8, 19.7725, 9.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "east": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "west": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 8, 6.75, 7.875], "texture": "#0"} + } + }, + { + "from": [10.8, 18.6725, 7.5], + "to": [11.8, 19.7725, 8.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "east": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "west": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 8, 6.75, 7.875], "texture": "#0"} + } + }, + { + "from": [11.8, 18.6725, 7.5], + "to": [12.8, 19.7725, 8.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "east": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "west": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.625, 2.125, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 8, 6.75, 7.875], "texture": "#0"} + } + }, + { + "from": [5.99289, 18.6725, 9.02132], + "to": [6.99289, 19.7725, 10.02132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 19.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [4.2, 18.6725, 8.5], + "to": [5.2, 19.7725, 9.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 7.875, 6.875, 8], "texture": "#0"} + } + }, + { + "from": [4.2, 18.6725, 7.5], + "to": [5.2, 19.7725, 8.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.5, 2.125, 8.625], "texture": "#0"}, + "down": {"uv": [6.75, 7.875, 6.875, 8], "texture": "#0"} + } + }, + { + "from": [3.2, 18.6725, 7.5], + "to": [4.2, 19.7725, 8.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.625, 2.125, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 7.875, 6.875, 8], "texture": "#0"} + } + }, + { + "from": [4.2, 18.6725, 6.5], + "to": [5.2, 19.7725, 7.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 19.2225, 8]}, + "faces": { + "north": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 7.875, 6.875, 8], "texture": "#0"} + } + }, + { + "from": [9.83345, 18.6725, 9.83345], + "to": [10.83345, 19.7725, 10.83345], + "rotation": {"angle": -45, "axis": "y", "origin": [10.33345, 19.2225, 10.33345]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [9.43345, 19.2725, 9.83345], + "to": [10.43345, 20.3725, 10.83345], + "rotation": {"angle": -45, "axis": "z", "origin": [10.33345, 19.2225, 10.33345]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [9.43345, 19.2725, 5.23345], + "to": [10.43345, 20.3725, 6.23345], + "rotation": {"angle": -45, "axis": "z", "origin": [10.33345, 19.2225, 10.33345]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [4.53345, 19.2725, 5.23345], + "to": [5.53345, 20.3725, 6.23345], + "rotation": {"angle": -45, "axis": "z", "origin": [5.43345, 19.2225, 10.33345]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [4.53345, 19.2725, 9.83345], + "to": [5.53345, 20.3725, 10.83345], + "rotation": {"angle": -45, "axis": "z", "origin": [5.43345, 19.2225, 10.33345]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [7.5, 20.9725, 7.5], + "to": [8.5, 22.0725, 8.5], + "rotation": {"angle": 45, "axis": "x", "origin": [8, 21.5225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + } + ], + "display": { + "thirdperson_righthand": { + "translation": [0, 1.75, 0], + "scale": [0.21875, 0.21875, 0.21875] + }, + "thirdperson_lefthand": { + "translation": [0, 1.75, 0], + "scale": [0.21875, 0.21875, 0.21875] + }, + "firstperson_righthand": { + "translation": [2, 1.75, 0], + "scale": [0.21875, 0.21875, 0.21875] + }, + "firstperson_lefthand": { + "translation": [2, 1.75, 0], + "scale": [0.21875, 0.21875, 0.21875] + }, + "ground": { + "scale": [0.40039, 0.40039, 0.40039] + }, + "gui": { + "rotation": [22.75, -30.5, 0], + "scale": [0.49609, 0.49609, 0.49609] + }, + "head": { + "translation": [0, -30.35, 0], + "scale": [1.6, 1.6, 1.6] + }, + "fixed": { + "rotation": [-90, 0, 0], + "translation": [0, 0, -13.75], + "scale": [1.6, 1.6, 1.6] + } + }, + "groups": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + { + "name": "group", + "origin": [8, 15.2225, 8], + "color": 0, + "boneType": "", + "children": [64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/models/lootbox/rare_box.json b/src/main/resources/contents/omc_daily_events/models/lootbox/rare_box.json new file mode 100644 index 000000000..ac705d3eb --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/models/lootbox/rare_box.json @@ -0,0 +1,714 @@ +{ + "texture_size": [128, 128], + "textures": { + "0": "omc_daily_events:lootbox/rare_box", + "particle": "omc_daily_events:lootbox/rare_box" + }, + "elements": [ + { + "from": [-2, 0, 2], + "to": [18, 15, 14], + "faces": { + "north": {"uv": [3, 3.75, 5.5, 5.625], "texture": "#0"}, + "east": {"uv": [0, 5.875, 1.5, 7.75], "texture": "#0"}, + "south": {"uv": [0, 4, 2.5, 5.875], "texture": "#0"}, + "west": {"uv": [5.5, 6, 7, 7.875], "texture": "#0"}, + "up": {"uv": [8, 4.5, 5.5, 3], "texture": "#0"}, + "down": {"uv": [8, 4.5, 5.5, 6], "texture": "#0"} + } + }, + { + "from": [-2.1, 10, 15], + "to": [18.1, 15, 17], + "rotation": {"angle": -22.5, "axis": "x", "origin": [8, 7.5, 14.5]}, + "faces": { + "north": {"uv": [3, 3.75, 5.5, 4.375], "texture": "#0"}, + "east": {"uv": [0, 5.875, 0.25, 6.5], "texture": "#0"}, + "south": {"uv": [0, 4, 2.5, 4.625], "texture": "#0"}, + "west": {"uv": [5.5, 6, 5.75, 6.625], "texture": "#0"}, + "up": {"uv": [8, 3.25, 5.5, 3], "texture": "#0"}, + "down": {"uv": [8, 4.5, 5.5, 4.75], "texture": "#0"} + } + }, + { + "from": [-2.1, 10, -1], + "to": [18.1, 15, 1], + "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 7.5, 1.5]}, + "faces": { + "north": {"uv": [2.5, 4, 0, 4.625], "texture": "#0"}, + "east": {"uv": [0.25, 5.875, 0, 6.5], "texture": "#0"}, + "south": {"uv": [5.5, 3.75, 3, 4.375], "texture": "#0"}, + "west": {"uv": [5.75, 6, 5.5, 6.625], "texture": "#0"}, + "up": {"uv": [8, 3, 5.5, 3.25], "texture": "#0"}, + "down": {"uv": [8, 4.75, 5.5, 4.5], "texture": "#0"} + } + }, + { + "from": [-4, 0, 0], + "to": [1, 1, 5], + "faces": { + "north": {"uv": [1.5, 7.375, 2.125, 7.5], "texture": "#0"}, + "east": {"uv": [4.75, 7.75, 5.375, 7.875], "texture": "#0"}, + "south": {"uv": [8, 5.875, 8.625, 6], "texture": "#0"}, + "west": {"uv": [8.375, 3.875, 9, 4], "texture": "#0"}, + "up": {"uv": [2.125, 6.5, 1.5, 5.875], "texture": "#0"}, + "down": {"uv": [2.125, 6.5, 1.5, 7.125], "texture": "#0"} + } + }, + { + "from": [-3, 1, 1], + "to": [0, 8, 4], + "faces": { + "north": {"uv": [2.5, 4, 2.875, 4.875], "texture": "#0"}, + "east": {"uv": [2.125, 5.875, 2.5, 6.75], "texture": "#0"}, + "south": {"uv": [1.875, 8, 2.25, 8.875], "texture": "#0"}, + "west": {"uv": [8, 1.875, 8.375, 2.75], "texture": "#0"}, + "up": {"uv": [5.25, 8.625, 4.875, 8.25], "texture": "#0"}, + "down": {"uv": [5.625, 8.25, 5.25, 8.625], "texture": "#0"} + } + }, + { + "from": [-3, 1, 12], + "to": [0, 8, 15], + "faces": { + "north": {"uv": [2.25, 8, 2.625, 8.875], "texture": "#0"}, + "east": {"uv": [2.625, 8, 3, 8.875], "texture": "#0"}, + "south": {"uv": [8, 2.75, 8.375, 3.625], "texture": "#0"}, + "west": {"uv": [3, 8, 3.375, 8.875], "texture": "#0"}, + "up": {"uv": [6, 8.625, 5.625, 8.25], "texture": "#0"}, + "down": {"uv": [6.375, 8.25, 6, 8.625], "texture": "#0"} + } + }, + { + "from": [-4, 0, 11], + "to": [1, 1, 16], + "faces": { + "north": {"uv": [8.375, 4, 9, 4.125], "texture": "#0"}, + "east": {"uv": [8.375, 4.125, 9, 4.25], "texture": "#0"}, + "south": {"uv": [8.375, 4.25, 9, 4.375], "texture": "#0"}, + "west": {"uv": [8.375, 4.375, 9, 4.5], "texture": "#0"}, + "up": {"uv": [0.625, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 0.625, 8.375], "texture": "#0"} + } + }, + { + "from": [16, 1, 12], + "to": [19, 8, 15], + "faces": { + "north": {"uv": [3.375, 8, 3.75, 8.875], "texture": "#0"}, + "east": {"uv": [8, 3.625, 8.375, 4.5], "texture": "#0"}, + "south": {"uv": [3.75, 8, 4.125, 8.875], "texture": "#0"}, + "west": {"uv": [4.125, 8, 4.5, 8.875], "texture": "#0"}, + "up": {"uv": [6.75, 8.625, 6.375, 8.25], "texture": "#0"}, + "down": {"uv": [0.375, 8.375, 0, 8.75], "texture": "#0"} + } + }, + { + "from": [15, 0, 11], + "to": [20, 1, 16], + "faces": { + "north": {"uv": [8.375, 4.5, 9, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 9, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [8.625, 0.625, 8, 0], "texture": "#0"}, + "down": {"uv": [8.625, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [16, 1, 1], + "to": [19, 8, 4], + "faces": { + "north": {"uv": [8, 4.5, 8.375, 5.375], "texture": "#0"}, + "east": {"uv": [6.75, 8.125, 7.125, 9], "texture": "#0"}, + "south": {"uv": [7.125, 8.125, 7.5, 9], "texture": "#0"}, + "west": {"uv": [7.5, 8.125, 7.875, 9], "texture": "#0"}, + "up": {"uv": [0.75, 8.75, 0.375, 8.375], "texture": "#0"}, + "down": {"uv": [1.125, 8.375, 0.75, 8.75], "texture": "#0"} + } + }, + { + "from": [15, 0, 0], + "to": [20, 1, 5], + "faces": { + "north": {"uv": [8.375, 5, 9, 5.125], "texture": "#0"}, + "east": {"uv": [8.375, 5.125, 9, 5.25], "texture": "#0"}, + "south": {"uv": [8.375, 5.25, 9, 5.375], "texture": "#0"}, + "west": {"uv": [8.5, 8.125, 9.125, 8.25], "texture": "#0"}, + "up": {"uv": [1.875, 8.625, 1.25, 8], "texture": "#0"}, + "down": {"uv": [8.625, 1.25, 8, 1.875], "texture": "#0"} + } + }, + { + "from": [15, 2, 11], + "to": [20, 3, 16], + "faces": { + "north": {"uv": [8.375, 4.5, 9, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 9, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [8.625, 0.625, 8, 0], "texture": "#0"}, + "down": {"uv": [8.625, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [-4, 2, 11], + "to": [1, 3, 16], + "faces": { + "north": {"uv": [8.375, 4, 9, 4.125], "texture": "#0"}, + "east": {"uv": [8.375, 4.125, 9, 4.25], "texture": "#0"}, + "south": {"uv": [8.375, 4.25, 9, 4.375], "texture": "#0"}, + "west": {"uv": [8.375, 4.375, 9, 4.5], "texture": "#0"}, + "up": {"uv": [0.625, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 0.625, 8.375], "texture": "#0"} + } + }, + { + "from": [-4, 2, 0], + "to": [1, 3, 5], + "faces": { + "north": {"uv": [1.5, 7.375, 2.125, 7.5], "texture": "#0"}, + "east": {"uv": [4.75, 7.75, 5.375, 7.875], "texture": "#0"}, + "south": {"uv": [8, 5.875, 8.625, 6], "texture": "#0"}, + "west": {"uv": [8.375, 3.875, 9, 4], "texture": "#0"}, + "up": {"uv": [2.125, 6.5, 1.5, 5.875], "texture": "#0"}, + "down": {"uv": [2.125, 6.5, 1.5, 7.125], "texture": "#0"} + } + }, + { + "from": [15, 2, 0], + "to": [20, 3, 5], + "faces": { + "north": {"uv": [8.375, 5, 9, 5.125], "texture": "#0"}, + "east": {"uv": [8.375, 5.125, 9, 5.25], "texture": "#0"}, + "south": {"uv": [8.375, 5.25, 9, 5.375], "texture": "#0"}, + "west": {"uv": [8.5, 8.125, 9.125, 8.25], "texture": "#0"}, + "up": {"uv": [1.875, 8.625, 1.25, 8], "texture": "#0"}, + "down": {"uv": [8.625, 1.25, 8, 1.875], "texture": "#0"} + } + }, + { + "from": [15, 6, 11], + "to": [20, 7, 16], + "faces": { + "north": {"uv": [8.375, 4.5, 9, 4.625], "texture": "#0"}, + "east": {"uv": [8.375, 4.625, 9, 4.75], "texture": "#0"}, + "south": {"uv": [8.375, 4.75, 9, 4.875], "texture": "#0"}, + "west": {"uv": [8.375, 4.875, 9, 5], "texture": "#0"}, + "up": {"uv": [8.625, 0.625, 8, 0], "texture": "#0"}, + "down": {"uv": [8.625, 0.625, 8, 1.25], "texture": "#0"} + } + }, + { + "from": [-4, 6, 11], + "to": [1, 7, 16], + "faces": { + "north": {"uv": [8.375, 4, 9, 4.125], "texture": "#0"}, + "east": {"uv": [8.375, 4.125, 9, 4.25], "texture": "#0"}, + "south": {"uv": [8.375, 4.25, 9, 4.375], "texture": "#0"}, + "west": {"uv": [8.375, 4.375, 9, 4.5], "texture": "#0"}, + "up": {"uv": [0.625, 8.375, 0, 7.75], "texture": "#0"}, + "down": {"uv": [1.25, 7.75, 0.625, 8.375], "texture": "#0"} + } + }, + { + "from": [-4, 6, 0], + "to": [1, 7, 5], + "faces": { + "north": {"uv": [1.5, 7.375, 2.125, 7.5], "texture": "#0"}, + "east": {"uv": [4.75, 7.75, 5.375, 7.875], "texture": "#0"}, + "south": {"uv": [8, 5.875, 8.625, 6], "texture": "#0"}, + "west": {"uv": [8.375, 3.875, 9, 4], "texture": "#0"}, + "up": {"uv": [2.125, 6.5, 1.5, 5.875], "texture": "#0"}, + "down": {"uv": [2.125, 6.5, 1.5, 7.125], "texture": "#0"} + } + }, + { + "from": [15, 6, 0], + "to": [20, 7, 5], + "faces": { + "north": {"uv": [8.375, 5, 9, 5.125], "texture": "#0"}, + "east": {"uv": [8.375, 5.125, 9, 5.25], "texture": "#0"}, + "south": {"uv": [8.375, 5.25, 9, 5.375], "texture": "#0"}, + "west": {"uv": [8.5, 8.125, 9.125, 8.25], "texture": "#0"}, + "up": {"uv": [1.875, 8.625, 1.25, 8], "texture": "#0"}, + "down": {"uv": [8.625, 1.25, 8, 1.875], "texture": "#0"} + } + }, + { + "from": [5.5, 4, 14], + "to": [10.5, 8, 16], + "rotation": {"angle": 0, "axis": "y", "origin": [4.5, 0, 0]}, + "faces": { + "north": {"uv": [8, 5.375, 8.625, 5.875], "texture": "#0"}, + "east": {"uv": [8.375, 1.875, 8.625, 2.375], "texture": "#0"}, + "south": {"uv": [7.875, 8.125, 8.5, 8.625], "texture": "#0"}, + "west": {"uv": [8.375, 2.375, 8.625, 2.875], "texture": "#0"}, + "up": {"uv": [2.125, 7.375, 1.5, 7.125], "texture": "#0"}, + "down": {"uv": [5.375, 7.5, 4.75, 7.75], "texture": "#0"} + } + }, + { + "from": [6.5, 5, 15], + "to": [9.5, 9, 17], + "rotation": {"angle": 0, "axis": "y", "origin": [4.5, 0, 0]}, + "faces": { + "north": {"uv": [2.5, 4.875, 2.875, 5.375], "texture": "#0"}, + "east": {"uv": [8.375, 2.875, 8.625, 3.375], "texture": "#0"}, + "south": {"uv": [2.125, 6.75, 2.5, 7.25], "texture": "#0"}, + "west": {"uv": [8.375, 3.375, 8.625, 3.875], "texture": "#0"}, + "up": {"uv": [2.875, 5.625, 2.5, 5.375], "texture": "#0"}, + "down": {"uv": [2.5, 7.25, 2.125, 7.5], "texture": "#0"} + } + }, + { + "from": [7.2, 13.85, 13.85], + "to": [9.2, 15.85, 14.85], + "rotation": {"angle": -22.5, "axis": "x", "origin": [8.05, 14.9, 17.55]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [7.2, 11.82922, 14.81272], + "to": [9.2, 13.82922, 15.81272], + "rotation": {"angle": -45, "axis": "z", "origin": [8.2, 12.82922, 14.61272]}, + "faces": { + "north": {"uv": [6.75, 7.875, 7, 8.125], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.875, 1.25], "rotation": 90, "texture": "#0"}, + "south": {"uv": [1.25, 7.75, 1.5, 8], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.875, 1.125], "rotation": 270, "texture": "#0"}, + "up": {"uv": [8.875, 1, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "down": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"} + } + }, + { + "from": [7.5, 14.6725, 7.5], + "to": [8.5, 15.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [8.5, 14.6725, 7.5], + "to": [9.5, 15.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [10.8, 14.6725, 7.5], + "to": [11.8, 15.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [11.8, 14.6725, 7.5], + "to": [12.8, 15.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.625, 2.125, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [10.8, 14.6725, 8.5], + "to": [11.8, 15.7725, 9.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.5, 2.125, 8.625], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [10.8, 14.6725, 6.5], + "to": [11.8, 15.7725, 7.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [3.2, 14.6725, 7.5], + "to": [4.2, 15.7725, 8.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.625, 2.125, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 7.875, 6.875, 8], "texture": "#0"} + } + }, + { + "from": [4.2, 14.6725, 7.5], + "to": [5.2, 15.7725, 8.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.5, 2.125, 8.625], "texture": "#0"}, + "down": {"uv": [6.75, 7.875, 6.875, 8], "texture": "#0"} + } + }, + { + "from": [4.2, 14.6725, 8.5], + "to": [5.2, 15.7725, 9.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 7.875, 6.875, 8], "texture": "#0"} + } + }, + { + "from": [4.2, 14.6725, 6.5], + "to": [5.2, 15.7725, 7.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "east": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "west": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 7.875, 6.875, 8], "texture": "#0"} + } + }, + { + "from": [3.2, 14.6725, 7.5], + "to": [4.2, 15.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "east": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "west": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.625, 2.125, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 8, 6.875, 7.875], "texture": "#0"} + } + }, + { + "from": [4.2, 14.6725, 7.5], + "to": [5.2, 15.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "east": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "west": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 8, 6.875, 7.875], "texture": "#0"} + } + }, + { + "from": [4.2, 14.6725, 6.5], + "to": [5.2, 15.7725, 7.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "east": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "west": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2.75, 8.375, 2.875, 8.5], "texture": "#0"}, + "down": {"uv": [6.75, 8, 6.875, 7.875], "texture": "#0"} + } + }, + { + "from": [4.2, 14.6725, 8.5], + "to": [5.2, 15.7725, 9.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "east": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "west": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.75, 8, 6.875, 7.875], "texture": "#0"} + } + }, + { + "from": [10.8, 14.6725, 6.5], + "to": [11.8, 15.7725, 7.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "east": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "west": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 8, 6.75, 7.875], "texture": "#0"} + } + }, + { + "from": [10.8, 14.6725, 7.5], + "to": [11.8, 15.7725, 8.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "east": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "west": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 8, 6.75, 7.875], "texture": "#0"} + } + }, + { + "from": [11.8, 14.6725, 7.5], + "to": [12.8, 15.7725, 8.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "east": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "west": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.625, 2.125, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 8, 6.75, 7.875], "texture": "#0"} + } + }, + { + "from": [10.8, 14.6725, 8.5], + "to": [11.8, 15.7725, 9.5], + "rotation": {"angle": 45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [1.5, 8.625, 1.25, 8.75], "texture": "#0"}, + "east": {"uv": [8.625, 1.25, 8.75, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [8.75, 1, 8.625, 1.125], "texture": "#0"}, + "west": {"uv": [8.625, 1.375, 8.75, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "down": {"uv": [6.875, 8, 6.75, 7.875], "texture": "#0"} + } + }, + { + "from": [6.5, 14.6725, 7.5], + "to": [7.5, 15.7725, 8.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [7.5, 14.6725, 6.5], + "to": [8.5, 15.7725, 7.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [7.5, 14.6725, 8.5], + "to": [8.5, 15.7725, 9.5], + "rotation": {"angle": -45, "axis": "y", "origin": [8, 15.2225, 8]}, + "faces": { + "north": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "east": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "south": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "west": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "up": {"uv": [2, 8.125, 2.125, 8.25], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "texture": "#0"} + } + }, + { + "from": [5.99289, 14.6725, 9.02132], + "to": [6.99289, 15.7725, 10.02132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 15.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [8.99289, 14.6725, 9.02132], + "to": [9.99289, 15.7725, 10.02132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 15.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [8.99289, 14.6725, 5.92132], + "to": [9.99289, 15.7725, 6.92132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 15.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [5.99289, 14.6725, 5.92132], + "to": [6.99289, 15.7725, 6.92132], + "rotation": {"angle": 0, "axis": "y", "origin": [7.29289, 15.2225, 10.12132]}, + "faces": { + "north": {"uv": [8.75, 1.375, 8.625, 1.25], "rotation": 180, "texture": "#0"}, + "east": {"uv": [8.625, 1, 8.75, 1.125], "texture": "#0"}, + "south": {"uv": [8.75, 1.25, 8.625, 1.125], "rotation": 180, "texture": "#0"}, + "west": {"uv": [1.25, 8.625, 1.5, 8.75], "texture": "#0"}, + "up": {"uv": [2, 8.25, 2.125, 8.375], "texture": "#0"}, + "down": {"uv": [6.875, 7.875, 6.75, 8], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [13, 11, 1.3], + "to": [14, 16, 14.8], + "rotation": {"angle": 0, "axis": "y", "origin": [4.5, 0, 0]}, + "faces": { + "north": {"uv": [8.625, 0, 8.75, 0.5], "texture": "#0"}, + "east": {"uv": [1.5, 7.5, 3.125, 8], "texture": "#0"}, + "south": {"uv": [8.625, 0.5, 8.75, 1], "texture": "#0"}, + "west": {"uv": [3.125, 7.5, 4.75, 8], "texture": "#0"}, + "up": {"uv": [4.75, 9.625, 4.625, 8], "texture": "#0"}, + "down": {"uv": [4.875, 8.25, 4.75, 9.875], "texture": "#0"} + } + }, + { + "from": [13, 10, 14.8], + "to": [14, 15.5, 15.8], + "rotation": {"angle": -22.5, "axis": "x", "origin": [13.5, 13.25, 14.3]}, + "faces": { + "north": {"uv": [8.625, 0, 8.75, 0.5], "texture": "#0"}, + "east": {"uv": [1.5, 7.5, 3.125, 8], "texture": "#0"}, + "south": {"uv": [8.625, 0.5, 8.75, 1], "texture": "#0"}, + "west": {"uv": [3.125, 7.5, 4.75, 8], "texture": "#0"}, + "up": {"uv": [4.75, 9.625, 4.625, 8], "texture": "#0"}, + "down": {"uv": [4.875, 8.25, 4.75, 9.875], "texture": "#0"} + } + }, + { + "from": [2, 10, 14.8], + "to": [3, 15.5, 15.8], + "rotation": {"angle": -22.5, "axis": "x", "origin": [13.5, 13.25, 14.3]}, + "faces": { + "north": {"uv": [8.625, 0, 8.75, 0.5], "texture": "#0"}, + "east": {"uv": [1.5, 7.5, 3.125, 8], "texture": "#0"}, + "south": {"uv": [8.625, 0.5, 8.75, 1], "texture": "#0"}, + "west": {"uv": [3.125, 7.5, 4.75, 8], "texture": "#0"}, + "up": {"uv": [4.75, 9.625, 4.625, 8], "texture": "#0"}, + "down": {"uv": [4.875, 8.25, 4.75, 9.875], "texture": "#0"} + } + }, + { + "from": [2, 11, 1.3], + "to": [3, 16, 14.8], + "rotation": {"angle": 0, "axis": "y", "origin": [4.5, 0, 0]}, + "faces": { + "north": {"uv": [1.125, 8.375, 1.25, 8.875], "texture": "#0"}, + "east": {"uv": [7, 6.75, 8.625, 7.25], "texture": "#0"}, + "south": {"uv": [8.5, 8.25, 8.625, 8.75], "texture": "#0"}, + "west": {"uv": [7, 7.25, 8.625, 7.75], "texture": "#0"}, + "up": {"uv": [3, 5.625, 2.875, 4], "texture": "#0"}, + "down": {"uv": [4.625, 8, 4.5, 9.625], "texture": "#0"} + } + }, + { + "from": [-4, 8, 0], + "to": [20, 11, 16], + "faces": { + "north": {"uv": [7, 6, 10, 6.375], "texture": "#0"}, + "east": {"uv": [7, 7.75, 9, 8.125], "texture": "#0"}, + "south": {"uv": [7, 6.375, 10, 6.75], "texture": "#0"}, + "west": {"uv": [4.75, 7.875, 6.75, 8.25], "texture": "#0"}, + "up": {"uv": [3, 2, 0, 0], "texture": "#0"}, + "down": {"uv": [3, 2, 0, 4], "texture": "#0"} + } + } + ], + "display": { + "thirdperson_righthand": { + "translation": [0, 1.75, 0], + "scale": [0.21875, 0.21875, 0.21875] + }, + "thirdperson_lefthand": { + "translation": [0, 1.75, 0], + "scale": [0.21875, 0.21875, 0.21875] + }, + "firstperson_righthand": { + "translation": [2, 1.75, 0], + "scale": [0.21875, 0.21875, 0.21875] + }, + "firstperson_lefthand": { + "translation": [2, 1.75, 0], + "scale": [0.21875, 0.21875, 0.21875] + }, + "ground": { + "scale": [0.40039, 0.40039, 0.40039] + }, + "gui": { + "rotation": [22.75, -30.5, 0], + "scale": [0.53125, 0.53125, 0.53125] + }, + "head": { + "translation": [0, -30.35, 0], + "scale": [1.6, 1.6, 1.6] + }, + "fixed": { + "rotation": [-90, 0, 0], + "translation": [0, 0, -13.75], + "scale": [1.6, 1.6, 1.6] + } + } +} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/textures/armor/ancient_fishing/ancient_armor_layer_1.png b/src/main/resources/contents/omc_daily_events/textures/armor/ancient_fishing/ancient_armor_layer_1.png new file mode 100644 index 0000000000000000000000000000000000000000..c0f2dd47d3e3c1b6707b1cd20b859fc9cc17b9ac GIT binary patch literal 1377 zcmV-n1)lneP)Px)8%ab#RA_0loku)u9&$(AirgIPNu9V*ulsCqE911*(9f}tsx zK=7dydMNg#4RSB(wY1a(j3Fw71lG4yIo06Mw1y&4%c{W!$&w{IMbw7)AVD$HgZ8a< zc4v2G{n%;yotAmCv+uom^WOJn9k4<7e2V#lUIZj3H=azNAd@Jdba%vIx5mp1m)!)B z@c@)DFG}sw?2KUR05U$AJ~503Bq!F}r`ws}mGf5MykQ#w1ko}0FTmCTax4db&?}T> z5`}i?bSf015$3tGB22_qGD5>iu!?_w612?$TI1zd4st9fl${0G+9)eWJxn{+Gyaz8 zd@C8jC93lj_Id+L*}U@PQ^#i0FBoxxshhQN8iPp`wTeeL-kvvo-%6&=nN7doJgQe5 z%2}@&Uq$yoA18xtx?rm$TN`EivC8TmI`0&lCShC-kYhR3(D?Bjuu+pu{J6<| z?Ed61( zp83eb{6ExoKQ$9(?*6WZoZzC64M;vD)81-0Z`5x*6i3A;hZz~JKL&Cvhk)ec#wllr zn55o#09?3hjR$~{UYOd!P@{Wcm2<+^He}$}!L$0dQ3V=Hm~q zI_SI~?j8XE8VP4QHuOF;d4Z0I78GUGk7%3#0QWbhxyfeEptDc-`0@kwxs=TV53dT> zH^>FXxCeXC(O=CYX620ia+d)>Ww#*Q<$7TMf<8h_lqPh~r%NwE_=8@o z%gCpnhG;=)suviXMiM_m!1zYMX0KJnEnI}J#mWcoxg+6Ot7 zJC&YfYHT9GUuIc=$S-4`NeAO(p? z0YGLT#j4KusyazYq@b#EED#(P4Lg7a~JTbsd4G9gvy{vv*(r#$Z6c z^F3&rmyq{~!N8yX{1l`x?IPiDdmo3pN4PXDsf4JqTi|5+egOb3xL;#Ge;}!A+EMJ5 z@NZ&nTIJ2Sx7D1N2IZ)Si7p||3+>eBfB#>A>%=bgZ=)mJYnZgT+zD+rrOmqS4r9^I zTj@g}d+e^wT#=zA06?Z(K%DAm&?v8LT9N&Eb0O&3oZ+S2T04q(JXbo*8=?M2? z^m!bZ(EXG69bCBt0RIH(+GSi+0~fI-GVWjp2zj5V&VZ&&i7rdqje{Lv`u$C;%g<28 zZ3M14vAFP5I9J;pQVF&Dcj+o+^PKmnT=|1ubjtVC#YAWox3_}-?|Yb)oX8~lI3lHI jmPD#TQ)9wgY%}}=#Mj8A2~&S?00000NkvXXu0mjf;&_wp literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/armor/ancient_fishing/ancient_armor_layer_2.png b/src/main/resources/contents/omc_daily_events/textures/armor/ancient_fishing/ancient_armor_layer_2.png new file mode 100644 index 0000000000000000000000000000000000000000..8c07fd7e168eda9a0afe1eabcb5d2d8470c8025f GIT binary patch literal 508 zcmVPx$wn;=mRA_6iTA<>;oT%xA{U(uf` z&Sl~fUdpAYQP%o*ej`KePoZ6q*!m&>;AT7xPkh(oT)MxH_d5ag6OE)oqVG$ptf4ZO zh9`b7(Bc80uYlL&8db}+Z+(G~AHluzffvs(3}Y*FwLtY`@K2A^UaJQbx0VP1rj}>S zS)$);K)Dpb7`GoU71JIF`4NbWb;MTh-%u^rFng4>^>1VOaACJd>zfk*fV1OgROZqc z3EuU@HL@>2WED~&fv@oZ5RQtNpBe6m&nr!+vIadhYij{4-+*vbL|$o{0;EC$`o#)p zXCIC13*H}q(P_X}I)qUFT(0s;6X9s<#&nDSw29EICinxE3vhdOZETIADF{Z#eWgPH yfcmfvVNx>vW_OLzT9sRcY5P^VwUIipi+liMaF2}JmoBpa0000NS%G}%0G|+7(Td9q;akmDz5jp6;(Md?y%_1IjX@b#KLO=Ard(SCq&Q20{DS{O z0Yk8Vg%C)vz$3Dlfr0NZ2s0kfUy%Y74EA(!4ABT)+ZV`nz<|Sfazys~`bP_mqITWq zZ2VB+v|-(0e+G+!uv2EMk`6!D7F)p1C@jsNS%G}T0G|+7^HuLfD=ssHZ~cGB;(McX#??=k6CJ-V&$$;P{j?Ee=3kpr?m&vW zB*-uLKO8W4`7?e33Ud~CL>4nJ@ErzW#^d=bQhE8;#~K@Rw7O7x=N7e;m~TabqZxyYfHQn<1f|i zd!x6z>c{olUwcm%gnVE4j_a^eNsB}8i6??*WDaW9F!^l^w|hRDJ)NUWbQaK322WQ% Jmvv4FO#qQzXW;+< literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/armor/ancient_fishing/ancient_helmet.png b/src/main/resources/contents/omc_daily_events/textures/armor/ancient_fishing/ancient_helmet.png new file mode 100644 index 0000000000000000000000000000000000000000..27b7578b21b072da8266b7f72f6d7c1de274c894 GIT binary patch literal 271 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G}@0G|+7^HuLfD=z;(WbwUGI^*i6|HnI?HU`~`k-nVh$Pm7j&#C+S@*JSr zeWxDn08+dqL4LvikpP433#B%o1ZROqWHAE+-(e7DJf6QI1t=Kd>Ealo5!`#uk*`64 z$K_&X_Cnn||M#?UO`4JMXLsdl$NHA}3`vT&8klt)PBF;XOq#-?t25QNmMOENx>q_z y`Su094DKXHpA7+};k?oIYqs2rmi+zpm-rmj?VSJSTW$k+ox#)9&t;ucLK6UJ#AFBn literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/armor/ancient_fishing/ancient_leggings.png b/src/main/resources/contents/omc_daily_events/textures/armor/ancient_fishing/ancient_leggings.png new file mode 100644 index 0000000000000000000000000000000000000000..7d3cc9cded7bf16f10c222a9e44c53447697ab7f GIT binary patch literal 253 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G}H0G|-o|A#ETH%dQk3}Oi1`h9thXvO7wG13`VKbfz34^;B|mFQ(4#Z?mI z7yKUv7&e{JIS&-&EbxddW?X2Q;0*)78&qol`;+0E{188~^|S literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/fisherman_props/fisherman.png b/src/main/resources/contents/omc_daily_events/textures/fisherman_props/fisherman.png new file mode 100644 index 0000000000000000000000000000000000000000..aef4e3edbdc0bba29ad9714166952ddd4225fe48 GIT binary patch literal 7805 zcmb_>^n zRFvS4(Tf~Q0N|8+D0lC%>(iAa<8RJ}`pv%2uP)pW(nP(xF&lU%%=fa-eS@#Bm(v%l zo=`!TQ@C$EjN}wJ&wTy9kJ-)3KIUx*#w%J^ABA7=vWlLBMCCA4FWpGL@-kGn)g#&7 zvnvtPSvfdS(@M`dFtT}U;24JPtQ;6$J%}tE-y<$wGCtT?ym|YrnC4ySx})p-$eyQr z^@n%;9Fi41N+OrcbEQa9`k#_BdzNC~LhFue8R=3GFf3>5&DK@L@uN$3r`**%MsGhg zDvK2r`UP0v=_Ce4Em!)AM#GX1vMeHhwcR;CWy`lh=+RYMlnT?hy@W~e{ww;ttCO3s zZk)0^y}U9zlu_~6HpE}@C~YTmzLa-*SHDrY#a+|IrBhTMKBY(PLHz|9_T@GACEAQs zJ_ab;(luMXEgV(&1y5mUD#v+oP15#@=P6}dXLslB*1260)#~bPS~6jkY87^T_s4=g zoQWwUeQ*=mf?*+9wjktsS~qV(aZU?pPWwABu3E38@;*yn9UBX)B=-+PlNsWGks`bB z!X&ET-YQql4|^@;N4JD%Zbucfl!=;~4nCLz79_0ho>f*BccmJ)(yCt6ud>yF81P(* zL;+>7_FYy9e?~gNrGZ{qhdrY_#fkjh+l()p|Ad4(-t6Bj_uhcM?DrLISqi}#W|)Z! zJvpnAPyP6Uuo`mMmTPl7Om?iVd%&=S4H79PM|!QrmMNxsDf2+LY9c}_UMr4)W>7 zP}lL1y|Fs!h3%x?MMk)Qx1DV-g_Yh-6B>iq(glA?TH+fsgS zkkL`dt-X3qocGnhB`=Q;(9KBRAB}t}-+Lq5$gvjnPS?@rS|KE@ro<%YjR3sMoP?4Y z&7O#z?NYKy-JlBk&`}paaI`)q+^Tq;bWxlj%w58EjfT9KHrn{s&V!Huw`=O5$x^{v z+ux5{4-2Vj7V%PD4G$iEOJ&)qq(APF#9~G6mxd0i%>jM-V>c|Ja^VJ5Y3?)1rZ|hH z7nme3CWR)6_t^^SDe?;YK6qj2<6-evn=ad-u$)p6KxAGcIM||B|Le1aGB4`YgUT$S zO|7gy+p%HU$hnfDOV6O))iH8OzGzeK+j#@S=Vo)Ae`z_eeVRJ=L_yVy(oq~(!4Din z!SROs*Tye+O3O5ADmYQL-L2i0Lln#*HEy(Oe5vJ;+8Mk%e=)hI3YsFw%+Q5lInbU_ z=vCFXqj~51Bb7Y)uEZtQ;f~G*B@3%3B14suZVHRJ%ErnAob>|q(wi-qcq9;;?MJ{n z)m_aLHqbdc2mf=o!L3ga(|K=Z=t41(m7cZWkNH|{3P$V^zlDK)c=NhXNgu>&h;CT5 zY1!97Z<%|AkFF85X`$Tyx!^oDE*OR$j(^Vd)R4VMKOyQIA{-fdaoEcwC2HR)Oe#0< zPIL!?!S`ZP<74*ry=BECWPY%l@R(=tf{Fv5?+@Ii!l#nsMlQ4sN^gTX*xGwwZNGBU z_8?2VbPX&v7Us^kuEI>fpe;YONr^xmoN?e=I6R2qKb9>{B(A?RNDM32`XMsyRcG!H z%C62NE~PF8y!)}R%hs)oCr_Urcui4Cn{P(lp^hXia(DH{^hQxW(eV?!G8ZB7XyMS- zx;m>z(0#HdbVi2sj^FDSe=yeg?`&%j7W*Y?-!-UWqYBh(q-puAtKoUiYmKU&IENB} zR0}JPM^>-iqb_Njug)Sb6BJfqJGc2D`R3LuLg^Ed6!G|B%BKYUUnCw?+NIn2wzC_Yr&fjR3BwTK80TR&aTNqsRSNEAtxEy#gy;Gf+|-x zxVNYI4H@2PdP}Wc$g7WChPL{;ltUhTzGRJ$wh7iU|DIKOfheOye$7!%pOrUC^OMj& zhLvvX&yGo9yrd-n|MiJyu(;6l>@v5FfiX*;D(buunq@yA+I zUR`pG9Q98*UK0vufzz;gGkNqwaJ)ekU(T@0++t^liBbt(Lk^XAJ}P2ok4W*5b4Fgv zyGlcDi{`s91%ES%n^t{{*i>ju0J-Sv>V*|;{j)wYeHdh|w9~@QrFH|`JGC1$vvz0N zXd?8@-mnn`F^T#6WGEK%BUa&-rdE97RE~!Qc5k6~ud0W3-(lWkB z3ejrv4FUwklMU|L1}6H-LnER{_pNd1wMY-e?2pzNAA+p$qHnd5BEVFiwZ1++Pt1*o zy-}?@_X61tnS2njNE=TlKqt#N8#)@mIuSIWs`N8=2t!`O^z`2V<*WQ*i_KFfB0zbE zqDi5c*uO>>jgW%;Xia!t%;!5A@tJsiNgDD@K_zE}(*q}JSqjfJgAvS6HtN zrv`HEu~W zI-dyFr$y<|nV-lj1bT_0Q(|Z8b&2c#8nQ5)!*&2(B~d#%_K9A2wBdQH8{2%eR%|)s zrg3i{omkKst7-WXFl0#4BTejPtu0k@rG11(3N$ z%r!sp+D!?NJ>wE1ZjVwz1C5$kxJT#T_6kZS)Zhg)Ze=`1f7B&rxP`F!nqlr5;?61I z4IlOmFDLn)mcIWe^nVGAwPTRHfno{$C(GV;!GtB!+gEeD^oRP;W}T)4c)gJKTxj;H zTMvJVLtn*BPVd=ywG_`k;U{k_yBg}v2IsBj1Wwok_9T<4ndtsY`S=4XP9gfty1yA& z-hpUq(tiKY^O|H9LFl`D>gR6bOUKh&TgIMSHyEDzr)~5i=Deogu1frHYt4J!!0j@0 zVf=7p8Zl=FNw;fcc8ZoGcQefM-WX1^0E$R5 zcIA15{TSIKl_Jh;QDQEMk=f(>&BXS9bTRo+f4(LcPkomWE3C?>+MZ?2Hd4TwoPE5! zI(GFF3rVa?1YXzN?Xr@fi5w3y1V}Cau6s?bq6&5Y{&)<2Uzb!RBr8VX8YDXxDh7!s zWb~INa++0_*(=12k(rwx9O`ubSY2gy*9g*%(T+PY;VjfNZy|kmPBh=F?VbNhYnjFa zN8}q3mC-yeAth&;cdvg+sWckazu?N6iUI7o(e^dDC+R$V9;QHDRO(q6M_t)k`k7Pq z6}V~on>H2sifC(bK~gQ7@67EmS)uwddFuqIpYaay2pF3{Wzwe}@RHaPnc=$6)ourvF5(dwY_q zq)J=D1(+Z+3pR7$pILr)TE(KxVceHK3OJvM7`~2ka zA;`&RkYNza%VP@btyO~S3uR5h#S)>$BhP+hZg(sK0)zzs`TM!sZ{1|1J6y>)dI~ zxsa?B()2RdQc#067BED;)|-EPP-?I6PlcI0gB(Stx2}tO|KcI_1Bn3oKxGRlwN;wk zQG0Rd%}IqAe$N8cU<}QQBPmV$%TMKy=LD)Obvrr64G8rYpg8KU{Vz8Phq-QD9 zB}a=|PlPmJ+Yz7Ft8WC|3R00Dy49yO_Sh31wqBgCm?Y?KkXmY^mdgLQ^3>y z2%o$4Xx(N6)*(J`5AkD{Axzl+JimP~sATu<)7o4q@9z6GylCVZ9}MU){c)m=H3n;A zV1ILU43=6!@$HlVaFa@U(wd01*UuQu;KJq(-=itN+%88U5j|}j=$VYHMZ84uN(GBE zkcqh!)f2C%x>+8Xwm9zu=qjqRmmxL4MNg>VZ*_c;G1ii0Rl-R@RD%sE{hum?CkC=s z5)S6;brtQh3YuRVc*1{cv7QSGa(qtOR~q;Q^pz%NsxIk{jzQSHXfzUXG1ycV84lp!ov5bac*sy>IX}?eS zFkqzx!X7uG@+6qNY}a5clL49mTdOg&6)(6RWPOLH=%clVS>3{HhH<;%(eB=-o&@IH zf1w4CYf%th2HUlk<)m&epD9iH1xz1TP7ZGF#qI6Id9J4%Ep0^~{H{iX8iuG#ZXaZO z{~d$cuPhz^9qwbjK)O;GefR!<4GnnvUu}JleJ}|GMfi5Gn$-S`#8Y*Zx5w`ei{~Zg z2OwjWj`LeXic(d}tWt_i^RuA~9YKB5GVofKmp7XrpU6h5n+Y=pk2MtWL;U+G1q$VW z1DX13-JD@2-UrgMUmU3_9;nOmHKNtn@O|2H#B%;~{Td0`C zxEOM#rtVp4uH8G%L*kYP16qt|hRC{$m@}IlIv&ji!0KZ$3dbFia6e4)m0y7HQ!ry( z)4g97V4vypd-o?i?_Bq$UMnP~s6=fNbieGLX;gPw*Z0n9PubjHx5gGouWFM@1kF$q z-n04PYJ|bqe*Fdr5rt8NYMk%!KA!jfI3?1v;TST5@=eg!(XlLMPvk#pYc`_ecOT?W z%KD7@aUN!p%M5S;O+L&rOxlEHw+YOvS_}nl3z_ZUJU6(NDI7;$;WlkUq?M_dSYKYf zW#9y;d;JJc{_TD6c89frejea;MUvT)PX}>30!-dao?sz^12fa2_eq-m+ z!JJT_c#z;ES2Dn z$nwv70puIvmf7l)*>Sp{JV+xOrY{B^5aQlNfoS=2QvnlXDm4_TyBU)hn2fJ@HhB(; z-^_gh3w*GLgv|nAiIt`@Fr#6}p9O?f=YTI{0*+~TH_ML21wcs-i}nlJ+SG#K=pj)m ze}U<&sm)08$-VQtaNO|qTdwjHg?@rtj*I9oHCCwgV3|h~5FjzskOM$3Eg%IwO8i`w z0piGlZA#o+T$E#?O!VF75Cisl-m1^Kq%F8BjmZEd*52hr^W@_kkESZw1v+%ND7ZPoUF6~elPg4aP;@3_e!#hJB7)B0{VdX zylyx0wvtO5&`P&MmMv(ysnIXJ@-M&(0H?YX zw)RjM_b3@FUUa{WA79O0?=f*O&ZtUr)vy5Qlt=HyTaRCa8vGAw#gi|X+QU*~Y+D91<`8ol zCUqRm0Rll0>qX*gXL}NW10Q%aWGunA5fE}dd$<~=@omEgr z4H7s!UN5}~6|jhJjg{@e7p^{}nR5U?>lDjtyQP%4835Os3YIm_1ks>4vn%+rF_VQ9UXj%CVF(-T^ zmtlQX?_-S6GKxoIZkK&Hoj+B#JqJuL7h=E3-uv=9+k3es{eeNlkRLCf9ud#;AHfqv zMNnw>0WIJ*(;GXVZ)*Ft9GGL+BL0%JW*eLaO2-xeh4DNgdh~8`IS}{20|aCXwPNZY zhZExd2TL=gk53Gsx*U{%e}-WlmCldNP2eR2{iOu1= zew)bx(HSrq>DBM0b}oRfPY}In=Bc&ZmVS+s+|%=Xws)WcC1kjOo6m!)ctV`f=~`1O z&8Na=SMWrf6>(6Bp&K z&*ON5Au`%=Nfb_Ht?JCgNU7I2nGu^L-d%kJUJpnOLRcNOPr{k!3$Le@_yr(6Vl1}@ z1nfQ_s{n`ArM)l#GnHb%(e3|}{P^Py3anG=!7w1@va1+0UJUr6wS>BeKMTU>vN5HZJI(C4 zl-q9>xWOaVbTO{qqxbn&BYH?BML@f^7?4OptO@Z&L!1JoorNtK-7Wtl_cyQ*E6Fs9 z^VTZqz-mkn>6lvhXW1BxyK}ATd^htOF~AIV?;jVu0gD+mS8K&;Aqp6i9?!cOyu*>A z?}rE`%>ZE~WUL5hfaz|`e&Qbfr}s7k!_JwVH#^zpDvjXnz*5^??#B!tA$4oz%YZ;M z1o3Drab5fGdLoQl>P(YY&|g>kcp){NNZKq0ff`PJCzjL}i+3a$X)Hn;U(U{Y=o zMs$71M_8IVJ*+CTK5)kYGyG$&;}=^5D<}f)hu?lvah%Pl0i9&Vq0TTQNkxvdfn|}Q zr>CKHagy-jrx#hox@eibO)}0tX)p*+Ym~O;F7qC%^d7lKoDO zzhh)M_1Uy;6%?_-6`yk1NCM&IpxFlKPnqyepA2F#S-1C}sKbLoK9$k?i1Jtt+;GT1 zoQ-v`&=fD29b3j;7RN`oX-EWCM=B@l+7lCF%_syeI9P(UWZ9?{O%%ZH)nu+%(7Z!j zu}oZY410e$f54h}tLf)XG$95qqhM>?F;_uprb9ulgD%crHd^N^BMZ148Q-i;TcC*E z|5tp0k8q+}&xQhsnBF@R=DAk)yA#I5c`B@(RG z7~9{&wrfP%7&HgJNi4m2faOC0f9<3}R#ROvUg|Grw^7M(zKEx0Evn+ z-oV?vrkL@` zw$}+e{UqN!-VyS@erMtzZ5OMiE2E>rD>b+cyaYsS1}A}#N?xZM(u1X*W+8}{<#S12 z%L$Gn9|tW%;(&&pn!nMaBR4?LQQ{otTxlE%n)#co#v+FytU^@H*{gpBMZq~ypy8{B z?V*2a{lS3#4r}GZs1YbiV2+8niR^ zdiQC_LlNSX>HS{2IiRGYz%I3#ar>W(?cEzEfB{VF|CZZ5Rd3%27e%RVZp$|<8D z0>=MSP<}FO>-ThjY~oZD+-eMrstcK1WmcM+^vRfmcWrc<8W^7fR`B6M)X0G-2NBTes5f<>slmi1@DVR=<+@S+DFncYr9E=>eI}?g3?RQ(2V;6uB zgsvaBk#5L;AKnS}MCKXL0slJ)PPec+hPqOi5Shu>4@6SI*OQ$8|Mx&0Lx*_qudd#a SZ~#9m0}tiZ{_(!_{J7l;Nafq+Oe zR6%<05Q_Bn_|AKO!uw%w=k8{9Kl|C8*}aQ1Lg-$jOv`nsa*ndJpeYFzQ z?YaQ~CT@MLyAS=}Z{|Kp;OPhmYtF043wrZ+QA+GSzd-p-nO6)@Y!(e0c+87eP)p$^ zo_vn7I-HU^5_;DrvVro~yFHdsxtlc7NDTz}s4>f}2$s=UW?ElLF#B!exBB`+uG#|@ zuDFf~S?l4+fR)XuJO?MI&z^yqrhL$>tuHxwIVJOzmz9?!g{>bXb>de^lM=RjG;r+3h}$UGBI09QIlA*Z8b)r>v_v|bgZ{1d3is%?6%ASCwxym zhTMF(5~-8CzhADL*N%GtqM*2=sZ+@b9}&Rjr%;1I8P&Da&Zo}b#wCNR+FGssKBQ5E z34rqg*Tk$w+P_N5WP<=5d@8@QQTfvL$Fjc4tzRYM+wIFZ42lNJr3VI#x@lOWli17P*CG6q_1y=Sxx&7QWHIXVnRJq>*bwvj8d*aG!pmckt9?!@3tL@H#&k-WzTYOh0Gz?y#7vK7O4-_b zcwAc)^*kRc_dfyyi21Zv(QTS>tNG7wC@XYvi(*EbLt*~O*nup5?V2fa4fya5@5N`m zdCQEI&d1ob)tmEhan5r6WJGcGxI&k)o)FqPGq8N?HBbnh7WtOWH0z@lT?hJ14&!wv zGq5pf{kxroircK{x8%fByo0t5EAA>>}fR7UTM ze-gn?;b9tEx}D2=`e)aFylqnr8#|k~Ci3C(){jZdfBAS~=8$_z;=HYA1#_!YI=O*! z090O}v|8wu5t;pRilNKhF+HCQ6Ppp#;t=Uf|MXdTKC){R0~Ebp$h87C|719(YQW5Y%5O-QcuS7q2Is|cy#!2a-qi;Mjk{DG$Uuh8 zt2Eug@8e_3jsy}LCvo#CN=dMNdOKe^SB1=LkB|HRIg1!!`5*rhJ~urS>?8t`Dz}uA zG#hP1auJN~N1pCKOk*p{%Zt(?nS?)yeI9l#tE}{sWKeZJLe=Rc1~wvaRtz;?hS#wB zyfLeM8lo7zF3yi>tym8bA#=0WkrhDTylCFENeTV_&(1L0O@dGw(5!aZUD%yO(drX) z+YLQiFV(VdJ%TYt%>?jfJiE3ZASP7jn&^%&oYqhA2hwEajKicpGkJd`>2}3y=ZihQ2CGpWtFO~)EQ$4b?l;1ZSF3N5fH zk5LG7Eb44~(GOvjg^Oj3cgOiuOd{rd0r$<_%Z~FDfebvzOR{NPkxiv(YZthiN_ z#7SG(_|=hf2WbKHVzY z5R4V=VCu{)g)MxcJ}8`9mIB~b>UQx#N~P7#jrH?1C=6xrf=6WH(OHiZjMdEwKaOhL zEDa|-DMqPy#u_54h@p#J*O!);&lB`Cb^XYHsJ3-=(fMCg*lWB;lNE9~i#Ag0kz1bp z2=8@Fb*$;^cnn+GP9gZ`b*$Ar3cdfQz#-gkyYDV6X@+orXuau+lKdtKD9FrFFpQ@} z^8kr^=9ZT9)>XEr$8Hp`nx?6ejJoknqYKq8q2a~u=G>snua8z#)IXP*QLqZe(veTE z9XKyaJnfZCwSSB23E2{#GT2faSYVeaJ2y-}bR|^{G{LnWWwE8cRNTu=T5kvc=O~Jn z>v9DJUR=zySz6tIMKg%rqj4r%RWL@%R^e=(}Mm)I0jfz)e&?bzecEclShGzK!qb02!G% zm^J~bxTH6YTv<^B9ViAaMp&7_!>VjbW##3gAIg9zJD5# z31;9n?zWidZ_#g~qI5-KOm-;DCEeUxf3_nSxbtF2y+6c?fy(X=*N2nDhQF4L7Ddh{ z(Z_xX4;N;NjX-;`FzYM1Q<{Ex_T&O2^Hft4rAzzUdgPEJR#gg_%%#NOMxOG2A>2I* zKx+ds7fCK$MnU*qGa(p0g+ep#z=@y{K)jn$dRU_K_fQG{)R$PD5z=stmxsx z>`cQ8NV<2lmDGsh5@c&-Mv&7@zG~cVeqV8VW_Ul-D~&G=mrKymP7m-o7jk#;Q*zfz zG5N_0eoyJp$UVAQwNn!lva$TDg@GG#_B-^HtHryLpcD4&Nm}=!`4s_<8-5h?zN4`$ z)_R+NR%W*3=_k$(E=Bo0V-h!MK17a}V^JhN7BKj|o}9NEo0$j2`ASUL~h=`0PZ#{p9CS*Sa9nf6TJCdY08j*9w`9 z+51jQz9wBY>g}19@Lj*aK(3WgzhosNcy&FtYoljlw49=CqsLvzzWF4^c2Z`;KZ?}P ze0l=0A@yaF!N&YjuWxUwctfEXeTK~aN<4wXTGA6-wWQ-7Fc_W&Zi{tY+ z>rh1jyzV8;8onCjwDSv#xx|dN~8(d7@~qBR#IfM&X@-_c6~v z#syj`MiV8VTPYNU|5}!!^>dF1BW`R+<}IhdF-GtdxJNtT0RrJUEVBF~oln)bhd${? z<(|f>0W0k5CC>gf{OhqvwX42xJUQTM|P$O zf-+x*#fgg-xevv!Z|wj{;9SxA-?Ys=q0xu8WfZLk!5w~HC0pl>2pQZ8vObOtx^(e1z$ayr`U;vEZ)64^%;CHtINwuY*gGv zRRJ|?v8zf@X4vj80h@BOB6G>ziRZ-0p+K!8h?C5XtG7v_P7$hQEinDnBn(39iCbik z(4jdpJdCNjL6ySzT& z=wX-M6Z0zAFYN95iW;vh<#Ia^zm(o5Dz1!NoN$hvFIvvM3t7!ix)2(_lU!(fvJ;aO zqi|MfeJblHUc(kO-S-^m*vb1Kk`_V0)LS_0%<(JB5_1~kH?b)dz0JX{rLz@QxYlpS zL0&f(F;EZIK{@98gY_@z@QxWAy+2<%%fGjkEHSTH)6925Sc` zJ}lFSbemJd-;$cE#^0CVk@KlZe+U8cri|NDV)$SK*O;Ei58sA5ycsklP`ug#gpMgq zrXFaW@TttL&8aXP2@aAP52w~QhyF_0G>kqE7JDY6cxx0BYj?3Q&j==+3T_f&7=ywE zXz;!r{ijr*RNfIi9!w2YLMjBX(b_vO7>ZWm3D5s1&A_L=aUOo|b0Kto2QaYuVzeb< zo}NQ$qkcNH2TU$6LCA+jU#%Gp=3o+3f{f5q8X#Mnb4l_!w8&smP^ isyh1rf0d`;C8K>f(a^9Bk#O}}0MOS)XjR-pM*I&pS|g(X literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_animation.png b/src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_animation.png new file mode 100644 index 0000000000000000000000000000000000000000..c4f4560ad7256cf82626dfdf7c0b961f8d95e135 GIT binary patch literal 827 zcmV-B1H}A^P)4q zjSLYz_s#~>Aw{;)|<+{kf&F zcUq$vmke|HZ{gDB0000FAsW?E^kUaamh7_EbFI{4Z`4wUC?7;ev!eElM7m+Kp=5S{ zSES(V{;uc{{@JpbqBDD^wTic%0{{R3X%xFI`|xS=pB*AS4<51Cc{UNBHh`tLo^n|^ zLov<%HctDyusP8-_5V(#!nMX$>p1`b005*oy0$HP>&t8o^lLUJ`n6QGSk{Yc+vxj% zOPZhF5C8xG0C1FgZ6rVC{`hE^ty+P!^&9{I004kn_zRT!7y56bhm literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_animation.png.mcmeta b/src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_animation.png.mcmeta new file mode 100644 index 000000000..891fa8840 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_animation.png.mcmeta @@ -0,0 +1,20 @@ +{ + "animation": { + "frames": [ + {"index": 0, "time": 2}, + {"index": 1, "time": 2}, + {"index": 2, "time": 2}, + {"index": 3, "time": 2}, + {"index": 4, "time": 2}, + {"index": 5, "time": 2}, + {"index": 6, "time": 2}, + {"index": 7, "time": 2}, + {"index": 8, "time": 2}, + {"index": 9, "time": 2}, + {"index": 10, "time": 2}, + {"index": 11, "time": 2}, + {"index": 12, "time": 2}, + {"index": 13, "time": 2} + ] + } +} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_animation_2.png b/src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_animation_2.png new file mode 100644 index 0000000000000000000000000000000000000000..dfb66d430cbfd2088990023673f64d60093362a9 GIT binary patch literal 360 zcmV-u0hj)XP)$b1$GI5 zw_~76LuG}Ba&XpC0^rRW>p5I1(NL*C*8uF&av$hV_but>bb+!8tT1pB)*O`Yf?*Dn zOAc1SzA$hj)*Q@(lq%89rGn_E`+jAGforgiuN5BVf>N1=^!b#Iak^lz!ay56iK)}L z3hDDw6i(5CbeaD5birU30N0>LId!C?K(w~B+8nKg^t1I#=DkaHLBt9Jdqwl`F&(IM ziH7v~RP^RlLA$+g2lk7m@?(0Tq)X;dsX$o; literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_animation_2.png.mcmeta b/src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_animation_2.png.mcmeta new file mode 100644 index 000000000..02e5a3fab --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_animation_2.png.mcmeta @@ -0,0 +1,25 @@ +{ + "animation": { + "frames": [ + {"index": 0, "time": 2}, + {"index": 1, "time": 2}, + {"index": 2, "time": 2}, + {"index": 3, "time": 2}, + {"index": 4, "time": 2}, + {"index": 5, "time": 2}, + {"index": 6, "time": 2}, + {"index": 7, "time": 2}, + {"index": 8, "time": 2}, + {"index": 9, "time": 2}, + {"index": 10, "time": 2}, + {"index": 11, "time": 2}, + {"index": 12, "time": 2}, + {"index": 13, "time": 2}, + {"index": 14, "time": 2}, + {"index": 15, "time": 2}, + {"index": 16, "time": 2}, + {"index": 17, "time": 2}, + {"index": 18, "time": 2} + ] + } +} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_chest.png b/src/main/resources/contents/omc_daily_events/textures/lootbox/fishing_furniture/fishing_furniture_chest.png new file mode 100644 index 0000000000000000000000000000000000000000..b7e0dc8aa43f340296f78449731abc6cde96a2a6 GIT binary patch literal 3821 zcmZ8kc{mho*Pm$^Mnf^fSdt}%lF3pJ$ugvnY?WlsQhJPKBumyYC2OfqLc~ZtLX<3x zFvA!oSt~`>8QzS?G7Dia%r`yncU|B2et+EO{^OkMKEL~%bN|kLGMpW4BqbCj004lb zovrl+;g0*g#KA(@Y3|nx07y01SzBI;^;v$_RuyU|o9cN(R^-o)hEg;~HUXS`&`LU> z-cc4LJx=JSw!iL>vW7wx?|@;3u>M5+z?(i$fZ_W4xz}st;AipG^Z>SNb<*{I{i^k; zpwf6&ysv;UIF+!-B*$`=E%0?Huw0!o(l<672&;h=zWKwFu-nLK!2ylcM0 z4}5hcenuY(YWNWfxM>73h7*k7WbhyS9`zwgXZzxtXQ8pMcxOo%(YU71oN6o){ z?PNis^Y^Jyk22UHnRdh7{peO@QLW+l3kCGcD{o$8rtJB3)~Zp&^JcPxXK5}TwqSPn zJXUAZ?LrqC7*{?yX)+cy-D4d!S{m^8qyMKh)cRgXo!Et-pVO31TefNaA3Rp#thws+ z=F^-{BGM{rC2%A$kFQhdPXM&_K-*1N6ECsZAqOp3jf-aH|Kac=B)4N^Q)0ar`bYtH zJ)QTTx42t&1tU^=XLhSNVkvnw%figrYqZJ=IXFXT36Z z%H;j;lqF)|YDfqAo>G4tSI2KrXw7Ibf2ii~C}>Si2bz8^;g<{nsw#we#oDM@?!d+Q zv{s-bIx#3qX7SW=7+EeU2*i1|Tq`s`J)+WKop*$ESlO!Wv)Vh$Cab304~U!mPwSSTk%*s+Q-eO zfBpRvXA*`Is+#M8yv-f$S6}~3g^&)#{DBjw_6JD5QwgiQFQ8sr<98soFYk;_2XMCL zZFbUt(KBFTlwbfo!@y^cl_Q)P4_j6!9!~*;88n`AEE_@XnVb; z@JVLDkJyFsrU-}M9@RnGXAv(opJx3`)Fy5)V)J+hoFXJa#kl`k?8%{}pMdp`l&`x~ zm{-MsmK2wX!rlw3r9QnR@P{=El2-wnVA{l=GmT=ZTg@@*Y4z zM}vw1%9Rfm%NeEzJN3|7+7f3@DGpQ^M=Q`-6F&ekDO&?i{BV)<@D=f$v-`$j;cUUK zuK+%g9Iu^}qA|te8l@w4=Jw}|w{%)h%1StaoYSg^^AECwOaV>c^z9?@H|%d(@R>pT z%z4`t$EcBsOIuR{QfvzOvHQ1UYIEz#$LfS>*0BCaMWEj8U5-+iLY71(7~!Z=mYT*n z0zX_X7Q|!SDl6VUoZS31^%ImnvppJy+yBK^;+90<>s@%e=)Mw$JvzNRA3)anOy<(2 z%@{3tEt8V;!2s5NSL8}QNWub&l`+7vu^G%Y7v_w;Ey84>{JzNduzX0Y33VcgzYlZ^ z4d%=ifgcX3)l&26W1BwA?#lCYFz1l(FKYO7Zzljpki@wN3*@F)DVq+)=Lq>d<0alj2n*3 zM1GFi!`n`IHPTpQ3+BMkoSn4O3>pM0qh^(U8ffsDKf2+q3z|}dqRZ|a4*6% z_AD3+b3SeXIRcwcMB67AT^tV8$2kHQyyQ@^oNQ}sUBY__?=<4BhccywH$}3Fgn}k; zPsC-4Tk^xD>b;#l|M`k=!sv{!z9E?pGoCUw65WDmX4|i(dzFS}-lRI;5)#F4l#J3a z$gS3(`B}wnPJkD9+qe_(j6jFq`zZ1{pZ8j;ruiPwMAd~KA;nrcHv}E%$|v~YvLMp$ zloS7W8d(E;#SUTM#RhGm(;b-TUoyr%rYc|}L=8_)$+c~r%FJ3G=>!;Aw&b#BZnw!k z=v@2+pa^cfpgH_ch*aA?Lic}gNhl*$M!FN}9flKiZn+sMscYHeC&J{S514k2ELHbV zbF4r^B2!KOSjbqNx?p3N8r=A~kyYa6i>FIL7UjY9cElvp2lqEFU9$G^zIRtG&xePPDskx1rd`X<;Xr zj)_EEPzqHiP+knwZR1#D&^BVc}vHY=YUB(-qL(*ulU+?tNTBC8ho zCCRc2vm`Lc_CV(2!jvct%*Fd!bGt5wXWv{U+dL8|{ zRU|oN^1N#6WL1)RK5c(S-i?VK47W~bK`n6KC4LW{v>zG`10eE+^bR%mM7xq7S0y(M z)k|Wjc66=1tF#l>G2U59xRxTKnzGPK$f#11lzHaM{P%qgQgfRroDFP$ysyAD)iC#MT{Lx!afP9N!PONOMAY47uZ7tLN)c|egLm#lX*A(bO3yfRw3NhLPdzs^C0C2inexv5j%p3Q#6>3!T zP#tQa`9p~GbQv!X@~;G4$B``^LgBWVwEK!_N1P+GG&TF@;tXp&>J`c}?fcTnh(leC zD%(l#uEm+OS{z=&%8|5nFV8G^5P4xxr;^!O?3AkEk^9AsJ!8S=joK$n5+vWpeq~oa7DAej9q`3#=p$15MdsRGJACt5{DJ>IBalpJcT&XPhKIN{ zR!rqSzlX_nZgj<`%W#CCNme*&HBqh~d;{el7fKN(H@60T=zVpXEKuYb8uzH|zyIjM=CH9X426jvm#(O4uYG&PU!63?U15E z90Y;-5FKQ?#bpm})Y5X2N{gD|B&15(^4%FvFXQ&hJdn&covThJxiij$mr?$I*CI%( zZQ<0~SzqwOx;ABI<-*C*v7`Fv>wB64;(!0tKp~cU36MSD<6^MCKG&N)K?2yuR_{-s&~p({Kz9M`-~LBjr8;Ah2$#zBDzpf9o2>`60TZ;Gk^s zciQ62qgl6|19KNS{l7w|L@wO03H9%YLq#a4`cX{FO0es_TS4lZ1t|FV44jU zPa;cN1-_OH=09W&GF8;9)x6|-%sKCiwVo=R!4tas?##Z&Axx|fmZHh*{WFWvq^ zeA+3bTotN!jgiH80LO%?;Dqi+W+oJ7IwPKL_gwXy_Ux7)qE0aeh6<9uR#+~n$dAE6- zsi0R^<*Ar|HNImrebD~&lFZiIluSylhFp;XZs&;{vS1_UNZ;3DU=?LO4>-zhprmql zr&j(@x|-!|fB&XCgAyy4UulxRiXnvs;i`Mx!9$osY!z2+{$)_>>KO{G$EQEfKpHACavuo^X0`HB;XX=W_lYMOX&_zIE zo^|n}v=kKMV(*$37#!8;_TI8oy=`*o5{CiXIr}BS%T+2(a*fI=YHC#5CUZ@Ou;|o& znnYJm&#Yg+s8(;|EXyZBMr{QA2jBDyX_JvV{Ky7BywuFhjONDvd_=Z#aSoW1?ww~* zj0XJbV;)QV_D6a zjarhHG74-kS`3oUgvy%G+(scZCwnAF8Z+7tTkNtEPh0cGcINTT`0ub=7=%h2H&VRf zvU@g0?h$TriS4}w;?poQh*y7bw3<($24ave?kb^m6F^#@KyFXcwSo@vkWec;SLIm*2MA&nEfnP zi0Xo@5^*~3%?Bd^gH{fqu8)y(KA}blGMo&Nr*9iXgd6&4o^6uhu>o(^-oM5F$}E4= zd39InL5SG1G@BPS6|8DvjG>BzE=4uGVNWDITO2U}Q=p@xzX{=yZe4R^ddGb_$B^yx zW3SVIW^Z+v!WdJ~tncMRH((9Op;QD;_qqrwp!cw>o}M1n81`)t^u3CqmxMAxzp|<- z+$d~ADvqN@_+UKh3KWVhe|{sf50q{r#t8J0`3ARPUbwn`a44q3ic{_dE0n<^?Cw&+ zFh$ma2ysf5SQlw(rn-F`7qSaCN#I1Iy=oNPLYaJ^$Fi_3k%>PXS7*%{Xhv_q5g_A# z-N>4pL{m4OV;dhtM08BM5s0KKq-9d~&3yVkJLh$6k$3sp)MM>1Per9`nyL)%ez6q$Av5}dhj#cNDA9bred59D8B>>70Ez@C6 zf%|bwc1&S<*khvSKkRj`+;MUJUg)MrzQd~%z1@@eGg+(-Y*&c$Vni54gu(46(U8Md z#yp?~t({f9G|ODplgK$wL!l(G2TR`(jex3C{O0ALi5E%vTKS_Y& z3YL3+(U{vqz~Beryp!_V%T-q(fd~tQdk3>k z0Wq<$x@b6_oc5+o`DBluP2dmVOL)9(eGC?F-3HH${Y8Zi!9JzrPH76|Jv*yadSz!S z1V{s*{uLccZjI*gym7b12OI+TgPS!P#Wav&8p9HgC=r_cqLeb3rZ45sj{=gK{ro@5OGixNK<<@vqqC@9eU@o120_ zrk-~h?R5XEZ;!tw(SRQ@&Nqd{D;ym^Kq~9!aGZlXpM-Vq^Q*f1=aRnT@qn^a%i1Si zy5}TD(6f|bJ&xaLfKTr9(x}F9C$$37aa~&qmc2e1f4=A7KM-$#3_hyocU*KT=N;JB zcOtgPioD-?R!=*@;leTJMb^}LAug2%3jk?YR-)#HVfo{|0!jx^FpYps!KY-gxLdx+ zZUpZk@{oD-!2tB@jkh!_}jeZ^x z#jjz^i&`}A9fE>nsXMOr<3l7)WUq;Mrp}}99E0O2Wb(ba!-&3*yb~1{FKhPCyvg(X zI5P2Kcue;r3F7QY$NmaYJgf-<-yNe{MU6BaVq0)ZUz=y7ekD7>_4fP;GEDU$>zFOn0E3;%51Vso7H)X*W(@hSb2z+ecnXjnwTNakSs# zdjryxl|8i$0Eq_kcsr4*J0@1YK=pEuYNrUZZKNsfZ&#zJw@(W|cgtJP-CC}O#GiN6 z?U+hke@L3|g z`}OYItmTAS4KR_^m#o^F>WJ!ois+$smuhC-3UhIUl<+QnMVOIq5L>vluB4P*{`e-P zZ}Bx2WU*yHZ52l;XJ6eKQvMv>&t=EGX;j*h6bSYH8vt4wYPVpz6D>p}l_xyzXI-IM zGTmW88*5RJC_a7;QvD0MJ0MIyilQD4UrtqvJiA%8^~HI(+g_=Ft>TeoybFRYgEW6g z@m_boSs$xfIJ=_K4|I-EvFK#*`zU?7GmA?iyLU}fQy!HNd%L~UgRNOhZ1sIO!lhcN z*rcLdeC;|-iWo=g?%T{>KY?#>*)uqym};m+7tI`df814USHC^!XZ$aMv@9xC z>Z!NMyrI5JyCEj+y=-u*q^Q_qzY|h-Rr6%E{NI|AveF(da4FH9&{&?bE%x*6c|(_Z zLmYwcmMhqOJ8GC(J|nt@SZX+1LBH6#7a^bImbS8TKaYKRXhS@-)5m)AnC*Pw=oPx^ zzu{korIc;elV{v7frvIV~>ssXAECGgAwsBV5Sa||${ad^*yh5jLD*I}gkN8Baea5V; zn^7+0N^Z`R(KvPcSpkFup;+g*q(yTp68a=AVl8Ny($TJ+IV7I5PV~V$TGsfyq!*N+ zvHB^F)?=^zC(mJvy33y}BT6J3<~Q*2$~P}YbX#j{ zdsYThuv?&fpwP22KYF$}2}0i$&8k7V1Et6xi>uE^(h_xv_FJ8ulF)NgFlB+mET*wD z#>JFl5&;K)L_~EXl<#RYzBIC`5q(3N+;2GaRmg;-Xjl$ne?m82 zJKBf!n9d<*a1|aLC}UVrYn2!CE@OAiLnxh=f63!TzugUnsSJp7jpf6ul{W3=*Nt!E z6fCL94PR&6A+U6$^8Mry>q0WN0D~BU=210xH^Xsans}8?D*D z5q-hLG+izSelZlBhiep!J8=7#Bq}YB3=dOlYip~7OSq9KrB5s_R*1V|D;pcnicKO- zK})w>Yo-chCCS-h3QaVgy%i0TR+ztiBIkvH=(2w`wW}p(ichWUiR0SPi(S1z1Y$DF zMUS-ltZDQW(odBK?{u215sM$j+tUUTDd@%Me(^21Q62ufnFu#HeOF#;tCdY``MoYIkH$uV;=o@07f0a9Dh|;HZC)BM=|u~;{o-6)s+;2Z zVH+RC0hb<$wHGZq2(~QcU4d}1S}8rwc>2kOY)R#J(0h%~atvgh1%i&FX?+%IIx`L$ zhU^O*>o_o`#iGn)9V$~PGmX6fh25h~g|~5Fv#+xOK54*a8G=NTUrA0VT!^A~ad@Ac zbu=Vy7=!-HLYv`Gsd;_HHJZlY?vp@oC*?BhyMuNAI-oLx0vBVhVOIB9>iWfN;<;coRa zCf}af2JO^xd#HEoHyZF8@YAhBo4NI8XFcZwn31cW=EK13oF(s~LjuRZQXu{$$o``~ zpT&O1!K#MfErvG2xF2BKbP2TioUk2mX>|NFv>F=Q34pB*F_#=lzRsg;jT&nlm{8x# zgql@7^M8BR76<45+r1!y34B@-O&I!*AG9|7lnuW}SnuSm?cp7NZ7}qAlk6Y~@mYM| zIR*MAX3MPHNI1=XoXvf*FF{_UZNK<5@ZVA{wDRm)Y~iOke>{GWM;hiWg?IVz~Ip#I=;k)f@aIv@tP;B*@^kA_vIu+WIP}y2PlS7 zOMe@GhgaN?CBc+IlW*gv#1ZA8b6z%(fw_43kKivLYoh2pLnO=ZsX=T940`x+wyGtFQDOz5H6K)4tD;5`dv8T;ZP9_&3TijCYR}kF)C#rt zY8x?XOYr9TAKnl5eZE}hckXlj&NC7WPYobgZn#$Ac&C-O%uiO?b;X|ZpY=?#*GzB!8*E+wCy7Nzp%3T zXJn!>Q68R?5EM+!dE!aQ@ME*1v*EMhlbl`jI4X2U(bj%LA>&BpWYA-JQCDMe}BJC~H?-!Zq9u+oOu|_)9FrctAPACn%#MJlJl~{xFI0Ez` zugQ&^w4u6W?&D5 zW-i3Y(4eaI8{EO}hS=QnG(hL#Qb=_C_g|_#fGBdiMPL7GdHD)sX9+57-19VVzbLhK z&b_%!kfSk#z?TIC(hEa<*6BH_d=w23C6ffoW%_D@?5)MqbmtwY2UE4Cdfz{)+vOH- z2RDAr$XBq_V>=I2GRwJ8Tf+QwE6q^&sV1gkty!|m{~8>mnqrEM#RosM=={cxYFG>1 zZl?{um_BF?-#!!A(DhG(`Ad5|Ut}@lR}*A8sqyt48Xoq*5p{IC>kA%&!06#22%t*z5YN?ky_uhTOeg=d?TrCzdmtADow zbO~A0s!n|vUrPCXiBz6Wspm|NU+3UE8u?Ms$|VQuFymTWF&Zi$q0D&+nF3Dh#4xL| znoCNox0f4Go8Aqp5kpL_@gJ(M7NFBk_+=jU49XhdmFz{!rW}7T)$?Kz8Z0~;K@M)s zc_Q>X6B|3E4Vd!R(7QZYOVQBtIa9&maLTtMb=$&y?W3(Bce8VHjwUq>0Ph=H4>d2( zGjb0a)XoJ1ekz=P`q0K$eSLoQKN6kecgI#|^a_-uY&}A%Xk1d=yN~DzG1_)DgjQZzfJKQJgw!zws zjInaeqjFmCXck=Kz&y}k6O&AUhNlD|__3WIIFibFBU-Bi=T5Aq%tTHXF+l}fOtHvx zA*mFmmlD()aAEw@7vS&Vtn8mcEAZnkb^RMYRKRwjxy6d!sh?BVDqcJD@D%IT%sf}U zqyJeTTt2JTQbJxqp};=rf&CO-Fn&d-<2w9pnye1}OZPeCOOIVYB>-}E595CICTxE= zN5DVbEKcD77Ibxyk58s5{FeqB~pHdNs~FHJ#yKs8u=a>EAeJt~*f z`dAK`spSmU`i>J<8qEP!Y?L;?l$wjjkn&{;e3vFw?0(IN+j=6m2OO9Y*wI>@J92qr zF85)P0VUmjMN!gGM-VWaK4kDjma`(-a5Ef$`)1B`!!ub>bzltCSTN~A9$O^6d{M}B zc-6Nq(mcO!=bq5dN!h=D5;u1)BfE#&ztZG6U;0!P3sV{8iHcaZssyw?13f3nQf>b@ zdNUlh_dQ$!WX{4rotJM0$yf0c(8fOMt9N&7zcQMx&&mAf5L&H+R4sGM$G5~rf6VUNzme1GMcP^w6(?p~Pv@4AHFCd@n`{rJ_eF>%@b4g~3$h?&e3)?m_ zu&J62++9@N+}e8Cz7i3s4wjO-X`9sm`Oz9V$~+OnqkpeT>SkoIv!9ZHQVuJdAZ&d* zLssXmg$1H$40*awQGKQ8O@f-}?SLi57!7)V+o*zGw*nk!9TV`)WZ2WEui;e@higJ? zq}-z;f}=&{)aygcUaLSgsUOAY;arNu@t{4@BIA}?V9Y>S z$yu3QGA>PJ$=YMI_2^pL23>;VLghhVL_Hxabb|)jq*6~9xfb`G$=K1RFDB^7+< zt9D8et8jIjQC<4q50ZNtd)$b(?Cbl$5_~Xe=Ahsas6Fqgmfz7bk&q^KNJ*$UuM<$%gj zbt?`u`EGqy{5^>_V>=qiI~x$MbQ3=*n5}1g}?(xyaSCl%+cqp#-u6tkvh4w;SmDgmrp` zZrI%9H<1|pyLKM$hSXtCH8)qxOb@Z{0LgmsZ&EvQQ2?7>*Cb49 zdGUv+MP>waJP6Z?JtRj4!JMwaPY1_3Z@RN8JI+!7bwlLP+skq~GF1QK48r_|Y;W~WsQ-`pgl5rJzBAud7>WOQK(l?q%C5$`#2kEklT?%=kWFLn zPJ2w}HZ2hW7l|qyTA-BQPK%$$i$lj3xvH*Vy|X9Cv2DJZQ4y)+tuu1tkCa%MnWsC|;xwmrGRO5<3k zr;~1KCwnqrD4Xo_5VRSdaCw+=F)0-hJZKR8OLo!zintKi zFf#}sx3FN&-guFIZFIc)sKN{r_e*%1ZA`vZy{9g+8Rf=8ZK`GZsrWnT-OY@gE0BHH zFV*8`OJ|j(!`xC~tkXUvnZ>+6jw!z2aO=_6ig1Jnn+_$o{KsHBW!4=- zXg@^u(UW;Y;K*-b#K)Pd)1P~oLyBJhI_&Lhfh9Zj;4H2<=j1{ez9iaS&j?P$RKdOQ zn=5Bp`@x0@yrkGJXX-6K1oy}Rl0T}B(sx3T>1lU(_GnJ##%C7xvQM^89+W-iE2Uh$ z;$|i86QH_c%idT6H1>gh2RzT250A$`Mo$Vvr5-YbXPQF&PB_)%6{V%$4;YKtKpgp0 z<#!BOG_hSGlZCXEQ+NYILl0kumd>Xd?-PW8Pi)c{dEO|xr2Kn>jGCgJ2Tdw7DCqF+ zN&z3MsmOonXeW*9-<+iD+f1@$526$*!uBO9n{4OhYq39ReR^?e-~E%#o;m&r@2k#F zDYN!#JaHQ61xJr?m{L4YWmy=e&qgB_miRb~l|5Y~JYxG(!n0j=F?+Y>zc=k*E-6X4 z-+s`5ZSz84C)+KuHl`A-J0@I+-pv;)rl{1GIGf&-`;_v913Up6-d57uglgSeZ4PK4 z_%J3_U&N9SP-qx{&boPJ*!ID+orOdrHH3h@IT%p`N^!2&W75hxatzNP)qW?ECzwOv zW$+GSC7KD7fEvu-I#~a5Z{9EqCu(GpRcb8bXT=bxB!5D+)Q-GYJ!O`0{t>g#K)krJ z`?dEmF@huxxKypt-w$3{?d^}p{2jz-wpn(Ai7YQ_P1k~?Zz!LS}+@d|3G2((O2gRnk#NT*@);J?ZqYkdCI* z7@uXOSzc-K~td6K1>MO(lZ2$hMjPgu1nptc!$ND0}z zLt)Hsu=+FdhVle`p7EXQjIr?i|F78=y`lqhb#huXc@LBS=m6dOhFTSHo2dT*zhBOJ literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events/textures/other/tenders.png b/src/main/resources/contents/omc_daily_events/textures/other/tenders.png new file mode 100644 index 0000000000000000000000000000000000000000..11f68bbe75a3c36534c7752d618eb25c7371e992 GIT binary patch literal 497 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0ftFLK~y+Toszpw z0#Oi#|6Pn$nnfX~i5HAfIzvH7jHQK@FW?(!;RBdp;S*T+2qu;`CKMJ{7{!=?Hz)`J zVdWyQ&~Op!8MP-j}QO=~rb1WmN`6lG%r8JJ`XQ?kqjCzBVi6O{*Ej<^py~u`;R{q!2`JOE4A(S`zgKG(2IlOJWe>x4 zrvv3e5n4_~BKZcP>%E%;I-u&Z-e#CUsvM7}VILnwp z!)+5>(i(`q)ETCGKR#nPbSk{QEzX0xZeB_E5o2gWCQRxxAh6YJ!N0N1`@^FE#)2oD zlfHv}%4MU1LWmAW`=cZd0(*VGuB8Yhz=SD=h7HNDsRz6lvbeiG Date: Fri, 19 Jun 2026 13:31:42 +0200 Subject: [PATCH 52/74] fix: sub loot table rewards don't show their message --- .../listeners/PlayerFishListener.java | 31 ++++++++++++------- .../registry/loottable/loots/CustomLoot.java | 4 ++- .../registry/loottable/loots/ItemLoot.java | 16 ++++++++-- .../registry/loottable/loots/LootboxLoot.java | 6 +++- .../registry/loottable/loots/MethodLoot.java | 5 ++- .../registry/loottable/loots/MoneyLoot.java | 6 +++- .../registry/loottable/loots/TableLoot.java | 6 ++-- 7 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java index 05f17a8bd..bd3d449d0 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java @@ -24,6 +24,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerFishEvent; +import java.util.Collection; import java.util.List; public class PlayerFishListener implements Listener { @@ -42,7 +43,7 @@ public void onStartFishing(PlayerFishEvent event) { case FISHING -> { // * SFX // todo sfx - player.playSound(player.getLocation(), Sound.ENTITY_FISHING_BOBBER_SPLASH, 1f, 0.3f); + player.playSound(player.getLocation(), Sound.ENTITY_FISHING_BOBBER_SPLASH, 1f, 0.7f); } case CAUGHT_FISH -> { @@ -62,17 +63,25 @@ public void onStartFishing(PlayerFishEvent event) { Component.text(loots.size()).color(NamedTextColor.YELLOW) ), Prefix.MIRACULOUS_FISHING, MessageType.INFO, false); - for (CustomLoot loot : loots) { - if (loot.getDisplayText() != null) - player.sendMessage(Component.text(" - ", NamedTextColor.GRAY) - .append(loot.getDisplayText())); - MiraculousFishingManager.simulateLaunchLoot(player, hook.getLocation(), loot); - - if (loot instanceof MoneyLoot || loot instanceof MethodLoot || loot instanceof TableLoot) { - loot.run(player); - } - } + sendMessagesLoot(player, hook, loots); } } } + + private void sendMessagesLoot(Player player, FishHook hook, Collection loots) { + for (CustomLoot loot : loots) { + if (loot.getDisplayText() != null) + player.sendMessage(Component.text(" - ", NamedTextColor.GRAY) + .append(loot.getDisplayText())); + MiraculousFishingManager.simulateLaunchLoot(player, hook.getLocation(), loot); + + // * Si y'a des sous loots, alors on affiche les sous loots obtenu + if (loot instanceof TableLoot) + sendMessagesLoot(player, hook, loot.run(player)); + // * Si c'est un loot de type MoneyLoot ou MethodLoot, + // on exécute le loot, car on ne le donne va via un item + else if (loot instanceof MoneyLoot || loot instanceof MethodLoot) + loot.run(player); + } + } } diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java index d0a8b07c2..4895fd3b8 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java @@ -3,8 +3,10 @@ import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; +import java.util.Set; + public interface CustomLoot { Component getDisplayText(); double getChance(); - void run(Player receiver); + Set run(Player receiver); } \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java index aff111a85..2de2bddf7 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java @@ -17,6 +17,7 @@ public class ItemLoot implements CustomLoot { private final ItemStack displayedItem; private final int minAmount; private final int maxAmount; + private final int amount; public ItemLoot(Set items, ItemStack displayedItem, double chance, int minAmount, int maxAmount) { this.chance = chance; @@ -24,6 +25,7 @@ public ItemLoot(Set items, ItemStack displayedItem, double chance, in this.displayedItem = displayedItem; this.minAmount = minAmount; this.maxAmount = maxAmount; + this.amount = getRandomAmount(); } public ItemLoot(ItemStack item, double chance, int minAmount, int maxAmount) { @@ -95,7 +97,15 @@ public ItemStack getFirstLoot() { if (items.size() == 1) { return items.iterator().next(); } - return items.stream().findFirst().orElse(null); + + ItemStack item = items.stream().findFirst().orElse(null); + + if (item != null) { + item.setAmount(this.getRandomAmount()); + return item; + } + + return null; } public int getRandomAmount() { @@ -104,16 +114,16 @@ public int getRandomAmount() { @Override public Component getDisplayText() { - System.out.println(getFirstLoot()); return getFirstLoot().displayName(); } @Override - public void run(Player receiver) { + public Set run(Player receiver) { for (ItemStack lootItem : this.getItems()) { ItemStack item = lootItem.clone(); item.setAmount(this.getRandomAmount()); receiver.getInventory().addItem(item); } + return Collections.singleton(this); } } \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java index 8189edaa6..343c5f23b 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java @@ -5,6 +5,9 @@ import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; +import java.util.Collections; +import java.util.Set; + @Getter public class LootboxLoot implements CustomLoot { private final double chance; @@ -21,7 +24,8 @@ public Component getDisplayText() { } @Override - public void run(Player receiver) { + public Set run(Player receiver) { lootbox.open(receiver); + return Collections.singleton(this); } } \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java index 93f1e6efd..46a3c7b56 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java @@ -4,6 +4,8 @@ import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; +import java.util.Collections; +import java.util.Set; import java.util.function.Consumer; @Getter @@ -24,7 +26,8 @@ public Component getDisplayText() { } @Override - public void run(Player receiver) { + public Set run(Player receiver) { receiverAction.accept(receiver); + return Collections.singleton(this); } } diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java index 4f15df698..b3349dd95 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java @@ -6,6 +6,9 @@ import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; +import java.util.Collections; +import java.util.Set; + public record MoneyLoot(int money, double getChance) implements CustomLoot { public MoneyLoot(int minMoney, int maxMoney, double chance) { @@ -20,7 +23,8 @@ public Component getDisplayText() { } @Override - public void run(Player receiver) { + public Set run(Player receiver) { EconomyManager.addBalance(receiver.getUniqueId(), money); + return Collections.singleton(this); } } diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java index 7bb2ad4e4..19a67d40e 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java @@ -5,6 +5,8 @@ import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; +import java.util.Set; + @Getter public class TableLoot implements CustomLoot { private final double chance; @@ -21,7 +23,7 @@ public Component getDisplayText() { } @Override - public void run(Player receiver) { - lootTable.rollLoots(receiver); + public Set run(Player receiver) { + return Set.copyOf(lootTable.rollLoots(receiver)); } } \ No newline at end of file From 995cc39815f29b0ae41b8fb8cc43fc058cbc35c5 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Fri, 19 Jun 2026 13:34:42 +0200 Subject: [PATCH 53/74] fix: coin pickup --- .../listeners/PlayerNotPickUpListener.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerNotPickUpListener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerNotPickUpListener.java index e026f2c16..347202455 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerNotPickUpListener.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerNotPickUpListener.java @@ -10,9 +10,9 @@ public class PlayerNotPickUpListener implements Listener { @EventHandler public void onPickUp(EntityPickupItemEvent event) { if (!(event.getEntity() instanceof Player)) return; - if (event.getItem().getItemStack().getPersistentDataContainer().has(MiraculousFishingManager.NOT_PICKUP_KEY)) { - event.getItem().remove(); - } + if (!event.getItem().getItemStack().getPersistentDataContainer().has(MiraculousFishingManager.NOT_PICKUP_KEY)) return; + event.getItem().remove(); + event.setCancelled(true); } } From 38504ede2b31cdf8675105c1b795a9caf10f2ea2 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Fri, 19 Jun 2026 14:02:06 +0200 Subject: [PATCH 54/74] change: enchance item display for a loot + add coin item --- .../MiraculousFishingManager.java | 32 ++++++++----------- .../lootboxes/EpicFishingTreasureLootbox.java | 1 + .../lootboxes/FishingFurnitureLootbox.java | 1 + .../LegendaryFishingTreasureLootbox.java | 1 + .../lootboxes/RareFishingTreasureLootbox.java | 1 + .../listeners/PlayerFishListener.java | 6 ++-- .../registry/items/CustomItemRegistry.java | 3 ++ .../registry/lootboxes/CustomLootbox.java | 9 ++++++ .../registry/loottable/loots/ItemLoot.java | 7 +++- .../registry/loottable/loots/LootboxLoot.java | 8 ++++- .../registry/loottable/loots/MethodLoot.java | 7 ++-- .../registry/loottable/loots/MoneyLoot.java | 9 +++++- .../loottable/loots/RepresentedItem.java | 7 ++++ .../contents/omc_daily_events/head.yml | 10 ++++++ .../omc_daily_events/nbt/head/coin.json | 12 +++++++ 15 files changed, 88 insertions(+), 26 deletions(-) create mode 100644 src/main/java/fr/openmc/core/registry/loottable/loots/RepresentedItem.java create mode 100644 src/main/resources/contents/omc_daily_events/head.yml create mode 100644 src/main/resources/contents/omc_daily_events/nbt/head/coin.json diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java index b212e3116..b57c7f1a9 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java @@ -1,8 +1,10 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing; import fr.openmc.core.OMCPlugin; -import fr.openmc.core.registry.loottable.loots.*; -import fr.openmc.core.utils.bukkit.SkullUtils; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.MoneyLoot; +import fr.openmc.core.registry.loottable.loots.RepresentedItem; +import fr.openmc.core.registry.loottable.loots.TableLoot; import org.bukkit.Location; import org.bukkit.NamespacedKey; import org.bukkit.entity.FishHook; @@ -57,24 +59,18 @@ public static void simulateLaunchLoot(Player player, Location hookLocation, Cust * @return un item stack en fonction du loot */ private static ItemStack getLaunchedItem(CustomLoot loot) { - if (loot instanceof ItemLoot itemLoot) { - ItemStack item = itemLoot.getItems().iterator().next(); - item.setAmount(itemLoot.getRandomAmount()); - return item; - } else if (loot instanceof MoneyLoot) { - ItemStack base = SkullUtils.getCustomHead( - "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWFmMGQ4ZDc5NGEzYTRhNWUyMGE1MjkyZWQyNTUxMzRmNzZkNGYzYTU1NTZmYzdmNDI2ZDI3YjI0NzQ3NGQ2NyJ9fX0=", - "§6§lAywenito"); - if (base != null) - base.editPersistentDataContainer(c -> - c.set(NOT_PICKUP_KEY, PersistentDataType.BOOLEAN, true)); - return base; - } else if (loot instanceof LootboxLoot lootboxLoot - && lootboxLoot.getLootbox().getItemDisplayed() != null) { - return lootboxLoot.getLootbox().getItemDisplayed(); - } else if (loot instanceof TableLoot tableLoot) { + // * SI c'est un loot provenant d'une sous loot table, on roll puis on le renvoie + if (loot instanceof TableLoot tableLoot) { List loots = tableLoot.getLootTable().rollLoots(null, false); return getLaunchedItem(loots.getFirst()); + // * Si c'est une loot qui peut être représenter par un item + } else if (loot instanceof RepresentedItem itemDisplayed) { + ItemStack item = itemDisplayed.getRepresentativeItem(); + // * et que si c'est une item, qui ne doit pas etre donné (ex Money) + if (loot instanceof MoneyLoot) + item.editPersistentDataContainer(c -> + c.set(NOT_PICKUP_KEY, PersistentDataType.BOOLEAN, true)); + else return item; } return null; diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/EpicFishingTreasureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/EpicFishingTreasureLootbox.java index e955ed240..32ff97f43 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/EpicFishingTreasureLootbox.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/EpicFishingTreasureLootbox.java @@ -11,6 +11,7 @@ public class EpicFishingTreasureLootbox extends CustomLootbox { public EpicFishingTreasureLootbox() { super( + OMCRegistry.CUSTOM_ITEMS.EPIC_FISHING_TREASURE, "omc_daily_events:epic_fishing_treasure", TranslationManager.translation("feature.dailyevents.miraculousfishing.lootbox.epic_fishing_treasure.name"), OMCRegistry.CUSTOM_LOOT_TABLES.EPIC_FISHING_TREASURE, diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/FishingFurnitureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/FishingFurnitureLootbox.java index 79e228298..2f5e24228 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/FishingFurnitureLootbox.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/FishingFurnitureLootbox.java @@ -11,6 +11,7 @@ public class FishingFurnitureLootbox extends CustomLootbox { public FishingFurnitureLootbox() { super( + OMCRegistry.CUSTOM_ITEMS.FISHING_FURNITURE_BOX, "omc_daily_events:fishing_furniture", TranslationManager.translation("feature.dailyevents.miraculousfishing.lootbox.fishing_furniture.name"), OMCRegistry.CUSTOM_LOOT_TABLES.FISHING_FURNITURE, diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/LegendaryFishingTreasureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/LegendaryFishingTreasureLootbox.java index 741b97d20..494d54489 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/LegendaryFishingTreasureLootbox.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/LegendaryFishingTreasureLootbox.java @@ -11,6 +11,7 @@ public class LegendaryFishingTreasureLootbox extends CustomLootbox { public LegendaryFishingTreasureLootbox() { super( + OMCRegistry.CUSTOM_ITEMS.LEGENDARY_FISHING_TREASURE, "omc_daily_events:legendary_fishing_treasure", TranslationManager.translation("feature.dailyevents.miraculousfishing.lootbox.legendary_fishing_treasure.name"), OMCRegistry.CUSTOM_LOOT_TABLES.LEGENDARY_FISHING_TREASURE, diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/RareFishingTreasureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/RareFishingTreasureLootbox.java index bd206b6c2..5c4e573ab 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/RareFishingTreasureLootbox.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/lootboxes/RareFishingTreasureLootbox.java @@ -11,6 +11,7 @@ public class RareFishingTreasureLootbox extends CustomLootbox { public RareFishingTreasureLootbox() { super( + OMCRegistry.CUSTOM_ITEMS.RARE_FISHING_TREASURE, "omc_daily_events:rare_fishing_treasure", TranslationManager.translation("feature.dailyevents.miraculousfishing.lootbox.rare_fishing_treasure.name"), OMCRegistry.CUSTOM_LOOT_TABLES.RARE_FISHING_TREASURE, diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java index bd3d449d0..3a7440cc2 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java @@ -63,12 +63,12 @@ public void onStartFishing(PlayerFishEvent event) { Component.text(loots.size()).color(NamedTextColor.YELLOW) ), Prefix.MIRACULOUS_FISHING, MessageType.INFO, false); - sendMessagesLoot(player, hook, loots); + sendLoot(player, hook, loots); } } } - private void sendMessagesLoot(Player player, FishHook hook, Collection loots) { + private void sendLoot(Player player, FishHook hook, Collection loots) { for (CustomLoot loot : loots) { if (loot.getDisplayText() != null) player.sendMessage(Component.text(" - ", NamedTextColor.GRAY) @@ -77,7 +77,7 @@ private void sendMessagesLoot(Player player, FishHook hook, Collection implements public final CustomItem LEGENDARY_FISHING_TREASURE = register("omc_daily_events:legendary_fishing_treasure_lootbox", Material.GLASS); public final CustomItem FISHING_FURNITURE_BOX = register("omc_daily_events:fishing_furniture_lootbox", Material.GLASS); + public final CustomItem COIN = register("omc_daily_events:coin", Material.GOLD_INGOT); + + @Override public void postInit() { CommandsManager.getHandler().register(new CustomItemsDebugCommand()); diff --git a/src/main/java/fr/openmc/core/registry/lootboxes/CustomLootbox.java b/src/main/java/fr/openmc/core/registry/lootboxes/CustomLootbox.java index 1fae53a2c..87c069825 100644 --- a/src/main/java/fr/openmc/core/registry/lootboxes/CustomLootbox.java +++ b/src/main/java/fr/openmc/core/registry/lootboxes/CustomLootbox.java @@ -1,6 +1,7 @@ package fr.openmc.core.registry.lootboxes; import fr.openmc.api.menulib.utils.InventorySize; +import fr.openmc.core.registry.items.CustomItem; import fr.openmc.core.registry.loottable.CustomLootTable; import lombok.Getter; import net.kyori.adventure.text.Component; @@ -36,6 +37,14 @@ public CustomLootbox(String namespace, Component name, CustomLootTable lootTable this.lootTable = lootTable; } + public CustomLootbox(CustomItem itemDisplayed, String namespace, Component name, CustomLootTable lootTable, LootboxOptions options) { + this.itemDisplayed = itemDisplayed.getBest(); + this.namespace = namespace; + this.name = name; + this.lootTable = lootTable; + this.options = options; + } + public CustomLootbox(ItemStack itemDisplayed, String namespace, Component name, CustomLootTable lootTable, LootboxOptions options) { this.itemDisplayed = itemDisplayed; this.namespace = namespace; diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java index 2de2bddf7..560cb7dcb 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java @@ -11,7 +11,7 @@ import java.util.Set; @Getter -public class ItemLoot implements CustomLoot { +public class ItemLoot implements CustomLoot, RepresentedItem { private final double chance; private final Set items; private final ItemStack displayedItem; @@ -126,4 +126,9 @@ public Set run(Player receiver) { } return Collections.singleton(this); } + + @Override + public ItemStack getRepresentativeItem() { + return getFirstLoot(); + } } \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java index 343c5f23b..c0fcb7969 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/LootboxLoot.java @@ -4,12 +4,13 @@ import lombok.Getter; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import java.util.Collections; import java.util.Set; @Getter -public class LootboxLoot implements CustomLoot { +public class LootboxLoot implements CustomLoot, RepresentedItem { private final double chance; private final CustomLootbox lootbox; @@ -28,4 +29,9 @@ public Set run(Player receiver) { lootbox.open(receiver); return Collections.singleton(this); } + + @Override + public ItemStack getRepresentativeItem() { + return lootbox.getItemDisplayed(); + } } \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java index 46a3c7b56..b81cb12b1 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/MethodLoot.java @@ -3,18 +3,21 @@ import lombok.Getter; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import java.util.Collections; import java.util.Set; import java.util.function.Consumer; @Getter -public class MethodLoot implements CustomLoot { +public class MethodLoot implements CustomLoot, RepresentedItem { + private final ItemStack representativeItem; private final Component text; private final double chance; private final Consumer receiverAction; - public MethodLoot(Component text, Consumer receiverAction, double chance) { + public MethodLoot(ItemStack representativeItem, Component text, Consumer receiverAction, double chance) { + this.representativeItem = representativeItem; this.text = text; this.chance = chance; this.receiverAction = receiverAction; diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java index b3349dd95..198c6d4cf 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/MoneyLoot.java @@ -1,16 +1,18 @@ package fr.openmc.core.registry.loottable.loots; +import fr.openmc.core.OMCRegistry; import fr.openmc.core.features.economy.EconomyManager; import fr.openmc.core.utils.RandomUtils; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import java.util.Collections; import java.util.Set; -public record MoneyLoot(int money, double getChance) implements CustomLoot { +public record MoneyLoot(int money, double getChance) implements CustomLoot, RepresentedItem { public MoneyLoot(int minMoney, int maxMoney, double chance) { this(RandomUtils.randomBetween(minMoney, maxMoney), chance); } @@ -27,4 +29,9 @@ public Set run(Player receiver) { EconomyManager.addBalance(receiver.getUniqueId(), money); return Collections.singleton(this); } + + @Override + public ItemStack getRepresentativeItem() { + return OMCRegistry.CUSTOM_ITEMS.COIN.getBest(); + } } diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/RepresentedItem.java b/src/main/java/fr/openmc/core/registry/loottable/loots/RepresentedItem.java new file mode 100644 index 000000000..25afaec98 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/RepresentedItem.java @@ -0,0 +1,7 @@ +package fr.openmc.core.registry.loottable.loots; + +import org.bukkit.inventory.ItemStack; + +public interface RepresentedItem { + ItemStack getRepresentativeItem(); +} diff --git a/src/main/resources/contents/omc_daily_events/head.yml b/src/main/resources/contents/omc_daily_events/head.yml new file mode 100644 index 000000000..1707c7468 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/head.yml @@ -0,0 +1,10 @@ +info: + namespace: omc_daily_events + +items: + coin: + display_name: "Aywenito" + resource: + generate: false + components_nbt_file: "nbt/head/coin.json" + material: PLAYER_HEAD \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/nbt/head/coin.json b/src/main/resources/contents/omc_daily_events/nbt/head/coin.json new file mode 100644 index 000000000..fa8187943 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/nbt/head/coin.json @@ -0,0 +1,12 @@ +{ + "components":{ + "minecraft:profile": { + "properties": [ + { + "name":"textures", + "value":"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmYwYTY3Njg0NjlhZDZlMGFiMDI0YzNhNTI1ZDQ4MWVhMDdmNTZhMjNkZTZhOTAyYmQ4ZDg4NzVmY2MwMTZjNSJ9fX0=" + } + ] + } + } +} \ No newline at end of file From d29345c5f462a94281ed91e3fd0992d354ae8120 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Fri, 19 Jun 2026 14:05:59 +0200 Subject: [PATCH 55/74] change: velocity of launched item (similar to minecraft code FishingHook ln 541) --- .../contents/miraculousfishing/MiraculousFishingManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java index b57c7f1a9..dddb89c97 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java @@ -50,6 +50,8 @@ public static void simulateLaunchLoot(Player player, Location hookLocation, Cust // * Revient à faire le vecteur vitesse entre 2 vecteur (xp - xh, yp - yh, zp - zh) Vector velocity = player.getEyeLocation().toVector().subtract(hookLocation.toVector()); velocity.multiply(0.1); + velocity.setY(velocity.getY() + Math.sqrt(Math.sqrt( + velocity.getX()*2 + velocity.getY()*2 + velocity.getZ()*2)) * 0.08); itemEntity.setVelocity(velocity); } From c7673f2f3bb677d49f812b06c5cefaa31dcd47e4 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Fri, 19 Jun 2026 14:23:48 +0200 Subject: [PATCH 56/74] branch change --- .../resources/contents/omc_daily_events/head.yml | 6 ++---- .../omc_daily_events/nbt/head/poiscaille.json | 12 ++++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 src/main/resources/contents/omc_daily_events/nbt/head/poiscaille.json diff --git a/src/main/resources/contents/omc_daily_events/head.yml b/src/main/resources/contents/omc_daily_events/head.yml index 1707c7468..a5c4f38ff 100644 --- a/src/main/resources/contents/omc_daily_events/head.yml +++ b/src/main/resources/contents/omc_daily_events/head.yml @@ -4,7 +4,5 @@ info: items: coin: display_name: "Aywenito" - resource: - generate: false - components_nbt_file: "nbt/head/coin.json" - material: PLAYER_HEAD \ No newline at end of file + components_nbt_file: "nbt/head/coin.json" + material: PLAYER_HEAD \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/nbt/head/poiscaille.json b/src/main/resources/contents/omc_daily_events/nbt/head/poiscaille.json new file mode 100644 index 000000000..fa8187943 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/nbt/head/poiscaille.json @@ -0,0 +1,12 @@ +{ + "components":{ + "minecraft:profile": { + "properties": [ + { + "name":"textures", + "value":"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmYwYTY3Njg0NjlhZDZlMGFiMDI0YzNhNTI1ZDQ4MWVhMDdmNTZhMjNkZTZhOTAyYmQ4ZDg4NzVmY2MwMTZjNSJ9fX0=" + } + ] + } + } +} \ No newline at end of file From d26244ffbd5d60c76f75b8e81f8aaa7853d69168 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Fri, 19 Jun 2026 17:02:44 +0200 Subject: [PATCH 57/74] feat: add sea creature head --- .../registry/items/CustomItemRegistry.java | 3 ++ .../contents/omc_daily_events/head.yml | 36 +++++++++++++++++++ .../omc_daily_events/nbt/head/coin.json | 8 ++--- .../omc_daily_events/nbt/head/kraken.json | 12 +++++++ .../omc_daily_events/nbt/head/leviathan.json | 12 +++++++ .../omc_daily_events/nbt/head/poiscaille.json | 12 ------- .../nbt/head/poisson_steve.json | 12 +++++++ 7 files changed, 79 insertions(+), 16 deletions(-) create mode 100644 src/main/resources/contents/omc_daily_events/nbt/head/kraken.json create mode 100644 src/main/resources/contents/omc_daily_events/nbt/head/leviathan.json delete mode 100644 src/main/resources/contents/omc_daily_events/nbt/head/poiscaille.json create mode 100644 src/main/resources/contents/omc_daily_events/nbt/head/poisson_steve.json diff --git a/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java b/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java index 5ab1f5c42..c366b1386 100644 --- a/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java +++ b/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java @@ -120,6 +120,9 @@ public class CustomItemRegistry extends Registry implements public final CustomItem FISHING_FURNITURE_BOX = register("omc_daily_events:fishing_furniture_lootbox", Material.GLASS); public final CustomItem COIN = register("omc_daily_events:coin", Material.GOLD_INGOT); + public final CustomItem POISSON_STEVE_HEAD = register("omc_daily_events:poisson_steve_head", Material.PLAYER_HEAD); + public final CustomItem KRAKEN_HEAD = register("omc_daily_events:kraken_head", Material.PLAYER_HEAD); + public final CustomItem LEVIATHAN_HEAD = register("omc_daily_events:leviathan_head", Material.PLAYER_HEAD); @Override diff --git a/src/main/resources/contents/omc_daily_events/head.yml b/src/main/resources/contents/omc_daily_events/head.yml index a5c4f38ff..53b204b82 100644 --- a/src/main/resources/contents/omc_daily_events/head.yml +++ b/src/main/resources/contents/omc_daily_events/head.yml @@ -5,4 +5,40 @@ items: coin: display_name: "Aywenito" components_nbt_file: "nbt/head/coin.json" + material: PLAYER_HEAD + + poisson_steve_head: + display_name: "Tete du Poisson Steve" + lore: + - "§7§oSteve, le (Poi-)" + - "§7§oLe poisson Steve" + - "§7§o(Poisson Steve)" + - "§7§oIl est orange (ooh-ooh)" + - "§7§oIl a des bras" + - "§7§oEt des jambes" + - "§7§oLe poisson Steve" + - "§7§oPa-la-la, pa-la-la" + - "§7§oLa-la, la-la, la-la-la" + - "§7§oLa-la, la-la, la-la-la" + - "§7§oLa-la, la-la, la-la, la-la" + - "§7§oPa-la-la, pa-la-la" + - "§7§oLe poisson Steve (Poi-)" + - "§7§oIl est vraiment très beau" + - "§7§o(Poisson Steve)" + - "§7§oIl peut nager sur la Terre (ooh-ah, ooh-ah)" + - "§7§oIl peut marcher dans l'eau" + - "§7§oLe poisson Steve" + - "§7§oIl sent forcément mauvais" + - "§7§oMais on l'aime bien" + components_nbt_file: "nbt/head/poisson_steve.json" + material: PLAYER_HEAD + + kraken_head: + display_name: "Tete de Kraken" + components_nbt_file: "nbt/head/kraken.json" + material: PLAYER_HEAD + + leviathan_head: + display_name: "Tete de Léviathan" + components_nbt_file: "nbt/head/leviathan.json" material: PLAYER_HEAD \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/nbt/head/coin.json b/src/main/resources/contents/omc_daily_events/nbt/head/coin.json index fa8187943..d871b2f44 100644 --- a/src/main/resources/contents/omc_daily_events/nbt/head/coin.json +++ b/src/main/resources/contents/omc_daily_events/nbt/head/coin.json @@ -1,10 +1,10 @@ { - "components":{ - "minecraft:profile": { + "components": { + "profile": { "properties": [ { - "name":"textures", - "value":"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmYwYTY3Njg0NjlhZDZlMGFiMDI0YzNhNTI1ZDQ4MWVhMDdmNTZhMjNkZTZhOTAyYmQ4ZDg4NzVmY2MwMTZjNSJ9fX0=" + "name": "textures", + "value": "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODE2MjBkYzcxYTMwMjBjOGVmMmJiOTNkZTIxMzhkOTExZTEyMmJjYTczZGQxZjdkNDYxYTY0NjU1YTBmNjFiOCJ9fX0=" } ] } diff --git a/src/main/resources/contents/omc_daily_events/nbt/head/kraken.json b/src/main/resources/contents/omc_daily_events/nbt/head/kraken.json new file mode 100644 index 000000000..d611a0042 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/nbt/head/kraken.json @@ -0,0 +1,12 @@ +{ + "components": { + "profile": { + "properties": [ + { + "name": "textures", + "value": "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTllZTIxNjE4NWM1NmUyOTFjOGVkZjQ3NTdiMWI3NTc3ZGY1ZjNmZDRiZmQzYTBjNzYwODRjODFkMjcwIn19fQ==" + } + ] + } + } +} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/nbt/head/leviathan.json b/src/main/resources/contents/omc_daily_events/nbt/head/leviathan.json new file mode 100644 index 000000000..6f3c56dbb --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/nbt/head/leviathan.json @@ -0,0 +1,12 @@ +{ + "components": { + "profile": { + "properties": [ + { + "name": "textures", + "value": "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDBjZDA2ODI5NDZhNThlYTA1ZDEwODdjYzczMGY1ZmVlNzIzNDQzZDJlOWQxOWRmNGM3OTFmYjUxOTBmNTJmYSJ9fX0=" + } + ] + } + } +} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/nbt/head/poiscaille.json b/src/main/resources/contents/omc_daily_events/nbt/head/poiscaille.json deleted file mode 100644 index fa8187943..000000000 --- a/src/main/resources/contents/omc_daily_events/nbt/head/poiscaille.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "components":{ - "minecraft:profile": { - "properties": [ - { - "name":"textures", - "value":"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmYwYTY3Njg0NjlhZDZlMGFiMDI0YzNhNTI1ZDQ4MWVhMDdmNTZhMjNkZTZhOTAyYmQ4ZDg4NzVmY2MwMTZjNSJ9fX0=" - } - ] - } - } -} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/nbt/head/poisson_steve.json b/src/main/resources/contents/omc_daily_events/nbt/head/poisson_steve.json new file mode 100644 index 000000000..962729fbe --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/nbt/head/poisson_steve.json @@ -0,0 +1,12 @@ +{ + "components": { + "profile": { + "properties": [ + { + "name": "textures", + "value": "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMmNkNWYwYTVkOGViMTdmZmYyYTc5MzA0MmJlNDIyYWNiYmFmNGI4OWIwODFhMzgzMTcxOGJjMGU5Yzc1YWJjOCJ9fX0=" + } + ] + } + } +} \ No newline at end of file From 878284c7ff52b36f2d7337e8db357d01d0641ff8 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Fri, 19 Jun 2026 17:23:58 +0200 Subject: [PATCH 58/74] feat: add openable lootbox item --- .../items/EpicFishingTreasureLootbox.java | 27 +++++++++++++++++++ .../items/FishingFurnitureLootbox.java | 27 +++++++++++++++++++ .../LegendaryFishingTreasureLootbox.java | 27 +++++++++++++++++++ .../items/RareFishingTreasureLootbox.java | 27 +++++++++++++++++++ .../registry/items/CustomItemRegistry.java | 12 ++++++--- 5 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/EpicFishingTreasureLootbox.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/FishingFurnitureLootbox.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/LegendaryFishingTreasureLootbox.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/RareFishingTreasureLootbox.java diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/EpicFishingTreasureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/EpicFishingTreasureLootbox.java new file mode 100644 index 000000000..1e6200570 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/EpicFishingTreasureLootbox.java @@ -0,0 +1,27 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.items; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.items.CustomItem; +import fr.openmc.core.registry.items.options.UsableItem; +import fr.openmc.core.utils.bukkit.ItemUtils; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +public class EpicFishingTreasureLootbox extends CustomItem implements UsableItem { + public EpicFishingTreasureLootbox(String id) { + super(id); + } + + @Override + public ItemStack getVanilla() { + return new ItemStack(Material.GLASS); + } + + @Override + public void onRightClick(Player player, PlayerInteractEvent event) { + ItemUtils.removeItemsFromInventory(player, this.getBest(), 1); + OMCRegistry.CUSTOM_LOOTBOXES.EPIC_FISHING_TREASURE.open(player); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/FishingFurnitureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/FishingFurnitureLootbox.java new file mode 100644 index 000000000..3f3900a78 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/FishingFurnitureLootbox.java @@ -0,0 +1,27 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.items; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.items.CustomItem; +import fr.openmc.core.registry.items.options.UsableItem; +import fr.openmc.core.utils.bukkit.ItemUtils; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +public class FishingFurnitureLootbox extends CustomItem implements UsableItem { + public FishingFurnitureLootbox(String id) { + super(id); + } + + @Override + public ItemStack getVanilla() { + return new ItemStack(Material.GLASS); + } + + @Override + public void onRightClick(Player player, PlayerInteractEvent event) { + ItemUtils.removeItemsFromInventory(player, this.getBest(), 1); + OMCRegistry.CUSTOM_LOOTBOXES.FISHING_FURNITURE.open(player); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/LegendaryFishingTreasureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/LegendaryFishingTreasureLootbox.java new file mode 100644 index 000000000..b4046c573 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/LegendaryFishingTreasureLootbox.java @@ -0,0 +1,27 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.items; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.items.CustomItem; +import fr.openmc.core.registry.items.options.UsableItem; +import fr.openmc.core.utils.bukkit.ItemUtils; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +public class LegendaryFishingTreasureLootbox extends CustomItem implements UsableItem { + public LegendaryFishingTreasureLootbox(String id) { + super(id); + } + + @Override + public ItemStack getVanilla() { + return new ItemStack(Material.GLASS); + } + + @Override + public void onRightClick(Player player, PlayerInteractEvent event) { + ItemUtils.removeItemsFromInventory(player, this.getBest(), 1); + OMCRegistry.CUSTOM_LOOTBOXES.LEGENDARY_FISHING_TREASURE.open(player); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/RareFishingTreasureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/RareFishingTreasureLootbox.java new file mode 100644 index 000000000..e85fcf94b --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/RareFishingTreasureLootbox.java @@ -0,0 +1,27 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.items; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.items.CustomItem; +import fr.openmc.core.registry.items.options.UsableItem; +import fr.openmc.core.utils.bukkit.ItemUtils; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +public class RareFishingTreasureLootbox extends CustomItem implements UsableItem { + public RareFishingTreasureLootbox(String id) { + super(id); + } + + @Override + public ItemStack getVanilla() { + return new ItemStack(Material.GLASS); + } + + @Override + public void onRightClick(Player player, PlayerInteractEvent event) { + ItemUtils.removeItemsFromInventory(player, this.getBest(), 1); + OMCRegistry.CUSTOM_LOOTBOXES.RARE_FISHING_TREASURE.open(player); + } +} diff --git a/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java b/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java index c366b1386..f96d58213 100644 --- a/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java +++ b/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java @@ -4,6 +4,10 @@ import fr.openmc.core.CommandsManager; import fr.openmc.core.bootstrap.registries.KeyedRegistry; import fr.openmc.core.bootstrap.registries.Registry; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.items.EpicFishingTreasureLootbox; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.items.FishingFurnitureLootbox; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.items.LegendaryFishingTreasureLootbox; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.items.RareFishingTreasureLootbox; import fr.openmc.core.hooks.itemsadder.ItemsAdderHook; import fr.openmc.core.registry.items.contents.AywenCap; import fr.openmc.core.registry.items.contents.Hammer; @@ -114,10 +118,10 @@ public class CustomItemRegistry extends Registry implements public final CustomItem FISHERMAN_STAND = register("omc_daily_events:fisherman_stand", Material.PAPER); public final CustomItem FISHERMAN_TABLE = register("omc_daily_events:fisherman_table", Material.PAPER); - public final CustomItem RARE_FISHING_TREASURE = register("omc_daily_events:rare_fishing_treasure_lootbox", Material.GLASS); - public final CustomItem EPIC_FISHING_TREASURE = register("omc_daily_events:epic_fishing_treasure_lootbox", Material.GLASS); - public final CustomItem LEGENDARY_FISHING_TREASURE = register("omc_daily_events:legendary_fishing_treasure_lootbox", Material.GLASS); - public final CustomItem FISHING_FURNITURE_BOX = register("omc_daily_events:fishing_furniture_lootbox", Material.GLASS); + public final CustomItem RARE_FISHING_TREASURE = register(new RareFishingTreasureLootbox("omc_daily_events:rare_fishing_treasure_lootbox")); + public final CustomItem EPIC_FISHING_TREASURE = register(new EpicFishingTreasureLootbox("omc_daily_events:epic_fishing_treasure_lootbox")); + public final CustomItem LEGENDARY_FISHING_TREASURE = register(new LegendaryFishingTreasureLootbox("omc_daily_events:legendary_fishing_treasure_lootbox")); + public final CustomItem FISHING_FURNITURE_BOX = register(new FishingFurnitureLootbox("omc_daily_events:fishing_furniture_lootbox")); public final CustomItem COIN = register("omc_daily_events:coin", Material.GOLD_INGOT); public final CustomItem POISSON_STEVE_HEAD = register("omc_daily_events:poisson_steve_head", Material.PLAYER_HEAD); From 2fc86d680079fad08759767608c184e0f095eda0 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 10:42:38 +0200 Subject: [PATCH 59/74] feat: lootbox openable while block palce + fix: lootbox menu --- .../java/fr/openmc/core/ListenersManager.java | 1 + .../items/EpicFishingTreasureLootbox.java | 9 +-- .../items/FishingFurnitureLootbox.java | 9 +-- .../LegendaryFishingTreasureLootbox.java | 9 +-- .../items/RareFishingTreasureLootbox.java | 9 +-- .../core/listeners/BlockPlaceListener.java | 52 ++++++++++++++ .../registry/items/options/UsableBlock.java | 12 ++++ .../registry/lootboxes/LootboxOpenMenu.java | 69 ++++++++----------- .../registry/loottable/loots/CustomLoot.java | 8 +++ 9 files changed, 121 insertions(+), 57 deletions(-) create mode 100644 src/main/java/fr/openmc/core/listeners/BlockPlaceListener.java create mode 100644 src/main/java/fr/openmc/core/registry/items/options/UsableBlock.java diff --git a/src/main/java/fr/openmc/core/ListenersManager.java b/src/main/java/fr/openmc/core/ListenersManager.java index 3e6547eb0..2705944c2 100644 --- a/src/main/java/fr/openmc/core/ListenersManager.java +++ b/src/main/java/fr/openmc/core/ListenersManager.java @@ -33,6 +33,7 @@ public static void init() { new PlayerDeathListener(), new AsyncChatListener(OMCPlugin.getInstance()), new InteractListener(), + new BlockPlaceListener(), new EquipableItemListener(), new NoMoreRabbit(), new ArmorListener(), diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/EpicFishingTreasureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/EpicFishingTreasureLootbox.java index 1e6200570..456c3a6d1 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/EpicFishingTreasureLootbox.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/EpicFishingTreasureLootbox.java @@ -1,15 +1,15 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.items; +import dev.lone.itemsadder.api.Events.FurniturePrePlaceEvent; import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.items.CustomItem; -import fr.openmc.core.registry.items.options.UsableItem; +import fr.openmc.core.registry.items.options.UsableBlock; import fr.openmc.core.utils.bukkit.ItemUtils; import org.bukkit.Material; import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; -public class EpicFishingTreasureLootbox extends CustomItem implements UsableItem { +public class EpicFishingTreasureLootbox extends CustomItem implements UsableBlock { public EpicFishingTreasureLootbox(String id) { super(id); } @@ -20,7 +20,8 @@ public ItemStack getVanilla() { } @Override - public void onRightClick(Player player, PlayerInteractEvent event) { + public void onFurniturePlace(Player player, FurniturePrePlaceEvent event) { + event.setCancelled(true); ItemUtils.removeItemsFromInventory(player, this.getBest(), 1); OMCRegistry.CUSTOM_LOOTBOXES.EPIC_FISHING_TREASURE.open(player); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/FishingFurnitureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/FishingFurnitureLootbox.java index 3f3900a78..173bb3c60 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/FishingFurnitureLootbox.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/FishingFurnitureLootbox.java @@ -1,15 +1,15 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.items; +import dev.lone.itemsadder.api.Events.FurniturePrePlaceEvent; import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.items.CustomItem; -import fr.openmc.core.registry.items.options.UsableItem; +import fr.openmc.core.registry.items.options.UsableBlock; import fr.openmc.core.utils.bukkit.ItemUtils; import org.bukkit.Material; import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; -public class FishingFurnitureLootbox extends CustomItem implements UsableItem { +public class FishingFurnitureLootbox extends CustomItem implements UsableBlock { public FishingFurnitureLootbox(String id) { super(id); } @@ -20,7 +20,8 @@ public ItemStack getVanilla() { } @Override - public void onRightClick(Player player, PlayerInteractEvent event) { + public void onFurniturePlace(Player player, FurniturePrePlaceEvent event) { + event.setCancelled(true); ItemUtils.removeItemsFromInventory(player, this.getBest(), 1); OMCRegistry.CUSTOM_LOOTBOXES.FISHING_FURNITURE.open(player); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/LegendaryFishingTreasureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/LegendaryFishingTreasureLootbox.java index b4046c573..aa3678878 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/LegendaryFishingTreasureLootbox.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/LegendaryFishingTreasureLootbox.java @@ -1,15 +1,15 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.items; +import dev.lone.itemsadder.api.Events.FurniturePrePlaceEvent; import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.items.CustomItem; -import fr.openmc.core.registry.items.options.UsableItem; +import fr.openmc.core.registry.items.options.UsableBlock; import fr.openmc.core.utils.bukkit.ItemUtils; import org.bukkit.Material; import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; -public class LegendaryFishingTreasureLootbox extends CustomItem implements UsableItem { +public class LegendaryFishingTreasureLootbox extends CustomItem implements UsableBlock { public LegendaryFishingTreasureLootbox(String id) { super(id); } @@ -20,7 +20,8 @@ public ItemStack getVanilla() { } @Override - public void onRightClick(Player player, PlayerInteractEvent event) { + public void onFurniturePlace(Player player, FurniturePrePlaceEvent event) { + event.setCancelled(true); ItemUtils.removeItemsFromInventory(player, this.getBest(), 1); OMCRegistry.CUSTOM_LOOTBOXES.LEGENDARY_FISHING_TREASURE.open(player); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/RareFishingTreasureLootbox.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/RareFishingTreasureLootbox.java index e85fcf94b..f95e58f71 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/RareFishingTreasureLootbox.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/items/RareFishingTreasureLootbox.java @@ -1,15 +1,15 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.items; +import dev.lone.itemsadder.api.Events.FurniturePrePlaceEvent; import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.items.CustomItem; -import fr.openmc.core.registry.items.options.UsableItem; +import fr.openmc.core.registry.items.options.UsableBlock; import fr.openmc.core.utils.bukkit.ItemUtils; import org.bukkit.Material; import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; -public class RareFishingTreasureLootbox extends CustomItem implements UsableItem { +public class RareFishingTreasureLootbox extends CustomItem implements UsableBlock { public RareFishingTreasureLootbox(String id) { super(id); } @@ -20,7 +20,8 @@ public ItemStack getVanilla() { } @Override - public void onRightClick(Player player, PlayerInteractEvent event) { + public void onFurniturePlace(Player player, FurniturePrePlaceEvent event) { + event.setCancelled(true); ItemUtils.removeItemsFromInventory(player, this.getBest(), 1); OMCRegistry.CUSTOM_LOOTBOXES.RARE_FISHING_TREASURE.open(player); } diff --git a/src/main/java/fr/openmc/core/listeners/BlockPlaceListener.java b/src/main/java/fr/openmc/core/listeners/BlockPlaceListener.java new file mode 100644 index 000000000..1bf9760b2 --- /dev/null +++ b/src/main/java/fr/openmc/core/listeners/BlockPlaceListener.java @@ -0,0 +1,52 @@ +package fr.openmc.core.listeners; + +import dev.lone.itemsadder.api.Events.CustomBlockPlaceEvent; +import dev.lone.itemsadder.api.Events.FurniturePrePlaceEvent; +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.items.CustomItem; +import fr.openmc.core.registry.items.options.UsableBlock; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockPlaceEvent; + +import java.util.Optional; + +public class BlockPlaceListener implements Listener { + @EventHandler(priority = EventPriority.LOWEST) + void onFurniturePlace(FurniturePrePlaceEvent event) { + Player player = event.getPlayer(); + + Optional item = OMCRegistry.CUSTOM_ITEMS.get(event.getNamespacedID()); + if (item.isEmpty()) return; + + if (item.get() instanceof UsableBlock usable) { + usable.onFurniturePlace(player, event); + } + } + + @EventHandler(priority = EventPriority.LOWEST) + void onCustomBlockPlace(CustomBlockPlaceEvent event) { + Player player = event.getPlayer(); + + Optional item = OMCRegistry.CUSTOM_ITEMS.get(event.getNamespacedID()); + if (item.isEmpty()) return; + if (item.get() instanceof UsableBlock usable) { + usable.onCustomBlockPlace(player, event); + } + } + + @EventHandler(priority = EventPriority.LOWEST) + void onBlockPlace(BlockPlaceEvent event) { + Player player = event.getPlayer(); + + Optional item = OMCRegistry.CUSTOM_ITEMS.get(event.getItemInHand()); + if (item.isEmpty()) return; + + if (item.get() instanceof UsableBlock usable) { + usable.onBlockPlace(player, event); + } + } + +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/items/options/UsableBlock.java b/src/main/java/fr/openmc/core/registry/items/options/UsableBlock.java new file mode 100644 index 000000000..9663c2cf9 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/items/options/UsableBlock.java @@ -0,0 +1,12 @@ +package fr.openmc.core.registry.items.options; + +import dev.lone.itemsadder.api.Events.CustomBlockPlaceEvent; +import dev.lone.itemsadder.api.Events.FurniturePrePlaceEvent; +import org.bukkit.entity.Player; +import org.bukkit.event.block.BlockPlaceEvent; + +public interface UsableBlock { + default void onFurniturePlace(Player player, FurniturePrePlaceEvent event) {} + default void onCustomBlockPlace(Player player, CustomBlockPlaceEvent event) {} + default void onBlockPlace(Player player, BlockPlaceEvent event) {} +} diff --git a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java index 0409cfe85..4d1a3b9c9 100644 --- a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java +++ b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java @@ -46,7 +46,7 @@ public class LootboxOpenMenu extends Menu { private final CustomLootbox box; private int itemOffset = 0; - private ItemLoot winningItem = null; + private CustomLoot winningLoot = null; private boolean finished = false; public LootboxOpenMenu(@NotNull Player owner, CustomLootbox box) { @@ -79,21 +79,24 @@ public String getTexture() { public @NotNull Map getContent() { Map items = fill(Material.GRAY_STAINED_GLASS_PANE); - if (!isAnimating && !finished) startAnimation(); - if (finished && winningItem != null) { - items.put(22, new ItemMenuBuilder(this, winningItem.getDisplayedItem().getType(), meta -> { + if (finished && winningLoot != null && winningLoot.getRepresentativeItem() != null) { + ItemStack displayedItem = winningLoot.getRepresentativeItem(); + + items.put(box.getOptions().rewardSlot(), new ItemMenuBuilder(this, displayedItem, meta -> { meta.displayName(Component.text("§6§l✦ ") - .append(winningItem.getDisplayedItem().effectiveName()) + .append(displayedItem.effectiveName()) .append(Component.text(" §6§l✦"))); List lore = new ArrayList<>(); lore.add(Component.text("§e§lFÉLICITATIONS !")); lore.add(Component.text(" ")); - lore.addAll(winningItem.getDisplayedItem().lore()); + if (displayedItem.lore() != null) + lore.addAll(displayedItem.lore()); meta.lore(lore); })); + return items; } @@ -104,8 +107,8 @@ public String getTexture() { if (!(loot instanceof ItemLoot itemLoot)) continue; - items.put(displaySlots.get(i), new ItemMenuBuilder(this, itemLoot.getDisplayedItem().getType(), meta -> { - meta.displayName(winningItem.getDisplayedItem().effectiveName()); + items.put(displaySlots.get(i), new ItemMenuBuilder(this, itemLoot.getDisplayedItem(), meta -> { + meta.displayName(winningLoot.getRepresentativeItem().effectiveName()); meta.lore(itemLoot.getDisplayedItem().lore()); })); } @@ -144,16 +147,9 @@ public void startAnimation() { getOwner().playSound(Sound.sound(Key.key("minecraft", "block.note_block.pling"), Sound.Source.BLOCK, 1f, 1f)); - if (box.getLootTable().selectRandomLoot() instanceof ItemLoot itemLoot) { - winningItem = itemLoot; - } else { - winningItem = null; - } + winningLoot = box.getLootTable().selectRandomLoot(); - List weightedPool = box.getLootTable().generateWeightedPool() - .stream() - .filter(item -> item instanceof ItemLoot) - .map(item -> (ItemLoot) item).toList(); + List weightedPool = box.getLootTable().generateWeightedPool(); animationTask = new BukkitRunnable() { @Override @@ -178,11 +174,7 @@ public void run() { } private void finishAnimation(boolean withLatency) { - if (box.getLootTable().selectRandomLoot() instanceof ItemLoot itemLoot) { - winningItem = itemLoot; - } else { - winningItem = null; - } + winningLoot = box.getLootTable().selectRandomLoot(); finished = true; @@ -194,13 +186,13 @@ private void finishAnimation(boolean withLatency) { new BukkitRunnable() { @Override public void run() { - boolean cancelled = giveReward(winningItem); + boolean cancelled = giveReward(winningLoot); if (cancelled) { cancel(); return; } getOwner().closeInventory(); - if (winningItem.getChance() <= 10.0) { + if (winningLoot.getChance() <= 10.0) { getOwner().playSound(Sound.sound(Key.key("minecraft", "entity.firework_rocket.launch"), Sound.Source.BLOCK, 1f, 1f)); @@ -215,11 +207,12 @@ public void run() { firework.setFireworkMeta(meta); firework.detonate(); }); + MessagesManager.broadcastMessage( Component.text("§6§l✦ §e§lFÉLICITATIONS §r§eà ") .append(Component.text(getOwner().getName())) .append(Component.text(" §equi vient de gagner ")) - .append(winningItem.getDisplayedItem().effectiveName()) + .append(winningLoot.getRepresentativeItem().effectiveName()) .append(Component.text(" §eà ")) .append(box.getName()) .append(Component.text(" §e! §6§l✦")), @@ -229,45 +222,39 @@ public void run() { }.runTaskLater(OMCPlugin.getInstance(), withLatency ? 60L : 0L); } - private boolean giveReward(ItemLoot wonItem) { + private boolean giveReward(CustomLoot wonItem) { LootboxRewardEvent rewardEvent = new LootboxRewardEvent(getOwner(), box, wonItem); Bukkit.getPluginManager().callEvent(rewardEvent); if (rewardEvent.isCancelled()) return true; - for (ItemStack reward : wonItem.getItems()) { - if (getOwner().getInventory().firstEmpty() != -1) { - getOwner().getInventory().addItem(reward); - } else { - getOwner().getWorld().dropItemNaturally(getOwner().getLocation(), reward); - } - } + wonItem.run(getOwner()); MessagesManager.sendMessage(getOwner(), Component.text("§aVous avez gagné : ") - .append(wonItem.getDisplayedItem().displayName()) + .append(wonItem.getRepresentativeItem().displayName()) .append(Component.text(" §a!")), Prefix.OPENMC, MessageType.SUCCESS, true); return false; } - private void refreshAnimated(List pool) { + private void refreshAnimated(List pool) { if (!(getOwner().getOpenInventory().getTopInventory().getHolder() instanceof LootboxOpenMenu)) return; Inventory inv = getOwner().getOpenInventory().getTopInventory(); for (int i = 0; i < displaySlots.size(); i++) { int index; - ItemLoot itemToShow; + ItemStack itemToShow; if (animationTick > maxAnimationTicks - 10 && i == displaySlots.indexOf(box.getOptions().rewardSlot())) { - itemToShow = winningItem; + itemToShow = winningLoot.getRepresentativeItem(); } else { index = (itemOffset + i) % pool.size(); - itemToShow = pool.get(index); + itemToShow = pool.get(index).getRepresentativeItem(); } - inv.setItem(displaySlots.get(i), new ItemMenuBuilder(this, itemToShow.getDisplayedItem().getType(), meta -> { - meta.displayName(itemToShow.getDisplayedItem().effectiveName()); - meta.lore(itemToShow.getDisplayedItem().lore()); + inv.setItem(displaySlots.get(i), new ItemMenuBuilder(this, itemToShow, meta -> { + meta.displayName(itemToShow.effectiveName()); + meta.lore(itemToShow.lore()); })); } diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java index 4895fd3b8..55e23669c 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java @@ -2,6 +2,7 @@ import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import java.util.Set; @@ -9,4 +10,11 @@ public interface CustomLoot { Component getDisplayText(); double getChance(); Set run(Player receiver); + + default ItemStack getRepresentativeItem() { + if (this instanceof RepresentedItem representedItem) { + return representedItem.getRepresentativeItem(); + } + return null; + } } \ No newline at end of file From f5d2565e60b2807011a156c41172ea0b2d6b34fe Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 10:44:29 +0200 Subject: [PATCH 60/74] change: adjust chance lootbox machine ball --- .../core/registry/lootboxes/LootboxOpenMenu.java | 2 +- .../loottable/contents/MachineBallLootTable.java | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java index 4d1a3b9c9..8667f7088 100644 --- a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java +++ b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java @@ -192,7 +192,7 @@ public void run() { return; } getOwner().closeInventory(); - if (winningLoot.getChance() <= 10.0) { + if (winningLoot.getChance() <= 0.1) { getOwner().playSound(Sound.sound(Key.key("minecraft", "entity.firework_rocket.launch"), Sound.Source.BLOCK, 1f, 1f)); diff --git a/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java b/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java index 7ad1f0b06..c5dfa1bb2 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java +++ b/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java @@ -30,7 +30,7 @@ public Set getLoots() { meta.lore(List.of(Component.text("§7Une petite peluche comme Seinyy !"))); } ), - 10.0, + 0.1, 1, 1 ), @@ -43,7 +43,7 @@ public Set getLoots() { meta.lore(List.of(Component.text("§7Ohhhh mais qu'est ce que c'est précieux ce truc !?"))); } ), - 15.0, + 0.15, 1, 1 ), @@ -56,7 +56,7 @@ public Set getLoots() { meta.lore(List.of(Component.text("§7Simplement du fer, rien de fou quoi..."))); } ), - 20.0, + 0.2, 1, 1 ), @@ -69,7 +69,7 @@ public Set getLoots() { meta.lore(List.of(Component.text("§7Le truc le plus rare du jeu !"))); } ), - 0.5, + 0.05, 1, 1 ), @@ -82,7 +82,7 @@ public Set getLoots() { meta.lore(List.of(Component.text("§7De quoi te faire une petite maison hihi"))); } ), - 25, + 0.25, 1, 1 ), @@ -95,7 +95,7 @@ public Set getLoots() { meta.lore(List.of(Component.text("§7Miam miam, de la bonne viande !"))); } ), - 15, + 0.15, 1, 1 ), @@ -108,7 +108,7 @@ public Set getLoots() { meta.lore(List.of(Component.text("§7De quoi faire du feu"))); } ), - 14.5, + 0.145, 1, 1 ) From 051edf8448d055d6d83551602835ba7d689b06cf Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 10:54:11 +0200 Subject: [PATCH 61/74] change: italic name + chance --- .../lootbox/LegendaryFishingTreasureLootTable.java | 4 ++-- .../openmc/core/registry/lootboxes/LootboxOpenMenu.java | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/LegendaryFishingTreasureLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/LegendaryFishingTreasureLootTable.java index 0de478e1b..db4686f21 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/LegendaryFishingTreasureLootTable.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/LegendaryFishingTreasureLootTable.java @@ -17,8 +17,8 @@ public String getNamespace() { @Override public Set getLoots() { return Set.of( - new ItemLoot(OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_HELMET, OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_HELMET, 0.20, 1, 1), - new ItemLoot(OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_BOOTS, OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_BOOTS, 0.20, 1, 1), + new ItemLoot(OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_HELMET, OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_HELMET, 0.10, 1, 1), + new ItemLoot(OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_BOOTS, OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_BOOTS, 0.10, 1, 1), new ItemLoot(DreamItemRegistry.EWENITE_BLOCK, DreamItemRegistry.EWENITE_BLOCK, 0.006, 1, 1) ); } diff --git a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java index 8667f7088..b142a2b55 100644 --- a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java +++ b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java @@ -13,6 +13,7 @@ import net.kyori.adventure.key.Key; import net.kyori.adventure.sound.Sound; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextDecoration; import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.FireworkEffect; @@ -87,7 +88,7 @@ public String getTexture() { items.put(box.getOptions().rewardSlot(), new ItemMenuBuilder(this, displayedItem, meta -> { meta.displayName(Component.text("§6§l✦ ") - .append(displayedItem.effectiveName()) + .append(displayedItem.effectiveName().decoration(TextDecoration.ITALIC, false)) .append(Component.text(" §6§l✦"))); List lore = new ArrayList<>(); lore.add(Component.text("§e§lFÉLICITATIONS !")); @@ -108,7 +109,7 @@ public String getTexture() { if (!(loot instanceof ItemLoot itemLoot)) continue; items.put(displaySlots.get(i), new ItemMenuBuilder(this, itemLoot.getDisplayedItem(), meta -> { - meta.displayName(winningLoot.getRepresentativeItem().effectiveName()); + meta.displayName(winningLoot.getRepresentativeItem().effectiveName().decoration(TextDecoration.ITALIC, false)); meta.lore(itemLoot.getDisplayedItem().lore()); })); } @@ -212,7 +213,7 @@ public void run() { Component.text("§6§l✦ §e§lFÉLICITATIONS §r§eà ") .append(Component.text(getOwner().getName())) .append(Component.text(" §equi vient de gagner ")) - .append(winningLoot.getRepresentativeItem().effectiveName()) + .append(winningLoot.getRepresentativeItem().effectiveName().decoration(TextDecoration.ITALIC, false)) .append(Component.text(" §eà ")) .append(box.getName()) .append(Component.text(" §e! §6§l✦")), @@ -253,7 +254,7 @@ private void refreshAnimated(List pool) { } inv.setItem(displaySlots.get(i), new ItemMenuBuilder(this, itemToShow, meta -> { - meta.displayName(itemToShow.effectiveName()); + meta.displayName(itemToShow.effectiveName().decoration(TextDecoration.ITALIC, false)); meta.lore(itemToShow.lore()); })); } From da5fd80f7fafcdbf35e4cbda4d5e284396e31217 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 11:13:46 +0200 Subject: [PATCH 62/74] feat: enchance message loot (sound, proba, amount) --- .../mecanism/rng/DreamRngLootManager.java | 24 ++--------------- .../listeners/PlayerFishListener.java | 9 ++++++- .../java/fr/openmc/core/utils/RngUtils.java | 27 +++++++++++++++++++ 3 files changed, 37 insertions(+), 23 deletions(-) create mode 100644 src/main/java/fr/openmc/core/utils/RngUtils.java diff --git a/src/main/java/fr/openmc/core/features/dream/mecanism/rng/DreamRngLootManager.java b/src/main/java/fr/openmc/core/features/dream/mecanism/rng/DreamRngLootManager.java index 290ebfc69..c22b56784 100644 --- a/src/main/java/fr/openmc/core/features/dream/mecanism/rng/DreamRngLootManager.java +++ b/src/main/java/fr/openmc/core/features/dream/mecanism/rng/DreamRngLootManager.java @@ -1,16 +1,12 @@ package fr.openmc.core.features.dream.mecanism.rng; +import fr.openmc.core.utils.RngUtils; import fr.openmc.core.utils.text.messages.MessageType; import fr.openmc.core.utils.text.messages.MessagesManager; import fr.openmc.core.utils.text.messages.Prefix; -import net.kyori.adventure.key.Key; -import net.kyori.adventure.sound.Sound; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; -import java.util.ArrayList; -import java.util.List; - public class DreamRngLootManager { public static void sendMessageLoot(DreamRngLootEvent event) { double chance = event.getChance() != null ? event.getChance() : 0.0; @@ -38,22 +34,6 @@ private static void sendSoundLoot(DreamRngLootEvent event) { double chance = event.getChance() != null ? event.getChance() : 0.0; Player player = event.getPlayer(); - List sounds = new ArrayList<>(); - if (chance <= 0.001) { // 0.1% - sounds.add(Sound.sound(Key.key("minecraft:entity.player.levelup"), Sound.Source.MASTER, 2f, 0.1f)); - player.getWorld().playSound(player.getLocation(), "minecraft:entity.ender_dragon.death", 1f, 0.1f); - } else if (chance <= 0.05) { // 5% - sounds.add(Sound.sound(Key.key("minecraft:entity.player.levelup"), Sound.Source.MASTER, 2f, 0.5f)); - } else if (chance <= 0.1) { // 10% - sounds.add(Sound.sound(Key.key("minecraft:entity.player.levelup"), Sound.Source.MASTER, 2f, 1.0f)); - } else if (chance <= 0.25) { // 25% - sounds.add(Sound.sound(Key.key("minecraft:entity.player.levelup"), Sound.Source.MASTER, 2f, 1.3f)); - } else { - sounds.add(Sound.sound(Key.key("minecraft:entity.player.levelup"), Sound.Source.MASTER, 2f, 2f)); - } - - for (Sound sound : sounds) { - player.playSound(sound); - } + RngUtils.sendSoundRng(player, chance); } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java index 3a7440cc2..1b1d77fd1 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java @@ -9,6 +9,7 @@ import fr.openmc.core.registry.loottable.loots.MethodLoot; import fr.openmc.core.registry.loottable.loots.MoneyLoot; import fr.openmc.core.registry.loottable.loots.TableLoot; +import fr.openmc.core.utils.RngUtils; import fr.openmc.core.utils.text.messages.MessageType; import fr.openmc.core.utils.text.messages.MessagesManager; import fr.openmc.core.utils.text.messages.Prefix; @@ -72,7 +73,13 @@ private void sendLoot(Player player, FishHook hook, Collection loots for (CustomLoot loot : loots) { if (loot.getDisplayText() != null) player.sendMessage(Component.text(" - ", NamedTextColor.GRAY) - .append(loot.getDisplayText())); + .append(Component.text(loot.getRepresentativeItem().getAmount() + "x ")) + .append(loot.getDisplayText()) + .append(Component.text(" ("+ Math.round(loot.getChance() * 1000.0) +"% ★)", NamedTextColor.AQUA)) + ); + + RngUtils.sendSoundRng(player, loot.getChance()); + MiraculousFishingManager.simulateLaunchLoot(player, hook.getLocation(), loot); // * Si y'a des sous loots, alors on affiche les sous loots obtenu diff --git a/src/main/java/fr/openmc/core/utils/RngUtils.java b/src/main/java/fr/openmc/core/utils/RngUtils.java new file mode 100644 index 000000000..7e29d3c2c --- /dev/null +++ b/src/main/java/fr/openmc/core/utils/RngUtils.java @@ -0,0 +1,27 @@ +package fr.openmc.core.utils; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.sound.Sound; +import org.bukkit.entity.Player; + +public class RngUtils { + /** + * Renvoie un son aléatoire en fonction de la chance donnée. + * @param player le joueur ciblé (et le monde ciblé si il y a une basse probabilité + * @param chance la chance eu + */ + public static void sendSoundRng(Player player, double chance) { + if (chance <= 0.001) { // 0.1% + player.playSound(Sound.sound(Key.key("minecraft:entity.player.levelup"), Sound.Source.MASTER, 2f, 0.1f)); + player.getWorld().playSound(player.getLocation(), "minecraft:entity.ender_dragon.death", 1f, 0.1f); + } else if (chance <= 0.05) { // 5% + player.playSound(Sound.sound(Key.key("minecraft:entity.player.levelup"), Sound.Source.MASTER, 2f, 0.5f)); + } else if (chance <= 0.1) { // 10% + player.playSound(Sound.sound(Key.key("minecraft:entity.player.levelup"), Sound.Source.MASTER, 2f, 1.0f)); + } else if (chance <= 0.25) { // 25% + player.playSound(Sound.sound(Key.key("minecraft:entity.player.levelup"), Sound.Source.MASTER, 2f, 1.3f)); + } else { + player.playSound(Sound.sound(Key.key("minecraft:entity.player.levelup"), Sound.Source.MASTER, 2f, 2f)); + } + } +} From f3cf55b7b384b99e52d4928abb07fa31e893f098 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 11:57:49 +0200 Subject: [PATCH 63/74] fix: money loot --- .../contents/miraculousfishing/MiraculousFishingManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java index dddb89c97..62cf766b7 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java @@ -72,7 +72,7 @@ private static ItemStack getLaunchedItem(CustomLoot loot) { if (loot instanceof MoneyLoot) item.editPersistentDataContainer(c -> c.set(NOT_PICKUP_KEY, PersistentDataType.BOOLEAN, true)); - else return item; + return item; } return null; From 9dd8258929ff95ebb71599f292251236df2a7677 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 11:58:30 +0200 Subject: [PATCH 64/74] fix: chance format --- .../miraculousfishing/listeners/PlayerFishListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java index 1b1d77fd1..052d1fb05 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java @@ -75,7 +75,7 @@ private void sendLoot(Player player, FishHook hook, Collection loots player.sendMessage(Component.text(" - ", NamedTextColor.GRAY) .append(Component.text(loot.getRepresentativeItem().getAmount() + "x ")) .append(loot.getDisplayText()) - .append(Component.text(" ("+ Math.round(loot.getChance() * 1000.0) +"% ★)", NamedTextColor.AQUA)) + .append(Component.text(" ("+ Math.round(loot.getChance() * 100.0) +"% ★)", NamedTextColor.AQUA)) ); RngUtils.sendSoundRng(player, loot.getChance()); From 19ebd2a0555a4faa5b596469a6b9a49792d24852 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 12:16:35 +0200 Subject: [PATCH 65/74] fix: name item --- .../core/registry/lootboxes/LootboxOpenMenu.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java index b142a2b55..d1b65f3cc 100644 --- a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java +++ b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java @@ -106,11 +106,15 @@ public String getTexture() { int lootIndex = (itemOffset + i) % weightedPool.size(); CustomLoot loot = weightedPool.get(lootIndex); - if (!(loot instanceof ItemLoot itemLoot)) continue; + ItemStack itemDisplay = loot.getRepresentativeItem(); + if (loot instanceof ItemLoot itemLoot) { + itemDisplay = itemLoot.getDisplayedItem(); + } - items.put(displaySlots.get(i), new ItemMenuBuilder(this, itemLoot.getDisplayedItem(), meta -> { + ItemStack finalItemDisplay = itemDisplay; + items.put(displaySlots.get(i), new ItemMenuBuilder(this, itemDisplay, meta -> { meta.displayName(winningLoot.getRepresentativeItem().effectiveName().decoration(TextDecoration.ITALIC, false)); - meta.lore(itemLoot.getDisplayedItem().lore()); + meta.lore(finalItemDisplay.lore()); })); } From 137b0cfee574bb0cc4e7133b9f7831835edb348d Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 12:38:13 +0200 Subject: [PATCH 66/74] change: show min / max amount for loot --- .../registry/lootboxes/LootboxOpenMenu.java | 35 ++++++++++++++++--- .../registry/loottable/loots/ItemLoot.java | 2 -- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java index d1b65f3cc..70a0874f9 100644 --- a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java +++ b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java @@ -107,13 +107,25 @@ public String getTexture() { CustomLoot loot = weightedPool.get(lootIndex); ItemStack itemDisplay = loot.getRepresentativeItem(); - if (loot instanceof ItemLoot itemLoot) { + + if (loot instanceof ItemLoot itemLoot && itemLoot.getDisplayedItem() != null) { itemDisplay = itemLoot.getDisplayedItem(); } + if (itemDisplay == null) continue; + ItemStack finalItemDisplay = itemDisplay; + items.put(displaySlots.get(i), new ItemMenuBuilder(this, itemDisplay, meta -> { - meta.displayName(winningLoot.getRepresentativeItem().effectiveName().decoration(TextDecoration.ITALIC, false)); + Component name = finalItemDisplay.effectiveName().decoration(TextDecoration.ITALIC, false); + + if (loot instanceof ItemLoot itemLoot + && itemLoot.getMinAmount() != itemLoot.getMaxAmount()) { + name = Component.text("§7" + itemLoot.getMinAmount() + "-" + itemLoot.getMaxAmount() + " ") + .append(name); + } + + meta.displayName(name); meta.lore(finalItemDisplay.lore()); })); } @@ -249,17 +261,30 @@ private void refreshAnimated(List pool) { for (int i = 0; i < displaySlots.size(); i++) { int index; ItemStack itemToShow; + CustomLoot currentLoot; if (animationTick > maxAnimationTicks - 10 && i == displaySlots.indexOf(box.getOptions().rewardSlot())) { itemToShow = winningLoot.getRepresentativeItem(); + currentLoot = winningLoot; } else { index = (itemOffset + i) % pool.size(); - itemToShow = pool.get(index).getRepresentativeItem(); + currentLoot = pool.get(index); + itemToShow = currentLoot.getRepresentativeItem(); } + ItemStack finalItemToShow = itemToShow; + CustomLoot finalCurrentLoot = currentLoot; inv.setItem(displaySlots.get(i), new ItemMenuBuilder(this, itemToShow, meta -> { - meta.displayName(itemToShow.effectiveName().decoration(TextDecoration.ITALIC, false)); - meta.lore(itemToShow.lore()); + Component name = finalItemToShow.effectiveName().decoration(TextDecoration.ITALIC, false); + + if (finalCurrentLoot instanceof ItemLoot itemLoot + && itemLoot.getMinAmount() != itemLoot.getMaxAmount()) { + name = Component.text("§7" + itemLoot.getMinAmount() + "-" + itemLoot.getMaxAmount() + " ") + .append(name); + } + + meta.displayName(name); + meta.lore(finalItemToShow.lore()); })); } diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java index 560cb7dcb..727241347 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java @@ -17,7 +17,6 @@ public class ItemLoot implements CustomLoot, RepresentedItem { private final ItemStack displayedItem; private final int minAmount; private final int maxAmount; - private final int amount; public ItemLoot(Set items, ItemStack displayedItem, double chance, int minAmount, int maxAmount) { this.chance = chance; @@ -25,7 +24,6 @@ public ItemLoot(Set items, ItemStack displayedItem, double chance, in this.displayedItem = displayedItem; this.minAmount = minAmount; this.maxAmount = maxAmount; - this.amount = getRandomAmount(); } public ItemLoot(ItemStack item, double chance, int minAmount, int maxAmount) { From f3d6fbbff659448061b05a5a25eba7dd701d1b62 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 13:43:25 +0200 Subject: [PATCH 67/74] fix: enchanced book, loot box --- .../lootbox/EpicFishingTreasureLootTable.java | 5 ++-- .../lootbox/RareFishingTreasureLootTable.java | 3 +-- .../registry/loottable/loots/ItemLoot.java | 23 +++++++++++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/EpicFishingTreasureLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/EpicFishingTreasureLootTable.java index a7285921f..57d4c3470 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/EpicFishingTreasureLootTable.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/EpicFishingTreasureLootTable.java @@ -4,7 +4,6 @@ import fr.openmc.core.registry.loottable.CustomLootTable; import fr.openmc.core.registry.loottable.loots.CustomLoot; import fr.openmc.core.registry.loottable.loots.ItemLoot; -import fr.openmc.core.registry.loottable.loots.LootboxLoot; import fr.openmc.core.utils.RandomUtils; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; @@ -23,7 +22,7 @@ public String getNamespace() { @Override public Set getLoots() { return Set.of( - new ItemLoot(generateEnchantedBook(), Material.ENCHANTED_BOOK, 0.2, 1, 2), + new ItemLoot(this::generateEnchantedBook, Material.ENCHANTED_BOOK, 0.2, 1, 2), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.KEBAB_FERMENTED, OMCRegistry.CUSTOM_ITEMS.KEBAB_FERMENTED, @@ -38,7 +37,7 @@ public Set getLoots() { 2, 6 ), - new LootboxLoot(OMCRegistry.CUSTOM_LOOTBOXES.LEGENDARY_FISHING_TREASURE, 0.1) + new ItemLoot(OMCRegistry.CUSTOM_ITEMS.LEGENDARY_FISHING_TREASURE, 0.1, 1, 1) ); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/RareFishingTreasureLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/RareFishingTreasureLootTable.java index de7fce132..abc5194fe 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/RareFishingTreasureLootTable.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/RareFishingTreasureLootTable.java @@ -4,7 +4,6 @@ import fr.openmc.core.registry.loottable.CustomLootTable; import fr.openmc.core.registry.loottable.loots.CustomLoot; import fr.openmc.core.registry.loottable.loots.ItemLoot; -import fr.openmc.core.registry.loottable.loots.LootboxLoot; import org.bukkit.Material; import java.util.Set; @@ -23,7 +22,7 @@ public Set getLoots() { new ItemLoot(Material.TROPICAL_FISH, Material.TROPICAL_FISH, 0.3, 32, 64), new ItemLoot(Material.PUFFERFISH, Material.PUFFERFISH, 0.3, 15, 32), new ItemLoot(Material.NAUTILUS_SHELL, Material.NAUTILUS_SHELL, 0.15, 2, 4), - new LootboxLoot(OMCRegistry.CUSTOM_LOOTBOXES.EPIC_FISHING_TREASURE, 0.1) + new ItemLoot(OMCRegistry.CUSTOM_ITEMS.EPIC_FISHING_TREASURE, 0.1, 1, 1) ); } diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java index 727241347..6d79a017e 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java @@ -9,11 +9,13 @@ import java.util.Collections; import java.util.Set; +import java.util.function.Supplier; @Getter public class ItemLoot implements CustomLoot, RepresentedItem { private final double chance; private final Set items; + private Supplier itemSupplier = null; private final ItemStack displayedItem; private final int minAmount; private final int maxAmount; @@ -26,6 +28,19 @@ public ItemLoot(Set items, ItemStack displayedItem, double chance, in this.maxAmount = maxAmount; } + public ItemLoot(Supplier itemSupplier, ItemStack displayedItem, double chance, int minAmount, int maxAmount) { + this.chance = chance; + this.items = Collections.emptySet(); + this.itemSupplier = itemSupplier; + this.displayedItem = displayedItem; + this.minAmount = minAmount; + this.maxAmount = maxAmount; + } + + public ItemLoot(Supplier itemSupplier, Material displayedItem, double chance, int minAmount, int maxAmount) { + this(itemSupplier, ItemStack.of(displayedItem), chance, minAmount, maxAmount); + } + public ItemLoot(ItemStack item, double chance, int minAmount, int maxAmount) { this(Collections.singleton(item), null, @@ -117,11 +132,19 @@ public Component getDisplayText() { @Override public Set run(Player receiver) { + if (itemSupplier != null) { + ItemStack item = itemSupplier.get(); + item.setAmount(this.getRandomAmount()); + receiver.getInventory().addItem(item); + return Collections.singleton(this); + } + for (ItemStack lootItem : this.getItems()) { ItemStack item = lootItem.clone(); item.setAmount(this.getRandomAmount()); receiver.getInventory().addItem(item); } + return Collections.singleton(this); } From 5a53572184d7a0066ea357c5e7c2ead7b70ea922 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 13:58:10 +0200 Subject: [PATCH 68/74] fix: amount --- .../registry/lootboxes/LootboxOpenMenu.java | 2 ++ .../contents/MachineBallLootTable.java | 32 +++++++++---------- .../registry/loottable/loots/ItemLoot.java | 5 ++- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java index 70a0874f9..ad9a911ca 100644 --- a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java +++ b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java @@ -272,6 +272,8 @@ private void refreshAnimated(List pool) { itemToShow = currentLoot.getRepresentativeItem(); } + if (itemToShow == null) continue; + ItemStack finalItemToShow = itemToShow; CustomLoot finalCurrentLoot = currentLoot; inv.setItem(displaySlots.get(i), new ItemMenuBuilder(this, itemToShow, meta -> { diff --git a/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java b/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java index c5dfa1bb2..bafadd3aa 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java +++ b/src/main/java/fr/openmc/core/registry/loottable/contents/MachineBallLootTable.java @@ -35,7 +35,7 @@ public Set getLoots() { 1 ), new ItemLoot( - Set.of(new ItemStack(Material.DIAMOND, 3)), + Set.of(ItemStack.of(Material.DIAMOND)), new ItemBuilder( Material.DIAMOND, meta -> { @@ -44,11 +44,11 @@ public Set getLoots() { } ), 0.15, - 1, - 1 + 3, + 3 ), new ItemLoot( - Set.of(new ItemStack(Material.IRON_INGOT, 10)), + Set.of(ItemStack.of(Material.IRON_INGOT)), new ItemBuilder( Material.IRON_INGOT, meta -> { @@ -57,11 +57,11 @@ public Set getLoots() { } ), 0.2, - 1, - 1 + 10, + 10 ), new ItemLoot( - Set.of(new ItemStack(Material.NETHERITE_INGOT)), + Set.of(ItemStack.of(Material.NETHERITE_INGOT)), new ItemBuilder( Material.NETHERITE_INGOT, meta -> { @@ -74,7 +74,7 @@ public Set getLoots() { 1 ), new ItemLoot( - Set.of(new ItemStack(Material.OAK_LOG, 32)), + Set.of(ItemStack.of(Material.OAK_LOG)), new ItemBuilder( Material.OAK_LOG, meta -> { @@ -83,11 +83,11 @@ public Set getLoots() { } ), 0.25, - 1, - 1 + 32, + 32 ), new ItemLoot( - Set.of(new ItemStack(Material.COOKED_BEEF, 16)), + Set.of(ItemStack.of(Material.COOKED_BEEF)), new ItemBuilder( Material.COOKED_BEEF, meta -> { @@ -96,11 +96,11 @@ public Set getLoots() { } ), 0.15, - 1, - 1 + 16, + 16 ), new ItemLoot( - Set.of(new ItemStack(Material.COAL, 16)), + Set.of(ItemStack.of(Material.COAL)), new ItemBuilder( Material.COAL, meta -> { @@ -109,8 +109,8 @@ public Set getLoots() { } ), 0.145, - 1, - 1 + 16, + 16 ) ); } diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java index 6d79a017e..6397cdea3 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java @@ -150,6 +150,9 @@ public Set run(Player receiver) { @Override public ItemStack getRepresentativeItem() { - return getFirstLoot(); + if (this.displayedItem != null) + return this.getDisplayedItem(); + else + return getFirstLoot(); } } \ No newline at end of file From f4ba9cda996a65313c88db4d3b643660baf3462c Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 14:07:58 +0200 Subject: [PATCH 69/74] fix: amount --- .../registry/lootboxes/LootboxOpenMenu.java | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java index ad9a911ca..e39130125 100644 --- a/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java +++ b/src/main/java/fr/openmc/core/registry/lootboxes/LootboxOpenMenu.java @@ -116,7 +116,7 @@ public String getTexture() { ItemStack finalItemDisplay = itemDisplay; - items.put(displaySlots.get(i), new ItemMenuBuilder(this, itemDisplay, meta -> { + ItemMenuBuilder itemMenuBuilder = new ItemMenuBuilder(this, finalItemDisplay, meta -> { Component name = finalItemDisplay.effectiveName().decoration(TextDecoration.ITALIC, false); if (loot instanceof ItemLoot itemLoot @@ -127,7 +127,14 @@ public String getTexture() { meta.displayName(name); meta.lore(finalItemDisplay.lore()); - })); + }); + + if (loot instanceof ItemLoot itemLoot + && itemLoot.getMinAmount() == itemLoot.getMaxAmount()) { + itemMenuBuilder.setAmount(itemLoot.getMinAmount()); + } + + items.put(displaySlots.get(i), itemMenuBuilder); } return items; @@ -276,7 +283,7 @@ private void refreshAnimated(List pool) { ItemStack finalItemToShow = itemToShow; CustomLoot finalCurrentLoot = currentLoot; - inv.setItem(displaySlots.get(i), new ItemMenuBuilder(this, itemToShow, meta -> { + ItemMenuBuilder itemMenuBuilder = new ItemMenuBuilder(this, itemToShow, meta -> { Component name = finalItemToShow.effectiveName().decoration(TextDecoration.ITALIC, false); if (finalCurrentLoot instanceof ItemLoot itemLoot @@ -287,7 +294,14 @@ private void refreshAnimated(List pool) { meta.displayName(name); meta.lore(finalItemToShow.lore()); - })); + }); + + if (finalCurrentLoot instanceof ItemLoot itemLoot + && itemLoot.getMinAmount() == itemLoot.getMaxAmount()) { + itemMenuBuilder.setAmount(itemLoot.getMinAmount()); + } + + inv.setItem(displaySlots.get(i), itemMenuBuilder); } if (animationTick >= maxAnimationTicks) { From 35ddac85371ddf66f3a24ad23c5672a3e360531c Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 14:12:19 +0200 Subject: [PATCH 70/74] change: adjust chance --- .../lootbox/FishingFurnitureLootTable.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/FishingFurnitureLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/FishingFurnitureLootTable.java index 7e2867be4..6454f907e 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/FishingFurnitureLootTable.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/loottable/lootbox/FishingFurnitureLootTable.java @@ -19,119 +19,119 @@ public Set getLoots() { new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_BLUE_FISH, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_BLUE_FISH, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_CYAN_FISH, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_CYAN_FISH, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_ORANGE_FISH, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_ORANGE_FISH, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_RED_FISH, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_RED_FISH, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_BOAT, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_BOAT, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_CHAIR, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_CHAIR, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISH_BOX, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISH_BOX, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISH_RACK, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISH_RACK, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISHING_POLE, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISHING_POLE, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISHINGPOLE_RACK, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FISHINGPOLE_RACK, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FLOATIE, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_FLOATIE, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_HANGING_FISH, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_HANGING_FISH, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_LANDING_NET, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_LANDING_NET, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_LARGE_FISHNET, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_LARGE_FISHNET, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_LOBSTER_TRAP, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_LOBSTER_TRAP, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_STAND, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_STAND, - 0.1, + 0.2, 1, 1 ), new ItemLoot( OMCRegistry.CUSTOM_ITEMS.FISHERMAN_TABLE, OMCRegistry.CUSTOM_ITEMS.FISHERMAN_TABLE, - 0.1, + 0.2, 1, 1 ) From 909d5cca7a9fba2646a7e3b342c5fb8bccb35de1 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 14:24:50 +0200 Subject: [PATCH 71/74] fix: multiple loots --- .../miraculousfishing/MiraculousFishingManager.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java index 62cf766b7..e3c3df405 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java @@ -4,7 +4,6 @@ import fr.openmc.core.registry.loottable.loots.CustomLoot; import fr.openmc.core.registry.loottable.loots.MoneyLoot; import fr.openmc.core.registry.loottable.loots.RepresentedItem; -import fr.openmc.core.registry.loottable.loots.TableLoot; import org.bukkit.Location; import org.bukkit.NamespacedKey; import org.bukkit.entity.FishHook; @@ -14,8 +13,6 @@ import org.bukkit.persistence.PersistentDataType; import org.bukkit.util.Vector; -import java.util.List; - public class MiraculousFishingManager { public static final NamespacedKey NOT_PICKUP_KEY = new NamespacedKey(OMCPlugin.getInstance(), "not_pickup"); @@ -61,12 +58,8 @@ public static void simulateLaunchLoot(Player player, Location hookLocation, Cust * @return un item stack en fonction du loot */ private static ItemStack getLaunchedItem(CustomLoot loot) { - // * SI c'est un loot provenant d'une sous loot table, on roll puis on le renvoie - if (loot instanceof TableLoot tableLoot) { - List loots = tableLoot.getLootTable().rollLoots(null, false); - return getLaunchedItem(loots.getFirst()); // * Si c'est une loot qui peut être représenter par un item - } else if (loot instanceof RepresentedItem itemDisplayed) { + if (loot instanceof RepresentedItem itemDisplayed) { ItemStack item = itemDisplayed.getRepresentativeItem(); // * et que si c'est une item, qui ne doit pas etre donné (ex Money) if (loot instanceof MoneyLoot) From 46113a3616405900f5d5c74cc4bef509b410e984 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 14:41:38 +0200 Subject: [PATCH 72/74] =?UTF-8?q?fix:=20items=20(bob=20sponge=20&=20kebab?= =?UTF-8?q?=20ferment=C3=A9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/contents/omc_daily_events/items.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/resources/contents/omc_daily_events/items.yml b/src/main/resources/contents/omc_daily_events/items.yml index 5b446cb80..c3ca0add8 100644 --- a/src/main/resources/contents/omc_daily_events/items.yml +++ b/src/main/resources/contents/omc_daily_events/items.yml @@ -15,7 +15,7 @@ items: bob_sponge: display_name: "Bob l'éponge" resource: - material: PAPER + material: SPONGE generate: false model_path: "minecraft:item/sponge" lore: @@ -25,9 +25,10 @@ items: kebab_fermented: display_name: "Kebab fermenté" resource: - material: SPONGE - generate: false - model_path: "omc_foods:items/kebab" + material: PAPER + generate: true + textures: + - "omc_foods:items/kebab" lore: - "§7§ol'originel, une légende raconte qu'il existait avant la kebaberie" glint: true From a398577de6505ef59429e8c083821bf288162dcd Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 14:53:00 +0200 Subject: [PATCH 73/74] feat: impl prout when eat kebab fermented --- .../MiraculousFishingEvent.java | 4 +- .../listeners/EatKebabFermentedListener.java | 68 +++++++++++++++++++ .../default/dailyevents.properties | 6 +- 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/EatKebabFermentedListener.java diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java index 713c7d96d..16eabe5eb 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java @@ -2,6 +2,7 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.bootstrap.features.types.HasListeners; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.listeners.EatKebabFermentedListener; import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.listeners.PlayerFishListener; import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.listeners.PlayerNotPickUpListener; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; @@ -103,7 +104,8 @@ public Component getEndBroadcast() { public Set getListeners() { return Set.of( new PlayerFishListener(), - new PlayerNotPickUpListener() + new PlayerNotPickUpListener(), + new EatKebabFermentedListener() ); } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/EatKebabFermentedListener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/EatKebabFermentedListener.java new file mode 100644 index 000000000..69e115de6 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/EatKebabFermentedListener.java @@ -0,0 +1,68 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.listeners; + +import edu.umd.cs.findbugs.annotations.Nullable; +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.items.CustomItem; +import fr.openmc.core.utils.text.messages.TranslationManager; +import net.kyori.adventure.text.Component; +import org.bukkit.*; +import org.bukkit.entity.Boat; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerItemConsumeEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import java.util.Optional; + +public class EatKebabFermentedListener implements Listener { + + @EventHandler + public void onFoodEated(PlayerItemConsumeEvent event) { + Optional customItem = OMCRegistry.CUSTOM_ITEMS.get(event.getItem()); + + if (customItem.isEmpty() || !customItem.get().getId().equals(OMCRegistry.CUSTOM_ITEMS.KEBAB_FERMENTED.getId())) return; + + proutAction(event.getPlayer()); + } + + /** + * l'original, l'unique, le vrai + */ + private void proutAction(Player player) { + player.sendMessage(TranslationManager.translation("feature.dailyevents.miraculousfishing.eat_kebab_fermented.smelt")); + + if(player.isInsideVehicle()){ + if(player.getVehicle() instanceof Boat boat){ + ItemStack itemBoat = ItemStack.of(boat.getBoatMaterial()); + player.getVehicle().remove(); + player.getWorld().dropItemNaturally(boat.getLocation(), itemBoat); + + player.sendMessage(TranslationManager.translation("feature.dailyevents.miraculousfishing.eat_kebab_fermented.boat")); + } + } + + // Make the player jump + final Vector currentVelocity = player.getVelocity(); + currentVelocity.setY(0.55d); + + player.setVelocity(currentVelocity); + + // Spawn some cloud particles + final Location location = player.getLocation(); + final @Nullable World world = location.getWorld(); + + if (world != null) { + world.spawnParticle(Particle.CLOUD, location, 3, 0.02d, -0.04d, 0.02d, 0.09d); + + // Funny sound! + world.playSound(location, Sound.ENTITY_VILLAGER_NO, SoundCategory.PLAYERS, 0.8f, 2.3f); + world.playSound(location, Sound.ENTITY_GOAT_EAT, SoundCategory.PLAYERS,0.7f, 0.2f); + } + + // Broadcast the message + Bukkit.broadcast(TranslationManager.translation("feature.dailyevents.miraculousfishing.eat_kebab_fermented.broadcast", + Component.text(player.getName()))); + } +} diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties index ca8e7e39a..c9ddcf16c 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -72,4 +72,8 @@ feature.dailyevents.miraculousfishing.lootbox.rare_fishing_treasure.name=< feature.dailyevents.miraculousfishing.lootbox.epic_fishing_treasure.name=Trésor de pêche épique feature.dailyevents.miraculousfishing.lootbox.legendary_fishing_treasure.name=Trésor de pêche légendaire -feature.dailyevents.miraculousfishing.loottable.get=Vous avez pêché %1$s objets ! \ No newline at end of file +feature.dailyevents.miraculousfishing.loottable.get=Vous avez pêché %1$s objets ! + +feature.dailyevents.miraculousfishing.eat_kebab_fermented.smelt=Beuuurk, ça pue ! +feature.dailyevents.miraculousfishing.eat_kebab_fermented.boat=Votre bateau a coulé. +feature.dailyevents.miraculousfishing.eat_kebab_fermented.broadcast=[§ka] PROUT !!! %1$s a pété. Beuurk ! \ No newline at end of file From d7ccfa7b0c91fdb28b75d13ec5b023dbb87e9b4f Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 20 Jun 2026 15:12:34 +0200 Subject: [PATCH 74/74] fix: messages + items eatable --- src/main/resources/contents/omc_daily_events/items.yml | 2 +- .../resources/translations/default/dailyevents.properties | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/contents/omc_daily_events/items.yml b/src/main/resources/contents/omc_daily_events/items.yml index c3ca0add8..ef38f1fdd 100644 --- a/src/main/resources/contents/omc_daily_events/items.yml +++ b/src/main/resources/contents/omc_daily_events/items.yml @@ -25,7 +25,7 @@ items: kebab_fermented: display_name: "Kebab fermenté" resource: - material: PAPER + material: COOKED_BEEF generate: true textures: - "omc_foods:items/kebab" diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties index c9ddcf16c..5f60c97fd 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -74,6 +74,6 @@ feature.dailyevents.miraculousfishing.lootbox.legendary_fishing_treasure.name=Vous avez pêché %1$s objets ! -feature.dailyevents.miraculousfishing.eat_kebab_fermented.smelt=Beuuurk, ça pue ! +feature.dailyevents.miraculousfishing.eat_kebab_fermented.smelt=Beuuurk, ça pue ! feature.dailyevents.miraculousfishing.eat_kebab_fermented.boat=Votre bateau a coulé. -feature.dailyevents.miraculousfishing.eat_kebab_fermented.broadcast=[§ka] PROUT !!! %1$s a pété. Beuurk ! \ No newline at end of file +feature.dailyevents.miraculousfishing.eat_kebab_fermented.broadcast=[a] PROUT !!! %1$s a pété. Beuurk ! \ No newline at end of file