Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
245 changes: 240 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,251 @@
### Warning
# Cheat Utils

## Warning

If you use download button on github, repository will not work since it is using git submodules.

To download repository with submodules use below command:

`git clone --recurse-submodules https://github.com/Zergatul/cheatutils.git`

### Build
## Build

To build mod by yourself go to Forge or Fabric directory and run `gradlew build`.

### Debugging/Customizing Web App
## Debugging/Customizing Web App

Download repo (or just `/common/resources/web` directory), and add JVM argument in Minecraft launcher like this:
```

```bat
-Dcheatutils.web.dir=C:\full\path\to\web\directory
```
Now local website uses static files from this directory instead of mod resources.

Now local website uses static files from this directory instead of mod resources.

## Code Examples :-

### Adding a module to the mod :-

#### Step 1

Create your main class file.
This is where most of your modules code will be written.

First, navigate to the modules folder located in `common/java/com/zergatul/cheatutils/modules`.
Select the folder that best fits your module type.
from here on, we will refer to a theoretical module named "AutoPearl", however you should follow the same naming conventions

Create a new file : `"AutoPearl.java"`.

the class should be in this format:

```java
import com.zergatul.cheatutils.modules.Module;

public class AutoPearl implements Module {
public static final AutoPearl instance = new AutoPearl();
AutoPearl(){

}
}
```

#### Step 2

For the purposes of this explaination, it is assumed your module is named as "AutoPearl"
Register your module in the mod.
Navigate to `Modules.java` in the same directory.
Add your module to the following function

```java
public static void register() {
register(AutoPearl.instance);
}
```

Make sure you place it in the right position, modules are initialized in the order listed here. This includes the order of their events added to EventsApi

#### Step 3

Add your configuration class

Navigate to `common/java/com/zergatul/cheatutils/configs`

create a new file `AutoPearlConfig.java`

```java
package com.zergatul.cheatutils.configs;

