-
Notifications
You must be signed in to change notification settings - Fork 3
Working on redstone sulfur cube #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
9f6aa3b
18d2512
5434fe6
78d44da
89d268c
5342c18
80bc52a
39c775c
98cf7cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| package blob.vanillasquared.main.world.redstone; | ||
|
|
||
| import net.minecraft.core.BlockPos; | ||
| import net.minecraft.server.level.ServerLevel; | ||
| import net.minecraft.util.Mth; | ||
| import net.minecraft.world.entity.Entity; | ||
| import net.minecraft.world.level.block.Blocks; | ||
| import net.minecraft.world.phys.AABB; | ||
|
|
||
| public final class VSQEntityRedstonePower { | ||
| public static final String POWER_REDSTONE_KEY = "vsq:powerRedstone"; | ||
|
|
||
| private VSQEntityRedstonePower() { | ||
| } | ||
|
|
||
| public static int getPower(Entity entity) { | ||
| if (entity instanceof VSQEntityRedstonePowerAccess access) { | ||
| return access.vsq$getRedstonePower(); | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| public static boolean hasPoweredEntities(ServerLevel level) { | ||
| return level instanceof VSQEntityRedstonePowerLevelAccess access && access.vsq$getPoweredEntityCount() > 0; | ||
| } | ||
|
|
||
| public static void incrementPoweredEntityCount(ServerLevel level) { | ||
| if (level instanceof VSQEntityRedstonePowerLevelAccess access) { | ||
| access.vsq$incrementPoweredEntityCount(); | ||
| } | ||
| } | ||
|
|
||
| public static void decrementPoweredEntityCount(ServerLevel level) { | ||
| if (level instanceof VSQEntityRedstonePowerLevelAccess access) { | ||
| access.vsq$decrementPoweredEntityCount(); | ||
| } | ||
| } | ||
|
|
||
| public static int getSignal(ServerLevel level, BlockPos pos) { | ||
| if (!hasPoweredEntities(level)) { | ||
| return 0; | ||
| } | ||
|
|
||
| AABB blockBounds = new AABB(pos); | ||
| int signal = 0; | ||
| for (Entity entity : level.getEntities((Entity) null, blockBounds, entity -> !entity.isRemoved())) { | ||
| signal = Math.max(signal, getPower(entity)); | ||
| if (signal >= 15) { | ||
| return 15; | ||
| } | ||
| } | ||
| return signal; | ||
| } | ||
|
|
||
| public static void updateNeighbors(ServerLevel level, AABB sourceBounds) { | ||
| AABB updateBounds = sourceBounds.inflate(1.0D); | ||
| for (BlockPos pos : BlockPos.betweenClosed(updateBounds)) { | ||
| if (vsq$isOnShell(pos, updateBounds) || new AABB(pos).intersects(sourceBounds)) { | ||
| level.updateNeighborsAt(pos, Blocks.REDSTONE_WIRE, null); | ||
| } | ||
| } | ||
|
PainterFlow marked this conversation as resolved.
|
||
| } | ||
|
pxlarified marked this conversation as resolved.
|
||
|
|
||
| private static boolean vsq$isOnShell(BlockPos pos, AABB bounds) { | ||
| int minX = Mth.floor(bounds.minX); | ||
| int minY = Mth.floor(bounds.minY); | ||
| int minZ = Mth.floor(bounds.minZ); | ||
| int maxX = Mth.floor(bounds.maxX); | ||
| int maxY = Mth.floor(bounds.maxY); | ||
| int maxZ = Mth.floor(bounds.maxZ); | ||
| return pos.getX() == minX || pos.getX() == maxX | ||
| || pos.getY() == minY || pos.getY() == maxY | ||
| || pos.getZ() == minZ || pos.getZ() == maxZ; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package blob.vanillasquared.main.world.redstone; | ||
|
|
||
| public interface VSQEntityRedstonePowerAccess { | ||
| int vsq$getRedstonePower(); | ||
|
|
||
| void vsq$setRedstonePower(int power); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package blob.vanillasquared.main.world.redstone; | ||
|
|
||
| public interface VSQEntityRedstonePowerLevelAccess { | ||
| int vsq$getPoweredEntityCount(); | ||
|
|
||
| void vsq$incrementPoweredEntityCount(); | ||
|
|
||
| void vsq$decrementPoweredEntityCount(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,163 @@ | ||
| package blob.vanillasquared.mixin.world.entity; | ||
|
|
||
| import blob.vanillasquared.main.world.redstone.VSQEntityRedstonePower; | ||
| import blob.vanillasquared.main.world.redstone.VSQEntityRedstonePowerAccess; | ||
| import net.minecraft.server.level.ServerLevel; | ||
| import net.minecraft.util.Mth; | ||
| import net.minecraft.world.entity.Entity; | ||
| import net.minecraft.world.entity.EquipmentSlot; | ||
| import net.minecraft.world.entity.monster.cubemob.SulfurCube; | ||
| import net.minecraft.world.item.Items; | ||
| import net.minecraft.world.level.storage.ValueInput; | ||
| import net.minecraft.world.level.storage.ValueOutput; | ||
| import net.minecraft.world.phys.AABB; | ||
| import org.spongepowered.asm.mixin.Mixin; | ||
| import org.spongepowered.asm.mixin.Unique; | ||
| import org.spongepowered.asm.mixin.injection.At; | ||
| import org.spongepowered.asm.mixin.injection.Inject; | ||
| import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; | ||
|
|
||
| @Mixin(Entity.class) | ||
| public abstract class EntityRedstonePowerMixin implements VSQEntityRedstonePowerAccess { | ||
| @Unique | ||
| private AABB vsq$previousRedstoneSourceBounds; | ||
| @Unique | ||
| private int vsq$previousRedstonePower; | ||
| @Unique | ||
| private int vsq$redstonePower; | ||
| @Unique | ||
| private boolean vsq$redstonePowerCounted; | ||
| @Unique | ||
| private ServerLevel vsq$redstonePowerCountedLevel; | ||
|
|
||
| @Inject(method = "load", at = @At("TAIL")) | ||
| private void vsq$loadEntityRedstonePower(ValueInput input, CallbackInfo ci) { | ||
| input.getInt(VSQEntityRedstonePower.POWER_REDSTONE_KEY) | ||
| .ifPresent(power -> this.vsq$redstonePower = Mth.clamp(power, 0, 15)); | ||
| Entity entity = (Entity) (Object) this; | ||
| if (entity instanceof SulfurCube sulfurCube) { | ||
| this.vsq$redstonePower = sulfurCube.getItemBySlot(EquipmentSlot.BODY).is(Items.REDSTONE_BLOCK) ? 15 : 0; | ||
| } | ||
| this.vsq$reconcileRedstonePowerCount(); | ||
|
pxlarified marked this conversation as resolved.
|
||
| } | ||
|
|
||
| @Inject(method = "saveWithoutId", at = @At("TAIL")) | ||
| private void vsq$saveEntityRedstonePower(ValueOutput output, CallbackInfo ci) { | ||
| if (this.vsq$redstonePower > 0) { | ||
| output.putInt(VSQEntityRedstonePower.POWER_REDSTONE_KEY, this.vsq$redstonePower); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public int vsq$getRedstonePower() { | ||
| return this.vsq$redstonePower; | ||
| } | ||
|
|
||
| @Override | ||
| public void vsq$setRedstonePower(int power) { | ||
| int previousPower = this.vsq$redstonePower; | ||
| this.vsq$redstonePower = Mth.clamp(power, 0, 15); | ||
| this.vsq$reconcileRedstonePowerCount(); | ||
| this.vsq$notifyRedstonePowerChange(previousPower); | ||
| } | ||
|
|
||
| @Inject(method = "tick", at = @At("TAIL")) | ||
| private void vsq$tickEntityRedstonePower(CallbackInfo ci) { | ||
| Entity entity = (Entity) (Object) this; | ||
| this.vsq$reconcileRedstonePowerCount(); | ||
| if (!(entity.level() instanceof ServerLevel level)) { | ||
| return; | ||
| } | ||
|
|
||
| AABB currentBounds = entity.getBoundingBox(); | ||
| int currentPower = VSQEntityRedstonePower.getPower(entity); | ||
| boolean boundsChanged = this.vsq$previousRedstoneSourceBounds != null | ||
| && !this.vsq$previousRedstoneSourceBounds.equals(currentBounds); | ||
| boolean powerChanged = this.vsq$previousRedstonePower != currentPower; | ||
|
|
||
| if (this.vsq$previousRedstonePower > 0 && this.vsq$previousRedstoneSourceBounds != null | ||
| && (currentPower <= 0 || boundsChanged)) { | ||
| VSQEntityRedstonePower.updateNeighbors(level, this.vsq$previousRedstoneSourceBounds); | ||
| } | ||
|
|
||
| if (currentPower > 0) { | ||
| if (this.vsq$previousRedstoneSourceBounds == null || boundsChanged || powerChanged) { | ||
| VSQEntityRedstonePower.updateNeighbors(level, currentBounds); | ||
| } | ||
|
PainterFlow marked this conversation as resolved.
|
||
| this.vsq$previousRedstoneSourceBounds = currentBounds; | ||
| } else { | ||
| this.vsq$previousRedstoneSourceBounds = null; | ||
| } | ||
| this.vsq$previousRedstonePower = currentPower; | ||
| } | ||
|
|
||
| @Inject(method = "onRemoval", at = @At("TAIL")) | ||
| private void vsq$removeEntityRedstonePower(Entity.RemovalReason reason, CallbackInfo ci) { | ||
| Entity entity = (Entity) (Object) this; | ||
| ServerLevel level = entity.level() instanceof ServerLevel currentLevel ? currentLevel : this.vsq$redstonePowerCountedLevel; | ||
| if (level != null) { | ||
| if (this.vsq$previousRedstonePower > 0 && this.vsq$previousRedstoneSourceBounds != null) { | ||
| VSQEntityRedstonePower.updateNeighbors(level, this.vsq$previousRedstoneSourceBounds); | ||
| } else if (VSQEntityRedstonePower.getPower(entity) > 0) { | ||
| VSQEntityRedstonePower.updateNeighbors(level, entity.getBoundingBox()); | ||
| } | ||
| } | ||
|
pxlarified marked this conversation as resolved.
|
||
|
|
||
| this.vsq$unregisterRedstonePowerCount(); | ||
| this.vsq$previousRedstoneSourceBounds = null; | ||
| this.vsq$previousRedstonePower = 0; | ||
| } | ||
|
|
||
| @Unique | ||
| private void vsq$notifyRedstonePowerChange(int previousPower) { | ||
| if (previousPower == this.vsq$redstonePower) { | ||
| return; | ||
| } | ||
|
|
||
| Entity entity = (Entity) (Object) this; | ||
| if (!(entity.level() instanceof ServerLevel level)) { | ||
| return; | ||
| } | ||
|
|
||
| AABB currentBounds = entity.getBoundingBox(); | ||
| if (previousPower > 0) { | ||
| VSQEntityRedstonePower.updateNeighbors(level, | ||
| this.vsq$previousRedstoneSourceBounds != null ? this.vsq$previousRedstoneSourceBounds : currentBounds); | ||
| } | ||
| if (this.vsq$redstonePower > 0) { | ||
| VSQEntityRedstonePower.updateNeighbors(level, currentBounds); | ||
| this.vsq$previousRedstoneSourceBounds = currentBounds; | ||
| } else { | ||
| this.vsq$previousRedstoneSourceBounds = null; | ||
| } | ||
| this.vsq$previousRedstonePower = this.vsq$redstonePower; | ||
| } | ||
|
|
||
| @Unique | ||
| private void vsq$reconcileRedstonePowerCount() { | ||
| Entity entity = (Entity) (Object) this; | ||
| if (this.vsq$redstonePower > 0 && !entity.isRemoved() && entity.level() instanceof ServerLevel level) { | ||
| if (!this.vsq$redstonePowerCounted) { | ||
| VSQEntityRedstonePower.incrementPoweredEntityCount(level); | ||
| this.vsq$redstonePowerCounted = true; | ||
| this.vsq$redstonePowerCountedLevel = level; | ||
| } else if (this.vsq$redstonePowerCountedLevel != level) { | ||
| this.vsq$unregisterRedstonePowerCount(); | ||
| VSQEntityRedstonePower.incrementPoweredEntityCount(level); | ||
| this.vsq$redstonePowerCounted = true; | ||
| this.vsq$redstonePowerCountedLevel = level; | ||
|
Comment on lines
+146
to
+148
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a powered entity changes to another |
||
| } | ||
| } else { | ||
| this.vsq$unregisterRedstonePowerCount(); | ||
| } | ||
| } | ||
|
|
||
| @Unique | ||
| private void vsq$unregisterRedstonePowerCount() { | ||
| if (this.vsq$redstonePowerCounted && this.vsq$redstonePowerCountedLevel != null) { | ||
| VSQEntityRedstonePower.decrementPoweredEntityCount(this.vsq$redstonePowerCountedLevel); | ||
| } | ||
| this.vsq$redstonePowerCounted = false; | ||
| this.vsq$redstonePowerCountedLevel = null; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
|
|
||
| import blob.vanillasquared.main.world.entity.SulfurCubeBreedingState; | ||
| import blob.vanillasquared.main.world.item.VSQItems; | ||
| import blob.vanillasquared.main.world.redstone.VSQEntityRedstonePowerAccess; | ||
| import blob.vanillasquared.mixin.world.entity.CubeMobMoveControlAccessor; | ||
| import net.minecraft.core.particles.ParticleTypes; | ||
| import net.minecraft.server.level.ServerLevel; | ||
|
|
@@ -11,12 +12,14 @@ | |
| import net.minecraft.world.InteractionResult; | ||
| import net.minecraft.world.entity.AgeableMob; | ||
| import net.minecraft.world.entity.EntityType; | ||
| import net.minecraft.world.entity.EquipmentSlot; | ||
| import net.minecraft.world.entity.ExperienceOrb; | ||
| import net.minecraft.world.entity.Mob; | ||
| import net.minecraft.world.entity.ai.goal.Goal; | ||
| import net.minecraft.world.entity.ai.goal.TemptGoal; | ||
| import net.minecraft.world.entity.monster.cubemob.SulfurCube; | ||
| import net.minecraft.world.entity.player.Player; | ||
| import net.minecraft.world.item.Items; | ||
| import net.minecraft.world.item.ItemStack; | ||
| import net.minecraft.world.level.Level; | ||
| import net.minecraft.world.level.gamerules.GameRules; | ||
|
|
@@ -46,6 +49,8 @@ public abstract class SulfurCubeMixin extends AgeableMob implements SulfurCubeBr | |
| @Unique | ||
| private int vsq$breedTime; | ||
| @Unique | ||
| private int vsq$lastResolvedContentRedstonePower = -1; | ||
| @Unique | ||
| @Nullable | ||
| private ServerPlayer vsq$loveCause; | ||
|
|
||
|
|
@@ -90,7 +95,9 @@ protected SulfurCubeMixin(EntityType<? extends AgeableMob> type, Level level) { | |
| } | ||
|
|
||
| @Inject(method = "customServerAiStep", at = @At("TAIL")) | ||
| private void vsq$tickBreeding(ServerLevel level, CallbackInfo ci) { | ||
| private void vsq$customServerAiStep(ServerLevel level, CallbackInfo ci) { | ||
| this.vsq$setRedstonePowerForContent(); | ||
|
Comment on lines
+98
to
+99
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When the Sulfur Cube body slot changes outside Context Used: AGENTS.md (source) |
||
|
|
||
| if (this.getAge() != 0) { | ||
| this.vsq$resetLove(); | ||
| return; | ||
|
|
@@ -127,6 +134,18 @@ protected SulfurCubeMixin(EntityType<? extends AgeableMob> type, Level level) { | |
| @Inject(method = "readAdditionalSaveData", at = @At("TAIL")) | ||
| private void vsq$loadBreedingState(ValueInput input, CallbackInfo ci) { | ||
| this.vsq$inLove = input.getIntOr("VSQInLove", 0); | ||
| this.vsq$setRedstonePowerForContent(); | ||
| } | ||
|
PainterFlow marked this conversation as resolved.
|
||
|
|
||
| @Unique | ||
| private void vsq$setRedstonePowerForContent() { | ||
| ItemStack bodyItem = this.getItemBySlot(EquipmentSlot.BODY); | ||
| int redstonePower = bodyItem.is(Items.REDSTONE_BLOCK) ? 15 : 0; | ||
| if (redstonePower == this.vsq$lastResolvedContentRedstonePower) { | ||
| return; | ||
| } | ||
| this.vsq$lastResolvedContentRedstonePower = redstonePower; | ||
| ((VSQEntityRedstonePowerAccess) this).vsq$setRedstonePower(redstonePower); | ||
|
pxlarified marked this conversation as resolved.
|
||
| } | ||
|
pxlarified marked this conversation as resolved.
|
||
|
|
||
| @Override | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package blob.vanillasquared.mixin.world.redstone; | ||
|
|
||
| import blob.vanillasquared.main.world.redstone.VSQEntityRedstonePower; | ||
| import net.minecraft.core.BlockPos; | ||
| import net.minecraft.core.Direction; | ||
| import net.minecraft.server.level.ServerLevel; | ||
| import net.minecraft.world.level.SignalGetter; | ||
| import org.spongepowered.asm.mixin.Mixin; | ||
|
|
||
| @Mixin(ServerLevel.class) | ||
| public abstract class SignalGetterMixin implements SignalGetter { | ||
| @Override | ||
| public int getSignal(BlockPos pos, Direction direction) { | ||
| int signal = SignalGetter.super.getSignal(pos, direction); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This override calls Context Used: AGENTS.md (source) |
||
| return Math.max(signal, VSQEntityRedstonePower.getSignal((ServerLevel) (Object) this, pos)); | ||
| } | ||
|
|
||
| @Override | ||
| public int getDirectSignal(BlockPos pos, Direction direction) { | ||
| int signal = SignalGetter.super.getDirectSignal(pos, direction); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This adds the entity signal to |
||
| return Math.max(signal, VSQEntityRedstonePower.getSignal((ServerLevel) (Object) this, pos)); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.