Skip to content

ClickCrystals Development

ImproperIssues edited this page Oct 9, 2023 · 13 revisions

Resource/Texture Pack Development

Getting Resources

Hate how the in-game GUI looks? Did you know that you can change the textures with a resource pack? To start, all ClickCrystals assets can be found here.

The link above will take you to all the default textures on ClickCrystal's Github. In the repository, you can find all the texture assets that ClickCrystals uses, feel free to download them and edit them!

Do you want some examples of other resource packs for ClickCrystals? Visit ClickCrystalsPlus Pack on Modrinth

Creating the Pack

Just like how you would create a normal texture pack, follow the steps below:

  1. Create a folder with the name of your texture MyPack
  2. Inside of the folder create a new file named "pack.mcmeta" MyPack/pack.mcmeta
  3. In the same folder, create a new folder named "assets" MyPack/assets/
  4. Then in that assets folder create another folder inside of it MyPack/assets/clickcrystals/
  5. Go to the link provided above and download contents from its clickcrystals folder to the one that you just created https://github.com/ItziSpyder/ClickCrystals/tree/main/src/main/resources/assets/clickcrystals -> MyPack/assets/clickcrystals
  6. Start editing the textures and get creative!

ClickCrystals Fork Development

Forking and Cloning Repository

Hating the lack of features, or wanting new modules? Guess what? You can fork this repository and make your versions of ClickCrystals! (DISCLAIMER: DO NOT MARKET AS OWN WITHOUT GIVING US CREDIT!)

To set up your environment for making your version of ClickCrystals:

  1. Clone this repository or Github. (It does not matter if you make it public or private.)
  2. Make sure you have your IDE ready
  3. You would also want to make sure Git Desktop is downloaded to your computer
  4. In your IDE projects folder, open up the command prompt and type in git clone <your cloned repository link>
  5. Load up the project in your IDE and get creative!

Creating New Modules

Modules can be created by creating a Java class under the modules.modules package. It is best to note that creating a Module Java file directly under the modules can result in a structure looking rather unorganized. Your new Java class should extend the io.github.itzispyder.clickcrystals.modules.Module class, and inherit its constructor.

public class Foo extends Module {
 
 public Foo() {
  super("foo-module", Categories.MISC, "A custom module that I've made!");
 }
}

It is also important to implement the abstract methods from the Module class you extended from.

public class Foo extends Module {

 public Foo() {
  super("foo-module", Categories.MISC, "A custom module that I've made!");
 }

 @Override
 public void onEnable() {
 
 }

 @Override
 public void onDisable() {

 }
}

If your new module is going to be firing events, it is important to implement the io.github.itzispyder.clickcrystals.events.Listener interface After implementing the Listener interface, you would want to include a way to register this interface. In this case, we'll register the listener on enable and unregister on disable. The field system comes from the interface io.github.itzispyder.clickcrystals.Global that the Module class implements.

Any events will be fired with a method annotated by @io.github.itzispyder.clickcrystals.EventHandler. This is important, as the event bus won't pass on any methods without this annotation!

public class Foo extends Module implements Listener {

 public Foo() {
  super("foo-module", Categories.MISC, "A custom module that I've made!");
 }

 @Override
 public void onEnable() {
  system.addListener(this);
 }

 @Override
 public void onDisable() {
  system.removeListener(this);
 }

 @EventHandler // event annotation
 private void foo(/*Target Event*/) {
  // do something
 }
}

The tasks above may be found tedious, so there is also a way to simplify the creation of listener-type modules.

public class Foo extends ListenerModule {

 public Foo() {
  super("foo-module", Categories.MISC, "A custom module that I've made!");
 }

 @EventHandler // event annotation
 private void foo(/*Target Event*/) {
  // do something
 }
}

While creating your module, there are a few helper util classes that you may want to know about. The utils can be found under the package io.github.itzispyder.clickcrystals.util These include:

  • HotbarUtils which swaps to items in the hotbar, or getting in-hand items.
  • InvUtils or inventory utils, sends inventory packets like swapping to offhand or clicking on items, or even dropping items.
  • PlayerUtils which include helper methods for the MinecraftClient's player
  • BlockUtils for managing or checking blocks and interactions
  • InteractionUtils for simulating or managing in-game interactions
  • ChatUtils for sending chat messages.
  • etc.

Keep in mind that all modules are registered in the main class io.github.itzispyder.clickcrystals.ClickCrystals in the initModules() method.

system.addModule(new Foo());

Firing and Passing Events

All event listeners need to implement the io.github.itzispyder.clickcrystals.events.Listener interface in order be able to be registered. It is important to also implement the io.github.itzispyder.clickcrystals.Global if you want to register the event in the same class. If not, the system field would not be accessible and you'd have to call ClickCrystalsSystem.getInstance(). Once you have a way to register the event, make sure that method gets called!

