promotional bannermobile promotional banner

ProtectionBlocks

ProtectionBlocks allows players to secure their builds with customizable protection blocks and manage permissions with ease.
Back to Files

protectionblocks-1.0.9.jar

File nameprotectionblocks-1.0.9.jar
Uploader
ReaperFtxReaperFtx
Uploaded
Jul 4, 2026
Downloads
31
Size
8.4 MB
Mod Loaders
Forge
File ID
8369334
Type
R
Release
Supported game versions
  • 1.20.1

Curse Maven Snippet

Forge

implementation fg.deobf("curse.maven:protection-blocks-1351203:8369334")

Learn more aboutΒ Curse Maven

What's new

πŸš€ v1.0.9 β€” Admin UX polish & several fixes

Focus release on tightening the admin experience: the ConfigScreen and the block management GUI got a batch of small-but-important quality-of-life improvements, and a handful of nasty bugs from 1.0.8 got hunted down (including one where "Sin permisos" for an ally silently didn't apply). New admin command /protection grantfreetime to bypass the "once per player" limit on the free-time bonus when testing.


πŸ†• New admin tools

  • /protection grantfreetime <player> <hours> β€” OP-only. Overrides the VeteranPlayerTracker pool of the target player: sets their remaining free time to the given number of hours (0 = cut without removing the veteran flag). Bypasses the "once per player" rule so you can re-test the mechanic on any player, including those who already burned through their bonus. After applying, the mod broadcasts a fresh SyncFuelStatePacket to all the target's blocks so any open GUI reflects the change instantly.
  • /protection diag extended β€” the block diagnostic now dumps the full free-time state: graceGlobal, gracePersonal, graceEffective (all with a human-readable "23h 45m 12s remaining" or "expired X ago"), isInPersonalGrace, lastConsumeMs, plus ownerIsVeteran and the current newPlayerGraceHours config value. Everything you need to answer "why is / isn't this player's block in grace right now?" with a single command.

🎨 Admin ConfigScreen polish

In-GUI toast notifications

Chat confirmations were unreadable behind the dark admin panel. Replaced by proper toast cards that float centered just above the Save/Cancel buttons.

  • Card style follows the ModernUI system β€” dark background, 2px accent border on top (green for success, amber for warning), horizontally centered icon (βœ“/⚠/β„Ή) + text.
  • Auto-dismiss after 4s with a fade-out in the final 500ms.
  • Server-side sendSystemMessage to the admin sender was suppressed for the confirmed actions (config saved, grace granted, grace cancelled). The toast now owns the feedback loop; the chat stays clean.
  • The broadcast to other players (global grace grant/cancel) is untouched β€” they still get the chat message.

Auto-disable everything when currency mode is OFF

Toggling off "Activar modo moneda" now visually and functionally disables the rest of the Currency tab in real time, so admins can't accidentally change values that won't matter.

  • All EditBoxes call setEditable(false) as well as .active = false β€” in vanilla 1.20.1, .active alone doesn't visibly gray out an EditBox; you have to flip the editable flag to get the muted textColorUneditable.
  • All buttons gray out via the vanilla .active flag.
  • LabelWidget now respects its own .active: when off it forces a muted 0x555F6A color, overriding any inline Style the Component might carry (so the blue-accented "Tiempo gratis" hint header also dims properly).
  • The 5 tier-cost lines and the grace countdown, both drawn manually each frame, also render muted when currency mode is OFF for coherence.
  • The checkbox is a subclass with an onPress override that flips draft.enableCurrencyMode AND runs setCurrencyDependentActive(selected) immediately β€” before this the draft was only committed on Save so the toggle appeared "dead" until you saved.

Global grace broadcasts to all online players

  • Grant global free time β†’ all online players (not just the admin) receive a chat message: "🎁 The admin granted X of global free time β€” your blocks won't consume fuel during that period." (5 langs, in gold).
  • Cancel global free time β†’ same treatment: "Global free time was cancelled by the admin." (in yellow).
  • Also, granting global grace now broadcasts a fresh SyncFuelStatePacket to every loaded block just like cancel already did. Before, the cancel side was instant on other players' open GUIs while grant was not β€” the label update on other clients had to wait for the next fuel tick or a GUI reopen.

🎨 Block management GUI polish

Fuel label: "1 item = HH:MM:SS" instead of "0.017x/min"

The fuel state line used to say "Combustible: agotado (0.017x Iron ingot/min)" β€” an unintuitive ratio the admin had to divide mentally to understand. It now says "Combustible: agotado (1 Iron ingot = 00H:58M:49S)" β€” the duration a single unit lasts, formatted as a stable-width clock.

  • New helper formatOneUnitDurationHMS(costPerMin) = 60 / costPerMin seconds, formatted as NNH:NNM:NNS with zero-padding.
  • The H, M, S letters render in a distinct pastel-blue accent color (#AED6F1), while the digits keep the fuel state color (green/amber/red). Built via styled Component args to Component.translatable so drawString(Component) respects the per-segment Style.
  • Ratio ≀ 0 renders --.

Ally picker input polish

  • Typing now auto-focuses the search input right when the picker opens β€” no more click-to-focus. Fixed by deferring the setFocused to the first render frame after opening; before, Screen.mouseClicked was resetting the focus back to the "+ Add ally" button at the end of the click cycle, silently overriding our call.
  • New CenteredEditBox subclass: text is centered horizontally and vertically in the input via a translate before super.render. Vanilla unbordered EditBox pins the text to the top-left corner; the shift math replicates what bordered mode would do.

πŸ› Fixed

  • "Sin Permisos" silently didn't apply. Setting an ally to "no permissions" via the dropdown left them with their previous rights β€” they could still build/break as before. Root cause: EnumSet.copyOf(Collection) throws IllegalArgumentException when the collection is not itself an EnumSet AND is empty (documented but easy to miss). UpdatePermissionsPacket decodes into a plain HashSet; an empty "no permissions" arrived as an empty HashSet; AllyData.setPermissions tried EnumSet.copyOf(emptyHashSet) and threw. The exception was silently swallowed inside the packet handler's enqueueWork, so updateAllyPermissions never ran. Fixed by building an EnumSet.noneOf(PermissionType.class) and using addAll β€” works for both empty and non-empty inputs without special-casing.
  • Grant global grace was NOT real-time on other players. Cancel broadcast a fresh SyncFuelStatePacket to every loaded block so open GUIs updated instantly; grant broadcast the chat message but forgot the fuel state. Result: cancelling was instant on other players' open GUIs, granting only appeared after the next fuel tick or a GUI reopen. Extracted the two-line broadcast logic into a helper (broadcastFreshFuelStateAll) and called from both paths.
  • Cancel of global grace was clearing personal grace timestamps too. A previous attempt to fix the "grace shows 24h after cancel" symptom accidentally also cleared the per-player free time pool. Reverted: cancel only touches GracePeriodManager (the global admin grace), VeteranPlayerTracker is untouched. The "shows 24h after cancel" symptom is now fixed a different way β€” the broadcast of the fresh fuel state (see above) makes clients re-read getEffectiveGraceUntilMs = max(0, personalOfOwner) immediately, so what the client sees is the actual remaining personal grace (not the stale cached global timestamp).
  • Toast card was showing two βœ“ marks. The lang strings started with a hardcoded "βœ“ …" carried over from when notifications were plain drawString. The card renders its own icon per type; the extra βœ“ in the text was redundant. Stripped in all 5 langs.
  • Free-time hint clarified. "(los depΓ³sitos se consumen al terminar)" was ambiguous β€” several users interpreted it as "there IS consumption". Changed in all 5 langs to "(el combustible NO se consume mientras tanto)" β€” explicit statement that fuel is preserved for the duration of the grace window. Same rewording (with the appropriate wording) applied to en_us, de_de, fr_fr, it_it.

πŸ”§ Under the hood

  • VeteranPlayerTracker: new forceSetGraceUntilMs(uuid, endMs) that overrides the pool ignoring the "already veteran" rule β€” used by /protection grantfreetime. Kept private-friendly so gameplay code keeps using grantOnce.
  • DepositFuelPacket.broadcastState was package-private; upgraded to public so the command layer can call it directly instead of duplicating the packet build.
  • LabelWidget.renderWidget: adds an active-aware branch. Active β†’ keeps the Component's Style. Inactive β†’ renders the plain String ignoring Style, forcing a muted color.
  • New CenteredEditBox in the GUI package: only overrides render with a translate. Hitbox, focus, keyboard handling, everything else inherited from vanilla EditBox.
  • ConfigScreen: currencyDependentWidgets list + setCurrencyDependentActive(boolean). All labels routed through a new addCurrencyLabel helper so they get registered in the list automatically. setEditable is toggled on EditBoxes in addition to .active β€” vanilla 1.20.1 doesn't gray out EditBoxes on .active = false alone.
  • Ally-picker focus fix: new pickerFocusPending flag. openAddAllyPicker sets it to true, renderAddAllyPicker applies the focus on the first frame after the picker opens (when the button's mouseClicked cycle has finished and can no longer overwrite it).

πŸ“¦ Compatibility

  • Minecraft 1.20.1
  • Forge 47.x (built against 47.4.8)
  • Fully compatible with 1.0.8 worlds β€” no data migration.

Β© 2026 vicxelcode β€” MIT License

This mod has no additional files