From 7a8bd974ceb174491f4ca26fce6a1b5da3f77c1b Mon Sep 17 00:00:00 2001 From: Elenterius Date: Mon, 14 Aug 2023 18:51:20 +0200 Subject: [PATCH] feat: rework Cradle sacrifice system to prefer to spawn hostile mobs and occasionally anomalies This reworks how the tributes affect the spawning of flesh blobs and removes the spawning of malignant blobs when using living flesh. --- .../biomancy/block/cradle/ITribute.java | 15 ++- .../block/cradle/MobEffectTribute.java | 5 + .../cradle/PrimordialCradleBlockEntity.java | 82 ++++++++-------- .../block/cradle/SacrificeHandler.java | 13 ++- .../biomancy/block/cradle/Tribute.java | 61 ++++++++++++ .../biomancy/block/cradle/Tributes.java | 94 +++++++++---------- 6 files changed, 177 insertions(+), 93 deletions(-) create mode 100644 src/main/java/com/github/elenterius/biomancy/block/cradle/Tribute.java diff --git a/src/main/java/com/github/elenterius/biomancy/block/cradle/ITribute.java b/src/main/java/com/github/elenterius/biomancy/block/cradle/ITribute.java index d1d453ad5..e1b311cd3 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/cradle/ITribute.java +++ b/src/main/java/com/github/elenterius/biomancy/block/cradle/ITribute.java @@ -1,6 +1,6 @@ package com.github.elenterius.biomancy.block.cradle; -interface ITribute { +public interface ITribute { ITribute EMPTY = new ITribute() { @Override public int biomass() { @@ -27,6 +27,11 @@ public int hostileModifier() { return 0; } + @Override + public int anomalyModifier() { + return 0; + } + @Override public boolean isEmpty() { return true; @@ -43,7 +48,13 @@ public boolean isEmpty() { int hostileModifier(); + int anomalyModifier(); + default boolean isEmpty() { - return biomass() == 0 && lifeEnergy() == 0 && successModifier() == 0 && diseaseModifier() == 0 && hostileModifier() == 0; + return biomass() == 0 && lifeEnergy() == 0 + && successModifier() == 0 + && diseaseModifier() == 0 + && hostileModifier() == 0 + && anomalyModifier() == 0; } } diff --git a/src/main/java/com/github/elenterius/biomancy/block/cradle/MobEffectTribute.java b/src/main/java/com/github/elenterius/biomancy/block/cradle/MobEffectTribute.java index 9864e8b36..f5df57faf 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/cradle/MobEffectTribute.java +++ b/src/main/java/com/github/elenterius/biomancy/block/cradle/MobEffectTribute.java @@ -109,4 +109,9 @@ public int diseaseModifier() { public int hostileModifier() { return hostileModifier; } + + @Override + public int anomalyModifier() { + return 0; + } } diff --git a/src/main/java/com/github/elenterius/biomancy/block/cradle/PrimordialCradleBlockEntity.java b/src/main/java/com/github/elenterius/biomancy/block/cradle/PrimordialCradleBlockEntity.java index a05dad218..4ecd90164 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/cradle/PrimordialCradleBlockEntity.java +++ b/src/main/java/com/github/elenterius/biomancy/block/cradle/PrimordialCradleBlockEntity.java @@ -1,21 +1,22 @@ package com.github.elenterius.biomancy.block.cradle; -import com.github.elenterius.biomancy.block.FleshVeinsBlock; import com.github.elenterius.biomancy.block.entity.SimpleSyncedBlockEntity; -import com.github.elenterius.biomancy.entity.fleshblob.AbstractFleshBlob; -import com.github.elenterius.biomancy.init.*; +import com.github.elenterius.biomancy.entity.fleshblob.FleshBlob; +import com.github.elenterius.biomancy.init.ModBlockEntities; +import com.github.elenterius.biomancy.init.ModDamageSources; +import com.github.elenterius.biomancy.init.ModEntityTypes; +import com.github.elenterius.biomancy.init.ModSoundEvents; import com.github.elenterius.biomancy.network.ISyncableAnimation; import com.github.elenterius.biomancy.network.ModNetworkHandler; import com.github.elenterius.biomancy.util.SoundUtil; +import com.github.elenterius.biomancy.world.PrimordialEcosystem; import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.particles.SimpleParticleType; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntitySelector; @@ -133,47 +134,63 @@ private void resetState() { public void onSacrifice(ServerLevel level) { BlockPos pos = getBlockPos(); - if (sacrificeHandler.getTumorFactor() < 2f && level.random.nextFloat() < sacrificeHandler.getSuccessChance()) { - spawnFleshBlob(level, pos, sacrificeHandler); - SoundUtil.broadcastBlockSound(level, pos, ModSoundEvents.CREATOR_SPAWN_MOB); + if (level.random.nextFloat() < sacrificeHandler.getSuccessChance()) { + + if (level.random.nextFloat() < sacrificeHandler.getAnomalyChance()) { + spawnPrimordialFleshBlob(level, pos, sacrificeHandler); + SoundUtil.broadcastBlockSound(level, pos, SoundEvents.FOX_SCREECH, 2f, 0.5f); + } + else { + if (sacrificeHandler.getHostileChance() < -4.2f) { + spawnLegacyFleshBlob(level, pos, sacrificeHandler); + } + else { + spawnFleshBlob(level, pos, sacrificeHandler); + } + SoundUtil.broadcastBlockSound(level, pos, ModSoundEvents.CREATOR_SPAWN_MOB); + } + level.sendParticles(ParticleTypes.EXPLOSION, pos.getX() + 0.5d, pos.getY() + 0.5d, pos.getZ() + 0.5d, 1, 0, 0, 0, 0); } else { - if (sacrificeHandler.getSuccessChance() > -9000) { - attackAOE(level, pos); - SoundUtil.broadcastBlockSound(level, pos, ModSoundEvents.CREATOR_SPIKE_ATTACK); - spawnFleshBlocks(level, pos, sacrificeHandler); - } - else { - spawnMalignantFleshBlob(level, pos); - SoundUtil.broadcastBlockSound(level, pos, SoundEvents.TRIDENT_THUNDER, 5f, 0.9f); - level.sendParticles(ParticleTypes.EXPLOSION, pos.getX() + 0.5d, pos.getY() + 0.5d, pos.getZ() + 0.5d, 1, 0, 0, 0, 0); + attackAOE(level, pos); + SoundUtil.broadcastBlockSound(level, pos, ModSoundEvents.CREATOR_SPIKE_ATTACK); + if (level.random.nextFloat() < sacrificeHandler.getTumorFactor()) { + PrimordialEcosystem.spreadMalignantVeinsFromSource(level, pos); } } resetState(); } - public void spawnMalignantFleshBlob(ServerLevel level, BlockPos pos) { - AbstractFleshBlob fleshBlob = ModEntityTypes.MALIGNANT_FLESH_BLOB.get().create(level); + public void spawnPrimordialFleshBlob(ServerLevel level, BlockPos pos, SacrificeHandler sacrificeHandler) { + EntityType entityType = level.random.nextFloat() < sacrificeHandler.getHostileChance() ? ModEntityTypes.PRIMORDIAL_HUNGRY_FLESH_BLOB.get() : ModEntityTypes.PRIMORDIAL_FLESH_BLOB.get(); + spawnPrimordialFleshBlob(level, pos, entityType); + } + + public void spawnPrimordialFleshBlob(ServerLevel level, BlockPos pos, EntityType fleshBlobType) { + FleshBlob fleshBlob = fleshBlobType.create(level); if (fleshBlob != null) { float yaw = PrimordialCradleBlock.getYRotation(getBlockState()); fleshBlob.moveTo(pos.getX() + 0.5f, pos.getY() + 4f / 16f, pos.getZ() + 0.5f, yaw, 0); fleshBlob.yHeadRot = fleshBlob.getYRot(); fleshBlob.yBodyRot = fleshBlob.getYRot(); - fleshBlob.randomizeTumors(); fleshBlob.restrictTo(pos, 32); level.addFreshEntity(fleshBlob); } } + public void spawnLegacyFleshBlob(ServerLevel level, BlockPos pos, SacrificeHandler sacrificeHandler) { + spawnFleshBlob(level, pos, sacrificeHandler, ModEntityTypes.LEGACY_FLESH_BLOB.get()); + } + public void spawnFleshBlob(ServerLevel level, BlockPos pos, SacrificeHandler sacrificeHandler) { - EntityType entityType = level.random.nextFloat() < sacrificeHandler.getHostileChance() ? ModEntityTypes.HUNGRY_FLESH_BLOB.get() : ModEntityTypes.FLESH_BLOB.get(); + EntityType entityType = level.random.nextFloat() < sacrificeHandler.getHostileChance() ? ModEntityTypes.HUNGRY_FLESH_BLOB.get() : ModEntityTypes.FLESH_BLOB.get(); spawnFleshBlob(level, pos, sacrificeHandler, entityType); } - public void spawnFleshBlob(ServerLevel level, BlockPos pos, SacrificeHandler sacrificeHandler, EntityType fleshBlobType) { - AbstractFleshBlob fleshBlob = fleshBlobType.create(level); + public void spawnFleshBlob(ServerLevel level, BlockPos pos, SacrificeHandler sacrificeHandler, EntityType fleshBlobType) { + FleshBlob fleshBlob = fleshBlobType.create(level); if (fleshBlob != null) { float yaw = PrimordialCradleBlock.getYRotation(getBlockState()); fleshBlob.moveTo(pos.getX() + 0.5f, pos.getY() + 4f / 16f, pos.getZ() + 0.5f, yaw, 0); @@ -185,25 +202,6 @@ public void spawnFleshBlob(ServerLevel level, BlockPos pos, SacrificeHandler sac } } - public void spawnFleshBlocks(ServerLevel level, BlockPos pos, SacrificeHandler sacrificeHandler) { - if (level.random.nextFloat() >= sacrificeHandler.getTumorFactor()) return; - - FleshVeinsBlock veinsBlock = ModBlocks.MALIGNANT_FLESH_VEINS.get(); - BlockState state = level.getBlockState(pos); - - if (level.random.nextFloat() < 0.6f) veinsBlock.getSpreader().spreadFromRandomFaceTowardRandomDirection(state, level, pos, level.random); - if (level.random.nextFloat() < 0.6f) veinsBlock.getSpreader().spreadFromRandomFaceTowardRandomDirection(state, level, pos, level.random); - if (level.random.nextFloat() < 0.6f) veinsBlock.getSpreader().spreadFromRandomFaceTowardRandomDirection(state, level, pos, level.random); - if (level.random.nextFloat() < 0.6f) veinsBlock.getSpreader().spreadFromRandomFaceTowardRandomDirection(state, level, pos, level.random); - level.playSound(null, pos, ModSoundEvents.FLESH_BLOCK_STEP.get(), SoundSource.BLOCKS, 1f, 0.15f + level.random.nextFloat() * 0.5f); - - for (Direction subDirection : Direction.allShuffled(level.random)) { - BlockPos neighborPos = pos.relative(subDirection); - BlockState neighborState = level.getBlockState(neighborPos); - veinsBlock.increaseCharge(level, neighborPos, neighborState, level.random.nextIntBetweenInclusive(1, 3)); - } - } - public void attackAOE() { if (level != null && !level.isClientSide() && level instanceof ServerLevel serverLevel) { attackAOE(serverLevel, worldPosition); diff --git a/src/main/java/com/github/elenterius/biomancy/block/cradle/SacrificeHandler.java b/src/main/java/com/github/elenterius/biomancy/block/cradle/SacrificeHandler.java index 58c512a98..a1eb11e92 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/cradle/SacrificeHandler.java +++ b/src/main/java/com/github/elenterius/biomancy/block/cradle/SacrificeHandler.java @@ -14,7 +14,8 @@ public class SacrificeHandler implements INBTSerializable { private byte lifeEnergy; private int successValue; private int diseaseValue; - private int hostileValue; + private int hostileValue = 100; + private int anomalyValue = 5; public boolean isFull() { return lifeEnergy >= MAX_VALUE && biomass >= MAX_VALUE; @@ -84,6 +85,10 @@ public float getHostileChance() { return hostileValue / 100f; } + public float getAnomalyChance() { + return anomalyValue / 100f; + } + public float getTumorFactor() { return diseaseValue / 100f; } @@ -140,6 +145,7 @@ public boolean addTribute(ITribute tribute) { diseaseValue += tribute.diseaseModifier(); hostileValue += tribute.hostileModifier(); successValue += tribute.successModifier(); + anomalyValue += tribute.anomalyModifier(); return true; } @@ -151,8 +157,9 @@ public void reset() { lifeEnergy = 0; diseaseValue = 0; - hostileValue = 0; + hostileValue = 100; successValue = 0; + anomalyValue = 5; } @Override @@ -164,6 +171,7 @@ public CompoundTag serializeNBT() { tag.putInt("Disease", diseaseValue); tag.putInt("Hostile", hostileValue); tag.putInt("Success", successValue); + tag.putInt("Anomaly", anomalyValue); return tag; } @@ -175,6 +183,7 @@ public void deserializeNBT(CompoundTag tag) { diseaseValue = tag.getInt("Disease"); hostileValue = tag.getInt("Hostile"); successValue = tag.getInt("Success"); + anomalyValue = tag.getInt("Anomaly"); } } diff --git a/src/main/java/com/github/elenterius/biomancy/block/cradle/Tribute.java b/src/main/java/com/github/elenterius/biomancy/block/cradle/Tribute.java new file mode 100644 index 000000000..4f8ccdc5d --- /dev/null +++ b/src/main/java/com/github/elenterius/biomancy/block/cradle/Tribute.java @@ -0,0 +1,61 @@ +package com.github.elenterius.biomancy.block.cradle; + +public record Tribute(int biomass, int lifeEnergy, int successModifier, int diseaseModifier, int hostileModifier, int anomalyModifier) implements ITribute { + public Tribute(ITribute a, ITribute b) { + this( + a.biomass() + b.biomass(), + a.lifeEnergy() + b.lifeEnergy(), + a.successModifier() + b.successModifier(), + a.diseaseModifier() + b.diseaseModifier(), + a.hostileModifier() + b.hostileModifier(), + a.anomalyModifier() + b.anomalyModifier() + ); + } + + public static Tribute.Builder builder() { + return new Tribute.Builder(); + } + + public static class Builder { + private int successModifier = 0; + private int diseaseModifier = 0; + private int hostileModifier = 0; + private int biomass = 0; + private int lifeEnergy = 0; + private int anomalyModifier = 0; + + public Builder successModifier(int successModifier) { + this.successModifier = successModifier; + return this; + } + + public Builder diseaseModifier(int diseaseModifier) { + this.diseaseModifier = diseaseModifier; + return this; + } + + public Builder hostileModifier(int hostileModifier) { + this.hostileModifier = hostileModifier; + return this; + } + + public Builder biomass(int biomass) { + this.biomass = biomass; + return this; + } + + public Builder lifeEnergy(int lifeEnergy) { + this.lifeEnergy = lifeEnergy; + return this; + } + + public Builder anomalyModifier(int anomalyModifier) { + this.anomalyModifier = anomalyModifier; + return this; + } + + public ITribute create() { + return new Tribute(biomass, lifeEnergy, successModifier, diseaseModifier, hostileModifier, anomalyModifier); + } + } +} diff --git a/src/main/java/com/github/elenterius/biomancy/block/cradle/Tributes.java b/src/main/java/com/github/elenterius/biomancy/block/cradle/Tributes.java index ee2d746f4..24108c08c 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/cradle/Tributes.java +++ b/src/main/java/com/github/elenterius/biomancy/block/cradle/Tributes.java @@ -8,37 +8,51 @@ import net.minecraft.world.item.Items; import net.minecraftforge.common.Tags; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; + final class Tributes { - static final ImmutableMap ITEM_MAP = new ImmutableMap.Builder() - .put(ModItems.CREATOR_MIX.get(), new ImmutableTribute(20, 20, 19, 6, 6)) - - .put(ModItems.HEALING_ADDITIVE.get(), new ImmutableTribute(0, 50, 1, -5, 0)) - .put(ModItems.REGENERATIVE_FLUID.get(), new ImmutableTribute(0, 5, 0, 0, 0)) - - .put(Items.ROTTEN_FLESH, new ImmutableTribute(10, 0, 6, 20, 15)) - .put(ModItems.MOB_SINEW.get(), new ImmutableTribute(5, 0, 2, 0, 0)) - .put(ModItems.FLESH_BITS.get(), new ImmutableTribute(5, 0, 2, 0, 0)) - - .put(Items.RABBIT_FOOT, new ImmutableTribute(40, 0, -10)) - .put(Items.SPIDER_EYE, new ImmutableTribute(10, 10, 5)) - .put(Items.FERMENTED_SPIDER_EYE, new ImmutableTribute(-10, 0, 25)) - .put(ModItems.TOXIN_GLAND.get(), new ImmutableTribute(0, 50, 30)) - .put(ModItems.VOLATILE_GLAND.get(), new ImmutableTribute(0, 20, 30)) - .put(ModItems.GENERIC_MOB_GLAND.get(), new ImmutableTribute(0, -5, -5)) - .put(Items.BONE_MEAL, new ImmutableTribute(2, -2, 0)) - .put(ModItems.MOB_MARROW.get(), new ImmutableTribute(5, -20, -5)) - .put(ModItems.WITHERED_MOB_MARROW.get(), new ImmutableTribute(-30, -30, 40)) - .put(ModItems.MOB_FANG.get(), new ImmutableTribute(0, 0, 30)) - .put(ModItems.MOB_CLAW.get(), new ImmutableTribute(0, 0, 20)) - - .put(ModItems.LIVING_FLESH.get(), new ImmutableTribute(-999999, 999999, 999999)) + static final Map ITEM_MAP = new ImmutableMap.Builder() + .put(ModItems.CREATOR_MIX.get(), Tribute.builder().biomass(20).lifeEnergy(20).successModifier(19).diseaseModifier(6).hostileModifier(-12).create()) + .put(ModItems.PRIMORDIAL_CORE.get(), Tribute.builder().biomass(80).successModifier(64).anomalyModifier(100).diseaseModifier(50).create()) + .put(ModItems.LIVING_FLESH.get(), Tribute.builder().biomass(10).lifeEnergy(10).successModifier(40).anomalyModifier(55).create()) + .put(Items.GOLDEN_APPLE, Tribute.builder().successModifier(10).hostileModifier(-100).create()) + .put(Items.ENCHANTED_GOLDEN_APPLE, Tribute.builder().lifeEnergy(15).successModifier(40).hostileModifier(-200).create()) + .put(Items.CAKE, Tribute.builder().hostileModifier(-80).diseaseModifier(10).create()) + + .put(ModItems.HEALING_ADDITIVE.get(), Tribute.builder().lifeEnergy(50).successModifier(1).diseaseModifier(-5).hostileModifier(-10).create()) + .put(ModItems.REGENERATIVE_FLUID.get(), Tribute.builder().lifeEnergy(5).hostileModifier(-1).create()) + + .put(Items.ROTTEN_FLESH, Tribute.builder().biomass(10).successModifier(-10).diseaseModifier(20).create()) + .put(ModItems.MOB_SINEW.get(), Tribute.builder().biomass(5).successModifier(2).hostileModifier(-2).create()) + .put(ModItems.FLESH_BITS.get(), Tribute.builder().biomass(5).successModifier(2).hostileModifier(-2).create()) + + .put(Items.RABBIT_FOOT, Tribute.builder().successModifier(1000).hostileModifier(-50).anomalyModifier(50).create()) + .put(Items.SPIDER_EYE, Tribute.builder().successModifier(10).diseaseModifier(10).hostileModifier(-5).create()) + .put(Items.FERMENTED_SPIDER_EYE, Tribute.builder().successModifier(-10).hostileModifier(-10).create()) + .put(ModItems.TOXIN_GLAND.get(), Tribute.builder().successModifier(-5).diseaseModifier(50).create()) + .put(ModItems.VOLATILE_GLAND.get(), Tribute.builder().successModifier(-5).diseaseModifier(20).create()) + .put(ModItems.GENERIC_MOB_GLAND.get(), Tribute.builder().diseaseModifier(-5).hostileModifier(-20).create()) + .put(Items.BONE, Tribute.builder().successModifier(3).diseaseModifier(-10).create()) + .put(Items.BONE_MEAL, Tribute.builder().successModifier(1).diseaseModifier(-1).create()) + .put(ModItems.MOB_MARROW.get(), Tribute.builder().successModifier(5).diseaseModifier(-20).hostileModifier(-10).create()) + .put(ModItems.WITHERED_MOB_MARROW.get(), Tribute.builder().successModifier(-30).diseaseModifier(-40).create()) + .put(ModItems.MOB_FANG.get(), Tribute.builder().successModifier(5).hostileModifier(5).create()) + .put(ModItems.MOB_CLAW.get(), Tribute.builder().successModifier(5).hostileModifier(5).create()) + .put(Items.ENDER_PEARL, Tribute.builder().hostileModifier(50).anomalyModifier(50).create()) + + .put(ModItems.ELASTIC_FIBERS.get(), Tribute.builder().diseaseModifier(1).anomalyModifier(1).create()) + .put(ModItems.TOUGH_FIBERS.get(), Tribute.builder().diseaseModifier(1).anomalyModifier(1).create()) .build(); - static final ImmutableTribute GENERIC_BONES = new ImmutableTribute(5, -5, 0); - static final ImmutableTribute GENERIC_RAW_MEATS = new ImmutableTribute(20, 0, 16, 5, 0); - static final ImmutableTribute COOKED_MEATS = new ImmutableTribute(-999, 0, 10); - static final ImmutableTribute INVALID_ITEM = new ImmutableTribute(-99, 0, 20); + static final List FUZZY_TRIBUTES = List.of( + new FuzzyTribute(stack -> stack.is(ModItemTags.RAW_MEATS), Tribute.builder().biomass(20).successModifier(16).diseaseModifier(5).hostileModifier(-5).create()), + new FuzzyTribute(stack -> stack.is(ModItemTags.COOKED_MEATS), Tribute.builder().successModifier(-999).create()), + new FuzzyTribute(stack -> stack.is(Tags.Items.BONES), Tribute.builder().successModifier(5).diseaseModifier(-5).create()) + ); + static final ITribute INVALID_ITEM = Tribute.builder().successModifier(-99).diseaseModifier(5).hostileModifier(20).create(); private Tributes() {} @@ -51,36 +65,22 @@ static ITribute from(ItemStack stack) { return INVALID_ITEM; } - return new ImmutableTribute(tribute, mobEffectTribute); + return new Tribute(tribute, mobEffectTribute); } static ITribute findExistingTribute(ItemStack stack) { if (stack.isEmpty()) return ITribute.EMPTY; - ImmutableTribute foundTribute = ITEM_MAP.get(stack.getItem()); + ITribute foundTribute = ITEM_MAP.get(stack.getItem()); if (foundTribute != null) return foundTribute; - if (stack.is(ModItemTags.RAW_MEATS)) return GENERIC_RAW_MEATS; - if (stack.is(ModItemTags.COOKED_MEATS)) return COOKED_MEATS; - if (stack.is(Tags.Items.BONES)) return GENERIC_BONES; + for (FuzzyTribute fuzzyTribute : FUZZY_TRIBUTES) { + if (fuzzyTribute.predicate.test(stack)) return fuzzyTribute.tribute; + } return ITribute.EMPTY; } - record ImmutableTribute(int biomass, int lifeEnergy, int successModifier, int diseaseModifier, int hostileModifier) implements ITribute { - public ImmutableTribute(int successModifier, int diseaseModifier, int hostileModifier) { - this(0, 0, successModifier, diseaseModifier, hostileModifier); - } - - public ImmutableTribute(ITribute a, ITribute b) { - this( - a.biomass() + b.biomass(), - a.lifeEnergy() + b.lifeEnergy(), - a.successModifier() + b.successModifier(), - a.diseaseModifier() + b.diseaseModifier(), - a.hostileModifier() + b.hostileModifier() - ); - } + record FuzzyTribute(Predicate predicate, ITribute tribute) {} - } }