Skip to content

Fixed pasting a color config not applying it - #6659

Merged
Wide-Cat merged 1 commit into
MeteorDevelopment:masterfrom
c8dhjp4tyv-bit:fix/color-paste-not-applied
Sep 13, 2026
Merged

Wide-Cat merged 1 commit into
MeteorDevelopment:masterfrom
c8dhjp4tyv-bit:fix/color-paste-not-applied

Conversation

@c8dhjp4tyv-bit

@c8dhjp4tyv-bit c8dhjp4tyv-bit commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Type of change

  • Bug fix
  • New feature

Description

Copying a colour config and pasting it into another one appears to work in the colour picker, but the value never reaches the setting's owner. In Block ESP the pasted block config is dropped entirely and falls back to the default.

NbtUtils.fromClipboard(ISerializable) deserialises onto the existing object:

serializable.fromTag(tag);

So NbtUtils.fromClipboard(setting.get()) mutates the SettingColor in place. It never goes through Setting#set or Setting#fromTag, both of which call onChanged() — and fromClipboard() did not call it either:

if (!NbtUtils.fromClipboard(setting.get())) {
    ...
    setting.set(parsed);   // <- this branch DOES notify
}

setting.get().validate();  // <- ...the NBT branch never did

Every other mutation path in this screen notifies the setting afterwards — rgbaChanged(), hsvChanged(), the rainbow checkbox and the reset button all end in setting.onChanged(). Paste was the only one that did not, and only on the NBT branch, which is the branch the copy button produces.

Settings whose value object is read directly still looked fine, because the mutated object is the live one. Settings that rely on their onChanged callback to propagate the value did not:

  • ESPBlockDataScreen — the callback copies the colour into the ESPBlockData and runs firstChangeConsumer, which is what puts the block into BlockDataSetting's map. Without it the block is never registered, so it renders with the default config. This is the reported symptom.
  • DefaultSettingsWidgetFactory#colorListWFill — the callback writes back into the list entry (setting.get().get(_i).set(settingColor)), so pasting into a colour-list entry did nothing.
  • BaritoneSettings — the callback mirrors the colour into the Baritone setting.

The fix notifies the setting on the NBT branch. Two notes on the rest of the diff:

  • callAction() now runs on both branches, matching the reset button and the other mutation paths. It is a no-op in-tree (nothing assigns action), but it is public API and paste is a value change like any other.
  • The trailing validate() moves into the NBT branch rather than running unconditionally. It is not load-bearing in either branch — Color#fromTag already validates, and the parse branch validates through Setting#setColorSetting#isValueValid before onChanged() runs — but keeping it on the branch that mutates in place makes the "valid before the callback sees it" invariant explicit where Setting is not doing it for us.

Related issues

Closes #6511

How Has This Been Tested?

./gradlew compileJava passes.

I modelled the Setting / SettingColor / ESPBlockDataScreen wiring in isolation and pasted (255, 0, 128, 255) into a block config:

BEFORE fix: ui color (255,0,128,255) | blockData.lineColor (0,255,200,255) | stored in map: false
AFTER  fix: ui color (255,0,128,255) | blockData.lineColor (255,0,128,255) | stored in map: true

The picker shows the pasted colour either way — which is why it looks like it worked — but before the fix the block data keeps the default and is never added to the map, exactly as described in #6511.

In-game: Block ESP → block configs → pick a block → change the colour → copy → pick another block → paste → back. The second block now keeps the pasted colour instead of resetting. Colour-list entries and normal module colour settings paste correctly too, and copy/paste on a plain module colour behaves as before.

Checklist:

  • My code follows the style guidelines of this project.
  • I have added comments to my code in more complex areas.
  • I have tested the code in both development and production environments.

NbtUtils.fromClipboard(ISerializable) deserialises onto the existing object,
so pasting NBT mutated the SettingColor in place without ever going through
Setting#set and therefore without firing onChanged(). Every other mutation
path in the screen (the RGBA boxes, the hue and brightness quads, the rainbow
checkbox, the reset button) notifies the setting afterwards; paste did not.

Settings whose value object is read directly appeared to work, but any
setting that relies on its onChanged callback to propagate the value silently
kept the old colour. In Block ESP that callback is also what registers the
block in the map, so pasting a block config fell back to the default.

Notify the setting on the NBT branch, and run the screen's action on both
branches so paste is consistent with the other mutation paths. The trailing
validate() moves into the NBT branch: the parse branch already validates
through Setting#set -> ColorSetting#isValueValid.
@c8dhjp4tyv-bit
c8dhjp4tyv-bit force-pushed the fix/color-paste-not-applied branch from 57257d5 to c726b00 Compare September 13, 2026 05:08
@Wide-Cat
Wide-Cat merged commit 3963fb8 into MeteorDevelopment:master Sep 13, 2026
1 check passed
@c8dhjp4tyv-bit
c8dhjp4tyv-bit deleted the fix/color-paste-not-applied branch September 13, 2026 17:11
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.

[Bug] Paste color config on Block Esp doesn't work

2 participants