1010import java .io .IOException ;
1111import java .nio .file .Files ;
1212import java .nio .file .Path ;
13+ import java .util .LinkedHashMap ;
1314import java .util .LinkedHashSet ;
15+ import java .util .Map ;
1416import java .util .Set ;
1517
1618import com .google .gson .JsonArray ;
19+ import com .google .gson .JsonElement ;
20+ import com .google .gson .JsonObject ;
1721
1822import net .wurstclient .Category ;
1923import net .wurstclient .DontBlock ;
2529import net .wurstclient .util .json .JsonException ;
2630import net .wurstclient .util .json .JsonUtils ;
2731import net .wurstclient .util .json .WsonArray ;
32+ import net .wurstclient .util .json .WsonObject ;
2833import net .wurstclient .util .text .WText ;
2934
3035@ SearchTags ({"legit" , "disable" })
3136@ DontBlock
3237public final class PanicHack extends Hack
3338{
34- private final Set <String > savedHackNames = new LinkedHashSet <>();
39+ private final Map <String , Boolean > savedHackStates = new LinkedHashMap <>();
3540 private final Path snapshotFile =
3641 WURST .getWurstFolder ().resolve ("panic-snapshot.json" );
3742 private boolean startupRestorePending ;
@@ -54,7 +59,7 @@ public PanicHack()
5459 @ Override
5560 protected void onEnable ()
5661 {
57- int saved = snapshotEnabledHacks ();
62+ int saved = snapshotHackStates ();
5863 disableOtherHacks ();
5964 setEnabled (false );
6065
@@ -66,17 +71,26 @@ protected void onEnable()
6671 ChatUtils .message ("No other hacks were enabled." );
6772 }
6873
69- private int snapshotEnabledHacks ()
74+ private int snapshotHackStates ()
7075 {
71- savedHackNames .clear ();
76+ savedHackStates .clear ();
77+ int enabledCount = 0 ;
7278
7379 for (Hack hack : WURST .getHax ().getAllHax ())
74- if (hack .isEnabled () && hack != this )
75- savedHackNames .add (hack .getName ());
80+ {
81+ if (hack == this )
82+ continue ;
7683
84+ boolean enabled = hack .isEnabled ();
85+ if (enabled )
86+ enabledCount ++;
87+
88+ savedHackStates .put (hack .getName (), enabled );
89+ }
90+
7791 persistSavedHacks ();
7892 startupRestorePending = false ;
79- return savedHackNames . size () ;
93+ return enabledCount ;
8094 }
8195
8296 private void disableOtherHacks ()
@@ -88,7 +102,7 @@ private void disableOtherHacks()
88102
89103 public void restoreSavedHacks ()
90104 {
91- if (savedHackNames .isEmpty ())
105+ if (savedHackStates .isEmpty ())
92106 {
93107 ChatUtils .error ("There is no saved Panic state to restore." );
94108 return ;
@@ -97,10 +111,16 @@ public void restoreSavedHacks()
97111 HackList hax = WURST .getHax ();
98112 Set <String > missing = new LinkedHashSet <>();
99113 Set <String > blocked = new LinkedHashSet <>();
100- int restored = 0 ;
114+ int enabledRestored = 0 ;
115+ int disabledRestored = 0 ;
116+ Map <String , Boolean > remainingStates = new LinkedHashMap <>();
101117
102- for (String name : new LinkedHashSet <>(savedHackNames ))
118+ for (Map .Entry <String , Boolean > entry : new LinkedHashMap <>(
119+ savedHackStates ).entrySet ())
103120 {
121+ String name = entry .getKey ();
122+ boolean targetEnabled = entry .getValue ();
123+
104124 Hack hack = hax .getHackByName (name );
105125 if (hack == null || hack == this )
106126 {
@@ -109,46 +129,90 @@ public void restoreSavedHacks()
109129 }
110130
111131 boolean wasEnabled = hack .isEnabled ();
112- hack .setEnabled (true );
113132
114- if (!hack .isEnabled ())
133+ if (targetEnabled )
134+ {
135+ hack .setEnabled (true );
136+
137+ if (!hack .isEnabled ())
138+ {
139+ blocked .add (name );
140+ remainingStates .put (name , targetEnabled );
141+ continue ;
142+ }
143+
144+ if (!wasEnabled && hack .isEnabled ())
145+ enabledRestored ++;
146+
147+ continue ;
148+ }
149+
150+ hack .setEnabled (false );
151+
152+ if (hack .isEnabled ())
115153 {
116154 blocked .add (name );
155+ remainingStates .put (name , targetEnabled );
117156 continue ;
118157 }
119158
120- if (! wasEnabled && hack . isEnabled () )
121- restored ++;
159+ if (wasEnabled )
160+ disabledRestored ++;
122161 }
123162
124- savedHackNames .clear ();
125- savedHackNames . addAll ( blocked );
163+ savedHackStates .clear ();
164+ savedHackStates . putAll ( remainingStates );
126165
127- if (restored > 0 )
128- ChatUtils .message ("Restored " + restored + " hack"
129- + (restored == 1 ? "" : "s" ) + " from Panic." );
130- else if (savedHackNames .isEmpty ())
131- ChatUtils .message ("All saved Panic hacks are already enabled." );
166+ if (enabledRestored > 0 || disabledRestored > 0 )
167+ {
168+ String message =
169+ buildRestoreMessage (enabledRestored , disabledRestored );
170+ ChatUtils .message (message );
171+
172+ }else if (savedHackStates .isEmpty ())
173+ ChatUtils
174+ .message ("All hacks already matched the saved Panic state." );
132175
133176 if (!missing .isEmpty ())
134177 ChatUtils
135178 .warning ("Missing Panic hacks: " + String .join (", " , missing ));
136179
137- if (!savedHackNames .isEmpty ())
138- ChatUtils
139- .warning ("Still blocked: " + String .join (", " , savedHackNames ));
180+ if (!blocked .isEmpty ())
181+ ChatUtils .warning ("Still blocked: " + String .join (", " , blocked ));
140182
141183 persistSavedHacks ();
142184 }
143185
186+ private String buildRestoreMessage (int enabledRestored ,
187+ int disabledRestored )
188+ {
189+ StringBuilder sb = new StringBuilder ("Restored Panic state" );
190+
191+ if (enabledRestored > 0 )
192+ {
193+ sb .append (": enabled " ).append (enabledRestored ).append (" hack" )
194+ .append (enabledRestored == 1 ? "" : "s" );
195+
196+ if (disabledRestored > 0 )
197+ sb .append (", " );
198+ }
199+
200+ if (disabledRestored > 0 )
201+ sb .append (enabledRestored > 0 ? "" : ": " ).append ("disabled " )
202+ .append (disabledRestored ).append (" hack" )
203+ .append (disabledRestored == 1 ? "" : "s" );
204+
205+ return sb .append ('.' ).toString ();
206+ }
207+
144208 public void handleStartupRestore ()
145209 {
146210 if (!startupRestorePending )
147211 return ;
148212
149213 startupRestorePending = false ;
150214
151- if (savedHackNames .isEmpty ())
215+ if (savedHackStates .isEmpty ())
152216 {
153217 deleteSnapshotFile ();
154218 return ;
@@ -160,17 +224,17 @@ public void handleStartupRestore()
160224 private void loadSnapshotFromDisk ()
161225 {
162226 startupRestorePending = false ;
163- savedHackNames .clear ();
227+ savedHackStates .clear ();
164228
165229 if (!Files .exists (snapshotFile ))
166230 return ;
167231
168232 try
169233 {
170234 WsonArray wson = JsonUtils .parseFileToArray (snapshotFile );
171- savedHackNames . addAll (wson . getAllStrings () );
235+ loadSnapshotEntries (wson );
172236
173- if (savedHackNames .isEmpty ())
237+ if (savedHackStates .isEmpty ())
174238 deleteSnapshotFile ();
175239 else
176240 startupRestorePending = true ;
@@ -183,16 +247,45 @@ private void loadSnapshotFromDisk()
183247 }
184248 }
185249
250+ private void loadSnapshotEntries (WsonArray wson ) throws JsonException
251+ {
252+ for (int i = 0 ; i < wson .size (); i ++)
253+ {
254+ JsonElement element = wson .getElement (i );
255+
256+ if (element .isJsonObject ())
257+ {
258+ WsonObject obj = new WsonObject (element .getAsJsonObject ());
259+ String name = obj .getString ("name" , null );
260+ boolean enabled = obj .getBoolean ("enabled" , true );
261+
262+ if (name != null )
263+ savedHackStates .put (name , enabled );
264+
265+ continue ;
266+ }
267+
268+ if (element .isJsonPrimitive ()
269+ && element .getAsJsonPrimitive ().isString ())
270+ savedHackStates .put (element .getAsString (), true );
271+ }
272+ }
273+
186274 private void persistSavedHacks ()
187275 {
188- if (savedHackNames .isEmpty ())
276+ if (savedHackStates .isEmpty ())
189277 {
190278 deleteSnapshotFile ();
191279 return ;
192280 }
193281
194282 JsonArray json = new JsonArray ();
195- savedHackNames .forEach (json ::add );
283+ savedHackStates .forEach ((name , enabled ) -> {
284+ JsonObject obj = new JsonObject ();
285+ obj .addProperty ("name" , name );
286+ obj .addProperty ("enabled" , enabled );
287+ json .add (obj );
288+ });
196289
197290 try
198291 {
0 commit comments