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
CONTAINERtrust (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:
- In a claim you do not own and have no container trust in, find multi-block furniture with storage.
- Right-click an extension cell. Nothing should open.
- 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:
ServerPlayer.getBukkitEntity()(a CraftBukkit addition, public on the hybrid) → theCraftPlayer.- That object's classloader can see
org.bukkit.Bukkit→ thePluginManager. 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.