public class AutoPearlConfig extends ModuleConfig implements ValidatableConfig {

AutoPearlConfig() {

}

@Override
public void validate() {
return;
}
}
```

add your config validation inside the `validate()` function, this is where you will add limits to your variables, for example clampign the range of a value.
If your API will be accessible from the scripting, it is highly recomended to include validation for any variables.

>[!NOTE]
> In case if your module does not require validation, you can skip `implements ValidatableConfig` and the overriden `public void validate()` function. When doing this, also skip adding validation to [`Root.java`](#adding-a-module-to-the-mod--)
>
> If your module does not require enable / disable, you can skip `extends ModuleConfig` as well. This also means you cannot use the `enabled` boolean or the `isEnabled()` inherited functions. Keep this in mind when creating the website / code for it.

you can also add any more functions or values to change here.
for example:

```java
public boolean bl1;
public double db1;
```

and so on. These must be public, you can also use functions internally, however functions will not work with the website API.
The API directly changes variables.

an example of a minimal config which does not need validation or enable variable:

```java
public class AutoPearlConfig {}
```

Next, navigate to `Config.java`, located in the same directory.

Add your config to the class

```java
public AutoPearlConfig classNameConfig = new AutoPearlConfig();
```

Now, navigate to `configStore.java`, located in the same directory and add these lines

```java
private void onConfigLoaded() {
config.classNameConfig.validate();
```

#### Step 4

Adding the module API for the website to work with.
Navigate to `common/java/com/zergatul/cheatutils/scripting/modules/`
make a new file `AutoPearlConfig.java`

add these lines

```java
package com.zergatul.cheatutils.scripting.modules;

import com.zergatul.cheatutils.configs.AutoPearlConfig;
import com.zergatul.cheatutils.configs.ConfigStore;

public class AutoPearlApi extends ModuleApi<AutoPearlConfig> {


@Override
protected AutoPearlConfig getConfig() {
return ConfigStore.instance.getConfig().classNameconfig;
}
}
```

#### Step 5

Allow the API to be accessed from scripting tools (this refers to user side scripting)

Navigate to `common/java/com/zergatul/cheatutils/scripting/Root.java`

Add the following lines inside the Root class.

```java
public static AutoPearlApi className = new AutoPearlApi();
```

This step is OPTIONAL and not required for module to function.
If you want your module configuration to be accessed from scripting
However, it is recomended to do this step

#### Step 6

Adding your module to the website

Navigate to `common/resources/web/modules.js`

Add your module under line 21 with the following format:

```javascript
module({
group: 'automation',
name: 'Display Name',
component: 'AutoPearl',
path: 'class-name',
tags: ['search', 'terms', 'identifers']
});
```

Make sure you add your module to the correct section with the rest of its group
There are the following groups that can be used:

```javascript
`automation`
`esp`
`hacks`
`visuals`
`scripting`
`utility`
```

In our example, we used `'automation'`, you can change this to match your module type

now navigate to `common/resources/web/components`
next, navigate to the relevant folder for your module from the available folders. This is mapped to the groups used, so ensure you use the same folder.

Create 2 new files:

* AutoPearl.js
* AutoPearl.html

inside the javascript file, add the following:

```javascript
import { createSimpleComponent } from '/components/SimpleModule.js';

export function createComponent(template) {
return createSimpleComponent('/api/class-name', template);
}

```

if you use any new components as listed in `common/resources/web/components.js` in your html, make sure to include them in your javascript file

for example:

```javascript
import { createSimpleComponent } from '/components/SimpleModule.js'

export function createComponent(template) {
return createSimpleComponent('/api/class-name', template, {
components: ['CodeBlock', 'ColorBox']
});
}
```

##### How to make your html file

This guide will focus on the working, for style and other formatting / component usage, look at the html of other modules already implemented

your html file should look like this:

```html
<div class="module-main" v-if="config">

</div>
```

all components can be found at `common/resources/web/components/common`

[Refer to this Document for more information and examples](./common/\/resources/web/Web%20Examples.md)
33 changes: 27 additions & 6 deletions common/java/com/zergatul/cheatutils/common/Events.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.zergatul.cheatutils.common.events.*;
import com.zergatul.cheatutils.controllers.SnapshotChunk;
import net.minecraft.WorldVersion;
import net.minecraft.client.DeltaTracker;
import net.minecraft.core.BlockPos;
import net.minecraft.network.Connection;
Expand All @@ -11,6 +12,8 @@
import net.minecraft.world.level.chunk.LevelChunk;
import org.joml.Vector2ic;

import java.util.function.Consumer;

public class Events {
// to better understand sequence of events they are ordered in trigger order

Expand Down Expand Up @@ -45,10 +48,6 @@ public class Events {
public static final SimpleEventHandler ClientTickEnd = new SimpleEventHandler();






public static final ParameterizedEventHandler<Connection> ClientPlayerLoggingIn = new ParameterizedEventHandler<>();
public static final SimpleEventHandler ClientPlayerLoggingOut = new SimpleEventHandler();
public static final ParameterizedEventHandler<LevelChunk> RawChunkLoaded = new ParameterizedEventHandler<>();
Expand All @@ -59,7 +58,6 @@ public class Events {
public static final ParameterizedEventHandler<BlockUpdateEvent> BlockUpdated = new ParameterizedEventHandler<>();



public static final CancelableEventHandler<PreRenderGuiOverlayEvent> PreRenderGuiOverlay = new CancelableEventHandler<>();

public static final CancelableEventHandler<MouseScrollEvent> MouseScroll = new CancelableEventHandler<>();
Expand All @@ -74,7 +72,7 @@ public class Events {
public static final SimpleEventHandler PostRenderTooltip = new SimpleEventHandler();
public static final ParameterizedEventHandler<ScreenRenderEvent> AfterScreenRendered = new ParameterizedEventHandler<>();
public static final CancelableEventHandler<SendChatEvent> SendChat = new CancelableEventHandler<>();
public static final CancelableEventHandler<BeforeAttackEvent> BeforeAttack = new CancelableEventHandler<>();

public static final ParameterizedEventHandler<Entity> EntityInteract = new ParameterizedEventHandler<>();
public static final ParameterizedEventHandler<BlockPos> BeforeInstaMine = new ParameterizedEventHandler<>();
public static final SimpleEventHandler WindowResize = new SimpleEventHandler();
Expand All @@ -85,4 +83,27 @@ public class Events {
public static final CancelableEventHandler<PlayerReleaseUsingItemEvent> PlayerReleaseUsingItem = new CancelableEventHandler<>();
public static final CancelableEventHandler<PlayerTurnByMouseEvent> PlayerTurnByMouse = new CancelableEventHandler<>();
public static final ParameterizedEventHandler<PlayerInfoUpdateEvent> PlayerInfoUpdated = new ParameterizedEventHandler<>();

//Attack Events ======================
public static final CancelableEventHandler<BeforeAttackEvent> BeforeAttack = new CancelableEventHandler<>();
public static final SimpleEventHandler AfterAttack = new SimpleEventHandler();
public static final SimpleEventHandler BeforeStartAttack = new SimpleEventHandler();
public static final SimpleEventHandler AfterStartAttack = new SimpleEventHandler();
//=====================================
/**
* binds 2 functions to the beforeAttack and afterAttack event respectively.
* Tries to ensure that the order of module execution is preserved <br>
* Example: <br>
* if there are 2 actions bound:
* <p>
* breachSwap and criticals, it should function like this:
* <p>
* {@code BreachSwapBefore -> CriticalsBefore -> Vanilla code -> CriticalsAfter -> BreachSwapAfter} <br>
* This ensures that the cleanup for each module always gets the same state as its initial condition
*/

public static void AttackEventHandler(Consumer<BeforeAttackEvent> beforeAttackFunction, Runnable afterAttackFunction, int priority) {
BeforeAttack.add(beforeAttackFunction, priority);
AfterAttack.add(afterAttackFunction, -priority);
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,59 @@
package com.zergatul.cheatutils.common.events;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;

public class CancelableEventHandler<T extends CancelableEvent> {

private final List<Entry<T>> entries = new ArrayList<>();
private final List<Consumer<T>> handlers = new ArrayList<>();
private int counter;

public void add(Consumer<T> handler) {
handlers.add(handler);
add(handler, 0);
}

/**
*
* @param handler Passed function that is added to the Event list
* @param priority Defaults to 0 when not passed.
* Events are executed in ascending order of their priority.
* If multiple functions have the same priority, it follows the order it was added <br>
* <br>
* Example execution order:
* {@code Priority 1 -> Priority 2}
*/
public void add(Consumer<T> handler, int priority) {
entries.add(new Entry<>(handler, priority, counter++));
Collections.sort(entries);

handlers.clear();
entries.stream().map(entry -> entry.handler).forEach(handlers::add);
}

public boolean trigger(T parameter) {
for (Consumer<T> handler: handlers) {
for (Consumer<T> handler : handlers) {
handler.accept(parameter);
if (parameter.isCanceled()) {
return true;
}
}
return false;
}

private record Entry<T>(Consumer<T> handler, int priority1, int priority2) implements Comparable<Entry<T>> {
@Override
public int compareTo(@NotNull Entry other) {
int result = Integer.compare(priority1, other.priority1);
if (result != 0) {
return result;
} else {
return Integer.compare(priority2, other.priority2);
}
}
}
}
Loading