init
9
.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
./node_modules
|
||||
./build
|
||||
|
||||
|
||||
node_modules
|
||||
build
|
||||
export
|
||||
.git
|
||||
|
||||
5
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
12
.idea/Reeks2Missie6.iml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
57
.idea/codeStyles/Project.xml
generated
Normal file
@@ -0,0 +1,57 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<HTMLCodeStyleSettings>
|
||||
<option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
|
||||
</HTMLCodeStyleSettings>
|
||||
<JSCodeStyleSettings version="0">
|
||||
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
||||
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
||||
<option name="FORCE_QUOTE_STYlE" value="true" />
|
||||
<option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
|
||||
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||
</JSCodeStyleSettings>
|
||||
<TypeScriptCodeStyleSettings version="0">
|
||||
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
||||
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
||||
<option name="FORCE_QUOTE_STYlE" value="true" />
|
||||
<option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
|
||||
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||
</TypeScriptCodeStyleSettings>
|
||||
<VueCodeStyleSettings>
|
||||
<option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" />
|
||||
<option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" />
|
||||
</VueCodeStyleSettings>
|
||||
<codeStyleSettings language="HTML">
|
||||
<option name="SOFT_MARGINS" value="120" />
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="JavaScript">
|
||||
<option name="SOFT_MARGINS" value="120" />
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="TypeScript">
|
||||
<option name="SOFT_MARGINS" value="120" />
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="Vue">
|
||||
<option name="SOFT_MARGINS" value="120" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
||||
4
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/Reeks2Missie6.iml" filepath="$PROJECT_DIR$/.idea/Reeks2Missie6.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
10
.prettierrc.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 2,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"tabs": false,
|
||||
"backetSpacing": true,
|
||||
"arrowParens": "always",
|
||||
"printWidth": 120
|
||||
}
|
||||
7
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"esbenp.prettier-vscode",
|
||||
"blockceptionltd.blockceptionvscodeminecraftbedrockdevelopmentextension",
|
||||
"mojang-studios.minecraft-debugger"
|
||||
]
|
||||
}
|
||||
16
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"version": "0.3.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "minecraft-js",
|
||||
"request": "attach",
|
||||
"name": "Debug with Minecraft",
|
||||
"mode": "listen",
|
||||
"preLaunchTask": "build",
|
||||
"targetModuleUuid": "868bf88f-78d9-4109-b1b2-308645e367bd",
|
||||
"sourceMapRoot": "${workspaceFolder}/build/_Reeks2Missie6Debug",
|
||||
"generatedSourceRoot": "${workspaceFolder}/build/behavior_packs/scripts",
|
||||
"port": 19144
|
||||
}
|
||||
]
|
||||
}
|
||||
39
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"git.ignoreLimitWarning": true,
|
||||
"editor.formatOnSave": true,
|
||||
"search.exclude": {
|
||||
"**/.git": true,
|
||||
"**/node_modules": true,
|
||||
"**/build": true
|
||||
},
|
||||
"files.exclude": {
|
||||
"**/.DS_Store": true,
|
||||
"**/.git": true,
|
||||
"**/build": false,
|
||||
"**/node_modules": true
|
||||
},
|
||||
"cSpell.words": ["gametest", "gametests", "minecart", "shulker", "zoglin"],
|
||||
"editor.tabSize": 2,
|
||||
"workbench.colorCustomizations": {
|
||||
"activityBar.background": "#243b1e",
|
||||
"titleBar.activeBackground": "#1f3d21",
|
||||
"titleBar.activeForeground": "#F5FCEB"
|
||||
},
|
||||
|
||||
"emeraldwalk.runonsave": {
|
||||
"commands": [{ "cmd": "gulp", "isAsync": true, "match": "\\.ts$" }]
|
||||
},
|
||||
"BC-MC.Education.Enable": true
|
||||
}
|
||||
12
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"dependsOrder": "sequence",
|
||||
"dependsOn": [
|
||||
"gulp: default"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
50
README.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Codefever Typescript level framework
|
||||
|
||||
This is the readme for the typescript framework for minecraft education
|
||||
|
||||
# Terminology
|
||||
|
||||
## Puppeteer
|
||||
|
||||
Puppeteer is a class that handles all the UI code for displaying messages to the player. It also handles translations. see [Translations](#translations)
|
||||
|
||||
## MindKeeper
|
||||
|
||||
This is the system that handles all the world storage, supported types are `boolean`, `number`, `string`
|
||||
|
||||
> **Important** : all registering of the world variables must be done in the world.afterEvents.worldInitialize event (this event can't send anything to the world (like messages))
|
||||
>
|
||||
> Here is a example of a definition of the world variable foo
|
||||
|
||||
```typescript
|
||||
world.afterEvents.worldInitialize.subscribe(({ propertyRegistry }) => {
|
||||
mindKeeper.registerStore("foo", StoreType.string);
|
||||
|
||||
mindKeeper.registerToWorld(propertyRegistry);
|
||||
});
|
||||
```
|
||||
|
||||
## Level (could be abit convoluted) **WIP**
|
||||
|
||||
This defines a level in a world, it has 3 callback functions as parameters. These functions should
|
||||
|
||||
- define the setup logic
|
||||
- define the update (loop) logic (Used for actionbar mainly)
|
||||
- define the condition to pass the level
|
||||
- define the code to be run when the level is completed
|
||||
|
||||
> There is a a AbstractCondition class included with a BlockCondition. This (convoluted) way you can define a BlockCondition in the function that checks if the level is complete.
|
||||
|
||||
## Translations
|
||||
|
||||
Translations work with a resource pack. It's the same as with regular resource packs. The way it works with Pupeteer is to set a message to the screen but add the "%" prefix to the key.
|
||||
So `pupeteer.setActionbar("%foo.bar)` will look for the key `foo.bar` in the resource pack and display that message.
|
||||
|
||||
# Random knowlege
|
||||
|
||||
bunch of helper scripts for this [here](https://github.com/JaylyDev/ScriptAPI)
|
||||
This could be handy [jaylydb](https://github.com/JaylyDev/ScriptAPI/tree/stable/scripts/jaylydb)
|
||||
|
||||
# Authors
|
||||
|
||||
- [Bram Verhulst](https://github.com/brammie15) :p
|
||||
63
Setup.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Setup
|
||||
|
||||
## Prerequisites
|
||||
|
||||
**Install Node.js tools, if you haven't already**
|
||||
|
||||
We're going to use the package manager [npm](https://www.npmjs.com/package/npm) to get more tools to make the process of building our project easier.
|
||||
|
||||
Visit [https://nodejs.org/](https://nodejs.org).
|
||||
|
||||
Download the version with "LTS" next to the number and install it. (LTS stands for Long Term Support, if you're curious.) In the Node.js Windows installer, accept the installation defaults. You do not need to install any additional tools for Native compilation.
|
||||
|
||||
**Install Visual Studio Code, if you haven't already**
|
||||
|
||||
Visit the [Visual Studio Code website](https://code.visualstudio.com) and install Visual Studio Code.
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Use npm to install our tools:
|
||||
|
||||
```powershell
|
||||
npm i
|
||||
```
|
||||
|
||||
1. When that's done, enter:
|
||||
|
||||
```powershell
|
||||
npm i gulp-cli --global
|
||||
```
|
||||
|
||||
It might also ask you to install the Minecraft Debugger and Blockception's Visual Studio Code plugin, which are plugins to Visual Studio Code that can help with Minecraft development. Go ahead and do that, if you haven't already.
|
||||
|
||||
# Running
|
||||
|
||||
To actually run the project, you must run `gulp` or `gulp watch` in the terminal.
|
||||
|
||||
# Gulpfile
|
||||
|
||||
At the top of the gulpfile there is a field for the name of the folder/project
|
||||
|
||||
# Manifest
|
||||
|
||||
In the behavior_packs folder change the name of the folder in that to match the name in the gulpfile.
|
||||
|
||||
In the same folder change the manifest.json to match your needs.
|
||||
|
||||
> `note`: this whole folder will be copied to the development_behavior_packs folder located at `%appdata%\Minecraft Education Edition\games\com.mojang\development_behavior_packs`
|
||||
|
||||
and if there is a resource_packs folder it will also be copied to the corresponding folder.
|
||||
|
||||
# World settings
|
||||
|
||||
Because education chose to be anoying (huge shock i know) you have to enable the js api manually through editing the world settings with nbt.
|
||||
|
||||
see a guide [here](https://wiki.bedrock.dev/nbt/experimental-education-edition.html)
|
||||
|
||||
# Debugging
|
||||
|
||||
To enable the conent log you have to enable the content log in the education settings.
|
||||
Open `%appdata%\Minecraft Education Edition\games\com.mojang\minecraftpe\options.txt` and change `content_log_file` and `content_log_gui` to `1`.
|
||||
Than ingame you can CTRL+H to open the content log.
|
||||
|
||||
> Note: it would be advised to change the keyboard settings because H defaults to show the tutorial witch can be anoying.
|
||||
20
behavior_packs/blocks/cracked_glass.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"format_version": "1.20.13",
|
||||
"minecraft:block": {
|
||||
"description": {
|
||||
"identifier": "cc:cracked_glass",
|
||||
"menu_category": {
|
||||
"category": "construction",
|
||||
"is_hidden_in_commands": false
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:light_dampening": 0,
|
||||
"minecraft:material_instances": {
|
||||
"*": {
|
||||
"render_method": "blend"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
behavior_packs/cameras/presets/camera.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"format_version": "1.19.50",
|
||||
"minecraft:camera_preset": {
|
||||
"identifier": "example:custom",
|
||||
"inherit_from": "minecraft:free",
|
||||
"pos_x": 30,
|
||||
"pos_y": 90,
|
||||
"pos_z": -20,
|
||||
"rot_x": 10,
|
||||
"rot_y": 40
|
||||
}
|
||||
}
|
||||
0
behavior_packs/dialogue/scene.json
Normal file
62
behavior_packs/entities/floating_text.json
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"minecraft:entity": {
|
||||
"description": {
|
||||
"identifier": "cc:floating_text",
|
||||
"is_spawnable": true,
|
||||
"is_summonable": true,
|
||||
"is_experimental": false
|
||||
},
|
||||
"components": {
|
||||
"minecraft:type_family": {
|
||||
"family": ["floatingtext"]
|
||||
},
|
||||
"minecraft:health": {
|
||||
"value": 999999999,
|
||||
"max": 999999999
|
||||
},
|
||||
"minecraft:collision_box": {
|
||||
"width": 0.6,
|
||||
"height": 1.8
|
||||
},
|
||||
"minecraft:nameable": {
|
||||
"alwaysShow": true,
|
||||
"allowNameTagRenaming": true
|
||||
},
|
||||
"minecraft:fire_immune": true,
|
||||
"minecraft:scale": {
|
||||
"value": 0
|
||||
},
|
||||
"minecraft:knockback_resistance": {
|
||||
"value": 1
|
||||
},
|
||||
"minecraft:physics": {
|
||||
"has_gravity": false
|
||||
},
|
||||
"minecraft:pushable": {
|
||||
"is_pushable": false
|
||||
},
|
||||
"minecraft:damage_sensor": {
|
||||
"triggers": {
|
||||
"cause": "all",
|
||||
"deals_damage": false,
|
||||
"on_damage": {
|
||||
"event": "left_click"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"component_groups": {},
|
||||
"events": {
|
||||
"left_click": {
|
||||
"run_command": {
|
||||
"target": "self",
|
||||
"command": [
|
||||
"tag @s add edit",
|
||||
"execute @s[tag=edit] ~ ~ ~ execute @e[tag=floating] ~ ~ ~ function floating_text_function/menu_edit_multi/edit"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
behavior_packs/functions/summon.mcfunction
Normal file
@@ -0,0 +1,3 @@
|
||||
summon cc:floating_text ~ ~ ~ "§f[§aUse Name Tag§f]"
|
||||
playsound lodestone_compass.link_compass_to_lodestone @s ~ ~ ~
|
||||
titleraw @s actionbar {"rawtext":[{"text":"§l§7[§6Floating §bText§7]§r §a\n§2Floating text spawned template"}]}
|
||||
33
behavior_packs/manifest.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"format_version": 2,
|
||||
"metadata": {
|
||||
"authors": ["Me and my cat"]
|
||||
},
|
||||
"header": {
|
||||
"name": "Reeks2Missie9BP",
|
||||
"description": "De behavior pack voor Reeks 2 Missie 9",
|
||||
"uuid": "2d4894af-d185-4b31-8ec8-265d585ee3fb",
|
||||
"version": [1, 0, 0],
|
||||
"min_engine_version": [1, 20, 0]
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"description": "Script resources",
|
||||
"language": "javascript",
|
||||
"type": "script",
|
||||
"uuid": "9d9d8955-50eb-4093-84af-2012ec37f049",
|
||||
"version": [1, 0, 1],
|
||||
"entry": "scripts/main.js"
|
||||
}
|
||||
],
|
||||
"dependencies": [
|
||||
{
|
||||
"module_name": "@minecraft/server",
|
||||
"version": "1.12.0-beta"
|
||||
},
|
||||
{
|
||||
"uuid": "0b55c95c-33d9-4cef-8040-3607704aa2a2",
|
||||
"version": [1, 0, 0]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
behavior_packs/pack_icon.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
564
gulpfile.js
Normal file
@@ -0,0 +1,564 @@
|
||||
// === CONFIGURABLE VARIABLES
|
||||
|
||||
const bpfoldername = "Reeks2Missie9";
|
||||
const isStoreVersion = true;
|
||||
|
||||
const resource_pack_name = "Reeks2Missie9RP";
|
||||
const resource_pack_description = "De resource pack voor Reeks 2 Missie 9";
|
||||
const resource_pack_authors = ["Me and my cat"];
|
||||
|
||||
const behavior_pack_name = "Reeks2Missie6BP";
|
||||
const behavior_pack_description = "De behavior pack voor Reeks 2 Missie 9";
|
||||
const behavior_pack_authors = ["Me and my cat"];
|
||||
|
||||
// === Optional variables
|
||||
|
||||
const exportWorldFolderPath = "";
|
||||
|
||||
// === END CONFIGURABLE VARIABLES
|
||||
|
||||
const gulp = require("gulp");
|
||||
const ts = require("gulp-typescript");
|
||||
const del = require("del");
|
||||
const os = require("os");
|
||||
const spawn = require("child_process").spawn;
|
||||
const sourcemaps = require("gulp-sourcemaps");
|
||||
const zip = require("gulp-zip");
|
||||
const fs = require("fs");
|
||||
const rename = require("gulp-rename");
|
||||
const crypto = require("crypto");
|
||||
|
||||
var readLineSync = import("readline-sync");
|
||||
var NBT = import("nbtify");
|
||||
|
||||
const worldsFolderName = "minecraftWorlds";
|
||||
|
||||
const regularVersionMojangRoot = os.homedir() + "/appdata/Roaming/Minecraft Education Edition/games/com.mojang/";
|
||||
const storeVersionMojangRoot =
|
||||
os.homedir() +
|
||||
"/AppData/Local/Packages/Microsoft.MinecraftEducationEdition_8wekyb3d8bbwe/LocalState/games/com.mojang/";
|
||||
|
||||
const mcdir = isStoreVersion ? storeVersionMojangRoot : regularVersionMojangRoot;
|
||||
|
||||
function clean_build(callbackFunction) {
|
||||
del(["build/behavior_packs/", "build/resource_packs/"]).then(
|
||||
(value) => {
|
||||
callbackFunction(); // success
|
||||
},
|
||||
(reason) => {
|
||||
callbackFunction(); // error
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function clean_export(cb) {
|
||||
del(["export/**/**"]).then(
|
||||
(value) => {
|
||||
cb(); // success
|
||||
},
|
||||
(reason) => {
|
||||
cb(); // error
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function copy_behavior_packs() {
|
||||
return gulp.src(["behavior_packs/**/*"]).pipe(gulp.dest("build/behavior_packs"));
|
||||
}
|
||||
|
||||
function copy_resource_packs() {
|
||||
return gulp.src(["resource_packs/**/*"]).pipe(gulp.dest("build/resource_packs"));
|
||||
}
|
||||
|
||||
const copy_content = gulp.parallel(copy_behavior_packs, copy_resource_packs);
|
||||
|
||||
function compile_scripts() {
|
||||
return gulp
|
||||
.src("scripts/**/*.ts")
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(
|
||||
ts({
|
||||
module: "es2020",
|
||||
moduleResolution: "node",
|
||||
lib: ["es2020", "dom"],
|
||||
strict: true,
|
||||
target: "es2020",
|
||||
noImplicitAny: true,
|
||||
})
|
||||
)
|
||||
.pipe(
|
||||
sourcemaps.write("../../_" + bpfoldername + "Debug", {
|
||||
destPath: bpfoldername + "/scripts/",
|
||||
sourceRoot: "./../../../scripts/",
|
||||
})
|
||||
)
|
||||
.pipe(gulp.dest("build/behavior_packs/scripts"));
|
||||
}
|
||||
|
||||
const build = gulp.series(clean_build, copy_content, compile_scripts);
|
||||
|
||||
function clean_localmc(callbackFunction) {
|
||||
if (!bpfoldername || !bpfoldername.length || bpfoldername.length < 2) {
|
||||
console.log("No bpfoldername specified.");
|
||||
callbackFunction();
|
||||
return;
|
||||
}
|
||||
|
||||
del([mcdir + "development_behavior_packs/" + bpfoldername, mcdir + "development_resource_packs/" + bpfoldername], {
|
||||
force: true,
|
||||
}).then(
|
||||
(value) => {
|
||||
callbackFunction(); // Success
|
||||
},
|
||||
(reason) => {
|
||||
callbackFunction(); // Error
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function deploy_localmc_behavior_packs() {
|
||||
console.log("Deploying to '" + mcdir + "development_behavior_packs/" + bpfoldername + "'");
|
||||
return gulp.src(["build/behavior_packs/**/*"]).pipe(gulp.dest(mcdir + "development_behavior_packs/" + bpfoldername));
|
||||
}
|
||||
|
||||
function deploy_localmc_resource_packs() {
|
||||
console.log("Deploying to '" + mcdir + "development_resource_packs/" + bpfoldername + "'");
|
||||
|
||||
return gulp.src(["build/resource_packs/**/*"]).pipe(gulp.dest(mcdir + "development_resource_packs/" + bpfoldername));
|
||||
}
|
||||
|
||||
function getTargetWorldPath() {
|
||||
return mcdir + worldsFolderName + "/" + activeWorldFolderName;
|
||||
}
|
||||
|
||||
function getTargetConfigPath() {
|
||||
return mcdir + "config";
|
||||
}
|
||||
|
||||
function getTargetWorldBackupPath() {
|
||||
return "backups/worlds/" + activeWorldFolderName;
|
||||
}
|
||||
|
||||
function getDevConfigPath() {
|
||||
return "config";
|
||||
}
|
||||
|
||||
function getDevWorldPath() {
|
||||
return "worlds/default";
|
||||
}
|
||||
|
||||
function getDevWorldBackupPath() {
|
||||
return "backups/worlds/devdefault";
|
||||
}
|
||||
|
||||
function clean_localmc_world(callbackFunction) {
|
||||
console.log("Removing '" + getTargetWorldPath() + "'");
|
||||
|
||||
del([getTargetWorldPath()], {
|
||||
force: true,
|
||||
}).then(
|
||||
(value) => {
|
||||
callbackFunction(); // Success
|
||||
},
|
||||
(reason) => {
|
||||
callbackFunction(); // Error
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function clean_localmc_config(callbackFunction) {
|
||||
console.log("Removing '" + getTargetConfigPath() + "'");
|
||||
|
||||
del([getTargetConfigPath()], {
|
||||
force: true,
|
||||
}).then(
|
||||
(value) => {
|
||||
callbackFunction(); // Success
|
||||
},
|
||||
(reason) => {
|
||||
callbackFunction(); // Error
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function clean_dev_world(callbackFunction) {
|
||||
console.log("Removing '" + getDevWorldPath() + "'");
|
||||
|
||||
del([getDevWorldPath()], {
|
||||
force: true,
|
||||
}).then(
|
||||
(value) => {
|
||||
callbackFunction(); // Success
|
||||
},
|
||||
(reason) => {
|
||||
callbackFunction(); // Error
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function clean_localmc_world_backup(callbackFunction) {
|
||||
console.log("Removing backup'" + getTargetWorldBackupPath() + "'");
|
||||
|
||||
del([getTargetWorldBackupPath()], {
|
||||
force: true,
|
||||
}).then(
|
||||
(value) => {
|
||||
callbackFunction(); // Success
|
||||
},
|
||||
(reason) => {
|
||||
callbackFunction(); // Error
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function clean_dev_world_backup(callbackFunction) {
|
||||
console.log("Removing backup'" + getDevWorldBackupPath() + "'");
|
||||
|
||||
del([getTargetWorldBackupPath()], {
|
||||
force: true,
|
||||
}).then(
|
||||
(value) => {
|
||||
callbackFunction(); // Success
|
||||
},
|
||||
(reason) => {
|
||||
callbackFunction(); // Error
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function backup_dev_world() {
|
||||
console.log("Copying world '" + getDevWorldPath() + "' to '" + getDevWorldBackupPath() + "'");
|
||||
return gulp
|
||||
.src([getTargetWorldPath() + "/**/*"])
|
||||
.pipe(gulp.dest(getDevWorldBackupPath() + "/worlds/" + activeWorldFolderName));
|
||||
}
|
||||
|
||||
function deploy_localmc_config() {
|
||||
console.log("Copying world 'config/' to '" + getTargetConfigPath() + "'");
|
||||
return gulp.src([getDevConfigPath() + "/**/*"]).pipe(gulp.dest(getTargetConfigPath()));
|
||||
}
|
||||
|
||||
function deploy_localmc_world() {
|
||||
console.log("Copying world 'worlds/default/' to '" + getTargetWorldPath() + "'");
|
||||
return gulp.src([getDevWorldPath() + "/**/*"]).pipe(gulp.dest(getTargetWorldPath()));
|
||||
}
|
||||
|
||||
function ingest_localmc_world() {
|
||||
console.log("Ingesting world '" + getTargetWorldPath() + "' to '" + getDevWorldPath() + "'");
|
||||
return gulp.src([getTargetWorldPath() + "/**/*"]).pipe(gulp.dest(getDevWorldPath()));
|
||||
}
|
||||
|
||||
function backup_localmc_world() {
|
||||
console.log("Copying world '" + getTargetWorldPath() + "' to '" + getTargetWorldBackupPath() + "/'");
|
||||
return gulp
|
||||
.src([getTargetWorldPath() + "/**/*"])
|
||||
.pipe(gulp.dest(getTargetWorldBackupPath() + "/" + activeWorldFolderName));
|
||||
}
|
||||
|
||||
const deploy_localmc = gulp.series(
|
||||
clean_localmc,
|
||||
function (callbackFunction) {
|
||||
callbackFunction();
|
||||
},
|
||||
gulp.parallel(deploy_localmc_behavior_packs, deploy_localmc_resource_packs)
|
||||
);
|
||||
|
||||
function watch() {
|
||||
return gulp.watch(
|
||||
["scripts/**/*.ts", "behavior_packs/**/*", "resource_packs/**/*"],
|
||||
gulp.series(build, deploy_localmc)
|
||||
);
|
||||
}
|
||||
|
||||
function serve() {
|
||||
return gulp.watch(
|
||||
["scripts/**/*.ts", "behavior_packs/**/*", "resource_packs/**/*"],
|
||||
gulp.series(stopServer, build, deploy_localmc, startServer)
|
||||
);
|
||||
}
|
||||
|
||||
let activeServer = null;
|
||||
|
||||
function stopServer(callbackFunction) {
|
||||
if (activeServer) {
|
||||
activeServer.stdin.write("stop\n");
|
||||
activeServer = null;
|
||||
}
|
||||
|
||||
callbackFunction();
|
||||
}
|
||||
|
||||
function startServer(callbackFunction) {
|
||||
if (activeServer) {
|
||||
activeServer.stdin.write("stop\n");
|
||||
activeServer = null;
|
||||
}
|
||||
|
||||
activeServer = spawn(dedicatedServerPath + "bedrock_server");
|
||||
|
||||
let logBuffer = "";
|
||||
|
||||
let serverLogger = function (buffer) {
|
||||
let incomingBuffer = buffer.toString();
|
||||
|
||||
if (incomingBuffer.endsWith("\n")) {
|
||||
(logBuffer + incomingBuffer).split(/\n/).forEach(function (message) {
|
||||
if (message) {
|
||||
if (message.indexOf("Server started.") >= 0) {
|
||||
activeServer.stdin.write("script debugger listen 19144\n");
|
||||
}
|
||||
console.log("Server: " + message);
|
||||
}
|
||||
});
|
||||
logBuffer = "";
|
||||
} else {
|
||||
logBuffer += incomingBuffer;
|
||||
}
|
||||
};
|
||||
|
||||
activeServer.stdout.on("data", serverLogger);
|
||||
activeServer.stderr.on("data", serverLogger);
|
||||
|
||||
callbackFunction();
|
||||
}
|
||||
|
||||
hasZipped = false;
|
||||
|
||||
function rename_zip_to_mcworld(cb) {
|
||||
gulp
|
||||
.src(["export/export.zip"])
|
||||
.pipe(rename(bpfoldername + ".mcworld"))
|
||||
.pipe(gulp.dest("export/"));
|
||||
cb();
|
||||
}
|
||||
|
||||
function zip_world(cb) {
|
||||
let zip_path = "export/export.zip";
|
||||
console.log("export/" + bpfoldername + "/**/**");
|
||||
return gulp
|
||||
.src(["export/" + bpfoldername + "/**/**"], { base: "export/" + bpfoldername + "/" })
|
||||
.pipe(zip("export.zip", { compress: false, buffer: false }))
|
||||
.pipe(gulp.dest("export/"));
|
||||
}
|
||||
|
||||
function get_version() {
|
||||
let currentTimeStamp = new Date().toISOString().replace(/T/, " ").replace(/\..+/, "");
|
||||
return currentTimeStamp;
|
||||
}
|
||||
|
||||
function add_version_to_world_name(cb) {
|
||||
let worldNameFilePath = "export/" + bpfoldername + "/levelname.txt";
|
||||
let worldName = fs.readFileSync(worldNameFilePath, "utf8");
|
||||
currentTimeStamp = get_version();
|
||||
worldName = worldName + " " + currentTimeStamp;
|
||||
fs.writeFileSync(worldNameFilePath, worldName);
|
||||
console.log("Written " + worldName + " to " + worldNameFilePath);
|
||||
cb();
|
||||
}
|
||||
|
||||
function copy_build_resource_pack_to_export_folder(cb) {
|
||||
gulp
|
||||
.src(["build/resource_packs/**/**"])
|
||||
.pipe(gulp.dest("export/" + bpfoldername + "/resource_packs/" + bpfoldername));
|
||||
console.log(
|
||||
"Copied build/resource_packs/" +
|
||||
bpfoldername +
|
||||
"/**/** to export/" +
|
||||
bpfoldername +
|
||||
"/resource_packs/" +
|
||||
bpfoldername
|
||||
);
|
||||
cb();
|
||||
}
|
||||
|
||||
function copy_build_behavior_pack_to_export_folder(cb) {
|
||||
gulp
|
||||
.src(["build/behavior_packs/**/**"])
|
||||
.pipe(gulp.dest("export/" + bpfoldername + "/behavior_packs/" + bpfoldername));
|
||||
cb();
|
||||
}
|
||||
|
||||
function copy_world_to_export_folder(cb) {
|
||||
if (exportWorldFolderPath == "") {
|
||||
var readLineSync = import("readline-sync").then((readLineSync) => {
|
||||
let data = get_worlds_paths_and_names(cb);
|
||||
let index = readLineSync.keyInSelect(
|
||||
data.map((d) => d.name),
|
||||
"Which world do you want to copy?"
|
||||
);
|
||||
if (index === -1) {
|
||||
cb();
|
||||
return;
|
||||
}
|
||||
const world = data[index];
|
||||
//console.log("Copying world '" + world.path + "' to 'build/worlds/export/'");
|
||||
return gulp.src([world.path + "/**/*"]).pipe(gulp.dest("export/" + bpfoldername));
|
||||
});
|
||||
} else {
|
||||
return gulp.src([exportWorldFolderPath + "/**/*"]).pipe(gulp.dest("export/" + bpfoldername));
|
||||
}
|
||||
//copy the build to the correct folder
|
||||
cb();
|
||||
}
|
||||
|
||||
function get_worlds_paths_and_names(cb) {
|
||||
let data = [];
|
||||
const worldsPath = mcdir + worldsFolderName;
|
||||
const worlds = fs.readdirSync(worldsPath);
|
||||
worlds.forEach((world) => {
|
||||
let worldName = "UNDEFINED";
|
||||
try {
|
||||
worldName = fs.readFileSync(worldsPath + "/" + world + "/levelname.txt", "utf8");
|
||||
} catch (e) {
|
||||
console.log("Error reading levelname.txt for " + world);
|
||||
console.error(e);
|
||||
}
|
||||
data.push({
|
||||
path: worldsPath + "/" + world,
|
||||
name: worldName,
|
||||
});
|
||||
});
|
||||
cb();
|
||||
return data;
|
||||
}
|
||||
|
||||
async function nbt_rename_world(cb) {
|
||||
const NBT = await import("nbtify");
|
||||
const { readFile, writeFile } = await import("fs/promises");
|
||||
const buffer = await readFile("export/" + bpfoldername + "/level.dat");
|
||||
const data = await NBT.read(buffer);
|
||||
let oldLevelName = data.data.LevelName;
|
||||
let newName = bpfoldername + " " + get_version();
|
||||
data.data.LevelName = newName;
|
||||
const result = await NBT.write(data);
|
||||
await writeFile("export/" + bpfoldername + "/level.dat", result);
|
||||
console.log("Renamed " + oldLevelName + " to " + newName);
|
||||
cb();
|
||||
}
|
||||
|
||||
function levelnametxt_rename(cb) {
|
||||
const { readFile, writeFile } = import("fs/promises");
|
||||
const levelNameFilePath = "export/" + bpfoldername + "/levelname.txt";
|
||||
let levelName = fs.readFileSync(levelNameFilePath, "utf8");
|
||||
let newName = bpfoldername + " " + get_version();
|
||||
fs.writeFileSync(levelNameFilePath, newName);
|
||||
console.log("Renamed " + levelName + " to " + newName);
|
||||
cb();
|
||||
}
|
||||
|
||||
// Setup functions
|
||||
|
||||
function setup_behaviour_pack(cb) {
|
||||
const manifestPath = "behavior_packs/manifest.json";
|
||||
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
||||
|
||||
let header_uuid = get_behaviour_pack_uuid(cb);
|
||||
let module_uuid = generate_UUID(cb);
|
||||
let resource_pack_dependencies_uuid = get_resource_pack_uuid(cb);
|
||||
|
||||
console.log("Header UUID: " + header_uuid);
|
||||
console.log("Module UUID: " + module_uuid);
|
||||
|
||||
manifest.header.uuid = header_uuid;
|
||||
manifest.modules[0].uuid = module_uuid;
|
||||
manifest.dependencies[1].uuid = resource_pack_dependencies_uuid;
|
||||
|
||||
manifest.metadata.authors = behavior_pack_authors;
|
||||
manifest.header.name = behavior_pack_name;
|
||||
manifest.header.description = behavior_pack_description;
|
||||
|
||||
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 1));
|
||||
cb();
|
||||
}
|
||||
function setup_resource_pack(cb) {
|
||||
const manifestPath = "resource_packs/manifest.json";
|
||||
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
||||
|
||||
let header_uuid = get_resource_pack_uuid(cb);
|
||||
let module_uuid = generate_UUID(cb);
|
||||
let dependencies_uuid = get_behaviour_pack_uuid(cb);
|
||||
|
||||
manifest.header.uuid = header_uuid;
|
||||
manifest.modules[0].uuid = module_uuid;
|
||||
manifest.dependencies[0].uuid = dependencies_uuid;
|
||||
|
||||
manifest.metadata.authors = resource_pack_authors;
|
||||
manifest.header.name = resource_pack_name;
|
||||
manifest.header.description = resource_pack_description;
|
||||
|
||||
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 1));
|
||||
cb();
|
||||
}
|
||||
|
||||
function generate_UUID(cb) {
|
||||
let uuid = crypto.randomUUID();
|
||||
return uuid;
|
||||
}
|
||||
|
||||
var behavior_pack_uuid = null;
|
||||
var resource_pack_uuid = null;
|
||||
|
||||
function get_uuid_for_type(cb, type) {
|
||||
let to_return = null;
|
||||
switch (type) {
|
||||
case "behaviour_pack":
|
||||
if (behavior_pack_uuid === null) {
|
||||
behavior_pack_uuid = generate_UUID(cb);
|
||||
}
|
||||
to_return = behavior_pack_uuid;
|
||||
break;
|
||||
case "resource_pack":
|
||||
if (resource_pack_uuid === null) {
|
||||
resource_pack_uuid = generate_UUID(cb);
|
||||
}
|
||||
to_return = resource_pack_uuid;
|
||||
break;
|
||||
default:
|
||||
return generate_UUID(cb);
|
||||
}
|
||||
return to_return;
|
||||
}
|
||||
let get_behaviour_pack_uuid = (cb) => get_uuid_for_type(cb, "behaviour_pack");
|
||||
let get_resource_pack_uuid = (cb) => get_uuid_for_type(cb, "resource_pack");
|
||||
|
||||
exports.clean_build = clean_build;
|
||||
exports.copy_behavior_packs = copy_behavior_packs;
|
||||
exports.copy_resource_packs = copy_resource_packs;
|
||||
exports.compile_scripts = compile_scripts;
|
||||
exports.copy_content = copy_content;
|
||||
exports.build = build;
|
||||
exports.clean_localmc = clean_localmc;
|
||||
exports.deploy_localmc = deploy_localmc;
|
||||
exports.default = gulp.series(build, deploy_localmc);
|
||||
exports.clean = gulp.series(clean_build, clean_localmc);
|
||||
exports.watch = gulp.series(build, deploy_localmc, watch);
|
||||
exports.serve = gulp.series(build, deploy_localmc, startServer, serve);
|
||||
exports.updateworld = gulp.series(
|
||||
clean_localmc_world_backup,
|
||||
backup_localmc_world,
|
||||
clean_localmc_world,
|
||||
deploy_localmc_world
|
||||
);
|
||||
exports.ingestworld = gulp.series(clean_dev_world_backup, backup_dev_world, clean_dev_world, ingest_localmc_world);
|
||||
exports.updateconfig = gulp.series(clean_localmc_config, deploy_localmc_config);
|
||||
exports.compile_world = gulp.series(
|
||||
clean_export,
|
||||
build,
|
||||
copy_world_to_export_folder,
|
||||
gulp.parallel(copy_build_behavior_pack_to_export_folder, copy_build_resource_pack_to_export_folder),
|
||||
gulp.parallel(add_version_to_world_name, nbt_rename_world)
|
||||
);
|
||||
exports.zip = gulp.series(zip_world, rename_zip_to_mcworld);
|
||||
exports.export = gulp.series(
|
||||
clean_export,
|
||||
copy_world_to_export_folder,
|
||||
build,
|
||||
gulp.parallel(copy_build_behavior_pack_to_export_folder, copy_build_resource_pack_to_export_folder),
|
||||
levelnametxt_rename,
|
||||
nbt_rename_world,
|
||||
zip_world,
|
||||
rename_zip_to_mcworld
|
||||
);
|
||||
|
||||
exports.test = gulp.parallel(setup_behaviour_pack, setup_resource_pack);
|
||||
exports.export_clean = gulp.series(clean_export);
|
||||
524
old_readme.md
Normal file
@@ -0,0 +1,524 @@
|
||||
---
|
||||
page_type: sample
|
||||
author: mammerla
|
||||
description: A basic Hello World example of developing Minecraft scripts using TypeScript and a build process.
|
||||
ms.author: mikeam@microsoft.com
|
||||
ms.date: 04/01/2022
|
||||
languages:
|
||||
- typescript
|
||||
products:
|
||||
- minecraft
|
||||
---
|
||||
|
||||
# Minecraft TypeScript Starter Project
|
||||
|
||||
This sample demonstrates a simple build process and TypeScript compilation for Minecraft. This readme shows how you can use Betas APIs experiment to build out simple gameplay styles. You can use this project as a starter for your own scripting projects.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
**Install Node.js tools, if you haven't already**
|
||||
|
||||
We're going to use the package manager [npm](https://www.npmjs.com/package/npm) to get more tools to make the process of building our project easier.
|
||||
|
||||
Visit [https://nodejs.org/](https://nodejs.org).
|
||||
|
||||
Download the version with "LTS" next to the number and install it. (LTS stands for Long Term Support, if you're curious.) In the Node.js Windows installer, accept the installation defaults. You do not need to install any additional tools for Native compilation.
|
||||
|
||||
**Install Visual Studio Code, if you haven't already**
|
||||
|
||||
Visit the [Visual Studio Code website](https://code.visualstudio.com) and install Visual Studio Code.
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. To make your own environment look like the example, create a folder on your `C:\` drive and call it **projects**. Create a subfolder called **cotta**.
|
||||
|
||||
1. Put the extracted contents of the TypeScript Starter Project folder into **cotta**.
|
||||
|
||||
1. Open a Windows Terminal or PowerShell window and change the working directory to your **cotta** folder:
|
||||
|
||||
```powershell
|
||||
cd c:\projects\cotta\
|
||||
```
|
||||
|
||||
1. Use npm to install our tools:
|
||||
|
||||
```powershell
|
||||
npm i
|
||||
```
|
||||
|
||||
1. When that's done, enter:
|
||||
|
||||
```powershell
|
||||
npm i gulp-cli --global
|
||||
```
|
||||
|
||||
1. Use this shortcut command to open the project in Visual Studio Code:
|
||||
|
||||
```powershell
|
||||
code .
|
||||
```
|
||||
|
||||
It might also ask you to install the Minecraft Debugger and Blockception's Visual Studio Code plugin, which are plugins to Visual Studio Code that can help with Minecraft development. Go ahead and do that, if you haven't already.
|
||||
|
||||
### Chapter 1. Customize the behavior pack
|
||||
|
||||
In Visual Studio Code, expand the `behavior_packs` node in the treeview to the left, and rename the **cotta** folder to "cotta".
|
||||
|
||||
Use the Find/Replace command (Ctrl-Shift-F) to search for "cotta" and replace the instance in **gulpfile.js** and the instance in **launch.json** with "cotta."
|
||||
|
||||
Go back the Files tree view and open `behavior_packs\cotta\manifest.json`
|
||||
|
||||
Update the name and description properties to something like "Cotta Behavior Pack" and "My TypeScript Project".
|
||||
|
||||
Update the first and second UUID properties to make it unique to your project. See [this article](https://learn.microsoft.com/minecraft/creator/documents/behaviorpack) for tips on working with behavior packs and creating your own unique UUIDs.
|
||||
|
||||
> IMPORTANT:
|
||||
> You may also need to update the version of Beta APIs in your `dependencies` section to match your version of Minecraft.
|
||||
> Versions 1.19.40 feature `1.0.0-beta` APIs
|
||||
> Versions 1.19.50, 1.19.60, and 1.19.70 feature `1.1.0-beta` APIs
|
||||
> Versions 1.19.80 features `1.2.0-beta` APIs
|
||||
> Versions 1.20.0 features `1.3.0-beta` APIs
|
||||
> Versions 1.20.10 features `1.4.0-beta` APIs
|
||||
> Versions 1.20.20 features `1.5.0-beta` APIs
|
||||
> Future versions will likely require updated versions of Beta APIs.
|
||||
|
||||
### Chapter 2. Let's test the parts of our project
|
||||
|
||||
To get started, go into PowerShell and navigate to your **C:\projects\cotta** directory.
|
||||
Run this command:
|
||||
|
||||
```powershell
|
||||
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
|
||||
```
|
||||
|
||||
Run this one, too.
|
||||
|
||||
```powershell
|
||||
gulp
|
||||
```
|
||||
|
||||
This uses a build tool called GulpJS and automatically compiles your TypeScript project and pushes it over into Minecraft.
|
||||
|
||||
You may hear a little tone through your speakers when it has successfully completed deployment.
|
||||
|
||||
Launch Minecraft and create a new world:
|
||||
|
||||
1. Call it **Cotta Test**.
|
||||
1. Select a Creative game mode.
|
||||
1. Select a Flat world option, under the Advanced section of the Create New World screen.
|
||||
1. Under Behavior Packs, under Available, you should see your Cotta Behavior Pack. Select it and Activate it.
|
||||
1. Enable the Beta APIs experiment toggle, under the Experiments section of the Create New World screen.
|
||||
1. Create the world and go into it.
|
||||
|
||||
Now you're in. Great!
|
||||
|
||||
By default, this starter pack comes with a simple script that will display a message:
|
||||
|
||||
`[Script Engine] Hello starter! Tick: <number>`
|
||||
|
||||
This means your behavior pack is working and your tools for compiling and pushing TypeScript are just fine. Awesome!
|
||||
|
||||
### Chapter 3. Scripting your gameplay
|
||||
|
||||
Let's go back to Visual Studio Code and change up some code.
|
||||
|
||||
Open up `scripts/main.ts` within Visual Studio Code.
|
||||
|
||||
#### Add some initialization code
|
||||
|
||||
Remove all the existing script code in **main.ts**. Replace it with this to start:
|
||||
|
||||
```typescript
|
||||
import {
|
||||
world,
|
||||
system,
|
||||
BlockPermutation,
|
||||
EntityInventoryComponent,
|
||||
ItemStack,
|
||||
DisplaySlotId,
|
||||
BlockType,
|
||||
BlockTypes,
|
||||
} from "@minecraft/server";
|
||||
|
||||
const START_TICK = 100;
|
||||
|
||||
// global variables
|
||||
let curTick = 0;
|
||||
|
||||
const ARENA_X_SIZE = 30;
|
||||
const ARENA_Z_SIZE = 30;
|
||||
const ARENA_X_OFFSET = 0;
|
||||
const ARENA_Y_OFFSET = -60;
|
||||
const ARENA_Z_OFFSET = 0;
|
||||
|
||||
function initializeBreakTheTerracotta() {
|
||||
const overworld = world.getDimension("overworld");
|
||||
|
||||
let scoreObjective = world.scoreboard.getObjective("score");
|
||||
|
||||
if (!scoreObjective) {
|
||||
scoreObjective = world.scoreboard.addObjective("score", "Level");
|
||||
}
|
||||
|
||||
// eliminate pesky nearby mobs
|
||||
let entities = overworld.getEntities({
|
||||
excludeTypes: ["player"],
|
||||
});
|
||||
|
||||
for (let entity of entities) {
|
||||
entity.kill();
|
||||
}
|
||||
|
||||
// set up scoreboard
|
||||
world.scoreboard.setObjectiveAtDisplaySlot(DisplaySlotId.Sidebar, {
|
||||
objective: scoreObjective,
|
||||
});
|
||||
|
||||
let players = world.getAllPlayers();
|
||||
|
||||
for (let player of players) {
|
||||
player.runCommand("scoreboard players set @s score 0");
|
||||
|
||||
let inv = player.getComponent("inventory") as EntityInventoryComponent;
|
||||
inv.container.addItem(new ItemStack("diamond_sword"));
|
||||
inv.container.addItem(new ItemStack("dirt", 64));
|
||||
|
||||
player.teleport(
|
||||
{
|
||||
x: ARENA_X_OFFSET - 3,
|
||||
y: ARENA_Y_OFFSET,
|
||||
z: ARENA_Z_OFFSET - 3,
|
||||
},
|
||||
{
|
||||
dimension: overworld,
|
||||
rotation: { x: 0, y: 0 }
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
world.sendMessage("BREAK THE TERRACOTTA");
|
||||
}
|
||||
|
||||
function gameTick() {
|
||||
try {
|
||||
curTick++;
|
||||
|
||||
if (curTick === START_TICK) {
|
||||
initializeBreakTheTerracotta();
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("Tick error: " + e);
|
||||
}
|
||||
|
||||
system.run(gameTick);
|
||||
}
|
||||
|
||||
system.run(gameTick);
|
||||
|
||||
```
|
||||
|
||||
This code does some work to initialize our gameplay for Minecraft by running several commands.
|
||||
|
||||
First, we queue up a run to our main tick function, gameTick. Note that at the end, we will requeue a game tick, which will run within the next tick frame. This will give us a callback that fires 20 times a second, and within this, we can put all of our game logic. We want the game to initialize some code; namely, the `initializeBreakTheTerracotta` function.
|
||||
|
||||
Note that we wait until `START_TICK` (100 ticks in) before the world is actually initialized. This gives Minecraft time to fully load up and get ready.
|
||||
|
||||
Within the initialize function, we run commands that:
|
||||
|
||||
- Clear out any existing mobs near the player in the world.
|
||||
- Set up a scoreboard objective for overall Level of the player, meaning the number of terracotta breaks they have
|
||||
- Give the current player a diamond sword and some dirty dirt
|
||||
- Use chat to give the player an instructional message
|
||||
|
||||
Now, let's run the code. This time, we're going to run gulp in "watch mode" - meaning it will just sit in the background and watch for changes, and if they happen, they will automatically compile and deploy to the Minecraft folder. This way, we won't have to worry about separately compiling every time we make a change to code.
|
||||
|
||||
Go back to your PowerShell window, and enter:
|
||||
|
||||
```powershell
|
||||
gulp watch
|
||||
```
|
||||
|
||||
You should see gulp compile and deploy to the Minecraft folder, and make a noise when it does that. From here, we don't need to tend to PowerShell except to see if there are any compilation errors down the road.
|
||||
|
||||
When you are done coding for the day, either hit **ctrl-c** in the PowerShell Window to stop the watch mode or close the window.
|
||||
|
||||
Now, let's go back to Minecraft.
|
||||
|
||||
Save and Quit to exit out of the world. We'll want to reload the world from here - any time you make a script change, you need to exit out of the world and reload it to see changes. Or, you can run the `/reload` command to reload the JavaScript files that have been deployed.
|
||||
|
||||
Now load the world. You should see your initialization changes: a new scoreboard, new items in your inventory, and a script message.
|
||||
|
||||
Note that as you work through this tutorial, we are going to run the initialization code more than once, so your player is going to get multiples of these items during this development and test phase. If that bothers you, feel free to toss out these items before you close the world.
|
||||
|
||||
#### Build your arena with some helper code
|
||||
|
||||
We're going to start by adding some handy helper utility code functions. This will show you how you can organize your code into separate modules or classes.
|
||||
|
||||
Add a new file to your `scripts` folder called `Utilities.ts`. Correct capitalization matters, so make sure the `U` is capitalized. Add the following code:
|
||||
|
||||
```typescript
|
||||
import { world, BlockType, BlockPermutation } from "@minecraft/server";
|
||||
|
||||
export default class Utilities {
|
||||
static fillBlock(
|
||||
blockType: BlockType,
|
||||
xFrom: number,
|
||||
yFrom: number,
|
||||
zFrom: number,
|
||||
xTo: number,
|
||||
yTo: number,
|
||||
zTo: number
|
||||
) {
|
||||
let overworld = world.getDimension("overworld");
|
||||
let perm = BlockPermutation.resolve(blockType.id);
|
||||
|
||||
for (let i = xFrom; i <= xTo; i++) {
|
||||
for (let j = yFrom; j <= yTo; j++) {
|
||||
for (let k = zFrom; k <= zTo; k++) {
|
||||
overworld.getBlock({ x: i, y: j, z: k })?.setPermutation(perm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static fourWalls(
|
||||
blockType: BlockType,
|
||||
xFrom: number,
|
||||
yFrom: number,
|
||||
zFrom: number,
|
||||
xTo: number,
|
||||
yTo: number,
|
||||
zTo: number
|
||||
) {
|
||||
let overworld = world.getDimension("overworld");
|
||||
let perm = BlockPermutation.resolve(blockType.id);
|
||||
|
||||
for (let i = xFrom; i <= xTo; i++) {
|
||||
for (let k = yFrom; k <= yTo; k++) {
|
||||
overworld.getBlock({ x: i, y: k, z: zFrom })?.setPermutation(perm);
|
||||
overworld.getBlock({ x: i, y: k, z: zTo })?.setPermutation(perm);
|
||||
}
|
||||
}
|
||||
|
||||
for (let j = zFrom + 1; j < zTo; j++) {
|
||||
for (let k = yFrom; k <= yTo; k++) {
|
||||
overworld.getBlock({ x: xFrom, y: k, z:j })?.setPermutation(perm);
|
||||
overworld.getBlock({ x: xTo, y: k, z: j })?.setPermutation(perm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The first utility function here (`Utilities.fillBlock`) is relatively straightforward:
|
||||
|
||||
Across three dimensions (within three loops), it will basically set a block in the overworld to a particular type. This function just makes a big chunk of blocks.
|
||||
|
||||
The second utility function here (`Utilities.fourWalls`) basically creates a walled enclave. The first inner loop creates two stripes of blocks left to right (across X). The second inner loop creates two stripes of blocks south to north (across Z) - thus completing four walls that join each other.
|
||||
|
||||
Go back to **main.ts**. Let's use these functions in our initialization function.
|
||||
|
||||
First, we'll need an import function. Add a new line above `const START_TICK = 100;` and make this the second line of the file:
|
||||
|
||||
```typescript
|
||||
import Utilities from "./Utilities.js";
|
||||
```
|
||||
|
||||
Next, within `initializeBreakTheTerracotta`, let's add our arena initialization beneath the `world.sendMessage("BREAK THE TERRACOTTA!");` line of code:
|
||||
|
||||
```typescript
|
||||
let airBlockType = BlockTypes.get("minecraft:air");
|
||||
let cobblestoneBlockType = BlockTypes.get("minecraft:cobblestone");
|
||||
|
||||
if (airBlockType) {
|
||||
Utilities.fillBlock(
|
||||
airBlockType,
|
||||
ARENA_X_OFFSET - ARENA_X_SIZE / 2 + 1,
|
||||
ARENA_Y_OFFSET,
|
||||
ARENA_Z_OFFSET - ARENA_Z_SIZE / 2 + 1,
|
||||
ARENA_X_OFFSET + ARENA_X_SIZE / 2 - 1,
|
||||
ARENA_Y_OFFSET + 10,
|
||||
ARENA_Z_OFFSET + ARENA_Z_SIZE / 2 - 1
|
||||
);
|
||||
}
|
||||
|
||||
if (cobblestoneBlockType) {
|
||||
Utilities.fourWalls(
|
||||
cobblestoneBlockType,
|
||||
ARENA_X_OFFSET - ARENA_X_SIZE / 2,
|
||||
ARENA_Y_OFFSET,
|
||||
ARENA_Z_OFFSET - ARENA_Z_SIZE / 2,
|
||||
ARENA_X_OFFSET + ARENA_X_SIZE / 2,
|
||||
ARENA_Y_OFFSET + 10,
|
||||
ARENA_Z_OFFSET + ARENA_Z_SIZE / 2
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
The first line just fills a cuboid with air - basically clearing out the arena of any previous items. The second line re-installs and adds four walls of cobblestone.
|
||||
|
||||
Exit out of your Minecraft world and restart it to load your changes. After a brief delay, you should find yourself in an arena.
|
||||
|
||||
Now, let's give ourselves some terracotta to break.
|
||||
|
||||
### Chapter 4. Add some gameplay basics - scoring and objectives
|
||||
|
||||
First, let's track some more game variables. Inside **main.ts**, add this directly beneath the `let curTick = 0` line of code:
|
||||
|
||||
```typescript
|
||||
let score = 0;
|
||||
let cottaX = 0;
|
||||
let cottaZ = 0;
|
||||
let spawnCountdown = 1;
|
||||
```
|
||||
|
||||
Add the following to the `gameTick` function, beneath the `curTick++` line of code:
|
||||
|
||||
```typescript
|
||||
if (curTick > START_TICK && curTick % 20 === 0) {
|
||||
let overworld = world.getDimension("overworld");
|
||||
|
||||
// no terracotta exists, and we're waiting to spawn a new one.
|
||||
if (spawnCountdown > 0) {
|
||||
spawnCountdown--;
|
||||
|
||||
if (spawnCountdown <= 0) {
|
||||
spawnNewTerracotta();
|
||||
}
|
||||
} else {
|
||||
checkForTerracotta();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now add the `spawnNewTerracotta()` and `checkForTerracotta()` functions after the last function and before the last `system.run(gameTick);` line of code:
|
||||
|
||||
```typescript
|
||||
function spawnNewTerracotta() {
|
||||
let overworld = world.getDimension("overworld");
|
||||
|
||||
// create new terracotta
|
||||
cottaX = Math.floor(Math.random() * (ARENA_X_SIZE - 1)) - (ARENA_X_SIZE / 2 - 1);
|
||||
cottaZ = Math.floor(Math.random() * (ARENA_Z_SIZE - 1)) - (ARENA_Z_SIZE / 2 - 1);
|
||||
|
||||
world.sendMessage("Creating new terracotta!");
|
||||
let block = overworld
|
||||
.getBlock({ x: cottaX + ARENA_X_OFFSET, y: 1 + ARENA_Y_OFFSET, z: cottaZ + ARENA_Z_OFFSET });
|
||||
|
||||
if (block) {
|
||||
block.setPermutation(BlockPermutation.resolve("minecraft:yellow_glazed_terracotta"));
|
||||
}
|
||||
}
|
||||
|
||||
function checkForTerracotta() {
|
||||
let overworld = world.getDimension("overworld");
|
||||
|
||||
let block = overworld.getBlock({ x: cottaX + ARENA_X_OFFSET, y: 1 + ARENA_Y_OFFSET, z: cottaZ + ARENA_Z_OFFSET });
|
||||
|
||||
if (block && !block.permutation.matches("minecraft:yellow_glazed_terracotta")) {
|
||||
// we didn't find the terracotta! set a new spawn countdown
|
||||
score++;
|
||||
spawnCountdown = 2;
|
||||
cottaX = -1;
|
||||
|
||||
let players = world.getAllPlayers();
|
||||
|
||||
for (let player of players) {
|
||||
player.runCommand("scoreboard players set @s score " + score);
|
||||
}
|
||||
|
||||
world.sendMessage("You broke the terracotta! Creating new terracotta in a few seconds.");
|
||||
cottaZ = -1;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Congratulations! You've just created a very basic and very easy game where you can run around and break terracotta with your sword.
|
||||
|
||||
To play, you will need to run the command `/gamemode s` to put Minecraft into survival mode so that you can break the terracotta.
|
||||
|
||||
After the terracotta is broken, your score will increment, and a new block is spawned.
|
||||
|
||||
#### Add a challenge - let's add some mobs
|
||||
|
||||
OK, let's add this function after the `checkForTerracotta()` function:
|
||||
|
||||
```typescript
|
||||
function spawnMobs() {
|
||||
let overworld = world.getDimension("overworld");
|
||||
|
||||
// spawn mobs = create 1-2 mobs
|
||||
let spawnMobCount = Math.floor(Math.random() * 2) + 1;
|
||||
|
||||
for (let j = 0; j < spawnMobCount; j++) {
|
||||
let zombieX = Math.floor(Math.random() * (ARENA_X_SIZE - 2)) - ARENA_X_SIZE / 2;
|
||||
let zombieZ = Math.floor(Math.random() * (ARENA_Z_SIZE - 2)) - ARENA_Z_SIZE / 2;
|
||||
|
||||
overworld.spawnEntity(
|
||||
"minecraft:zombie",
|
||||
{ x: zombieX + ARENA_X_OFFSET, y: 1 + ARENA_Y_OFFSET, z: zombieZ + ARENA_Z_OFFSET }
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This function will spawn 1-2 zombies within the arena, at a random location. You can change the kinds of mobs to spawn, the number, and more within this function.
|
||||
|
||||
Let's call that function within our `gameTick` method:
|
||||
|
||||
```typescript
|
||||
let spawnInterval = Math.ceil(200 / ((score + 1) / 3));
|
||||
if (curTick > START_TICK && curTick % spawnInterval === 0) {
|
||||
spawnMobs();
|
||||
}
|
||||
```
|
||||
|
||||
For gameplay, we want mobs to spawn more frequently as your score goes up. To do this, the frequency at which `spawnMobs` is called depends on the `spawnInterval` variable. `spawnInterval` is the span of time between spawning new mobs. Because we divide this interval by our current score, this means that as our score goes up, the interval of time between spawning mobs gets shorter. This makes the challenge harder over time.
|
||||
|
||||
As you play, zombies should spawn and start chasing you. They'll spawn slowly at first, but as you break blocks they'll start to accumulate and bother you while you try to break terracotta blocks.
|
||||
|
||||
### Add more challenges!
|
||||
|
||||
Let's add a new gameplay twist: randomly spawning obstructions in the form of leaves.
|
||||
|
||||
Add this function to **main.ts** to randomly place some fuzzy leaves:
|
||||
|
||||
```typescript
|
||||
function addFuzzyLeaves() {
|
||||
let overworld = world.getDimension("overworld");
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const leafX = Math.floor(Math.random() * (ARENA_X_SIZE - 1)) - (ARENA_X_SIZE / 2 - 1);
|
||||
const leafY = Math.floor(Math.random() * 10);
|
||||
const leafZ = Math.floor(Math.random() * (ARENA_Z_SIZE - 1)) - (ARENA_Z_SIZE / 2 - 1);
|
||||
|
||||
overworld
|
||||
.getBlock({ x: leafX + ARENA_X_OFFSET, y: leafY + ARENA_Y_OFFSET, z: leafZ + ARENA_Z_OFFSET})
|
||||
?.setPermutation(BlockPermutation.resolve("minecraft:leaves"));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And call that function in your gameTick() function:
|
||||
|
||||
```typescript
|
||||
if (curTick > START_TICK && curTick % 29 === 0) {
|
||||
addFuzzyLeaves();
|
||||
}
|
||||
```
|
||||
|
||||
You may wonder why the interval here is 29. The main idea was to select a number to avoid the chance that on a particular tick we do everything at once (create new leaves, spawn mobs AND check terracotta state), so we try to have offset schedules for all of these different game activities.
|
||||
|
||||
Now exit out and reload your game. As you run around, you should see new leaves get spawned. This should add a little bit more challenge to your gameplay!
|
||||
|
||||
### Summary
|
||||
|
||||
With this starter, you've seen how to build a nice little arena game.
|
||||
|
||||
Like the randomly spawning leaves, you can see how you can add different gameplay elements into your arena. Maybe rather than leaves, you want to randomly generate some parkour platforms - or some treasures or weapons, or different types of mobs. Experiment and build your own custom competition arenas!
|
||||
|
||||
## Manifest
|
||||
|
||||
- [gulpfile.js](https://github.com/microsoft/minecraft-scripting-samples/blob/main/ts-starter/gulpfile.js): This file contains build instructions for Gulp, for building out TypeScript code.
|
||||
- [scripts](https://github.com/microsoft/minecraft-scripting-samples/blob/main/ts-starter/scripts): This contains all of your TypeScript files, that will be compiled and built into your projects.
|
||||
- [behavior_packs](https://github.com/microsoft/minecraft-scripting-samples/blob/main/ts-starter/behavior_packs): This contains resources and JSON files that define your behavior pack.
|
||||
9456
package-lock.json
generated
Normal file
29
package.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "scripting-starter",
|
||||
"version": "0.1.0",
|
||||
"productName": "Minecraft TypeScript Starter Project",
|
||||
"description": "Minecraft TypeScript Starter Project",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@minecraft/server-ui": "^1.1.0",
|
||||
"del": "^6.0.0",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-cli": "^2.3.0",
|
||||
"gulp-rename": "^2.0.0",
|
||||
"gulp-sourcemaps": "^3.0.0",
|
||||
"gulp-typescript": "^6.0.0-alpha.1",
|
||||
"gulp-zip": "^5.1.0",
|
||||
"nbtify": "^1.85.0",
|
||||
"readline-sync": "^1.4.10",
|
||||
"source-map": "^0.7.4",
|
||||
"typescript": "^4.4.3"
|
||||
},
|
||||
"scripts": {
|
||||
"enablemcloopback": "CheckNetIsolation.exe LoopbackExempt -a -p=S-1-15-2-1958404141-86561845-1752920682-3514627264-368642714-62675701-733520436",
|
||||
"enablemcpreviewloopback": "CheckNetIsolation.exe LoopbackExempt -a -p=S-1-15-2-424268864-5579737-879501358-346833251-474568803-887069379-4040235476"
|
||||
},
|
||||
"dependencies": {
|
||||
"@minecraft/server": "^1.12.0-beta.1.21.0-stable",
|
||||
"decode-uri-component": "^0.2.2"
|
||||
}
|
||||
}
|
||||
7
resource_packs/blocks.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"format_version": [1, 1, 0],
|
||||
"cc:cracked_glass": {
|
||||
"textures": "cracked_glass",
|
||||
"sound": "glass"
|
||||
}
|
||||
}
|
||||
44
resource_packs/manifest.json
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"format_version": 2,
|
||||
"metadata": {
|
||||
"authors": [
|
||||
"Me and my cat"
|
||||
]
|
||||
},
|
||||
"header": {
|
||||
"name": "Reeks2Missie9RP",
|
||||
"description": "De resource pack voor Reeks 2 Missie 9",
|
||||
"min_engine_version": [
|
||||
1,
|
||||
20,
|
||||
0
|
||||
],
|
||||
"uuid": "0b55c95c-33d9-4cef-8040-3607704aa2a2",
|
||||
"version": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"type": "resources",
|
||||
"uuid": "8f58e8a4-13db-4b7a-8466-89b1564e6a8b",
|
||||
"version": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"dependencies": [
|
||||
{
|
||||
"uuid": "2d4894af-d185-4b31-8ec8-265d585ee3fb",
|
||||
"version": [
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
resource_packs/pack_icon.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
37
resource_packs/particles/point.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "codecosmos:point",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particle/point"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 0.1
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.25, 0.25],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 16,
|
||||
"texture_height": 16,
|
||||
"uv": [0, 0],
|
||||
"uv_size": [16, 16]
|
||||
}
|
||||
},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": ["variable.color.r ", "variable.color.g", "variable.color.b", 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
67
resource_packs/texts/en_US.lang
Normal file
@@ -0,0 +1,67 @@
|
||||
## General messages
|
||||
message.trail.follow=Follow the trail
|
||||
message.levels.completed=You have completed all levels!
|
||||
|
||||
|
||||
## Fail conditions
|
||||
message.level.incorrect=§cIncorrect!§b
|
||||
message.level.incorrect.subtext=Probeer opnieuw!
|
||||
|
||||
message.level.outofbounds=§cOut of bounds!§b
|
||||
message.level.outofbounds.subtext=You can't be over water!
|
||||
|
||||
|
||||
## npc names
|
||||
npc.name.help=Help
|
||||
npc.name.suki=§2Suki
|
||||
npc.name.bilal=§6Bilal
|
||||
npc.name.ramses=§dRamses
|
||||
npc.name.chanel=§9Wetenschapper Chanel
|
||||
npc.name.paul=§7Paul
|
||||
npc.name.farah=§5Farah
|
||||
npc.name.turt=§aTurt
|
||||
npc.name.mo=§4Mo
|
||||
npc.name.al=Al
|
||||
|
||||
## Default buttons
|
||||
button.thanks=Thanks!
|
||||
button.close=Close
|
||||
button.ok=Ok
|
||||
button.hello=Hello
|
||||
button.noprob=No problem
|
||||
button.letsgo=Let's Go!
|
||||
|
||||
message.talkto.ramses=Talk to §dRamses
|
||||
message.talkto.chanel=Talk to §9Chanel
|
||||
|
||||
## Intro messages
|
||||
message.intro.started=Crack the Vault!
|
||||
message.intro.make=Break the code!
|
||||
message.intro.done=§aYou have cracked the code!§b
|
||||
|
||||
## Level 1 messages
|
||||
message.level1.name=Level 1
|
||||
message.level1.started=Level 1 is started!
|
||||
message.level1.complete=Level 1 is complete!
|
||||
message.level1.make=Make Level 1
|
||||
message.level1.outOfBoun=§cOut of bounds!§bwd
|
||||
|
||||
## Level 2 messages
|
||||
message.level2.name=Level 2
|
||||
message.level2.started=Level 2 is started!
|
||||
message.level2.complete=Level 2 is complete!
|
||||
message.level2.make=Make Level 2
|
||||
|
||||
## Level 3 messages
|
||||
message.level3.name=Level 3
|
||||
message.level3.started=Level 3 is started!
|
||||
message.level3.complete=Level 3 is complete!
|
||||
message.level3.make=Make Level 3
|
||||
|
||||
## Goto messages
|
||||
message.goto.field.1=Go to the First Field
|
||||
message.goto.field.2=Go to the Second Field
|
||||
message.goto.field.3=Go to the Last Field
|
||||
|
||||
chanel.greeting.1.text=Hello! I'm §9Chanel§0, the scientist. I'm here to help you with the vault.
|
||||
chanel.greeting.1.button=Ok!
|
||||
3
resource_packs/texts/languages.json
Normal file
@@ -0,0 +1,3 @@
|
||||
[
|
||||
"en_US"
|
||||
]
|
||||
BIN
resource_packs/textures/blocks/cracked_glass.png
Normal file
|
After Width: | Height: | Size: 392 B |
BIN
resource_packs/textures/blocks/redstone_lamp_off.png
Normal file
|
After Width: | Height: | Size: 107 B |
BIN
resource_packs/textures/blocks/redstone_lamp_on.png
Normal file
|
After Width: | Height: | Size: 107 B |
BIN
resource_packs/textures/entity/agent.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
resource_packs/textures/particle/point.png
Normal file
|
After Width: | Height: | Size: 168 B |
11
resource_packs/textures/terrain_texture.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"texture_name": "atlas.terrain",
|
||||
"resource_pack_name": "cc",
|
||||
"padding": 8,
|
||||
"num_mip_levels": 4,
|
||||
"texture_data": {
|
||||
"cracked_glass": {
|
||||
"textures": "textures/blocks/cracked_glass"
|
||||
}
|
||||
}
|
||||
}
|
||||
13
scripts/Commandeer/Trigger/CCTrigger.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Trigger } from "./trigger";
|
||||
import { Maker } from "./maker";
|
||||
import { Manager } from "./manager";
|
||||
|
||||
export * from "./trigger";
|
||||
export * from "./maker";
|
||||
export * from "./manager";
|
||||
|
||||
export const CCTrigger = {
|
||||
Trigger,
|
||||
Maker,
|
||||
Manager,
|
||||
};
|
||||
204
scripts/Commandeer/Trigger/maker.ts
Normal file
@@ -0,0 +1,204 @@
|
||||
import { Trigger } from "./trigger";
|
||||
|
||||
import {
|
||||
Block,
|
||||
ChatSendAfterEvent,
|
||||
PaletteColor,
|
||||
EntityInventoryComponent,
|
||||
ItemStack,
|
||||
ItemUseOnBeforeEvent,
|
||||
MolangVariableMap,
|
||||
Player,
|
||||
Vector3,
|
||||
world,
|
||||
} from "@minecraft/server";
|
||||
import { vector3, vector3Distance } from "../utils/vectorUtils";
|
||||
import { Mindkeeper, StoreType } from "../mindKeeper";
|
||||
import { spawnParticle } from "../utils/particleUtils";
|
||||
import { Manager } from "./manager";
|
||||
|
||||
export class Maker {
|
||||
private manager: Manager;
|
||||
|
||||
log: Map<string, number> = new Map();
|
||||
|
||||
currentTrigger: Trigger | null = null;
|
||||
waitingForPoint2: boolean = false;
|
||||
point1: Vector3 = vector3(0, 0, 0);
|
||||
point2: Vector3 = vector3(0, 0, 0);
|
||||
|
||||
mindKeeper: Mindkeeper;
|
||||
|
||||
constructor(mindKeeper: Mindkeeper, manager: Manager) {
|
||||
this.mindKeeper = mindKeeper;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
OnChat(event: ChatSendAfterEvent) {
|
||||
if (event.message === "!toggleTriggers") {
|
||||
this.mindKeeper.set("ShowTriggers", (this.mindKeeper.get("ShowTriggers") as boolean) ? false : true);
|
||||
}
|
||||
if (event.message === "!TWand") {
|
||||
const item = new ItemStack("minecraft:stick");
|
||||
item.nameTag = "MakeTrigger";
|
||||
((event.sender as Player).getComponent("inventory") as EntityInventoryComponent).container!.addItem(item);
|
||||
world.sendMessage("Thou shall have the Powah");
|
||||
}
|
||||
|
||||
if (event.message === "!deleteCurrentTrigger") {
|
||||
let currentTriggerdTrigger = this.manager
|
||||
.GetTriggers()
|
||||
.filter((trigger) => trigger.IsPlayerInside(event.sender as Player));
|
||||
if (currentTriggerdTrigger.length > 0) {
|
||||
this.manager.GetTriggers().splice(this.manager.GetTriggers().indexOf(currentTriggerdTrigger[0]), 1);
|
||||
world.sendMessage("Trigger deleted");
|
||||
} else {
|
||||
world.sendMessage("No trigger to delete");
|
||||
}
|
||||
this.manager.Save();
|
||||
}
|
||||
const command = event.message.split(" ")[0];
|
||||
if (command == "!setFunction") {
|
||||
const name = event.message.split(" ")[1];
|
||||
const trigger = this.manager.GetCurrentActiveTriggers()[0];
|
||||
|
||||
if (trigger === undefined) {
|
||||
world.sendMessage("No trigger selected");
|
||||
return;
|
||||
}
|
||||
|
||||
trigger.eventToDispatch = name;
|
||||
this.manager.Save();
|
||||
world.sendMessage(`Function set to ${name}`);
|
||||
}
|
||||
}
|
||||
|
||||
OnItemUse(event: ItemUseOnBeforeEvent) {
|
||||
const currentItemHeld: ItemStack = event.itemStack;
|
||||
const blockInteracted: Block = event.block;
|
||||
const player: Player = event.source as Player;
|
||||
const oldLog = this.log.get(player.name)!;
|
||||
this.log.set(player.name, Date.now());
|
||||
if (oldLog + 150 >= Date.now()) return;
|
||||
|
||||
if (currentItemHeld.typeId == "minecraft:stick" && currentItemHeld.nameTag == "MakeTrigger") {
|
||||
if (this.waitingForPoint2) {
|
||||
this.point2 = vector3(blockInteracted.location.x, blockInteracted.location.y, blockInteracted.location.z);
|
||||
|
||||
let minX = Math.min(this.point1.x, this.point2.x);
|
||||
let maxX = Math.max(this.point1.x, this.point2.x) + 1;
|
||||
let minY = Math.min(this.point1.y, this.point2.y);
|
||||
let maxY = Math.max(this.point1.y, this.point2.y) + 1;
|
||||
let minZ = Math.min(this.point1.z, this.point2.z);
|
||||
let maxZ = Math.max(this.point1.z, this.point2.z) + 1;
|
||||
|
||||
//Take the outer bounds of the two points
|
||||
this.point1 = vector3(minX, minY, minZ);
|
||||
this.point2 = vector3(maxX, maxY, maxZ);
|
||||
|
||||
this.currentTrigger = new Trigger(this.point1, this.point2);
|
||||
|
||||
this.manager.AddTrigger(this.currentTrigger!);
|
||||
this.currentTrigger = null;
|
||||
this.waitingForPoint2 = false;
|
||||
world.sendMessage(`Trigger added`);
|
||||
this.manager.Save();
|
||||
return;
|
||||
} else {
|
||||
this.point1 = vector3(event.block.location.x, event.block.location.y, event.block.location.z);
|
||||
this.waitingForPoint2 = true;
|
||||
world.sendMessage(`Select a second point`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DrawLine(pos1: Vector3, pos2: Vector3, color: PaletteColor): void {
|
||||
if (pos1 != null && pos2 != null) {
|
||||
//draw a line with particles
|
||||
const xStep = pos2.x - pos1.x;
|
||||
const yStep = pos2.y - pos1.y;
|
||||
const zStep = pos2.z - pos1.z;
|
||||
|
||||
const steps = Math.max(Math.abs(xStep), Math.abs(yStep), Math.abs(zStep));
|
||||
for (let i = 0; i <= steps; i++) {
|
||||
const x = pos1.x + (xStep / steps) * i;
|
||||
const y = pos1.y + (yStep / steps) * i;
|
||||
const z = pos1.z + (zStep / steps) * i;
|
||||
|
||||
//make the ends and starts a different color
|
||||
let map = new MolangVariableMap();
|
||||
if (i == 0 || i == steps) {
|
||||
map.setColorRGB("variable.color", { red: 0, green: 255, blue: 0 });
|
||||
const particleData: MolangVariableMap = new MolangVariableMap();
|
||||
particleData.setColorRGB("variable.color", {
|
||||
red: 0,
|
||||
green: 1,
|
||||
blue: 0,
|
||||
});
|
||||
spawnParticle(vector3(x, y + 0.1, z), "codecosmos:point", particleData);
|
||||
} else {
|
||||
map.setColorRGB("variable.color", { red: 0, green: 255, blue: 0 });
|
||||
const particleData: MolangVariableMap = new MolangVariableMap();
|
||||
particleData.setColorRGB("variable.color", {
|
||||
red: 1,
|
||||
green: 1,
|
||||
blue: 1,
|
||||
});
|
||||
spawnParticle(vector3(x, y + 0.1, z), "codecosmos:point", particleData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Update() {
|
||||
let shouldRender = this.mindKeeper.get("ShowTriggers") as boolean;
|
||||
this.manager.GetTriggers().forEach((trigger: Trigger) => {
|
||||
trigger.Update();
|
||||
|
||||
if (shouldRender) {
|
||||
const players = world.getAllPlayers();
|
||||
const triggerCenter = vector3(
|
||||
(trigger.point1.x + trigger.point2.x) / 2,
|
||||
(trigger.point1.y + trigger.point2.y) / 2,
|
||||
(trigger.point1.z + trigger.point2.z) / 2
|
||||
);
|
||||
const distnaces = players.map((player) => {
|
||||
return {
|
||||
player: player,
|
||||
distance: vector3Distance(player.location, triggerCenter),
|
||||
};
|
||||
});
|
||||
|
||||
distnaces.sort((a, b) => a.distance - b.distance);
|
||||
const closestPlayer = distnaces[0].player;
|
||||
const distance = distnaces[0].distance;
|
||||
|
||||
if (distance > 25) return;
|
||||
|
||||
const p1 = trigger.point1;
|
||||
const p2 = vector3(trigger.point1.x, trigger.point2.y, trigger.point1.z);
|
||||
const p3 = vector3(trigger.point2.x, trigger.point1.y, trigger.point1.z);
|
||||
const p4 = vector3(trigger.point2.x, trigger.point2.y, trigger.point1.z);
|
||||
const p5 = vector3(trigger.point1.x, trigger.point1.y, trigger.point2.z);
|
||||
const p6 = vector3(trigger.point1.x, trigger.point2.y, trigger.point2.z);
|
||||
const p7 = vector3(trigger.point2.x, trigger.point1.y, trigger.point2.z);
|
||||
const p8 = trigger.point2;
|
||||
|
||||
//is there a player inside this trigger
|
||||
const color = trigger.IsAnyPlayerInside() ? PaletteColor.Red : PaletteColor.White;
|
||||
this.DrawLine(p1, p2, color);
|
||||
this.DrawLine(p2, p4, color);
|
||||
this.DrawLine(p4, p3, color);
|
||||
this.DrawLine(p3, p1, color);
|
||||
this.DrawLine(p5, p6, color);
|
||||
this.DrawLine(p6, p8, color);
|
||||
this.DrawLine(p8, p7, color);
|
||||
this.DrawLine(p7, p5, color);
|
||||
this.DrawLine(p1, p5, color);
|
||||
this.DrawLine(p2, p6, color);
|
||||
this.DrawLine(p3, p7, color);
|
||||
this.DrawLine(p4, p8, color);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
117
scripts/Commandeer/Trigger/manager.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { ChatSendAfterEvent, ItemUseOnBeforeEvent, Player, system, world } from "@minecraft/server";
|
||||
import { Mindkeeper, StoreType } from "../mindKeeper";
|
||||
import { vector3 } from "../utils/vectorUtils";
|
||||
import { Maker } from "./maker";
|
||||
import { Trigger } from "./trigger";
|
||||
|
||||
export class TriggerEvent {
|
||||
player: Player;
|
||||
trigger: Trigger;
|
||||
|
||||
constructor(player: Player, trigger: Trigger) {
|
||||
this.player = player;
|
||||
this.trigger = trigger;
|
||||
}
|
||||
}
|
||||
|
||||
export type TriggerEventHandler = (event: TriggerEvent) => void;
|
||||
|
||||
export class Manager {
|
||||
private triggers: Trigger[] = [];
|
||||
private functionTriggers: Map<string, TriggerEventHandler> = new Map();
|
||||
private mindKeeper: Mindkeeper;
|
||||
private maker: Maker;
|
||||
|
||||
constructor(mindKeeper: Mindkeeper) {
|
||||
this.mindKeeper = mindKeeper;
|
||||
this.maker = new Maker(mindKeeper, this);
|
||||
}
|
||||
|
||||
RegisterStores() {
|
||||
this.mindKeeper.registerStore("triggers", StoreType.string);
|
||||
this.mindKeeper.registerStore("ShowTriggers", StoreType.boolean);
|
||||
}
|
||||
|
||||
OnItemUse(event: ItemUseOnBeforeEvent) {
|
||||
this.maker.OnItemUse(event);
|
||||
}
|
||||
|
||||
OnChat(event: ChatSendAfterEvent) {
|
||||
this.maker.OnChat(event);
|
||||
}
|
||||
//the func should have a TriggerEvent as a parameter
|
||||
RegisterFunctionTrigger(name: string, func: TriggerEventHandler) {
|
||||
this.functionTriggers.set(name, func);
|
||||
}
|
||||
|
||||
//#region Loading / Saving
|
||||
|
||||
Load() {
|
||||
this.LoadTriggers();
|
||||
}
|
||||
|
||||
Save() {
|
||||
this.SaveTriggers();
|
||||
}
|
||||
|
||||
private LoadTriggers() {
|
||||
const triggers = this.mindKeeper.get("triggers") as string;
|
||||
if (triggers === undefined) return;
|
||||
|
||||
const data = JSON.parse(triggers);
|
||||
data.forEach((trigger: any) => {
|
||||
let point1 = vector3(trigger.point1.x, trigger.point1.y, trigger.point1.z);
|
||||
let point2 = vector3(trigger.point2.x, trigger.point2.y, trigger.point2.z);
|
||||
let eventToDispatch = trigger.eventToDispatch;
|
||||
|
||||
let newTrigger = new Trigger(point1, point2);
|
||||
newTrigger.eventToDispatch = eventToDispatch;
|
||||
|
||||
this.triggers.push(newTrigger);
|
||||
});
|
||||
}
|
||||
|
||||
private SaveTriggers() {
|
||||
this.mindKeeper.set("triggers", JSON.stringify(this.triggers));
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
AddTrigger(trigger: Trigger) {
|
||||
this.triggers.push(trigger);
|
||||
}
|
||||
|
||||
GetCurrentActiveTriggers(): Trigger[] {
|
||||
return this.triggers.filter((trigger) => trigger.IsAnyPlayerInside());
|
||||
}
|
||||
|
||||
Update() {
|
||||
const players = world.getAllPlayers();
|
||||
|
||||
this.maker.Update();
|
||||
this.triggers.forEach((trigger: Trigger) => {
|
||||
trigger.Update();
|
||||
|
||||
players.forEach((player) => {
|
||||
// player.sendMessage(`Player ${player.name} is in trigger ${trigger.IsPlayerInside(player)}`);
|
||||
if (trigger.hasPlayerEnterdTrigger(player)) {
|
||||
world.sendMessage(`Player ${player.name} entered trigger`);
|
||||
//Check if a function trigger is set
|
||||
const isFunctionSet = this.functionTriggers.has(trigger.eventToDispatch);
|
||||
|
||||
if (isFunctionSet) {
|
||||
const event = new TriggerEvent(player, trigger);
|
||||
|
||||
this.functionTriggers.get(trigger.eventToDispatch)!(event);
|
||||
} else {
|
||||
world.sendMessage(`Triggered ${trigger.eventToDispatch}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
GetTriggers(): Trigger[] {
|
||||
return this.triggers;
|
||||
}
|
||||
}
|
||||
82
scripts/Commandeer/Trigger/trigger.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { Player, Vector3, world } from "@minecraft/server";
|
||||
import { vector3 } from "../utils/vectorUtils";
|
||||
|
||||
export class Trigger {
|
||||
point1: Vector3 = vector3(0, 0, 0);
|
||||
point2: Vector3 = vector3(0, 0, 0);
|
||||
eventToDispatch: string = "";
|
||||
|
||||
isPlayerInTrigger: Map<string, boolean> = new Map();
|
||||
|
||||
hasTriggerd: boolean = false;
|
||||
|
||||
constructor(point1: Vector3, point2: Vector3) {
|
||||
this.point1 = point1;
|
||||
this.point2 = point2;
|
||||
}
|
||||
|
||||
hasPlayerEnterdTrigger(player: Player): boolean {
|
||||
const minX = Math.min(this.point1.x, this.point2.x);
|
||||
const maxX = Math.max(this.point1.x, this.point2.x);
|
||||
const minY = Math.min(this.point1.y, this.point2.y);
|
||||
const maxY = Math.max(this.point1.y, this.point2.y);
|
||||
const minZ = Math.min(this.point1.z, this.point2.z);
|
||||
const maxZ = Math.max(this.point1.z, this.point2.z);
|
||||
|
||||
const playerPos = player.location;
|
||||
|
||||
const inside =
|
||||
playerPos.x >= minX &&
|
||||
playerPos.x <= maxX &&
|
||||
playerPos.y >= minY &&
|
||||
playerPos.y + 1 <= maxY &&
|
||||
playerPos.z >= minZ &&
|
||||
playerPos.z <= maxZ;
|
||||
|
||||
let entererdTrigger = false;
|
||||
if (!this.isPlayerInTrigger.get(player.name) && inside) {
|
||||
entererdTrigger = true;
|
||||
}
|
||||
|
||||
this.isPlayerInTrigger.set(player.name, inside);
|
||||
|
||||
return entererdTrigger;
|
||||
}
|
||||
|
||||
IsPlayerInside(player: Player): boolean {
|
||||
return this.isPlayerInTrigger.get(player.name) || false;
|
||||
}
|
||||
|
||||
IsAnyPlayerInside(): boolean {
|
||||
let isInside = false;
|
||||
world.getAllPlayers().forEach((player) => {
|
||||
if (this.isPlayerInTrigger.get(player.name)) {
|
||||
isInside = true;
|
||||
}
|
||||
});
|
||||
return isInside;
|
||||
}
|
||||
|
||||
ShouldTrigger(): boolean {
|
||||
let isSomethingInTrigger = false;
|
||||
const players = world.getAllPlayers();
|
||||
players.forEach((player) => {
|
||||
if (this.hasPlayerEnterdTrigger(player)) {
|
||||
isSomethingInTrigger = true;
|
||||
}
|
||||
});
|
||||
return isSomethingInTrigger;
|
||||
}
|
||||
|
||||
Update() {
|
||||
world
|
||||
.getDimension("overworld")
|
||||
.getEntities({ type: "minecraft:player" })
|
||||
.forEach((player) => {
|
||||
//Check if the distance between the player and the trigger is less than the width of the trigger
|
||||
// if (this.hasPlayerEnterdTrigger(player.location)) {
|
||||
// world.sendMessage(`Player ${player.nameTag} is in trigger`);
|
||||
// }
|
||||
});
|
||||
}
|
||||
}
|
||||
70
scripts/Commandeer/chalk.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
class Chalk {
|
||||
static red(text: string): string {
|
||||
return "§c" + text + "§r";
|
||||
}
|
||||
static yellow(text: string): string {
|
||||
return "§e" + text + "§r";
|
||||
}
|
||||
static green(text: string): string {
|
||||
return "§a" + text + "§r";
|
||||
}
|
||||
static blue(text: string): string {
|
||||
return "§9" + text + "§r";
|
||||
}
|
||||
static aqua(text: string): string {
|
||||
return "§b" + text + "§r";
|
||||
}
|
||||
static white(text: string): string {
|
||||
return "§f" + text + "§r";
|
||||
}
|
||||
static black(text: string): string {
|
||||
return "§0" + text + "§r";
|
||||
}
|
||||
static gold(text: string): string {
|
||||
return "§6" + text + "§r";
|
||||
}
|
||||
static gray(text: string): string {
|
||||
return "§7" + text + "§r";
|
||||
}
|
||||
static darkRed(text: string): string {
|
||||
return "§4" + text + "§r";
|
||||
}
|
||||
static darkGreen(text: string): string {
|
||||
return "§2" + text + "§r";
|
||||
}
|
||||
static darkBlue(text: string): string {
|
||||
return "§1" + text + "§r";
|
||||
}
|
||||
static darkAqua(text: string): string {
|
||||
return "§3" + text + "§r";
|
||||
}
|
||||
static darkPurple(text: string): string {
|
||||
return "§5" + text + "§r";
|
||||
}
|
||||
static darkGray(text: string): string {
|
||||
return "§8" + text + "§r";
|
||||
}
|
||||
static lightPurple(text: string): string {
|
||||
return "§d" + text + "§r";
|
||||
}
|
||||
static bold(text: string): string {
|
||||
return "§l" + text + "§r";
|
||||
}
|
||||
static italic(text: string): string {
|
||||
return "§o" + text + "§r";
|
||||
}
|
||||
static underline(text: string): string {
|
||||
return "§n" + text + "§r";
|
||||
}
|
||||
static strikethrough(text: string): string {
|
||||
return "§m" + text + "§r";
|
||||
}
|
||||
static obfuscated(text: string): string {
|
||||
return "§k" + text + "§r";
|
||||
}
|
||||
static reset(text: string): string {
|
||||
return "§r" + text + "§r";
|
||||
}
|
||||
}
|
||||
|
||||
export default Chalk;
|
||||
99
scripts/Commandeer/command/command.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { CommandResult, Dimension, Entity, world, Player } from "@minecraft/server";
|
||||
|
||||
export class Command {
|
||||
private __player: Player;
|
||||
public argv: IterableIterator<string>;
|
||||
public get player(): Player {
|
||||
return this.__player;
|
||||
}
|
||||
public get argv0(): string {
|
||||
return this.argv.next().value;
|
||||
}
|
||||
constructor(argv: string[], player: Player) {
|
||||
this.argv = (function* () {
|
||||
for (let arg of argv) yield arg;
|
||||
})();
|
||||
this.__player = player;
|
||||
}
|
||||
}
|
||||
|
||||
export class Commands {
|
||||
/**
|
||||
* @remarks
|
||||
* Runs a particular command synchronously from the context.
|
||||
* @param commandString
|
||||
* Command to run. Note that command strings should not start
|
||||
* with slash.
|
||||
* @param target
|
||||
* Target to be used as context for the command to run
|
||||
* within.
|
||||
* @returns
|
||||
* For commands that return data, returns a CommandResult with
|
||||
* an indicator of command results.
|
||||
* @throws This function can throw errors.
|
||||
*/
|
||||
static run(commandString: string, target: Dimension | Entity = world.getDimension("overworld")): CommandResult {
|
||||
if (target instanceof Dimension || Entity) return target.runCommand(commandString);
|
||||
else throw TypeError("Native type conversion failed");
|
||||
}
|
||||
/**
|
||||
* @remarks
|
||||
* Runs a particular command asynchronously from the context.
|
||||
* Where possible - and especially for
|
||||
* long-running operations - you should use runCommandAsync
|
||||
* over runCommand.
|
||||
* @param commandString
|
||||
* Command to run. Note that command strings should not start
|
||||
* with slash.
|
||||
* @param target
|
||||
* Target to be used as context for the command to run
|
||||
* within.
|
||||
* @returns
|
||||
* For commands that return data, returns a CommandResult with
|
||||
* an indicator of command results.
|
||||
* @throws This function can throw errors.
|
||||
*/
|
||||
static async runAsync(
|
||||
commandString: string,
|
||||
target: Dimension | Entity = world.getDimension("overworld")
|
||||
): Promise<CommandResult> {
|
||||
if (target instanceof Dimension || Entity) return await target.runCommandAsync(commandString);
|
||||
else throw TypeError("Native type conversion failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* @remarks
|
||||
* Registers a new custom command. This command will become
|
||||
* available in Minecraft via [prefix][command].
|
||||
* @param prefix
|
||||
* The prefix of this specific command. (Case sensitive)
|
||||
* @param command
|
||||
* Name of this specific command. (Case sensitive)
|
||||
* @param commandFunction
|
||||
* Implementation of the command function.
|
||||
* @throws
|
||||
* This function can throw error: You are not allow to register a new slash command.
|
||||
* @example example1.js
|
||||
* ```typescript
|
||||
* Commands.register("!", "test", function (arg) {
|
||||
* arg.player.runCommandAsync(`say ${arg.argv0} ${JSON.stringify([...arg.argv])}`);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
public static register(prefix: string, command: string, commandFunction: (arg: Command) => void): void {
|
||||
if (prefix.startsWith("/")) throw Error("Unable to register slash commands.");
|
||||
world.beforeEvents.chatSend.subscribe((arg) => {
|
||||
var argv = arg.message.split(/(".*?"|[^"\s]+)+(?=\s*|\s*$)/g).filter((e) => e.trim().length > 0);
|
||||
if (argv[0] === `${prefix}${command}`) {
|
||||
arg.cancel = true;
|
||||
try {
|
||||
commandFunction(new Command(argv, arg.sender));
|
||||
} catch (err) {
|
||||
let { statusMessage } = JSON.parse(err as string);
|
||||
console.error(err);
|
||||
arg.sender.sendMessage(`§c${statusMessage}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
abstract class AbstractLevelCondition {
|
||||
constructor() {}
|
||||
|
||||
abstract checkCondition(): boolean;
|
||||
}
|
||||
|
||||
export default AbstractLevelCondition;
|
||||
|
||||
//Interface could be better
|
||||
24
scripts/Commandeer/completionCondition/BlockCondition.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { BlockType, Vector3, world } from "@minecraft/server";
|
||||
import AbstractLevelCondition from "./AbstractCondition";
|
||||
import { Vector3ToString } from "../utils/vectorUtils";
|
||||
|
||||
class BlockCondition extends AbstractLevelCondition {
|
||||
position: Vector3;
|
||||
blockType: BlockType;
|
||||
|
||||
constructor(position: Vector3, blockType: BlockType) {
|
||||
super();
|
||||
this.position = position;
|
||||
this.blockType = blockType;
|
||||
}
|
||||
|
||||
checkCondition(): boolean {
|
||||
const block = world.getDimension("overworld").getBlock(this.position);
|
||||
if (!block) {
|
||||
return false;
|
||||
}
|
||||
return block.typeId === this.blockType.id;
|
||||
}
|
||||
}
|
||||
|
||||
export default BlockCondition;
|
||||
@@ -0,0 +1,21 @@
|
||||
import { BlockType, Vector3, world } from "@minecraft/server";
|
||||
import AbstractLevelCondition from "./AbstractCondition";
|
||||
|
||||
class ButtonPushCondition extends AbstractLevelCondition {
|
||||
position: Vector3;
|
||||
|
||||
constructor(position: Vector3) {
|
||||
super();
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
checkCondition(): boolean {
|
||||
const button = world.getDimension("overworld").getBlock(this.position);
|
||||
if (!button || !button.getRedstonePower()) {
|
||||
return false;
|
||||
}
|
||||
return button.getRedstonePower()! > 0;
|
||||
}
|
||||
}
|
||||
|
||||
export default ButtonPushCondition;
|
||||
52
scripts/Commandeer/level/level.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { World } from "@minecraft/server";
|
||||
|
||||
class Level {
|
||||
levelCompleteCallback: Function;
|
||||
levelCheckCallback: Function;
|
||||
levelSetupCallback: Function;
|
||||
levelUpdateCallback: Function;
|
||||
levelResetCallback: Function;
|
||||
isCompleted: boolean = false;
|
||||
isSetup: boolean = false;
|
||||
|
||||
constructor(
|
||||
levelSetupCallback: Function,
|
||||
levelUpdateCallback: Function,
|
||||
levelCompleteCallback: Function,
|
||||
levelCheckCallback: Function,
|
||||
levelResetCallback: Function = () => {}
|
||||
) {
|
||||
this.levelSetupCallback = levelSetupCallback;
|
||||
this.levelCompleteCallback = levelCompleteCallback;
|
||||
this.levelCheckCallback = levelCheckCallback;
|
||||
this.levelUpdateCallback = levelUpdateCallback;
|
||||
this.levelResetCallback = levelResetCallback;
|
||||
}
|
||||
|
||||
setup() {
|
||||
this.levelSetupCallback();
|
||||
}
|
||||
|
||||
update() {
|
||||
if (!this.isSetup) {
|
||||
this.setup();
|
||||
this.isSetup = true;
|
||||
}
|
||||
this.levelUpdateCallback();
|
||||
if (this.levelCheckCallback() && !this.isCompleted) {
|
||||
this.levelCompleteCallback();
|
||||
this.isCompleted = true;
|
||||
}
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.levelResetCallback();
|
||||
this.isCompleted = false;
|
||||
}
|
||||
}
|
||||
|
||||
//nextlevel
|
||||
//mindkeeper
|
||||
//pupeteer
|
||||
|
||||
export default Level;
|
||||
44
scripts/Commandeer/level/levelTypes.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { BlockType, Vector3, World } from "@minecraft/server";
|
||||
|
||||
export type blockCondition = {
|
||||
block: string;
|
||||
position: Vector3;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if there is a lever at the specified position in the world.
|
||||
*
|
||||
* @param world - The world object.
|
||||
* @param position - The position of the lever.
|
||||
* @returns Returns true if there is a lever at the specified position and it has a redstone power of 15, otherwise returns false.
|
||||
* @throws Throws an error if there is no lever at the specified position.
|
||||
*/
|
||||
export function leverOn(world: World, position: Vector3): boolean {
|
||||
let lever = world.getDimension("overworld").getBlock(position);
|
||||
if (!(lever?.typeId == "minecraft:lever")) {
|
||||
throw new Error(`No lever at ${position}`);
|
||||
}
|
||||
return lever.getRedstonePower() == 15;
|
||||
}
|
||||
|
||||
export type LeverCondition = {
|
||||
position: Vector3;
|
||||
state: boolean;
|
||||
};
|
||||
|
||||
export type LevelBlockCondition = {
|
||||
conditions: blockCondition[];
|
||||
};
|
||||
|
||||
export type LevelLeverCondition = {
|
||||
conditions: LeverCondition[];
|
||||
};
|
||||
|
||||
export type AgentNoGoZone = {
|
||||
//Reason for needing to use is because the Agent can't be queried for its location in minecraft
|
||||
position: Vector3;
|
||||
};
|
||||
|
||||
export type LevelNoGoZone = {
|
||||
zones: AgentNoGoZone[];
|
||||
};
|
||||
230
scripts/Commandeer/mindKeeper.ts
Normal file
@@ -0,0 +1,230 @@
|
||||
import { ChatSendAfterEvent, Vector3, World, system } from "@minecraft/server";
|
||||
|
||||
class Store {
|
||||
type: StoreType;
|
||||
name: string;
|
||||
|
||||
constructor(type: StoreType, name: string) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
getType(): StoreType {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
getName(): string {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
enum StoreType {
|
||||
string = "string",
|
||||
number = "number",
|
||||
boolean = "boolean",
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a Mindkeeper, responsible for managing stores and dynamic properties in a world.
|
||||
*/
|
||||
class Mindkeeper {
|
||||
registerdStores: Array<Store> = [];
|
||||
// propertyManager = new DynamicPropertiesDefinition();
|
||||
world: World;
|
||||
initialised: boolean = false;
|
||||
debugLog: string[] = [];
|
||||
|
||||
/**
|
||||
* Creates a new instance of Mindkeeper.
|
||||
* @param world The world associated with the Mindkeeper.
|
||||
*/
|
||||
constructor(world: World) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a store with the specified name and type.
|
||||
* @param store The name of the store.
|
||||
* @param type The type of the store.
|
||||
*/
|
||||
registerStore(store: string, type: StoreType): void {
|
||||
this.registerdStores.push(new Store(type, store));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of registered stores.
|
||||
* @returns An array of registered stores.
|
||||
*/
|
||||
getStores() {
|
||||
return this.registerdStores;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the debug log by sending each log entry as a message to the world.
|
||||
*/
|
||||
printDebug() {
|
||||
this.debugLog.forEach((t) => {
|
||||
this.world.sendMessage(t);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the dynamic properties to the world's property registry.
|
||||
* @param propertyRegistry The property registry of the world.
|
||||
*/
|
||||
registerToWorld() {
|
||||
for (let i = 0; i < this.registerdStores.length; i++) {
|
||||
let isAlreadyDefined = true;
|
||||
|
||||
try {
|
||||
let test = this.world.getDynamicProperty(this.registerdStores[i].getName());
|
||||
if (test === undefined) {
|
||||
isAlreadyDefined = false;
|
||||
}
|
||||
} catch (e) {
|
||||
isAlreadyDefined = false;
|
||||
}
|
||||
if (isAlreadyDefined) {
|
||||
continue;
|
||||
}
|
||||
switch (this.registerdStores[i].getType()) {
|
||||
case StoreType.string:
|
||||
this.world.setDynamicProperty(this.registerdStores[i].getName(), "");
|
||||
this.debugLog.push("registerd string" + this.registerdStores[i].getName());
|
||||
break;
|
||||
case StoreType.number:
|
||||
this.world.setDynamicProperty(this.registerdStores[i].getName(), 0);
|
||||
this.debugLog.push("registerd number" + this.registerdStores[i].getName());
|
||||
break;
|
||||
case StoreType.boolean:
|
||||
this.world.setDynamicProperty(this.registerdStores[i].getName(), false);
|
||||
this.debugLog.push("registerd boolean" + this.registerdStores[i].getName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.initialised = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a store.
|
||||
* @param store The name of the store.
|
||||
* @param value The value to set.
|
||||
*/
|
||||
set(store: string, value: string | number | boolean | Vector3): void {
|
||||
if (this.registerdStores.find((s) => s.getName() === store)?.getType() != typeof value) {
|
||||
this.world.sendMessage(`Store ${store} is not of type ${typeof value}`);
|
||||
return;
|
||||
}
|
||||
system.run(() => {
|
||||
this.world.setDynamicProperty(store, value);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the value of a store.
|
||||
* @param store The name of the store.
|
||||
* @returns The value of the store, or undefined if the store is not defined.
|
||||
*/
|
||||
get(store: string): string | number | boolean | Vector3 | undefined {
|
||||
try {
|
||||
let data = this.world.getDynamicProperty(store);
|
||||
if (data === undefined) {
|
||||
this.world.sendMessage(`Store ${store} is not defined`);
|
||||
return undefined;
|
||||
}
|
||||
return data;
|
||||
} catch (e) {
|
||||
// this.world.sendMessage(`Store ${store} is not defined`);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the value of a store if it is a number.
|
||||
* @param store The name of the store.
|
||||
*/
|
||||
increment(store: string): void {
|
||||
let data = this.get(store);
|
||||
if (typeof data === "number") {
|
||||
this.set(store, data + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles chat commands by executing the corresponding actions.
|
||||
* @param event The chat send after event.
|
||||
*/
|
||||
private secondWarning = false;
|
||||
chatCommands(event: ChatSendAfterEvent) {
|
||||
const command = event.message.split(" ")[0];
|
||||
const args = event.message.split(" ").slice(1);
|
||||
|
||||
if (command === "!get") {
|
||||
const store = event.message.split(" ")[1];
|
||||
const value = this.get(store);
|
||||
this.world.sendMessage(`Value of ${store} is ${value}`);
|
||||
}
|
||||
if (command === "!set") {
|
||||
const store = event.message.split(" ")[1];
|
||||
if (store === undefined) {
|
||||
this.world.sendMessage(`Please provide a store to set`);
|
||||
return;
|
||||
}
|
||||
const value = event.message.split(" ")[2];
|
||||
if (value === undefined) {
|
||||
this.world.sendMessage(`Please provide a value to set for ${store}`);
|
||||
return;
|
||||
}
|
||||
const type = event.message.split(" ")[3];
|
||||
|
||||
let actualType = this.getStores()
|
||||
.find((s) => s.getName() === store)
|
||||
?.getType();
|
||||
|
||||
if (actualType === undefined) {
|
||||
this.world.sendMessage(`Store ${store} is not defined`);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (actualType) {
|
||||
case StoreType.string:
|
||||
this.set(store, String(value));
|
||||
break;
|
||||
case StoreType.number:
|
||||
if (isNaN(Number(value))) {
|
||||
this.world.sendMessage(`Can't parse ${value} as a number`);
|
||||
return;
|
||||
}
|
||||
this.set(store, Number(value));
|
||||
break;
|
||||
case StoreType.boolean:
|
||||
const ActualValue = value.toLowerCase();
|
||||
this.set(store, ActualValue === "true");
|
||||
break;
|
||||
}
|
||||
this.world.sendMessage(`Value of ${store} is ${value}`);
|
||||
}
|
||||
if (event.message.startsWith("!listStores")) {
|
||||
this.getStores().forEach((store) => {
|
||||
this.world.sendMessage(`${store.getName()} is ${store.getType()}`);
|
||||
});
|
||||
}
|
||||
if (command === "!deleteStores") {
|
||||
this.world.sendMessage("ARE YOU SURE YOU WANT TO DELETE ALL STORES? THIS COULD CAUSE ISSUES");
|
||||
this.world.sendMessage("If you are sure, type !deleteStoresConfirm");
|
||||
this.secondWarning = true;
|
||||
}
|
||||
if (this.secondWarning) {
|
||||
if (command === "!deleteStoresConfirm") {
|
||||
this.getStores().forEach((store) => {
|
||||
this.world.sendMessage(`Deleting ${store.getName()}`);
|
||||
this.world.sendMessage("This feature no longer works, thanks minecraft ");
|
||||
// this.world.dynami(store.getName());
|
||||
});
|
||||
this.secondWarning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { Mindkeeper, Store, StoreType };
|
||||
16
scripts/Commandeer/nextLevel.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
class NextLevel {
|
||||
currentState = 0;
|
||||
states: Array<Function> = [];
|
||||
|
||||
constructor(states: Array<Function>) {
|
||||
this.states = states;
|
||||
}
|
||||
|
||||
update() {
|
||||
this.states[this.currentState]();
|
||||
}
|
||||
|
||||
next() {
|
||||
this.currentState++;
|
||||
}
|
||||
}
|
||||
112
scripts/Commandeer/pupeteer.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import {
|
||||
EntityInventoryComponent,
|
||||
ItemStack,
|
||||
Player,
|
||||
RawText,
|
||||
TicksPerSecond,
|
||||
TitleDisplayOptions,
|
||||
Vector3,
|
||||
World,
|
||||
system,
|
||||
world,
|
||||
} from "@minecraft/server";
|
||||
import { delayedRun } from "./utils/waitUtil";
|
||||
|
||||
class Pupeteer {
|
||||
private static getActualString(message: string): string | RawText {
|
||||
if (message.startsWith("%")) {
|
||||
const key = message.substring(1);
|
||||
return { rawtext: [{ translate: key }] };
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
static setActionBarTimed(message: string, duration: number): void {
|
||||
world.getPlayers().forEach((player) => {
|
||||
system.run(() => {
|
||||
player.onScreenDisplay.setActionBar(this.getActualString(message));
|
||||
});
|
||||
});
|
||||
delayedRun(() => {
|
||||
this.clearActionBar();
|
||||
}, duration * TicksPerSecond);
|
||||
}
|
||||
|
||||
static setActionBar(message: string): void {
|
||||
world.getPlayers().forEach((player) => {
|
||||
system.run(() => {
|
||||
player.onScreenDisplay.setActionBar(this.getActualString(message));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static sendWorldMessage(message: string): void {
|
||||
world.sendMessage(this.getActualString(message));
|
||||
}
|
||||
|
||||
static setTitleTimed(message: string, duration: number): void {
|
||||
world.getPlayers().forEach((player) => {
|
||||
let options: TitleDisplayOptions = {
|
||||
fadeInDuration: 20,
|
||||
fadeOutDuration: 20,
|
||||
stayDuration: duration * TicksPerSecond,
|
||||
};
|
||||
player.onScreenDisplay.setTitle(this.getActualString(message), options);
|
||||
});
|
||||
}
|
||||
|
||||
static setTitle(message: string): void {
|
||||
world.getPlayers().forEach((player) => {
|
||||
player.onScreenDisplay.setTitle(message);
|
||||
});
|
||||
}
|
||||
|
||||
static updateSubtitle(message: string): void {
|
||||
world.getPlayers().forEach((player) => {
|
||||
player.onScreenDisplay.updateSubtitle(this.getActualString(message));
|
||||
});
|
||||
}
|
||||
|
||||
static clearTitle(): void {
|
||||
world.getPlayers().forEach((player) => {
|
||||
player.onScreenDisplay.setTitle("");
|
||||
});
|
||||
}
|
||||
|
||||
static clearSubtitle(): void {
|
||||
world.getPlayers().forEach((player) => {
|
||||
player.onScreenDisplay.updateSubtitle("");
|
||||
});
|
||||
}
|
||||
|
||||
static clearActionBar(): void {
|
||||
world.getPlayers().forEach((player) => {
|
||||
player.onScreenDisplay.setActionBar("");
|
||||
});
|
||||
}
|
||||
|
||||
static testForLocation(location: Vector3, radius: number): boolean {
|
||||
let isPlayerInArea = false;
|
||||
world.getPlayers().forEach((player) => {
|
||||
let dx = location.x - player.location.x;
|
||||
let dy = location.y - player.location.y;
|
||||
let dz = location.z - player.location.z;
|
||||
|
||||
let distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||
if (distance < radius) {
|
||||
isPlayerInArea = true;
|
||||
}
|
||||
});
|
||||
return isPlayerInArea;
|
||||
}
|
||||
|
||||
static setNpcText(npcTag: string, sceneName: string) {
|
||||
world.getDimension("overworld").runCommand(`/dialogue change @e[tag=${npcTag}] ${sceneName} @a`);
|
||||
}
|
||||
|
||||
static givePlayerItem(player: Player, item: ItemStack) {
|
||||
(player.getComponent("inventory") as EntityInventoryComponent).container!.addItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
export default Pupeteer;
|
||||
85
scripts/Commandeer/trail/trailEngine.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { MolangVariableMap, Vector3, world } from "@minecraft/server";
|
||||
import { Vector3Add } from "../utils/vectorUtils";
|
||||
import { TrailType } from "./trailTypes";
|
||||
|
||||
class TrailPoint {
|
||||
postion: Vector3;
|
||||
index: number;
|
||||
|
||||
constructor(position: Vector3, index: number) {
|
||||
this.postion = position;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
spawn() {
|
||||
// let spawnPosition: Vector3 = Vector3Add(this.postion, { x: 0.5, y: 0.5, z: 0.5 });
|
||||
let spawnPosition: Vector3 = this.postion;
|
||||
try {
|
||||
world
|
||||
.getDimension("overworld")
|
||||
.spawnParticle("minecraft:balloon_gas_particle", spawnPosition, new MolangVariableMap());
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
class Trail {
|
||||
id: string;
|
||||
points: TrailPoint[] = [];
|
||||
currentPoint: number = 0;
|
||||
wrapIndex: number = 0;
|
||||
nextParticleTimer: number = 0;
|
||||
currentParticleCounter: number = 0;
|
||||
|
||||
calculatedLength: number = 0;
|
||||
constructor(id: string, nextParticleTimer: number = 5, wrapIndex: number = 0) {
|
||||
this.id = id;
|
||||
this.nextParticleTimer = nextParticleTimer;
|
||||
this.wrapIndex = wrapIndex;
|
||||
}
|
||||
|
||||
addPoint(point: TrailPoint) {
|
||||
this.points.push(point);
|
||||
|
||||
//this could be a one liner,
|
||||
let maxlength: number = 0;
|
||||
this.points.forEach((point) => {
|
||||
if (point.index > maxlength) {
|
||||
maxlength = point.index;
|
||||
}
|
||||
});
|
||||
this.calculatedLength = maxlength;
|
||||
}
|
||||
|
||||
fromTrail(trail: TrailType) {
|
||||
trail.points.forEach((point) => {
|
||||
this.addPoint(new TrailPoint(point.position, point.index));
|
||||
});
|
||||
}
|
||||
|
||||
spawnNext() {
|
||||
if (this.currentParticleCounter >= this.nextParticleTimer) {
|
||||
this.currentParticleCounter = 0;
|
||||
//wrapindex is in how many segments the trail is divided into
|
||||
let pointsPerInterval = this.wrapIndex > 0 ? this.calculatedLength / this.wrapIndex : 0;
|
||||
this.points
|
||||
.filter((point) => {
|
||||
return (
|
||||
point.index === this.currentPoint ||
|
||||
(this.wrapIndex > 0 && point.index % pointsPerInterval === this.currentPoint)
|
||||
);
|
||||
})
|
||||
.forEach((point) => {
|
||||
point.spawn();
|
||||
});
|
||||
|
||||
this.currentPoint++;
|
||||
if (this.currentPoint >= this.calculatedLength) {
|
||||
this.currentPoint = 0;
|
||||
}
|
||||
} else {
|
||||
this.currentParticleCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { Trail, TrailPoint };
|
||||
212
scripts/Commandeer/trail/trailMaker.ts
Normal file
@@ -0,0 +1,212 @@
|
||||
import {
|
||||
Block,
|
||||
ChatSendAfterEvent,
|
||||
EntityInventoryComponent,
|
||||
ItemStack,
|
||||
ItemUseOnBeforeEvent,
|
||||
MolangVariableMap,
|
||||
Player,
|
||||
world,
|
||||
} from "@minecraft/server";
|
||||
import { Vector3 } from "@minecraft/server";
|
||||
import { Vector3Add, Vector3ToString, vector3 } from "../utils/vectorUtils";
|
||||
import { spawnParticle } from "../utils/particleUtils";
|
||||
import Pupeteer from "../pupeteer";
|
||||
import Chalk from "../chalk";
|
||||
|
||||
export namespace TrailMaker {
|
||||
export class Maker {
|
||||
currentTrail: Trail;
|
||||
log: Map<string, number> = new Map();
|
||||
selectedIndex: number = 0;
|
||||
|
||||
//Line
|
||||
point1: Vector3 = vector3(0, 0, 0);
|
||||
point2: Vector3 = vector3(0, 0, 0);
|
||||
|
||||
waitingForPoint2: boolean = false;
|
||||
|
||||
OnChat(event: ChatSendAfterEvent) {
|
||||
if (event.message == "!trailWand") {
|
||||
let item: ItemStack = new ItemStack("minecraft:stick");
|
||||
item.nameTag = "AddPoint";
|
||||
Pupeteer.givePlayerItem(event.sender as Player, item);
|
||||
world.sendMessage("Thou shall have the Trailing Powah");
|
||||
}
|
||||
if (event.message == "!trailDeleteWand") {
|
||||
let item: ItemStack = new ItemStack("minecraft:stick");
|
||||
item.nameTag = "DeletePoint";
|
||||
Pupeteer.givePlayerItem(event.sender as Player, item);
|
||||
world.sendMessage("Luke, i'm NOT your father");
|
||||
}
|
||||
if (event.message == "!trailLineWand") {
|
||||
let item: ItemStack = new ItemStack("minecraft:stick");
|
||||
item.nameTag = "AddLine";
|
||||
Pupeteer.givePlayerItem(event.sender as Player, item);
|
||||
world.sendMessage(`This is where i draw the ${Chalk.red("Line")} >:(`);
|
||||
}
|
||||
if (event.message == "!trailExport") {
|
||||
this.Export();
|
||||
}
|
||||
}
|
||||
OnItemUse(event: ItemUseOnBeforeEvent) {
|
||||
const currentItemHeld: ItemStack = event.itemStack;
|
||||
const blockInteracted: Block = event.block;
|
||||
const player: Player = event.source as Player;
|
||||
const oldLog = this.log.get(player.name)!;
|
||||
this.log.set(player.name, Date.now());
|
||||
if (oldLog + 150 >= Date.now()) return;
|
||||
|
||||
if (event.itemStack.typeId == "minecraft:stick" && event.itemStack.nameTag == "AddPoint") {
|
||||
let block = event.block;
|
||||
let pos = this.BlockToParticlePosition(block);
|
||||
world.sendMessage(`Added Point ${Vector3ToString(pos)}`);
|
||||
this.currentTrail.points.push(new Point(pos, this.currentTrail.currentPoint));
|
||||
|
||||
this.currentTrail.currentPoint++;
|
||||
Pupeteer.setActionBarTimed(`Added point ${this.currentTrail.currentPoint}`, 3);
|
||||
}
|
||||
|
||||
if (event.itemStack.typeId == "minecraft:stick" && event.itemStack.nameTag == "DeletePoint") {
|
||||
let block = event.block;
|
||||
let pos = this.BlockToParticlePosition(block);
|
||||
|
||||
let point = this.currentTrail.points.find((point) => Vector3ToString(point.position) == Vector3ToString(pos));
|
||||
if (point) {
|
||||
this.currentTrail.points.splice(this.currentTrail.points.indexOf(point), 1);
|
||||
Pupeteer.setActionBarTimed(`Deleted point ${point.index}`, 3);
|
||||
} else {
|
||||
Pupeteer.setActionBarTimed(`No point found`, 3);
|
||||
}
|
||||
}
|
||||
|
||||
if (event.itemStack.typeId == "minecraft:stick" && event.itemStack.nameTag == "AddLine") {
|
||||
world.sendMessage(`Waiting for point 2: ${this.waitingForPoint2}`);
|
||||
if (!this.waitingForPoint2) {
|
||||
// this.point1 = vector3(blockInteracted.location.x, blockInteracted.location.y, blockInteracted.location.z);
|
||||
this.point1 = this.BlockToParticlePosition(blockInteracted);
|
||||
|
||||
this.waitingForPoint2 = true;
|
||||
Pupeteer.setActionBar("Select a second point");
|
||||
world.sendMessage("Select a second point");
|
||||
|
||||
return;
|
||||
} else {
|
||||
this.point2 = this.BlockToParticlePosition(blockInteracted);
|
||||
|
||||
//Calculate the blocks between these 2 points, andd add them to the trail
|
||||
//Assume point1 is the start, and point2 is the end
|
||||
let x1 = this.point1.x;
|
||||
let x2 = this.point2.x;
|
||||
let y1 = this.point1.y;
|
||||
let y2 = this.point2.y;
|
||||
let z1 = this.point1.z;
|
||||
let z2 = this.point2.z;
|
||||
|
||||
//Find out what axis is the movement on, throw an error if it's on more than one axis
|
||||
|
||||
let xDiff = Math.abs(x2 - x1);
|
||||
let yDiff = Math.abs(y2 - y1);
|
||||
let zDiff = Math.abs(z2 - z1);
|
||||
|
||||
let axis = "";
|
||||
|
||||
if (xDiff > 0 && yDiff == 0 && zDiff == 0) {
|
||||
axis = "x";
|
||||
} else if (xDiff == 0 && yDiff > 0 && zDiff == 0) {
|
||||
axis = "y";
|
||||
} else if (xDiff == 0 && yDiff == 0 && zDiff > 0) {
|
||||
axis = "z";
|
||||
} else {
|
||||
Pupeteer.setActionBarTimed("Invalid line", 3);
|
||||
return;
|
||||
}
|
||||
|
||||
let start = 0;
|
||||
let end = 0;
|
||||
|
||||
if (axis == "x") {
|
||||
start = Math.min(x1, x2);
|
||||
end = Math.max(x1, x2);
|
||||
} else if (axis == "y") {
|
||||
start = Math.min(y1, y2);
|
||||
end = Math.max(y1, y2);
|
||||
} else if (axis == "z") {
|
||||
start = Math.min(z1, z2);
|
||||
end = Math.max(z1, z2);
|
||||
}
|
||||
|
||||
for (let i = start; i <= end; i++) {
|
||||
let pos = vector3(0, 0, 0);
|
||||
if (axis == "x") {
|
||||
pos = vector3(i, y1, z1);
|
||||
} else if (axis == "y") {
|
||||
pos = vector3(x1, i, z1);
|
||||
} else if (axis == "z") {
|
||||
pos = vector3(x1, y1, i);
|
||||
}
|
||||
|
||||
this.currentTrail.points.push(new Point(pos, this.currentTrail.currentPoint));
|
||||
this.currentTrail.currentPoint++;
|
||||
}
|
||||
|
||||
this.waitingForPoint2 = false;
|
||||
Pupeteer.setActionBarTimed("Added line", 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Update() {
|
||||
this.currentTrail.points.forEach((point) => {
|
||||
spawnParticle(point.position, "minecraft:balloon_gas_particle", new MolangVariableMap());
|
||||
});
|
||||
}
|
||||
|
||||
Export() {
|
||||
let output = "";
|
||||
for (let i = 0; i < this.currentTrail.points.length; i++) {
|
||||
let point = this.currentTrail.points[i];
|
||||
let actualPos = point.position;
|
||||
output += `{ index: ${point.index}, position: vector3(${actualPos.x}, ${actualPos.y}, ${actualPos.z}) },\n`;
|
||||
}
|
||||
console.warn(output);
|
||||
}
|
||||
|
||||
private BlockToParticlePosition(block: Block): Vector3 {
|
||||
let pos = vector3(block.location.x, block.location.y, block.location.z);
|
||||
pos = Vector3Add(pos, vector3(0.5, 0, 0.5));
|
||||
//If block is a slab or stair, offset by half a block
|
||||
|
||||
let isHalfBlock = block.typeId.includes("slab") || block.typeId.includes("stair");
|
||||
if (isHalfBlock) {
|
||||
pos = Vector3Add(pos, vector3(0, 0.5, 0));
|
||||
} else {
|
||||
pos = Vector3Add(pos, vector3(0, 1.1, 0));
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.currentTrail = new Trail();
|
||||
}
|
||||
}
|
||||
|
||||
class Trail {
|
||||
points: Point[] = [];
|
||||
currentPoint: number = 0;
|
||||
nextParticleTimer: number = 0;
|
||||
currentParticleCounter: number = 0;
|
||||
|
||||
constructor() {}
|
||||
}
|
||||
|
||||
class Point {
|
||||
position: Vector3;
|
||||
index: number;
|
||||
|
||||
constructor(position: Vector3, index: number) {
|
||||
this.position = position;
|
||||
this.index = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
13
scripts/Commandeer/trail/trailTypes.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Vector3 } from "@minecraft/server";
|
||||
|
||||
type TrailPointType = {
|
||||
index: number;
|
||||
position: Vector3;
|
||||
};
|
||||
|
||||
type TrailType = {
|
||||
name: string;
|
||||
points: TrailPointType[];
|
||||
};
|
||||
|
||||
export { TrailPointType, TrailType };
|
||||
40
scripts/Commandeer/utils/agentUtils.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { Entity, Vector3, world } from "@minecraft/server";
|
||||
import { Vector3ToString, vector3 } from "./vectorUtils";
|
||||
import { mindKeeper } from "../../main";
|
||||
function teleportAgent(position: Vector3) {
|
||||
world
|
||||
.getDimension("overworld")
|
||||
.runCommand(`/execute as @a run tp @e[type=agent] ${position.x} ${position.y} ${position.z}`);
|
||||
}
|
||||
|
||||
function isAgentAt(position: Vector3): boolean {
|
||||
let isAgentAt: boolean = false;
|
||||
world
|
||||
.getDimension("overworld")
|
||||
.getEntitiesAtBlockLocation(position)
|
||||
.forEach((entity) => {
|
||||
if (!entity.isValid()) {
|
||||
world.sendMessage("INVALID ENTITY");
|
||||
return;
|
||||
}
|
||||
if (entity.typeId == "minecraft:agent") {
|
||||
isAgentAt = true;
|
||||
}
|
||||
});
|
||||
return isAgentAt;
|
||||
}
|
||||
|
||||
function getAgent(): Entity {
|
||||
let agent = world.getEntity(mindKeeper.get("agentid") as string);
|
||||
return agent!;
|
||||
}
|
||||
|
||||
function getAgentLocation(): Vector3 {
|
||||
let agentLocation: Vector3 = vector3(0, 0, 0);
|
||||
let agent = world.getEntity(mindKeeper.get("agentid") as string);
|
||||
agentLocation = agent!.location;
|
||||
|
||||
return agentLocation;
|
||||
}
|
||||
|
||||
export { teleportAgent, isAgentAt, getAgentLocation, getAgent };
|
||||
62
scripts/Commandeer/utils/arrow.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { MolangVariableMap, Vector3, world } from "@minecraft/server";
|
||||
import { Vector3Add, vector3 } from "./vectorUtils";
|
||||
import { PARTICLES, spawnParticle } from "./particleUtils";
|
||||
|
||||
let arrowTemplate: Vector3[] = [
|
||||
vector3(0, 0, 0),
|
||||
|
||||
vector3(1, 1, 0),
|
||||
vector3(-1, 1, 0),
|
||||
|
||||
vector3(1.5, 2, 0),
|
||||
vector3(-1.5, 2, 0),
|
||||
|
||||
vector3(2, 3, 0),
|
||||
vector3(-2, 3, 0),
|
||||
|
||||
vector3(0, 1, 0),
|
||||
vector3(0, 2, 0),
|
||||
vector3(0, 3, 0),
|
||||
vector3(0, 4, 0),
|
||||
vector3(0, 5, 0),
|
||||
];
|
||||
|
||||
let offset: Vector3 = vector3(0, 0, 0);
|
||||
|
||||
let angleOffset = 0;
|
||||
let heightBobbing = 0;
|
||||
let tickCounter = 0;
|
||||
|
||||
function rotate(pos: Vector3, angle: number) {
|
||||
let x = pos.x;
|
||||
let z = pos.z;
|
||||
|
||||
let newX = x * Math.cos(angle) - z * Math.sin(angle);
|
||||
let newZ = x * Math.sin(angle) + z * Math.cos(angle);
|
||||
|
||||
return vector3(newX, pos.y, newZ);
|
||||
}
|
||||
|
||||
const particleData = new MolangVariableMap();
|
||||
particleData.setColorRGB("variable.color", {
|
||||
red: 1,
|
||||
green: 1,
|
||||
blue: 1,
|
||||
});
|
||||
|
||||
function drawArrow(offsetPos: Vector3) {
|
||||
tickCounter++;
|
||||
if (tickCounter % 2 == 0) {
|
||||
angleOffset += 0.1;
|
||||
heightBobbing += 0.3;
|
||||
offset = vector3(46.5, 75, 220.5);
|
||||
arrowTemplate.forEach((pos) => {
|
||||
let rotatedPos = rotate(pos, angleOffset);
|
||||
let finalPos = Vector3Add(offsetPos, rotatedPos);
|
||||
finalPos.y += Math.sin(heightBobbing) / 2;
|
||||
spawnParticle(finalPos, PARTICLES.point, particleData);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { drawArrow };
|
||||
24
scripts/Commandeer/utils/levelUtils.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { BlockType, BlockTypes, BlockVolume, Vector3, world } from "@minecraft/server";
|
||||
import { MinecraftBlockTypes } from "../../vanilla-data/mojang-block";
|
||||
|
||||
type Wall = {
|
||||
startPos: Vector3;
|
||||
endPos: Vector3;
|
||||
};
|
||||
|
||||
function clearWall(wall: Wall) {
|
||||
let volume: BlockVolume = new BlockVolume(wall.startPos, wall.endPos);
|
||||
world.getDimension("overworld").fillBlocks(volume, MinecraftBlockTypes.Air);
|
||||
}
|
||||
|
||||
function fillWall(wall: Wall, block: BlockType) {
|
||||
let volume: BlockVolume = new BlockVolume(wall.startPos, wall.endPos);
|
||||
world.getDimension("overworld").fillBlocks(volume, block);
|
||||
}
|
||||
|
||||
function startLevel(commandBlockPos: Vector3) {
|
||||
let volume: BlockVolume = new BlockVolume(commandBlockPos, commandBlockPos);
|
||||
world.getDimension("overworld").fillBlocks(volume, MinecraftBlockTypes.RedstoneBlock);
|
||||
}
|
||||
BlockTypes;
|
||||
export { Wall, clearWall, fillWall, startLevel };
|
||||
232
scripts/Commandeer/utils/particleUtils.ts
Normal file
@@ -0,0 +1,232 @@
|
||||
import { MolangVariableMap, Vector3, world } from "@minecraft/server";
|
||||
import { Vector3Add, vector3 } from "./vectorUtils";
|
||||
|
||||
const bedrockParticles = [
|
||||
"minecraft:mobspell_emitter",
|
||||
"minecraft:villager_angry",
|
||||
"minecraft:bleach",
|
||||
"minecraft:breaking_item_icon",
|
||||
"minecraft:blockdust",
|
||||
"minecraft:bubble_column_up_particle",
|
||||
"minecraft:compfire_smoke_particle",
|
||||
"minecraft:campfire_tall_smoke_particle",
|
||||
"minecraft:cherry_leaves_particle",
|
||||
"minecraft:crop_growth_emitter",
|
||||
"minecraft:conduit_particle",
|
||||
"minecraft:critical_hit_emitter",
|
||||
"minecraft:bubble_column_down_particle",
|
||||
"minecraft:dolphin_move_particle",
|
||||
"minecraft:dragon_breath_trail",
|
||||
"minecraft:dragon_breath_lingering",
|
||||
"minecraft:lava_drip_particle",
|
||||
"minecraft:water_drip_particle",
|
||||
"minecraft:redstone_wire_dust_particle",
|
||||
"minecraft:sculk_sensor_redstone_particle",
|
||||
"minecraft:splash_spell_emitter",
|
||||
"minecraft:electric_spark__particle",
|
||||
"minecraft:enchanting_table_particle",
|
||||
"minecraft:endrod",
|
||||
"minecraft:balloon_gas_particle",
|
||||
"minecraft:evoker_spell",
|
||||
"minecraft:huge_explosion_emitter",
|
||||
"minecraft:falling_dust_red_sand_particle",
|
||||
"minecraft:falling_dust_sand_particle",
|
||||
"minecraft:falling_dust_gravel_particle",
|
||||
"minecraft:falling_dust_top_snow_particle",
|
||||
"minecraft:falling_dust_dragon_egg_particle",
|
||||
"minecraft:falling_dust_concrete_particle",
|
||||
"minecraft:falling_dust_scaffolding_particle",
|
||||
"minecraft:honey_drip_particle",
|
||||
"minecraft:nectar_drip_particle",
|
||||
"minecraft:obsidian_tear_particle",
|
||||
"minecraft:spore_blossom_shower_particle",
|
||||
"minecraft:water_splash_particle",
|
||||
"minecraft:sparkler_emitter",
|
||||
"minecraft:water_wake_particle",
|
||||
"minecraft:basic_flame_particle",
|
||||
"minecraft:flash",
|
||||
"minecraft:glow_particle",
|
||||
"minecraft:villager_happy",
|
||||
"minecraft:heart_particle",
|
||||
"minecraft:water_evaporation_actor_emitter",
|
||||
"minecraft:lava_particle",
|
||||
"minecraft:mobflame_emitter",
|
||||
"minecraft:mobflame_single",
|
||||
"minecraft:mycelium_dust_particle",
|
||||
"minecraft:note_particle",
|
||||
"minecraft:explode",
|
||||
"minecraft:mob_portal",
|
||||
"minecraft:rainsplash",
|
||||
"minecraft:basic_smoke_particle",
|
||||
"minecraft:snowflake_particle",
|
||||
"minecraft:soul_particle",
|
||||
"minecraft:blue_flame_particle",
|
||||
"minecraft:spore_blossom_ambient_particle",
|
||||
"minecraft:watersplash",
|
||||
"minecraft:terrain",
|
||||
"minecraft:totem_particle",
|
||||
"minecraft:tracking_emitter",
|
||||
"minecraft:vibration_signal",
|
||||
"minecraft:wax_particle",
|
||||
"minecraft:witchspell",
|
||||
];
|
||||
|
||||
const PARTICLES = {
|
||||
mobspell_emitter: "minecraft:mobspell_emitter",
|
||||
villager_angry: "minecraft:villager_angry",
|
||||
bleach: "minecraft:bleach",
|
||||
breaking_item_icon: "minecraft:breaking_item_icon",
|
||||
blockdust: "minecraft:blockdust",
|
||||
bubble_column_up_particle: "minecraft:bubble_column_up_particle",
|
||||
compfire_smoke_particle: "minecraft:compfire_smoke_particle",
|
||||
campfire_tall_smoke_particle: "minecraft:campfire_tall_smoke_particle",
|
||||
cherry_leaves_particle: "minecraft:cherry_leaves_particle",
|
||||
crop_growth_emitter: "minecraft:crop_growth_emitter",
|
||||
conduit_particle: "minecraft:conduit_particle",
|
||||
critical_hit_emitter: "minecraft:critical_hit_emitter",
|
||||
bubble_column_down_particle: "minecraft:bubble_column_down_particle",
|
||||
dolphin_move_particle: "minecraft:dolphin_move_particle",
|
||||
dragon_breath_trail: "minecraft:dragon_breath_trail",
|
||||
dragon_breath_lingering: "minecraft:dragon_breath_lingering",
|
||||
lava_drip_particle: "minecraft:lava_drip_particle",
|
||||
water_drip_particle: "minecraft:water_drip_particle",
|
||||
redstone_wire_dust_particle: "minecraft:redstone_wire_dust_particle",
|
||||
sculk_sensor_redstone_particle: "minecraft:sculk_sensor_redstone_particle",
|
||||
splash_spell_emitter: "minecraft:splash_spell_emitter",
|
||||
electric_spark__particle: "minecraft:electric_spark__particle",
|
||||
enchanting_table_particle: "minecraft:enchanting_table_particle",
|
||||
endrod: "minecraft:endrod",
|
||||
balloon_gas_particle: "minecraft:balloon_gas_particle",
|
||||
evoker_spell: "minecraft:evoker_spell",
|
||||
huge_explosion_emitter: "minecraft:huge_explosion_emitter",
|
||||
falling_dust_red_sand_particle: "minecraft:falling_dust_red_sand_particle",
|
||||
falling_dust_sand_particle: "minecraft:falling_dust_sand_particle",
|
||||
falling_dust_gravel_particle: "minecraft:falling_dust_gravel_particle",
|
||||
falling_dust_top_snow_particle: "minecraft:falling_dust_top_snow_particle",
|
||||
falling_dust_dragon_egg_particle: "minecraft:falling_dust_dragon_egg_particle",
|
||||
falling_dust_concrete_particle: "minecraft:falling_dust_concrete_particle",
|
||||
falling_dust_scaffolding_particle: "minecraft:falling_dust_scaffolding_particle",
|
||||
honey_drip_particle: "minecraft:honey_drip_particle",
|
||||
nectar_drip_particle: "minecraft:nectar_drip_particle",
|
||||
obsidian_tear_particle: "minecraft:obsidian_tear_particle",
|
||||
spore_blossom_shower_particle: "minecraft:spore_blossom_shower_particle",
|
||||
water_splash_particle: "minecraft:water_splash_particle",
|
||||
sparkler_emitter: "minecraft:sparkler_emitter",
|
||||
water_wake_particle: "minecraft:water_wake_particle",
|
||||
basic_flame_particle: "minecraft:basic_flame_particle",
|
||||
flash: "minecraft:flash",
|
||||
glow_particle: "minecraft:glow_particle",
|
||||
villager_happy: "minecraft:villager_happy",
|
||||
heart_particle: "minecraft:heart_particle",
|
||||
water_evaporation_actor_emitter: "minecraft:water_evaporation_actor_emitter",
|
||||
lava_particle: "minecraft:lava_particle",
|
||||
mobflame_emitter: "minecraft:mobflame_emitter",
|
||||
mobflame_single: "minecraft:mobflame_single",
|
||||
mycelium_dust_particle: "minecraft:mycelium_dust_particle",
|
||||
note_particle: "minecraft:note_particle",
|
||||
explode: "minecraft:explode",
|
||||
mob_portal: "minecraft:mob_portal",
|
||||
rainsplash: "minecraft:rainsplash",
|
||||
basic_smoke_particle: "minecraft:basic_smoke_particle",
|
||||
snowflake_particle: "minecraft:snowflake_particle",
|
||||
soul_particle: "minecraft:soul_particle",
|
||||
blue_flame_particle: "minecraft:blue_flame_particle",
|
||||
spore_blossom_ambient_particle: "minecraft:spore_blossom_ambient_particle",
|
||||
watersplash: "minecraft:watersplash",
|
||||
terrain: "minecraft:terrain",
|
||||
totem_particle: "minecraft:totem_particle",
|
||||
tracking_emitter: "minecraft:tracking_emitter",
|
||||
vibration_signal: "minecraft:vibration_signal",
|
||||
wax_particle: "minecraft:wax_particle",
|
||||
witchspell: "minecraft:witchspell",
|
||||
point: "codecosmos:point",
|
||||
};
|
||||
|
||||
class ParticleColumn {
|
||||
pos: Vector3;
|
||||
radius: number;
|
||||
pointsPerLayer: number;
|
||||
layerCount: number;
|
||||
particle: string;
|
||||
points: Vector3[] = [];
|
||||
speed: number;
|
||||
anglePerLayer: number[] = [];
|
||||
tickCounter: number = 0;
|
||||
|
||||
constructor(
|
||||
pos: Vector3,
|
||||
radius: number,
|
||||
pointsPerLayer: number,
|
||||
layerCount: number,
|
||||
speed: number,
|
||||
particle: string
|
||||
) {
|
||||
this.pos = pos;
|
||||
this.radius = radius;
|
||||
this.particle = particle;
|
||||
this.pointsPerLayer = pointsPerLayer;
|
||||
this.layerCount = layerCount;
|
||||
this.speed = speed;
|
||||
this.generatePoints();
|
||||
}
|
||||
|
||||
generatePoints() {
|
||||
for (let layer = 0; layer < this.layerCount; layer++) {
|
||||
let layerRadius = this.radius - layer;
|
||||
for (let point = 0; point < this.pointsPerLayer; point++) {
|
||||
let angle = (point / this.pointsPerLayer) * (Math.PI * 2);
|
||||
this.anglePerLayer.push(angle);
|
||||
let x = Math.cos(angle) * layerRadius;
|
||||
let z = Math.sin(angle) * layerRadius;
|
||||
let y = layer;
|
||||
this.points.push(Vector3Add(this.pos, vector3(x, y, z)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update() {
|
||||
//update each point by increasing the angle by the speed
|
||||
let layerCount = 0;
|
||||
let pointCount = 0;
|
||||
this.tickCounter++;
|
||||
if (this.tickCounter % 2 == 0) {
|
||||
this.points.forEach((point, index) => {
|
||||
let layer = Math.floor(index / this.pointsPerLayer);
|
||||
let angle = this.anglePerLayer[index];
|
||||
angle += this.speed * (layer / 5);
|
||||
this.anglePerLayer[index] = angle;
|
||||
let layerRadius = this.radius - Math.floor(index / this.pointsPerLayer);
|
||||
let calcAngle = angle;
|
||||
let x = Math.cos(calcAngle) * this.radius;
|
||||
let z = Math.sin(calcAngle) * this.radius;
|
||||
let y = Math.floor(index / this.pointsPerLayer) + (this.tickCounter % 2);
|
||||
this.points[index] = Vector3Add(this.pos, vector3(x, y, z));
|
||||
});
|
||||
}
|
||||
}
|
||||
draw() {
|
||||
this.points.forEach((point) => {
|
||||
spawnParticle(point);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function spawnParticle(
|
||||
position: Vector3,
|
||||
particle: string = PARTICLES.balloon_gas_particle,
|
||||
map: MolangVariableMap = new MolangVariableMap()
|
||||
) {
|
||||
//check if the chunk is loaded
|
||||
const chunk = world.getDimension("overworld").getBlock(position);
|
||||
if (!chunk?.isValid()) {
|
||||
return;
|
||||
}
|
||||
map.setVector3("variable.direction", vector3(0, 0, 0));
|
||||
|
||||
const dimension = world.getDimension("overworld");
|
||||
if (dimension) {
|
||||
dimension.spawnParticle(particle, position, map);
|
||||
}
|
||||
}
|
||||
|
||||
export { PARTICLES, bedrockParticles, ParticleColumn, spawnParticle };
|
||||
71
scripts/Commandeer/utils/vectorUtils.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { Vector3 } from "@minecraft/server";
|
||||
|
||||
function vector3(x: number, y: number, z: number): Vector3 {
|
||||
return { x: x, y: y, z: z };
|
||||
}
|
||||
|
||||
function Vector3ToString(vector: Vector3) {
|
||||
return vector.x + "," + vector.y + "," + vector.z;
|
||||
}
|
||||
|
||||
function Vector3ToCommandString(vector: Vector3) {
|
||||
return `${vector.x} ${vector.y} ${vector.z}`;
|
||||
}
|
||||
|
||||
function Vector3ToFancyString(vector: Vector3) {
|
||||
return `{X: ${Math.floor(vector.x)}, Y: ${Math.floor(vector.y)}, Z: ${Math.floor(vector.z)}}`;
|
||||
}
|
||||
|
||||
function Vector3Add(vector1: Vector3, vector2: Vector3): Vector3 {
|
||||
return { x: vector1.x + vector2.x, y: vector1.y + vector2.y, z: vector1.z + vector2.z };
|
||||
}
|
||||
|
||||
function Vector3Subtract(vector1: Vector3, vector2: Vector3): Vector3 {
|
||||
return { x: vector1.x - vector2.x, y: vector1.y - vector2.y, z: vector1.z - vector2.z };
|
||||
}
|
||||
|
||||
function Vector3Multiply(vector1: Vector3, vector2: Vector3): Vector3 {
|
||||
return { x: vector1.x * vector2.x, y: vector1.y * vector2.y, z: vector1.z * vector2.z };
|
||||
}
|
||||
|
||||
function Vector3Divide(vector1: Vector3, vector2: Vector3): Vector3 {
|
||||
return { x: vector1.x / vector2.x, y: vector1.y / vector2.y, z: vector1.z / vector2.z };
|
||||
}
|
||||
|
||||
function Vector3Floor(vector: Vector3): Vector3 {
|
||||
return { x: Math.floor(vector.x), y: Math.floor(vector.y), z: Math.floor(vector.z) };
|
||||
}
|
||||
|
||||
function Vector3Ceil(vector: Vector3): Vector3 {
|
||||
return { x: Math.ceil(vector.x), y: Math.ceil(vector.y), z: Math.ceil(vector.z) };
|
||||
}
|
||||
|
||||
function Vector3Round(vector: Vector3): Vector3 {
|
||||
return { x: Math.round(vector.x), y: Math.round(vector.y), z: Math.round(vector.z) };
|
||||
}
|
||||
|
||||
function Vector3Abs(vector: Vector3): Vector3 {
|
||||
return { x: Math.abs(vector.x), y: Math.abs(vector.y), z: Math.abs(vector.z) };
|
||||
}
|
||||
|
||||
function vector3Distance(vector1: Vector3, vector2: Vector3): number {
|
||||
return Math.sqrt(
|
||||
Math.pow(vector2.x - vector1.x, 2) + Math.pow(vector2.y - vector1.y, 2) + Math.pow(vector2.z - vector1.z, 2)
|
||||
);
|
||||
}
|
||||
|
||||
export {
|
||||
Vector3ToString,
|
||||
Vector3ToFancyString,
|
||||
Vector3Add,
|
||||
Vector3Subtract,
|
||||
Vector3Multiply,
|
||||
Vector3Divide,
|
||||
Vector3Floor,
|
||||
Vector3Ceil,
|
||||
Vector3Round,
|
||||
Vector3Abs,
|
||||
vector3Distance,
|
||||
Vector3ToCommandString,
|
||||
vector3,
|
||||
};
|
||||
16
scripts/Commandeer/utils/waitUtil.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { system } from "@minecraft/server";
|
||||
|
||||
function delayedRun(callback: Function, delay: number) {
|
||||
let timer = system.runTimeout(() => {
|
||||
callback();
|
||||
system.clearRun(timer);
|
||||
}, delay);
|
||||
}
|
||||
|
||||
function delay(t: number) {
|
||||
return new Promise((r: any) => {
|
||||
system.runTimeout(r, t);
|
||||
});
|
||||
}
|
||||
|
||||
export { delayedRun, delay };
|
||||
34
scripts/Commandeer/utils/worldEditUtils.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { Vector3, world } from "@minecraft/server";
|
||||
|
||||
function clone(startPos: Vector3, endPos: Vector3, destination: Vector3) {
|
||||
world
|
||||
.getDimension("overworld")
|
||||
.runCommand(
|
||||
`clone ${startPos.x} ${startPos.y} ${startPos.z} ${endPos.x} ${endPos.y} ${endPos.z} ${destination.x} ${destination.y} ${destination.z} replace normal`
|
||||
);
|
||||
}
|
||||
|
||||
enum LeverDirection {
|
||||
DownEastWest = "down_east_west",
|
||||
DownNorthSouth = "down_north_south",
|
||||
East = "east",
|
||||
North = "north",
|
||||
South = "south",
|
||||
UpEastWest = "up_east_west",
|
||||
UpNorthSouth = "up_north_south",
|
||||
West = "west",
|
||||
}
|
||||
|
||||
function setLever(pos: Vector3, direction: LeverDirection, isOpen: boolean) {
|
||||
world
|
||||
.getDimension("overworld")
|
||||
.runCommandAsync(
|
||||
`/setblock ${pos.x} ${pos.y} ${pos.z} lever["lever_direction":"${direction}","open_bit":${
|
||||
isOpen ? "true" : "false"
|
||||
}]`
|
||||
);
|
||||
|
||||
///setblock 53 70 216 lever["lever_direction"="down_east_west","open_bit"=false]
|
||||
}
|
||||
|
||||
export { clone, LeverDirection, setLever };
|
||||
141
scripts/levelConditions/level1.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import { BlockType, Vector3 } from "@minecraft/server";
|
||||
import { LevelBlockCondition, LevelNoGoZone } from "../Commandeer/level/levelTypes";
|
||||
import { vector3 } from "../Commandeer/utils/vectorUtils";
|
||||
import { MinecraftBlockTypes } from "../vanilla-data/mojang-block";
|
||||
|
||||
let level1Conditions: LevelBlockCondition = {
|
||||
conditions: [
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(55, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(56, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(57, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(58, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(59, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(60, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(61, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(62, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(63, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(65, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(66, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(67, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(68, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(69, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(70, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(71, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(72, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(73, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(74, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(74, 70, 216),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
let level1NoGoZones: LevelNoGoZone = {
|
||||
zones: [
|
||||
{ position: vector3(55, 70, 215) },
|
||||
{ position: vector3(56, 70, 215) },
|
||||
{ position: vector3(57, 70, 215) },
|
||||
{ position: vector3(58, 70, 215) },
|
||||
{ position: vector3(59, 70, 215) },
|
||||
{ position: vector3(60, 70, 215) },
|
||||
{ position: vector3(61, 70, 215) },
|
||||
{ position: vector3(62, 70, 215) },
|
||||
{ position: vector3(63, 70, 215) },
|
||||
{ position: vector3(64, 70, 215) },
|
||||
{ position: vector3(65, 70, 215) },
|
||||
{ position: vector3(66, 70, 215) },
|
||||
{ position: vector3(67, 70, 215) },
|
||||
{ position: vector3(68, 70, 215) },
|
||||
{ position: vector3(69, 70, 215) },
|
||||
{ position: vector3(70, 70, 215) },
|
||||
{ position: vector3(71, 70, 215) },
|
||||
{ position: vector3(72, 70, 215) },
|
||||
{ position: vector3(73, 70, 215) },
|
||||
{ position: vector3(74, 70, 215) },
|
||||
|
||||
{ position: vector3(55, 70, 217) },
|
||||
{ position: vector3(56, 70, 217) },
|
||||
{ position: vector3(57, 70, 217) },
|
||||
{ position: vector3(58, 70, 217) },
|
||||
{ position: vector3(59, 70, 217) },
|
||||
{ position: vector3(60, 70, 217) },
|
||||
{ position: vector3(61, 70, 217) },
|
||||
{ position: vector3(62, 70, 217) },
|
||||
{ position: vector3(63, 70, 217) },
|
||||
{ position: vector3(64, 70, 217) },
|
||||
{ position: vector3(65, 70, 217) },
|
||||
{ position: vector3(66, 70, 217) },
|
||||
{ position: vector3(67, 70, 217) },
|
||||
{ position: vector3(68, 70, 217) },
|
||||
{ position: vector3(69, 70, 217) },
|
||||
{ position: vector3(70, 70, 217) },
|
||||
{ position: vector3(71, 70, 217) },
|
||||
{ position: vector3(72, 70, 217) },
|
||||
{ position: vector3(73, 70, 217) },
|
||||
{ position: vector3(74, 70, 217) },
|
||||
],
|
||||
};
|
||||
|
||||
export { level1Conditions, level1NoGoZones };
|
||||
145
scripts/levelConditions/level2.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
import { BlockType, Vector3 } from "@minecraft/server";
|
||||
import { LevelBlockCondition, LevelNoGoZone } from "../Commandeer/level/levelTypes";
|
||||
import { vector3 } from "../Commandeer/utils/vectorUtils";
|
||||
import { MinecraftBlockTypes } from "../vanilla-data/mojang-block";
|
||||
|
||||
let level2Conditions: LevelBlockCondition = {
|
||||
conditions: [
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(45, 70, 220),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(44, 70, 220),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(43, 70, 220),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(42, 70, 220),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(41, 70, 220),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(40, 70, 220),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(39, 70, 220),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(38, 70, 220),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(37, 70, 220),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(36, 70, 220),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(35, 70, 220),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(34, 70, 220),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(33, 70, 220),
|
||||
},
|
||||
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(33, 70, 219),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(33, 70, 218),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(33, 70, 217),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(33, 70, 216),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(33, 70, 215),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(33, 70, 214),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(33, 70, 213),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(33, 70, 212),
|
||||
},
|
||||
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(34, 70, 212),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(35, 70, 212),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(36, 70, 212),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(37, 70, 212),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(38, 70, 212),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(39, 70, 212),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(40, 70, 212),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(41, 70, 212),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(42, 70, 212),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(43, 70, 212),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(44, 70, 212),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(45, 70, 212),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export { level2Conditions };
|
||||
140
scripts/levelConditions/level3.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import { BlockType, Vector3 } from "@minecraft/server";
|
||||
import { LevelBlockCondition } from "../Commandeer/level/levelTypes";
|
||||
import { vector3 } from "../Commandeer/utils/vectorUtils";
|
||||
import { MinecraftBlockTypes } from "../vanilla-data/mojang-block";
|
||||
|
||||
let level3Conditions: LevelBlockCondition = {
|
||||
conditions: [
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(57, 70, 235),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(58, 70, 235),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(59, 70, 235),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(60, 70, 235),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(60, 70, 234),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(60, 70, 233),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(60, 70, 232),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(60, 70, 231),
|
||||
},
|
||||
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(61, 70, 231),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(62, 70, 231),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(63, 70, 231),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 231),
|
||||
},
|
||||
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 232),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 233),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 234),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 235),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 236),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 237),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 238),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 239),
|
||||
},
|
||||
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(65, 70, 239),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(66, 70, 239),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(67, 70, 239),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(68, 70, 239),
|
||||
},
|
||||
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(68, 70, 238),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(68, 70, 237),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(68, 70, 236),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(68, 70, 235),
|
||||
},
|
||||
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(69, 70, 235),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(70, 70, 235),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(71, 70, 235),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export { level3Conditions };
|
||||
140
scripts/levelConditions/level4.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import { BlockType, Vector3 } from "@minecraft/server";
|
||||
import { LevelBlockCondition } from "../Commandeer/level/levelTypes";
|
||||
import { vector3 } from "../Commandeer/utils/vectorUtils";
|
||||
import { MinecraftBlockTypes } from "../vanilla-data/mojang-block";
|
||||
|
||||
let level3Conditions: LevelBlockCondition = {
|
||||
conditions: [
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(57, 70, 235),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(58, 70, 235),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(59, 70, 235),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(60, 70, 235),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(60, 70, 234),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(60, 70, 233),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(60, 70, 232),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(60, 70, 231),
|
||||
},
|
||||
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(61, 70, 231),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(62, 70, 231),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(63, 70, 231),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 231),
|
||||
},
|
||||
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 232),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 233),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 234),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 235),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 236),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 237),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 238),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(64, 70, 239),
|
||||
},
|
||||
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(65, 70, 239),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(66, 70, 239),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(67, 70, 239),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(68, 70, 239),
|
||||
},
|
||||
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(68, 70, 238),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(68, 70, 237),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(68, 70, 236),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(68, 70, 235),
|
||||
},
|
||||
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(69, 70, 235),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(70, 70, 235),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.Air,
|
||||
position: vector3(71, 70, 235),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export { level3Conditions };
|
||||
26
scripts/levelConditions/levelIntro.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { LevelBlockCondition, LevelLeverCondition } from "../Commandeer/level/levelTypes";
|
||||
import { vector3 } from "../Commandeer/utils/vectorUtils";
|
||||
import { MinecraftBlockTypes } from "../vanilla-data/mojang-block";
|
||||
|
||||
let levelIntroConditions: LevelBlockCondition = {
|
||||
conditions: [
|
||||
{
|
||||
block: MinecraftBlockTypes.EmeraldBlock,
|
||||
position: vector3(2471, 12, 108),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.EmeraldBlock,
|
||||
position: vector3(2469, 12, 108),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.LapisBlock,
|
||||
position: vector3(2468, 12, 108),
|
||||
},
|
||||
{
|
||||
block: MinecraftBlockTypes.LapisBlock,
|
||||
position: vector3(2464, 12, 108),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export { levelIntroConditions };
|
||||
69
scripts/levels/level1/mission1.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { BlockType, BlockTypes, Vector3, world } from "@minecraft/server";
|
||||
import Level from "../../Commandeer/level/level";
|
||||
import pupeteer from "../../Commandeer/pupeteer";
|
||||
import { teleportAgent, isAgentAt, getAgentLocation, getAgent } from "../../Commandeer/utils/agentUtils";
|
||||
import { startLevel } from "../../Commandeer/utils/levelUtils";
|
||||
import { vector3, Vector3Add, Vector3ToCommandString } from "../../Commandeer/utils/vectorUtils";
|
||||
import { level1Conditions } from "../../levelConditions/level1";
|
||||
import { mindKeeper, CURRENT_LEVEL } from "../../main";
|
||||
import { MinecraftBlockTypes } from "../../vanilla-data/mojang-block";
|
||||
const Level1CommandBlockPos: Vector3 = vector3(-73, 71, 283);
|
||||
|
||||
const level1StartPosition: Vector3 = vector3(-73, 69, 267);
|
||||
const Level1EndPosition: Vector3 = vector3(-82, 69, 265);
|
||||
|
||||
const level1ResetCommandBlockPos: Vector3 = vector3(56, 68, 211);
|
||||
const level1: Level = new Level(
|
||||
() => {
|
||||
pupeteer.sendWorldMessage("%message.level1.started");
|
||||
pupeteer.setTitleTimed("%message.level1.name", 2.5);
|
||||
startLevel(Level1CommandBlockPos);
|
||||
teleportAgent(level1StartPosition);
|
||||
},
|
||||
() => {
|
||||
pupeteer.setActionBar("%message.level1.make");
|
||||
},
|
||||
() => {
|
||||
pupeteer.clearActionBar();
|
||||
pupeteer.sendWorldMessage("%message.level1.complete");
|
||||
pupeteer.setTitleTimed("%message.level1.complete", 2.5);
|
||||
|
||||
mindKeeper.increment(CURRENT_LEVEL);
|
||||
},
|
||||
() => {
|
||||
let isComplete = false;
|
||||
let isOutOfBounds = false;
|
||||
let hasAllTools = false;
|
||||
|
||||
//6 blocks lower is lava
|
||||
|
||||
let agentPos = getAgentLocation();
|
||||
let blockAir = world.getDimension("overworld").getBlock(Vector3Add(agentPos, vector3(0, -1, 0)));
|
||||
|
||||
if (blockAir && blockAir.type.id === MinecraftBlockTypes.Air) {
|
||||
isOutOfBounds = true;
|
||||
}
|
||||
|
||||
if (isAgentAt(Level1EndPosition) && hasAllTools) {
|
||||
isComplete = true;
|
||||
}
|
||||
|
||||
// world.sendMessage(`isComplete: ${isComplete}`);
|
||||
// world.sendMessage(`isOutOfBounds: ${isOutOfBounds}`);
|
||||
|
||||
if (isOutOfBounds) {
|
||||
pupeteer.sendWorldMessage("%message.level1.outOfBounds");
|
||||
pupeteer.setTitleTimed("%message.level1.outOfBounds", 2.5);
|
||||
// world.getDimension("overworld").runCommand("/kill @e[type=agent]");
|
||||
world.getDimension("overworld").runCommand("execute as @p run codebuilder runtime stop @s");
|
||||
|
||||
teleportAgent(level1StartPosition);
|
||||
return false;
|
||||
} else if (isComplete) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
export default level1;
|
||||
68
scripts/levels/level2/mission1.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { Vector3, world } from "@minecraft/server";
|
||||
import Level from "../../Commandeer/level/level";
|
||||
import pupeteer from "../../Commandeer/pupeteer";
|
||||
import { teleportAgent, isAgentAt, getAgentLocation, getAgent } from "../../Commandeer/utils/agentUtils";
|
||||
import { startLevel } from "../../Commandeer/utils/levelUtils";
|
||||
import { vector3, Vector3Add, Vector3ToCommandString } from "../../Commandeer/utils/vectorUtils";
|
||||
// import { level2Conditions } from "../../levelConditions/level2";
|
||||
import { mindKeeper, CURRENT_LEVEL } from "../../main";
|
||||
import { MinecraftBlockTypes } from "../../vanilla-data/mojang-block";
|
||||
const level2CommandBlockPos: Vector3 = vector3(-111, 70, 282);
|
||||
|
||||
const level2StartPosition: Vector3 = vector3(-111, 69, 272);
|
||||
const level2EndPosition: Vector3 = vector3(-124, 69, 258);
|
||||
|
||||
const level2ResetCommandBlockPos: Vector3 = vector3(56, 68, 211);
|
||||
const level2: Level = new Level(
|
||||
() => {
|
||||
pupeteer.sendWorldMessage("%message.level2.started");
|
||||
pupeteer.setTitleTimed("%message.level2.name", 2.5);
|
||||
startLevel(level2CommandBlockPos);
|
||||
teleportAgent(level2StartPosition);
|
||||
},
|
||||
() => {
|
||||
pupeteer.setActionBar("%message.level2.make");
|
||||
},
|
||||
() => {
|
||||
pupeteer.clearActionBar();
|
||||
pupeteer.sendWorldMessage("%message.level2.complete");
|
||||
pupeteer.setTitleTimed("%message.level2.complete", 2.5);
|
||||
|
||||
mindKeeper.increment(CURRENT_LEVEL);
|
||||
},
|
||||
() => {
|
||||
let isComplete = false;
|
||||
let isOutOfBounds = false;
|
||||
|
||||
//6 blocks lower is lava
|
||||
|
||||
let agentPos = getAgentLocation();
|
||||
let blockAir = world.getDimension("overworld").getBlock(Vector3Add(agentPos, vector3(0, -1, 0)));
|
||||
|
||||
if (blockAir && blockAir.type.id === MinecraftBlockTypes.Air) {
|
||||
isOutOfBounds = true;
|
||||
}
|
||||
|
||||
if (isAgentAt(level2EndPosition)) {
|
||||
isComplete = true;
|
||||
}
|
||||
|
||||
// world.sendMessage(`isComplete: ${isComplete}`);
|
||||
// world.sendMessage(`isOutOfBounds: ${isOutOfBounds}`);
|
||||
|
||||
if (isOutOfBounds) {
|
||||
pupeteer.sendWorldMessage("%message.level2.outOfBounds");
|
||||
pupeteer.setTitleTimed("%message.level2.outOfBounds", 2.5);
|
||||
// world.getDimension("overworld").runCommand("/kill @e[type=agent]");
|
||||
world.getDimension("overworld").runCommand("execute as @p run codebuilder runtime stop @s");
|
||||
|
||||
teleportAgent(level2StartPosition);
|
||||
return false;
|
||||
} else if (isComplete) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
export default level2;
|
||||
73
scripts/levels/level2/mission2.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { Vector3, world } from "@minecraft/server";
|
||||
import Level from "../../Commandeer/level/level";
|
||||
import pupeteer from "../../Commandeer/pupeteer";
|
||||
import { teleportAgent, isAgentAt, getAgentLocation, getAgent } from "../../Commandeer/utils/agentUtils";
|
||||
import { startLevel } from "../../Commandeer/utils/levelUtils";
|
||||
import { vector3, Vector3Add, Vector3ToCommandString } from "../../Commandeer/utils/vectorUtils";
|
||||
import { mindKeeper, CURRENT_LEVEL } from "../../main";
|
||||
import { MinecraftBlockTypes } from "../../vanilla-data/mojang-block";
|
||||
const Level3CommandBlockPos: Vector3 = vector3(-133, 68, 281);
|
||||
|
||||
const level3StartPosition: Vector3 = vector3(-133, 68, 265);
|
||||
const Level3EndPosition: Vector3 = vector3(-148, 68, 265);
|
||||
|
||||
const level3ResetCommandBlockPos: Vector3 = vector3(56, 68, 211);
|
||||
const level3: Level = new Level(
|
||||
() => {
|
||||
pupeteer.sendWorldMessage("%message.level3.started");
|
||||
pupeteer.setTitleTimed("%message.level3.name", 2.5);
|
||||
startLevel(Level3CommandBlockPos);
|
||||
teleportAgent(level3StartPosition);
|
||||
},
|
||||
() => {
|
||||
pupeteer.setActionBar("%message.level3.make");
|
||||
},
|
||||
() => {
|
||||
pupeteer.clearActionBar();
|
||||
pupeteer.sendWorldMessage("%message.level3.complete");
|
||||
pupeteer.setTitleTimed("%message.level3.complete", 2.5);
|
||||
|
||||
mindKeeper.increment(CURRENT_LEVEL);
|
||||
},
|
||||
() => {
|
||||
let isComplete = false;
|
||||
let isOutOfBounds = false;
|
||||
|
||||
//6 blocks lower is lava
|
||||
|
||||
let agentPos = getAgentLocation();
|
||||
let blockLava = world.getDimension("overworld").getBlock(Vector3Add(agentPos, vector3(0, -7, 0)));
|
||||
let blockAir = world.getDimension("overworld").getBlock(Vector3Add(agentPos, vector3(0, -1, 0)));
|
||||
|
||||
if (
|
||||
blockLava &&
|
||||
blockLava.type.id === MinecraftBlockTypes.Lava &&
|
||||
blockAir &&
|
||||
blockAir.type.id === MinecraftBlockTypes.Air
|
||||
) {
|
||||
isOutOfBounds = true;
|
||||
}
|
||||
|
||||
if (isAgentAt(Level3EndPosition)) {
|
||||
isComplete = true;
|
||||
}
|
||||
|
||||
// world.sendMessage(`isComplete: ${isComplete}`);
|
||||
// world.sendMessage(`isOutOfBounds: ${isOutOfBounds}`);
|
||||
|
||||
if (isOutOfBounds) {
|
||||
pupeteer.sendWorldMessage("%message.level3.outOfBounds");
|
||||
pupeteer.setTitleTimed("%message.level3.outOfBounds", 2.5);
|
||||
// world.getDimension("overworld").runCommand("/kill @e[type=agent]");
|
||||
world.getDimension("overworld").runCommand("execute as @p run codebuilder runtime stop @s");
|
||||
|
||||
teleportAgent(level3StartPosition);
|
||||
return false;
|
||||
} else if (isComplete) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
export default level3;
|
||||
72
scripts/levels/level2/mission3.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { Vector3, world } from "@minecraft/server";
|
||||
import Level from "../../Commandeer/level/level";
|
||||
import pupeteer from "../../Commandeer/pupeteer";
|
||||
import { teleportAgent, isAgentAt, getAgentLocation, getAgent } from "../../Commandeer/utils/agentUtils";
|
||||
import { startLevel } from "../../Commandeer/utils/levelUtils";
|
||||
import { vector3, Vector3Add, Vector3ToCommandString } from "../../Commandeer/utils/vectorUtils";
|
||||
import { mindKeeper, CURRENT_LEVEL } from "../../main";
|
||||
import { MinecraftBlockTypes } from "../../vanilla-data/mojang-block";
|
||||
const Level4CommandBlockPos: Vector3 = vector3(-161, 68, 291);
|
||||
const level4StartPosition: Vector3 = vector3(-161, 62, 261);
|
||||
const level4EndPosition: Vector3 = vector3(-174, 62, 268);
|
||||
|
||||
const level4ResetCommandBlockPos: Vector3 = vector3(56, 68, 211);
|
||||
const level4: Level = new Level(
|
||||
() => {
|
||||
pupeteer.sendWorldMessage("%message.level4.started");
|
||||
pupeteer.setTitleTimed("%message.level4.name", 2.5);
|
||||
startLevel(Level4CommandBlockPos);
|
||||
teleportAgent(level4StartPosition);
|
||||
},
|
||||
() => {
|
||||
pupeteer.setActionBar("%message.level4.make");
|
||||
},
|
||||
() => {
|
||||
pupeteer.clearActionBar();
|
||||
pupeteer.sendWorldMessage("%message.level4.complete");
|
||||
pupeteer.setTitleTimed("%message.level4.complete", 2.5);
|
||||
|
||||
mindKeeper.increment(CURRENT_LEVEL);
|
||||
},
|
||||
() => {
|
||||
let isComplete = false;
|
||||
let isOutOfBounds = false;
|
||||
|
||||
//6 blocks lower is lava
|
||||
|
||||
let agentPos = getAgentLocation();
|
||||
let blockLava = world.getDimension("overworld").getBlock(Vector3Add(agentPos, vector3(0, -7, 0)));
|
||||
let blockAir = world.getDimension("overworld").getBlock(Vector3Add(agentPos, vector3(0, -1, 0)));
|
||||
|
||||
if (
|
||||
blockLava &&
|
||||
blockLava.type.id === MinecraftBlockTypes.Lava &&
|
||||
blockAir &&
|
||||
blockAir.type.id === MinecraftBlockTypes.Air
|
||||
) {
|
||||
isOutOfBounds = true;
|
||||
}
|
||||
|
||||
if (isAgentAt(level4EndPosition)) {
|
||||
isComplete = true;
|
||||
}
|
||||
|
||||
// world.sendMessage(`isComplete: ${isComplete}`);
|
||||
// world.sendMessage(`isOutOfBounds: ${isOutOfBounds}`);
|
||||
|
||||
if (isOutOfBounds) {
|
||||
pupeteer.sendWorldMessage("%message.level4.outOfBounds");
|
||||
pupeteer.setTitleTimed("%message.level4.outOfBounds", 2.5);
|
||||
// world.getDimension("overworld").runCommand("/kill @e[type=agent]");
|
||||
world.getDimension("overworld").runCommand("execute as @p run codebuilder runtime stop @s");
|
||||
|
||||
teleportAgent(level4StartPosition);
|
||||
return false;
|
||||
} else if (isComplete) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
export default level4;
|
||||
115
scripts/levels/levelIntro.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { BlockType, Vector3, world } from "@minecraft/server";
|
||||
import Level from "../Commandeer/level/level";
|
||||
import { leverOn } from "../Commandeer/level/levelTypes";
|
||||
import { teleportAgent, isAgentAt } from "../Commandeer/utils/agentUtils";
|
||||
import { startLevel } from "../Commandeer/utils/levelUtils";
|
||||
import { vector3 } from "../Commandeer/utils/vectorUtils";
|
||||
import { levelIntroConditions } from "../levelConditions/levelIntro";
|
||||
import { CURRENT_LEVEL, mindKeeper } from "../main";
|
||||
import Pupeteer from "../Commandeer/pupeteer";
|
||||
import { MinecraftBlockTypes } from "../vanilla-data/mojang-block";
|
||||
|
||||
// const levelIntroCommandBlockPos: Vector3 = vector3(58, 66, 276);
|
||||
// const levelIntroStartPosition: Vector3 = vector3(28, 70, 269);
|
||||
// const levelIntroEndPosition: Vector3 = vector3(39, 70, 269);
|
||||
const buttonPositions: Vector3[] = [
|
||||
vector3(2471, 11, 106),
|
||||
vector3(2469, 11, 106),
|
||||
vector3(2468, 11, 106),
|
||||
vector3(2464, 11, 106),
|
||||
];
|
||||
|
||||
const blockPositions: Vector3[] = [
|
||||
vector3(2471, 12, 108),
|
||||
vector3(2469, 12, 108),
|
||||
vector3(2468, 12, 108),
|
||||
vector3(2464, 12, 108),
|
||||
];
|
||||
|
||||
let currentBlockSequence: string[] = [];
|
||||
let currentBlockSeuqenceIndex: number[] = [];
|
||||
|
||||
const blockCycle: string[] = [
|
||||
MinecraftBlockTypes.RedstoneBlock,
|
||||
MinecraftBlockTypes.GoldBlock,
|
||||
MinecraftBlockTypes.DiamondBlock,
|
||||
MinecraftBlockTypes.EmeraldBlock,
|
||||
MinecraftBlockTypes.LapisBlock,
|
||||
];
|
||||
|
||||
let buttonPressed: boolean[] = buttonPositions.map(() => false);
|
||||
|
||||
const levelIntro: Level = new Level(
|
||||
() => {
|
||||
Pupeteer.sendWorldMessage("%message.intro.started");
|
||||
Pupeteer.setTitleTimed("%message.intro.started", 2.5);
|
||||
// startLevel(levelIntroCommandBlockPos);
|
||||
// teleportAgent(levelIntroStartPosition);
|
||||
blockPositions.forEach((pos) => {
|
||||
let block = world.getDimension("overworld").getBlock(pos);
|
||||
let index = blockPositions.indexOf(pos);
|
||||
let blockType = block!.type;
|
||||
currentBlockSequence[index] = blockType.id;
|
||||
});
|
||||
},
|
||||
() => {
|
||||
Pupeteer.setActionBar("%message.intro.make");
|
||||
|
||||
buttonPositions.forEach((pos) => {
|
||||
let block = world.getDimension("overworld").getBlock(pos);
|
||||
if (!block) return;
|
||||
let index = buttonPositions.indexOf(pos);
|
||||
let prevState = buttonPressed[index];
|
||||
let currentState = block!.getRedstonePower()! > 0;
|
||||
|
||||
if (currentState && !prevState) {
|
||||
buttonPressed[index] = true;
|
||||
//NextBlock
|
||||
let nextBlock = currentBlockSequence[index];
|
||||
let nextIndex = blockCycle.indexOf(nextBlock);
|
||||
nextIndex = (nextIndex + 1) % blockCycle.length;
|
||||
currentBlockSequence[index] = blockCycle[nextIndex];
|
||||
//Update the block
|
||||
let blockPos = blockPositions[index];
|
||||
world.getDimension("overworld").getBlock(blockPos)!.setType(blockCycle[nextIndex]);
|
||||
}
|
||||
|
||||
if (!currentState && prevState) {
|
||||
buttonPressed[index] = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
() => {
|
||||
Pupeteer.clearActionBar();
|
||||
world.sendMessage("%message.intro.done");
|
||||
Pupeteer.setTitleTimed("%message.intro.done", 2.5);
|
||||
|
||||
mindKeeper.increment(CURRENT_LEVEL);
|
||||
},
|
||||
() => {
|
||||
let counter = 0;
|
||||
let isComplete = true;
|
||||
levelIntroConditions.conditions.forEach((condition) => {
|
||||
let blockInworld = world.getDimension("overworld").getBlock(condition.position);
|
||||
if (blockInworld?.type.id !== condition.block) {
|
||||
isComplete = false;
|
||||
counter++;
|
||||
}
|
||||
});
|
||||
world.sendMessage(`%message.intro.progress ${counter}/${levelIntroConditions.conditions.length}`);
|
||||
world.sendMessage(`isComplete: ${isComplete}`);
|
||||
if (isComplete) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
() => {
|
||||
blockPositions.forEach((pos) => {
|
||||
let block = world.getDimension("overworld").getBlock(pos);
|
||||
let randomBlock = blockCycle[Math.floor(Math.random() * blockCycle.length)];
|
||||
block!.setType(randomBlock);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
export default levelIntro;
|
||||
299
scripts/main.ts
Normal file
@@ -0,0 +1,299 @@
|
||||
import {
|
||||
world,
|
||||
system,
|
||||
Vector3,
|
||||
MolangVariableMap,
|
||||
ChatSendAfterEvent,
|
||||
Dimension,
|
||||
TicksPerSecond,
|
||||
BlockVolume,
|
||||
} from "@minecraft/server";
|
||||
import { Mindkeeper, StoreType } from "./Commandeer/mindKeeper";
|
||||
import Pupeteer from "./Commandeer/pupeteer";
|
||||
import { Vector3ToCommandString, Vector3ToFancyString, vector3 } from "./Commandeer/utils/vectorUtils";
|
||||
import { delay } from "./Commandeer/utils/waitUtil";
|
||||
import { spawnParticle } from "./Commandeer/utils/particleUtils";
|
||||
import { TrailMaker } from "./Commandeer/trail/trailMaker";
|
||||
import * as CCTrigger from "./Commandeer/Trigger/CCTrigger";
|
||||
import { Commands } from "./Commandeer/command/command";
|
||||
import { Trail } from "./Commandeer/trail/trailEngine";
|
||||
import { startTrail } from "./trails/startTrail";
|
||||
import level1 from "./levels/level1/mission1";
|
||||
import level2 from "./levels/level2/mission1";
|
||||
import level3 from "./levels/level2/mission2";
|
||||
import level4 from "./levels/level2/mission3";
|
||||
import { MinecraftBlockTypes } from "./vanilla-data/mojang-block";
|
||||
import { TransitionTrailToLevel1 } from "./trails/TransitionTrailToLevel1";
|
||||
import { TransitionTrailToLevel2 } from "./trails/TransitionTrailToLevel2";
|
||||
import { TransitionTrailToLevel3 } from "./trails/TransitionTrailToLevel3";
|
||||
|
||||
const mindKeeper = new Mindkeeper(world);
|
||||
const trailMaker: TrailMaker.Maker = new TrailMaker.Maker();
|
||||
const triggerManager = new CCTrigger.Manager(mindKeeper);
|
||||
const CURRENT_LEVEL = "currentLevel";
|
||||
const AGENT_ID = "agentid";
|
||||
const PREFIX = "!";
|
||||
export { mindKeeper, CURRENT_LEVEL, triggerManager };
|
||||
|
||||
triggerManager.RegisterFunctionTrigger("resetPath", (event) => {
|
||||
resetLightPath();
|
||||
});
|
||||
|
||||
async function resetLightPath() {
|
||||
world.getDimension("overworld").runCommand("/fill 2467 9 87 2468 9 105 air");
|
||||
}
|
||||
|
||||
let isIntroToLevel1Sqeuence = false;
|
||||
let isMakingLevel1 = false;
|
||||
let isMakingLevel2 = false;
|
||||
let isMakingLevel3 = false;
|
||||
let isMakingLevel4 = false;
|
||||
|
||||
let introTrail: Trail = new Trail("introTrail", 4, 4);
|
||||
introTrail.fromTrail(startTrail);
|
||||
|
||||
let transitionTrail1 = new Trail("transitionTrail1", 2, 2);
|
||||
transitionTrail1.fromTrail(TransitionTrailToLevel1);
|
||||
|
||||
let transitionTrail2 = new Trail("transitionTrail2", 2, 2);
|
||||
transitionTrail2.fromTrail(TransitionTrailToLevel2);
|
||||
|
||||
let transitionTrail3 = new Trail("transitionTrail3", 2, 2);
|
||||
transitionTrail3.fromTrail(TransitionTrailToLevel3);
|
||||
|
||||
const DEVELOPER_MODE = true;
|
||||
let tickCounter = 0;
|
||||
system.runInterval(async () => {
|
||||
tickCounter++;
|
||||
if (mindKeeper.initialised) {
|
||||
trailMaker.Update();
|
||||
if (tickCounter % 2 == 0) {
|
||||
triggerManager.Update();
|
||||
}
|
||||
|
||||
const currentLevel = mindKeeper.get(CURRENT_LEVEL);
|
||||
switch (currentLevel) {
|
||||
case 0:
|
||||
Pupeteer.setActionBar("Leave the treehouse and go down the ladder.");
|
||||
introTrail.spawnNext();
|
||||
break;
|
||||
case 1:
|
||||
Pupeteer.setActionBar("Trigger1 works");
|
||||
if (!isMakingLevel1) {
|
||||
isMakingLevel1 = true;
|
||||
world.sendMessage("Starting level1");
|
||||
level1.update();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
Pupeteer.setActionBar("Go to the next level.");
|
||||
transitionTrail1.spawnNext();
|
||||
break;
|
||||
case 3:
|
||||
Pupeteer.setActionBar("Trigger2 works");
|
||||
if (!isMakingLevel2) {
|
||||
isMakingLevel2 = true;
|
||||
world.sendMessage("Starting level2");
|
||||
level2.update();
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
Pupeteer.setActionBar("Trigger3 works");
|
||||
if (!isMakingLevel3) {
|
||||
isMakingLevel3 = true;
|
||||
world.sendMessage("Starting level3");
|
||||
level3.update();
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
Pupeteer.setActionBar("Trigger4 works");
|
||||
if (!isMakingLevel4) {
|
||||
isMakingLevel4 = true;
|
||||
world.sendMessage("Starting level4");
|
||||
level4.update();
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
triggerManager.RegisterFunctionTrigger("lightPath", (event) => {
|
||||
lightUpPath();
|
||||
});
|
||||
|
||||
async function lightUpPath() {
|
||||
let overworld: Dimension = world.getDimension("overworld");
|
||||
let pos1 = vector3(2467, 9, 87);
|
||||
let pos2 = vector3(2468, 9, 105);
|
||||
|
||||
for (let z = pos2.z; z >= pos1.z; z--) {
|
||||
let volume: BlockVolume = new BlockVolume(vector3(pos1.x, pos1.y, z), vector3(pos1.x + 1, pos1.y, z));
|
||||
overworld.fillBlocks(volume, MinecraftBlockTypes.RedstoneBlock);
|
||||
await delay(4);
|
||||
}
|
||||
}
|
||||
|
||||
world.afterEvents.worldInitialize.subscribe(() => {
|
||||
mindKeeper.registerStore(CURRENT_LEVEL, StoreType.number);
|
||||
mindKeeper.registerStore(AGENT_ID, StoreType.string);
|
||||
triggerManager.RegisterStores();
|
||||
mindKeeper.registerToWorld();
|
||||
|
||||
triggerManager.Load();
|
||||
});
|
||||
|
||||
world.beforeEvents.itemUseOn.subscribe((event) => {
|
||||
trailMaker.OnItemUse(event);
|
||||
triggerManager.OnItemUse(event);
|
||||
});
|
||||
|
||||
async function randomExplosions() {
|
||||
let pos1 = vector3(2465, 10, 82);
|
||||
let pos2 = vector3(2471, 18, 90);
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
let pos = vector3(
|
||||
pos1.x + Math.random() * (pos2.x - pos1.x),
|
||||
pos1.y + Math.random() * (pos2.y - pos1.y),
|
||||
pos1.z + Math.random() * (pos2.z - pos1.z)
|
||||
);
|
||||
|
||||
system.run(() => {
|
||||
spawnParticle(pos, "minecraft:huge_explosion_emitter", new MolangVariableMap());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
world.afterEvents.chatSend.subscribe(async (event: ChatSendAfterEvent) => {
|
||||
const command = event.message.split(" ")[0];
|
||||
|
||||
trailMaker.OnChat(event);
|
||||
mindKeeper.chatCommands(event);
|
||||
triggerManager.OnChat(event);
|
||||
|
||||
if (command === "!reset") {
|
||||
world.sendMessage("Resetting");
|
||||
|
||||
mindKeeper.set(CURRENT_LEVEL, 0);
|
||||
|
||||
resetLightPath();
|
||||
|
||||
level1.reset();
|
||||
level2.reset();
|
||||
level3.reset();
|
||||
level4.reset();
|
||||
|
||||
isIntroToLevel1Sqeuence = false;
|
||||
}
|
||||
});
|
||||
|
||||
system.afterEvents.scriptEventReceive.subscribe((event) => {
|
||||
if (event.id == "cc:getId") {
|
||||
let id = event.message;
|
||||
world.sendMessage("Script got the id " + id);
|
||||
mindKeeper.set(AGENT_ID, id);
|
||||
}
|
||||
});
|
||||
|
||||
class ClonePos {
|
||||
point1: Vector3;
|
||||
point2: Vector3;
|
||||
|
||||
constructor(point1: Vector3, point2: Vector3) {
|
||||
this.point1 = point1;
|
||||
this.point2 = point2;
|
||||
}
|
||||
}
|
||||
|
||||
triggerManager.RegisterFunctionTrigger("BottomTreeHouse", async (event) => {
|
||||
if (mindKeeper.get(CURRENT_LEVEL) == 0) {
|
||||
// mindKeeper.increment(CURRENT_LEVEL);
|
||||
mindKeeper.set(CURRENT_LEVEL, 1);
|
||||
}
|
||||
});
|
||||
|
||||
triggerManager.RegisterFunctionTrigger("PastLevel1", async (event) => {
|
||||
if (mindKeeper.get(CURRENT_LEVEL) == 0) {
|
||||
// mindKeeper.increment(CURRENT_LEVEL);
|
||||
mindKeeper.set(CURRENT_LEVEL, 2);
|
||||
}
|
||||
});
|
||||
|
||||
triggerManager.RegisterFunctionTrigger("PastLevel2", async (event) => {
|
||||
if (mindKeeper.get(CURRENT_LEVEL) == 0) {
|
||||
// mindKeeper.increment(CURRENT_LEVEL);
|
||||
mindKeeper.set(CURRENT_LEVEL, 3);
|
||||
}
|
||||
});
|
||||
|
||||
triggerManager.RegisterFunctionTrigger("PastLevel3", async (event) => {
|
||||
if (mindKeeper.get(CURRENT_LEVEL) == 0) {
|
||||
// mindKeeper.increment(CURRENT_LEVEL);
|
||||
mindKeeper.set(CURRENT_LEVEL, 4);
|
||||
}
|
||||
});
|
||||
|
||||
Commands.register(PREFIX, "info", (arg) => {
|
||||
world.sendMessage("-----------------");
|
||||
world.sendMessage("Current level: " + mindKeeper.get(CURRENT_LEVEL));
|
||||
world.sendMessage("Agent ID: " + mindKeeper.get(AGENT_ID));
|
||||
world.sendMessage("Engine Version: 1.0.2");
|
||||
world.sendMessage("Engine is running");
|
||||
world.sendMessage("Active players: " + world.getPlayers().length);
|
||||
world.sendMessage("Current dimension: " + arg.player.dimension.id);
|
||||
world.sendMessage("Current position: " + Vector3ToFancyString(arg.player.location));
|
||||
world.sendMessage("-----------------");
|
||||
});
|
||||
|
||||
async function SetFrame(frame: ClonePos, destination: Vector3) {
|
||||
await world
|
||||
.getDimension("overworld")
|
||||
.runCommandAsync(
|
||||
`/clone ${Vector3ToCommandString(frame.point1)} ${Vector3ToCommandString(frame.point2)} ${Vector3ToCommandString(
|
||||
destination
|
||||
)}`
|
||||
);
|
||||
}
|
||||
|
||||
let animationPlaying = false;
|
||||
async function playAnimation(
|
||||
frames: ClonePos[],
|
||||
delayTime: number,
|
||||
reverse: boolean,
|
||||
destination: Vector3,
|
||||
force: boolean = false
|
||||
) {
|
||||
if (animationPlaying && !force) {
|
||||
world.sendMessage("Animation already playing");
|
||||
return;
|
||||
}
|
||||
let frameCount = frames.length;
|
||||
if (!force) {
|
||||
animationPlaying = true;
|
||||
}
|
||||
|
||||
for (let i = 0; i < frameCount; i++) {
|
||||
let frame = reverse ? frames[frameCount - i - 1] : frames[i];
|
||||
await world
|
||||
.getDimension("overworld")
|
||||
.runCommandAsync(
|
||||
`/clone ${Vector3ToCommandString(frame.point1)} ${Vector3ToCommandString(
|
||||
frame.point2
|
||||
)} ${Vector3ToCommandString(destination)}`
|
||||
);
|
||||
await delay(delayTime);
|
||||
}
|
||||
if (!force) {
|
||||
animationPlaying = false;
|
||||
}
|
||||
}
|
||||
|
||||
system.afterEvents.scriptEventReceive.subscribe((event) => {
|
||||
if (event.id == "cc:getId") {
|
||||
let id = event.message;
|
||||
world.sendMessage("Script got the id " + id);
|
||||
mindKeeper.set(AGENT_ID, id);
|
||||
}
|
||||
});
|
||||
47
scripts/trails/TransitionTrailToLevel1.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Vector3 } from "@minecraft/server";
|
||||
import { TrailType } from "../Commandeer/trail/trailTypes";
|
||||
import { vector3 } from "../Commandeer/utils/vectorUtils";
|
||||
|
||||
let TransitionTrailToLevel1: TrailType = {
|
||||
name: "TransitionTrailToLevel1",
|
||||
points: [
|
||||
{ index: 0, position: vector3(-54, 88.1, 265.5) },
|
||||
{ index: 1, position: vector3(-55, 88.1, 265.5) },
|
||||
{ index: 2, position: vector3(-56, 88.1, 265.5) },
|
||||
{ index: 3, position: vector3(-57, 88.1, 265.5) },
|
||||
{ index: 4, position: vector3(-58, 88.1, 265.5) },
|
||||
{ index: 5, position: vector3(-58, 87.1, 265.5) },
|
||||
{ index: 6, position: vector3(-58, 86.1, 265.5) },
|
||||
{ index: 7, position: vector3(-58, 85.1, 265.5) },
|
||||
{ index: 8, position: vector3(-58, 84.1, 265.5) },
|
||||
{ index: 9, position: vector3(-58, 83.1, 265.5) },
|
||||
{ index: 10, position: vector3(-58, 82.1, 265.5) },
|
||||
{ index: 11, position: vector3(-58, 81.1, 265.5) },
|
||||
{ index: 12, position: vector3(-58, 80.1, 265.5) },
|
||||
{ index: 13, position: vector3(-58, 79.1, 265.5) },
|
||||
{ index: 14, position: vector3(-58, 78.1, 265.5) },
|
||||
{ index: 15, position: vector3(-58, 77.1, 265.5) },
|
||||
{ index: 16, position: vector3(-58, 76.1, 265.5) },
|
||||
{ index: 17, position: vector3(-58, 75.1, 265.5) },
|
||||
{ index: 18, position: vector3(-58, 74.1, 265.5) },
|
||||
{ index: 19, position: vector3(-58, 74.1, 264.5) },
|
||||
{ index: 20, position: vector3(-59, 74.1, 264.5) },
|
||||
{ index: 21, position: vector3(-59, 74.1, 263.5) },
|
||||
{ index: 22, position: vector3(-60, 74.1, 263.5) },
|
||||
{ index: 23, position: vector3(-61, 74.1, 263.5) },
|
||||
{ index: 24, position: vector3(-62, 74.1, 263.5) },
|
||||
{ index: 25, position: vector3(-63, 74.1, 263.5) },
|
||||
{ index: 26, position: vector3(-63, 73.1, 263.5) },
|
||||
{ index: 27, position: vector3(-63, 72.1, 263.5) },
|
||||
{ index: 28, position: vector3(-63, 71.1, 263.5) },
|
||||
{ index: 29, position: vector3(-64, 71.1, 263.5) },
|
||||
{ index: 30, position: vector3(-65, 71.1, 263.5) },
|
||||
{ index: 31, position: vector3(-66, 71.1, 263.5) },
|
||||
{ index: 32, position: vector3(-67, 71.1, 263.5) },
|
||||
{ index: 33, position: vector3(-68, 71.1, 263.5) },
|
||||
{ index: 34, position: vector3(-69, 71.1, 263.5) },
|
||||
{ index: 35, position: vector3(-70, 71.1, 263.5) },
|
||||
],
|
||||
};
|
||||
|
||||
export { TransitionTrailToLevel1 };
|
||||
47
scripts/trails/TransitionTrailToLevel2.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Vector3 } from "@minecraft/server";
|
||||
import { TrailType } from "../Commandeer/trail/trailTypes";
|
||||
import { vector3 } from "../Commandeer/utils/vectorUtils";
|
||||
|
||||
let TransitionTrailToLevel2: TrailType = {
|
||||
name: "TransitionTrailToLevel2",
|
||||
points: [
|
||||
{ index: 0, position: vector3(-54, 88.1, 265.5) },
|
||||
{ index: 1, position: vector3(-55, 88.1, 265.5) },
|
||||
{ index: 2, position: vector3(-56, 88.1, 265.5) },
|
||||
{ index: 3, position: vector3(-57, 88.1, 265.5) },
|
||||
{ index: 4, position: vector3(-58, 88.1, 265.5) },
|
||||
{ index: 5, position: vector3(-58, 87.1, 265.5) },
|
||||
{ index: 6, position: vector3(-58, 86.1, 265.5) },
|
||||
{ index: 7, position: vector3(-58, 85.1, 265.5) },
|
||||
{ index: 8, position: vector3(-58, 84.1, 265.5) },
|
||||
{ index: 9, position: vector3(-58, 83.1, 265.5) },
|
||||
{ index: 10, position: vector3(-58, 82.1, 265.5) },
|
||||
{ index: 11, position: vector3(-58, 81.1, 265.5) },
|
||||
{ index: 12, position: vector3(-58, 80.1, 265.5) },
|
||||
{ index: 13, position: vector3(-58, 79.1, 265.5) },
|
||||
{ index: 14, position: vector3(-58, 78.1, 265.5) },
|
||||
{ index: 15, position: vector3(-58, 77.1, 265.5) },
|
||||
{ index: 16, position: vector3(-58, 76.1, 265.5) },
|
||||
{ index: 17, position: vector3(-58, 75.1, 265.5) },
|
||||
{ index: 18, position: vector3(-58, 74.1, 265.5) },
|
||||
{ index: 19, position: vector3(-58, 74.1, 264.5) },
|
||||
{ index: 20, position: vector3(-59, 74.1, 264.5) },
|
||||
{ index: 21, position: vector3(-59, 74.1, 263.5) },
|
||||
{ index: 22, position: vector3(-60, 74.1, 263.5) },
|
||||
{ index: 23, position: vector3(-61, 74.1, 263.5) },
|
||||
{ index: 24, position: vector3(-62, 74.1, 263.5) },
|
||||
{ index: 25, position: vector3(-63, 74.1, 263.5) },
|
||||
{ index: 26, position: vector3(-63, 73.1, 263.5) },
|
||||
{ index: 27, position: vector3(-63, 72.1, 263.5) },
|
||||
{ index: 28, position: vector3(-63, 71.1, 263.5) },
|
||||
{ index: 29, position: vector3(-64, 71.1, 263.5) },
|
||||
{ index: 30, position: vector3(-65, 71.1, 263.5) },
|
||||
{ index: 31, position: vector3(-66, 71.1, 263.5) },
|
||||
{ index: 32, position: vector3(-67, 71.1, 263.5) },
|
||||
{ index: 33, position: vector3(-68, 71.1, 263.5) },
|
||||
{ index: 34, position: vector3(-69, 71.1, 263.5) },
|
||||
{ index: 35, position: vector3(-70, 71.1, 263.5) },
|
||||
],
|
||||
};
|
||||
|
||||
export { TransitionTrailToLevel2 };
|
||||
47
scripts/trails/TransitionTrailToLevel3.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Vector3 } from "@minecraft/server";
|
||||
import { TrailType } from "../Commandeer/trail/trailTypes";
|
||||
import { vector3 } from "../Commandeer/utils/vectorUtils";
|
||||
|
||||
let TransitionTrailToLevel3: TrailType = {
|
||||
name: "TransitionTrailToLevel3",
|
||||
points: [
|
||||
{ index: 0, position: vector3(-54, 88.1, 265.5) },
|
||||
{ index: 1, position: vector3(-55, 88.1, 265.5) },
|
||||
{ index: 2, position: vector3(-56, 88.1, 265.5) },
|
||||
{ index: 3, position: vector3(-57, 88.1, 265.5) },
|
||||
{ index: 4, position: vector3(-58, 88.1, 265.5) },
|
||||
{ index: 5, position: vector3(-58, 87.1, 265.5) },
|
||||
{ index: 6, position: vector3(-58, 86.1, 265.5) },
|
||||
{ index: 7, position: vector3(-58, 85.1, 265.5) },
|
||||
{ index: 8, position: vector3(-58, 84.1, 265.5) },
|
||||
{ index: 9, position: vector3(-58, 83.1, 265.5) },
|
||||
{ index: 10, position: vector3(-58, 82.1, 265.5) },
|
||||
{ index: 11, position: vector3(-58, 81.1, 265.5) },
|
||||
{ index: 12, position: vector3(-58, 80.1, 265.5) },
|
||||
{ index: 13, position: vector3(-58, 79.1, 265.5) },
|
||||
{ index: 14, position: vector3(-58, 78.1, 265.5) },
|
||||
{ index: 15, position: vector3(-58, 77.1, 265.5) },
|
||||
{ index: 16, position: vector3(-58, 76.1, 265.5) },
|
||||
{ index: 17, position: vector3(-58, 75.1, 265.5) },
|
||||
{ index: 18, position: vector3(-58, 74.1, 265.5) },
|
||||
{ index: 19, position: vector3(-58, 74.1, 264.5) },
|
||||
{ index: 20, position: vector3(-59, 74.1, 264.5) },
|
||||
{ index: 21, position: vector3(-59, 74.1, 263.5) },
|
||||
{ index: 22, position: vector3(-60, 74.1, 263.5) },
|
||||
{ index: 23, position: vector3(-61, 74.1, 263.5) },
|
||||
{ index: 24, position: vector3(-62, 74.1, 263.5) },
|
||||
{ index: 25, position: vector3(-63, 74.1, 263.5) },
|
||||
{ index: 26, position: vector3(-63, 73.1, 263.5) },
|
||||
{ index: 27, position: vector3(-63, 72.1, 263.5) },
|
||||
{ index: 28, position: vector3(-63, 71.1, 263.5) },
|
||||
{ index: 29, position: vector3(-64, 71.1, 263.5) },
|
||||
{ index: 30, position: vector3(-65, 71.1, 263.5) },
|
||||
{ index: 31, position: vector3(-66, 71.1, 263.5) },
|
||||
{ index: 32, position: vector3(-67, 71.1, 263.5) },
|
||||
{ index: 33, position: vector3(-68, 71.1, 263.5) },
|
||||
{ index: 34, position: vector3(-69, 71.1, 263.5) },
|
||||
{ index: 35, position: vector3(-70, 71.1, 263.5) },
|
||||
],
|
||||
};
|
||||
|
||||
export { TransitionTrailToLevel3 };
|
||||
47
scripts/trails/startTrail.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Vector3 } from "@minecraft/server";
|
||||
import { TrailType } from "../Commandeer/trail/trailTypes";
|
||||
import { vector3 } from "../Commandeer/utils/vectorUtils";
|
||||
|
||||
let startTrail: TrailType = {
|
||||
name: "startTrail",
|
||||
points: [
|
||||
{ index: 0, position: vector3(-54, 88.1, 265.5) },
|
||||
{ index: 1, position: vector3(-55, 88.1, 265.5) },
|
||||
{ index: 2, position: vector3(-56, 88.1, 265.5) },
|
||||
{ index: 3, position: vector3(-57, 88.1, 265.5) },
|
||||
{ index: 4, position: vector3(-58, 88.1, 265.5) },
|
||||
{ index: 5, position: vector3(-58, 87.1, 265.5) },
|
||||
{ index: 6, position: vector3(-58, 86.1, 265.5) },
|
||||
{ index: 7, position: vector3(-58, 85.1, 265.5) },
|
||||
{ index: 8, position: vector3(-58, 84.1, 265.5) },
|
||||
{ index: 9, position: vector3(-58, 83.1, 265.5) },
|
||||
{ index: 10, position: vector3(-58, 82.1, 265.5) },
|
||||
{ index: 11, position: vector3(-58, 81.1, 265.5) },
|
||||
{ index: 12, position: vector3(-58, 80.1, 265.5) },
|
||||
{ index: 13, position: vector3(-58, 79.1, 265.5) },
|
||||
{ index: 14, position: vector3(-58, 78.1, 265.5) },
|
||||
{ index: 15, position: vector3(-58, 77.1, 265.5) },
|
||||
{ index: 16, position: vector3(-58, 76.1, 265.5) },
|
||||
{ index: 17, position: vector3(-58, 75.1, 265.5) },
|
||||
{ index: 18, position: vector3(-58, 74.1, 265.5) },
|
||||
{ index: 19, position: vector3(-58, 74.1, 264.5) },
|
||||
{ index: 20, position: vector3(-59, 74.1, 264.5) },
|
||||
{ index: 21, position: vector3(-59, 74.1, 263.5) },
|
||||
{ index: 22, position: vector3(-60, 74.1, 263.5) },
|
||||
{ index: 23, position: vector3(-61, 74.1, 263.5) },
|
||||
{ index: 24, position: vector3(-62, 74.1, 263.5) },
|
||||
{ index: 25, position: vector3(-63, 74.1, 263.5) },
|
||||
{ index: 26, position: vector3(-63, 73.1, 263.5) },
|
||||
{ index: 27, position: vector3(-63, 72.1, 263.5) },
|
||||
{ index: 28, position: vector3(-63, 71.1, 263.5) },
|
||||
{ index: 29, position: vector3(-64, 71.1, 263.5) },
|
||||
{ index: 30, position: vector3(-65, 71.1, 263.5) },
|
||||
{ index: 31, position: vector3(-66, 71.1, 263.5) },
|
||||
{ index: 32, position: vector3(-67, 71.1, 263.5) },
|
||||
{ index: 33, position: vector3(-68, 71.1, 263.5) },
|
||||
{ index: 34, position: vector3(-69, 71.1, 263.5) },
|
||||
{ index: 35, position: vector3(-70, 71.1, 263.5) },
|
||||
],
|
||||
};
|
||||
|
||||
export { startTrail };
|
||||
48
scripts/triggers.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { BlockVolume, Dimension, world } from "@minecraft/server";
|
||||
import { CCTrigger } from "./Commandeer/Trigger/CCTrigger";
|
||||
import { mindKeeper, triggerManager } from "./main";
|
||||
import { vector3 } from "./Commandeer/utils/vectorUtils";
|
||||
import { delay } from "./Commandeer/utils/waitUtil";
|
||||
import { MinecraftBlockTypes } from "./vanilla-data/mojang-block";
|
||||
|
||||
// const triggerManager = new CCTrigger.Manager(mindKeeper);
|
||||
|
||||
triggerManager.RegisterFunctionTrigger("test", (event) => {
|
||||
world.sendMessage("Wow, this is a trigger :O");
|
||||
world.sendMessage("This was caused by " + event.player.name);
|
||||
});
|
||||
|
||||
triggerManager.RegisterFunctionTrigger("lightPath", (event) => {
|
||||
lightUpPath();
|
||||
});
|
||||
|
||||
triggerManager.RegisterFunctionTrigger("resetPath", (event) => {
|
||||
resetLightPath();
|
||||
});
|
||||
|
||||
triggerManager.RegisterFunctionTrigger("test2", (event) => {
|
||||
world.sendMessage("Wow, this is another trigger :O");
|
||||
});
|
||||
|
||||
triggerManager.RegisterFunctionTrigger("die", (event) => {
|
||||
world.sendMessage("You died");
|
||||
event.player.applyDamage(1000);
|
||||
});
|
||||
|
||||
//fill 2467 9 87 2468 9 105 redstone_block
|
||||
async function lightUpPath() {
|
||||
let overworld: Dimension = world.getDimension("overworld");
|
||||
let pos1 = vector3(2467, 9, 87);
|
||||
let pos2 = vector3(2468, 9, 105);
|
||||
|
||||
for (let z = pos2.z; z >= pos1.z; z--) {
|
||||
let volume: BlockVolume = new BlockVolume(vector3(pos1.x, pos1.y, z), vector3(pos1.x + 1, pos1.y, z));
|
||||
overworld.fillBlocks(volume, MinecraftBlockTypes.RedstoneBlock);
|
||||
await delay(4);
|
||||
}
|
||||
// let pos2 = vector3(2468, 9, 105);
|
||||
}
|
||||
|
||||
async function resetLightPath() {
|
||||
world.getDimension("overworld").runCommand("/fill 2467 9 87 2468 9 105 air");
|
||||
}
|
||||
95
scripts/vanilla-data/mojang-biome.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* All possible MinecraftBiomeTypes
|
||||
*/
|
||||
export enum MinecraftBiomeTypes {
|
||||
BambooJungle = "minecraft:bamboo_jungle",
|
||||
BambooJungleHills = "minecraft:bamboo_jungle_hills",
|
||||
BasaltDeltas = "minecraft:basalt_deltas",
|
||||
Beach = "minecraft:beach",
|
||||
BirchForest = "minecraft:birch_forest",
|
||||
BirchForestHills = "minecraft:birch_forest_hills",
|
||||
BirchForestHillsMutated = "minecraft:birch_forest_hills_mutated",
|
||||
BirchForestMutated = "minecraft:birch_forest_mutated",
|
||||
CherryGrove = "minecraft:cherry_grove",
|
||||
ColdBeach = "minecraft:cold_beach",
|
||||
ColdOcean = "minecraft:cold_ocean",
|
||||
ColdTaiga = "minecraft:cold_taiga",
|
||||
ColdTaigaHills = "minecraft:cold_taiga_hills",
|
||||
ColdTaigaMutated = "minecraft:cold_taiga_mutated",
|
||||
CrimsonForest = "minecraft:crimson_forest",
|
||||
DeepColdOcean = "minecraft:deep_cold_ocean",
|
||||
DeepDark = "minecraft:deep_dark",
|
||||
DeepFrozenOcean = "minecraft:deep_frozen_ocean",
|
||||
DeepLukewarmOcean = "minecraft:deep_lukewarm_ocean",
|
||||
DeepOcean = "minecraft:deep_ocean",
|
||||
DeepWarmOcean = "minecraft:deep_warm_ocean",
|
||||
Desert = "minecraft:desert",
|
||||
DesertHills = "minecraft:desert_hills",
|
||||
DesertMutated = "minecraft:desert_mutated",
|
||||
DripstoneCaves = "minecraft:dripstone_caves",
|
||||
ExtremeHills = "minecraft:extreme_hills",
|
||||
ExtremeHillsEdge = "minecraft:extreme_hills_edge",
|
||||
ExtremeHillsMutated = "minecraft:extreme_hills_mutated",
|
||||
ExtremeHillsPlusTrees = "minecraft:extreme_hills_plus_trees",
|
||||
ExtremeHillsPlusTreesMutated = "minecraft:extreme_hills_plus_trees_mutated",
|
||||
FlowerForest = "minecraft:flower_forest",
|
||||
Forest = "minecraft:forest",
|
||||
ForestHills = "minecraft:forest_hills",
|
||||
FrozenOcean = "minecraft:frozen_ocean",
|
||||
FrozenPeaks = "minecraft:frozen_peaks",
|
||||
FrozenRiver = "minecraft:frozen_river",
|
||||
Grove = "minecraft:grove",
|
||||
Hell = "minecraft:hell",
|
||||
IceMountains = "minecraft:ice_mountains",
|
||||
IcePlains = "minecraft:ice_plains",
|
||||
IcePlainsSpikes = "minecraft:ice_plains_spikes",
|
||||
JaggedPeaks = "minecraft:jagged_peaks",
|
||||
Jungle = "minecraft:jungle",
|
||||
JungleEdge = "minecraft:jungle_edge",
|
||||
JungleEdgeMutated = "minecraft:jungle_edge_mutated",
|
||||
JungleHills = "minecraft:jungle_hills",
|
||||
JungleMutated = "minecraft:jungle_mutated",
|
||||
LegacyFrozenOcean = "minecraft:legacy_frozen_ocean",
|
||||
LukewarmOcean = "minecraft:lukewarm_ocean",
|
||||
LushCaves = "minecraft:lush_caves",
|
||||
MangroveSwamp = "minecraft:mangrove_swamp",
|
||||
Meadow = "minecraft:meadow",
|
||||
MegaTaiga = "minecraft:mega_taiga",
|
||||
MegaTaigaHills = "minecraft:mega_taiga_hills",
|
||||
Mesa = "minecraft:mesa",
|
||||
MesaBryce = "minecraft:mesa_bryce",
|
||||
MesaPlateau = "minecraft:mesa_plateau",
|
||||
MesaPlateauMutated = "minecraft:mesa_plateau_mutated",
|
||||
MesaPlateauStone = "minecraft:mesa_plateau_stone",
|
||||
MesaPlateauStoneMutated = "minecraft:mesa_plateau_stone_mutated",
|
||||
MushroomIsland = "minecraft:mushroom_island",
|
||||
MushroomIslandShore = "minecraft:mushroom_island_shore",
|
||||
Ocean = "minecraft:ocean",
|
||||
Plains = "minecraft:plains",
|
||||
RedwoodTaigaHillsMutated = "minecraft:redwood_taiga_hills_mutated",
|
||||
RedwoodTaigaMutated = "minecraft:redwood_taiga_mutated",
|
||||
River = "minecraft:river",
|
||||
RoofedForest = "minecraft:roofed_forest",
|
||||
RoofedForestMutated = "minecraft:roofed_forest_mutated",
|
||||
Savanna = "minecraft:savanna",
|
||||
SavannaMutated = "minecraft:savanna_mutated",
|
||||
SavannaPlateau = "minecraft:savanna_plateau",
|
||||
SavannaPlateauMutated = "minecraft:savanna_plateau_mutated",
|
||||
SnowySlopes = "minecraft:snowy_slopes",
|
||||
SoulsandValley = "minecraft:soulsand_valley",
|
||||
StoneBeach = "minecraft:stone_beach",
|
||||
StonyPeaks = "minecraft:stony_peaks",
|
||||
SunflowerPlains = "minecraft:sunflower_plains",
|
||||
Swampland = "minecraft:swampland",
|
||||
SwamplandMutated = "minecraft:swampland_mutated",
|
||||
Taiga = "minecraft:taiga",
|
||||
TaigaHills = "minecraft:taiga_hills",
|
||||
TaigaMutated = "minecraft:taiga_mutated",
|
||||
TheEnd = "minecraft:the_end",
|
||||
WarmOcean = "minecraft:warm_ocean",
|
||||
WarpedForest = "minecraft:warped_forest",
|
||||
}
|
||||
/**
|
||||
* Union type equivalent of the MinecraftBiomeTypes enum.
|
||||
*/
|
||||
export type MinecraftBiomeTypesUnion = keyof typeof MinecraftBiomeTypes;
|
||||
5374
scripts/vanilla-data/mojang-block.ts
Normal file
13
scripts/vanilla-data/mojang-cameraPresets.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* All possible MinecraftCameraPresetsTypes
|
||||
*/
|
||||
export enum MinecraftCameraPresetsTypes {
|
||||
FirstPerson = "minecraft:first_person",
|
||||
Free = "minecraft:free",
|
||||
ThirdPerson = "minecraft:third_person",
|
||||
ThirdPersonFront = "minecraft:third_person_front",
|
||||
}
|
||||
/**
|
||||
* Union type equivalent of the MinecraftCameraPresetsTypes enum.
|
||||
*/
|
||||
export type MinecraftCameraPresetsTypesUnion = keyof typeof MinecraftCameraPresetsTypes;
|
||||
14
scripts/vanilla-data/mojang-cooldownCategory.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* All possible MinecraftCooldownCategoryTypes
|
||||
*/
|
||||
export enum MinecraftCooldownCategoryTypes {
|
||||
Chorusfruit = "minecraft:chorusfruit",
|
||||
EnderPearl = "minecraft:ender_pearl",
|
||||
GoatHorn = "minecraft:goat_horn",
|
||||
Shield = "minecraft:shield",
|
||||
WindCharge = "minecraft:wind_charge",
|
||||
}
|
||||
/**
|
||||
* Union type equivalent of the MinecraftCooldownCategoryTypes enum.
|
||||
*/
|
||||
export type MinecraftCooldownCategoryTypesUnion = keyof typeof MinecraftCooldownCategoryTypes;
|
||||
12
scripts/vanilla-data/mojang-dimension.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* All possible MinecraftDimensionTypes
|
||||
*/
|
||||
export enum MinecraftDimensionTypes {
|
||||
Nether = "minecraft:nether",
|
||||
Overworld = "minecraft:overworld",
|
||||
TheEnd = "minecraft:the_end",
|
||||
}
|
||||
/**
|
||||
* Union type equivalent of the MinecraftDimensionTypes enum.
|
||||
*/
|
||||
export type MinecraftDimensionTypesUnion = keyof typeof MinecraftDimensionTypes;
|
||||
46
scripts/vanilla-data/mojang-effect.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* All possible MinecraftEffectTypes
|
||||
*/
|
||||
export enum MinecraftEffectTypes {
|
||||
Absorption = "absorption",
|
||||
BadOmen = "bad_omen",
|
||||
Blindness = "blindness",
|
||||
ConduitPower = "conduit_power",
|
||||
Darkness = "darkness",
|
||||
Empty = "empty",
|
||||
FatalPoison = "fatal_poison",
|
||||
FireResistance = "fire_resistance",
|
||||
Haste = "haste",
|
||||
HealthBoost = "health_boost",
|
||||
Hunger = "hunger",
|
||||
Infested = "infested",
|
||||
InstantDamage = "instant_damage",
|
||||
InstantHealth = "instant_health",
|
||||
Invisibility = "invisibility",
|
||||
JumpBoost = "jump_boost",
|
||||
Levitation = "levitation",
|
||||
MiningFatigue = "mining_fatigue",
|
||||
Nausea = "nausea",
|
||||
NightVision = "night_vision",
|
||||
Oozing = "oozing",
|
||||
Poison = "poison",
|
||||
RaidOmen = "raid_omen",
|
||||
Regeneration = "regeneration",
|
||||
Resistance = "resistance",
|
||||
Saturation = "saturation",
|
||||
SlowFalling = "slow_falling",
|
||||
Slowness = "slowness",
|
||||
Speed = "speed",
|
||||
Strength = "strength",
|
||||
TrialOmen = "trial_omen",
|
||||
VillageHero = "village_hero",
|
||||
WaterBreathing = "water_breathing",
|
||||
Weakness = "weakness",
|
||||
Weaving = "weaving",
|
||||
WindCharged = "wind_charged",
|
||||
Wither = "wither",
|
||||
}
|
||||
/**
|
||||
* Union type equivalent of the MinecraftEffectTypes enum.
|
||||
*/
|
||||
export type MinecraftEffectTypesUnion = keyof typeof MinecraftEffectTypes;
|
||||
50
scripts/vanilla-data/mojang-enchantment.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* All possible MinecraftEnchantmentTypes
|
||||
*/
|
||||
export enum MinecraftEnchantmentTypes {
|
||||
AquaAffinity = "aqua_affinity",
|
||||
BaneOfArthropods = "bane_of_arthropods",
|
||||
Binding = "binding",
|
||||
BlastProtection = "blast_protection",
|
||||
Breach = "breach",
|
||||
Channeling = "channeling",
|
||||
Density = "density",
|
||||
DepthStrider = "depth_strider",
|
||||
Efficiency = "efficiency",
|
||||
FeatherFalling = "feather_falling",
|
||||
FireAspect = "fire_aspect",
|
||||
FireProtection = "fire_protection",
|
||||
Flame = "flame",
|
||||
Fortune = "fortune",
|
||||
FrostWalker = "frost_walker",
|
||||
Impaling = "impaling",
|
||||
Infinity = "infinity",
|
||||
Knockback = "knockback",
|
||||
Looting = "looting",
|
||||
Loyalty = "loyalty",
|
||||
LuckOfTheSea = "luck_of_the_sea",
|
||||
Lure = "lure",
|
||||
Mending = "mending",
|
||||
Multishot = "multishot",
|
||||
Piercing = "piercing",
|
||||
Power = "power",
|
||||
ProjectileProtection = "projectile_protection",
|
||||
Protection = "protection",
|
||||
Punch = "punch",
|
||||
QuickCharge = "quick_charge",
|
||||
Respiration = "respiration",
|
||||
Riptide = "riptide",
|
||||
Sharpness = "sharpness",
|
||||
SilkTouch = "silk_touch",
|
||||
Smite = "smite",
|
||||
SoulSpeed = "soul_speed",
|
||||
SwiftSneak = "swift_sneak",
|
||||
Thorns = "thorns",
|
||||
Unbreaking = "unbreaking",
|
||||
Vanishing = "vanishing",
|
||||
WindBurst = "wind_burst",
|
||||
}
|
||||
/**
|
||||
* Union type equivalent of the MinecraftEnchantmentTypes enum.
|
||||
*/
|
||||
export type MinecraftEnchantmentTypesUnion = keyof typeof MinecraftEnchantmentTypes;
|
||||
129
scripts/vanilla-data/mojang-entity.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* All possible MinecraftEntityTypes
|
||||
*/
|
||||
export enum MinecraftEntityTypes {
|
||||
Agent = "agent",
|
||||
Allay = "allay",
|
||||
AreaEffectCloud = "area_effect_cloud",
|
||||
Armadillo = "armadillo",
|
||||
ArmorStand = "armor_stand",
|
||||
Arrow = "arrow",
|
||||
Axolotl = "axolotl",
|
||||
Bat = "bat",
|
||||
Bee = "bee",
|
||||
Blaze = "blaze",
|
||||
Boat = "boat",
|
||||
Bogged = "bogged",
|
||||
Breeze = "breeze",
|
||||
BreezeWindChargeProjectile = "breeze_wind_charge_projectile",
|
||||
Camel = "camel",
|
||||
Cat = "cat",
|
||||
CaveSpider = "cave_spider",
|
||||
ChestBoat = "chest_boat",
|
||||
ChestMinecart = "chest_minecart",
|
||||
Chicken = "chicken",
|
||||
Cod = "cod",
|
||||
CommandBlockMinecart = "command_block_minecart",
|
||||
Cow = "cow",
|
||||
Creeper = "creeper",
|
||||
Dolphin = "dolphin",
|
||||
Donkey = "donkey",
|
||||
DragonFireball = "dragon_fireball",
|
||||
Drowned = "drowned",
|
||||
Egg = "egg",
|
||||
ElderGuardian = "elder_guardian",
|
||||
EnderCrystal = "ender_crystal",
|
||||
EnderDragon = "ender_dragon",
|
||||
EnderPearl = "ender_pearl",
|
||||
Enderman = "enderman",
|
||||
Endermite = "endermite",
|
||||
EvocationIllager = "evocation_illager",
|
||||
EyeOfEnderSignal = "eye_of_ender_signal",
|
||||
Fireball = "fireball",
|
||||
FireworksRocket = "fireworks_rocket",
|
||||
FishingHook = "fishing_hook",
|
||||
Fox = "fox",
|
||||
Frog = "frog",
|
||||
Ghast = "ghast",
|
||||
GlowSquid = "glow_squid",
|
||||
Goat = "goat",
|
||||
Guardian = "guardian",
|
||||
Hoglin = "hoglin",
|
||||
HopperMinecart = "hopper_minecart",
|
||||
Horse = "horse",
|
||||
Husk = "husk",
|
||||
IronGolem = "iron_golem",
|
||||
LightningBolt = "lightning_bolt",
|
||||
LingeringPotion = "lingering_potion",
|
||||
Llama = "llama",
|
||||
LlamaSpit = "llama_spit",
|
||||
MagmaCube = "magma_cube",
|
||||
Minecart = "minecart",
|
||||
Mooshroom = "mooshroom",
|
||||
Mule = "mule",
|
||||
Npc = "npc",
|
||||
Ocelot = "ocelot",
|
||||
OminousItemSpawner = "ominous_item_spawner",
|
||||
Panda = "panda",
|
||||
Parrot = "parrot",
|
||||
Phantom = "phantom",
|
||||
Pig = "pig",
|
||||
Piglin = "piglin",
|
||||
PiglinBrute = "piglin_brute",
|
||||
Pillager = "pillager",
|
||||
Player = "player",
|
||||
PolarBear = "polar_bear",
|
||||
Pufferfish = "pufferfish",
|
||||
Rabbit = "rabbit",
|
||||
Ravager = "ravager",
|
||||
Salmon = "salmon",
|
||||
Sheep = "sheep",
|
||||
Shulker = "shulker",
|
||||
ShulkerBullet = "shulker_bullet",
|
||||
Silverfish = "silverfish",
|
||||
Skeleton = "skeleton",
|
||||
SkeletonHorse = "skeleton_horse",
|
||||
Slime = "slime",
|
||||
SmallFireball = "small_fireball",
|
||||
Sniffer = "sniffer",
|
||||
SnowGolem = "snow_golem",
|
||||
Snowball = "snowball",
|
||||
Spider = "spider",
|
||||
SplashPotion = "splash_potion",
|
||||
Squid = "squid",
|
||||
Stray = "stray",
|
||||
Strider = "strider",
|
||||
Tadpole = "tadpole",
|
||||
ThrownTrident = "thrown_trident",
|
||||
Tnt = "tnt",
|
||||
TntMinecart = "tnt_minecart",
|
||||
TraderLlama = "trader_llama",
|
||||
TripodCamera = "tripod_camera",
|
||||
Tropicalfish = "tropicalfish",
|
||||
Turtle = "turtle",
|
||||
Vex = "vex",
|
||||
Villager = "villager",
|
||||
VillagerV2 = "villager_v2",
|
||||
Vindicator = "vindicator",
|
||||
WanderingTrader = "wandering_trader",
|
||||
Warden = "warden",
|
||||
WindChargeProjectile = "wind_charge_projectile",
|
||||
Witch = "witch",
|
||||
Wither = "wither",
|
||||
WitherSkeleton = "wither_skeleton",
|
||||
WitherSkull = "wither_skull",
|
||||
WitherSkullDangerous = "wither_skull_dangerous",
|
||||
Wolf = "wolf",
|
||||
XpBottle = "xp_bottle",
|
||||
XpOrb = "xp_orb",
|
||||
Zoglin = "zoglin",
|
||||
Zombie = "zombie",
|
||||
ZombieHorse = "zombie_horse",
|
||||
ZombiePigman = "zombie_pigman",
|
||||
ZombieVillager = "zombie_villager",
|
||||
ZombieVillagerV2 = "zombie_villager_v2",
|
||||
}
|
||||
/**
|
||||
* Union type equivalent of the MinecraftEntityTypes enum.
|
||||
*/
|
||||
export type MinecraftEntityTypesUnion = keyof typeof MinecraftEntityTypes;
|
||||
26
scripts/vanilla-data/mojang-feature.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* All possible MinecraftFeatureTypes
|
||||
*/
|
||||
export enum MinecraftFeatureTypes {
|
||||
AncientCity = "minecraft:ancient_city",
|
||||
BastionRemnant = "minecraft:bastion_remnant",
|
||||
BuriedTreasure = "minecraft:buried_treasure",
|
||||
EndCity = "minecraft:end_city",
|
||||
Fortress = "minecraft:fortress",
|
||||
Mansion = "minecraft:mansion",
|
||||
Mineshaft = "minecraft:mineshaft",
|
||||
Monument = "minecraft:monument",
|
||||
PillagerOutpost = "minecraft:pillager_outpost",
|
||||
RuinedPortal = "minecraft:ruined_portal",
|
||||
Ruins = "minecraft:ruins",
|
||||
Shipwreck = "minecraft:shipwreck",
|
||||
Stronghold = "minecraft:stronghold",
|
||||
Temple = "minecraft:temple",
|
||||
TrailRuins = "minecraft:trail_ruins",
|
||||
TrialChambers = "minecraft:trial_chambers",
|
||||
Village = "minecraft:village",
|
||||
}
|
||||
/**
|
||||
* Union type equivalent of the MinecraftFeatureTypes enum.
|
||||
*/
|
||||
export type MinecraftFeatureTypesUnion = keyof typeof MinecraftFeatureTypes;
|
||||
1281
scripts/vanilla-data/mojang-item.ts
Normal file
32
tsconfig.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"compilerOptions":{
|
||||
"target":"es6",
|
||||
"moduleResolution":"node",
|
||||
"module":"es2020",
|
||||
"declaration":false,
|
||||
"noLib":false,
|
||||
"emitDecoratorMetadata":true,
|
||||
"experimentalDecorators":true,
|
||||
"sourceMap":true,
|
||||
"pretty":true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"allowUnreachableCode":true,
|
||||
"allowUnusedLabels":true,
|
||||
"noImplicitAny":true,
|
||||
"noImplicitReturns":false,
|
||||
"noImplicitUseStrict":false,
|
||||
"outDir":"build/",
|
||||
"rootDir": ".",
|
||||
"baseUrl":"behavior_packs/",
|
||||
"listFiles":false,
|
||||
"noEmitHelpers":true
|
||||
},
|
||||
"include":[
|
||||
"scripts/**/*"
|
||||
],
|
||||
"exclude":[
|
||||
"node_modules"
|
||||
],
|
||||
"compileOnSave":false
|
||||
}
|
||||