66import dev .overgrown .thaumaturge .block .VesselBlock ;
77import dev .overgrown .thaumaturge .registry .ModBlocks ;
88import dev .overgrown .thaumaturge .recipe .VesselRecipe ;
9+
10+ import dev .overgrown .aspectslib .aether .DynamicAetherDensityManager ;
11+ import net .minecraft .block .SculkSpreadable ;
12+ import net .minecraft .registry .entry .RegistryEntry ;
13+ import net .minecraft .registry .RegistryKey ;
14+ import net .minecraft .util .Identifier ;
15+ import net .minecraft .world .biome .Biome ;
16+ import net .minecraft .sound .SoundEvents ;
17+ import net .minecraft .sound .SoundCategory ;
18+ import net .minecraft .block .Blocks ;
19+
920import net .minecraft .block .Block ;
1021import net .minecraft .block .BlockState ;
1122import net .minecraft .block .entity .BlockEntity ;
2536import net .minecraft .world .World ;
2637import org .jetbrains .annotations .Nullable ;
2738
39+ import java .util .Map .Entry ;
2840import java .util .HashMap ;
2941import java .util .Map ;
3042import java .util .Optional ;
3143
3244public class VesselBlockEntity extends BlockEntity implements Inventory {
3345 private final DefaultedList <ItemStack > items = DefaultedList .ofSize (6 , ItemStack .EMPTY );
46+ public static final Identifier VITIUM_ASPECT = new Identifier ("aspectslib" , "vitium" );
3447 private final Map <String , Integer > aspects = new HashMap <>();
3548 private ItemStack catalyst = ItemStack .EMPTY ;
3649 private boolean boiling = false ;
@@ -54,6 +67,129 @@ public static void serverTick(World world, BlockPos pos, BlockState state, Vesse
5467 blockEntity .processItemForAspects ();
5568 }
5669 }
70+
71+ // Check if water level is 0 and there are aspects
72+ int waterLevel = state .get (VesselBlock .WATER_LEVEL );
73+ if (waterLevel == 0 && !blockEntity .aspects .isEmpty ()) {
74+ blockEntity .convertAspectsToVitium (world , pos );
75+ }
76+
77+ // Handle biome corruption if vitium is present
78+ if (world .getTime () % 200 == 0 ) { // Check every 10 seconds
79+ blockEntity .corruptBiome (world , pos );
80+ }
81+ }
82+
83+ private void convertAspectsToVitium (World world , BlockPos pos ) {
84+ // Calculate total aspects
85+ int totalAspects = this .aspects .values ().stream ().mapToInt (Integer ::intValue ).sum ();
86+
87+ if (totalAspects == 0 ) {
88+ return ;
89+ }
90+
91+ // Get biome ID
92+ RegistryEntry <Biome > biomeEntry = world .getBiome (pos );
93+ Optional <RegistryKey <Biome >> optionalKey = biomeEntry .getKey ();
94+ if (optionalKey .isEmpty ()) {
95+ return ;
96+ }
97+ Identifier biomeId = optionalKey .get ().getValue ();
98+
99+ // Add vitium to biome
100+ DynamicAetherDensityManager .addModification (biomeId , VITIUM_ASPECT , totalAspects );
101+
102+ // Clear aspects from vessel
103+ this .aspects .clear ();
104+
105+ // Reset boiling state and process time
106+ this .boiling = false ;
107+ this .processTime = 0 ;
108+
109+ // Visual and sound effects
110+ if (world instanceof ServerWorld serverWorld ) {
111+ serverWorld .spawnParticles (ParticleTypes .SMOKE ,
112+ pos .getX () + 0.5 , pos .getY () + 1.0 , pos .getZ () + 0.5 ,
113+ 10 , 0.2 , 0.2 , 0.2 , 0.0 );
114+ world .playSound (null , pos , SoundEvents .BLOCK_LAVA_EXTINGUISH ,
115+ SoundCategory .BLOCKS , 1.0f , 1.0f );
116+ }
117+
118+ markDirty ();
119+ syncToClient ();
120+ }
121+
122+ private void corruptBiome (World world , BlockPos pos ) {
123+ // Get biome ID
124+ RegistryEntry <Biome > biomeEntry = world .getBiome (pos );
125+ Optional <RegistryKey <Biome >> optionalKey = biomeEntry .getKey ();
126+ if (optionalKey .isEmpty ()) {
127+ return ;
128+ }
129+ Identifier biomeId = optionalKey .get ().getValue ();
130+
131+ // Get current modifications
132+ Map <Identifier , Double > modifications = DynamicAetherDensityManager .getModifications (biomeId );
133+ if (modifications == null ) {
134+ return ;
135+ }
136+
137+ // Check if vitium is dominant
138+ Double vitiumAmount = modifications .get (VITIUM_ASPECT );
139+ if (vitiumAmount == null || vitiumAmount <= 0 ) {
140+ return ;
141+ }
142+
143+ double totalOtherAspects = modifications .entrySet ().stream ()
144+ .filter (entry -> !entry .getKey ().equals (VITIUM_ASPECT ))
145+ .mapToDouble (Entry ::getValue )
146+ .sum ();
147+
148+ // If vitium is dominant, convert other aspects to vitium
149+ if (vitiumAmount > totalOtherAspects ) {
150+ modifications .entrySet ().stream ()
151+ .filter (entry -> !entry .getKey ().equals (VITIUM_ASPECT ))
152+ .forEach (entry -> {
153+ double convertedAmount = entry .getValue () * 0.1 ; // Convert 10% per check
154+ modifications .put (entry .getKey (), entry .getValue () - convertedAmount );
155+ modifications .put (VITIUM_ASPECT , vitiumAmount + convertedAmount );
156+ });
157+
158+ // If only vitium remains, replace random blocks with sculk
159+ if (totalOtherAspects <= 0 ) {
160+ replaceRandomBlockWithSculk (world , pos );
161+ }
162+
163+ markDirty ();
164+ syncToClient ();
165+ }
166+ }
167+
168+ private void replaceRandomBlockWithSculk (World world , BlockPos pos ) {
169+ // Get a random position within 16 blocks
170+ BlockPos targetPos = pos .add (
171+ world .random .nextInt (32 ) - 16 ,
172+ world .random .nextInt (8 ) - 4 ,
173+ world .random .nextInt (32 ) - 16
174+ );
175+
176+ // Check if the block is replaceable
177+ BlockState currentState = world .getBlockState (targetPos );
178+ if (currentState .isAir () || currentState .getBlock () instanceof SculkSpreadable ) {
179+ return ;
180+ }
181+
182+ // Replace with sculk block
183+ world .setBlockState (targetPos , Blocks .SCULK .getDefaultState ());
184+
185+ // Visual and sound effects
186+ if (world instanceof ServerWorld serverWorld ) {
187+ serverWorld .spawnParticles (ParticleTypes .SOUL ,
188+ targetPos .getX () + 0.5 , targetPos .getY () + 0.5 , targetPos .getZ () + 0.5 ,
189+ 5 , 0.2 , 0.2 , 0.2 , 0.0 );
190+ world .playSound (null , targetPos , SoundEvents .BLOCK_SCULK_PLACE ,
191+ SoundCategory .BLOCKS , 1.0f , 1.0f );
192+ }
57193 }
58194
59195 public void processItemForAspects () {
0 commit comments