Skip to content

Commit

Permalink
Push our docs for today.
Browse files Browse the repository at this point in the history
  • Loading branch information
iChun committed May 29, 2021
1 parent e3370bb commit f698d51
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 6 deletions.
2 changes: 1 addition & 1 deletion docs/advanced/arrays.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Arrays: The Black Sheep of Variables
========================================

When CCI was developed, variables were designed to be of relatively primitive types: `Integer`, `Double`, `Boolean`, `String`. And then ~~the fire nation attacked~~ Arrays got in the way and became an inevitable issue.
When CCI was developed, variables were designed to be of relatively primitive types: `Integer`, `Double`, `Boolean`, `String`. And then <s>the fire nation attacked</s> Arrays got in the way and became an inevitable issue.

Sometimes, sockets send information in the form of Arrays, that, or CCI missed one and slipped in an Array to the Variables list. It had to be dealt with.

Expand Down
2 changes: 1 addition & 1 deletion docs/advanced/libraries.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Libraries&#58; Not The Book Kind
================================

Libraries are a direct extension of [Constants](../../intermediate/constants.md).
Libraries are a direct extension of [Constants](../../intermediate/constants/).

Libraries are essentially `Constants` files with a different purpose. They are meant to be distributed to other people for their use. Similarly to what you see in [Programming](https://en.wikipedia.org/wiki/Library_(computing)).

Expand Down
32 changes: 32 additions & 0 deletions docs/advanced/strings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
Strings&#58; Untying the Knot
=============================

If you've come this far without knowing what [Strings](https://en.wikipedia.org/wiki/String_(computer_science)) are, I applaud you. As Variables are primarily String driven, a suite of conditions exist for manipulating them.

These literally call the Java function for the String and inserts the result into a variable. Find the function documentation [here](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html).

| Name | ID |
| ------------------------------------ | ---------------- |
| [StringConcatCondition](url.tbd) | `stringConcat` |
| [StringCompareToCondition](url.tbd) | `stringCompare` |
| [StringContainsCondition](url.tbd) | `stringContains` |
| [StringEndsWithCondition](url.tbd) | `stringEnds` |
| [StringEqualsCondition](url.tbd) | `stringEquals` |
| [StringIndexOfCondition](url.tbd) | `stringIndex` |
| [StringLowerCaseCondition](url.tbd) | `stringLower` |
| [StringReplaceCondition](url.tbd) | `stringReplace` |
| [StringSplitCondition](url.tbd) | `stringSplit` |
| [StringStartsWithCondition](url.tbd) | `stringStarts` |
| [StringSubStringCondition](url.tbd) | `stringSubstr` |
| [StringTrimCondition](url.tbd) | `stringTrim` |
| [StringUpperCaseCondition](url.tbd) | `stringUpper` |
| [StringLengthCondition](url.tbd) | `stringLength` |


However, there are also a few special Conditions made to handle Strings:

| Name | ID | Description |
| -------------------------------- | -------------- | ------------------------------------------------------- |
| [Base64DecodeCondition](url.tbd) | `base64Decode` | Decodes a Base64 String |
| [Base64EncodeCondition](url.tbd) | `base64Encode` | Encodes a String into a Base64 String |
| [JsonSafeCondition](url.tbd) | `jsonSafe` | Converts a String to be safe to insert into JSON files. |
79 changes: 79 additions & 0 deletions docs/expert/gamehooks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
Game Event Hooks&#58; The Config Maker&#39;s Nightmare
======================================================

**Warning**: You will need a [Forge Development Environment](https://mcforge.readthedocs.io/en/1.16.x/gettingstarted/#from-zero-to-modding) for this. This feature is not available on Fabric builds of CCI.

## Game Event Hooks: An Introduction

Game Event Hooks, or which I will refer to more frequently, Game Hooks, is a special layer that CCI adds to hook into things that happen in the game using the [Forge Event system](https://github.com/MinecraftForge/MinecraftForge/tree/1.16.x/src/main/java/net/minecraftforge/event).

Understanding how to use this will require a decent grasp of Java, Java's [Reflection](https://www.oracle.com/technical-resources/articles/java/javareflection.html), and modding with Forge.

Game Hooks is primarily driven by Reflection, and has three helper classes to aid it:

| Class Name | Function |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| [Listener](url.tbd) | Checks Forge's Events if it matches what you're looking for and passes the Event to ObjectAccessors |
| [ObjectAccessor](url.tbd) | Used to access fields or functions in an Object's class, which is then passed into its own set of ObjectAccessors |
| [ParamInjector](url.tbd) | Used to provide arguments types (and their objects) for method invoking |

These three Classes will be outlined better in on their documentation page. This page's aim is more to describe the practical approach of using them.

<br />

## The Helpers, and How to Use Them

I find that the best way to show how these work, is by walking you through an example. In this example, I will show how to make a Pig jump upwards when you punch it. I will be using [IntelliJ IDEA](https://www.jetbrains.com/idea/) and MCP mappings. This guide also requires a **minimum of CCI 1.9.0** or later.

### The Flow of Thought

Let's have a look at a new Listener in the Editor first:

![](./images/gamehooks/listener.png){: class="img_center"}
<br />
<br />

Listeners will require the Class name (including the parent class, if this is an inner class) (name: `className`) and optionally the full package path (name: `isFullName`) of the Forge Event you would like to listen to.

For this, we will need to listen for the `LivingHurtEvent` (package: `net.minecraftforge.event.entity.living`). Go ahead and create a listener and set the `className`.

For this to also work on Servers, you will need to tell the Listener that we're listening to an event triggered on the server (name: `isServerEvent`).

Next up we have the `preAccessorEvent`. This is an optional Config Event that you can create just to populate the variables before the rest is triggered. Variables here are a bit different. Usually, the variables list contains an assortment of `int`, `double`, `boolean`, `String`, `Object[]` types. Here, our variables will contain Objects themselves. There is one special variable called `stopEventProcessing`. If this variable exists at any point between ObjectAccessors, processing is stopped.

After that, we have the `ObjectAccessor` fields, starting with `staticAccessors`. What `staticAccessors` is for is to allow you to retrieve or call static fields or methods to add to the variables list before actually referencing the actual Forge Event. You may need these objects for use with `ParamInjector`. These Object Accessors will need the full class path set in `classForStaticAccess`, as there is no object reference for them to access currently. We don't need any static accessors here, so let's move on.

Now, we're at the `accessor` field. These ObjectAccessors will have the Forge Event object passed to them. We will need an `ObjectAccessor` here, so let's make one. This is what it'll look like in the Editor:

![](./images/gamehooks/objectaccessor.png){: class="img_center"}
<br />
<br />

For readibility sake, we'll name this Object Accessor `ForgeEvent:getEntityLiving` (name: `name`). Now, move to your [IDE](https://en.wikipedia.org/wiki/Integrated_development_environment) and look at `LivingHurtEvent`. Note how it extends `LivingEvent`. We want to get the entity that got hurt here, and we get that from the function `getEntityLiving()`. Let's put that in our Object Accessor in `function`.

We know we want a Pig here, so for `instanceCheck`, we put in the full class name for the pig, `net.minecraft.entity.passive.PigEntity`. We also want to keep the pig object reference, so let's keep it in a variable called `pigEntity`, in the `argName` field.

Before I move on, here is where it gets a little complicated. Minecraft code is obfuscated, and Forge deobfuscates things. In runtime, all the fields and functions are mapped to something called Searge names (srgName), meaning the field names start with `field_`, and the method names start with `func_`, but in our IDE we see the deobfuscated name, like `world` or `getName`, which are MCP names. For the fields in ObjectAccessor, use Searge names. I will put the ones used in this guide as reference here, but if you want to convert the mapping names, consider checking out the `forge-bot` user in the Minecraft Forge discord (URL in their [Twitter bio](https://twitter.com/forgedevteam)).

Now, although we marked the event as triggering on a Server, that only makes things work for clients when connected to on Dedicated Servers. We still need to make sure that the Event is triggering on the entity on the Server side. Add a new `ObjectAccessor` in `nextAccessors`. These set of accessors will have the pig object as reference.

To check if we're on the Server side of things, the easy way is to check the `isRemote` (srgName: `field_72995_K`) field of the World object of the Entity. So now we need to get a reference to the World object via method `getEntityWorld()` (srgName: `func_130014_f_()`), or from accessing the `world` (srgName: `field_145850_b`) field. Either way is up to you, but I will be using the field. Set this in the ObjectAccessor. Don't forget to name your ObjectAccessor for readability eg `Entity:world`. This ObjectAccessor will be grabbing the World object, and passing it along to its own `nextAccessors`. We aren't keeping a reference to the world here, so no `argName` is required.

We're not done yet, make a new `ObjectAccessor` in `Entity:world`'s `nextAccessors`, we'll name this one `World:isRemote`. Set the `function` to `isRemote` (srgName: `field_72995_K`), and set the `argName` to `isRemote`, we will need it in a bit. Now we want to compare the `isRemote` value. This is a `boolean`, so it is either `true` or `false`. We will be checking to see if it is `true`, and if it is, to stop processing.

Make a new Event in `postAccessorEvent`. Add a `VariableCondition` (id: `variableCheck`), set `variableName` to the `argName` we set earlier: `isRemote`, and `variableResult` as `true`. Now, make a new `VariableInsertCondition` (id: `variableInsert`), and set `variableName` to `stopEventProcessing`. `variableInput` can be anything except for `null`, else it is considered invalid. What we've just done is checked if `isRemote` is true, and if it is, the Event is on the client side, and to stop processing.

We've done our checks, now to make the pig jump. Go back to `ForgeEvent:getEntityLiving` and add a new `ObjectAccessor` in `nextAccessors`. This is where we make the pig "jump". I'll be naming this ObjectAccessor `Entity:setMotion`. Here's where things get a little special, `Entity`'s `setMotion` (srgName: `func_213317_d`) method takes a `Vector3d` argument.

Backtrack a bit and return to `staticAccessors` in the `Listener` and add a new one `ObjectAccessor`. This one, we'll call `Vector3d:init`, set the `classForStaticAccess` as `net.minecraft.util.math.vector.Vector3d` and for the function, we put in `<>`. This tells CCI that you'd like to use a Constructor for the Class `Vector3d`. We will need 3 `ParamInjector`s here, so, create them. For all three, set `isPrimitive` to `true` and the `classType` to `double`. Set the `argToPull` for the first and third as `0`, and for the second, `1.5`. Go back to `Vector3d:init` and set the `argName` as `velocity`. What we've just done is we've created a `Vector3d` Object with `x = 0; y = 1.5; z = 0;`. However, as we're using `argToPull` to define the primitive, you must ensure the variable does not exist, as it will pull that variable instead, first.

Go back to the `Entity:setMotion` ObjectAccessor and create a `ParamInjector`. Here, set the `classType` as `net.minecraft.util.math.vector.Vector3d` and `argToPull` as `velocity`. You've just told CCI to call the method `setMotion(Vector3d)`, and to use the `Vector3d` we have in the variable `velocity`.

And that's all to it. Save, and test. If done right, the next time you punch a pig, it should shoot up into the sky.

For your reference, your Editor should look something like this once you're done:

TODO insert picture and JSON.


Attached is the JSON file generated from this so you can reference in case something went wrong:
Binary file added docs/expert/images/gamehooks/listener.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/expert/images/gamehooks/objectaccessor.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/intermediate/constants.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Constants, the Solution to Insanity

As you probably have seen, the term "constants" have been used every now and then. Constants are, to a degree, a way to direct a Config Event Object to a static reference.

Think of it this way. When you get bits, you spawn a pig. You get a subscription, you spawn a pig. You get raided, you spawn a pig, You get a follow, you sp-well, you see the pattern. In every one of those Config Events, you have a `CommandOutcome` that spawns the pig. But then round comes October, and in your "festive" mood, you decide to spawn a ~~Zombie Pigman~~ Piglin instead. There you go changing 4+ Outcomes.
Think of it this way. When you get bits, you spawn a pig. You get a subscription, you spawn a pig. You get raided, you spawn a pig, You get a follow, you sp-well, you see the pattern. In every one of those Config Events, you have a `CommandOutcome` that spawns the pig. But then round comes October, and in your "festive" mood, you decide to spawn a <s>Zombie Pigman</s> Piglin instead. There you go changing 4+ Outcomes.

Here's where you're thinking: "*There has to be a better way!*". The solution to that, is Constants. Have all those Outcomes point to the same, one Constant, change the Constant, change them all. That's the idea.

Expand Down
2 changes: 1 addition & 1 deletion docs/intermediate/notes.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
I'm Making A Note Here, Huge Success!
=====================================

~~For the good of all of us, except the ones who are dead~~
<s>For the good of all of us, except the ones who are dead</s>

Here we talk about Notes, and how they differ from Variables. Notes are, essentially, variables that save to disk. Variables are all kept in memory and thus are lost when the Event ends or Minecraft closes. Notes are loaded up when the profile loads, and saved to disk when added/modified.

Expand Down
2 changes: 1 addition & 1 deletion docs/libraries/index.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Libraries&#58; Still Not The Book Kind
======================================

CCI has a "libraries" feature. These are explained in more detail [here](../../advanced/libraries.md).
Libraries are explained in more detail [here](../../advanced/libraries.md).

This section serves for people to share libraries they have created, as well as write a guide on how to use them. Indirectly, this section is an extension of the "How To's" section.

Expand Down
3 changes: 2 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ nav:
- Debugging When Debugging Fails: 'advanced/debugmode.md'
- When Variable Insertion Goes Wrong: 'advanced/variableinsertion.md'
- Setting Default Variables: 'advanced/eventinit.md'
- 'Strings&#58; Untying the Knot': 'advanced/strings.md'
- 'Arrays&#58; The Black Sheep of Variables': 'advanced/arrays.md'
- Expert Guides:
- Expert Difficulty, for Advanced Advanced Users: 'expert/index.md'
Expand All @@ -44,7 +45,7 @@ nav:
- Outcome: 'components/outcome/outcome.md'
- Constants: 'components/constants.md'

# Suggested advanced: Arrays, Strings: Untying the Knot
# Suggested advanced: Strings: Untying the Knot
# Suggested expert: Game Hooks.
# How to, random mob, random chance, repeat outcome, Math

Expand Down

0 comments on commit f698d51

Please sign in to comment.