Skip to content

Port Watson to 1.21.11 + bug fixes + performance#2

Open
thehaffk wants to merge 17 commits intomasterfrom
feature/1.21.1-improvements
Open

Port Watson to 1.21.11 + bug fixes + performance#2
thehaffk wants to merge 17 commits intomasterfrom
feature/1.21.1-improvements

Conversation

@thehaffk
Copy link
Copy Markdown
Member

@thehaffk thehaffk commented Feb 23, 2026

Summary

Port Watson to Minecraft 1.21.11 (Fabric), fix critical bugs, improve rendering performance.

Based on MaximPixel's API port with our fixes on top.

1.21.11 Port (MaximPixel base — commits cd22cdc..05c4c59)

  • HoverEvent/ClickEvent record-based API
  • GuiContext instead of DrawContext for GUI widgets
  • GameProfile .name() instead of .getName()
  • Updated screenshot callback API
  • getEntityPos() / getEntityWorld() instead of getPos() / getWorld()
  • Updated dependencies: malilib 0.27.5 (pinned), mod-menu 17.x, fabric-api 0.141.3

Rendering

  • Access widener for RenderPipelines — direct field access replaces broken reflection for no-depth-test lines
  • Fixed outline buffer never submitted (drawOutline always returned 0, gating hasContent check)
  • Removed redundant GlStateManager._disableDepthTest() — pipeline handles depth test
  • VoxelShape-based block outlines — blocks render matching their actual shape (slabs, stairs, fences, etc.) instead of full cubes
  • Correct line normals via addLine() — proper direction vectors for the LINES shader instead of zero normals
  • oreLinewidth config now actually controls line thickness (was hardcoded to 2.5)
  • RenderUtils.submitBuffer() helper replacing 5 duplicate try/catch blocks

Performance

  • Batched draw calls: 1 per player instead of 1 per block (~1000x fewer draw calls)
  • O(N²) ore dedup → packed-coordinate HashSet
  • Distance culling based on view distance setting
  • Identifier.tryParse() cached per BlockEdit
  • Regex pattern caching in Analysis

Threading & safety

  • volatile on cross-thread fields: isCpMessage, _looping, colorBlock, thread
  • synchronized block around Analysis handler map iteration
  • ConcurrentHashMap for EditSelection._edits
  • mc.execute() wrapper for MC API calls in ReplayThread
  • NPE guards: WatsonRenderer, OverlayRenderer, replay(), printCommandUsage()
  • Safe cast check in MixinChatHud
  • printCommandUsage() passes real command source instead of null

