Skip to content

Immersive Furniture GD Guard

Closes a GriefDefender bypass in Immersive Furniture: on furniture wider than one block, players without container trust could open the chest by clicking an extension cell. This mod blocks that.

What it does

  • Every attempt to open an Immersive Furniture container is checked against GriefDefender at the furniture's base block.
  • Allowed: no claim, wilderness, the claim owner, players with CONTAINER trust (user, group or public), and anyone with a configured bypass.
  • Blocked: everyone else. Nothing opens; there is no message.
  • Only opening the container is checked. Sitting, sleeping and toggling furniture work as before.
  • If GriefDefender is not installed, the mod does nothing.

Server-side only. Clients install nothing. Built for the Youer hybrid with GriefDefender.

How players use it

Players do not interact with this mod. Furniture storage in a claim now follows the claim's trust, like any chest.

Staff guide

There are no commands. To give a player access to furniture storage in a claim, give them container trust in GriefDefender (for example /trust <player> container while standing in the claim).

To test it, use a non-op account, or set opBypass=false, because ops bypass the check by default:

  1. In a claim you do not own and have no container trust in, find multi-block furniture with storage.
  2. Right-click an extension cell. Nothing should open.
  3. Check that the owner and a container-trusted player can still open it.

Turn on debug=true to see an ALLOW or DENY line in the log for every open.

Configuration

config/ifgdguard.properties, written with defaults on first start and read once at boot. A JVM flag -Difgdguard.<key>=<value> overrides the file. Restart after changes.

Key Default Effect
debug false Log an ALLOW or DENY line for every decision
failClosed false Block opens when the GriefDefender check itself fails
opBypass true Ops always get through
bypassPermission (empty) Permission node whose holders always get through

The file exists because the panel owns the server's startup command, so JVM flags are often impossible to set; a file can be dropped in over SFTP.

Data and storage

None.

Troubleshooting

Symptom Cause Fix
Untrusted players can still open furniture storage Version 1.0.0 could not see GriefDefender and did nothing Use 1.1.0 or later. With debug=true you should see ALLOW/DENY lines
Owners cannot open their own furniture failClosed=true and the GriefDefender check is failing Look for the warning naming the failed step. Set failClosed=false
Test shows no effect Testing as op with opBypass=true Use a non-op account
A piece across a claim border behaves oddly The decision uses the base block only Expected. Move the furniture

Boot line: [ifgdguard] loaded - Immersive Furniture container opens are now gated through the protection bridge. The GriefDefender connection is made on the first furniture open, not at boot; it logs [ifgdguard] GriefDefender API bound successfully.

If GriefDefender is present but cannot be reached (for example after a version change) or a check throws, the mod allows the open and logs a warning naming the failed step, so owners are never locked out. failClosed=true reverses that.

Maintainer notes

The bug

Immersive Furniture builds multi-block furniture from a base block plus FurnitureProxyBlock "proxy" cells. A click on a proxy cell is forwarded directly into the base block's EntityFurnitureBlock.useWithoutItem(...), which ends in player.openMenu(blockEntity).

On the hybrid, a direct click on the base block is gated by the protection plugin, but the forwarded proxy-cell path reaches openMenu without producing the interaction event GriefDefender can cancel. So on any furniture wider than one block, the extension cells open the chest even for players who have no container trust. No GriefDefender flag, override, or trust change fixes this - the open never reaches GD.

The fix

One mixin, EntityFurnitureBlockMixin, @Redirects the single player.openMenu(...) call inside useWithoutItem. Because both the base click and every proxy-cell click funnel through that call, redirecting it gates the whole footprint. The redirect asks ProtectionBridge whether the player may open a container at the furniture's real position; if not, it returns OptionalInt.empty() and no screen opens.

@Redirect (not a blanket HEAD cancel) is deliberate, only the container open is gated. Sitting, sleeping, and toggle interactions are untouched. Claim owners and container-trusted players are unaffected.

Classloaders: why every lookup starts from a live object

A mod on Youer cannot reach Bukkit plugin classes by name. Mods are loaded by FML's transforming classloader; Bukkit plugins each get a child PluginClassLoader. A bare Class.forName("com.griefdefender.api.GriefDefender") therefore throws ClassNotFoundException - which is exactly how version 1.0.0 of this mod became a silent no-op: it reported GriefDefender not detected on a server where GD was enabled and working.

Resolution instead walks outward from objects handed to us at runtime:

  1. ServerPlayer.getBukkitEntity() (a CraftBukkit addition, public on the hybrid) → the CraftPlayer.
  2. That object's classloader can see org.bukkit.Bukkit → the PluginManager.
  3. PluginManager.getPlugin("GriefDefender") → the plugin instance, whose classloader is the one that can see the GD API.

GD API types are then resolved as interfaces (Core, ClaimManager, Claim) rather than off implementation objects, so non-public impl classes can't break the binding.

Note also that GD relocates its shaded libraries: Vector3i lives at com.griefdefender.lib.flowpowered.math.vector.Vector3i. This mod uses ClaimManager.getClaimAt(int, int, int) so no relocated type is ever referenced.

Compatibility

The mixin targets EntityFurnitureBlock#useWithoutItem and the Player#openMenu(MenuProvider) call inside it. Checked identical in Immersive Furniture 0.1.3, 0.2.2 and 0.3.0 for 1.21.1. Recheck when the furniture mod updates. A related GriefDefender gap for trapdoors, doors and levers is covered by a different mod; see documentation/mods/gd-interact-guard.md in the ops repo.

Building

cp immersive_furniture-neoforge-<version>+1.21.1.jar libs/
./gradlew build

JDK 21. Immersive Furniture is not included in this repo; put the jar that matches the server in libs/ first. Output: build/libs/ifgdguard-neoforge-1.21.1-<version>.jar. Install next to Immersive Furniture in each backend's mods/ and restart. The mod is declared Dist.DEDICATED_SERVER, so clients are not asked for it.

GPL-3.0-only, matching Immersive Furniture. Not affiliated with the Immersive Furniture author.

Full command, permission and config tables: Reference.