├── .gitignore
├── .idea
├── .gitignore
├── artifacts
│ └── InjectionClientTest_jar.xml
├── compiler.xml
├── discord.xml
├── jarRepositories.xml
├── misc.xml
└── uiDesigner.xml
├── README.md
├── pom.xml
└── src
├── main
├── java
│ ├── com
│ │ └── darkmagician6
│ │ │ └── eventapi
│ │ │ ├── EventAPI.java
│ │ │ ├── EventManager.java
│ │ │ ├── EventTarget.java
│ │ │ ├── events
│ │ │ ├── Cancellable.java
│ │ │ ├── Event.java
│ │ │ ├── EventStoppable.java
│ │ │ ├── Typed.java
│ │ │ └── callables
│ │ │ │ ├── EventCancellable.java
│ │ │ │ └── EventTyped.java
│ │ │ └── types
│ │ │ ├── EventType.java
│ │ │ └── Priority.java
│ └── me
│ │ └── dickmeister
│ │ ├── agent
│ │ ├── ClientAgent.java
│ │ ├── attacher
│ │ │ └── AgentAttacher.java
│ │ └── modules
│ │ │ ├── AgentModule.java
│ │ │ └── impl
│ │ │ ├── MinecraftJarInjectorModule.java
│ │ │ ├── MinecraftQueueFinderModule.java
│ │ │ ├── VersionFinderModule.java
│ │ │ └── VersionMappingDownloaderModule.java
│ │ ├── client
│ │ ├── ClientMain.java
│ │ ├── core
│ │ │ ├── command
│ │ │ │ ├── Command.java
│ │ │ │ ├── CommandManager.java
│ │ │ │ └── impl
│ │ │ │ │ ├── HelpCommand.java
│ │ │ │ │ ├── HitboxCommand.java
│ │ │ │ │ ├── PanicCommand.java
│ │ │ │ │ └── ToggleCommand.java
│ │ │ ├── event
│ │ │ │ ├── EventDistributor.java
│ │ │ │ ├── EventInjector.java
│ │ │ │ ├── impl
│ │ │ │ │ ├── ClientInternalTickEvent.java
│ │ │ │ │ ├── KeyPressEvent.java
│ │ │ │ │ ├── PlayerChatEvent.java
│ │ │ │ │ └── Render2DEvent.java
│ │ │ │ └── util
│ │ │ │ │ ├── EventCaller.java
│ │ │ │ │ └── EventInitializer.java
│ │ │ ├── gui
│ │ │ │ └── GuiIngameRenderer.java
│ │ │ ├── module
│ │ │ │ ├── Module.java
│ │ │ │ ├── ModuleCategory.java
│ │ │ │ ├── ModuleManager.java
│ │ │ │ └── impl
│ │ │ │ │ ├── combat
│ │ │ │ │ └── HitboxModule.java
│ │ │ │ │ └── render
│ │ │ │ │ └── ESPModule.java
│ │ │ └── utils
│ │ │ │ └── minecraft
│ │ │ │ ├── MinecraftUtil.java
│ │ │ │ └── impl
│ │ │ │ └── MinecraftUtil_118x.java
│ │ ├── mappings
│ │ │ ├── MappingManager.java
│ │ │ ├── VersionMappingsLoader.java
│ │ │ ├── loader
│ │ │ │ └── MappingsLoader.java
│ │ │ └── proguard
│ │ │ │ ├── MappingReader.java
│ │ │ │ ├── objects
│ │ │ │ ├── MappedClass.java
│ │ │ │ ├── MappedField.java
│ │ │ │ └── MappedMethod.java
│ │ │ │ ├── processor
│ │ │ │ ├── MappingProcessor.java
│ │ │ │ └── impl
│ │ │ │ │ └── ClientMappingProcessor.java
│ │ │ │ └── utils
│ │ │ │ └── ProguardMap.java
│ │ ├── tasks
│ │ │ └── TickingTask.java
│ │ ├── transformers
│ │ │ └── TestTransformer.java
│ │ └── version
│ │ │ ├── VersionFinder.java
│ │ │ └── component
│ │ │ ├── VersionFinderComponent.java
│ │ │ └── impl
│ │ │ └── LatestFinderComponent.java
│ │ ├── common
│ │ └── util
│ │ │ ├── LogUtil.java
│ │ │ └── URLUtils.java
│ │ └── injector
│ │ └── ClientInjector.java
└── resources
│ └── META-INF
│ └── MANIFEST.MF
└── test
└── java
├── AttachTest.java
└── MappingPrinter.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # Project exclude paths
2 | /out/
3 | /target/
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/artifacts/InjectionClientTest_jar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | $PROJECT_DIR$/out/artifacts/InjectionClientTest_jar
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/discord.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 | -
9 |
10 |
11 | -
12 |
13 |
14 | -
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 |
33 |
34 |
35 | -
36 |
37 |
38 |
39 |
40 |
41 | -
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 |
56 | -
57 |
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 |
66 | -
67 |
68 |
69 |
70 |
71 | -
72 |
73 |
74 | -
75 |
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 |
88 |
89 | -
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 |
98 |
99 | -
100 |
101 |
102 | -
103 |
104 |
105 | -
106 |
107 |
108 | -
109 |
110 |
111 | -
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 | -
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # InjectionClient
2 |
3 | This project was used to learn injecting a "working" hacked client into minecraft
4 |
5 | ### Requires to run client from the JDK, set your jdk 17 as runtime for minecraft client, idk if it requires it or not just use it to be safe.
6 | ### Only supports 1.18 vanilla version of the game, but feel free to push your changes regarding compatibility
7 |
8 | # Working modules
9 | - ESP (Click "O" when injected)
10 | - Hitbox (Click "K" when injected - it is bugged af causes movement problems)
11 |
12 | # Commands
13 | - ,help - Sends command list
14 | - ,hitbox - lets you set the hitbox width and height
15 | - ,toggle - toggles a module
16 | - ,panic - disabling client
17 |
18 | # How to run
19 | - Compile the project into jar file including all dependencies
20 | - Run your minecraft client (1.18 vanilla only supported)
21 | - Run the jar file using java -jar (jdk 17 or newer)
22 | - Select your minecraft client in the list that was displayed, enter a number containing "net.minecraft.client.main.Main" and click enter
23 | - After 3 - 5 seconds you should see a "InjectClient v0" text in the left upper corner of the game
24 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.example
8 | InjectionClientTest
9 | 1.0-SNAPSHOT
10 |
11 |
12 |
13 | com.google.code.gson
14 | gson
15 | 2.9.0
16 |
17 |
18 | net.bytebuddy
19 | byte-buddy
20 | LATEST
21 |
22 |
23 | net.bytebuddy
24 | byte-buddy-agent
25 | 1.12.10
26 |
27 |
28 | org.reflections
29 | reflections
30 | 0.10.2
31 |
32 |
33 | javassist
34 | javassist
35 | 3.12.1.GA
36 |
37 |
38 |
39 |
40 | 17
41 | 17
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/main/java/com/darkmagician6/eventapi/EventAPI.java:
--------------------------------------------------------------------------------
1 | /**
2 | * This is an API used for handling events across your java based projects.
3 | * It's meant to be simple to use without sacrificing performance and extensibility.
4 | *
5 | * Currently the API is in beta phase but it's stable and ready to be used.
6 | *
7 | * If you have any suggestion for improvements/fixes for shit,
8 | * feel free to make a pull request on the bitbucket: https://bitbucket.org/DarkMagician6/eventapi/overview.
9 | *
10 | * For information on how to use the API take a look at the wiki:
11 | * https://bitbucket.org/DarkMagician6/eventapi/wiki/Home
12 | *
13 | * @Todo Improve/update the wiki.
14 | */
15 | package com.darkmagician6.eventapi;
16 |
17 | /**
18 | * Main class for the API.
19 | * Contains various information about the API.
20 | *
21 | * @author DarkMagician6
22 | * @since July 31, 2013
23 | */
24 | public final class EventAPI {
25 |
26 | /**
27 | * No need to create an Object of this class as all Methods are static.
28 | */
29 | private EventAPI() {
30 | }
31 |
32 | /**
33 | * The current version of the API.
34 | */
35 | public static final String VERSION = String.format("%s-%s", "0.7", "beta");
36 |
37 | /**
38 | * Array containing the authors of the API.
39 | */
40 | public static final String[] AUTHORS = {
41 | "DarkMagician6"
42 | };
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/darkmagician6/eventapi/EventManager.java:
--------------------------------------------------------------------------------
1 | package com.darkmagician6.eventapi;
2 |
3 | import java.lang.reflect.InvocationTargetException;
4 | import java.lang.reflect.Method;
5 | import java.util.HashMap;
6 | import java.util.Iterator;
7 | import java.util.List;
8 | import java.util.Map;
9 | import java.util.concurrent.CopyOnWriteArrayList;
10 |
11 | import com.darkmagician6.eventapi.events.Event;
12 | import com.darkmagician6.eventapi.events.EventStoppable;
13 | import com.darkmagician6.eventapi.types.Priority;
14 |
15 | /**
16 | *
17 | *
18 | * @author DarkMagician6
19 | * @since February 2, 2014
20 | */
21 | public final class EventManager {
22 |
23 | /**
24 | * HashMap containing all the registered MethodData sorted on the event parameters of the methods.
25 | */
26 | private static final Map, List> REGISTRY_MAP = new HashMap, List>();
27 |
28 | /**
29 | * All methods in this class are static so there would be no reason to create an object of the EventManager class.
30 | */
31 | private EventManager() {
32 | }
33 |
34 | /**
35 | * Registers all the methods marked with the EventTarget annotation in the class of the given Object.
36 | *
37 | * @param object
38 | * Object that you want to register.
39 | */
40 | public static void register(Object object) {
41 | for (final Method method : object.getClass().getDeclaredMethods()) {
42 | if (isMethodBad(method)) {
43 | continue;
44 | }
45 |
46 | register(method, object);
47 | }
48 | }
49 |
50 | /**
51 | * Registers the methods marked with the EventTarget annotation and that require
52 | * the specified Event as the parameter in the class of the given Object.
53 | *
54 | * @param object
55 | * Object that contains the Method you want to register.
56 | * @param Parameter
57 | * class for the marked method we are looking for.
58 | */
59 | public static void register(Object object, Class extends Event> eventClass) {
60 | for (final Method method : object.getClass().getDeclaredMethods()) {
61 | if (isMethodBad(method, eventClass)) {
62 | continue;
63 | }
64 |
65 | register(method, object);
66 | }
67 | }
68 |
69 | /**
70 | * Unregisters all the methods inside the Object that are marked with the EventTarget annotation.
71 | *
72 | * @param object
73 | * Object of which you want to unregister all Methods.
74 | */
75 | public static void unregister(Object object) {
76 | for (final List dataList : REGISTRY_MAP.values()) {
77 | for (final MethodData data : dataList) {
78 | if (data.getSource().equals(object)) {
79 | dataList.remove(data);
80 | }
81 | }
82 | }
83 |
84 | cleanMap(true);
85 | }
86 |
87 | /**
88 | * Unregisters all the methods in the given Object that have the specified class as a parameter.
89 | *
90 | * @param object
91 | * Object that implements the Listener interface.
92 | * @param Parameter
93 | * class for the method to remove.
94 | */
95 | public static void unregister(Object object, Class extends Event> eventClass) {
96 | if (REGISTRY_MAP.containsKey(eventClass)) {
97 | for (final MethodData data : REGISTRY_MAP.get(eventClass)) {
98 | if (data.getSource().equals(object)) {
99 | REGISTRY_MAP.get(eventClass).remove(data);
100 | }
101 | }
102 |
103 | cleanMap(true);
104 | }
105 | }
106 |
107 | /**
108 | * Registers a new MethodData to the HashMap.
109 | * If the HashMap already contains the key of the Method's first argument it will add
110 | * a new MethodData to key's matching list and sorts it based on Priority. @see com.darkmagician6.eventapi.types.Priority
111 | * Otherwise it will put a new entry in the HashMap with a the first argument's class
112 | * and a new CopyOnWriteArrayList containing the new MethodData.
113 | *
114 | * @param method
115 | * Method to register to the HashMap.
116 | * @param object
117 | * Source object of the method.
118 | */
119 | private static void register(Method method, Object object) {
120 | Class extends Event> indexClass = (Class extends Event>) method.getParameterTypes()[0];
121 | //New MethodData from the Method we are registering.
122 | final MethodData data = new MethodData(object, method, method.getAnnotation(EventTarget.class).value());
123 |
124 | //Set's the method to accessible so that we can also invoke it if it's protected or private.
125 | if (!data.getTarget().isAccessible()) {
126 | data.getTarget().setAccessible(true);
127 | }
128 |
129 | if (REGISTRY_MAP.containsKey(indexClass)) {
130 | if (!REGISTRY_MAP.get(indexClass).contains(data)) {
131 | REGISTRY_MAP.get(indexClass).add(data);
132 | sortListValue(indexClass);
133 | }
134 | } else {
135 | REGISTRY_MAP.put(indexClass, new CopyOnWriteArrayList() {
136 | //Eclipse was bitching about a serialVersionUID.
137 | private static final long serialVersionUID = 666L; {
138 | add(data);
139 | }
140 | });
141 | }
142 | }
143 |
144 | /**
145 | * Removes an entry based on the key value in the map.
146 | *
147 | * @param indexClass
148 | * They index key in the map of which the entry should be removed.
149 | */
150 | public static void removeEntry(Class extends Event> indexClass) {
151 | Iterator, List>> mapIterator = REGISTRY_MAP.entrySet().iterator();
152 |
153 | while (mapIterator.hasNext()) {
154 | if (mapIterator.next().getKey().equals(indexClass)) {
155 | mapIterator.remove();
156 | break;
157 | }
158 | }
159 | }
160 |
161 | /**
162 | * Cleans up the map entries.
163 | * Uses an iterator to make sure that the entry is completely removed.
164 | *
165 | * @param onlyEmptyEntries
166 | * If true only remove the entries with an empty list, otherwise remove all the entries.
167 | */
168 | public static void cleanMap(boolean onlyEmptyEntries) {
169 | Iterator, List>> mapIterator = REGISTRY_MAP.entrySet().iterator();
170 |
171 | while (mapIterator.hasNext()) {
172 | if (!onlyEmptyEntries || mapIterator.next().getValue().isEmpty()) {
173 | mapIterator.remove();
174 | }
175 | }
176 | }
177 |
178 | /**
179 | * Sorts the List that matches the corresponding Event class based on priority value.
180 | *
181 | * @param indexClass
182 | * The Event class index in the HashMap of the List to sort.
183 | */
184 | private static void sortListValue(Class extends Event> indexClass) {
185 | List sortedList = new CopyOnWriteArrayList();
186 |
187 | for (final byte priority : Priority.VALUE_ARRAY) {
188 | for (final MethodData data : REGISTRY_MAP.get(indexClass)) {
189 | if (data.getPriority() == priority) {
190 | sortedList.add(data);
191 | }
192 | }
193 | }
194 |
195 | //Overwriting the existing entry.
196 | REGISTRY_MAP.put(indexClass, sortedList);
197 | }
198 |
199 | /**
200 | * Checks if the method does not meet the requirements to be used to receive event calls from the Dispatcher.
201 | * Performed checks: Checks if the parameter length is not 1 and if the EventTarget annotation is not present.
202 | *
203 | * @param method
204 | * Method to check.
205 | *
206 | * @return True if the method should not be used for receiving event calls from the Dispatcher.
207 | *
208 | * @see com.darkmagician6.eventapi.EventTarget
209 | */
210 | private static boolean isMethodBad(Method method) {
211 | return method.getParameterTypes().length != 1 || !method.isAnnotationPresent(EventTarget.class);
212 | }
213 |
214 | /**
215 | * Checks if the method does not meet the requirements to be used to receive event calls from the Dispatcher.
216 | * Performed checks: Checks if the parameter class of the method is the same as the event we want to receive.
217 | *
218 | * @param method
219 | * Method to check.
220 | * @param Class
221 | * of the Event we want to find a method for receiving it.
222 | *
223 | * @return True if the method should not be used for receiving event calls from the Dispatcher.
224 | *
225 | * @see com.darkmagician6.eventapi.EventTarget
226 | */
227 | private static boolean isMethodBad(Method method, Class extends Event> eventClass) {
228 | return isMethodBad(method) || !method.getParameterTypes()[0].equals(eventClass);
229 | }
230 |
231 | /**
232 | * Call's an event and invokes the right methods that are listening to the event call.
233 | * First get's the matching list from the registry map based on the class of the event.
234 | * Then it checks if the list is not null. After that it will check if the event is an instance of
235 | * EventStoppable and if so it will add an extra check when looping trough the data.
236 | * If the Event was an instance of EventStoppable it will check every loop if the EventStoppable is stopped, and if
237 | * it is it will break the loop, thus stopping the call.
238 | * For every MethodData in the list it will invoke the Data's method with the Event as the argument.
239 | * After that is all done it will return the Event.
240 | *
241 | * @param event
242 | * Event to dispatch.
243 | *
244 | * @return Event in the state after dispatching it.
245 | */
246 | public static final Event call(final Event event) {
247 | List dataList = REGISTRY_MAP.get(event.getClass());
248 |
249 | if (dataList != null) {
250 | if (event instanceof EventStoppable) {
251 | EventStoppable stoppable = (EventStoppable) event;
252 |
253 | for (final MethodData data : dataList) {
254 | invoke(data, event);
255 |
256 | if (stoppable.isStopped()) {
257 | break;
258 | }
259 | }
260 | } else {
261 | for (final MethodData data : dataList) {
262 | invoke(data, event);
263 | }
264 | }
265 | }
266 |
267 | return event;
268 | }
269 |
270 | /**
271 | * Invokes a MethodData when an Event call is made.
272 | *
273 | * @param data
274 | * The data of which the targeted Method should be invoked.
275 | * @param argument
276 | * The called Event which should be used as an argument for the targeted Method.
277 | *
278 | * TODO: Error messages.
279 | */
280 | private static void invoke(MethodData data, Event argument) {
281 | try {
282 | data.getTarget().invoke(data.getSource(), argument);
283 | } catch (IllegalAccessException e) {
284 | } catch (IllegalArgumentException e) {
285 | } catch (InvocationTargetException e) {
286 | }
287 | }
288 |
289 | /**
290 | *
291 | * @author DarkMagician6
292 | * @since January 2, 2014
293 | */
294 | private static final class MethodData {
295 |
296 | private final Object source;
297 |
298 | private final Method target;
299 |
300 | private final byte priority;
301 |
302 | /**
303 | * Sets the values of the data.
304 | *
305 | * @param source
306 | * The source Object of the data. Used by the VM to
307 | * determine to which object it should send the call to.
308 | * @param target
309 | * The targeted Method to which the Event should be send to.
310 | * @param priority
311 | * The priority of this Method. Used by the registry to sort
312 | * the data on.
313 | */
314 | public MethodData(Object source, Method target, byte priority) {
315 | this.source = source;
316 | this.target = target;
317 | this.priority = priority;
318 | }
319 |
320 | /**
321 | * Gets the source Object of the data.
322 | *
323 | * @return Source Object of the targeted Method.
324 | */
325 | public Object getSource() {
326 | return source;
327 | }
328 |
329 | /**
330 | * Gets the targeted Method.
331 | *
332 | * @return The Method that is listening to certain Event calls.
333 | */
334 | public Method getTarget() {
335 | return target;
336 | }
337 |
338 | /**
339 | * Gets the priority value of the targeted Method.
340 | *
341 | * @return The priority value of the targeted Method.
342 | */
343 | public byte getPriority() {
344 | return priority;
345 | }
346 |
347 | }
348 |
349 | public static Map, List> getRegistryMap() {
350 | return REGISTRY_MAP;
351 | }
352 | }
353 |
--------------------------------------------------------------------------------
/src/main/java/com/darkmagician6/eventapi/EventTarget.java:
--------------------------------------------------------------------------------
1 | package com.darkmagician6.eventapi;
2 |
3 | import com.darkmagician6.eventapi.types.Priority;
4 |
5 | import java.lang.annotation.*;
6 |
7 | /**
8 | * Marks a method so that the EventManager knows that it should be registered.
9 | * The priority of the method is also set with this.
10 | *
11 | * @author DarkMagician6
12 | * @see com.darkmagician6.eventapi.types.Priority
13 | * @since July 30, 2013
14 | */
15 | @Documented
16 | @Target(ElementType.METHOD)
17 | @Retention(RetentionPolicy.RUNTIME)
18 | public @interface EventTarget {
19 |
20 | byte value() default Priority.MEDIUM;
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/darkmagician6/eventapi/events/Cancellable.java:
--------------------------------------------------------------------------------
1 | package com.darkmagician6.eventapi.events;
2 |
3 | /**
4 | * Simple interface which should be implemented in events that can be cancelled.
5 | *
6 | * @author DarkMagician6
7 | * @since August 27, 2013
8 | */
9 | public interface Cancellable {
10 |
11 | /**
12 | * Gets the current cancelled state of the event.
13 | *
14 | * @return True if the event is cancelled.
15 | */
16 | boolean isCancelled();
17 |
18 | /**
19 | * Sets the cancelled state of the event.
20 | *
21 | * @param state
22 | * Whether the event should be cancelled or not.
23 | */
24 | void setCancelled(boolean state);
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/darkmagician6/eventapi/events/Event.java:
--------------------------------------------------------------------------------
1 | package com.darkmagician6.eventapi.events;
2 |
3 | /**
4 | * The most basic form of an event.
5 | * You have to implement this interface in order for the EventAPI to recognize the event.
6 | *
7 | * @author DarkMagician6
8 | * @since July 30, 2013
9 | */
10 | public interface Event {
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/darkmagician6/eventapi/events/EventStoppable.java:
--------------------------------------------------------------------------------
1 | package com.darkmagician6.eventapi.events;
2 |
3 | /**
4 | * The most basic form of an stoppable Event.
5 | * Stoppable events are called seperate from other events and the calling of methods is stopped
6 | * as soon as the EventStoppable is stopped.
7 | *
8 | * @author DarkMagician6
9 | * @since 26-9-13
10 | */
11 | public abstract class EventStoppable implements Event {
12 |
13 | private boolean stopped;
14 |
15 | /**
16 | * No need for the constructor to be public.
17 | */
18 | protected EventStoppable() {
19 | }
20 |
21 | /**
22 | * Sets the stopped state to true.
23 | */
24 | public void stop() {
25 | stopped = true;
26 | }
27 |
28 | /**
29 | * Checks the stopped boolean.
30 | *
31 | * @return
32 | * True if the EventStoppable is stopped.
33 | */
34 | public boolean isStopped() {
35 | return stopped;
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/darkmagician6/eventapi/events/Typed.java:
--------------------------------------------------------------------------------
1 | package com.darkmagician6.eventapi.events;
2 |
3 |
4 | /**
5 | * Simple interface that should be implemented in typed events.
6 | * A typed event is an event that can be called on multiple places
7 | * with the type defining where it was called.
8 | *
9 | * The type should be defined in the constructor when the new instance
10 | * of the event is created.
11 | *
12 | * @author DarkMagician6
13 | * @since August 27, 2013
14 | */
15 | public interface Typed {
16 |
17 | /**
18 | * Gets the current type of the event.
19 | *
20 | * @return The type ID of the event.
21 | */
22 | byte getType();
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/darkmagician6/eventapi/events/callables/EventCancellable.java:
--------------------------------------------------------------------------------
1 | package com.darkmagician6.eventapi.events.callables;
2 |
3 | import com.darkmagician6.eventapi.events.Cancellable;
4 | import com.darkmagician6.eventapi.events.Event;
5 |
6 | /**
7 | * Abstract example implementation of the Cancellable interface.
8 | *
9 | * @author DarkMagician6
10 | * @since August 27, 2013
11 | */
12 | public abstract class EventCancellable implements Event, Cancellable {
13 |
14 | private boolean cancelled;
15 |
16 | protected EventCancellable() {
17 | }
18 |
19 | /**
20 | * @see com.darkmagician6.eventapi.events.Cancellable.isCancelled
21 | */
22 | @Override
23 | public boolean isCancelled() {
24 | return cancelled;
25 | }
26 |
27 | /**
28 | * @see com.darkmagician6.eventapi.events.Cancellable.setCancelled
29 | */
30 | @Override
31 | public void setCancelled(boolean state) {
32 | cancelled = state;
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/com/darkmagician6/eventapi/events/callables/EventTyped.java:
--------------------------------------------------------------------------------
1 | package com.darkmagician6.eventapi.events.callables;
2 |
3 | import com.darkmagician6.eventapi.events.Event;
4 | import com.darkmagician6.eventapi.events.Typed;
5 |
6 | /**
7 | * Abstract example implementation of the Typed interface.
8 | *
9 | * @author DarkMagician6
10 | * @since August 27, 2013
11 | */
12 | public abstract class EventTyped implements Event, Typed {
13 |
14 | private final byte type;
15 |
16 | /**
17 | * Sets the type of the event when it's called.
18 | *
19 | * @param eventType
20 | * The type ID of the event.
21 | */
22 | protected EventTyped(byte eventType) {
23 | type = eventType;
24 | }
25 |
26 | /**
27 | * @see com.darkmagician6.eventapi.events.Typed.getType
28 | */
29 | @Override
30 | public byte getType() {
31 | return type;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/darkmagician6/eventapi/types/EventType.java:
--------------------------------------------------------------------------------
1 | package com.darkmagician6.eventapi.types;
2 |
3 | /**
4 | * Types that can be used for typed events.
5 | *
6 | * @author DarkMagician6
7 | * @since August 27, 2013
8 | */
9 | public class EventType {
10 |
11 | /**
12 | * Used to define the type of a typed event.
13 | */
14 | public static final byte
15 | PRE = 0,
16 | ON = 1,
17 | POST = 2,
18 | SEND = 3,
19 | RECIEVE = 4;
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/darkmagician6/eventapi/types/Priority.java:
--------------------------------------------------------------------------------
1 | package com.darkmagician6.eventapi.types;
2 |
3 | /**
4 | * The priority for the dispatcher to determine what method should be invoked first.
5 | * Ram was talking about the memory usage of the way I store the data so I decided
6 | * to just use bytes for the priority because they take up only 8 bits of memory
7 | * per value compared to the 32 bits per value of an enum (Same as an integer).
8 | *
9 | * @author DarkMagician6
10 | * @since August 3, 2013
11 | */
12 | public final class Priority {
13 |
14 | public static final byte
15 | /**
16 | * Highest priority, called first.
17 | */
18 | HIGHEST = 0,
19 | /**
20 | * High priority, called after the highest priority.
21 | */
22 | HIGH = 1,
23 | /**
24 | * Medium priority, called after the high priority.
25 | */
26 | MEDIUM = 2,
27 | /**
28 | * Low priority, called after the medium priority.
29 | */
30 | LOW = 3,
31 | /**
32 | * Lowest priority, called after all the other priorities.
33 | */
34 | LOWEST = 4;
35 |
36 | /**
37 | * Array containing all the prioriy values.
38 | */
39 | public static final byte[] VALUE_ARRAY;
40 |
41 | /**
42 | * Sets up the VALUE_ARRAY the first time anything in this class is called.
43 | */
44 | static {
45 | VALUE_ARRAY = new byte[]{
46 | HIGHEST,
47 | HIGH,
48 | MEDIUM,
49 | LOW,
50 | LOWEST
51 | };
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/agent/ClientAgent.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.agent;
2 |
3 | import me.dickmeister.agent.modules.AgentModule;
4 | import me.dickmeister.agent.modules.impl.MinecraftJarInjectorModule;
5 | import me.dickmeister.agent.modules.impl.MinecraftQueueFinderModule;
6 | import me.dickmeister.agent.modules.impl.VersionFinderModule;
7 | import me.dickmeister.agent.modules.impl.VersionMappingDownloaderModule;
8 | import me.dickmeister.common.util.LogUtil;
9 |
10 | import java.lang.instrument.Instrumentation;
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | public class ClientAgent {
15 |
16 | private static final List moduleList = new ArrayList<>();
17 |
18 | public static void agentmain(String agentArgs, Instrumentation inst) {
19 | LogUtil.log("Loading modules...");
20 | moduleList.add(new VersionFinderModule());
21 | moduleList.add(new VersionMappingDownloaderModule());
22 | moduleList.add(new MinecraftQueueFinderModule());
23 | moduleList.add(new MinecraftJarInjectorModule());
24 |
25 | LogUtil.log("Executing modules...");
26 | Object returnCache = new Object();
27 | for(AgentModule m : moduleList) {
28 | try{
29 | returnCache = m.execute(inst,returnCache);
30 | LogUtil.log("Executed module: " + m.getClass().getName());
31 | }catch(Exception e){
32 | e.printStackTrace();
33 | LogUtil.log("Failed to execute module " + m.getClass().getName());
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/agent/attacher/AgentAttacher.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.agent.attacher;
2 |
3 | import com.sun.tools.attach.VirtualMachine;
4 |
5 | import java.lang.management.ManagementFactory;
6 |
7 | public class AgentAttacher {
8 |
9 | public static void attachDynamic(String jarFilePath, String pid) throws Exception {
10 | VirtualMachine vm = VirtualMachine.attach(pid);
11 | vm.loadAgent(jarFilePath, "");
12 | vm.detach();
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/agent/modules/AgentModule.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.agent.modules;
2 |
3 | import java.lang.instrument.Instrumentation;
4 |
5 | public abstract class AgentModule {
6 |
7 | public abstract Object execute(Instrumentation instrumentation,Object arg) throws Exception;
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/agent/modules/impl/MinecraftJarInjectorModule.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.agent.modules.impl;
2 |
3 | import me.dickmeister.agent.ClientAgent;
4 | import me.dickmeister.agent.modules.AgentModule;
5 | import me.dickmeister.common.util.LogUtil;
6 |
7 | import java.io.File;
8 | import java.lang.instrument.Instrumentation;
9 | import java.net.URL;
10 | import java.net.URLClassLoader;
11 | import java.util.Objects;
12 | import java.util.Queue;
13 |
14 | public class MinecraftJarInjectorModule extends AgentModule {
15 | @Override
16 | public Object execute(Instrumentation instrumentation, Object arg) throws Exception {
17 | if(Objects.isNull(arg)) return null;
18 | var queue = (Queue) arg;
19 | var filePath = ClientAgent.class.getProtectionDomain().getCodeSource().getLocation().getPath();;
20 | queue.add(() -> {
21 | try {
22 | var file = new File(filePath);
23 | var classLoader = new URLClassLoader(new URL[]{file.toURI().toURL()}, Thread.currentThread().getContextClassLoader());
24 |
25 | var clazz = classLoader.loadClass("me.dickmeister.client.ClientMain");
26 | var instance = clazz.newInstance();
27 | clazz.getDeclaredMethod("invokeClient",Instrumentation.class).invoke(instance,instrumentation);
28 |
29 | Thread.currentThread().setContextClassLoader(classLoader);
30 | }catch(Exception e){
31 | e.printStackTrace();
32 | }
33 | });
34 | return null; //Last module
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/agent/modules/impl/MinecraftQueueFinderModule.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.agent.modules.impl;
2 |
3 | import me.dickmeister.agent.modules.AgentModule;
4 |
5 | import java.lang.instrument.Instrumentation;
6 | import java.util.Objects;
7 | import java.util.Queue;
8 | import java.util.Scanner;
9 |
10 | public class MinecraftQueueFinderModule extends AgentModule {
11 |
12 | @Override
13 | public Object execute(Instrumentation instrumentation, Object arg) throws Exception {
14 | var mappings = (String) arg;
15 | var mcClass = findMinecraftClass(mappings);
16 | var mcInstance = getMinecraftInstance(mcClass,mappings,instrumentation);
17 | var taskQueue = getMinecraftTaskQueue(mcInstance,mappings);
18 |
19 | if(Objects.isNull(taskQueue)){
20 | System.out.println("Failed to find task queue");
21 | return null;
22 | }
23 | return taskQueue;
24 | }
25 |
26 | /**
27 | * Get minecraft task queue
28 | * @param minecraftObject minecraft instance
29 | * @param mappingData mapping data
30 | * @return minecraft task queue
31 | * @throws Exception if failed to get queue
32 | */
33 | private Queue getMinecraftTaskQueue(Object minecraftObject,String mappingData) throws Exception{
34 | String fieldName = "";
35 | var scanner = new Scanner(mappingData);
36 | while(scanner.hasNextLine()){
37 | var line = scanner.nextLine();
38 | if(line.contains("progressTasks") && line.contains("java.util.Queue progressTasks")){
39 | fieldName = line.split(" -> ")[1];
40 | break;
41 | }
42 | }
43 |
44 | var method = minecraftObject.getClass().getDeclaredField(fieldName);
45 | method.setAccessible(true);
46 | return (Queue) method.get(minecraftObject);
47 | }
48 |
49 | /**
50 | * Get minecraft instance
51 | * @param className minecraft class name
52 | * @param mappingData mapping data
53 | * @return minecraft instance
54 | * @throws Exception
55 | */
56 | private Object getMinecraftInstance(String className,String mappingData,Instrumentation instrumentation) throws Exception{
57 |
58 | String methodName = "";
59 | var scanner = new Scanner(mappingData);
60 | while(scanner.hasNextLine()){
61 | var line = scanner.nextLine();
62 | if(line.contains("getInstance()")){
63 | if(line.contains("net.minecraft.client.Minecraft") && line.contains(" -> ")){
64 | methodName = line.split(" -> ")[1];
65 | break;
66 | }
67 | }
68 | }
69 |
70 | if(methodName.isEmpty()){
71 | System.err.println("[PreHook] Failed to find getInstance() method name!");
72 | return null;
73 | }
74 |
75 | for(Class clazz : instrumentation.getAllLoadedClasses()){
76 | if(clazz.getSimpleName().equals(className)){
77 | var method = clazz.getDeclaredMethod(methodName);
78 | method.setAccessible(true);
79 | return method.invoke(null);
80 | }
81 | }
82 |
83 | return null;
84 | }
85 |
86 | /**
87 | * Get minecraft class name
88 | * @param mappingData mapping data
89 | * @return minecraft class name
90 | */
91 | private String findMinecraftClass(String mappingData){
92 | var scanner = new Scanner(mappingData);
93 | while(scanner.hasNextLine()){
94 | var line = scanner.nextLine();
95 | if(line.contains("net.minecraft.client.Minecraft")){
96 | if(line.contains(" -> ") && line.endsWith(":") && !line.contains("$")){
97 | return line.split(" -> ")[1].split(":")[0];
98 | }
99 | }
100 | }
101 | return null;
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/agent/modules/impl/VersionFinderModule.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.agent.modules.impl;
2 |
3 | import me.dickmeister.agent.modules.AgentModule;
4 |
5 | import java.lang.instrument.Instrumentation;
6 |
7 | public class VersionFinderModule extends AgentModule {
8 |
9 | @Override
10 | public Object execute(Instrumentation instrumentation,Object arg) throws Exception {
11 | var classes = instrumentation.getAllLoadedClasses();
12 | for (var clazz : classes) {
13 | if(clazz.getSimpleName().equals("ab")) { //SharedConstants
14 | var versionStringField = clazz.getDeclaredField("d"); //VERSION_STRING
15 | return versionStringField.get(null);
16 | }
17 | }
18 |
19 | return null;
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/agent/modules/impl/VersionMappingDownloaderModule.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.agent.modules.impl;
2 |
3 | import com.google.gson.Gson;
4 | import com.google.gson.GsonBuilder;
5 | import com.google.gson.JsonElement;
6 | import com.google.gson.JsonObject;
7 | import me.dickmeister.agent.modules.AgentModule;
8 |
9 | import java.io.BufferedReader;
10 | import java.io.InputStreamReader;
11 | import java.lang.instrument.Instrumentation;
12 | import java.net.URL;
13 | import java.nio.charset.StandardCharsets;
14 |
15 | public class VersionMappingDownloaderModule extends AgentModule {
16 |
17 | private final String VERSION_MANIFEST = "https://launchermeta.mojang.com/mc/game/version_manifest.json";
18 |
19 | @Override
20 | public Object execute(Instrumentation instrumentation, Object arg) throws Exception {
21 | var gson = new GsonBuilder().create();
22 |
23 | var versionString = (String) arg;
24 | var manifestData = this.readAllFromURL(VERSION_MANIFEST);
25 | var versionManifestUrl = this.readVersionLists(versionString, gson.fromJson(manifestData, JsonObject.class));
26 | var mappingsUrl = this.readVersionManifest(gson,versionManifestUrl);
27 | return readAllFromURL(mappingsUrl);
28 | }
29 |
30 | /**
31 | * Get mappings from the client manifest
32 | * @param gson Gson instance
33 | * @param url URL to the client manifest
34 | * @return Mappings url
35 | * @throws Exception If the url is not found
36 | */
37 | private String readVersionManifest(Gson gson, String url) throws Exception{
38 | var data = this.readAllFromURL(url);
39 | var object = gson.fromJson(data, JsonObject.class);
40 | var downloads = object.get("downloads").getAsJsonObject();
41 | var clientMappings = downloads.get("client_mappings").getAsJsonObject();
42 | return clientMappings.get("url").getAsString();
43 | }
44 |
45 | /**
46 | * Get version manifest from version lists
47 | * @param versionName The version name to get the manifest for
48 | * @param object The version list object
49 | * @return The manifest url
50 | */
51 | private String readVersionLists(String versionName, JsonObject object){
52 | var versions = object.getAsJsonArray("versions");
53 | for(JsonElement element : versions){
54 | var version = element.getAsJsonObject();
55 | if(version.get("id").getAsString().equals(versionName)) return version.get("url").getAsString();
56 | }
57 |
58 | return null;
59 | }
60 |
61 | /**
62 | * Read all data as string from URL
63 | */
64 | private String readAllFromURL(String url) throws Exception{
65 | try (var is = new URL(url).openStream()) {
66 | var reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
67 | var sb = new StringBuilder();
68 | int cp;
69 | while ((cp = reader.read()) != -1) {
70 | sb.append((char) cp);
71 | }
72 | return sb.toString();
73 | }
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/ClientMain.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client;
2 |
3 | import com.darkmagician6.eventapi.EventManager;
4 | import com.darkmagician6.eventapi.EventTarget;
5 | import me.dickmeister.client.core.command.CommandManager;
6 | import me.dickmeister.client.core.event.EventDistributor;
7 | import me.dickmeister.client.core.event.EventInjector;
8 | import me.dickmeister.client.core.event.impl.ClientInternalTickEvent;
9 | import me.dickmeister.client.core.event.impl.Render2DEvent;
10 | import me.dickmeister.client.core.gui.GuiIngameRenderer;
11 | import me.dickmeister.client.core.module.ModuleManager;
12 | import me.dickmeister.client.core.utils.minecraft.MinecraftUtil;
13 | import me.dickmeister.client.mappings.MappingManager;
14 | import me.dickmeister.client.mappings.VersionMappingsLoader;
15 | import me.dickmeister.client.mappings.loader.MappingsLoader;
16 | import me.dickmeister.client.tasks.TickingTask;
17 | import me.dickmeister.client.transformers.TestTransformer;
18 | import me.dickmeister.client.version.VersionFinder;
19 | import me.dickmeister.common.util.LogUtil;
20 | import org.reflections.Reflections;
21 | import org.slf4j.LoggerFactory;
22 |
23 | import java.lang.instrument.ClassDefinition;
24 | import java.lang.instrument.Instrumentation;
25 | import java.util.concurrent.Executors;
26 | import java.util.concurrent.ScheduledExecutorService;
27 | import java.util.concurrent.TimeUnit;
28 | import java.util.logging.Level;
29 | import java.util.logging.Logger;
30 |
31 | public class ClientMain {
32 | public static final boolean DEBUG = true;
33 |
34 | public static Instrumentation instrumentation;
35 | private boolean initialized = false;
36 | private final ScheduledExecutorService tickingService;
37 | private static ClientMain instance;
38 |
39 | private final MappingManager mappingManager = new MappingManager();
40 | private final EventDistributor eventDistributor = new EventDistributor();
41 | private final CommandManager commandManager = new CommandManager();
42 | private final ModuleManager moduleManager = new ModuleManager();
43 |
44 | private MinecraftUtil minecraftUtil;
45 |
46 | public ClientMain(){
47 | tickingService = Executors.newSingleThreadScheduledExecutor();
48 | instance = this;
49 | }
50 |
51 | public void initialize() throws Exception {
52 |
53 |
54 | Logger.getLogger("org.reflections").setLevel(Level.OFF);
55 |
56 | LogUtil.log("Initializing client...");
57 | tickingService.scheduleAtFixedRate(new TickingTask(), 0, 50, TimeUnit.MILLISECONDS);
58 |
59 | LogUtil.log("Checking client version...");
60 | var version = new VersionFinder().findVersion();
61 | if(version == null) {
62 | LogUtil.log("Failed to find client version!");
63 | return;
64 | }
65 |
66 | LogUtil.log("Client version: %s", version.getVersion());
67 | LogUtil.log("Client protocol: %s", version.getProtocol());
68 |
69 | LogUtil.log("Downloading mappings...");
70 | var mappingsLoader = new MappingsLoader(mappingManager);
71 | var mappingsUrl = new VersionMappingsLoader().loadFromVersion(version);
72 | mappingsLoader.loadFromUrl(mappingsUrl);
73 |
74 | if(mappingManager.getMappedClasses().isEmpty()){
75 | LogUtil.err("Failed to load mappings data!");
76 | return;
77 | }
78 |
79 | LogUtil.log("Loaded %s mapped classes!", mappingManager.getMappedClasses().size());
80 |
81 | LogUtil.log("Injecting events...");
82 | var eventInjector = new EventInjector();
83 | eventInjector.initialize();
84 |
85 | commandManager.initialize();
86 | moduleManager.initialize();
87 |
88 | minecraftUtil = MinecraftUtil.getFromVersion(version.getVersion());
89 | if(minecraftUtil == null){
90 | LogUtil.err("Unsupported version: %s", version.getVersion());
91 | return;
92 | }
93 |
94 | LogUtil.log("Client initialized!");
95 |
96 | instrumentation.addTransformer(new TestTransformer());
97 | var clazz = ClientMain.getMappingManager().translateClassName("net.minecraft.world.entity.player.Player");
98 | instrumentation.retransformClasses(Class.forName(clazz));
99 |
100 | this.initialized = true;
101 | }
102 |
103 | public void start(){
104 | if(!initialized){
105 | LogUtil.err("Failed to start: client is not initialized!");
106 | return;
107 | }
108 |
109 | EventManager.register(new GuiIngameRenderer());
110 | LogUtil.log("Starting client...");
111 | }
112 |
113 | public static void invokeClient(Instrumentation inst){
114 | try {
115 | instrumentation = inst;
116 | instance.initialize();
117 | instance.start();
118 | }catch(Exception e){
119 | LogUtil.err("Failed to start client!");
120 | e.printStackTrace();
121 | }
122 | }
123 |
124 | public static ClientMain getInstance() {
125 | return instance;
126 | }
127 |
128 | public EventDistributor getEventDistributor() {
129 | return eventDistributor;
130 | }
131 |
132 | public ModuleManager getModuleManager() {
133 | return moduleManager;
134 | }
135 |
136 | public CommandManager getCommandManager() {
137 | return commandManager;
138 | }
139 | public static MinecraftUtil getMinecraftUtil() {
140 | return getInstance().minecraftUtil;
141 | }
142 |
143 | public static MappingManager getMappingManager() {
144 | return instance.mappingManager;
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/command/Command.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.command;
2 |
3 | public abstract class Command {
4 |
5 | private final String prefix;
6 | private final String usage;
7 | private final String description;
8 |
9 | public Command(String prefix, String usage, String description) {
10 | this.prefix = prefix;
11 | this.usage = usage;
12 | this.description = description;
13 | }
14 |
15 | public abstract void execute(String[] args) throws Exception;
16 |
17 | public String getDescription() {
18 | return description;
19 | }
20 |
21 | public String getPrefix() {
22 | return prefix;
23 | }
24 |
25 | public String getUsage() {
26 | return usage;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/command/CommandManager.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.command;
2 |
3 | import com.darkmagician6.eventapi.EventManager;
4 | import com.darkmagician6.eventapi.EventTarget;
5 | import me.dickmeister.client.ClientMain;
6 | import me.dickmeister.client.core.command.impl.HelpCommand;
7 | import me.dickmeister.client.core.command.impl.HitboxCommand;
8 | import me.dickmeister.client.core.command.impl.PanicCommand;
9 | import me.dickmeister.client.core.command.impl.ToggleCommand;
10 | import me.dickmeister.client.core.event.impl.PlayerChatEvent;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | public class CommandManager {
16 |
17 | private final List commandList = new ArrayList<>();
18 |
19 | public void initialize(){
20 | commandList.add(new HelpCommand());
21 | commandList.add(new PanicCommand());
22 | commandList.add(new ToggleCommand());
23 | commandList.add(new HitboxCommand());
24 | EventManager.register(this);
25 | }
26 |
27 | @EventTarget
28 | public void onChat(PlayerChatEvent event){
29 | var message = event.getMessage();
30 | if(message.startsWith(",")){
31 |
32 | var args = message.split(" ");
33 | var command = args[0].substring(1);
34 |
35 | var commandObject = commandList.stream().filter(cmd -> cmd.getPrefix().equalsIgnoreCase(command)).findFirst();
36 | commandObject.ifPresentOrElse(cmd -> {
37 | try {
38 | cmd.execute(args);
39 | } catch (Exception e) {
40 | try {
41 | ClientMain.getMinecraftUtil().sendSystemMessage("&cFailed to execute command!");
42 | e.printStackTrace();
43 | }catch(Exception e1){
44 | e1.printStackTrace();
45 | }
46 | }
47 | }, () -> {
48 | try {
49 | ClientMain.getMinecraftUtil().sendSystemMessage("&cCommand not found!");
50 | }catch(Exception e){
51 | e.printStackTrace();
52 | }
53 | });
54 |
55 |
56 | event.setCancelled(true);
57 | }
58 | }
59 |
60 | public List getCommandList() {
61 | return commandList;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/command/impl/HelpCommand.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.command.impl;
2 |
3 | import me.dickmeister.client.ClientMain;
4 | import me.dickmeister.client.core.command.Command;
5 |
6 | public class HelpCommand extends Command {
7 |
8 | public HelpCommand() {
9 | super("help","","Shows list of commands and their usage");
10 | }
11 |
12 | @Override
13 | public void execute(String[] args) throws Exception {
14 | var cmdManager = ClientMain.getInstance().getCommandManager();
15 | var spacing = " ".repeat(4);
16 | ClientMain.getMinecraftUtil().sendSystemMessage("&aAvailable commands&7:");
17 | cmdManager.getCommandList().forEach(cmd -> {
18 | try {
19 | ClientMain.getMinecraftUtil().sendSystemMessage(spacing + "&a," + cmd.getPrefix() + " &7" + cmd.getUsage() + " &8- &7" + cmd.getDescription());
20 | }catch(Exception e){}
21 | });
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/command/impl/HitboxCommand.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.command.impl;
2 |
3 | import me.dickmeister.client.core.command.Command;
4 | import me.dickmeister.client.core.module.impl.combat.HitboxModule;
5 |
6 | public class HitboxCommand extends Command {
7 |
8 | public HitboxCommand() {
9 | super("hitbox", "[width] [height]", "Expands player hitboxes");
10 | }
11 |
12 | @Override
13 | public void execute(String[] args) throws Exception {
14 | var width = Double.parseDouble(args[1]);
15 | var height = Double.parseDouble(args[2]);
16 |
17 | HitboxModule.hitboxWidth = (float) width;
18 | HitboxModule.hitboxHeight = (float) height;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/command/impl/PanicCommand.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.command.impl;
2 |
3 | import com.darkmagician6.eventapi.EventManager;
4 | import me.dickmeister.client.ClientMain;
5 | import me.dickmeister.client.core.command.Command;
6 |
7 | public class PanicCommand extends Command {
8 |
9 | public PanicCommand() {
10 | super("panic", "","Panic command");
11 | }
12 |
13 | @Override
14 | public void execute(String[] args) throws Exception {
15 | EventManager.getRegistryMap().clear();
16 | ClientMain.getInstance().getModuleManager().getModuleList().forEach(m -> {
17 | if(m.isEnabled()) m.toggle();
18 | });
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/command/impl/ToggleCommand.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.command.impl;
2 |
3 | import me.dickmeister.client.ClientMain;
4 | import me.dickmeister.client.core.command.Command;
5 |
6 | import java.util.Objects;
7 |
8 | public class ToggleCommand extends Command {
9 |
10 | public ToggleCommand() {
11 | super("toggle", "[modulename]","Toggle cheat module");
12 | }
13 |
14 | @Override
15 | public void execute(String[] args) throws Exception {
16 | var name = args[1];
17 | var module = ClientMain.getInstance().getModuleManager().getModuleList().stream().filter(m -> m.getName().equalsIgnoreCase(name)).findFirst().orElse(null);
18 | if(Objects.nonNull(module)){
19 | module.toggle();
20 | ClientMain.getMinecraftUtil().sendSystemMessage("&aModule " + module.getName() + " is now " + (module.isEnabled() ? "&aenabled" : "&cdisabled"));
21 | return;
22 | }
23 |
24 | ClientMain.getMinecraftUtil().sendSystemMessage("&cModule not found");
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/event/EventDistributor.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.event;
2 |
3 | import com.darkmagician6.eventapi.EventManager;
4 | import me.dickmeister.client.core.event.impl.KeyPressEvent;
5 | import me.dickmeister.client.core.event.impl.PlayerChatEvent;
6 | import me.dickmeister.client.core.event.impl.Render2DEvent;
7 |
8 | public class EventDistributor {
9 |
10 | public boolean onChat(String message){
11 | var event = new PlayerChatEvent(message);
12 | EventManager.call(event);
13 | return event.isCancelled();
14 | }
15 |
16 | public boolean onRender(Object poseStack,Float partialTicks){
17 | var event = new Render2DEvent(poseStack,partialTicks);
18 | EventManager.call(event);
19 | return false;
20 | }
21 |
22 | public boolean onKeyPress(long pressTime, int keyCode, int keyCode1, int pressType, int idkwhatthisis){
23 | var event = new KeyPressEvent(keyCode,pressType);
24 | EventManager.call(event);
25 | return false;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/event/EventInjector.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.event;
2 |
3 | import javassist.ClassPool;
4 | import javassist.CtClass;
5 | import javassist.CtMethod;
6 | import javassist.LoaderClassPath;
7 | import me.dickmeister.client.ClientMain;
8 | import me.dickmeister.client.core.event.util.EventInitializer;
9 | import me.dickmeister.client.mappings.MappingManager;
10 | import me.dickmeister.common.util.LogUtil;
11 | import net.bytebuddy.ByteBuddy;
12 | import net.bytebuddy.agent.ByteBuddyAgent;
13 | import net.bytebuddy.asm.Advice;
14 | import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
15 | import net.bytebuddy.dynamic.scaffold.TypeValidation;
16 | import org.reflections.Reflections;
17 | import org.reflections.scanners.SubTypesScanner;
18 |
19 | import java.io.BufferedReader;
20 | import java.io.InputStream;
21 | import java.io.InputStreamReader;
22 | import java.util.HashSet;
23 | import java.util.Set;
24 | import java.util.stream.Collectors;
25 |
26 | import static net.bytebuddy.matcher.ElementMatchers.named;
27 |
28 | public class EventInjector {
29 |
30 | public void initialize(){
31 |
32 | var loader = Thread.currentThread().getContextClassLoader();
33 | var mappingManager = ClientMain.getMappingManager();
34 |
35 | try {
36 | ByteBuddyAgent.install();
37 | var classes = findAllClassesUsingReflectionsLibrary("me.dickmeister.client.core.event.impl");
38 | for(var clazz : classes){
39 | var instance = clazz.newInstance();
40 | if(instance instanceof EventInitializer){
41 | ((EventInitializer) instance).initialize(new ByteBuddy(), loader, mappingManager);
42 | LogUtil.log("Injected event: " + clazz.getName());
43 | }
44 | }
45 | }catch(Exception e){
46 | e.printStackTrace();
47 | }
48 |
49 | }
50 |
51 | public Set findAllClassesUsingReflectionsLibrary(String packageName) {
52 | Reflections reflections = new Reflections(packageName, new SubTypesScanner(false));
53 | return new HashSet<>(reflections.getSubTypesOf(EventInitializer.class));
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/event/impl/ClientInternalTickEvent.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.event.impl;
2 |
3 | import com.darkmagician6.eventapi.events.Event;
4 | import me.dickmeister.client.core.event.util.EventInitializer;
5 | import me.dickmeister.client.mappings.MappingManager;
6 | import net.bytebuddy.ByteBuddy;
7 |
8 | public class ClientInternalTickEvent implements Event, EventInitializer {
9 | @Override
10 | public void initialize(ByteBuddy byteBuddy, ClassLoader loader, MappingManager mappingManager) throws Exception {
11 | //Ignore this, called internally by the client
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/event/impl/KeyPressEvent.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.event.impl;
2 |
3 | import com.darkmagician6.eventapi.events.Event;
4 | import me.dickmeister.client.core.event.util.EventCaller;
5 | import me.dickmeister.client.core.event.util.EventInitializer;
6 | import me.dickmeister.client.mappings.MappingManager;
7 | import net.bytebuddy.ByteBuddy;
8 | import net.bytebuddy.asm.Advice;
9 | import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
10 | import net.bytebuddy.dynamic.scaffold.TypeValidation;
11 | import net.bytebuddy.implementation.bind.annotation.RuntimeType;
12 |
13 | import static net.bytebuddy.matcher.ElementMatchers.named;
14 | import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
15 |
16 | public class KeyPressEvent implements Event, EventInitializer {
17 |
18 | private int keyCode;
19 | private int pressType; // 1 = pressed, 0 = released, 2 = pressed still
20 |
21 | public KeyPressEvent(int keyCode,int pressType) {
22 | this.keyCode = keyCode;
23 | this.pressType = pressType;
24 | }
25 |
26 | public KeyPressEvent(){}
27 |
28 | public int getKeyCode() {
29 | return keyCode;
30 | }
31 |
32 | public int getPressType() {
33 | return pressType;
34 | }
35 |
36 | @RuntimeType
37 | @Advice.OnMethodEnter(skipOn = Boolean.class)
38 | public static Boolean chat(@RuntimeType long p_90894_, int p_90895_, int p_90896_, int p_90897_, int p_90898_) {
39 | if(EventCaller.callEvent("onKeyPress", p_90894_, p_90895_, p_90896_, p_90897_, p_90898_)) return true;
40 | return null;
41 | }
42 |
43 | @Override
44 | public void initialize(ByteBuddy byteBuddy, ClassLoader loader, MappingManager mappingManager) throws Exception {
45 | // public void keyPress(long p_90894_, int p_90895_, int p_90896_, int p_90897_, int p_90898_) {
46 |
47 | //net.minecraft.client.KeyboardHandler
48 | var className = mappingManager.translateClassName("net.minecraft.client.KeyboardHandler");
49 | var methodName = mappingManager.translateMethodName("net.minecraft.client.KeyboardHandler","keyPress(JIIII)V");
50 |
51 | var clazz = loader.loadClass(className);
52 |
53 | byteBuddy.with(TypeValidation.DISABLED)
54 | .redefine(clazz)
55 | .visit(Advice.to(Class.forName("me.dickmeister.client.core.event.impl.KeyPressEvent")).withExceptionPrinting()
56 | .on(named(methodName).and(takesArgument(0, long.class).and(takesArgument(1, int.class).and(takesArgument(2, int.class).and(takesArgument(3, int.class).and(takesArgument(4, int.class))))))))
57 | .make().load(loader, ClassReloadingStrategy.fromInstalledAgent());
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/event/impl/PlayerChatEvent.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.event.impl;
2 |
3 | import com.darkmagician6.eventapi.events.callables.EventCancellable;
4 | import me.dickmeister.client.core.event.util.EventCaller;
5 | import me.dickmeister.client.core.event.util.EventInitializer;
6 | import me.dickmeister.client.mappings.MappingManager;
7 | import net.bytebuddy.ByteBuddy;
8 | import net.bytebuddy.asm.Advice;
9 | import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
10 | import net.bytebuddy.dynamic.scaffold.TypeValidation;
11 | import net.bytebuddy.implementation.bind.annotation.RuntimeType;
12 |
13 | import static net.bytebuddy.matcher.ElementMatchers.named;
14 |
15 | public class PlayerChatEvent extends EventCancellable implements EventInitializer {
16 |
17 | private String message;
18 |
19 | public PlayerChatEvent(){}
20 |
21 | public PlayerChatEvent(String message) {
22 | this.message = message;
23 | }
24 |
25 | public String getMessage() {
26 | return message;
27 | }
28 |
29 | @RuntimeType
30 | @Advice.OnMethodEnter(skipOn = Boolean.class)
31 | public static Boolean chat(@RuntimeType String p_108740_) {
32 | if(EventCaller.callEvent("onChat", p_108740_)) return true;
33 | return null;
34 | }
35 |
36 | @Override
37 | public void initialize(ByteBuddy byteBuddy, ClassLoader loader, MappingManager mappingManager) throws Exception{
38 | var clazz = loader.loadClass(mappingManager.translateClassName("net.minecraft.client.player.LocalPlayer"));
39 | var method = mappingManager.translateMethodName("net.minecraft.client.player.LocalPlayer", "chat(Ljava/lang/String;)V");
40 | byteBuddy.with(TypeValidation.DISABLED)
41 | .redefine(clazz)
42 | .visit(Advice.to(Class.forName("me.dickmeister.client.core.event.impl.PlayerChatEvent")).withExceptionPrinting().on(named(method)))
43 | .make().load(loader, ClassReloadingStrategy.fromInstalledAgent());
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/event/impl/Render2DEvent.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.event.impl;
2 |
3 | import com.darkmagician6.eventapi.events.Event;
4 | import me.dickmeister.client.core.event.util.EventCaller;
5 | import me.dickmeister.client.core.event.util.EventInitializer;
6 | import me.dickmeister.client.mappings.MappingManager;
7 | import net.bytebuddy.ByteBuddy;
8 | import net.bytebuddy.asm.Advice;
9 | import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
10 | import net.bytebuddy.dynamic.scaffold.TypeValidation;
11 | import net.bytebuddy.implementation.bind.annotation.RuntimeType;
12 |
13 | import static net.bytebuddy.matcher.ElementMatchers.*;
14 |
15 | public class Render2DEvent implements Event, EventInitializer {
16 |
17 | private Object poseStack;
18 | private float partialTicks;
19 |
20 | public Render2DEvent(){}
21 |
22 | public Render2DEvent(Object poseStack,float partialTicks) {
23 | this.poseStack = poseStack;
24 | this.partialTicks = partialTicks;
25 | }
26 |
27 | public float getPartialTicks() {
28 | return partialTicks;
29 | }
30 |
31 | public Object getPoseStack() {
32 | return poseStack;
33 | }
34 |
35 | @RuntimeType
36 | @Advice.OnMethodEnter(skipOn = Boolean.class)
37 | public static Boolean onRender(@RuntimeType Object obj, float partialTicks) {
38 | if(EventCaller.callEvent("onRender", obj,partialTicks)) return true;
39 | return null;
40 | }
41 |
42 | @Override
43 | public void initialize(ByteBuddy byteBuddy, ClassLoader loader, MappingManager mappingManager) throws Exception {
44 | var clazz = loader.loadClass(mappingManager.translateClassName("net.minecraft.client.gui.Gui"));
45 | var method = mappingManager.translateMethodName("net.minecraft.client.gui.Gui", "render(Lcom/mojang/blaze3d/vertex/PoseStack;F)V");
46 | byteBuddy.with(TypeValidation.DISABLED)
47 | .redefine(clazz)
48 | .visit(Advice.to(Class.forName(this.getClass().getName())).withExceptionPrinting().on(named(method).and(takesArgument(1, float.class))))
49 | .make().load(loader, ClassReloadingStrategy.fromInstalledAgent());
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/event/util/EventCaller.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.event.util;
2 |
3 | import me.dickmeister.common.util.LogUtil;
4 |
5 | import java.util.Arrays;
6 | import java.util.Objects;
7 | import java.util.concurrent.atomic.AtomicBoolean;
8 |
9 | public class EventCaller {
10 |
11 | public static boolean callEvent(String methodName,Object... args){
12 | var classLoader = Thread.currentThread().getContextClassLoader();
13 |
14 | try {
15 | var clazz = classLoader.loadClass("me.dickmeister.client.ClientMain");
16 | var instance = clazz.getDeclaredMethod("getInstance").invoke(null);
17 |
18 | var eventDistributor = clazz.getDeclaredMethod("getEventDistributor").invoke(instance);
19 |
20 | var result = new AtomicBoolean(false);
21 | var methods = eventDistributor.getClass().getMethods();
22 | Arrays.stream(methods).forEach(m -> {
23 | if(m.getName().equals(methodName)){
24 | try {
25 | result.set((Boolean) m.invoke(eventDistributor, args));
26 | }catch(Exception e){
27 | e.printStackTrace();
28 | }
29 | }
30 | });
31 |
32 |
33 | return result.get();
34 |
35 | }catch(Exception e){
36 | LogUtil.err("Failed to invoke event " + methodName);
37 | e.printStackTrace();
38 | }
39 |
40 | return false;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/event/util/EventInitializer.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.event.util;
2 |
3 | import me.dickmeister.client.mappings.MappingManager;
4 | import net.bytebuddy.ByteBuddy;
5 |
6 | public interface EventInitializer {
7 |
8 | void initialize(ByteBuddy byteBuddy, ClassLoader loader, MappingManager mappingManager) throws Exception;
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/gui/GuiIngameRenderer.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.gui;
2 |
3 | import com.darkmagician6.eventapi.EventTarget;
4 | import me.dickmeister.client.ClientMain;
5 | import me.dickmeister.client.core.event.impl.Render2DEvent;
6 |
7 | import java.util.concurrent.atomic.AtomicInteger;
8 |
9 | public class GuiIngameRenderer {
10 |
11 | @EventTarget
12 | public void onRender2D(Render2DEvent event) {
13 | try {
14 | ClientMain.getMinecraftUtil().drawFontString(event.getPoseStack(), "InjectClient v0", 5, 5, 0xFFFFFF);
15 |
16 | var modules = ClientMain.getInstance().getModuleManager();
17 |
18 | AtomicInteger yIndex = new AtomicInteger(15);
19 |
20 | modules.getModuleList().forEach(module -> {
21 | if(module.isEnabled()){
22 | var yPos = yIndex.getAndAdd(10);
23 | try {
24 | ClientMain.getMinecraftUtil().drawFontString(event.getPoseStack(), module.getName(), 5, yPos, 0xFFFFFF);
25 | }catch(Exception e){
26 | e.printStackTrace();
27 | }
28 | }
29 | });
30 |
31 | }catch(Exception e){
32 | e.printStackTrace();
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/module/Module.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.module;
2 |
3 | import com.darkmagician6.eventapi.EventManager;
4 |
5 | public abstract class Module {
6 |
7 | private final String name;
8 | private final int keybind;
9 | private final String description;
10 | private final ModuleCategory moduleCategory;
11 |
12 | private boolean enabled;
13 |
14 | public Module(String name, int keybind, String description, ModuleCategory moduleCategory) {
15 | this.name = name;
16 | this.keybind = keybind;
17 | this.description = description;
18 | this.moduleCategory = moduleCategory;
19 | }
20 |
21 | public void onEnable(){
22 | EventManager.register(this);
23 | }
24 |
25 | public void onDisable(){
26 | EventManager.unregister(this);
27 | }
28 |
29 | public void toggle(){
30 | this.enabled = !this.enabled;
31 | if(this.enabled){
32 | onEnable();
33 | return;
34 | }
35 |
36 | onDisable();
37 | }
38 |
39 | public String getDescription() {
40 | return description;
41 | }
42 |
43 | public int getKeybind() {
44 | return keybind;
45 | }
46 |
47 | public String getName() {
48 | return name;
49 | }
50 |
51 | public boolean isEnabled() {
52 | return enabled;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/module/ModuleCategory.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.module;
2 |
3 | public enum ModuleCategory {
4 |
5 | COMBAT,
6 | RENDER,
7 | PLAYER,
8 | OTHER
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/module/ModuleManager.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.module;
2 |
3 | import com.darkmagician6.eventapi.EventManager;
4 | import com.darkmagician6.eventapi.EventTarget;
5 | import me.dickmeister.client.core.event.impl.KeyPressEvent;
6 | import me.dickmeister.client.core.event.util.EventInitializer;
7 | import me.dickmeister.common.util.LogUtil;
8 | import org.reflections.Reflections;
9 | import org.reflections.scanners.SubTypesScanner;
10 |
11 | import java.util.ArrayList;
12 | import java.util.HashSet;
13 | import java.util.List;
14 |
15 | public class ModuleManager {
16 |
17 | private final List moduleList = new ArrayList<>();
18 |
19 | public void initialize() throws InstantiationException, IllegalAccessException {
20 | Reflections reflections = new Reflections("me.dickmeister.client.core.module.impl", new SubTypesScanner());
21 | var modules = reflections.getSubTypesOf(Module.class);
22 |
23 | for(var module : modules){
24 | var instance = module.newInstance();
25 | LogUtil.log("Loaded module: %s", module.getSimpleName());
26 | moduleList.add(instance);
27 | }
28 |
29 | EventManager.register(this);
30 | }
31 |
32 | @EventTarget
33 | public void onKeyPress(KeyPressEvent event){
34 |
35 | if(event.getPressType() == 1){
36 | getModuleList().forEach(m -> {
37 | var keybind = m.getKeybind();
38 |
39 | if(keybind != 0 && keybind == event.getKeyCode())
40 | m.toggle();
41 |
42 | });
43 | }
44 | }
45 |
46 |
47 | public void toggleModule(Module module){
48 | module.toggle();
49 | }
50 |
51 | public List getModuleList() {
52 | return moduleList;
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/module/impl/combat/HitboxModule.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.module.impl.combat;
2 |
3 | import me.dickmeister.client.ClientMain;
4 | import me.dickmeister.client.core.module.Module;
5 | import me.dickmeister.client.core.module.ModuleCategory;
6 | import me.dickmeister.client.core.utils.minecraft.MinecraftUtil;
7 |
8 | import java.awt.event.KeyEvent;
9 |
10 | public class HitboxModule extends Module {
11 |
12 | public HitboxModule() {
13 | super("Hitbox", KeyEvent.VK_K ,"Expands player hitboxes",ModuleCategory.COMBAT);
14 | }
15 |
16 | public static float hitboxWidth = 0.65f;
17 | public static float hitboxHeight = 1.9f;
18 |
19 | //Origin box 0.6F, 1.8F
20 | @Override
21 | public void onEnable() {
22 | super.onEnable();
23 |
24 | try {
25 | var player = ClientMain.getMinecraftUtil().getLocalPlayer();
26 | ClientMain.getMinecraftUtil().setPlayerDimensions(player, hitboxWidth, hitboxHeight);
27 | } catch (Exception e) {
28 | e.printStackTrace();
29 | }
30 |
31 | }
32 |
33 | @Override
34 | public void onDisable() {
35 | super.onDisable();
36 | try {
37 | var player = ClientMain.getMinecraftUtil().getLocalPlayer();
38 | ClientMain.getMinecraftUtil().setPlayerDimensions(player, 0.6F, 1.8F);
39 | } catch (Exception e) {
40 | e.printStackTrace();
41 | }
42 | }
43 |
44 |
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/module/impl/render/ESPModule.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.module.impl.render;
2 |
3 | import com.darkmagician6.eventapi.EventTarget;
4 | import me.dickmeister.client.ClientMain;
5 | import me.dickmeister.client.core.event.impl.ClientInternalTickEvent;
6 | import me.dickmeister.client.core.module.Module;
7 | import me.dickmeister.client.core.module.ModuleCategory;
8 |
9 | import java.awt.event.KeyEvent;
10 |
11 | public class ESPModule extends Module {
12 | public ESPModule() {
13 | super("ESP", KeyEvent.VK_O, "ESP", ModuleCategory.RENDER);
14 | }
15 |
16 | @Override
17 | public void onEnable() {
18 | super.onEnable();
19 | }
20 |
21 | @Override
22 | public void onDisable() {
23 | super.onDisable();
24 |
25 | try{
26 | var players = ClientMain.getMinecraftUtil().getAllPlayers();
27 | if(players == null){
28 | return;
29 | }
30 |
31 | for(var obj : players) {
32 | ClientMain.getMinecraftUtil().setSharedFlag(obj, 6, false);
33 | }
34 | }catch(Exception e){
35 | e.printStackTrace();
36 | }
37 | }
38 |
39 | @EventTarget
40 | public void tick(ClientInternalTickEvent event){
41 | try{
42 | var players = ClientMain.getMinecraftUtil().getAllPlayers();
43 | if(players == null){
44 | return;
45 | }
46 |
47 | for(var obj : players) {
48 | ClientMain.getMinecraftUtil().setSharedFlag(obj, 6, true);
49 | }
50 | }catch(Exception e){
51 | e.printStackTrace();
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/me/dickmeister/client/core/utils/minecraft/MinecraftUtil.java:
--------------------------------------------------------------------------------
1 | package me.dickmeister.client.core.utils.minecraft;
2 |
3 | import me.dickmeister.client.core.utils.minecraft.impl.MinecraftUtil_118x;
4 |
5 | import java.util.List;
6 |
7 | public abstract class MinecraftUtil {
8 |
9 | public static MinecraftUtil getFromVersion(String versionString){
10 | if(versionString.startsWith("1.18")){
11 | return new MinecraftUtil_118x();
12 | }
13 |
14 | return null;
15 | }
16 |
17 | public abstract void setPlayerDimensions(Object player, float width, float height) throws Exception;
18 | public abstract List