diff --git a/mubble-core/src/main/java/fr/hugman/mubble/world/entity/item/collectible/CollectibleEntity.java b/mubble-core/src/main/java/fr/hugman/mubble/world/entity/item/collectible/CollectibleEntity.java index 114b1154..2457f792 100644 --- a/mubble-core/src/main/java/fr/hugman/mubble/world/entity/item/collectible/CollectibleEntity.java +++ b/mubble-core/src/main/java/fr/hugman/mubble/world/entity/item/collectible/CollectibleEntity.java @@ -27,8 +27,10 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Level; +import net.minecraft.world.level.ServerExplosion; import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueOutput; +import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.jspecify.annotations.Nullable; @@ -65,6 +67,17 @@ public CollectibleEntity(Level level, double x, double y, double z, ItemStack st this.setFixed(true); } + @Nullable + public static Vec3 placePos(Level level, BlockPos blockPos) { + var dimensions = MubbleEntityTypes.COLLECTIBLE.getDimensions(); + Vec3 pos = Vec3.atBottomCenterOf(blockPos).add(0, Math.clamp((1 - dimensions.height()) / 2, 0.0f, 0.5f), 0); + AABB box = dimensions.makeBoundingBox(pos.x(), pos.y(), pos.z()); + if (level.noCollision(null, box) && level.getEntities(null, box).isEmpty()) { + return pos; + } + return null; + } + public ItemStack getItem() { return this.getEntityData().get(DATA_ITEM); } @@ -298,6 +311,10 @@ public boolean ignoreExplosion(final Explosion explosion) { if (!this.isFixed()) { return false; } + if(!(explosion instanceof ServerExplosion)) { + //TODO: make this more dynamic... + return true; + } return explosion.shouldAffectBlocklikeEntities() ? super.ignoreExplosion(explosion) : true; } diff --git a/mubble-core/src/main/java/fr/hugman/mubble/world/entity/projectile/Ball.java b/mubble-core/src/main/java/fr/hugman/mubble/world/entity/projectile/Ball.java index 0bcdcb72..3fa08d9b 100644 --- a/mubble-core/src/main/java/fr/hugman/mubble/world/entity/projectile/Ball.java +++ b/mubble-core/src/main/java/fr/hugman/mubble/world/entity/projectile/Ball.java @@ -88,7 +88,7 @@ public void reboundUp() { /** * Triggers after the ball has hit and can no longer rebound. */ - protected void finalHit() { + protected final void finalHit() { this.finalHit(this.getDeathSound()); } diff --git a/mubble-super_mario/build.gradle b/mubble-super_mario/build.gradle index 0e992bb1..6f624d8e 100644 --- a/mubble-super_mario/build.gradle +++ b/mubble-super_mario/build.gradle @@ -14,6 +14,8 @@ fabricApi { } loom { + accessWidenerPath = file("src/main/resources/super_mario.accesswidener") + runs { datagen { name "Data Generation" diff --git a/mubble-super_mario/src/client/java/fr/hugman/mubble/super_mario/client/renderer/SuperMarioRenderers.java b/mubble-super_mario/src/client/java/fr/hugman/mubble/super_mario/client/renderer/SuperMarioRenderers.java index c22c9501..8e4eddcc 100644 --- a/mubble-super_mario/src/client/java/fr/hugman/mubble/super_mario/client/renderer/SuperMarioRenderers.java +++ b/mubble-super_mario/src/client/java/fr/hugman/mubble/super_mario/client/renderer/SuperMarioRenderers.java @@ -16,6 +16,7 @@ public static void registerEntities() { EntityRenderers.register(SuperMarioEntityTypes.RED_KOOPA_SHELL, KoopaShellRenderer::new); EntityRenderers.register(SuperMarioEntityTypes.FIREBALL, BallRenderer::new); EntityRenderers.register(SuperMarioEntityTypes.ICEBALL, BallRenderer::new); + EntityRenderers.register(SuperMarioEntityTypes.GOLD_FIREBALL, BallRenderer::new); } public static void registerBlockEntities() { diff --git a/mubble-super_mario/src/client/resources/assets/super_mario/sounds/entity/generic/golden_explosion.ogg b/mubble-super_mario/src/client/resources/assets/super_mario/sounds/entity/generic/golden_explosion.ogg new file mode 100644 index 00000000..3c376759 Binary files /dev/null and b/mubble-super_mario/src/client/resources/assets/super_mario/sounds/entity/generic/golden_explosion.ogg differ diff --git a/mubble-super_mario/src/client/resources/assets/super_mario/sounds/power_up/obtain/gold.ogg b/mubble-super_mario/src/client/resources/assets/super_mario/sounds/power_up/obtain/gold.ogg new file mode 100644 index 00000000..b2e5b1e6 Binary files /dev/null and b/mubble-super_mario/src/client/resources/assets/super_mario/sounds/power_up/obtain/gold.ogg differ diff --git a/mubble-super_mario/src/client/resources/assets/super_mario/textures/entity/gold_fireball.png b/mubble-super_mario/src/client/resources/assets/super_mario/textures/entity/gold_fireball.png new file mode 100644 index 00000000..17a82ecb Binary files /dev/null and b/mubble-super_mario/src/client/resources/assets/super_mario/textures/entity/gold_fireball.png differ diff --git a/mubble-super_mario/src/client/resources/assets/super_mario/textures/item/gold_flower.png b/mubble-super_mario/src/client/resources/assets/super_mario/textures/item/gold_flower.png index bf6070ad..1d009a3a 100644 Binary files a/mubble-super_mario/src/client/resources/assets/super_mario/textures/item/gold_flower.png and b/mubble-super_mario/src/client/resources/assets/super_mario/textures/item/gold_flower.png differ diff --git a/mubble-super_mario/src/client/resources/assets/super_mario/textures/item/silver_flower.png b/mubble-super_mario/src/client/resources/assets/super_mario/textures/item/silver_flower.png new file mode 100644 index 00000000..83a3ac86 Binary files /dev/null and b/mubble-super_mario/src/client/resources/assets/super_mario/textures/item/silver_flower.png differ diff --git a/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/PowerUpItems.java b/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/PowerUpItems.java index 70efa0b5..0dab8c7f 100644 --- a/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/PowerUpItems.java +++ b/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/PowerUpItems.java @@ -16,7 +16,8 @@ public record Entry(ResourceKey item, ResourceKey powerUp) { } new Entry(SuperMarioItemKeys.MINI_MUSHROOM, SuperMarioPowerUpKeys.MINI), new Entry(SuperMarioItemKeys.MEGA_MUSHROOM, SuperMarioPowerUpKeys.MEGA), new Entry(SuperMarioItemKeys.FIRE_FLOWER, SuperMarioPowerUpKeys.FIRE), - new Entry(SuperMarioItemKeys.ICE_FLOWER, SuperMarioPowerUpKeys.ICE) + new Entry(SuperMarioItemKeys.ICE_FLOWER, SuperMarioPowerUpKeys.ICE), + new Entry(SuperMarioItemKeys.GOLD_FLOWER, SuperMarioPowerUpKeys.GOLD) ); public static ResourceKey getItem(ResourceKey powerUp) { diff --git a/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioBlockTagsProvider.java b/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioBlockTagsProvider.java index bdd1adbf..e22c65d7 100644 --- a/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioBlockTagsProvider.java +++ b/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioBlockTagsProvider.java @@ -34,6 +34,8 @@ protected void addTags(HolderLookup.Provider wrapperLookup) { valueLookupBuilder(SNAKE_BLOCKS).add(SNAKE_BLOCK, FAST_SNAKE_BLOCK, SLOW_SNAKE_BLOCK); valueLookupBuilder(BEEP_BLOCKS).add(RED_BEEP_BLOCK, BLUE_BEEP_BLOCK); + valueLookupBuilder(GOLD_EXPLOSION_SENSITIVE).add(BRICK_BLOCK, CRYSTAL_BLOCK); + valueLookupBuilder(EGG_BLOCKS).add( BLUE_EGG_BLOCK, CYAN_EGG_BLOCK, diff --git a/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioDamageTypeProvider.java b/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioDamageTypeProvider.java index 74c058e7..9a41849d 100644 --- a/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioDamageTypeProvider.java +++ b/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioDamageTypeProvider.java @@ -32,5 +32,6 @@ public static void bootstrap(BootstrapContext context) { context.register(SuperMarioDamageTypeKeys.KOOPA_SHELL, new DamageType(SuperMario.MOD_ID + ".koopa_shell", 0.1f)); context.register(SuperMarioDamageTypeKeys.FIREBALL, new DamageType(SuperMario.MOD_ID + ".fireball", 0.1f, DamageEffects.BURNING)); context.register(SuperMarioDamageTypeKeys.ICEBALL, new DamageType(SuperMario.MOD_ID + ".iceball", 0.1f, DamageEffects.FREEZING)); + context.register(SuperMarioDamageTypeKeys.GOLD_FIREBALL, new DamageType(SuperMario.MOD_ID + ".gold_fireball", 0.1f)); } } \ No newline at end of file diff --git a/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioEnglishLangProvider.java b/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioEnglishLangProvider.java index 05e54351..484ab1a4 100644 --- a/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioEnglishLangProvider.java +++ b/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioEnglishLangProvider.java @@ -39,6 +39,7 @@ public void generateTranslations(HolderLookup.Provider wrapperLookup, Translatio builder.add("subtitles." + SuperMario.MOD_ID + ".block.note_block.jump", "Note Block used"); builder.add(SuperMarioSounds.COIN_COLLECT.value(), "Coin collected"); builder.add("subtitles." + SuperMario.MOD_ID + ".item.cape_feather.use", "Cape Feather used"); + builder.add(SuperMarioSounds.GOLDEN_EXPLOSION.value(), "Golden explosion"); builder.add("subtitles." + SuperMario.MOD_ID + ".entity.goomba.find_target", "Goomba finds a target"); builder.add("subtitles." + SuperMario.MOD_ID + ".entity.goomba.death", "Goomba dies"); builder.add("subtitles." + SuperMario.MOD_ID + ".entity.goomba.stomp", "Goomba stomped"); @@ -52,6 +53,7 @@ public void generateTranslations(HolderLookup.Provider wrapperLookup, Translatio builder.add("subtitles." + SuperMario.MOD_ID + ".entity.fireball.throw", "Fireball thrown"); builder.add("subtitles." + SuperMario.MOD_ID + ".entity.iceball.hit", "Iceball hits"); builder.add("subtitles." + SuperMario.MOD_ID + ".entity.iceball.throw", "Iceball thrown"); + builder.add(SuperMarioSounds.GOLD_FIREBALL_THROW.value(), "Gold Fireball thrown"); builder.add("subtitles." + SuperMario.MOD_ID + ".power_up.obtain", "Power-up obtained"); builder.add("subtitles." + SuperMario.MOD_ID + ".power_up.loose", "Power-up lost"); @@ -64,5 +66,7 @@ public void generateTranslations(HolderLookup.Provider wrapperLookup, Translatio builder.add("death.attack." + SuperMario.MOD_ID + ".fireball.player", "%1$s was fireballed while fighting %2$s"); builder.add("death.attack." + SuperMario.MOD_ID + ".iceball", "%1$s was iceballed by %2$s"); builder.add("death.attack." + SuperMario.MOD_ID + ".iceball.player", "%1$s was iceballed while fighting %2$s"); + builder.add("death.attack." + SuperMario.MOD_ID + ".gold_fireball", "%1$s was gold-blasted by %2$s"); + builder.add("death.attack." + SuperMario.MOD_ID + ".gold_fireball.player", "%1$s was gold-blasted while fighting %2$s"); } } \ No newline at end of file diff --git a/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioModelProvider.java b/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioModelProvider.java index 4a1705fe..aa35708b 100644 --- a/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioModelProvider.java +++ b/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioModelProvider.java @@ -79,6 +79,7 @@ public void generateItemModels(ItemModelGenerators gen) { gen.generateFlatItem(SuperMarioItems.MEGA_MUSHROOM, ModelTemplates.FLAT_ITEM); gen.generateFlatItem(SuperMarioItems.FIRE_FLOWER, ModelTemplates.FLAT_ITEM); gen.generateFlatItem(SuperMarioItems.ICE_FLOWER, ModelTemplates.FLAT_ITEM); + gen.generateFlatItem(SuperMarioItems.GOLD_FLOWER, ModelTemplates.FLAT_ITEM); gen.generateFlatItem(SuperMarioItems.CAPE_FEATHER, ModelTemplates.FLAT_ITEM); gen.generateFlatItem(SuperMarioItems.SUPER_CAPE_FEATHER, ModelTemplates.FLAT_ITEM); diff --git a/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioPowerUpProvider.java b/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioPowerUpProvider.java index 572abdfd..0b7434ec 100644 --- a/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioPowerUpProvider.java +++ b/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioPowerUpProvider.java @@ -86,6 +86,16 @@ public static void bootstrap(BootstrapContext context) { Optional.empty() ))) .build()); + context.register(GOLD, create(GOLD) + .obtainSound(SuperMarioSounds.POWER_UP_OBTAIN_GOLD) + .action(Holder.direct(new ShootProjectilePowerUpAction( + SuperMarioEntityTypes.GOLD_FIREBALL, + SuperMarioSounds.GOLD_FIREBALL_THROW, + 0.4f, + Optional.of(3), + Optional.empty() + ))) + .build()); } public static PowerUpBuilder create(ResourceKey key) { diff --git a/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioSoundsProvider.java b/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioSoundsProvider.java index 2459bdb6..f017bafd 100644 --- a/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioSoundsProvider.java +++ b/mubble-super_mario/src/datagen/java/fr/hugman/mubble/super_mario/data/provider/SuperMarioSoundsProvider.java @@ -39,6 +39,8 @@ protected void configure(HolderLookup.Provider wrapperLookup, SoundExporter soun soundExporter.add(SuperMarioSounds.CAPE_FEATHER_USE, variantSoundBuilder(SuperMarioSounds.CAPE_FEATHER_USE, 1)); // Entities + soundExporter.add(SuperMarioSounds.GOLDEN_EXPLOSION, variantSoundBuilder(SuperMarioSounds.GOLDEN_EXPLOSION, 1)); + soundExporter.add(SuperMarioSounds.GOOMBA_WALK_STEP, variantSoundBuilder(SuperMarioSounds.GOOMBA_WALK_STEP, 1).subtitle("subtitles.block.generic.footsteps")); soundExporter.add(SuperMarioSounds.GOOMBA_RUN_STEP, variantSoundBuilder(SuperMarioSounds.GOOMBA_RUN_STEP, 1).subtitle("subtitles.block.generic.footsteps")); soundExporter.add(SuperMarioSounds.GOOMBA_FIND_TARGET, variantSoundBuilder(SuperMarioSounds.GOOMBA_FIND_TARGET, 1)); @@ -60,10 +62,15 @@ protected void configure(HolderLookup.Provider wrapperLookup, SoundExporter soun soundExporter.add(SuperMarioSounds.ICEBALL_HIT_ENTITY, variantSoundBuilder(SuperMarioSounds.ICEBALL_HIT_ENTITY, 1).subtitle("subtitles." + SuperMario.MOD_ID + ".entity.iceball.hit")); soundExporter.add(SuperMarioSounds.ICEBALL_THROW, variantSoundBuilder(SuperMarioSounds.ICEBALL_THROW, 1)); + soundExporter.add(SuperMarioSounds.GOLD_FIREBALL_THROW, variantSoundBuilder(SuperMarioSounds.FIREBALL_THROW, 1).subtitle("subtitles." + SuperMario.MOD_ID + ".entity.gold_fireball.throw")); + // Power-Up + var obtainSub = "subtitles." + SuperMario.MOD_ID + ".power_up.obtain"; + soundExporter.add(SuperMarioSounds.POWER_UP_OBTAIN, variantSoundBuilder(SuperMarioSounds.POWER_UP_OBTAIN, 1)); - soundExporter.add(SuperMarioSounds.POWER_UP_OBTAIN_MINI, variantSoundBuilder(SuperMarioSounds.POWER_UP_OBTAIN_MINI, 1).subtitle("subtitles." + SuperMario.MOD_ID + ".power_up.obtain")); - soundExporter.add(SuperMarioSounds.POWER_UP_OBTAIN_SUPER_STAR, variantSoundBuilder(SuperMarioSounds.POWER_UP_OBTAIN_SUPER_STAR, 1).subtitle("subtitles." + SuperMario.MOD_ID + ".power_up.obtain")); + soundExporter.add(SuperMarioSounds.POWER_UP_OBTAIN_MINI, variantSoundBuilder(SuperMarioSounds.POWER_UP_OBTAIN_MINI, 1).subtitle(obtainSub)); + soundExporter.add(SuperMarioSounds.POWER_UP_OBTAIN_SUPER_STAR, variantSoundBuilder(SuperMarioSounds.POWER_UP_OBTAIN_SUPER_STAR, 1).subtitle(obtainSub)); + soundExporter.add(SuperMarioSounds.POWER_UP_OBTAIN_GOLD, variantSoundBuilder(SuperMarioSounds.POWER_UP_OBTAIN_GOLD, 1).subtitle(obtainSub)); soundExporter.add(SuperMarioSounds.POWER_UP_LOOSE, variantSoundBuilder(SuperMarioSounds.POWER_UP_LOOSE, 1)); } diff --git a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioDamageTypeKeys.java b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioDamageTypeKeys.java index 8e4624fa..bb5d6386 100644 --- a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioDamageTypeKeys.java +++ b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioDamageTypeKeys.java @@ -10,6 +10,7 @@ public class SuperMarioDamageTypeKeys { public static final ResourceKey KOOPA_SHELL = createKey("koopa_shell"); public static final ResourceKey FIREBALL = createKey("fireball"); public static final ResourceKey ICEBALL = createKey("iceball"); + public static final ResourceKey GOLD_FIREBALL = createKey("gold_fireball"); private static ResourceKey createKey(String path) { return ResourceKey.create(Registries.DAMAGE_TYPE, SuperMario.id(path)); diff --git a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioEntityTypeKeys.java b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioEntityTypeKeys.java index e7f0927b..3c0dc804 100644 --- a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioEntityTypeKeys.java +++ b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioEntityTypeKeys.java @@ -10,6 +10,7 @@ public class SuperMarioEntityTypeKeys { public static final ResourceKey> RED_KOOPA_SHELL = createKey("red_koopa_shell"); public static final ResourceKey> FIREBALL = createKey("fireball"); public static final ResourceKey> ICEBALL = createKey("iceball"); + public static final ResourceKey> GOLD_FIREBALL = createKey("gold_fireball"); private static ResourceKey> createKey(String path) { return ResourceKey.create(Registries.ENTITY_TYPE, SuperMario.id(path)); diff --git a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioItemKeys.java b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioItemKeys.java index bd636b13..b2b5492e 100644 --- a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioItemKeys.java +++ b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioItemKeys.java @@ -17,6 +17,7 @@ public class SuperMarioItemKeys { public static final ResourceKey MEGA_MUSHROOM = createKey("mega_mushroom"); public static final ResourceKey FIRE_FLOWER = createKey("fire_flower"); public static final ResourceKey ICE_FLOWER = createKey("ice_flower"); + public static final ResourceKey GOLD_FLOWER = createKey("gold_flower"); public static final ResourceKey CAPE_FEATHER = createKey("cape_feather"); public static final ResourceKey SUPER_CAPE_FEATHER = createKey("super_cape_feather"); diff --git a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioPowerUpKeys.java b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioPowerUpKeys.java index 93ec6b59..ac9a6825 100644 --- a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioPowerUpKeys.java +++ b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/references/SuperMarioPowerUpKeys.java @@ -10,6 +10,7 @@ public class SuperMarioPowerUpKeys { public static final ResourceKey MEGA = createKey("mega"); public static final ResourceKey FIRE = createKey("fire"); public static final ResourceKey ICE = createKey("ice"); + public static final ResourceKey GOLD = createKey("gold"); private static ResourceKey createKey(String path) { return ResourceKey.create(MubbleRegistries.POWER_UP, SuperMario.id(path)); diff --git a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/sounds/SuperMarioSounds.java b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/sounds/SuperMarioSounds.java index 40705a8e..5e576f7f 100644 --- a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/sounds/SuperMarioSounds.java +++ b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/sounds/SuperMarioSounds.java @@ -21,6 +21,8 @@ public class SuperMarioSounds { public static final Holder.Reference COIN_BOUNCE = registerForHolder("item.coin.bounce"); public static final SoundEvent CAPE_FEATHER_USE = register("item.cape_feather.use"); + public static final Holder.Reference GOLDEN_EXPLOSION = registerForHolder("entity.generic.golden_explosion"); + public static final SoundEvent GOOMBA_WALK_STEP = register("entity.goomba.walk_step"); public static final SoundEvent GOOMBA_RUN_STEP = register("entity.goomba.run_step"); public static final SoundEvent GOOMBA_FIND_TARGET = register("entity.goomba.find_target"); @@ -42,9 +44,12 @@ public class SuperMarioSounds { public static final SoundEvent ICEBALL_HIT_ENTITY = register("entity.iceball.hit.entity"); public static final Holder.Reference ICEBALL_THROW = registerForHolder("entity.iceball.throw"); + public static final Holder.Reference GOLD_FIREBALL_THROW = registerForHolder("entity.gold_fireball.throw"); + public static final Holder.Reference POWER_UP_OBTAIN = registerForHolder("power_up.obtain"); public static final Holder.Reference POWER_UP_OBTAIN_MINI = registerForHolder("power_up.obtain.mini"); public static final Holder.Reference POWER_UP_OBTAIN_SUPER_STAR = registerForHolder("power_up.obtain.super_star"); + public static final Holder.Reference POWER_UP_OBTAIN_GOLD = registerForHolder("power_up.obtain.gold"); public static final Holder.Reference POWER_UP_LOOSE = registerForHolder("power_up.loose"); diff --git a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/tags/SuperMarioBlockTags.java b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/tags/SuperMarioBlockTags.java index e42a39c8..66820197 100644 --- a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/tags/SuperMarioBlockTags.java +++ b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/tags/SuperMarioBlockTags.java @@ -12,6 +12,9 @@ public class SuperMarioBlockTags { public static final TagKey SNAKE_BLOCKS = bind("snake_blocks"); public static final TagKey BEEP_BLOCKS = bind("beep_blocks"); + public static final TagKey GOLD_EXPLOSION_SENSITIVE = bind("gold_explosion_sensitive"); + + // YOSHI'S ISLAND public static final TagKey EGG_BLOCKS = bind("egg_blocks"); public static TagKey bind(String path) { diff --git a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/entity/SuperMarioEntityTypes.java b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/entity/SuperMarioEntityTypes.java index 49d94ae8..c2fef509 100644 --- a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/entity/SuperMarioEntityTypes.java +++ b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/entity/SuperMarioEntityTypes.java @@ -2,10 +2,7 @@ import fr.hugman.mubble.super_mario.references.SuperMarioEntityTypeKeys; import fr.hugman.mubble.super_mario.world.entity.monster.goomba.Goomba; -import fr.hugman.mubble.super_mario.world.entity.projectile.Fireball; -import fr.hugman.mubble.super_mario.world.entity.projectile.GreenKoopaShell; -import fr.hugman.mubble.super_mario.world.entity.projectile.Iceball; -import fr.hugman.mubble.super_mario.world.entity.projectile.RedKoopaShell; +import fr.hugman.mubble.super_mario.world.entity.projectile.*; import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; @@ -20,6 +17,7 @@ public final class SuperMarioEntityTypes { public static final EntityType RED_KOOPA_SHELL = of(SuperMarioEntityTypeKeys.RED_KOOPA_SHELL, EntityType.Builder.of(RedKoopaShell::new, MobCategory.MISC).sized(10 / 16f, 7 / 16f)); public static final EntityType FIREBALL = of(SuperMarioEntityTypeKeys.FIREBALL, EntityType.Builder.of(Fireball::new, MobCategory.MISC).sized(0.4F, 0.4F).clientTrackingRange(4).updateInterval(10)); public static final EntityType ICEBALL = of(SuperMarioEntityTypeKeys.ICEBALL, EntityType.Builder.of(Iceball::new, MobCategory.MISC).sized(0.4F, 0.4F).clientTrackingRange(4).updateInterval(10)); + public static final EntityType GOLD_FIREBALL = of(SuperMarioEntityTypeKeys.GOLD_FIREBALL, EntityType.Builder.of(GoldFireball::new, MobCategory.MISC).sized(0.4F, 0.4F).clientTrackingRange(4).updateInterval(10)); private static EntityType of(ResourceKey> id, EntityType.Builder type) { return Registry.register(BuiltInRegistries.ENTITY_TYPE, id, type.build(id)); diff --git a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/entity/projectile/GoldFireball.java b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/entity/projectile/GoldFireball.java new file mode 100644 index 00000000..3e5ce898 --- /dev/null +++ b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/entity/projectile/GoldFireball.java @@ -0,0 +1,69 @@ +package fr.hugman.mubble.super_mario.world.entity.projectile; + +import fr.hugman.mubble.Mubble; +import fr.hugman.mubble.super_mario.SuperMario; +import fr.hugman.mubble.super_mario.references.SuperMarioDamageTypeKeys; +import fr.hugman.mubble.super_mario.sounds.SuperMarioSounds; +import fr.hugman.mubble.super_mario.world.entity.SuperMarioEntityTypes; +import fr.hugman.mubble.super_mario.world.level.GoldenServerExplosion; +import fr.hugman.mubble.world.entity.projectile.Ball; +import net.minecraft.core.ClientAsset; +import net.minecraft.core.Direction; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.BlockHitResult; + +public class GoldFireball extends Ball { + private static final ClientAsset.ResourceTexture TEXTURE = new ClientAsset.ResourceTexture(SuperMario.id("entity/gold_fireball")); + + public GoldFireball(EntityType type, Level level) { + super(type, level); + } + + public GoldFireball(Level level, LivingEntity owner) { + super(SuperMarioEntityTypes.GOLD_FIREBALL, level, owner); + } + + public GoldFireball(double x, double y, double z, Level level) { + super(SuperMarioEntityTypes.GOLD_FIREBALL, x, y, z, level); + } + + @Override + protected SoundEvent getDeathSound() { + return SuperMarioSounds.FIREBALL_HIT_BLOCK; //TODO change + } + + @Override + protected ParticleOptions getDeathParticle() { + return ParticleTypes.FLAME; //TODO change + } + + @Override + protected void onHitBlock(BlockHitResult result) { + super.onHitBlock(result); + Direction face = result.getDirection(); + if (face == Direction.UP) { + this.reboundUp(); + } else { + this.finalHit(); + } + } + + @Override + protected void finalHit(SoundEvent deathSound) { + super.finalHit(deathSound); + if(this.level() instanceof ServerLevel serverLevel) { + GoldenServerExplosion.create(serverLevel, this, this.damageSources().source(SuperMarioDamageTypeKeys.GOLD_FIREBALL, this, this.getOwner()), null, this.getX(), this.getY(0.0625F), this.getZ(), 3.0F, Level.ExplosionInteraction.MOB); + } + } + + @Override + public ClientAsset.ResourceTexture getTexture() { + return TEXTURE; + } +} \ No newline at end of file diff --git a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/item/CollectibleItem.java b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/item/CollectibleItem.java index 4b576daf..178d85d8 100644 --- a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/item/CollectibleItem.java +++ b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/item/CollectibleItem.java @@ -38,10 +38,8 @@ public InteractionResult useOn(final UseOnContext context) { BlockPlaceContext placeContext = new BlockPlaceContext(context); BlockPos blockPos = placeContext.getClickedPos(); ItemStack itemStack = context.getItemInHand(); - var dimensions = MubbleEntityTypes.COLLECTIBLE.getDimensions(); - Vec3 pos = Vec3.atBottomCenterOf(blockPos).add(0, Math.clamp((1 - dimensions.height()) / 2, 0.0f, 0.5f), 0); - AABB box = dimensions.makeBoundingBox(pos.x(), pos.y(), pos.z()); - if (level.noCollision(null, box) && level.getEntities(null, box).isEmpty()) { + Vec3 pos = CollectibleEntity.placePos(level, blockPos); + if (pos != null) { if (level instanceof ServerLevel serverLevel) { CollectibleEntity entity = new CollectibleEntity(serverLevel, pos.x(), pos.y(), pos.z(), itemStack.copyWithCount(1)); entity.setCollectSound(new SoundConfig(SuperMarioSounds.COIN_COLLECT, 0.2f, 1.0f)); diff --git a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/item/SuperMarioCreativeModeTabs.java b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/item/SuperMarioCreativeModeTabs.java index adbbced5..5b07c45d 100644 --- a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/item/SuperMarioCreativeModeTabs.java +++ b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/item/SuperMarioCreativeModeTabs.java @@ -47,6 +47,7 @@ public static void appendItemGroups() { entries.accept(SuperMarioItems.FLOWER_COIN); entries.accept(SuperMarioItems.FIRE_FLOWER); entries.accept(SuperMarioItems.ICE_FLOWER); + entries.accept(SuperMarioItems.GOLD_FLOWER); entries.accept(SuperMarioItems.MINI_MUSHROOM); entries.accept(SuperMarioItems.MEGA_MUSHROOM); entries.accept(SuperMarioBlocks.QUESTION_BLOCK); diff --git a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/item/SuperMarioItems.java b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/item/SuperMarioItems.java index 7eab0136..3843b71c 100644 --- a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/item/SuperMarioItems.java +++ b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/item/SuperMarioItems.java @@ -34,6 +34,7 @@ public class SuperMarioItems { public static final PowerUpItem MEGA_MUSHROOM = registerPowerUp(SuperMarioItemKeys.MEGA_MUSHROOM, SuperMarioPowerUpKeys.MEGA); public static final PowerUpItem FIRE_FLOWER = registerPowerUp(SuperMarioItemKeys.FIRE_FLOWER, SuperMarioPowerUpKeys.FIRE); public static final PowerUpItem ICE_FLOWER = registerPowerUp(SuperMarioItemKeys.ICE_FLOWER, SuperMarioPowerUpKeys.ICE); + public static final PowerUpItem GOLD_FLOWER = registerPowerUp(SuperMarioItemKeys.GOLD_FLOWER, SuperMarioPowerUpKeys.GOLD); public static final CapeFeatherItem CAPE_FEATHER = register(SuperMarioItemKeys.CAPE_FEATHER, s -> new CapeFeatherItem(s, false)); public static final CapeFeatherItem SUPER_CAPE_FEATHER = register(SuperMarioItemKeys.SUPER_CAPE_FEATHER, s -> new CapeFeatherItem(s.rarity(Rarity.EPIC), true)); diff --git a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/level/GoldenServerExplosion.java b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/level/GoldenServerExplosion.java new file mode 100644 index 00000000..f7507f68 --- /dev/null +++ b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/level/GoldenServerExplosion.java @@ -0,0 +1,434 @@ +package fr.hugman.mubble.super_mario.world.level; + +import fr.hugman.mubble.sounds.SoundConfig; +import fr.hugman.mubble.super_mario.core.particles.SuperMarioParticleTypes; +import fr.hugman.mubble.super_mario.sounds.SuperMarioSounds; +import fr.hugman.mubble.super_mario.tags.SuperMarioBlockTags; +import fr.hugman.mubble.super_mario.world.item.SuperMarioItems; +import fr.hugman.mubble.super_mario.world.level.block.entity.BumpableBlockEntity; +import fr.hugman.mubble.world.entity.item.collectible.CollectibleEntity; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.particles.ExplosionParticleInfo; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.network.protocol.game.ClientboundExplodePacket; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.tags.EntityTypeTags; +import net.minecraft.util.Mth; +import net.minecraft.util.Util; +import net.minecraft.util.profiling.Profiler; +import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.util.random.WeightedList; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.item.PrimedTnt; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.*; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.gameevent.GameEvent; +import net.minecraft.world.level.gamerules.GameRules; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import org.jspecify.annotations.Nullable; + +import java.util.*; + +public class GoldenServerExplosion implements Explosion { + private static final ExplosionDamageCalculator EXPLOSION_DAMAGE_CALCULATOR = new ExplosionDamageCalculator(); + private static final WeightedList DEFAULT_EXPLOSION_BLOCK_PARTICLES = WeightedList.builder() //TODO change these + .add(new ExplosionParticleInfo(ParticleTypes.POOF, 0.5F, 1.0F)) + .add(new ExplosionParticleInfo(ParticleTypes.SMOKE, 1.0F, 1.0F)) + .build(); + + private final ServerLevel level; + private final @Nullable Entity source; + private final float radius; + private final Vec3 center; + private final BlockInteraction blockInteraction; + private final DamageSource damageSource; + private final ExplosionDamageCalculator damageCalculator; + private final Map hitPlayers = new HashMap(); + + public GoldenServerExplosion( + ServerLevel level, + @Nullable Entity source, + @Nullable DamageSource damageSource, + @Nullable ExplosionDamageCalculator damageCalculator, + Vec3 center, + float radius, + Explosion.BlockInteraction blockInteraction + ) { + this.level = level; + this.source = source; + this.radius = radius; + this.center = center; + this.blockInteraction = blockInteraction; + this.damageSource = damageSource == null ? level.damageSources().explosion(this) : damageSource; + this.damageCalculator = damageCalculator == null ? this.makeDamageCalculator(source) : damageCalculator; + } + + private ExplosionDamageCalculator makeDamageCalculator(@Nullable final Entity source) { + return source == null ? EXPLOSION_DAMAGE_CALCULATOR : new EntityBasedExplosionDamageCalculator(source); + } + + @Override + public ServerLevel level() { + return this.level; + } + + @Override + public BlockInteraction getBlockInteraction() { + return this.blockInteraction; + } + + @Override + public @Nullable LivingEntity getIndirectSourceEntity() { + return Explosion.getIndirectSourceEntity(this.source); + } + + @Override + public @Nullable Entity getDirectSourceEntity() { + return this.source; + } + + @Override + public float radius() { + return this.radius; + } + + @Override + public Vec3 center() { + return this.center; + } + + @Override + public boolean canTriggerBlocks() { + if (this.blockInteraction != Explosion.BlockInteraction.TRIGGER_BLOCK) { + return false; + } else { + return this.source != null && this.source.is(EntityType.BREEZE_WIND_CHARGE) ? this.level.getGameRules().get(GameRules.MOB_GRIEFING) : true; + } + } + + @Override + public boolean shouldAffectBlocklikeEntities() { + boolean mobGriefingEnabled = this.level.getGameRules().get(GameRules.MOB_GRIEFING); + boolean isNotWindCharge = this.source == null || !this.source.is(EntityType.BREEZE_WIND_CHARGE) && !this.source.is(EntityType.WIND_CHARGE); + return mobGriefingEnabled ? isNotWindCharge : this.blockInteraction.shouldAffectBlocklikeEntities() && isNotWindCharge; + } + + public Map getHitPlayers() { + return hitPlayers; + } + + private boolean interactsWithBlocks() { + return this.blockInteraction != Explosion.BlockInteraction.KEEP; + } + + public boolean isSmall() { + return this.radius < 2.0F || !this.interactsWithBlocks(); + } + + private List calculateAffectedPositions() { + Set toAffectSet = new HashSet(); + int size = 16; + + for (int xx = 0; xx < size; xx++) { + for (int yy = 0; yy < size; yy++) { + for (int zz = 0; zz < size; zz++) { + if (xx == 0 || xx == size - 1 || yy == 0 || yy == size - 1 || zz == 0 || zz == size - 1) { + double xd = xx / (size - 1.0F) * 2.0F - 1.0F; + double yd = yy / (size - 1.0F) * 2.0F - 1.0F; + double zd = zz / (size - 1.0F) * 2.0F - 1.0F; + double d = Math.sqrt(xd * xd + yd * yd + zd * zd); + xd /= d; + yd /= d; + zd /= d; + float remainingPower = this.radius * (0.7F + this.level.getRandom().nextFloat() * 0.6F); + double xp = this.center.x; + double yp = this.center.y; + double zp = this.center.z; + + for (float stepSize = 0.3F; remainingPower > 0.0F; remainingPower -= 0.22500001F) { + BlockPos pos = BlockPos.containing(xp, yp, zp); + BlockState block = this.level.getBlockState(pos); + FluidState fluid = this.level.getFluidState(pos); + if (!this.level.isInWorldBounds(pos)) { + break; + } + + Optional resistance = this.damageCalculator.getBlockExplosionResistance(this, this.level, pos, block, fluid); + if (resistance.isPresent()) { + remainingPower -= (resistance.get() + 0.3F) * 0.3F; + } + + if (remainingPower > 0.0F && this.damageCalculator.shouldBlockExplode(this, this.level, pos, block, remainingPower)) { + toAffectSet.add(pos); + } + + xp += xd * 0.3F; + yp += yd * 0.3F; + zp += zd * 0.3F; + } + } + } + } + } + + return new ObjectArrayList<>(toAffectSet); + } + + public int explode() { + this.level.gameEvent(this.source, GameEvent.EXPLODE, this.center); + List toAffect = this.calculateAffectedPositions(); + this.hurtEntities(); + if (this.interactsWithBlocks()) { + ProfilerFiller profiler = Profiler.get(); + profiler.push("golden_explosion_blocks"); + this.interactWithBlocks(toAffect); + profiler.pop(); + } + + return toAffect.size(); + } + + private void interactWithBlocks(final List targetBlocks) { + Util.shuffle(targetBlocks, this.level.getRandom()); + + for (BlockPos blockPos : targetBlocks) { + var state = this.level.getBlockState(blockPos); + if (!state.isAir() && this.getBlockInteraction() != BlockInteraction.TRIGGER_BLOCK) { + // TODO add custom explosion block interaction. Loot parameters and stuff + if (!state.is(SuperMarioBlockTags.GOLD_EXPLOSION_SENSITIVE)) { + continue; + } + if (level.getBlockEntity(blockPos) instanceof BumpableBlockEntity bumpable && !bumpable.isEmpty()) { + // TODO if not empty make them loot + continue; + } + + this.level.setBlock(blockPos, Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL); + Vec3 pos = CollectibleEntity.placePos(level, blockPos); + if (pos != null) { + var itemStack = new ItemStack(SuperMarioItems.COIN); + CollectibleEntity entity = new CollectibleEntity(level, pos.x(), pos.y(), pos.z(), itemStack.copyWithCount(1)); + entity.setCollectSound(new SoundConfig(SuperMarioSounds.COIN_COLLECT, 0.2f, 1.0f)); + entity.setBounceSound(new SoundConfig(SuperMarioSounds.COIN_BOUNCE, 1.0f, 1.0f)); + entity.setCollectParticle(SuperMarioParticleTypes.COIN_SPARKLE); + EntityType.createDefaultStackConfig(level, itemStack, null).accept(entity); + if (entity != null) { + entity.snapTo(entity.getX(), entity.getY(), entity.getZ(), 0.0f, 0.0F); + level.addFreshEntityWithPassengers(entity); + } + } + } + } + } + + private void hurtEntities() { + if (!(this.radius < 1.0E-5F)) { + float doubleRadius = this.radius * 2.0F; + int x0 = Mth.floor(this.center.x - doubleRadius - 1.0); + int x1 = Mth.floor(this.center.x + doubleRadius + 1.0); + int y0 = Mth.floor(this.center.y - doubleRadius - 1.0); + int y1 = Mth.floor(this.center.y + doubleRadius + 1.0); + int z0 = Mth.floor(this.center.z - doubleRadius - 1.0); + int z1 = Mth.floor(this.center.z + doubleRadius + 1.0); + + for (Entity entity : this.level.getEntities(this.source, new AABB(x0, y0, z0, x1, y1, z1))) { + if (!entity.ignoreExplosion(this)) { + double dist = Math.sqrt(entity.distanceToSqr(this.center)) / doubleRadius; + if (!(dist > 1.0)) { + Vec3 entityOrigin = entity instanceof PrimedTnt ? entity.position() : entity.getEyePosition(); + Vec3 direction = entityOrigin.subtract(this.center).normalize(); + boolean shouldDamageEntity = this.getIndirectSourceEntity() != entity && this.damageCalculator.shouldDamageEntity(this, entity); + float knockbackMultiplier = this.damageCalculator.getKnockbackMultiplier(entity); + float exposure = !shouldDamageEntity && knockbackMultiplier == 0.0F ? 0.0F : getExposure(this.center, entity); + + if (shouldDamageEntity) { + entity.hurtServer(this.level, this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity, exposure)); + } + + double knockbackResistance = entity instanceof LivingEntity livingEntity + ? livingEntity.getAttributeValue(Attributes.EXPLOSION_KNOCKBACK_RESISTANCE) + : 0.0; + double knockbackPower = (1.0 - dist) * exposure * knockbackMultiplier * (1.0 - knockbackResistance); + Vec3 knockback = direction.scale(knockbackPower); + entity.push(knockback); + if (entity.is(EntityTypeTags.REDIRECTABLE_PROJECTILE) && entity instanceof Projectile projectile) { + projectile.setOwner(this.damageSource.getEntity()); + } else if (entity instanceof Player player && !player.isSpectator() && (!player.isCreative() || !player.getAbilities().flying)) { + this.hitPlayers.put(player, knockback); + } + + entity.onExplosionHit(this.source); + + //TODO: if the entity dies, reward source with coins (or loot said coins if source is not player) + } + } + } + } + } + + public static float getExposure(final Vec3 center, final Entity entity) { + AABB bb = entity.getBoundingBox(); + double xs = 1.0 / ((bb.maxX - bb.minX) * 2.0 + 1.0); + double ys = 1.0 / ((bb.maxY - bb.minY) * 2.0 + 1.0); + double zs = 1.0 / ((bb.maxZ - bb.minZ) * 2.0 + 1.0); + double xOffset = (1.0 - Math.floor(1.0 / xs) * xs) / 2.0; + double zOffset = (1.0 - Math.floor(1.0 / zs) * zs) / 2.0; + if (!(xs < 0.0) && !(ys < 0.0) && !(zs < 0.0)) { + int hits = 0; + int count = 0; + + for (double xx = 0.0; xx <= 1.0; xx += xs) { + for (double yy = 0.0; yy <= 1.0; yy += ys) { + for (double zz = 0.0; zz <= 1.0; zz += zs) { + double x = Mth.lerp(xx, bb.minX, bb.maxX); + double y = Mth.lerp(yy, bb.minY, bb.maxY); + double z = Mth.lerp(zz, bb.minZ, bb.maxZ); + Vec3 from = new Vec3(x + xOffset, y, z + zOffset); + if (entity.level().clip(new ClipContext(from, center, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, entity)).getType() == HitResult.Type.MISS) { + hits++; + } + + count++; + } + } + } + + return (float) hits / count; + } else { + return 0.0F; + } + } + + public static void create( + ServerLevel level, + @Nullable Entity source, + double x, + double y, + double z, + float r, + Level.ExplosionInteraction blockInteraction + ) { + create(level, + source, + Explosion.getDefaultDamageSource(level, source), + null, + x, + y, + z, + r, + blockInteraction, + ParticleTypes.EXPLOSION, + ParticleTypes.EXPLOSION_EMITTER, + DEFAULT_EXPLOSION_BLOCK_PARTICLES, + SoundEvents.GENERIC_EXPLODE + ); + } + + public static void create( + ServerLevel level, + @Nullable Entity source, + @Nullable DamageSource damageSource, + @Nullable ExplosionDamageCalculator damageCalculator, + Vec3 boomPos, + float r, + Level.ExplosionInteraction blockInteraction + ) { + create( + level, + source, + damageSource, + damageCalculator, + boomPos.x(), + boomPos.y(), + boomPos.z(), + r, + blockInteraction, + ParticleTypes.EXPLOSION, + ParticleTypes.EXPLOSION_EMITTER, + DEFAULT_EXPLOSION_BLOCK_PARTICLES, + SuperMarioSounds.GOLDEN_EXPLOSION + ); + } + + public static void create( + ServerLevel level, + @Nullable Entity source, + @Nullable DamageSource damageSource, + @Nullable ExplosionDamageCalculator damageCalculator, + double x, + double y, + double z, + float r, + Level.ExplosionInteraction interactionType + ) { + create( + level, + source, + damageSource, + damageCalculator, + x, + y, + z, + r, + interactionType, + ParticleTypes.EXPLOSION, + ParticleTypes.EXPLOSION_EMITTER, + DEFAULT_EXPLOSION_BLOCK_PARTICLES, + SuperMarioSounds.GOLDEN_EXPLOSION + ); + } + + public static void create( + ServerLevel level, + @Nullable Entity source, + @Nullable DamageSource damageSource, + @Nullable ExplosionDamageCalculator damageCalculator, + double x, + double y, + double z, + float r, + Level.ExplosionInteraction interactionType, + ParticleOptions smallExplosionParticles, + ParticleOptions largeExplosionParticles, + WeightedList blockParticles, + Holder explosionSound + ) { + Explosion.BlockInteraction blockInteraction = switch (interactionType) { + case NONE -> Explosion.BlockInteraction.KEEP; + case BLOCK -> level.getDestroyType(GameRules.BLOCK_EXPLOSION_DROP_DECAY); + case MOB -> + level.getGameRules().get(GameRules.MOB_GRIEFING) ? level.getDestroyType(GameRules.MOB_EXPLOSION_DROP_DECAY) : Explosion.BlockInteraction.KEEP; + case TNT -> level.getDestroyType(GameRules.TNT_EXPLOSION_DROP_DECAY); + case TRIGGER -> Explosion.BlockInteraction.TRIGGER_BLOCK; + }; + Vec3 center = new Vec3(x, y, z); + GoldenServerExplosion explosion = new GoldenServerExplosion(level, source, damageSource, damageCalculator, center, r, blockInteraction); + int blockCount = explosion.explode(); + ParticleOptions explosionParticle = explosion.isSmall() ? smallExplosionParticles : largeExplosionParticles; + + for (ServerPlayer player : level.players()) { + if (player.distanceToSqr(center) < (double) 4096.0F) { + Optional playerKnockback = Optional.ofNullable(explosion.getHitPlayers().get(player)); + player.connection.send(new ClientboundExplodePacket(center, r, blockCount, playerKnockback, explosionParticle, explosionSound, blockParticles)); + } + } + } +} diff --git a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/level/block/SuperMarioBlocks.java b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/level/block/SuperMarioBlocks.java index 5b5dc4d6..ac8800d1 100644 --- a/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/level/block/SuperMarioBlocks.java +++ b/mubble-super_mario/src/main/java/fr/hugman/mubble/super_mario/world/level/block/SuperMarioBlocks.java @@ -23,8 +23,8 @@ public class SuperMarioBlocks { public static final EmptyBlock EMPTY_BLOCK = register(SuperMarioBlockKeys.EMPTY_BLOCK, EmptyBlock::new, BlockBehaviour.Properties.ofFullCopy(Blocks.IRON_BLOCK).mapColor(MapColor.COLOR_BROWN)); public static final DecoratedBumpableBlock QUESTION_BLOCK = registerBumpableBlock(SuperMarioBlockKeys.QUESTION_BLOCK, EMPTY_BLOCK, BlockBehaviour.Properties.ofFullCopy(Blocks.IRON_BLOCK).mapColor(MapColor.COLOR_YELLOW)); - public static final DecoratedBumpableBlock BRICK_BLOCK = registerBumpableBlock(SuperMarioBlockKeys.BRICK_BLOCK, Blocks.AIR, BlockBehaviour.Properties.ofFullCopy(Blocks.BRICKS).mapColor(MapColor.COLOR_BROWN)); - public static final DecoratedBumpableBlock CRYSTAL_BLOCK = registerBumpableBlock(SuperMarioBlockKeys.CRYSTAL_BLOCK, Blocks.AIR, BlockBehaviour.Properties.ofFullCopy(Blocks.BRICKS).sound(SoundType.AMETHYST).mapColor(MapColor.COLOR_PURPLE)); + public static final DecoratedBumpableBlock BRICK_BLOCK = registerBumpableBlock(SuperMarioBlockKeys.BRICK_BLOCK, Blocks.AIR, BlockBehaviour.Properties.ofFullCopy(Blocks.BRICKS).explosionResistance(0).mapColor(MapColor.COLOR_BROWN)); + public static final DecoratedBumpableBlock CRYSTAL_BLOCK = registerBumpableBlock(SuperMarioBlockKeys.CRYSTAL_BLOCK, Blocks.AIR, BlockBehaviour.Properties.ofFullCopy(Blocks.BRICKS).explosionResistance(0).sound(SoundType.AMETHYST).mapColor(MapColor.COLOR_PURPLE)); public static final DecoratedBumpableBlock GOLD_BLOCK = registerBumpableBlock(SuperMarioBlockKeys.GOLD_BLOCK, Blocks.AIR, BlockBehaviour.Properties.ofFullCopy(Blocks.BRICKS).mapColor(MapColor.GOLD)); public static final DecoratedBumpableBlock BLUE_EXCLAMATION_BLOCK = registerExclamationBlock(SuperMarioBlockKeys.BLUE_EXCLAMATION_BLOCK, MapColor.COLOR_BLUE); public static final DecoratedBumpableBlock GREEN_EXCLAMATION_BLOCK = registerExclamationBlock(SuperMarioBlockKeys.GREEN_EXCLAMATION_BLOCK, MapColor.COLOR_GREEN); diff --git a/mubble-super_mario/src/main/resources/fabric.mod.json b/mubble-super_mario/src/main/resources/fabric.mod.json index 241abf6a..7211defe 100644 --- a/mubble-super_mario/src/main/resources/fabric.mod.json +++ b/mubble-super_mario/src/main/resources/fabric.mod.json @@ -19,6 +19,7 @@ "environment": "client" } ], + "accessWidener": "super_mario.accesswidener", "depends": { "minecraft": "*", "fabric-api": "*", diff --git a/mubble-super_mario/src/main/resources/super_mario.accesswidener b/mubble-super_mario/src/main/resources/super_mario.accesswidener new file mode 100644 index 00000000..fa8d5d8d --- /dev/null +++ b/mubble-super_mario/src/main/resources/super_mario.accesswidener @@ -0,0 +1,2 @@ +accessWidener v1 official +accessible method net/minecraft/server/level/ServerLevel getDestroyType (Lnet/minecraft/world/level/gamerules/GameRule;)Lnet/minecraft/world/level/Explosion$BlockInteraction; \ No newline at end of file diff --git a/src/main/resources/mubble.accesswidener b/src/main/resources/mubble.accesswidener new file mode 100644 index 00000000..fa8d5d8d --- /dev/null +++ b/src/main/resources/mubble.accesswidener @@ -0,0 +1,2 @@ +accessWidener v1 official +accessible method net/minecraft/server/level/ServerLevel getDestroyType (Lnet/minecraft/world/level/gamerules/GameRule;)Lnet/minecraft/world/level/Explosion$BlockInteraction; \ No newline at end of file