A framework for Minecraft Forge that allows for client modifications to be scripted in JavaScript
MIT License
Bot releases are visible (Hide)
Published by kerbybit over 6 years ago
Message.setTextComponent(index, component)
Message.addTextComponent(component)
Message.addTextComponent(index, component)
Published by kerbybit over 6 years ago
custom sounds can now be played without loading them into a resource pack first.
var mySound = new Sound({
source: "location/mySoundFile.ogg",
stream: true,
volume: 1.0
});
register("worldLoad", function() {
mySound.play();
});
See the javadocs for more options [docs]
We are experimenting with this way to instance new objects. This will probably be the way to set up things like displays, GUIs, and other objects in the future.
We have added some new ways to control the way that items are shown and read from.
Player.getHeldItem().getLore();
register("itemTooltip", function(lore, item) {
if (item == Player.getHeldItem()) {
lore.clear();
lore.add("main hand");
lore.add(1, "example");
}
}
Messages can now be constructed using the ClientChatRecieved event that is passed through a trigger. This is super useful for getting different clickable parts of a message and what they do.
register("chat", function(event) {
var myMessage = new Message(event)
for (var i = 0; i < myMessage.getMessageParts(); i++) {
myMessage.getMessageParts()[i].chat();
}
});
Published by kerbybit over 6 years ago
Published by kerbybit over 6 years ago
Published by kerbybit over 6 years ago
Image.draw(x, y, size)
Image.draw(x, y)
Image.draw(x, y, width, height)
Image.getTextureWidth()
and Image.getTextureHeight()
Published by kerbybit over 6 years ago
We (mostly @FalseHonesty) changed the way that images are loaded and rendered which will give us more flexibility in the future. This has changed the syntax slightly and has also changed a bit how the Tessellator works.
var myImage = Renderer.image("resourceName.png", "url");
register("renderOverlay", function() {
myImage.draw(x, y, size);
});
The Tessellator now takes this new Image as the argument when binding a texture.
The "assets" folder is still usable and we always recommend putting pictures in there that wont change. If no URL is needed, you can either reference directly from the file path (using ./ for .minecraft folder) and not use a url, or set the url to null
. The size is optional. Default size is 256x256. We do plan on being able to draw images using a width and a height in the near future, we just wanted to make sure this works fine first.
We have added a console history. You can use the up and down arrows like you would in chat to use it.
We have also added a config option in /ct config
to automatically open the console on error. This is super useful for module developers. It is off by default.
Modules now have the ability to load JS files from sub-folders limited to a max depth of 5. This is not super useful for most small modules but will hopefully help out with organization for larger modules.
Because of subfolder loading, we have also added a way to still have a disabled modules folder. Users where just dragging module folders into a "disabledModules" folder and they wouldn't load because there was no sub-folder loading so we kept that functionality by making it so a folder named .disabled
will not load anything inside of it.
Required modules in the metadata.json have also been updated. They will now be loaded before whatever module is requiring them avoiding undefined problems when loading.
Modules now auto update themselves based on the version number inside of the metadata.json. If this number changes between boots of the game, CT will automatically fetch the new version of the module. This can be turned off in /ct config
. It can also be forced using /ct reload
instead of /ct load
In the interest of cleaning things up and getting things closer to what old ct had, we have added an update checker. If the mod needs updating, it will now show text on the home screen and warn you in game with a chat message and a ding. The in game warning can be turned off in /ct config
.
Published by kerbybit over 6 years ago
We've made some changes to the way that triggers get registered that make CT more like a real JavaScript library. Before anyone complains, no we did not break the old way of registering triggers, we have just added a new way.
Triggers can now be registered with anonymous functions or function paths. This should allow for much cleaner code with less randomly named functions. It is highly recommended
register("chat", function(name, message, event) {
cancel(event);
ChatLib.chat(name + ": " + message);
}).setCriteria("<${name}> ${message}");
register("renderCrosshair", function(event) {
cancel(event);
Renderer.drawRect(
0x50ffffff,
RenderLib.screen.getWidth()/2 - 1,
RenderLib.screen.getHeight()/2 -1,
2, 2
);
});
Published by kerbybit over 6 years ago
We have added back-end support for mixins which means we can directly tweak the minecraft code instead of just relying on forge for events. This means we can support more triggers that we could not before. We have only added a few for this version, but there will be many many more soon.
// improved
register("soundPlay", "function")
// new (not mixins)
register("noteBlockPlay", "function")
register("noteBlockChange", "function")
register("drawBlockHighlight", "function")
register("dropItem", "function")
register("pickupItem", "function")
// new (using mixins)
register("screenshotTaken", "function")
register("messageSent", "function")
/ct settings
and made them clickableItem.draw()
to Item.draw(x, y)
and Item.draw(x, y, scale)
docs
/ct import <import name>
Published by kerbybit over 6 years ago
We have added the ability to render things in 3D space using a tessellator (like Renderer.shape but for 3D). These shapes can be textured, translates, rotated, and scaled. To support this, we've also added a new trigger "onRenderWorld"
var cubes = [];
register("renderWorld", "testRenderWorld");
function testRenderWorld() {
cubes.forEach(function(cube) {cube.draw();});
}
var last = {x: Player.getX(), y: Player.getY(), z: Player.getZ()};
register("tick", "testStep");
function testStep() {
if (Math.abs(last.x - Player.getX()) > 1
|| Math.abs(last.y - Player.getY()) > 1
|| Math.abs(last.z - Player.getZ()) > 1) {
cubes.push(new Cube(Player.getX(), Player.getY(), Player.getZ(), Player.getPitch(), Player.getYaw()));
last.x = Player.getX();
last.y = Player.getY();
last.z = Player.getZ();
}
}
function Cube(x, y, z, pitch, yaw) {
this.x = x;
this.y = y;
this.z = z;
this.pitch = pitch;
this.yaw = yaw;
this.draw = function() {
Tessellator.bindTexture("top.png");
Tessellator.begin().translate(this.x, this.y, this.z)
.rotate(this.yaw, 0, -1, 0).rotate(this.pitch, 1, 0, 0)
.pos(-0.5, 0.5, -0.5).tex(0, 0)
.pos(-0.5, 0.5, 0.5).tex(0, 1)
.pos(0.5, 0.5, 0.5).tex(1, 1)
.pos(0.5, 0.5, -0.5).tex(1, 0).draw();
Tessellator.begin().translate(this.x, this.y, this.z)
.rotate(this.yaw, 0, -1, 0).rotate(this.pitch, 1, 0, 0)
.pos(-0.5, -0.5, -0.5).tex(0, 0)
.pos(0.5, -0.5, -0.5).tex(0, 1)
.pos(0.5, -0.5, 0.5).tex(1, 1)
.pos(-0.5, -0.5, 0.5).tex(1, 0).draw();
Tessellator.bindTexture("side.png");
Tessellator.begin().translate(this.x, this.y, this.z)
.rotate(this.yaw, 0, -1, 0).rotate(this.pitch, 1, 0, 0)
.pos(-0.5, 0.5, -0.5).tex(0, 0)
.pos(-0.5, -0.5, -0.5).tex(0, 1)
.pos(-0.5, -0.5, 0.5).tex(1, 1)
.pos(-0.5, 0.5, 0.5).tex(1, 0).draw();
Tessellator.begin().translate(this.x, this.y, this.z)
.rotate(this.yaw, 0, -1, 0).rotate(this.pitch, 1, 0, 0)
.pos(-0.5, 0.5, -0.5).tex(1, 0)
.pos(0.5, 0.5, -0.5).tex(0, 0)
.pos(0.5, -0.5, -0.5).tex(0, 1)
.pos(-0.5, -0.5, -0.5).tex(1, 1).draw();
Tessellator.begin().translate(this.x, this.y, this.z)
.rotate(this.yaw, 0, -1, 0).rotate(this.pitch, 1, 0, 0)
.pos(0.5, 0.5, -0.5).tex(1, 0)
.pos(0.5, 0.5, 0.5).tex(0, 0)
.pos(0.5, -0.5, 0.5).tex(0, 1)
.pos(0.5, -0.5, -0.5).tex(1, 1).draw();
Tessellator.begin().translate(this.x, this.y, this.z)
.rotate(this.yaw, 0, -1, 0).rotate(this.pitch, 1, 0, 0)
.pos(-0.5, 0.5, 0.5).tex(0, 0)
.pos(-0.5, -0.5, 0.5).tex(0, 1)
.pos(0.5, -0.5, 0.5).tex(1, 1)
.pos(0.5, 0.5, 0.5).tex(1, 0).draw();
}
}
Published by kerbybit over 6 years ago
Fixed bug with priority queue for triggers keeping triggers from working
Published by kerbybit over 6 years ago
Added Render
as an alias to Renderer
Added Renderer.drawRect(int color, float x, float y, float width, float height)
Added Renderer.drawString(String text, float x, float y)
Added Renderer.drawStringWithShadow(String text, float x, float y)
Reworked Renderer.drawPlayer(Object player, int x, int y, boolean rotate)
Docs
Added TextComponent.setClick(String action, String value)
Added TextComponent.setHover(String action, String value)
Docs
Published by kerbybit over 6 years ago
Fixed Renderer not working on the config gui, the modules gui, and the Gui object.
Published by kerbybit over 6 years ago
We didn't like the structure of ChatLib and Message so we added a new object to be used inside of Message, the TextComponent. This object is a piece of text that can have clickable and hover actions and values and can be used either in a Message as part of the message or by itself.
function myFunction() {
ChatLib.chat(
new TextComponent("text")
.setClickAction("run_command")
.setClickValue("hi")
.setHoverValue("say hi in chat")
);
new Message(
"some text. ",
TextComponent("some more text.").setHoverValue("hi"),
"even more text."
).chat();
new TextComponent("text").chat();
}
TextComponent docs
Message docs
playerJoined and playerLeft have both been added as triggers. Because of the client's limitations, these only trigger once per tick so only one player joining can trip the trigger every tick. All of the players will still get triggered, some might just be a bit late because they are waiting for others. playerJoined passes in the entire PlayerMP object and playerLeft just passes in the players name that left.
register("playerJoined", "myPlayerJoined");
function myPlayerJoined(player) {
ChatLib.chat(player.getName() + " joined.");
}
register("playerLeft", "myPlayerLeft");
function myPlayerLeft(playerName) {
ChatLib.chat(playerName + " left.");
}
Requiring other modules has been requested for a while and has finally been implemented. It has been in the code for a while, just never properly implemented to fetch the modules that are required so we added that now.
// metadata.json
{
"name":"module name",
"description":"module description",
"version":"1.0",
"author":"me",
"requires":[
"someModule",
"anotherModule",
"yetAnotherModule"
]
}
Published by kerbybit over 6 years ago
Fixed Client.getMouseY(); using the screen width to scale instead of the screen height
Published by kerbybit over 6 years ago
RenderLib has been renamed to Renderer to better reflect what the class does. All old functionality including a mirror with the old RenderLib name will remain in the mod and deprecated until the 0.11 release so you have until then to get things updated otherwise they will break.
All string rendering has been simplified into a Renderer subclass. You use Renderer.text(string, x, y)
to initialize a new text object. There are a bunch of modifier methods to be used with this object that keep all of the previous functionality of the deprecated methods.
var myText = Renderer.text("this is my text", 0, 0).setShadow(true);
register("renderOverlay", "renderMyText");
function renderMyText() {
myText.setX(Client.getMouseX()).setY(Client.getMouseY()).draw();
}
All of the methods are documented here
Drawing a rectangle only had one method, but I wanted to add more without making it ugly like drawing a string used to be so it got its own object as well.
var myRect = Renderer.rectangle(0x80000000, 50, 50, 100, 200).setShadow(0xc0000000, 5, 5);
register("renderOverlay", "renderMyRect");
function renderMyRect() {
myRect.draw();
}
All of the methods are documented here
The new shape object is a combination of drawPolygon, drawShape, and drawLine because all of these worked on the same principle which was setting vertexes and drawing based off of those vertexes. Creating a shape is like creating a polygon before but cleaner and more dynamic. setCircle and setLine are ways to automatically add vertexes to the shape and set the proper GL draw mode that would make the shape either a circle or a line.
var myShape = Renderer.shape(0xffffffff).addVertex(100, 100).addVertex(100, 90).addVertex(90, 90);
var myLine = Renderer.shape(0xffff0000);
var myCircle = Renderer.shape(0xff00ff00).setCircle(0, 0, 10, 100);
render("renderOverlay", "renderMyShaped");
function renderMyShaped() {
myShape.draw();
myLine.setLine(
Renderer.screen.getWidth() / 2,
Renderer.screen.getHeight() / 2,
Client.getMouseX(),
Client.getMouseY()
).draw();
myCircle.draw();
}
All of the methods are documented here
Like drawing a string, drawing an image had way too many methods so it has been simplified greatly with the image object.
var myImage = Renderer.image("myImage.png")
.setX(100).setY(100)
.download("image link", true);
render("renderOverlay", "renderMyImage");
function renderMyImage() {
myImage.draw()
}
All of the methods are documented here
Renderer.getRenderWidth() has been changed to Renderer.screen.getWidth()
Renderer.getRenderHeight() has been changed to Renderer.screen.getHeight()
Added MathLib.clamp(number, min, max) to clamp a number between two values
Config has been completely rewritten from the ground up to use json and have its own ui in /ct config
Module list changed commands to /ct modules
Removed deprecated LookingAt
Published by kerbybit over 6 years ago
Added a load of new render overlay triggers to take customization to a whole new level. It will be fun to see what people do with them.
All of the new render triggers pass in the render overlay event so that it can be cancelled like any other event.
They all also have the modifier OnRenderTrigger.triggerIfCancelled(Boolean)
to tell ct to trigger that method if the event is already cancelled.
Added a new way to register triggers to make it a bit easier to type. The old way will always still work too if that is your style.
/* example */
// old register
TriggerRegister.registerRenderAir("methodName");
// new register
register("renderBossHealth", "methodName");
register("renderCrosshair", "methodName");
register("renderDebug", "methodName");
register("renderExperience", "methodName");
register("renderFood", "methodName");
register("renderHealth", "methodName");
register("renderHotbar", "methodName");
register("renderMountHealth", "methodName");
function methodName(event) {
cancel(event);
}
Inventory and LookingAt has been drastically overhauled to make it more flexible and easier to work with by the addition of Item and Block wrappers.
Inventory has been changed to be an abstract object that is returned on Player.getInventory() and has a bunch of getters. Some of these getters return the new Item object for even more getters specific to the Item. docs
LookingAt has been deprecated in favor of Player.lookingAt()
that returns a new Block or Entity object.
An example of using this would be
var lookingAt = Player.lookingAt();
if (lookingAt instanceof Block) {
// Player is looking at a block, lookingAt is of the Block type (Possibly air)
} else {
// Player is looking at an entity, lookingAt is of the Entity type
}
Item is the new return for anything inventory related. the Item object stores both the item and itemStack so there are a bunch of getters to play with there. docs
Block is similar to Item in that they replace what is returned by the old LookingAt. docs
Entity is the other return type for Player.lookingAt()
. docs
Scoreboard replaces the old ScoreboardReader object. It has a new method that can stop the scoreboad from rendering. docs
Added Client.getCurrentMessage()
and Client.setCurrentMessage()
to get/set the currently typed message in the chat input box. docs
Added Player.armor.getHelmet() .getChestplate() .getLeggings() .getBoots()
. docs
Added World.particle.spawnParticle()
method. Also added a helper to get the names of all particles for use in that method. docs
Removed OnCommand.setUsage()
Deprecated LookingAt. This will be removed in a future release.
Published by kerbybit over 6 years ago
Runs while mouse is being held down and gives a delta x and delta y for mouse movement.
TriggerRegister.registerDragged("methodName");
function methodName(dx, dy, x, y, button) { }
Added new register method to make registering triggers more javascript oriented.
register("triggerType", "methodName");
function methodName() { }
This means you can now register a trigger like this:
register("chat", "methodName").setChatCriteria("example");
function methodName() { }
Updated descriptions for all methods in TriggerRegister to provide more information.
Does the same thing as TriggerRegister.registerDragged but only if the mouse is inside that display line's bounding box.
DisplayLine.registerDragged("methodName");
function methodName(dx, dy, x, y button) { }
Runs every frame that the mouse is inside the display line's bounding box.
DisplayLine.registerHovered("methodName");
function methodName(x, y) { }
Added a config option to change file location of modules and provided libs.
Added to the client wrapper (gui stuff).
Moved update checking to only happen on game startup.
This just improves loading times when running /ct load
.