Quality of life

  • Default block color: gray (#CC808080) instead of cyan — ores stand out
  • Expanded SMALLER_RENDER_BOX: 32 common terrain blocks
  • WatsonBlock.getEffectiveColor() — replaces 7 duplicate ternary expressions
  • WatsonCommandBase.printCommandUsage() — shared helper for help output
  • SyncTaskQueue throttling (max 200 tasks/tick)
  • IntCoord.hashCode() includes world for consistency with equals()
  • Static _edits cleanup on world unload (memory leak fix)
  • Removed dead isOreBlock() method

CI/CD

  • pr.yml: build + upload jar artifact on PR
  • publish.yml: build, tag, create GitHub Release with jar on push to master

Other

  • AuxProtect plugin stub (AUXPROTECT enum, empty AuxProtectAnalysis, config entries)
  • README updated with digitaldrugstech fork header
  • .gitignore for test-server/
  • malilib pinned to 0.27.5 (0.27.6 removed getOldStringValue())

Test plan

  • ./gradlew build — compiles clean
  • Client loads on 1.21.11 with Fabric + malilib 0.27.5
  • CoreProtect /co i results render 3D outlines through walls
  • Commands work without ClassCastException
  • Ore blocks render with distinct colors, terrain blocks render gray
  • Common terrain blocks render as small inner cubes (SMALLER_RENDER_BOX)
  • Block outlines match actual block shape (VoxelShape)
  • Stress test: 1000+ blocks — ~56 FPS (vs 33-36 on unoptimized build)
  • oreLinewidth config changes line thickness
  • CI builds and uploads jar artifact
  • Test with LogBlock/Prism/Ledger servers
  • Test replay functionality (/w replay)

vacla and others added 12 commits July 13, 2025 00:42
- Add volatile to static fields in CoreProtectAnalysis (_looping, isCpMessage)
- Wrap Analysis.m handler map with synchronizedListMultimap
- Synchronize iteration over handler entries in dispatchMatchedChat
- Fix handler duplication bug in removeMatchedChatHandler when key unchanged
- Add NPE guard in WatsonRenderer when getBlockEditSet() returns null
- Add NPE guard in OverlayRenderer for deposit labels and annotations
- Add instanceof check in MixinChatHud before casting Text to MutableText
- Make ReplayThread field volatile with null-safe cancelReplay
- Wrap ReplayThread MC API calls in mc.execute() for thread safety
- Cache compiled regex patterns in Analysis for better performance
- Batch all outline draw calls into single buffer per player (was 1 draw
  call per block, now 1 per player)
- Replace O(N²) isOreNotDrawn scan with packed-coordinate HashSet lookup
- Add view-distance-based culling to skip off-screen blocks
- Cache Identifier.tryParse result per BlockEdit to avoid repeated lookups
- Extract addVertex() helper in RenderUtils to eliminate ~100 duplicated
  vertex/color/normal/lineWidth call chains
- Remove dead no-op methods (renderModelQuadOutlines, renderQuadOutlinesBatched)
- Use full block outline fallback for drawBlockModelOutlinesBatched on 1.21.11
- SyncTaskQueue: add MAX_TASKS_PER_TICK (200) limit to prevent
  tick freeze when bulk-loading edits
- BlockEditSet: always log render errors (was DEBUG-only, hiding
  real issues)
- EditSelection: always log draw errors in selection renderer
- IntCoord.hashCode: include _world field for consistency with equals()
- EditSelection: clear static _edits map on disconnect to prevent memory leak
- WorldLoadListener: call EditSelection.clearAllEdits() when worldAfter is null
- CoreProtectAnalysis: compile formatting regex once (FORMATTING_PATTERN)
  instead of per-call String.replaceAll
- Add AUXPROTECT enum value to Plugins config
- Create AuxProtectAnalysis stub (patterns TBD from test server)
- Register AuxProtect handler in ChatProcessor
- Add translation keys for en_us and ru_ru
- Replace reflection with access widener for RenderPipelines fields
  (fixes NoSuchFieldException due to intermediary mapping mismatch)
- Fix ClientCommandSource ClassCastException in all command handlers
  by using raw CommandDispatcher and removing ServerCommandSource deps
- Fix outline rendering: remove hasContent gate that prevented buffer
  submission (drawOutline always returned 0)
- Change default block color from cyan to gray for better visibility
- Expand SMALLER_RENDER_BOX defaults with common terrain blocks
- Extract printCommandUsage() helper to WatsonCommandBase, removing
  duplicate @SuppressWarnings code from 4 command classes
- Add WatsonBlock.getEffectiveColor() to replace 7 repeated ternaries
- Make Analysis.colorBlock volatile for thread safety
- Replace HashMap with ConcurrentHashMap for EditSelection._edits
- Remove redundant GlStateManager depth test calls from WatsonRenderer
  (now handled by RenderLayer pipeline)
- Add RenderUtils.submitBuffer() helper, replacing 5 duplicate
  try/endNullable/draw/close blocks
- Use addVertex() + submitBuffer() in EditSelection.drawSelection()
Co-Authored-By: felix.haffk <felix.haffk@digitaldrugs.tech>
Co-Authored-By: felix.haffk <felix.haffk@digitaldrugs.tech>
@thehaffk thehaffk force-pushed the feature/1.21.1-improvements branch from 9abd0a1 to 72bc38b Compare February 23, 2026 15:19
- drawBlockModelOutlinesBatched now renders actual block shape via
  VoxelShape instead of falling back to full cube
- Pin malilib dependency to 0.27.5 (0.27.6 removed getOldStringValue)
- Add test-server/ to .gitignore
- replay() NPE guard on getBlockEditSet() null return
- printCommandUsage() passes real command source instead of null
- addVertex replaced with addLine — correct normals for LINES shader
- Remove dead isOreBlock() method
- detailsSign uses getEffectiveColor() consistently
…orts

- Wire ORE_OUTLINE_THICKER config to double line width when enabled
- Remove unused blockModelShapes field and MC client init from BlockEdit
- Remove duplicate javadoc on addLine method
- Remove unused imports: BlockStateModel, RenderSystem, BuiltBuffer, WatsonRenderLayers
Two bugs fixed:
- Queue not cleared on new inspector/lookup, causing old autopage
  commands to fire when user starts a new query
- firstMessage=true on autopage requests added unnecessary 1-second
  delay before first page request by resetting the send timer

Changes:
- Add ChatMessage.clearQueue() to discard pending autopage messages
- Clear queue on inspectorCoords() and lookupHeader() entry
- Clear queue on CoreProtectAnalysis.reset()
- Pass firstMessage=false for all autopage requests in Paginator
- Reset firstPageLoop flag in Paginator.reset()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants