From 5a29fb83e2fd9d422adb3189762f0ac6cb8e5519 Mon Sep 17 00:00:00 2001 From: Brian <5673408+illumincrotty@users.noreply.github.com> Date: Thu, 27 Jan 2022 18:54:00 -0600 Subject: [PATCH 1/5] Improved type definitions --- docs/clientcommands.ts | 985 --------------------------------- docs/src/clientCommands.d.ts | 1012 ++++++++++++++++++++++++++++++++++ 2 files changed, 1012 insertions(+), 985 deletions(-) delete mode 100644 docs/clientcommands.ts create mode 100644 docs/src/clientCommands.d.ts diff --git a/docs/clientcommands.ts b/docs/clientcommands.ts deleted file mode 100644 index 1f31a08..0000000 --- a/docs/clientcommands.ts +++ /dev/null @@ -1,985 +0,0 @@ - -/** - * The player which the user has control over - */ -declare const player: ControllablePlayer; -/** - * The client-side world which the player is in - */ -declare const world: World; - -/** - * Runs a client-side command and returns the result. Can also be an entity selector. - * @param command The command or entity selector to run. - * @return The integer result of the command, or list of matching entities in the case of an entity selector. - */ -declare function $(command: string): number | Array; - -/** - * Prints a string to client-side chat - * @param x The string to print - */ -declare function print(x: string): void; - -/** - * Sends a message to the game chat, prefix with "/" to run a server-side command. - * @param msg The message to send - */ -declare function chat(msg: string): void; - -/** - * Allows the game to run a tick. Pauses script execution until the next tick - */ -declare function tick(): void; - -/** - * Returns true if you are logged in to a game, false otherwise. Many operations are invalid if you are not logged in. - */ -declare function isLoggedIn(): boolean; - -/** - * If a string, matches items by their name, with the "minecraft:" prefix removed if it exists. - * If an object, matches the item NBT. - * If a function, it should return true or false based on the input item NBT. - */ -type ItemPredicate = string | object | ((itemNbt: object) => boolean); - -/** - * Represents a generic entity - */ -declare class Entity { - /** - * Whether this is a valid reference to an entity. A reference may be invalid if you are not ingame, you are in a - * different dimension to the entity, or the entity has died or unloaded. All other operations on this entity will - * fail if it is invalid. - */ - readonly valid: boolean; - /** - * The type of the entity, as used in commands. If the prefix, would be "minecraft:", then that prefix is stripped - */ - readonly type: string; - /** - * The x-position of the entity - */ - readonly x: number; - /** - * The y-position of the entity - */ - readonly y: number; - /** - * The z-position of the entity - */ - readonly z: number; - /** - * The yaw of the entity in degrees. 0 degrees is to the south, increasing clockwise - */ - readonly yaw: number; - /** - * The pitch of the entity in degrees. 0 degrees is forwards, increasing downwards - */ - readonly pitch: number; - /** - * The x-velocity of the entity - */ - readonly motionX: number; - /** - * The y-velocity of the entity - */ - readonly motionY: number; - /** - * The z-velocity of the entity - */ - readonly motionZ: number; - /** - * The NBT of the entity - */ - readonly nbt: object; - - /** - * Returns whether this entity is the same entity as the other entity - * @param other The other entity - */ - equals(other: Entity): boolean; -} - -/** - * A living entity, e.g. mobs, players - */ -declare class LivingEntity extends Entity { - /** - * The eye height of the entity in its current pose - */ - readonly eyeHeight: number; - /** - * The eye height of the entity in its standing pose - */ - readonly standingEyeHeight: number; -} - -/** - * A player - */ -declare class Player extends LivingEntity { - -} - -/** - * A player which the user has control over - */ -declare class ControllablePlayer extends Player { - - /** - * Teleports the player a limited distance. This function cannot teleport the player more than 0.5 blocks, - * and is meant for alignment rather than movement. Use properties like {@link pressingForward} and - * {@link sprinting} for movement. Returns whether successful (the player was close enough to the - * given position). - * @param x The x-position to snap the player to - * @param y The y-position to snap the player to - * @param z The z-position to snap the player to - * @param sync Whether to sync the position with the server immediately after the teleport, rather than - * at the start of the next tick. If absent, defaults to false - */ - snapTo(x: number, y: number, z: number, sync?: boolean): boolean; - - /** - * Moves the player in a straight line to the specified target position. Blocks until it reaches there. - * Returns whether successful - * @param x The x-position of the target - * @param z The z-position of the target - * @param smart Default true, whether to jump up single block gaps - */ - moveTo(x: number, z: number, smart?: boolean): boolean; - - /** - * Pathfinds the player to the specified target position. Blocks until it reaches there. - * Returns whether successful - * @param x The x-position of the target - * @param y The y-position of the target - * @param z The z-position of the target - * @param hints The pathfinding hints - */ - pathTo(x: number, y: number, z: number, hints?: PathfindingHints): boolean; - /** - * Pathfinds the player to the specified moving target entity. Blocks until it reaches there. - * Returns whether successful - * @param target The entity to follow - * @param hints The pathfinding hints - */ - pathTo(target: Entity, hints?: PathfindingHints): boolean; - /** - * Pathfinds the player to the specified moving target. The input function will be called periodically - * to update the target position. Returns whether successful - * @param movingTarget The moving target to follow - * @param hints The pathfinding hints - */ - pathTo(movingTarget: () => Position, hints?: PathfindingHints): boolean; - - /** - * The yaw of the player in degrees. 0 degrees is to the south, increasing clockwise - */ - yaw: number; - /** - * The pitch of the player in degrees. 0 degrees is forwards, increasing downwards - */ - pitch: number; - - /** - * Causes the player to look towards a point in space. - * @param x The x-position of the point to look at - * @param y The y-position of the point to look at - * @param z The z-position of the point to look at - */ - lookAt(x: number, y: number, z: number): void; - /** - * Causes the player to look towards an entity. If target is a {@link LivingEntity}, then - * the player will look at the eye height of that entity. Otherwise, it will look at the bottom - * of the entity. - * @param target The entity to look at - */ - lookAt(target: Entity): void; - - /** - * Forces a synchronization of the player's look angles with the server. By default, the player's - * new rotation is only sent to the server at the start of the next tick, meaning that if you - * perform certain actions that depend on the player's rotation, such as dropping an item, it will - * happen as if the player was still facing in the previous direction. Calling this function will - * immediately send the player's rotation to the server, so that further actions (like dropping an - * item) will be performed with the correct rotation. - */ - syncRotation(): void; - - /** - * The currently selected hotbar slot - */ - selectedSlot: number; - /** - * The player's inventory. Slot numbers are as follows: - * - * - * - * - * - * - * - * - *
NumberSlot
0-8Hotbar
9-35The rest of the main inventory
36-39Armor (head, torso, legs, feet)
40Offhand
41Crafting result slot
42-45Crafting grid
- * Slots beyond the hotbar and main inventory will be inaccessible while the player is looking into - * a container. - */ - readonly inventory: Inventory; - /** - * The inventory of the container the player is looking in, or null if the player isn't looking - * in any container - */ - readonly currentContainer: Inventory | null; - - /** - * Opens a container by right clicking the block at the given block position, and wait for a container - * of type expectedContainerType to be opened. - * @param x The x-position of the container block - * @param y The y-position of the container block - * @param z The z-position of the container block - * @param expectedContainerType The container type to expect, or a function that returns true/false - * depending on whether a container type should be accepted - * @return Whether successful - */ - openContainer(x: number, y: number, z: number, expectedContainerType: string | ((containerType: string) => boolean)): boolean; - - /** - * Opens a container by right clicking the given entity, and wait for a container of type - * expectedContainerType to be opened. - * @param entity The entity to click on - * @param expectedContainerType The container type to expect, or a function that returns true/false - * depending on whether a container type should be accepted - * @return Whether successful - */ - openContainer(entity: Entity, expectedContainerType: string | ((containerType: string) => boolean)): boolean; - - /** - * Closes the currently opened container, if any is open. Due to a threading issue in 1.16, this method delays - * the script by 1 tick, if a container was open. - */ - closeContainer(): void; - - /** - * If the player currently has a crafting container open, crafts as many times as possible up to the given - * number of times. Places items matching the given parameters into the given pattern, waits for a result matching - * result to appear, and pulls it out of the crafting grid. - * @param result The expected result of the recipe - * @param craftCount The number of crafts - * @param pattern An array of rows of the pattern. Each character corresponds to an item, use spaces for blank slots - * @param ingredients Associates characters with items - * @return The number of crafts managed - */ - craft(result: ItemPredicate, - craftCount: number, - pattern: Array, - ingredients: {[keys: string]: ItemPredicate}): number; - - /** - * "picks" an item from the player's inventory, and selects it in the hotbar, in a similar fashion to the - * vanilla pick block feature. - * @param item The item to pick - * @return Whether a matching item could be found in the inventory - */ - pick(item: ItemPredicate): boolean; - - /** - * Right clicks the currently held item in air - * - * Warning: right-clicking some items is a continuous action. This function on its own - * will not work for this! For an easy way to eat food, see {@link longUseItem} - * @return Whether the item use was considered successful - */ - rightClick(): boolean; - /** - * Right clicks a block. Will click on the closest part of the block at the given position. - * This function also modifies the player rotation to look at where they clicked, if they are - * not already hovering over the block. - * @param x The x-position of the block to right click - * @param y The y-position of the block to right click - * @param z The z-position of the block to right click - * @param side The side of the block to click on. If not specified, will click on the closest side. - * @return Whether the right click was successful - */ - rightClick(x: number, y: number, z: number, side?: string): boolean; - /** - * Right clicks an entity. This function also modifies the player rotation to look at the entity they - * clicked on. - * @param entity The entity to right click - * @return Whether the right click was successful - */ - rightClick(entity: Entity): boolean; - - /** - * Left clicks on a block. Will click on the closest part of the block at the given position. - * This function also modifies the player rotation to look at where they clicked, if they are - * not already hovering over the block. - * - * Warning: left-clicking many blocks is a continuous mining action. This function on its own - * will not work for this! For an easy way to mine blocks, see {@link longMineBlock} - * @param x The x-position of the block to right click - * @param y The y-position of the block to right click - * @param z The z-position of the block to right click - * @param side The side of the block to click on. If not specified, will click on the closest side. - * @return Whether the left click was successful - */ - leftClick(x: number, y: number, z: number, side?: string): boolean; - /** - * Left clicks on an entity (i.e. usually attacking it). This function also modifies the player rotation to - * look at the entity they clicked on. - * @param entity The entity to left click - * @return Whether the left click was successful - */ - leftClick(entity: Entity): boolean; - - /** - * Blocks user input until either this script terminates or {@link unblockInput} is called (and so long as - * no other scripts are also blocking input). - */ - blockInput(): void; - - /** - * Stops this script blocking user input - */ - unblockInput(): void; - - /** - * Holds down right click until the item can be used no more! For food, this has the effect of eating a single - * food item. Pauses execution of the script until the action is finished. Also blocks input for the duration - * of item use. - */ - longUseItem(): boolean; - - /** - * Mines a block with the currently held item until it is broken. Pauses execution of the script until the - * action is finished. Also blocks input for the duration of the block breaking. - * @param x The x-position of the block to mine - * @param y The y-position of the block to mine - * @param z The z-position of the block to mine - */ - longMineBlock(x: number, y: number, z: number): boolean; - - /** - * Whether the script is pressing forward for the player. This shouldn't be used to get whether forward is - * being pressed, it will produce inconsistent results. It should be used to set whether forward - * is pressed by the current script. - */ - pressingForward: boolean; - /** - * Whether the script is pressing back for the player. This shouldn't be used to get whether back is - * being pressed, it will produce inconsistent results. It should be used to set whether back - * is pressed by the current script. - */ - pressingBack: boolean; - /** - * Whether the script is pressing left for the player. This shouldn't be used to get whether left is - * being pressed, it will produce inconsistent results. It should be used to set whether left - * is pressed by the current script. - */ - pressingLeft: boolean; - /** - * Whether the script is pressing right for the player. This shouldn't be used to get whether right is - * being pressed, it will produce inconsistent results. It should be used to set whether right - * is pressed by the current script. - */ - pressingRight: boolean; - /** - * Whether the script is pressing the jump key for the player. This shouldn't be used to get whether jump is - * being pressed, it will produce inconsistent results. It should be used to set whether jump - * is pressed by the current script. - */ - jumping: boolean; - /** - * Whether the script is pressing the sneak key for the player. This shouldn't be used to get whether sneak is - * being pressed, it will produce inconsistent results. It should be used to set whether sneak - * is pressed by the current script. - */ - sneaking: boolean; - /** - * Whether the script is pressing the sprint key for the player. This shouldn't be used to get whether sprint is - * being pressed, it will produce inconsistent results. It should be used to set whether sprint - * is pressed by the current script. - */ - sprinting: boolean; - - /** - * Attempts to disconnect from the server. Terminates the script if successful. - */ - disconnect(): void; - - /** - * Disconnects and reconnects the player to the server. Returns whether successful. This function may return before - * the player has fully logged in again; check {@link isLoggedIn()} in a loop to wait for the player to be logged - * in. If the relog failed, depending on how it failed, the script may terminate after the next tick. The script - * will continue running if successful. - */ - relog(): boolean; -} - -/** - * The options for an inventory click - */ -interface InventoryClickOptions { - /** - * The click type, one of: - * - * - * - * - * - * - * - * - * - *
ValueDescription
"pickup"Swaps the item held by the cursor with the item in the given slot. This is the default click type.
"quick_move""Shift-clicks" on the given slot, which is commonly a quick way of moving items into and out of a container
"swap"Swaps the given slot with a hotbar slot, specified by also setting the {@link hotbarSlot} property on this object
"clone"(Creative-mode-only) clones the item in the given slot, equivalent to a middle-click on it
"throw"Throws the item in the given slot out of the inventory
"quick_craft"Performs a quick-craft. Must be performed in multiple stages, specified by also setting the {@link quickCraftStage} property in this object
"pickup_all"Picks up all items of the type in the slot
- */ - type?: string; - /** - * Whether to simulate a right click rather than a left click (which is the default). - * When {@link type} is "throw", then setting this to true throws all items rather than just one. - */ - rightClick?: boolean; - /** - * When {@link type} is "swap", specifies the hotbar slot to swap with - */ - hotbarSlot?: number; - /** - * When {@link type} is "quick_craft", specifies the quick craft stage (0-3) - */ - quickCraftStage?: number; -} - -/** - * Represents an inventory/container of items - */ -declare class Inventory { - /** - * The type of inventory. Returns either "player", "creative", "horse" or the container ID. - * Note that the container ID may be more generic than you might expect, e.g. "generic_9x3" - * for different types of chests. - */ - readonly type: string; - /** - * The items in the inventory. This is an array of item stack NBT objects. - */ - readonly items: Array; - - /** - * Simulates a click in an inventory slot. This function covers most inventory actions. - * @param slot The slot ID to click on. If null, this represents clicking outside - * the window (usually with the effect of dropping the stack under the cursor). - * @param options The options of the inventory action. See {@link InventoryClickOptions}. - */ - click(slot: number | null, options?: InventoryClickOptions): void; - - /** - * Finds the first slot in the container with an item that matches the given item predicate - * @param item The item to search for - * @param reverse If true, returns the last matching slot rather than the first one - * @return The index of the first matching slot, or null if no such slot is found. - */ - findSlot(item: ItemPredicate, reverse?: boolean): number | null; - - /** - * Lists the slots in the container with an item that matches the given item predicate, up - * until the maximum number of items has been reached. - * @param item The item to search for - * @param count The maximum amount of this item to search for, or -1 for no maximum - * @param reverse If true, returns the last matching slots first rather than the first matching slot first - * @return An array of matching slot indices - */ - findSlots(item: ItemPredicate, count: number, reverse?: boolean): Array; - - /** - * Shift clicks all the matching items in this container, up until the maximum number of items has been reached. - * @param item The item to search for - * @param count The maximum amount of this item to shift lick, or -1 for no maximum - * @param reverse If true, shift clicks the items in reverse order of slot indices - * @return The actual number of items shift clicked, may be greater than or equal to count if there - * are sufficient items in this container, or equal to the number of matching items if there are - * insufficient items. - */ - moveItems(item: ItemPredicate, count: number, reverse?: boolean): number; - - /** - * Return whether this inventory is the same as another inventory - * @param other The other inventory - */ - equals(other: Inventory): boolean; -} - -/** - * The type of the global world variable, the client-side world. - */ -declare class World { - /** - * The dimension ID of the current dimension. In vanilla, this can either be "overworld", - * "the_nether" or "the_end"; with datapacks or in modded this may take other values. - */ - readonly dimension: string; - - /** - * Gets the name of the block at the given position in the client-side world. - * @param x The x-position of the block to query - * @param y The y-position of the block to query - * @param z The z-position of the block to query - * @return The block name, as used in commands. If there would be a "minecraft:" prefix, the prefix is removed. - */ - getBlock(x: number, y: number, z: number): string; - - /** - * Gets the block state property with the given name at the given position. - * Equivalent to getBlockState(x, y, z).getProperty(property) - * @param x The x-position of the block state to query - * @param y The y-position of the block state to query - * @param z The z-position of the block state to query - * @param property The property name to query. E.g. could be "power" for redstone dust, or "bed_part" for beds. - */ - getBlockProperty(x: number, y: number, z: number, property: string): boolean | number | string; - - /** - * Gets the block state at the given position. - * @param x The x-position of the block state to get - * @param y The y-position of the block state to get - * @param z The z-position of the block state to get - */ - getBlockState(x: number, y: number, z: number): BlockState; - - /** - * Gets the client-side block entity NBT at the given coordinates - * @param x The x-position of the block entity whose NBT to get - * @param y The y-position of the block entity whose NBT to get - * @param z The z-position of the block entity whose NBT to get - * @return The NBT object of the block entity, or null if there was no block entity - */ - getBlockEntityNbt(x: number, y: number, z: number): object | null; - - /** - * Gets the block light at the given position, 0-15 - * @param x The x-coordinate of the position to get the block light of - * @param y The y-coordinate of the position to get the block light of - * @param z The z-coordinate of the position to get the block light of - */ - getBlockLight(x: number, y: number, z: number): number; - - /** - * Gets the sky light at the given position, 0-15 - * @param x The x-coordinate of the position to get the sky light of - * @param y The y-coordinate of the position to get the sky light of - * @param z The z-coordinate of the position to get the sky light of - */ - getSkyLight(x: number, y: number, z: number): number; - - /** - * Finds the closest visible point on a block - * @param x The x-position of the block to find the closest visible point on - * @param y The y-position of the block to find the closest visible point on - * @param z The z-position of the block to find the closest visible point on - * @param side The side of the block to find the closest visible point on. If not specified, will use the closest side. - * @return Whether there was a visible point on the block within reach - */ - getClosestVisiblePoint(x: number, y: number, z: number, side?: string): Position | null; -} - -/** - * Defines a "thread", which is an action which can run "concurrently" with other threads. - * This is not concurrency in the sense you may be used to as a programmer. Only one thread - * can run at a time. When you start another thread, that thread gains control immediately, - * until either it stops or it calls the {@link tick} function, which allows other script - * threads to run their code, and the game to run a tick. Therefore, you do not have to - * worry about thread safety, as all operations are thread safe. - */ -declare class Thread { - /** - * The currently executing thread. If this thread is not a clientcommands thread or the main script thread, then - * this returns null. This is possible for example via JsMacros' JavaWrapper. - */ - static readonly current: Thread | null; - - /** - * Whether the thread is currently running. Note this does not necessarily mean this - * thread is the currently executing thread. To test that, use thread === Thread.current - */ - readonly running: boolean; - - /** - * Whether the thread has been paused by {@link pause}. To pause an unpause threads, use the methods - */ - readonly paused: boolean; - - /** - * Whether the thread is a daemon thread. If true, this thread will be killed when the parent thread - * stops; if false, this thread may outlive its parent - */ - readonly daemon: boolean; - - /** - * The thread which started this thread. If null, either this thread was not started by a script, or - * this thread is not a daemon and the parent thread has died - */ - readonly parent: Thread | null; - - /** - * An array view of running threads started by this thread - */ - readonly children: Array; - - /** - * Creates a thread which will execute the given function on it when run. Does not - * run automatically, remember to explicitly call the {@link run} function. - * @param action The function to be executed on this thread - * @param daemon Whether this thread will be killed when the thread which started it - * is terminated. Defaults to true. If false, the thread can outlive the thread which - * started it. - */ - constructor(action: () => void, daemon?: boolean); - - /** - * Starts the thread. Does nothing if the thread has already started. - */ - run(): void; - - /** - * Pauses the thread. The thread will not return from the {@link tick} function until it - * has been unpaused. If a thread pauses itself, it will continue execution until the next - * time it calls the {@link tick} function. - */ - pause(): void; - - /** - * Unpauses the thread - */ - unpause(): void; - - /** - * Kills the thread, which stops it running any more code. If a thread tries to kill itself, - * it will continue running until it calls the {@link tick} function, at which point it will - * be killed - */ - kill(): void; - - /** - * Blocks the currently executing thread until this thread has finished executing. An exception - * is thrown if a thread tries to wait for itself - */ - waitFor(): void; -} - -/** - * Contains information about a block state - */ -declare class BlockState { - - /** - * Returns the default block state of the given block - * @param block The block to get the default block state of - */ - static defaultState(block: string): BlockState; - - /** - * The block of this block state - */ - readonly block: string; - - /** - * A list of block state properties supported by this block, i.e. those that can be used - * in {@link World.getBlockProperty} - */ - readonly stateProperties: Array; - - /** - * Returns the value of the given property of the block state. - * If the property is a boolean or numeric property, then the value of the property - * is returned directly. Otherwise, a string representation of the value is returned. - * @param property The property to get - */ - getProperty(property: string): boolean | number | string; - - /** - * The light level emitted, 0-15 - */ - readonly luminance: number; - - /** - * The hardness of the block, proportional to how long it takes to mine. For example: - *
    - *
  • Tall grass: 0
  • - *
  • Dirt: 0.5
  • - *
  • Stone: 1.5
  • - *
  • Obsidian: 50
  • - *
  • Bedrock: -1
  • - *
- */ - readonly hardness: number; - - /** - * How resistant this block is to explosions. For example: - *
    - *
  • Stone: 6
  • - *
  • Obsidian: 1200
  • - *
  • Bedrock: 3600000
  • - *
- * Note: the wiki has these values 5 times larger than they should be - */ - readonly blastResistance: number; - - /** - * Whether this block responds to random ticks - */ - readonly randomTickable: boolean; - - /** - * A value between 0-1 indicating how slippery a block is. A value of 1 means no friction at all - * (as if an entity was moving sideways in air), a value of 0 will stop an entity instantly. Most - * blocks have a slipperiness of 0.6, while ice has a slipperiness of 0.98 - */ - readonly slipperiness: number; - - /** - * The loot table used to drop items after this block is mined - */ - readonly lootTable: string; - - /** - * The translation key used to get the name of this block - */ - readonly translationKey: string; - - /** - * The item corresponding to this block, or null if the block has no corresponding item - */ - readonly item: string | null; - - /** - * A unique ID of the material of the block, may change across Minecraft versions or when other mods - * add materials. It's safest to compare against the material ID of a block with a known material - */ - readonly materialId: number; - - /** - * The map color of this block, in packed 0xRRGGBB format - */ - readonly mapColor: number; - - /** - * How this block reacts to being pushed by a piston. - * - * - * - * - * - * - *
ValueExampleDescription
"normal"StonePiston will move the block
"destroy"TorchPiston will destroy the block (it will "pop off")
"block"ObsidianPiston cannot pull the block and block will prevent piston from pushing
"push_only"Glazed terracottaBlock can only be pushed, does not stick to slime
- */ - readonly pistonBehavior: string; - - /** - * Whether this block is flammable - */ - readonly flammable: boolean; - - /** - * Whether this block will drop without using the correct tool - */ - readonly canBreakByHand: boolean; - - /** - * Whether this block is a liquid - */ - readonly liquid: boolean; - - /** - * Whether this block blocks light TODO: investigate - */ - readonly blocksLight: boolean; - - /** - * Whether this block is replaced when placing a block, e.g. tall grass - */ - readonly replaceable: boolean; - - /** - * Whether this is a solid block TODO: investigate - */ - readonly solid: boolean; - - /** - * The burn chance, related to how quickly the block burns once it has caught fire - */ - readonly burnChance: number; - - /** - * The spread chance, related to how quickly a block catches fire in response to nearby fire - */ - readonly spreadChance: number; - - /** - * Whether this block will fall like sand when unsupported - */ - readonly fallable: boolean; - - /** - * The tags applying to this block - */ - readonly tags: Array; -} - -/** - * Represents an item stack, used to get certain properties of that stack. Note that translating - * to and from this representation is inefficient, so shouldn't be done unnecessarily frequently - */ -declare class ItemStack { - - /** - * Returns the ItemStack representation of the given item stack NBT - * @param stack The NBT representation of the item stack - */ - static of(stack: object): ItemStack; - - /** - * Creates an item stack of size 1 with the given item - * @param item The item to make a stack of - */ - static of(item: string): ItemStack; - - /** - * Returns the NBT representation of this item stack - */ - readonly stack: object; - - /** - * Gets the mining speed of this item stack against a given block state. This is a multiplier, - * where a value of 1 indicates the same speed as with a fist against a block which doesn't require - * a tool - * @param block The block or block state to test against - */ - getMiningSpeed(block: string | BlockState): number; - - /** - * Returns whether this item is effective against a block which requires a tool. Note this does not - * affect mining speed, only whether the block drops its items or not - * @param block The block or block state to test against - */ - isEffectiveOn(block: string | BlockState): boolean; - - /** - * The maximum stack size of this item. Usually 64, but may also be 1 or 16 in vanilla. - * A value of 1 indicates that this item is non-stackable - */ - readonly maxCount: number; - - /** - * The maximum amount of damage this item can take, if it is for example a tool - */ - readonly maxDamage: number; - - /** - * Whether this item is a food item - */ - readonly isFood: boolean; - - /** - * The amount of hunger this item restores, or 0 if this is not a food item - */ - readonly hungerRestored: number; - - /** - * The amount of saturation this item restores, or 0 if this is not a food item - */ - readonly saturationRestored: number; - - /** - * Whether this is a food item and is meat (used for whether wolves like it) - */ - readonly isMeat: boolean; - - /** - * Whether this is a food item and can be eaten even with full hunger (e.g. golden apple) - */ - readonly alwaysEdible: boolean; - - /** - * Whether this is a snack food item, which doesn't take as long to eat (e.g. berries) - */ - readonly isSnack: boolean; - - /** - * The tags applying to this item - */ - readonly tags: Array; -} - -/** - * Represents a 3D position - */ -interface Position { - x: number; - y: number; - z: number; -} - -/** - * Pathfinding hints - */ -interface PathfindingHints { - - /** - * A function that gets the path node type for the given coordinates. Returns null for vanilla behavior. - * A list of current path node types and their penalties as of 1.15 is as follows: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
NameDefault penalty
"blocked"-1
"open"0
"walkable"0
"trapdoor"0
"fence"-1
"lava"-1
"water"8
"water_border"8
"rail"0
"danger_fire"8
"damage_fire"16
"danger_cactus"8
"damage_cactus"-1
"danger_other"8
"damage_other"-1
"door_open"0
"door_wood_closed"-1
"door_iron_closed"-1
"breach"4
"leaves"-1
"sticky_honey"8
"cocoa"0
- */ - nodeTypeFunction?: (x: number, y: number, z: number) => string | null; - - /** - * A function that gets the pathfinding penalty for the given path node type. - *
    - *
  • Return 0 for no penalty.
  • - *
  • Return -1 for a completely impassable block.
  • - *
  • Return higher positive numbers for higher penalties.
  • - *
- * See {@link nodeTypeFunction} for a list of path node types and their default penalties - */ - penaltyFunction?: (type: string) => number | null; - - /** - * The maximum Euclidean distance to the target that the player can be at any one time. - * Defaults to twice the distance to the target. - */ - followRange?: number; - - /** - * The maximum distance from the target which is sufficient to reach. Defaults to 0 - */ - reachDistance?: number; - - /** - * The maximum length of a path at any one time. Defaults to twice the distance to the target. - */ - maxPathLength?: number; - -} diff --git a/docs/src/clientCommands.d.ts b/docs/src/clientCommands.d.ts new file mode 100644 index 0000000..ea1b264 --- /dev/null +++ b/docs/src/clientCommands.d.ts @@ -0,0 +1,1012 @@ +declare namespace cc { + /** + * The player which the user has control over + */ + const player: ControllablePlayer; + /** + * The client-side world which the player is in + */ + const world: World; + + type blockSides = 'east' | 'west' | 'south' | 'north' | 'up' | 'down'; + + /** + * Runs a client-side command and returns the result. Can also be an entity selector. + * @param command The command or entity selector to run. + * @return The integer result of the command, or list of matching entities in the case of an entity selector. + */ + function $(command: string): number | Array; + + /** + * Prints a string to client-side chat + * @param x The string to print + */ + function print(x: string): void; + + /** + * Sends a message to the game chat, prefix with "/" to run a server-side command. + * @param msg The message to send + */ + function chat(msg: string): void; + + /** + * Allows the game to run a tick. Pauses script execution until the next tick + */ + function tick(): void; + + /** + * Returns true if you are logged in to a game, false otherwise. Many operations are invalid if you are not logged in. + */ + function isLoggedIn(): boolean; + + /** + * If a string, matches items by their name, with the "minecraft:" prefix removed if it exists. + * If an object, matches the item NBT. + * If a function, it should return true or false based on the input item NBT. + */ + type ItemPredicate = string | object | ((itemNbt: object) => boolean); + + /** + * Represents a generic entity + */ + interface Entity { + /** + * Whether this is a valid reference to an entity. A reference may be invalid if you are not ingame, you are in a + * different dimension to the entity, or the entity has died or unloaded. All other operations on this entity will + * fail if it is invalid. + */ + readonly valid: boolean; + /** + * The type of the entity, as used in commands. If the prefix, would be "minecraft:", then that prefix is stripped + */ + readonly type: string; + /** + * The x-position of the entity + */ + readonly x: number; + /** + * The y-position of the entity + */ + readonly y: number; + /** + * The z-position of the entity + */ + readonly z: number; + /** + * The yaw of the entity in degrees. 0 degrees is to the south, increasing clockwise + */ + readonly yaw: number; + /** + * The pitch of the entity in degrees. 0 degrees is forwards, increasing downwards + */ + readonly pitch: number; + /** + * The x-velocity of the entity + */ + readonly motionX: number; + /** + * The y-velocity of the entity + */ + readonly motionY: number; + /** + * The z-velocity of the entity + */ + readonly motionZ: number; + /** + * The NBT of the entity + */ + readonly nbt: object; + + /** + * Returns whether this entity is the same entity as the other entity + * @param other The other entity + */ + equals(other: Entity): boolean; + } + + /** + * A living entity, e.g. mobs, players + */ + interface LivingEntity extends Entity { + /** + * The eye height of the entity in its current pose + */ + readonly eyeHeight: number; + /** + * The eye height of the entity in its standing pose + */ + readonly standingEyeHeight: number; + } + + /** + * A player + */ + interface Player extends LivingEntity {} + + /** + * A player which the user has control over + */ + interface ControllablePlayer extends Player { + /** + * Teleports the player a limited distance. This function cannot teleport the player more than 0.5 blocks, + * and is meant for alignment rather than movement. Use properties like {@link pressingForward} and + * {@link sprinting} for movement. Returns whether successful (the player was close enough to the + * given position). + * @param x The x-position to snap the player to + * @param y The y-position to snap the player to + * @param z The z-position to snap the player to + * @param sync Whether to sync the position with the server immediately after the teleport, rather than + * at the start of the next tick. If absent, defaults to false + */ + snapTo(x: number, y: number, z: number, sync?: boolean): boolean; + + /** + * Moves the player in a straight line to the specified target position. Blocks until it reaches there. + * Returns whether successful + * @param x The x-position of the target + * @param z The z-position of the target + * @param smart Default true, whether to jump up single block gaps + */ + moveTo(x: number, z: number, smart?: boolean): boolean; + + /** + * Pathfinds the player to the specified target position. Blocks until it reaches there. + * Returns whether successful + * @param x The x-position of the target + * @param y The y-position of the target + * @param z The z-position of the target + * @param hints The pathfinding hints + */ + pathTo( + x: number, + y: number, + z: number, + hints?: PathfindingHints + ): boolean; + /** + * Pathfinds the player to the specified moving target entity. Blocks until it reaches there. + * Returns whether successful + * @param target The entity to follow + * @param hints The pathfinding hints + */ + pathTo(target: Entity, hints?: PathfindingHints): boolean; + /** + * Pathfinds the player to the specified moving target. The input function will be called periodically + * to update the target position. Returns whether successful + * @param movingTarget The moving target to follow + * @param hints The pathfinding hints + */ + pathTo(movingTarget: () => Position, hints?: PathfindingHints): boolean; + + /** + * The yaw of the player in degrees. 0 degrees is to the south, increasing clockwise + */ + yaw: number; + /** + * The pitch of the player in degrees. 0 degrees is forwards, increasing downwards + */ + pitch: number; + + /** + * Causes the player to look towards a point in space. + * @param x The x-position of the point to look at + * @param y The y-position of the point to look at + * @param z The z-position of the point to look at + */ + lookAt(x: number, y: number, z: number): void; + /** + * Causes the player to look towards an entity. If target is a {@link LivingEntity}, then + * the player will look at the eye height of that entity. Otherwise, it will look at the bottom + * of the entity. + * @param target The entity to look at + */ + lookAt(target: Entity): void; + + /** + * Forces a synchronization of the player's look angles with the server. By default, the player's + * new rotation is only sent to the server at the start of the next tick, meaning that if you + * perform certain actions that depend on the player's rotation, such as dropping an item, it will + * happen as if the player was still facing in the previous direction. Calling this function will + * immediately send the player's rotation to the server, so that further actions (like dropping an + * item) will be performed with the correct rotation. + */ + syncRotation(): void; + + /** + * The currently selected hotbar slot + */ + selectedSlot: number; + /** + * The player's inventory. Slot numbers are as follows: + * + * 0-8: Hotbar + * 9-35: The rest of the main inventory + * 36-39: Armor (head, torso, legs, feet) + * 40: Offhand + * 41: Crafting result slot + * 42-45: Crafting grid + * + * Slots beyond the hotbar and main inventory will be inaccessible while the player is looking into + * a container. + */ + readonly inventory: Inventory; + /** + * The inventory of the container the player is looking in, or null if the player isn't looking + * in any container + */ + readonly currentContainer: Inventory | null; + + /** + * Opens a container by right clicking the block at the given block position, and wait for a container + * of type expectedContainerType to be opened. + * @param x The x-position of the container block + * @param y The y-position of the container block + * @param z The z-position of the container block + * @param expectedContainerType The container type to expect, or a function that returns true/false + * depending on whether a container type should be accepted + * @return Whether successful + */ + openContainer( + x: number, + y: number, + z: number, + expectedContainerType: string | ((containerType: string) => boolean) + ): boolean; + + /** + * Opens a container by right clicking the given entity, and wait for a container of type + * expectedContainerType to be opened. + * @param entity The entity to click on + * @param expectedContainerType The container type to expect, or a function that returns true/false + * depending on whether a container type should be accepted + * @return Whether successful + */ + openContainer( + entity: Entity, + expectedContainerType: string | ((containerType: string) => boolean) + ): boolean; + + /** + * Closes the currently opened container, if any is open. Due to a threading issue in 1.16, this method delays + * the script by 1 tick, if a container was open. + */ + closeContainer(): void; + + /** + * If the player currently has a crafting container open, crafts as many times as possible up to the given + * number of times. Places items matching the given parameters into the given pattern, waits for a result matching + * result to appear, and pulls it out of the crafting grid. + * @param result The expected result of the recipe + * @param craftCount The number of crafts + * @param pattern An array of rows of the pattern. Each character corresponds to an item, use spaces for blank slots + * @param ingredients Associates characters with items + * @return The number of crafts managed + */ + craft( + result: ItemPredicate, + craftCount: number, + pattern: Array, + ingredients: { [keys: string]: ItemPredicate } + ): number; + + /** + * "picks" an item from the player's inventory, and selects it in the hotbar, in a similar fashion to the + * vanilla pick block feature. + * @param item The item to pick + * @return Whether a matching item could be found in the inventory + */ + pick(item: ItemPredicate): boolean; + + /** + * Right clicks the currently held item in air + * + * Warning: right-clicking some items is a continuous action. This function on its own + * will not work for this! For an easy way to eat food, see {@link longUseItem} + * @return Whether the item use was considered successful + */ + rightClick(): boolean; + /** + * Right clicks a block. Will click on the closest part of the block at the given position. + * This function also modifies the player rotation to look at where they clicked, if they are + * not already hovering over the block. + * @param x The x-position of the block to right click + * @param y The y-position of the block to right click + * @param z The z-position of the block to right click + * @param side The side of the block to click on. If not specified, will click on the closest side. + * @return Whether the right click was successful + */ + rightClick(x: number, y: number, z: number, side?: blockSides): boolean; + /** + * Right clicks an entity. This function also modifies the player rotation to look at the entity they + * clicked on. + * @param entity The entity to right click + * @return Whether the right click was successful + */ + rightClick(entity: Entity): boolean; + + /** + * Left clicks on a block. Will click on the closest part of the block at the given position. + * This function also modifies the player rotation to look at where they clicked, if they are + * not already hovering over the block. + * + * Warning: left-clicking many blocks is a continuous mining action. This function on its own + * will not work for this! For an easy way to mine blocks, see {@link longMineBlock} + * @param x The x-position of the block to right click + * @param y The y-position of the block to right click + * @param z The z-position of the block to right click + * @param side The side of the block to click on. If not specified, will click on the closest side. + * @return Whether the left click was successful + */ + leftClick(x: number, y: number, z: number, side?: string): boolean; + /** + * Left clicks on an entity (i.e. usually attacking it). This function also modifies the player rotation to + * look at the entity they clicked on. + * @param entity The entity to left click + * @return Whether the left click was successful + */ + leftClick(entity: Entity): boolean; + + /** + * Blocks user input until either this script terminates or {@link unblockInput} is called (and so long as + * no other scripts are also blocking input). + */ + blockInput(): void; + + /** + * Stops this script blocking user input + */ + unblockInput(): void; + + /** + * Holds down right click until the item can be used no more! For food, this has the effect of eating a single + * food item. Pauses execution of the script until the action is finished. Also blocks input for the duration + * of item use. + */ + longUseItem(): boolean; + + /** + * Mines a block with the currently held item until it is broken. Pauses execution of the script until the + * action is finished. Also blocks input for the duration of the block breaking. + * @param x The x-position of the block to mine + * @param y The y-position of the block to mine + * @param z The z-position of the block to mine + */ + longMineBlock(x: number, y: number, z: number): boolean; + + /** + * Whether the script is pressing forward for the player. This shouldn't be used to get whether forward is + * being pressed, it will produce inconsistent results. It should be used to __set__ whether forward + * is pressed by the current script. + */ + pressingForward: boolean; + /** + * Whether the script is pressing back for the player. This shouldn't be used to get whether back is + * being pressed, it will produce inconsistent results. It should be used to __set__ whether back + * is pressed by the current script. + */ + pressingBack: boolean; + /** + * Whether the script is pressing left for the player. This shouldn't be used to get whether left is + * being pressed, it will produce inconsistent results. It should be used to __set__ whether left + * is pressed by the current script. + */ + pressingLeft: boolean; + /** + * Whether the script is pressing right for the player. This shouldn't be used to get whether right is + * being pressed, it will produce inconsistent results. It should be used to __set__ whether right + * is pressed by the current script. + */ + pressingRight: boolean; + /** + * Whether the script is pressing the jump key for the player. This shouldn't be used to get whether jump is + * being pressed, it will produce inconsistent results. It should be used to __set__ whether jump + * is pressed by the current script. + */ + jumping: boolean; + /** + * Whether the script is pressing the sneak key for the player. This shouldn't be used to get whether sneak is + * being pressed, it will produce inconsistent results. It should be used to __set__ whether sneak + * is pressed by the current script. + */ + sneaking: boolean; + /** + * Whether the script is pressing the sprint key for the player. This shouldn't be used to get whether sprint is + * being pressed, it will produce inconsistent results. It should be used to __set__ whether sprint + * is pressed by the current script. + */ + sprinting: boolean; + + /** + * Attempts to disconnect from the server. Terminates the script if successful. + */ + disconnect(): void; + + /** + * Disconnects and reconnects the player to the server. Returns whether successful. This function may return before + * the player has fully logged in again; check {@link isLoggedIn()} in a loop to wait for the player to be logged + * in. If the relog failed, depending on how it failed, the script may terminate after the next tick. The script + * will continue running if successful. + */ + relog(): boolean; + } + + /** + * The options for an inventory click + */ + interface InventoryClickOptions { + /** + * The click type, one of: + * - pickup: Swaps the item held by the cursor with the item in the given slot. This is the default click type + * - quick_move: "Shift-clicks" on the given slot, which is commonly a quick way of moving items into and out of a container + * - swap: Swaps the given slot with a hotbar slot, specified by also setting the {@link hotbarSlot} property on this object + * - clone: (Creative-mode-only) clones the item in the given slot, equivalent to a middle-click on it + * - throw: Throws the item in the given slot out of the inventory + * - quick_craft: Performs a quick-craft. Must be performed in multiple stages, specified by also setting the {@link quickCraftStage} property in this object + * - pickup_all: Picks up all items of the type in the slot + * + * @default "pickup" + */ + type?: + | 'pickup' + | 'quick_move' + | 'swap' + | 'clone' + | 'throw' + | 'quick_craft' + | 'pickup_all'; + /** + * Whether to simulate a right click rather than a left click (which is the default). + * When {@link type} is "throw", then setting this to true throws all items rather than just one. + */ + rightClick?: boolean; + /** + * When {@link type} is "swap", specifies the hotbar slot to swap with + */ + hotbarSlot?: number; + /** + * When {@link type} is "quick_craft", specifies the quick craft stage (0-3) + */ + quickCraftStage?: number; + } + + /** + * Represents an inventory/container of items + */ + interface Inventory { + /** + * The type of inventory. Returns either "player", "creative", "horse" or the container ID. + * Note that the container ID may be more generic than you might expect, e.g. "generic_9x3" + * for different types of chests. + */ + readonly type: string; + /** + * The items in the inventory. This is an array of item stack NBT objects. + */ + readonly items: Array; + + /** + * Simulates a click in an inventory slot. This function covers most inventory actions. + * @param slot The slot ID to click on. If null, this represents clicking outside + * the window (usually with the effect of dropping the stack under the cursor). + * @param options The options of the inventory action. See {@link InventoryClickOptions}. + */ + click(slot: number | null, options?: InventoryClickOptions): void; + + /** + * Finds the first slot in the container with an item that matches the given item predicate + * @param item The item to search for + * @param reverse If true, returns the last matching slot rather than the first one + * @return The index of the first matching slot, or null if no such slot is found. + */ + findSlot(item: ItemPredicate, reverse?: boolean): number | null; + + /** + * Lists the slots in the container with an item that matches the given item predicate, up + * until the maximum number of items has been reached. + * @param item The item to search for + * @param count The maximum amount of this item to search for, or -1 for no maximum + * @param reverse If true, returns the last matching slots first rather than the first matching slot first + * @return An array of matching slot indices + */ + findSlots( + item: ItemPredicate, + count: number, + reverse?: boolean + ): Array; + + /** + * Shift clicks all the matching items in this container, up until the maximum number of items has been reached. + * @param item The item to search for + * @param count The maximum amount of this item to shift lick, or -1 for no maximum + * @param reverse If true, shift clicks the items in reverse order of slot indices + * @return The actual number of items shift clicked, may be greater than or equal to count if there + * are sufficient items in this container, or equal to the number of matching items if there are + * insufficient items. + */ + moveItems( + item: ItemPredicate, + count: number, + reverse?: boolean + ): number; + + /** + * Return whether this inventory is the same as another inventory + * @param other The other inventory + */ + equals(other: Inventory): boolean; + } + + /** + * The type of the global world variable, the client-side world. + */ + interface World { + /** + * The dimension ID of the current dimension. In vanilla, this can either be "overworld", + * "the_nether" or "the_end"; with datapacks or in modded this may take other values. + */ + readonly dimension: string; + + /** + * Gets the name of the block at the given position in the client-side world. + * @param x The x-position of the block to query + * @param y The y-position of the block to query + * @param z The z-position of the block to query + * @return The block name, as used in commands. If there would be a "minecraft:" prefix, the prefix is removed. + */ + getBlock(x: number, y: number, z: number): string; + + /** + * Gets the block state property with the given name at the given position. + * Equivalent to getBlockState(x, y, z).getProperty(property) + * @param x The x-position of the block state to query + * @param y The y-position of the block state to query + * @param z The z-position of the block state to query + * @param property The property name to query. E.g. could be "power" for redstone dust, or "bed_part" for beds. + */ + getBlockProperty( + x: number, + y: number, + z: number, + property: string + ): boolean | number | string; + + /** + * Gets the block state at the given position. + * @param x The x-position of the block state to get + * @param y The y-position of the block state to get + * @param z The z-position of the block state to get + */ + getBlockState(x: number, y: number, z: number): BlockState; + + /** + * Gets the client-side block entity NBT at the given coordinates + * @param x The x-position of the block entity whose NBT to get + * @param y The y-position of the block entity whose NBT to get + * @param z The z-position of the block entity whose NBT to get + * @return The NBT object of the block entity, or null if there was no block entity + */ + getBlockEntityNbt(x: number, y: number, z: number): object | null; + + /** + * Gets the block light at the given position, 0-15 + * @param x The x-coordinate of the position to get the block light of + * @param y The y-coordinate of the position to get the block light of + * @param z The z-coordinate of the position to get the block light of + */ + getBlockLight(x: number, y: number, z: number): number; + + /** + * Gets the sky light at the given position, 0-15 + * @param x The x-coordinate of the position to get the sky light of + * @param y The y-coordinate of the position to get the sky light of + * @param z The z-coordinate of the position to get the sky light of + */ + getSkyLight(x: number, y: number, z: number): number; + + /** + * Finds the closest visible point on a block + * @param x The x-position of the block to find the closest visible point on + * @param y The y-position of the block to find the closest visible point on + * @param z The z-position of the block to find the closest visible point on + * @param side The side of the block to find the closest visible point on. If not specified, will use the closest side. + * @return Whether there was a visible point on the block within reach + */ + getClosestVisiblePoint( + x: number, + y: number, + z: number, + side?: string + ): Position | null; + } + + /** + * Defines a "thread", which is an action which can run "concurrently" with other threads. + * This is not concurrency in the sense you may be used to as a programmer. Only one thread + * can run at a time. When you start another thread, that thread gains control immediately, + * until either it stops or it calls the {@link tick} function, which allows other script + * threads to run their code, and the game to run a tick. Therefore, you do not have to + * worry about thread safety, as all operations are thread safe. + */ + class Thread { + /** + * The currently executing thread. If this thread is not a clientcommands thread or the main script thread, then + * this returns null. This is possible for example via JsMacros' JavaWrapper. + */ + static readonly current: Thread | null; + + /** + * Whether the thread is currently running. Note this does not necessarily mean this + * thread is the currently executing thread. To test that, use thread === Thread.current + */ + readonly running: boolean; + + /** + * Whether the thread has been paused by {@link pause}. To pause an unpause threads, use the methods + */ + readonly paused: boolean; + + /** + * Whether the thread is a daemon thread. If true, this thread will be killed when the parent thread + * stops; if false, this thread may outlive its parent + */ + readonly daemon: boolean; + + /** + * The thread which started this thread. If null, either this thread was not started by a script, or + * this thread is not a daemon and the parent thread has died + */ + readonly parent: Thread | null; + + /** + * An array view of running threads started by this thread + */ + readonly children: Array; + + /** + * Creates a thread which will execute the given function on it when run. Does not + * run automatically, remember to explicitly call the {@link run} function. + * @param action The function to be executed on this thread + * @param daemon Whether this thread will be killed when the thread which started it + * is terminated. Defaults to true. If false, the thread can outlive the thread which + * started it. + */ + constructor(action: () => void, daemon?: boolean); + + /** + * Starts the thread. Does nothing if the thread has already started. + */ + run(): void; + + /** + * Pauses the thread. The thread will not return from the {@link tick} function until it + * has been unpaused. If a thread pauses itself, it will continue execution until the next + * time it calls the {@link tick} function. + */ + pause(): void; + + /** + * Unpauses the thread + */ + unpause(): void; + + /** + * Kills the thread, which stops it running any more code. If a thread tries to kill itself, + * it will continue running until it calls the {@link tick} function, at which point it will + * be killed + */ + kill(): void; + + /** + * Blocks the currently executing thread until this thread has finished executing. An exception + * is thrown if a thread tries to wait for itself + */ + waitFor(): void; + } + + /** + * Contains information about a block state + */ + class BlockState { + /** + * Returns the default block state of the given block + * @param block The block to get the default block state of + */ + static defaultState(block: string): BlockState; + + /** + * The block of this block state + */ + readonly block: string; + + /** + * A list of block state properties supported by this block, i.e. those that can be used + * in {@link World.getBlockProperty} + */ + readonly stateProperties: Array; + + /** + * Returns the value of the given property of the block state. + * If the property is a boolean or numeric property, then the value of the property + * is returned directly. Otherwise, a string representation of the value is returned. + * @param property The property to get + */ + getProperty(property: string): boolean | number | string; + + /** + * The light level emitted, 0-15 + */ + readonly luminance: number; + + /** + * The hardness of the block, proportional to how long it takes to mine. For example: + * - Tall grass: 0 + * - Dirt: 0.5 + * - Stone: 1.5 + * - Obsidian: 50 + * - Bedrock: -1 + * + */ + readonly hardness: number; + + /** + * How resistant this block is to explosions. For example: + * + * - Stone: 6 + * - Obsidian: 1200 + * - Bedrock: 3600000 + * + * Note: the wiki has these values 5 times larger than they should be + */ + readonly blastResistance: number; + + /** + * Whether this block responds to random ticks + */ + readonly randomTickable: boolean; + + /** + * A value between 0-1 indicating how slippery a block is. A value of 1 means no friction at all + * (as if an entity was moving sideways in air), a value of 0 will stop an entity instantly. Most + * blocks have a slipperiness of 0.6, while ice has a slipperiness of 0.98 + */ + readonly slipperiness: number; + + /** + * The loot table used to drop items after this block is mined + */ + readonly lootTable: string; + + /** + * The translation key used to get the name of this block + */ + readonly translationKey: string; + + /** + * The item corresponding to this block, or null if the block has no corresponding item + */ + readonly item: string | null; + + /** + * A unique ID of the material of the block, may change across Minecraft versions or when other mods + * add materials. It's safest to compare against the material ID of a block with a known material + */ + readonly materialId: number; + + /** + * The map color of this block, in packed 0xRRGGBB format + */ + readonly mapColor: number; + + /** + * How this block reacts to being pushed by a piston. + * - normal: Piston will move the block (ex. Stone) + * - destroy: Piston will destroy the block (it will "pop off") (ex. Torch) + * - block: Piston cannot pull the block and block will prevent piston from pushing (ex. Obsidian) + * - push_only: Block can only be pushed, does not stick to slime (ex. Glazed terracotta) + */ + readonly pistonBehavior: 'normal' | 'destroy' | 'block' | 'push_only'; + + /** + * Whether this block is flammable + */ + readonly flammable: boolean; + + /** + * Whether this block will drop without using the correct tool + */ + readonly canBreakByHand: boolean; + + /** + * Whether this block is a liquid + */ + readonly liquid: boolean; + + /** + * Whether this block blocks light TODO: investigate + */ + readonly blocksLight: boolean; + + /** + * Whether this block is replaced when placing a block, e.g. tall grass + */ + readonly replaceable: boolean; + + /** + * Whether this is a solid block TODO: investigate + */ + readonly solid: boolean; + + /** + * The burn chance, related to how quickly the block burns once it has caught fire + */ + readonly burnChance: number; + + /** + * The spread chance, related to how quickly a block catches fire in response to nearby fire + */ + readonly spreadChance: number; + + /** + * Whether this block will fall like sand when unsupported + */ + readonly fallable: boolean; + + /** + * The tags applying to this block + */ + readonly tags: Array; + } + + /** + * Represents an item stack, used to get certain properties of that stack. Note that translating + * to and from this representation is inefficient, so shouldn't be done unnecessarily frequently + */ + class ItemStack { + /** + * Returns the ItemStack representation of the given item stack NBT + * @param stack The NBT representation of the item stack + */ + static of(stack: object): ItemStack; + + /** + * Creates an item stack of size 1 with the given item + * @param item The item to make a stack of + */ + static of(item: string): ItemStack; + + /** + * Returns the NBT representation of this item stack + */ + readonly stack: object; + + /** + * Gets the mining speed of this item stack against a given block state. This is a multiplier, + * where a value of 1 indicates the same speed as with a fist against a block which doesn't require + * a tool + * @param block The block or block state to test against + */ + getMiningSpeed(block: string | BlockState): number; + + /** + * Returns whether this item is effective against a block which requires a tool. Note this does not + * affect mining speed, only whether the block drops its items or not + * @param block The block or block state to test against + */ + isEffectiveOn(block: string | BlockState): boolean; + + /** + * The maximum stack size of this item. Usually 64, but may also be 1 or 16 in vanilla. + * A value of 1 indicates that this item is non-stackable + */ + readonly maxCount: number; + + /** + * The maximum amount of damage this item can take, if it is for example a tool + */ + readonly maxDamage: number; + + /** + * Whether this item is a food item + */ + readonly isFood: boolean; + + /** + * The amount of hunger this item restores, or 0 if this is not a food item + */ + readonly hungerRestored: number; + + /** + * The amount of saturation this item restores, or 0 if this is not a food item + */ + readonly saturationRestored: number; + + /** + * Whether this is a food item and is meat (used for whether wolves like it) + */ + readonly isMeat: boolean; + + /** + * Whether this is a food item and can be eaten even with full hunger (e.g. golden apple) + */ + readonly alwaysEdible: boolean; + + /** + * Whether this is a snack food item, which doesn't take as long to eat (e.g. berries) + */ + readonly isSnack: boolean; + + /** + * The tags applying to this item + */ + readonly tags: Array; + } + + /** + * Represents a 3D position + */ + interface Position { + x: number; + y: number; + z: number; + } + + /** + * Pathfinding hints + */ + interface PathfindingHints { + /** + * A function that gets the path node type for the given coordinates. Returns null for vanilla behavior. + * A list of current path node types and their penalties as of 1.15 is as follows: + * - blocked: -1 + * - open: 0 + * - walkable: 0 + * - trapdoor: 0 + * - fence: -1 + * - lava: -1 + * - water: 8 + * - water_border: 8 + * - rail: 0 + * - danger_fire: 8 + * - damage_fire: 16 + * - danger_cactus: 8 + * - damage_cactus: -1 + * - danger_other: 8 + * - damage_other: -1 + * - door_open: 0 + * - door_wood_closed: -1 + * - door_iron_closed: -1 + * - breach: 4 + * - leaves: -1 + * - sticky_honey: 8 + * - cocoa: 0 + */ + nodeTypeFunction?: (x: number, y: number, z: number) => string | null; + + /** + * A function that gets the pathfinding penalty for the given path node type. + * + * - Return 0 for no penalty. + * - Return -1 for a completely impassable block. + * - Return higher positive numbers for higher penalties. + * + * See {@link nodeTypeFunction} for a list of path node types and their default penalties + */ + penaltyFunction?: (type: string) => number | null; + + /** + * The maximum Euclidean distance to the target that the player can be at any one time. + * Defaults to twice the distance to the target. + */ + followRange?: number; + + /** + * The maximum distance from the target which is sufficient to reach. Defaults to 0 + */ + reachDistance?: number; + + /** + * The maximum length of a path at any one time. Defaults to twice the distance to the target. + */ + maxPathLength?: number; + } +} From ac19c7173fd3d4a21ef0669131f050069132f7aa Mon Sep 17 00:00:00 2001 From: Brian <5673408+illumincrotty@users.noreply.github.com> Date: Thu, 27 Jan 2022 18:54:19 -0600 Subject: [PATCH 2/5] Make Readme more clear and explicit --- README.md | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index b4a774d..a3d1092 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,20 @@ # Clientcommands Scripting -This repository is the scripting module of [clientcommands](https://github.com/Earthcomputer/clientcommands). This mod is distributed as part of clientcommands, so please refer to clientcommands' readme for installation instructions. + +This repository is the scripting module of [clientcommands](https://github.com/Earthcomputer/clientcommands). This mod is distributed as part of clientcommands, so please refer to clientcommands' readme for installation instructions. As of 1.18 [JSMacros](https://github.com/wagyourtail/JsMacros) is required and client commands scripts must use the namespace cc to access functions. For example, you must now use `cc.print("hello")` instead of just `print("hello")`. Scripts should now be put in `.minecraft/config/jsmMcros/Macros`. ## Contributing + As this mod is a submodule of clientcommands, you must clone it as a submodule of clientcommands and work with it that way. 1. Clone the clientcommands repository and submodules - ``` - git clone --recursive-submodules https://github.com/Earthcomputer/clientcommands - cd clientcommands - ``` + ``` + git clone --recursive-submodules https://github.com/Earthcomputer/clientcommands + cd clientcommands + ``` 1. Generate the Minecraft source code - ``` - ./gradlew genSources - ``` + ``` + ./gradlew genSources + ``` - Note: on Windows, use `gradlew` rather than `./gradlew`. 1. Import the clientcommands project into your preferred IDE. 1. If you use IntelliJ (the preferred option), you can simply import the project as a Gradle project. @@ -22,10 +24,10 @@ As this mod is a submodule of clientcommands, you must clone it as a submodule o 1. To test clientcommands-scripting inside the IDE, you need to edit the run configuration that was generated by Fabric loom to run the clientcommands-scripting module. In IntelliJ, the option can be found here: ![Image showing where to edit the module of a run configuration](https://user-images.githubusercontent.com/13084089/124387081-10077100-dcd5-11eb-826e-c84f717eafcc.png) 1. After testing in the IDE, build a JAR to test whether it works outside the IDE too. Build clientcommands by running the following command in the root project directory - ``` - ./gradlew build - ``` - The mod JAR may be found in the `build/libs` directory + ``` + ./gradlew build + ``` + The mod JAR may be found in the `build/libs` directory - Note: the build is currently slightly broken, in that you may need to run this command twice before the build is successful. So if the build fails, just run it again and it should hopefully succeed the second time. 1. [Create a pull request](https://help.github.com/en/articles/creating-a-pull-request) so that your changes can be integrated into Clientcommands Scripting From 2e65fd9f21e40146d11c9012e8f1f807e48d9dea Mon Sep 17 00:00:00 2001 From: Brian <5673408+illumincrotty@users.noreply.github.com> Date: Thu, 27 Jan 2022 18:54:33 -0600 Subject: [PATCH 3/5] Create working example --- docs/example_scripts/branch_mine.js | 443 ------------------------- docs/example_scripts/build_platform.js | 258 -------------- docs/src/snapToGrid.ts | 12 + docs/src/util.ts | 82 +++++ docs/tsconfig.json | 101 ++++++ 5 files changed, 195 insertions(+), 701 deletions(-) delete mode 100644 docs/example_scripts/branch_mine.js delete mode 100644 docs/example_scripts/build_platform.js create mode 100644 docs/src/snapToGrid.ts create mode 100644 docs/src/util.ts create mode 100644 docs/tsconfig.json diff --git a/docs/example_scripts/branch_mine.js b/docs/example_scripts/branch_mine.js deleted file mode 100644 index 977e67e..0000000 --- a/docs/example_scripts/branch_mine.js +++ /dev/null @@ -1,443 +0,0 @@ - -var wantedBlocks = ["emerald_ore", "diamond_ore", "gold_ore", "iron_ore", "coal_ore", "redstone_ore", "lapis_ore"]; - -var isWantedBlock = function(block) { - return wantedBlocks.indexOf(block) !== -1; -}; -var isWantedItemEntity = function(entity) { - if (entity.type !== "item") - return false; - var nbt = entity.nbt; - if (!nbt.Item) - return false; - var type = nbt.Item.id; - for (var i = 0; i < wantedBlocks.length; i++) - if (type === "minecraft:" + wantedBlocks[i]) - return true; - return type === "minecraft:emerald" || type === "minecraft:diamond" - || type === "minecraft:coal" || type === "minecraft:redstone" - || type === "minecraft:lapis_lazuli"; -}; - -var getDirectionName = function(dx, dz) { - if (Math.abs(dx) > Math.abs(dz)) { - if (dx > 0) - return "east"; - else - return "west"; - } else { - if (dz > 0) - return "south"; - else - return "north"; - } -}; - -var canWalkThrough = function(block) { - return block === "air" || block === "cave_air" || block === "torch"; -}; - -var canWalkOn = function(block) { - if (canWalkThrough(block)) - return false; - if (BlockState.defaultState(block).liquid) - return false; - return true; -}; - -var getTool = function(block) { - var effective = function(item, block) { - var stack = ItemStack.of(item); - if (!BlockState.defaultState(block).canBreakByHand && !stack.isEffectiveOn(block)) - return false; - return stack.getMiningSpeed(block) > 1; - }; - if (effective("diamond_pickaxe", block)) - return "pickaxe"; - if (effective("diamond_shovel", block)) - return "shovel"; - if (effective("diamond_axe", block)) - return "axe"; - if (effective("diamond_sword", block)) - return "sword"; - return null; -}; - -var centerPlayer = function() { - player.pressingForward = false; - while (player.motionX * player.motionX + player.motionZ * player.motionZ > 0.001) - tick(); - if (Math.abs(Math.floor(player.x) + 0.5 - player.x) >= 0.2 || Math.abs(Math.floor(player.z) + 0.5 - player.z) >= 0.2) - return player.moveTo(Math.floor(player.x) + 0.5, Math.floor(player.z) + 0.5); - return true; -}; - -var clearWay = function(x, y, z, dx, dz) { - // mine block in front of player's face if necessary - if (!canWalkThrough(world.getBlock(x + dx, y + 1, z + dz))) { - if (!mineBlock(x + dx, y + 1, z + dz)) { - throw new Error(); - } - } - // mine block in front of player's feet if necessary - if (!canWalkThrough(world.getBlock(x + dx, y, z + dz))) { - if (!mineBlock(x + dx, y, z + dz)) { - throw new Error(); - } - } - // build bridge if necessary - if (!canWalkOn(world.getBlock(x + dx, y - 1, z + dz))) { - if (!makeBridge(x, y, z, dx, dz)) { - throw new Error(); - } - } - return true; -}; - -var placeBlock = function(x, y, z) { - if (!player.pick(function(itemNbt) { - return itemNbt.id === "minecraft:cobblestone" || itemNbt.id === "minecraft:stone"; - })) - throw new Error(); - - if (player.rightClick(x - 1, y, z, "east")) return true; - if (player.rightClick(x + 1, y, z, "west")) return true; - if (player.rightClick(x, y, z - 1, "south")) return true; - if (player.rightClick(x, y, z + 1, "north")) return true; - if (player.rightClick(x, y - 1, z, "up")) return true; - if (player.rightClick(x, y + 1, z, "down")) return true; - return false; -}; - -var mineBlock = function(x, y, z) { - var toolMaterialOrder = ["netherite","diamond", "iron", "stone", "wooden", "golden"]; - var tool = getTool(world.getBlock(x, y, z)); - if (tool) { - var picked = false; - for (var i = 0; i < toolMaterialOrder.length; i++) { - if (player.pick(toolMaterialOrder[i] + "_" + tool)) { - picked = true; - break; - } - } - if (!picked && !world.getBlockState(x, y, z).canBreakByHand) - throw new Error(); - } - - var oldBlock = world.getBlock(x, y, z); - if (oldBlock === "air") return true; - var failCount = 0; - do { - if (!player.longMineBlock(x, y, z)) { - failCount++; - tick(); - } - if (failCount > 5) - throw new Error("Block pos: (" + x + ", " + y + ", " + z + ")"); - } while (world.getBlock(x, y, z) === oldBlock); - - var stateAbove = world.getBlockState(x, y + 1, z); - if (stateAbove.fallable) { - while (world.getBlock(x, y, z) !== stateAbove.block) - tick(); - if (!mineBlock(x, y, z)) - throw new Error(); - } - - return true; -}; - -var makeBridge = function(x, y, z, dx, dz) { - // face backwards - player.lookAt(player.x - dx, player.y, player.z - dz); - // sneak backwards - var continueSneaking = function() { - player.pressingBack = true; - tick(); - timeout++; - if (timeout % 20 === 0) { - player.pressingBack = false; - player.sneaking = false; - if (!clearWay(x, y, z, dx, dz)) { - player.unblockInput(); - throw new Error(); - } - player.sneaking = true; - } - return true; - }; - player.blockInput(); - player.sneaking = true; - var timeout = 0; - while (Math.floor(player.x) === x && Math.floor(player.z) === z) { - if (!continueSneaking()) - throw new Error(); - } - // keep sneaking for an extra 5 ticks to make sure there's part of the block in view - for (var i = 0; i < 5; i++) { - if (!continueSneaking()) - throw new Error(); - } - player.pressingBack = false; - player.sneaking = false; - player.unblockInput(); - return placeBlock(x + dx, y - 1, z + dz); -}; - -var mineNearbyOre = function(x, y, z) { - centerPlayer(); - - var cardinals4 = [[-1, 0], [1, 0], [0, -1], [0, 1]]; - var cardinals6 = [[-1, 0, 0], [1, 0, 0], [0, 0, -1], [0, 0, 1], [0, -1, 0], [0, 1, 0]]; - - // mine blocks around head and above head - for (var dy = 1; dy <= 2; dy++) { - if (canWalkThrough(world.getBlock(x, y + dy, z))) { - for (var dir = 0; dir < cardinals6.length; dir++) { - var ddx = cardinals6[dir][0], ddy = cardinals6[dir][1], ddz = cardinals6[dir][2]; - if (isWantedBlock(world.getBlock(x + ddx, y + dy + ddy, z + ddz))) { - if (!mineBlock(x + ddx, y + dy + ddy, z + ddz)) - throw new Error(); - } - } - } - } - - // step up - for (var i = 0; i < 4; i++) { - var dx = cardinals4[i][0], dz = cardinals4[i][1]; - - // check if we want to step up - if (!canWalkThrough(world.getBlock(x + dx, y + 2, z + dz))) continue; - if (!canWalkThrough(world.getBlock(x + dx, y + 1, z + dz)) && !canWalkThrough(world.getBlock(x, y + 2, z))) continue; - var wantToStepUp = false; - for (var j = 0; j < 6; j++) { - var ddx = cardinals6[j][0], ddy = cardinals6[j][1], ddz = cardinals6[j][2]; - if (isWantedBlock(world.getBlock(x + dx + ddx, y + 2 + ddy, z + dz + ddz))) { - wantToStepUp = true; - break; - } - } - if (!wantToStepUp) continue; - - // mine block(s) to allow us to step up if necessary - if (!canWalkThrough(world.getBlock(x + dx, y + 1, z + dz))) - if (!mineBlock(x + dx, y + 1, z + dz)) - throw new Error(); - if (!canWalkThrough(world.getBlock(x, y + 2, z))) - if (!mineBlock(x, y + 2, z)) - throw new Error(); - if (!canWalkOn(world.getBlock(x + dx, y, z + dz))) - if (!placeBlock(x + dx, y, z + dz)) - continue; - - centerPlayer(); - - // do the step up - if (!player.moveTo(x + dx + 0.5, z + dz + 0.5)) throw new Error(); - if (!mineNearbyOre(x + dx, y + 1, z + dz)) throw new Error(); - centerPlayer(); - for (var dy = 2; dy >= 0; dy--) { - if (!canWalkThrough(world.getBlock(x, y + dy, z))) - if (!mineBlock(x, y + dy, z)) - throw new Error(); - } - if (!canWalkOn(world.getBlock(x, y - 1, z))) - if (!placeBlock(x, y - 1, z)) throw new Error(); - if (!player.moveTo(x + 0.5, z + 0.5)) throw new Error(); - } - - // mine blocks around feet level - for (var i = 0; i < 4; i++) { - var dx = cardinals4[i][0], dz = cardinals4[i][1]; - if (isWantedBlock(world.getBlock(x + dx, y, z + dz))) { - if (!mineBlock(x + dx, y, z + dz)) - throw new Error(); - - if (!canWalkOn(world.getBlock(x + dx, y - 1, z + dz))) - if (!placeBlock(x + dx, y - 1, z + dz)) - continue; - - if (!canWalkThrough(world.getBlock(x + dx, y + 1, z + dz))) { - if (!mineBlock(x + dx, y + 1, z + dz)) - throw new Error(); - } - - centerPlayer(); - if (!player.moveTo(x + dx + 0.5, z + dz + 0.5)) throw new Error(); - if (!mineNearbyOre(x + dx, y, z + dz)) throw new Error(); - centerPlayer(); - for (var dy = 1; dy >= 0; dy--) { - if (!canWalkThrough(world.getBlock(x, y + dy, z))) - if (!mineBlock(x, y + dy, z)) - throw new Error(); - } - if (!canWalkOn(world.getBlock(x, y - 1, z))) - if (!placeBlock(x, y - 1, z)) throw new Error(); - if (!player.moveTo(x + 0.5, z + 0.5)) throw new Error(); - } - } - - // keep mining for blocks possibly exposed by the mining operation - for (var dy = 1; dy >= 0; dy--) { - for (var i = 0; i < 4; i++) { - var dx = cardinals4[i][0], dz = cardinals4[i][1]; - if (canWalkThrough(world.getBlock(x + dx, y + dy, z + dz))) { - for (var j = 0; j < 6; j++) { - var ddx = cardinals6[j][0], ddy = cardinals6[j][1], ddz = cardinals6[j][2]; - if (ddy === -1 && dy === 0) continue; // mineNearbyOre doesn't mine straight down - if (isWantedBlock(world.getBlock(x + dx + ddx, y + dy + ddy, z + dz + ddz))) { - if (!clearWay(x, y, z, dx, dz)) - throw new Error(); - - centerPlayer(); - if (!player.moveTo(x + dx + 0.5, z + dz + 0.5)) throw new Error(); - if (!mineNearbyOre(x + dx, y, z + dz)) throw new Error(); - centerPlayer(); - for (var dy = 1; dy >= 0; dy--) { - if (!canWalkThrough(world.getBlock(x, y + dy, z))) - if (!mineBlock(x, y + dy, z)) - throw new Error(); - } - if (!canWalkOn(world.getBlock(x, y - 1, z))) - if (!placeBlock(x, y - 1, z)) throw new Error(); - if (!player.moveTo(x + 0.5, z + 0.5)) throw new Error(); - } - } - } - } - } - - // mine block below feet level - for (var i = 0; i < 4; i++) { - var dx = cardinals4[i][0], dz = cardinals4[i][1]; - - if (canWalkThrough(world.getBlock(x + dx, y, z + dz)) && isWantedBlock(world.getBlock(x + dx, y - 1, z + dz))) { - if (!mineBlock(x + dx, y - 1, z + dz)) - throw new Error(); - if (!canWalkOn(world.getBlock(x + dx, y - 2, z + dz))) - if (!placeBlock(x + dx, y - 2, z + dz)) - continue; - - // collect the block - if (!player.moveTo(x + dx + 0.5, z + dz + 0.5)) throw new Error(); - if (!mineNearbyOre(x + dx, y - 1, z + dz)) throw new Error(); - centerPlayer(); - if (!canWalkThrough(x + dx, y + 1, z + dz)) - if (!mineBlock(x + dx, y + 1, z + dz)) - throw new Error(); - for (var dy = 1; dy >= 0; dy--) { - if (!canWalkThrough(world.getBlock(x, y + dy, z))) - if (!mineBlock(x, y + dy, z)) - throw new Error(); - } - if (!canWalkOn(world.getBlock(x, y - 1, z))) - if (!placeBlock(x, y - 1, z)) throw new Error(); - if (!player.moveTo(x + 0.5, z + 0.5)) throw new Error(); - } - } - - return true; -}; - -var makeTunnel = function(x, y, z, dx, dz) { - centerPlayer(); - - if (!clearWay(x, y, z, dx, dz)) - throw new Error(); - - // walk to next spot - if (!player.moveTo(x + dx + 0.5, z + dz + 0.5, false)) - throw new Error(); - - // place torch - if (world.getBlockLight(x, y, z) <= 1) { - if (!player.pick("torch")) - throw new Error(); - if (!player.rightClick(x, y - 1, z, "up")) - print("Couldn't place torch"); - } - - if (!mineNearbyOre(x + dx, y, z + dz)) throw new Error(); - - return true; -}; - -var makeTunnelLoop = function() { - try { - var x = Math.floor(player.x); - var y = Math.floor(player.y); - var z = Math.floor(player.z); - var dx = 1, dz = 0; - - while (makeTunnel(x, y, z, dx, dz)) { - x += dx; - z += dz; - } - } finally { - mainThread.kill(); - } -}; - -var pickUpItemsLoop = function() { - while (true) { - // find items needed to be picked up - var items = $("@e[type=item,distance=..3]"); - var itemsWanted = []; - for (var i = 0; i < items.length; i++) { - var item = items[i]; - if (Math.abs(item.x - player.x) < 1.425 && Math.abs(item.z - player.z) < 1.425 - && item.y - player.y >= -0.5 && item.y - player.y < 2.3 - player.standingEyeHeight + player.eyeHeight) { - if (isWantedItemEntity(item)) { - var nbt = item.nbt; - var itemId; - if (nbt.Item && itemsWanted.indexOf(itemId = nbt.Item.id) === -1) - itemsWanted.push(itemId); - } - } - } - - // throw out items from inventory if there's no space - var playerItems = player.inventory.items; - var cobblestoneCount = 0; - for (var slot = 0; slot < 36; slot++) { - if (playerItems[slot].Count < 64 && itemsWanted.indexOf(playerItems[slot].id) !== -1) - itemsWanted.splice(itemsWanted.indexOf(playerItems[slot].id), 1); - if (playerItems[slot].id === "minecraft:cobblestone" || playerItems[slot].id === "minecraft:stone") - cobblestoneCount++; - } - for (var slot = 0; slot < 36 && itemsWanted.length > 0; slot++) { - if (playerItems[slot].id === "minecraft:air") - itemsWanted.pop(); - } - for (var slot = 0; slot < 36 && itemsWanted.length > 0; slot++) { - var itemId = playerItems[slot].id; - var canThrow = false; - if ((itemId === "minecraft:cobblestone" || itemId === "minecraft:stone") && cobblestoneCount > 1) { - cobblestoneCount--; - canThrow = true; - } else if (itemId === "minecraft:dirt" || itemId === "minecraft:gravel" - || itemId === "minecraft:granite" || itemId === "minecraft:diorite" - || itemId === "minecraft:andesite") { - canThrow = true; - } - if (canThrow) { - player.inventory.click(slot, {type: 'throw', rightClick: true}); - itemsWanted.pop(); - } - } - - if (itemsWanted.length !== 0) - break; - - tick(); - } - mainThread.kill(); -}; - -var mainThread = Thread.current; - -new Thread(pickUpItemsLoop).run(); -new Thread(makeTunnelLoop).run(); - -while (true) tick(); // keep running until killed diff --git a/docs/example_scripts/build_platform.js b/docs/example_scripts/build_platform.js deleted file mode 100644 index 96d86b2..0000000 --- a/docs/example_scripts/build_platform.js +++ /dev/null @@ -1,258 +0,0 @@ - -var GROUP_NAME = "rsf"; -var PLATFORM_Y = 40; -var TEMPLATE_Y = 20; -var TEMPLATE_Z = -3367; -var PLATFORM_X_MIN = 3227; -var PLATFORM_X_MAX = 3305; -var PLATFORM_Z_MIN = -3442; -var PLATFORM_Z_MAX = -3364; -var STONE_BLOCK = "minecraft:stone"; -var SLAB_BLOCK = "minecraft:smooth_stone_slab"; - -var craftingTable; - -var directionNames = ["north", "east", "south", "west"]; -var dx = [0, 1, 0, -1]; -var dz = [-1, 0, 1, 0]; -var opposite = function(dir) { return (dir + 2) % 4; }; - -var isChestContainer = function(type) { return type === "generic_9x3" || type === "generic_9x6"; }; - -var openContainer = function(x, y, z, type) { - if (typeof(type) === "string") { - var typeName = type; - type = function(it) { return it === typeName }; - } - player.lookAt(x, y, z); - player.syncRotation(); - if (!player.rightClick(x, y, z)) - throw new Error("Could not right click on container at " + x + ", " + y + ", " + z); - var timeout = 0; - while (player.currentContainer === null || !type(player.currentContainer.type)) { - tick(); - timeout++; - if (timeout > 100) - throw new Error("Failed to open container at " + x + ", " + y + ", " + z); - } - anticheatDelay(); -}; - -var anticheatDelay = function() { - for (var i = 0; i < 20; i++) - tick(); -}; - -var anticheatMediumDelay = function() { - for (var i = 0; i < 4; i++) - tick(); -}; - -var anticheatLessDelay = function() { - tick(); -}; - -var findReplenishArea = function() { - var found = false; - var minDistanceSq = 1000000; - for (var xDelta = -7; xDelta <= 7; xDelta++) { - for (var zDelta = -7; zDelta <= 7; zDelta++) { - for (var yDelta = -7; yDelta <= 7; yDelta++) { - var distanceSq = xDelta * xDelta + yDelta * yDelta + zDelta * zDelta; - if (distanceSq >= minDistanceSq) - continue; - var x = player.x + xDelta; - var y = player.y + player.eyeHeight + yDelta; - var z = player.z + zDelta; - if (world.getBlock(x, y, z) === "crafting_table") { - craftingTable = [x, y, z]; - minDistanceSq = distanceSq; - found = true; - } - } - } - } - if (!found) - throw new Error("Could not find replenish area"); - return craftingTable; -}; - -var gatherStone = function(stoneNeeded) { - for (var xDelta = -5; xDelta <= 5; xDelta++) { - for (var zDelta = -5; zDelta <= 5; zDelta++) { - for (var yDelta = -5; yDelta <= 5; yDelta++) { - var x = player.x + xDelta; - var y = player.y + player.eyeHeight + yDelta; - var z = player.z + zDelta; - if (world.getBlock(x, y, z) === "chest" || world.getBlock(x, y, z) === "trapped_chest") { - try { - openContainer(x, y, z, isChestContainer); - var chestItems = player.currentContainer.items; - for (var i = 0; i < chestItems.length; i++) { - if (chestItems[i].id === STONE_BLOCK) { - stoneNeeded -= chestItems[i].Count; - player.currentContainer.click(i, {type: "quick_move"}); - anticheatLessDelay(); - if (stoneNeeded <= 0) - return; - } - } - player.closeContainer(); - anticheatDelay(); - } catch (e) { - if (!(e instanceof Error)) - throw e; - } - } - } - } - } - throw new Error("Not enough stone"); -}; - -var ensureResources = function() { - // Check if we already have the resources - var foundStone = 0, foundSlabs = 0; - var items = player.inventory.items; - for (var slot = 0; slot < 36; slot++) { - if (items[slot].id === STONE_BLOCK) - foundStone += items[slot].Count; - else if (items[slot].id === SLAB_BLOCK) - foundSlabs += items[slot].Count; - } - if (foundStone !== 0 && foundSlabs !== 0) - return; - - var slabsNeeded = Math.max(0, 64 * 10 - foundSlabs); - slabsNeeded = Math.ceil(slabsNeeded / 6) * 6; - var stoneNeeded = 64 * 10 - foundStone; - stoneNeeded += slabsNeeded / 2; - - // Travel near to the replenish area (blocks may not be visible until nearby) - var xDistanceToReplenishArea = replenishArea[0] + 0.5 - player.x; - var zDistanceToReplenishArea = replenishArea[2] + 0.5 - player.z; - var hDistanceToReplenishArea = Math.sqrt(xDistanceToReplenishArea * xDistanceToReplenishArea + zDistanceToReplenishArea * zDistanceToReplenishArea); - var targetX = replenishArea[0] + 0.5 - xDistanceToReplenishArea * 2 / hDistanceToReplenishArea; - var targetZ = replenishArea[2] + 0.5 - zDistanceToReplenishArea * 2 / hDistanceToReplenishArea; - - if (!player.pathTo(targetX, player.y, targetZ)) - throw new Error("Could not move to replenish area"); - - // Re-find the replenish area in case it has moved - findReplenishArea(); - - if (stoneNeeded > 0) { - gatherStone(stoneNeeded); - } - - // Craft slabs - if (slabsNeeded > 0) { - openContainer(craftingTable[0], craftingTable[1], craftingTable[2], "crafting"); - var recipeCount = slabsNeeded / 6; - while (recipeCount > 0) { - for (var slot = 1; slot <= 3; slot++) { - var itemsNeeded = Math.min(64, recipeCount); - items = player.inventory.items; - for (var i = 0; i < 36; i++) { - if (items[i].id === STONE_BLOCK) { - var count = items[i].Count; - player.inventory.click(i); // pickup the stone - anticheatMediumDelay(); - if (count <= itemsNeeded || itemsNeeded === 64) { - // drop down all the stone - itemsNeeded -= count; - player.currentContainer.click(slot); - anticheatMediumDelay(); - } else { - // drop down as many stone as needed then put the rest back - for (var j = 0; j < itemsNeeded; j++) { - player.currentContainer.click(slot, {rightClick: true}); - anticheatMediumDelay(); - } - player.inventory.click(i); - anticheatMediumDelay(); - itemsNeeded = 0; - } - if (itemsNeeded <= 0) - break; - } - } - } - - var timeout = 0; - while (player.currentContainer.items[0].id !== SLAB_BLOCK) { - tick(); - timeout++; - if (timeout > 100) - throw new Error("Failed to craft slabs"); - } - - player.currentContainer.click(0, {type: "quick_move"}); - anticheatMediumDelay(); - - recipeCount -= 64; - } - player.closeContainer(); - anticheatDelay(); - } - - if (foundStone === 0) { - if (!player.pick(STONE_BLOCK)) - throw new Error("Someone is tampering with the bot"); - anticheatDelay(); - chat("/ctf " + GROUP_NAME); - } -}; - -var placePlatform = function() { - for (var x = PLATFORM_X_MAX; x >= PLATFORM_X_MIN; x--) { - var countDown = x % 2 === PLATFORM_X_MAX % 2; - var standingX = x; - if (!countDown) - standingX--; - for (var z = countDown ? PLATFORM_Z_MAX : PLATFORM_Z_MIN; countDown ? z >= PLATFORM_Z_MIN : z <= PLATFORM_Z_MAX; z += countDown ? -1 : 1) { - ensureResources(); - if (world.getBlock(x, PLATFORM_Y, z).endsWith("_slab")) - continue; - if (!world.getBlockState(x, TEMPLATE_Y, z).solid || world.getBlock(x, TEMPLATE_Y, z).endsWith("sign")) - continue; - if (!player.pathTo(standingX + 0.5, player.y, z + 0.5)) - throw new Error("Movement to " + standingX + ", " + z + " failed"); - player.pick(SLAB_BLOCK); - var placementSide = -1; - for (var dir = 0; dir < 4; dir++) { - if (world.getBlockState(x + dx[dir], PLATFORM_Y, z + dz[dir]).solid) { - placementSide = dir; - break; - } - } - if (placementSide === -1) - throw new Error("Nothing to place the slab against at " + x + ", " + z); - var closestPoint = world.getClosestVisiblePoint(x + dx[placementSide], PLATFORM_Y, z + dz[placementSide], directionNames[opposite(dir)]); - if (!closestPoint) { - if (!player.moveTo(standingX + 0.5, z + 0.5)) - throw new Error("Movement to " + standingX + ", " + z + " failed"); - closestPoint = world.getClosestVisiblePoint(x + dx[placementSide], PLATFORM_Y, z + dz[placementSide], directionNames[opposite(dir)]); - if (!closestPoint) - throw new Error("Slab not in view"); - } - var clickX = closestPoint.x; - var clickY = closestPoint.y; - var clickZ = closestPoint.z; - if (clickY - Math.floor(clickY) < 0.6) - clickY += 0.1; - anticheatMediumDelay(); - player.lookAt(clickX, clickY, clickZ); - anticheatMediumDelay(); - player.rightClick(x + dx[placementSide], PLATFORM_Y, z + dz[placementSide], directionNames[opposite(dir)]); - } - } -}; - -replenishArea = findReplenishArea(); -chat("/cto"); -if (player.pick(STONE_BLOCK)) { - anticheatDelay(); - chat("/ctf " + GROUP_NAME); -} -placePlatform(); diff --git a/docs/src/snapToGrid.ts b/docs/src/snapToGrid.ts new file mode 100644 index 0000000..c672606 --- /dev/null +++ b/docs/src/snapToGrid.ts @@ -0,0 +1,12 @@ +import { cardinalRelative, getCurrentHeading } from './util'; + +const heading = getCurrentHeading(); + +cc.player.lookAt( + cc.player.x + cardinalRelative[heading].x, + cc.player.y + cc.player.eyeHeight, + cc.player.z + cardinalRelative[heading].z +); + +cc.print(`Facing ${heading}`); +cc.print(cc.player.eyeHeight.toString()); diff --git a/docs/src/util.ts b/docs/src/util.ts new file mode 100644 index 0000000..2805239 --- /dev/null +++ b/docs/src/util.ts @@ -0,0 +1,82 @@ +// directions +export type cardinalDirections = 'east' | 'west' | 'south' | 'north'; +export const cardinalList: cardinalDirections[] = [ + 'south', + 'west', + 'north', + 'east', +]; +export const cardinalRelative: Record< + cardinalDirections, + { x: number; z: number } +> = { + south: { x: 0, z: 1 }, + west: { x: -1, z: 0 }, + north: { x: 0, z: -1 }, + east: { x: 1, z: 0 }, +}; + +// non-solid blocks +const airBlocks = ['air', 'cave_air', 'void_air']; +const water = ['water', 'flowing_water']; + +const saplings = [ + 'oak_sapling', + 'spruce_sapling', + 'birch_sapling', + 'jungle_sapling', + 'acacia_sapling', + 'dark_oak_sapling', +]; +const fungus = [ + 'brown_mushroom', + 'red_mushroom', + 'crimson_fungus', + 'warped_fungus', +]; + +const vines = [ + 'vine', + 'twisting_vines', + 'twisting_vines_plant', + 'weeping_vines', + 'weeping_vines_plant', + 'cave_vines', + 'cave_vines_plant', +]; + +const otherPlant = ['moss_carpet', 'grass', 'fern', 'tall_grass', 'large_fern']; + +const plants = [...saplings, ...fungus, ...vines, ...otherPlant]; + +const torch = ['torch', 'soul_torch', 'wall_torch', 'soul_wall_torch']; + +const rail = ['rail', 'detector_rail', 'activator_rail', 'powered_rail']; + +export const safeNonSolidBlocks: string[] = [ + ...airBlocks, + ...water, + ...plants, + ...torch, + ...rail, +]; + +// functions + +export const getCurrentHeading = (): cardinalDirections => + cardinalList[(Math.floor((cc.player.yaw + 45) / 90) + 4) % 4]; + +export const centerOnCurrentBlock = () => { + cc.player.snapTo( + Math.floor(cc.player.x) + 0.5, + cc.player.y, + Math.floor(cc.player.z) + 0.5 + ); +}; + +export const getBlockBelowFeet = (): string => + cc.world.getBlock( + Math.floor(cc.player.x), + Math.floor(cc.player.y) - 1, + Math.floor(cc.player.z) + ); diff --git a/docs/tsconfig.json b/docs/tsconfig.json new file mode 100644 index 0000000..3212a1b --- /dev/null +++ b/docs/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "ES2015" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + "removeComments": false /* Disable emitting comments. */, + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} From 278c6e44b65cbb2353796ff743f7eddb249e7477 Mon Sep 17 00:00:00 2001 From: Brian <5673408+illumincrotty@users.noreply.github.com> Date: Thu, 27 Jan 2022 18:59:24 -0600 Subject: [PATCH 4/5] Improve comments --- docs/src/clientCommands.d.ts | 2 +- docs/src/snapToGrid.ts | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/src/clientCommands.d.ts b/docs/src/clientCommands.d.ts index ea1b264..bc1d137 100644 --- a/docs/src/clientCommands.d.ts +++ b/docs/src/clientCommands.d.ts @@ -18,7 +18,7 @@ declare namespace cc { function $(command: string): number | Array; /** - * Prints a string to client-side chat + * Prints a string to client-side chat (not to the server) * @param x The string to print */ function print(x: string): void; diff --git a/docs/src/snapToGrid.ts b/docs/src/snapToGrid.ts index c672606..8370224 100644 --- a/docs/src/snapToGrid.ts +++ b/docs/src/snapToGrid.ts @@ -1,12 +1,19 @@ import { cardinalRelative, getCurrentHeading } from './util'; +// the the current cardinal direction const heading = getCurrentHeading(); +// look at the block in front of you in that direction cc.player.lookAt( cc.player.x + cardinalRelative[heading].x, cc.player.y + cc.player.eyeHeight, cc.player.z + cardinalRelative[heading].z ); +// Print the direction your player is now facing to the client cc.print(`Facing ${heading}`); -cc.print(cc.player.eyeHeight.toString()); + +/** + * To try this function out, move the files from the build folder into .minecraft/config/jsMacro/Macros + * then you can run it (no reload needed) with /cscript + */ From 5f5303d39a3e51287fd95088f020a9bbecc577be Mon Sep 17 00:00:00 2001 From: Brian <5673408+illumincrotty@users.noreply.github.com> Date: Thu, 27 Jan 2022 19:04:28 -0600 Subject: [PATCH 5/5] Add comments --- docs/src/util.ts | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/docs/src/util.ts b/docs/src/util.ts index 2805239..5bed5c7 100644 --- a/docs/src/util.ts +++ b/docs/src/util.ts @@ -1,11 +1,19 @@ // directions +/** + * The cardinal directions + */ export type cardinalDirections = 'east' | 'west' | 'south' | 'north'; + +/** The cardinal directions by their order in game 0 is south and it increases clockwise (it also decreases counter-clockwise) */ export const cardinalList: cardinalDirections[] = [ 'south', 'west', 'north', 'east', ]; +/** + * Map of the cardinal directions to their unit coordinates + */ export const cardinalRelative: Record< cardinalDirections, { x: number; z: number } @@ -17,7 +25,7 @@ export const cardinalRelative: Record< }; // non-solid blocks -const airBlocks = ['air', 'cave_air', 'void_air']; +const air = ['air', 'cave_air', 'void_air']; const water = ['water', 'flowing_water']; const saplings = [ @@ -53,8 +61,11 @@ const torch = ['torch', 'soul_torch', 'wall_torch', 'soul_wall_torch']; const rail = ['rail', 'detector_rail', 'activator_rail', 'powered_rail']; +/** + * blocks that are safe for the player to pass through (not exhaustive, just some common ones) + */ export const safeNonSolidBlocks: string[] = [ - ...airBlocks, + ...air, ...water, ...plants, ...torch, @@ -63,9 +74,15 @@ export const safeNonSolidBlocks: string[] = [ // functions +/** + * @returns the user's current heading + */ export const getCurrentHeading = (): cardinalDirections => cardinalList[(Math.floor((cc.player.yaw + 45) / 90) + 4) % 4]; +/** + * Centers the user on the block they're currently mostly standing on + */ export const centerOnCurrentBlock = () => { cc.player.snapTo( Math.floor(cc.player.x) + 0.5, @@ -74,6 +91,9 @@ export const centerOnCurrentBlock = () => { ); }; +/** + * @returns the current block below the players feet + */ export const getBlockBelowFeet = (): string => cc.world.getBlock( Math.floor(cc.player.x),