Skip to content

Commit 26d8fd4

Browse files
committed
ChestSearch Bug Fix
1 parent 3673bee commit 26d8fd4

File tree

6 files changed

+286
-79
lines changed

6 files changed

+286
-79
lines changed

src/main/java/net/wurstclient/WurstClient.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,18 @@ public EventManager getEventManager()
180180
public void saveSettings()
181181
{
182182
settingsFile.save();
183+
// Also persist chest search cleaner config from ChestSearchHack
184+
try
185+
{
186+
net.wurstclient.hacks.ChestSearchHack csh =
187+
getHax().chestSearchHack;
188+
net.wurstclient.chestsearch.ChestConfig cc =
189+
new net.wurstclient.chestsearch.ChestManager().getConfig();
190+
cc.graceTicks = csh.getCleanerGraceTicks();
191+
cc.scanRadius = csh.getCleanerScanRadius();
192+
cc.save();
193+
}catch(Throwable ignored)
194+
{}
183195
}
184196

185197
public ArrayList<Path> listSettingsProfiles()

src/main/java/net/wurstclient/chestsearch/ChestCleaner.java

Lines changed: 156 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ public class ChestCleaner
1919
{
2020
private final ChestManager manager;
2121
private int tickCounter = 0;
22+
// ticks since we last observed a world/server change; used for grace
23+
// period after joining/reloading
24+
private int ticksSinceWorldObserved = 0;
25+
private String lastServer = null;
26+
private String lastDimension = null;
27+
// defaults (will be read from config at runtime)
2228

2329
public ChestCleaner()
2430
{
@@ -39,6 +45,37 @@ public void register()
3945
MinecraftClient mc = WurstClient.MC;
4046
if(mc == null || mc.world == null)
4147
return;
48+
49+
// update world/server observation ticks and detect join/world
50+
// changes
51+
String curServer = null;
52+
try
53+
{
54+
if(mc.getCurrentServerEntry() != null)
55+
curServer = mc.getCurrentServerEntry().address;
56+
}catch(Throwable ignored)
57+
{}
58+
String curDimension = null;
59+
try
60+
{
61+
curDimension =
62+
mc.world.getRegistryKey().getValue().toString();
63+
}catch(Throwable ignored)
64+
{}
65+
// reset grace timer on server/dimension change
66+
if(lastServer == null || !lastServer.equals(curServer)
67+
|| lastDimension == null
68+
|| !lastDimension.equals(curDimension))
69+
{
70+
ticksSinceWorldObserved = 0;
71+
lastServer = curServer;
72+
lastDimension = curDimension;
73+
}else
74+
{
75+
// increase observed ticks
76+
ticksSinceWorldObserved += 100; // we check every 100 ticks
77+
// interval
78+
}
4279

4380
String serverIp = null;
4481
try
@@ -66,44 +103,131 @@ public void register()
66103
continue;
67104
try
68105
{
69-
BlockPos pos = e.getMinPos();
70-
boolean chunkLoaded = false;
71-
try
106+
// read configured values
107+
int configuredGrace = manager.getConfig() == null ? 200
108+
: manager.getConfig().graceTicks;
109+
int configuredRadius = manager.getConfig() == null ? 64
110+
: manager.getConfig().scanRadius;
111+
// Only check entries when player is within scan radius
112+
// or when within the grace period after joining.
113+
if(ticksSinceWorldObserved < configuredGrace)
72114
{
73-
@SuppressWarnings("deprecation")
74-
boolean tmp = mc.world.isChunkLoaded(pos);
75-
chunkLoaded = tmp;
76-
}catch(Throwable ignored)
115+
// during grace period avoid deletions
116+
continue;
117+
}
118+
119+
// Determine canonical bounds for the recorded chest
120+
int minX = Math.min(e.x, e.maxX);
121+
int minY = Math.min(e.y, e.maxY);
122+
int minZ = Math.min(e.z, e.maxZ);
123+
int maxX = Math.max(e.x, e.maxX);
124+
int maxY = Math.max(e.y, e.maxY);
125+
int maxZ = Math.max(e.z, e.maxZ);
126+
127+
// compute distance from player to nearest point in
128+
// bounds
129+
BlockPos playerPos = mc.player.getBlockPos();
130+
int px = playerPos.getX();
131+
int py = playerPos.getY();
132+
int pz = playerPos.getZ();
133+
int closestX = Math.max(minX, Math.min(px, maxX));
134+
int closestY = Math.max(minY, Math.min(py, maxY));
135+
int closestZ = Math.max(minZ, Math.min(pz, maxZ));
136+
long dx = px - closestX;
137+
long dy = py - closestY;
138+
long dz = pz - closestZ;
139+
long distSq = dx * dx + dy * dy + dz * dz;
140+
if(distSq > (long)configuredRadius * configuredRadius)
141+
{
142+
// player too far to reliably observe this chest
143+
continue;
144+
}
145+
146+
boolean anyChunkNotLoaded = false;
147+
boolean anyContainerPresent = false;
148+
149+
// Iterate all block positions inside the recorded
150+
// bounds.
151+
// If any overlapping chunk is not loaded, skip
152+
// deletion.
153+
// If any block in the bounds is a container and has a
154+
// block entity,
155+
// skip deletion. Only delete when all chunks are loaded
156+
// and
157+
// NO matching container+block-entity exists in the
158+
// bounds.
159+
outer: for(int bx = minX; bx <= maxX; bx++)
77160
{
78-
try
161+
for(int by = minY; by <= maxY; by++)
79162
{
80-
Object cm = mc.world.getChunkManager();
81-
java.lang.reflect.Method m =
82-
cm.getClass().getMethod("isChunkLoaded",
83-
int.class, int.class);
84-
chunkLoaded = Boolean.TRUE.equals(m.invoke(cm,
85-
pos.getX() >> 4, pos.getZ() >> 4));
86-
}catch(Throwable ignored2)
87-
{}
163+
for(int bz = minZ; bz <= maxZ; bz++)
164+
{
165+
BlockPos pos = new BlockPos(bx, by, bz);
166+
boolean chunkLoaded = false;
167+
try
168+
{
169+
@SuppressWarnings("deprecation")
170+
boolean tmp =
171+
mc.world.isChunkLoaded(pos);
172+
chunkLoaded = tmp;
173+
}catch(Throwable ignored)
174+
{
175+
try
176+
{
177+
Object cm =
178+
mc.world.getChunkManager();
179+
java.lang.reflect.Method m =
180+
cm.getClass().getMethod(
181+
"isChunkLoaded", int.class,
182+
int.class);
183+
chunkLoaded = Boolean.TRUE.equals(
184+
m.invoke(cm, pos.getX() >> 4,
185+
pos.getZ() >> 4));
186+
}catch(Throwable ignored2)
187+
{}
188+
}
189+
if(!chunkLoaded)
190+
{
191+
anyChunkNotLoaded = true;
192+
break outer; // abort: wait until all
193+
// chunks loaded
194+
}
195+
196+
var state = mc.world.getBlockState(pos);
197+
boolean containerBlock =
198+
state != null && (state
199+
.getBlock() instanceof net.minecraft.block.ChestBlock
200+
|| state
201+
.getBlock() instanceof net.minecraft.block.BarrelBlock
202+
|| state
203+
.getBlock() instanceof net.minecraft.block.ShulkerBoxBlock
204+
|| state
205+
.getBlock() instanceof net.minecraft.block.DecoratedPotBlock);
206+
boolean hasBe =
207+
mc.world.getBlockEntity(pos) != null;
208+
if(containerBlock && hasBe)
209+
{
210+
anyContainerPresent = true;
211+
break outer; // container still present,
212+
// do not delete
213+
}
214+
}
215+
}
88216
}
89-
if(!chunkLoaded)
90-
continue; // don't delete when chunk is unloaded
91-
var state = mc.world.getBlockState(pos);
92-
boolean containerBlock = state != null && (state
93-
.getBlock() instanceof net.minecraft.block.ChestBlock
94-
|| state
95-
.getBlock() instanceof net.minecraft.block.BarrelBlock
96-
|| state
97-
.getBlock() instanceof net.minecraft.block.ShulkerBoxBlock
98-
|| state
99-
.getBlock() instanceof net.minecraft.block.DecoratedPotBlock);
100-
boolean hasBe = mc.world.getBlockEntity(pos) != null;
101-
if(!hasBe || !containerBlock)
217+
218+
if(anyChunkNotLoaded)
219+
continue; // wait until all relevant chunks are
220+
// loaded
221+
222+
if(!anyContainerPresent)
102223
{
224+
// No container found in the recorded bounds and all
225+
// chunks covering the bounds are loaded -> safe to
226+
// delete
103227
ChestSearchScreen.clearDecorations(e.dimension,
104-
pos);
105-
manager.removeChest(e.serverIp, e.dimension,
106-
pos.getX(), pos.getY(), pos.getZ());
228+
e.getMinPos());
229+
manager.removeChest(e.serverIp, e.dimension, minX,
230+
minY, minZ);
107231
}
108232
}catch(Throwable ignored)
109233
{}

src/main/java/net/wurstclient/chestsearch/ChestConfig.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ public class ChestConfig
1919
public boolean enabled = true;
2020
public boolean storeFullItemNbt = true;
2121
public String dbPath = "config/wurst/chest_database.json";
22+
// grace period in ticks to wait after joining/changing dimension before
23+
// allowing automatic deletions (20 ticks = 1 second)
24+
public int graceTicks = 200; // ~10s
25+
// scan radius in blocks within which the player must be to validate
26+
// a recorded chest
27+
public int scanRadius = 64;
2228

2329
private final File file;
2430
private final Gson gson = new GsonBuilder().setPrettyPrinting().create();

src/main/java/net/wurstclient/chestsearch/ChestManager.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ public List<ChestEntry> all()
104104
return getCurrentDb().all();
105105
}
106106

107+
public ChestConfig getConfig()
108+
{
109+
return this.config;
110+
}
111+
107112
// Helper: parse a string containing NBT JSON into JsonElement; caller may
108113
// obtain full ItemStack NBT
109114
public static JsonElement parseNbtJson(String nbtJson)

0 commit comments

Comments
 (0)