Skip to content
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

Allow entities to be "immutable" by default #20

Merged
merged 5 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ authors=jaskarth, unascribed
contributors=Patbox, IThundxr
license=AGPL-3.0-or-later
# Mod Version
baseVersion=0.6.1
baseVersion=0.6.2
# Branch Metadata
branch=1.21
tagBranch=1.21
Expand Down
14 changes: 10 additions & 4 deletions src/main/java/net/modfest/fireblanket/Fireblanket.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
import net.fabricmc.fabric.api.entity.event.v1.ServerEntityWorldChangeEvents;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.fabricmc.fabric.api.event.registry.RegistryEntryAddedCallback;
import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory;
import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
import net.fabricmc.fabric.api.networking.v1.ServerLoginConnectionEvents;
Expand All @@ -28,6 +29,7 @@
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.GameRules;
import net.modfest.fireblanket.command.CmdFindReplaceCommand;
import net.modfest.fireblanket.command.DumpCommand;
import net.modfest.fireblanket.command.RegionCommand;
Expand All @@ -49,9 +51,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
Expand All @@ -61,6 +60,13 @@ public class Fireblanket implements ModInitializer {
public static final Identifier FULL_STREAM_COMPRESSION = Identifier.of("fireblanket", "full_stream_compression");
public static final Identifier REGIONS_UPDATE = Identifier.of("fireblanket", "regions_update");

/**
* Whether new entities will be fixed.
* @see net.modfest.fireblanket.mixin.entity_immutability
*/
public static final GameRules.Key<GameRules.BooleanRule> NEW_ENTITIES_IMMUTABLE =
GameRuleRegistry.register("newEntitiesImmutable", GameRules.Category.MOBS, GameRuleFactory.createBooleanRule(true));

public static final Logger LOGGER = LoggerFactory.getLogger("Fireblanket");

public record QueuedPacket(ClientConnection conn, Packet<?> packet, PacketCallbacks listener) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package net.modfest.fireblanket.mixin.accessor;

import net.minecraft.entity.decoration.ArmorStandEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(ArmorStandEntity.class)
public interface ArmorStandEntityAccessor {
@Accessor
void setDisabledSlots(int d);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package net.modfest.fireblanket.mixin.accessor;

import net.minecraft.entity.decoration.ItemFrameEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(ItemFrameEntity.class)
public interface ItemFrameAccessor {
@Accessor
void setFixed(boolean v);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package net.modfest.fireblanket.mixin.adventure_fix;

import net.minecraft.block.BlockState;
import net.minecraft.block.FarmlandBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(FarmlandBlock.class)
public class MixinFarmlandBlock {
@Inject(
method = "setToDirt",
at = @At("HEAD"),
cancellable = true
)
private static void doNotSetToDirt(@Nullable Entity entity, BlockState state, World world, BlockPos pos, CallbackInfo ci) {
if (entity instanceof PlayerEntity player && !player.canModifyBlocks()) {
ci.cancel();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package net.modfest.fireblanket.mixin.entity_immutability;

import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.entity.decoration.AbstractDecorationEntity;
import net.minecraft.item.DecorationItem;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.util.ActionResult;
import net.modfest.fireblanket.Fireblanket;
import net.modfest.fireblanket.util.ImmutableEntities;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(DecorationItem.class)
public class MixinDecorationItem {
@Inject(method = "useOnBlock(Lnet/minecraft/item/ItemUsageContext;)Lnet/minecraft/util/ActionResult;", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getOrDefault(Lnet/minecraft/component/ComponentType;Ljava/lang/Object;)Ljava/lang/Object;"))
private void onInitSpawnedEntity(ItemUsageContext context, CallbackInfoReturnable<ActionResult> cir, @Local AbstractDecorationEntity entity) {
if (context.getWorld().getGameRules().getBoolean(Fireblanket.NEW_ENTITIES_IMMUTABLE)) {
ImmutableEntities.makeImmutable(entity);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package net.modfest.fireblanket.mixin.entity_immutability;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.SpawnReason;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.modfest.fireblanket.Fireblanket;
import net.modfest.fireblanket.util.ImmutableEntities;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

import java.util.function.Consumer;

@Mixin(EntityType.class)
public class MixinEntityType {
@WrapOperation(method = "create(Lnet/minecraft/server/world/ServerWorld;Ljava/util/function/Consumer;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/SpawnReason;ZZ)Lnet/minecraft/entity/Entity;", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/EntityType;create(Lnet/minecraft/world/World;)Lnet/minecraft/entity/Entity;"))
private Entity afterCreated(EntityType<?> instance, World world, Operation<Entity> original, ServerWorld world2, @Nullable Consumer<Entity> afterConsumer, BlockPos pos, SpawnReason reason, boolean alignPosition, boolean invertY) {
var entity = original.call(instance, world);
if (world.getGameRules().getBoolean(Fireblanket.NEW_ENTITIES_IMMUTABLE) && reason == SpawnReason.SPAWN_EGG) {
if (entity != null) {
ImmutableEntities.makeImmutable(entity);
}
}
return entity;
}
}
27 changes: 27 additions & 0 deletions src/main/java/net/modfest/fireblanket/util/ImmutableEntities.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package net.modfest.fireblanket.util;

import net.minecraft.entity.Entity;
import net.modfest.fireblanket.mixin.accessor.ArmorStandEntityAccessor;
import net.modfest.fireblanket.mixin.accessor.ItemFrameAccessor;
import net.modfest.fireblanket.mixinsupport.ImmmovableLivingEntity;

public class ImmutableEntities {
public static void makeImmutable(Entity entity) {
// Set invulnerability
entity.setInvulnerable(true);

if (entity instanceof ArmorStandEntityAccessor ae) {
// Disable all slots
ae.setDisabledSlots(4144959);
// Disable movement (prevents abuse of fishing rods)
if (entity instanceof ImmmovableLivingEntity im) {
im.setNoMovement(true);
}
}

if (entity instanceof ItemFrameAccessor ie) {
// Make item frames fixed
ie.setFixed(true);
}
}
}
5 changes: 3 additions & 2 deletions src/main/resources/assets/fireblanket/lang/en_us.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"argument.entity.selector.limit.unforced": "Targeting too many entities with no distance filter; add `force=true` to the selector to bypass",
"argument.entity.options.force.description": "Force-allow more than 50 entities targeted with no distance filter"
}
"argument.entity.options.force.description": "Force-allow more than 50 entities targeted with no distance filter",
"gamerule.newEntitiesImmutable": "Whether newly spawned entities should be immutable. (Item frames will be fixed for example"
}
13 changes: 9 additions & 4 deletions src/main/resources/fireblanket.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,30 @@
"compatibilityLevel": "JAVA_17",
"plugin": "net.modfest.fireblanket.FireblanketMixin",
"mixins": [
"accessor.ArmorStandEntityAccessor",
"accessor.BlockEntityTypeAccessor",
"accessor.ClientConnectionAccessor",
"accessor.EntityTypeAccessor",
"accessor.ItemFrameAccessor",
"accessor.ServerChunkManagerAccessor",
"accessor.ServerLoginNetworkHandlerAccessor",
"adventure_fix.MixinItemStack",
"adventure_fix.MixinItemStack",
"adventure_fix.MixinPlayerInteractEntityC2SPacketHandler",
"adventure_fix.MixinServerPlayerInteractionManager",
"adventure_fix.MixinFarmlandBlock",
"ai.MixinTemptGoal",
"be_sync.MixinBlockEntity",
"be_sync.MixinChunkHolder",
"block.MixinCommandBlock",
"block_format.MixinChunkSection",
"entity_immutability.MixinDecorationItem",
"entity_immutability.MixinEntityType",
"entity_ticking.MixinDebugStickItem",
"entity_ticking.MixinEntity",
"entity_ticking.MixinItemGroups",
"entity_ticking.MixinLivingEntity",
"entity_ticking.MixinMinecraftServer",
"entity_ticking.MixinServerChunkLoadingManager",
"mods.create.MixinSuperGlueEntity",
"footgun.MixinEntitySelectorOptions",
"footgun.MixinEntitySelectorReader",
"fsc.MixinClientConnection",
Expand All @@ -32,6 +36,7 @@
"io_uring.MixinServerNetworkIo",
"mods.create.AccessorSmartBlockEntity",
"mods.create.MixinMechanicalBearingBlockEntity",
"mods.create.MixinSuperGlueEntity",
"mods.mythicmetals.MixinCarmotShield",
"mods.pehkui.MixinScaleUtils",
"mods.pswg.MixinComplexCollisionManager",
Expand Down Expand Up @@ -61,7 +66,6 @@
"client.adventure_fix.MixinClientPlayerInteractionManager",
"client.be_masking.MixinBlockEntityRenderDispatcher",
"client.be_masking.MixinRebuildTask",
"mods.masking.sodium.MixinChunkRenderRebuildTask",
"client.bufferbuilder_opto.MixinBufferBuilder",
"client.bufferbuilder_opto.MixinVertexFormat",
"client.entity_masking.MixinEntityRenderer",
Expand All @@ -79,6 +83,7 @@
"client.vbo_opto.MixinShaderProgram",
"client.vbo_opto.MixinVertexBuffer",
"gamemode_selection.MixinKeyboard",
"gamemode_selection.MixinSelectionScreen"
"gamemode_selection.MixinSelectionScreen",
"mods.masking.sodium.MixinChunkRenderRebuildTask"
]
}