All events passed would have methods it can call. These methods would take in the type of event as a target parameter, and are always annotated with the annotation io.github.itzispyder.clickcrystals.events.EventHandler.

public class Foo implements Listener, Global {

 public static void init() { // call this somewhere!
  system.addListener(new Foo());
 }

 @EventHandler
 private void foo(ClientTickStartEvent e) {
  // before the start of every tick
 }

 @EventHandler
 private void foo(ClientTickEndEvent e) {
  // after every tick
 }

 @EventHandler
 private void foo(/*Some event*/) {
  // do something
 }
}
// without Global interface
public class Foo implements Listener {

 public static void init() { // call this somewhere!
  ClickCrystalsSystem.getInstance().eventbus.subscribe(new Foo());
 }

 @EventHandler
 private void foo(/*Some event*/) {
  // do something
 }
}

Firing the event is fairly simple. Call the pass method from the system event bus with an instance of io.github.itzispyder.clickcrystals.events.Event.

ClickCrystalsSystem.getInstance().eventbus.pass(/*Some event*/);
ClickCrystalsSystem.getInstance().eventbus.pass(new ClientTickEvent());

Events can be fired with a CallbackInfo from Mixins! This will automatically cancel the callback info if the event is canceled.

ClickCrystalsSystem.getInstance().eventbus.passWithCallbackInfo(CallbackInfo#, /*Some event*/);

Creating Your Own Event

Custom events can also be created as well. Each specific event should always extend the io.github.itzispyder.clickcrystals.events.Event class. If an event is going to be made cancellable, it is important to implement the io.github.itzispyder.clickcrystals.events.Cancellable interface. The Cancellable interface comes with two implementation methods, setCancelled(boolean cancelled) and isCancelled().

public class Foo extends Event implements Cancellable {
 
 private boolean cancelled;

 public Foo() {
  this.cancelled = false;
 }

 @Override
 public boolean isCancelled() {
  return cancelled;
 }

 @Override
 public void setCancelled(boolean cancelled) {
  this.cancelled = cancelled;
 }
}

Creating Custom Commands

Our custom commands are made using Brigadier, a powerful and fast command managing system by Minecraft Mojang. Our Command class is located in the package io.github.itzispyder.clickcrystals.commands package, and any custom commands should be created in its subpackage io.github.itzispyder.clickcrystals.commands.commands. Any commands should extend the io.github.itzispyder.clickcrystals.commands.Command class, and inherit its constructor.

public class Foo extends Command {

 public Foo() {
  super("custom-command", "/custom-command", "I've made my first custom command is ClickCrystals!", "custom-command-alias");
 }
}

There is also one abstract method to implement from the Command class. In this method, you get to create your own command execution.

public class Foo extends Command {

 public Foo() {
  super("custom-command", "/custom-command", "I've made my first custom command is ClickCrystals!", "custom-command-alias");
 }

 @Override
 public void build(LiteralArguemntBuilder builder) {
  builder.then(literal("test-arg-1").executes(context -> {
   info("test argument 1");
   return SINGLE_SUCCESS;
  }));
 }
}

Keep in mind that all commands are registered in the main class io.github.itzispyder.clickcrystals.ClickCrystals in the init() method.

system.addCommand(new Foo());

Creating Custom HUDs

Custom HUDs are a bit complicated, but once you've grasped the concept of rendering GUI in Minecraft, you should be good to go. To simplify what you have to do for just simple text, we've made a text hud you can create. All text HUDs extend io.github.itzispyder.clickcrystals.gui.hud.TextHud and inherit its constructor. TextHud has one implementation method getText().

public class Foo extends TextHud {
 
 public Foo() {
  super("custom-hud", 0, 0, 50, 12);
 }

 @Override
 public String getText() {
  return /*custom text can be coordinates or anything*/;
 }
}

Normal HUDs can be more challenging to create for people who don't know how to render Minecraft GUI. Luckily, I've made io.github.itzispyder.clickcrystals.util.RenderUtils for facilitating 2D rendering. All text HUDs extend io.github.itzispyder.clickcrystals.gui.hud.Hud and inherit its constructor. Hud has one implementation method render(DrawContext context).

public class Foo extends Hud {
 
 public Foo() {
  super("custom-hud", 0, 0, 50, 12);
 }

 @Override
 public void render(DrawContext context) {
  RenderUtils.fill(getX(), getY(), getWidth(), getHeight(), 0x90FFFFFF);
 }
}

Keep in mind that all HUDs are registered in the main class io.github.itzispyder.clickcrystals.ClickCrystals in the init() method.

system.addHud(new Foo());