objd 0.0.10 objd: ^0.0.10 copied to clipboard
objd is a Object Oriented framework for Building Minecraft Datapacks with ease
objD #
Objective Builder Just for Datapacks #
objD is a framework for developing Datapacks for Minecraft. It uses the Dart programming language.
Why a framework? #
A framework is a set of utilities to reduce the amount of repetitive work. I've tried many ways in the past to achieve a quick and easy way to generate Datapacks for Minecraft: A own programming language mcscript, several graphical online generators at stevertus.com or premade utilities.
Instead of developing a language, why not using the tools and parser an other language gives you? By building a custom frame around it you get the reliability and the extensive debugging tools in Editors.
The generation of Datapacks is easy,fast and aims to be less repetitive and modular by utilizing the concept of Widgets as one of the main features.
Installation #
[Temporary]
You need the Dart SDK for this framework. Download and install it from https://www.dartlang.org/tools/sdk
I would also recommend Visual Studio Code along with the dart plugin to edit dart files very conveniently.
Make a new folder that will house your project wherever you want(I would recommend datapacks folder).
And inside of that create a file named pubspec.yaml
and another folder called lib
.
Open the pubspec.yaml file and add
dependencies:
objd: ^0.0.10
And run
$ pub get
with the console in the new folder(VS code does this automatically)
Getting started #
Let's get started and create our first dart file with lib/main.dart
file.
Then we import the framework with:
import 'package:objd/core.dart';b
Then we need to create a new datapack project:
void main(){
createProject(
Project(
name:"This is going to be the generated folder name",
target:"./", // path for where to generate the project
generate: CustomWidget() // The starting point of generation
)
);
}
Next of we need to build this custom Widget:
class CustomWidget extends Widget {
@override
Widget generate(Context context){
}
}
To get more details on why we build it like that, check out the Widget documentation.
Like we can see the generate method, which is called on build, has to return another Widget, in our case an instance of the Pack class.
Widget generate(Context context){
return Pack(
name:"mypack",
main: File( // optional
path: 'main'
)
)
}
What we are doing right now is to generate a new subpack with a name(This will be the namespace of your functions later) and a main file(runs every tick) with the name "main.mcfunction".
You can run the project already and the result should be a pack with an empty main.mcfunction file.
So lets add some functionality to our project in our main file.
main: File(
path: 'main',
child: Log('Hello World')
)
But how to add a list of Actions then? Well there's also an Widget for that: For.of
child: For.of(List<Widget>[
Log('Hello World'),
Command('setblock 0 0 0 air')
])
So now we have a List of Widget, so we can use as many as we want
Widget #
A widget is the base element for basically everything in objD.
property | |
---|---|
generate(Context) | returns the underlying Widget Tree |
toMap() | Similar to toString, but returns a Map tree of the child in generate |
Example: We can use an Widget to get or build functionality. e.g
// building our own widget:
class CustomCommand extends Widget {
@override
Widget generate(Context context){
// using an existing widget
return Command('custom')
}
}
Context #
Maybe you already wondered what this context argument here is:
Widget generate(Context context){
The Context is a way to get certain important information from the parents.
properties | |
---|---|
packId | String of the current pack's name |
file | the current file name |
loadFile | the filename of your load file |
mainFile | the filename of your main file |
prefixes | a List of Strings that should be added in front of actions(mainly used by Groups) |
You can use this context to build more modular Widgets and don't need to hardcode certain files and the pack id:
class LoadWidget extends Widget {
@override
Widget generate(Context context){
return Command('function ' + context.packId + ":" + context.loadFile)
}
}
Project #
The project is a special Widget which is just defined once. It contains some built options, like description or name, but also the entire underlying tree of packs, files and actions.
constructor | |
---|---|
name | the name of the datapack folder |
generate | a widget that defines the projects content |
[description] | A description that will go in pack.mcmeta |
Example:
main() {
// create Project takes in one project and compiles it
createProject(
Project(
name: "tested",
generate: mainWidget(),
));
}
Pack #
A pack is logically the next step. This defines a sub-pack with an name again that will be our namespace afterwards. Here we can also define included files as well as the main and load function:
constructor | |
---|---|
name | the name of the sub-pack |
[main] | the main file that is ran every tick |
[load] | the load file that is ran on reload |
[files] | A List of type File witch includes other needed files |
Example:
Pack(
name:"tpcraft",
main: File(...),
load: File(...),
files: List<File> [
File(...)
]
)
The Pack class can be used as often as you want and where you want, so you can also define a new pack in some file.
Notice: The namespace of the pack is accessible in these files by using the context variable. e.g:
Command("function" + context.packId + ":run")
File #
The Pack class already required some files. The file class simply generates a new mcfunction file with content and a path.
The File constructor has two required arguments:
constructor | |
---|---|
path | the desired file path going from /data/:packId:/functions/ on |
child | the content of the file |
[execute] | Boolean if the function should be executed directly |
The File class can be used as often as you want and where you want, so you can also define a new file in a For container for example. Example:
Pack(
name:"tpcraft",
main: File(
path:"main",
// and defining a new file inside of an widget
child: File.execute( // same as execute: true
path: 'new'
child: Command(...)
)
),
)
Extend #
Extend is very similar to File, but instead of creating a new file it adds content to an existing file.
constructor | |
---|---|
String | the desired file path going from /data/:packId:/functions/ on |
child | the additional content |
[first] | Boolean if the content should be added in front of the original(def. false) |
So lets say we already have some files in our pack, but want to add something to the main file somewhere entirely else in our project:
Extend(
"main",
child: Command("say okay"),
first: true
)
This would add the command say okay
in front of our main.mcfunction.
Command #
A Command is a raw action, that is executed by Minecraft directly.
constructor | |
---|---|
String | the raw command in the format "/command" or "command" |
Example:
// using a command in a file:
File(
path:"command",
child: Command('/say hey')
)
// uses the say command in command.mcfunction:
say hey
For #
The For class enables you to add multiple endpoints to one Widget.
There is always a List of Widgets involved.
constructor | |
---|---|
to | the ending index including itself |
create | a function returning a Widget based on the index argument |
[from] | the starting index(default 0) |
[step ] | the value used in each iteration to increases the index(default 1) |
So the basic for class utilizes a loop from a value to another value:
File(
path:"for",
child: For(
from: 0,
to: 5,
create: (index){
return Command('/say ' + index.toString())
}
)
)
// results in:
say 0
say 1
say 2
say 3
say 4
say 5
There is also an other Constructor for looping through a given list of widgets:
For.of | |
---|---|
List of Widgets | loops through each of these Widgets |
Example:
File(
path:"for_of",
child: For.of(List<Widget>[
Command('say 1'),
Command('say 2'),
Command('say 3')
]),
)
// results in:
say 1
say 2
say 3
CommandList #
But there is a more efficient way to list raw Minecraft commands. The CommandList Widget allows you to input a List of Commands, a List of Strings representing a command or a multiline string.
constructor | |
---|---|
List | a list of commands or strings |
This has basically the same function as For.of just for commands.
CommandList(List<Command>[
Command('say 1'),
Command('say 2'),
Command('say 3')
]),
But there is also a subset which accepts one big multiline string:
CommandList.str | |
---|---|
String | list of commands each on a seperate line |
CommandList.str("""
/say 1
/say 2
/say 3
"""),
The slashes are automatically filtered out.
Group #
The group groups actions similar to for but has an option to prefix each action and encapsulate the content in a new file.
constructor | |
---|---|
prefix | a prefix type of String |
children | the underlying widgets |
[filename] | the targeted filename(will be combined with an unique id) |
[groupMin] | the minimum amount of children to encapsulate(default = 3, set to -1 to disable) |
If the children length is larger or equal groupMin a new file is created in /objD/
(the working directory for objectiveD) and executed.
Group(
prefix: "execute as @e run "
children: List<Widget>[
Command('say 1'),
Command('say 2'),
Command('say 3')
],
filename: "asgroup",
groupMin: 2
),
Entity #
constructor | arguments are optional |
---|---|
selector | the entity selector(e.g p,s,e or r) |
limit | number of matched entities |
type | EntityType, id of the entity |
area | A List of two Locations marking an area where the entity should be |
distance | Range to the entity |
level | Range of experience levels |
gamemode | Gamemode type(e.g Gamemode.creative, Gamemode.survival) |
horizontalRotation | Range of the horizontal facing direction |
verticalRotation | Range of the vertical facing direction |
playerName | a String if you prefer to use a playername instead of arguments |
Methods | |
sort | adds a sort attribute of type Sort |
storeResult | Command, path, useSuccess |
storeResult stores a result or success of a command in the nbt path of an entity. Example:
Entity.Selected().storeResult(
Command('say hello'),
path: "Invisisble",
useSuccess:true
)
⇒ execute store success entity @s Invisisble run say hello
Sort |
---|
Sort.random |
Sort.furthest |
Sort.nearest |
Sort.albitrary |
The Range class defines a range of values(e.g 3..10 in vanilla)
Range | |
---|---|
[to] | Number for the maximum range |
[from] | Number for the minimal range |
EntityType | |
---|---|
String | String representation of the type |
There is also an EntityType for every type_id in minecraft with EntityType.[type_id]
Say(
entity: Entity(
selector: "e",
limit: 1,
type: EntityType.armor_stand,
distance: Range(to:2),
area: [
// use null for a unlimited selection
Location.glob(x: -10,y: null,z: -10),
Location.glob(x: 10, y: null, z: 10)
// it also automatically calcs the distance between these
]
level: Range(from: 1),
gamemode: Gamemode.creative,
horizontalRotation: Range(from:1),
verticalRotation: Range(from: 20, to: 80),
).sort(Sort.random)
)
⇒ say @e[limit=1,type=armor_stand,distance=..2,x=-10,z=-10,dx=20,dz=20,level=1..,gamemode=creative,y_rotation=1..,x_rotation=20..80,sort=random]
specific constructors | |
---|---|
Entity.Selected(...) | creates an entity with @s |
Entity.Player(...) | creates an entity with @p |
Entity.PlayerName(String) | creates an entity with an implicit name |
Entity.All(...) | creates an entity with @a |
Entity.Random(...) | creates an entity with @r |
Scoreboard #
A scoreboard objective holds values, kind a like a Variable inside Minecraft. The Scoreboard class just handles adding or removing objectives. The value assignment is handled by the Score class.
constructor | |
---|---|
String | name of the objective(required) |
type | the objective type (default = dummy) |
display | TextComponent that displays the name |
addIntoLoad | bool whether the scoreboard should be added into your load file(default = true) |
objD automatically keeps a list of all scoreboards and inserts them into the given load file, ignoring doubled names. Example:
Scoreboard(
"death_count",
type: "deathCount",
display: TextComponent("This is how many deaths you have:"),
addIntoLoad: true
)
Scoreboard("death_count")
// load.mcfunction:
/scoreboard objectives add death_count deathCount [{"text":"This is how many deaths you have:"}]
So the second scoreboard was not added because one "death_count" already existed.
The Scoreboard.add
constructor does exactly the same but puts the result without checking in the current file.
Scoreboard.remove
removes an objective by its name again.
With Scoreboard.setdisplay
you can display the values:
Scoreboard.setdisplay | |
---|---|
String | name of the objective(required) |
display | String for display location (default = sidebar) |
Score #
The score class is the basis for setting values, calculating with scores and checking the values. It implements one base class with no functionality and several methods to do actions:
constructor | |
---|---|
Entity | the entity within the scoreboard |
String | the name of the objective |
addNew | bool whether it should add the scoreboard itself if it does not exist(default = true) |
With the addNew property it is not required to add a scoreboard before!
Calculations
These methods can be used to set or calculate the value:
name | arguments |
---|---|
set | int |
reset | |
add | int |
subtract | int |
The following compare another Score | |
setEqual | Score |
swapWith | Score |
setToSmallest | Score |
setToBiggest | Score |
addScore | Score |
subtractScore | Score |
multiplyByScore | Score |
divideByScore | Score |
modulo | Score |
setToData | Data |
setToResult | Command,useSuccess(bool) |
All of these methods return a new instance of Score with the calculations applied. So you can also chain single calculations or use multiple on one base Score.
Examples:
// defining scores variables inside the widget
Score base = Score(Entity.Selected(),"score",addNew: true)
Score another = Score(Entity.Selected(),"score2")
// ... in the generate method:
base.set(5).add(3).subtract(10).reset()
⇒ scoreboard players set @s score 5
⇒ scoreboard players add @s score 3
⇒ scoreboard players remove @s score 10
⇒ scoreboard players reset @s score
base.setEqual(another).swapWith(another).setToBiggest(another)
⇒ scoreboard players operation @s score = @s score2
⇒ scoreboard players operation @s score >< @s score2
⇒ scoreboard players operation @s score > @s score2
another.addScore(base).divideByScore(base).modulo(base)
⇒ scoreboard players operation @s score2 += @s score
⇒ scoreboard players operation @s score2 /= @s score
⇒ scoreboard players operation @s score2 %= @s score
// setToData must take in Data.get
base.setToData(Data.get(Location("~ ~ ~"),"Items[0].Count"))
⇒ execute store result score @s score run data get block ~ ~ ~ Items[0].Count 1
// using success instead of result
base.setToResult(Command("say hi"),useSuccess:true)
⇒ execute store success score @s score run say hi
Conditions
These methods can be used for example with if to match values:
name | arguments | example Result |
---|---|---|
matches | int | @s score matches 5 |
matchesRange | Range | @s score matches 0..20 |
isEqual | Score | @s score = @s score2 |
isSmaller | Score | @s score < @s score2 |
isSmallerOrEqual | Score | @s score <= @s score2 |
isBigger | Score | @s score > @s score2 |
isBiggerOrEqual | Score | @s score >= @s score2 |
Block #
There is also a util class called Block which provides a wrapper for all available blocks in Minecraft. Usage:
Block([minecraft_block_id]) // as string or
Block.[minecraft_block_id]
All ids can be found here. But you can also insert a block by its string:
constructor | |
---|---|
String | the minecraft block id |
Example:
SetBlock(
Block.stone,
location: Location.here()
)
Location #
In the block example we already used a class called Location. This translates into Minecraft Coordinates.
constructor | |
---|---|
String | the minecraft coordinate string(e.g "~ ~ ~") |
SetBlock(Block.stone,location: Location("~ 5 ~"))
There is also a shortcut for " ~ ~ ~ ":
Location.here | Selects the current Position |
---|
Location.here()
⇒ ~ ~ ~
But the Location class also provides a wrapper for global coordinates:
Location.glob | |
---|---|
x | a double defining the absolute x coordinate |
y | a double defining the absolute y coordinate |
z | a double defining the absolute z coordinate |
Location.glob(x: 5,y: 51.5,z: 784.20)
⇒ 5 51.5 784.2
And also for relative coordinates:
Location.rel | |
---|---|
x | a double defining the relative x coordinate |
y | a double defining the relative y coordinate |
z | a double defining the relative z coordinate |
Location.rel(x: 5,y: 1.5,z: 0)
⇒ ~5 ~1.5 ~
And local coordinates(depends on the rotation of the head):
Location.local | |
---|---|
x | a double defining the local x coordinate |
y | a double defining the local y coordinate |
z | a double defining the local z coordinate |
Location.local(x: 0,y: 1,z: 2.5)
⇒ ^ ^1 ^2.5
There is also a method for a location:
methods | |
---|---|
storeResult | Command, path, useSuccess |
This stores a result or success of a command in the nbt path of a location. | |
Example: |
Location.here().storeResult(Command('say hello'),path: "Items[0].tag.command",useSuccess:true)
⇒ execute store success block ~ ~ ~ Items[0].tag.command run say hello
Area #
The Area class provides a way to select a three dimensional space between some locations. Therefore it automatically builds the lowest and highest coordinates and calculates the distances.
constructor | doubles |
---|---|
x1 | one x corner |
y1 | one y corner |
z1 | one z corner |
x2 | second x corner |
y2 | second x corner |
z2 | second x corner |
This is especially useful for if blocks , Fill and Clone. |
Example:
Area(x1: 100, y1: -15.75, z1: 0, x2: 2, y1: 10, z2: -10)
⇒ 2 -15.75 -10 100 10 0
But if you would also like local or relative coordinates, you can always pass the locations directly:
Area.fromLocations | |
---|---|
Location | location 1 |
Location | location 2 |
Rotation #
The Rotation class is very similar to Location but takes in just two directions for an entities rotation:
constructor | |
---|---|
String | the minecraft coordinate string(e.g "~ ~") |
Rotation.glob | |
---|---|
x | int representing global x orientation |
y | int representing global y orientation |
Rotation.rel | |
---|---|
x | int representing rotation relative to the current x orientation |
y | int representing rotation relative to the current y orientation |
Example:
Rotation.rel(x: 90,y: 180)
⇒ ~90 ~180
Execute.rotated(Rotation.glob(x:0,y:90),children:[
Command("tp @s ^ ^ ^10")
])
⇒ execute rotated 0 90 run command tp @s ^ ^ ^10
Data #
The Data Widgets allows you to edit nbt data of Entities or Blocks.
constructor | |
---|---|
dynamic | The target Entity OR Block which you want to modify |
nbt | A Dart Map containing new nbt data |
type | A String defining the operation type(default=merge) |
Example:
Data(
Entity.Selected(),
nbt: {
"Invisible":1,
"NoGravity":1
}
)
⇒ data merge entity @s {"Invisible":1,"NoGravity":1}
There are also subconstructors for each operation type(Data.merge, Data.get, Data.remove)
And the modify operation is also available, yet a bit more complex:
Data.modify | |
---|---|
dynamic | The target Entity OR Location which you want to modify |
path | the nbt path you want to modify |
modify | A DataModify object defining which parameters you want to modify |
So this is split up into a seperate class: DataModify There are five sub operations again: set, merge, prepend, append and insert. All follow this constructor rules:
DataModify | |
---|---|
dynamic | The source of the modification. Can be a Map, String, Number, Entity or Location |
fromPath | optional path for the Entity or Location source from where to read the data |
So we can for Example use
Data.modify(
Entity.Selected(),
path: "my_Custom_Path",
modify: DataModify.set(
"hey" // or {"nbt":"here"} or 56
),
)
⇒ data modify @s my_Custom_Path set value "hey"
Or So we can for Example use
Data.modify(
Entity.Selected(),
path: "my_Custom_Path2",
modify: DataModify.insert(
Entity.Selected(), // or Location... to get data from a block
index: 2, // insert also needs an additional index
fromPath: "my_Custom_Path"
),
)
// this just copies one property to another
⇒ data modify @s my_Custom_Path2 insert from entity @s my_Custom_Path
A handy shortcut for that is the Data.copy constructor, which just copies a property from one path to another:
Data.copy | |
---|---|
dynamic | The target Entity OR Location which you want to modify |
path | the nbt path you want to copy to |
from | The source Entity OR Block |
fromPath | The source nbt path |
Data.copy(
Entity.Selected(),
path: "my_Custom_Path2",
from: Location("~ ~-1 ~"),
fromPath: "Items[0].tag.display.name"
)
⇒ data modify @s my_Custom_Path2 set from block ~ ~-1 ~ Items[0].tag.display.name
Item #
The Item class represents an item in an inventory in Minecraft. It is used in the Give or Nbt Commands.
This Class is incomplete, more functionality soon...
constructor | |
---|---|
ItemType | Block | String | the type of item(required, see example) |
count | Integer value for the amount of stacked items |
slot | The current slot of the item(does not work for give) |
damage | the used durability of the item |
model | int describing which model varient should be used |
nbt | addional NBT as Dart Map |
Example:
Give(Entity.Selected(),
item: Item(
ItemType.iron_axe, // OR Block.stone OR "whatever id"
count: 5,
damage: 40,
model: 3390001,
nbt: {
"customNBT":1
}
)
)
⇒ give @s minecraft:iron_axe{"customNBT":1,"Damage":40,"CustomModelData":3390001} 5
ItemType is like EntityType or Block a utility class to provide a list of all available items.
ItemType([minecraft_item_id]) | creates a ItemType from a String |
---|---|
ItemType.[minecraft_item_id] | there is also an value for each item in Minecraft |
Command Wrappers #
In this section are a few classes that build commands with inputs(Entities, Texts, Blocks, Locations).
Comment #
The Comment widget generates a simple line with some annotations(# ...). It also features a simple line break: Example:
Comment("hello world")
⇒ # hello world
Comment.LineBreak()
⇒
Execute #
One of the most used commands has a widget too. The execute command has multiple syntaxes that allow to manipulate the position, executer or condition.
constructor | |
---|---|
children | a List of children that should be executed(required) |
encapsulate | weither the children should be in an extra file for a certain length |
as | an Entity that runs the commands |
at | an Entity from where the command should run |
If | a Condition that must be true to execute the commands |
location | a Location or Entity from where to run the commands |
align | String with align statements e.g: "xyz" |
anchor | either Facing.eyes or Facing.feet |
facing | A Location or Entity to rotate to |
rotation | A rotation of type Rotation |
dimension | Dimension of overworld, the_end or the_nether |
All Execute classes are also an Group, so they will group commands in seperate files and allow multiple children. Example:
Execute(
as: Entity.player(),
at: Entity.Selected(),
If: Condition.entity(Entity())
location: Location.here(),
align: "yz",
anchor: Facing.eyes,
facing: Location().glob(x:0,y:0,z:0)
rotation: Rotation.rel(x:10,y:20),
dimension: Dimension.the_nether
children: List<Widget> [
Command("/say I get executed")
Say(msg:"Me too")
]
),
⇒ execute as @p at @s if entity @e positioned ~ ~ ~ align yz anchored eyes facing 0 0 0 rotated ~10 ~20 in the_nether run say I get executed
execute as @p at @s if entity @e positioned ~ ~ ~ align yz anchored eyes facing 0 0 0 rotated ~10 ~20 in the_nether run say Me too
Execute. as | |
---|---|
Entity | the entity from which the children should run |
children | a List of children that should be executed |
[encapsulate] | same as base |
This is just a different notation for Execute.
Execute.as(
Entity.player(),
children: List<Widget> [
Command("/say I get executed")
]
),
⇒ execute as @p run say I get executed
Execute. at | |
---|---|
Entity | the entity from where the children should run |
children | a List of children that should be executed |
[encapsulate] | same as base |
Execute.at(
Entity.player(),
children: List<Widget> [
Command("/say I get executed")
]
),
⇒ execute at @p run say I get executed
Execute.asat | |
---|---|
Entity | the entity from which and where the children should run |
children | a List of children that should be executed |
[encapsulate] | same as base |
Asat combines as and at to just one entity.
Execute.asat(
Entity.player(),
children: List<Widget> [
Command("/say I get executed")
]
),
⇒ execute as @p at @s run say I get executed
Execute.positioned | |
---|---|
Entity|Location | the new position |
... |
Positioned sets the execution point of the command to a new Location or Entity.
Execute.positioned(
Entity.player(), // Location...
children: List<Widget> [
Command("/say I get executed")
]
),
⇒ execute positioned as @p run say I get executed
Execute.align | |
---|---|
String | representation of the alignment |
... |
Aligns the position to the corners of the block grid.
Execute.anchored | |
---|---|
Facing | Facing.eyes or Facing.feet |
... |
Sets the execution position(^ ^ ^) to the eyes or the feet.
Execute.facing | |
---|---|
Entity or Location | the target to face(required) |
facing | either face the Facing.eyes(default) or Facing.feet |
... |
Sets the execution rotation so that it faces a location or an entity's feet or eyes. Example:
Execute.facing(
Entity.player(), // or Location...
facing: Facing.feet // optional
children: List<Widget> [
Command("/say I get executed")
]
)
⇒ execute facing entity @p feet run say I get executed
Execute.rotated | |
---|---|
Rotation | the rotation object |
... |
Sets the execution rotation to the given rotation.
Execute.dimension | |
---|---|
Dimension | the given dimension type |
... |
Sets the execution dimension(execute in) to either Dimension.overworld
, Dimension.the_end
or Dimension.the_nether
.
Methods #
All of these constructors are also available as methods with some additional utils:
Methods | |
---|---|
center | centeres the alignment(middle of the block) |
That means you can chain the actions, like with score, and use multiple actions at once:
// declaring the base
Execute ex = Execute(
children:[
Say(msg:"Hello"),
Command("say e")
]
)
// in the generate method:
ex.asat(
Entity.All())
.center()
.positioned(Location.rel(x:0,y:20,z:0))
⇒ execute as @a at @s align xyz positioned ~0.5 ~0.5 ~0.5 positioned ~ ~20 ~ run say Hello
execute as @a at @s align xyz positioned ~0.5 ~0.5 ~0.5 positioned ~ ~20 ~ run say e
If #
The if widget accepts a Condition and runs the children if the condition is true. If just gives you an execute wrapper with if and else statements. The conditions have their own class.
constructor | |
---|---|
Condition | the condition |
Then | a List of Wigets that runs on match |
Else | a List of Widget that runs if it does not match(optional) |
Example:
If(
Condition(Entity.Player()),
Then: [
Say(msg:"true")
],
Else: [
Say(msg:"false")
]
)
⇒ execute if entity @p run say true
⇒ execute unless entity @p run say false
Not Final! Will be done with tags later on.
You can also negate the Condition with If.not
:
If.not(
Condition(Entity.Player()),
Then: [
Say(msg:"true")
]
)
⇒ execute unless entity @p run say true
Condition #
The Condition class defines conditions for the if widget and more. It can also combines conditions and generates an argument list.
constructor | |
---|---|
dynamic | the thing you want to test |
Well it is not as easy as it looks. A condition can accept many values and this makes the Condition very complex. |
The argument can be a... | and generates e.g | |
---|---|---|
Entity | if entity @s | |
Score | if score @s objective matches 5 | Attention! This needs a score condition method! |
Location | unless block ~ ~2 ~ air | Just checks whether a block is present |
Condition | if entity @s if block ~ ~ ~ stone | Yes, you can nest Conditions like Widgets and combine them. |
Examples:
If(
Condition(
Entity.Selected()
)
,Then:[Say(msg:'entity')],
)
⇒ execute if entity @s run say entity
If(
Condition(
Location.here()
),
Then:[Say(msg:'block')],
)
⇒ execute unless block ~ ~ ~ minecraft:air run say block
If.not(
Condition(
Score(
Entity.PlayerName("Stevertus"),
"objective"
).matches(10)
),
Then:[Say(msg:'score')],
)
⇒ execute unless score Stevertus objective matches 10 run say score
For Score, Block and Entity there is also a named constructor along with:
Condition.blocks | |
---|---|
Area | the Area of blocks that you want to compare |
compare | the lowest comparison Location of the area of the same size |
Condition.block: also requires a block type:
If(
Condition.block(
Location.here(),
block: Block.stone
),
Then:[Say(msg:'stone')],
)
⇒ execute if block ~ ~ ~ minecraft:stone run say stone
Condition.not: accepts same dynamic condition types as above but negates them (if ⇒ unless, unless ⇒ if)
Condition.and: accepts a list of dynamic condition types, that all have to be true to trigger:
If(
Condition.and([
Location.here(),
Entity(),
Condition(...)
]),
Then:[Say(msg:'true')],
)
⇒ execute unless block ~ ~ ~ minecraft:air if entity @e if ... run say true
Condition.or: accepts a list of dynamic condition types, but just one has to be true to trigger:
If(
Condition.or([
Location.here(),
Entity(),
Condition(...)
]),
Then:[Say(msg:'true')],
)
⇒ execute unless block ~ ~ ~ minecraft:air run say true
⇒ execute if entity @e run say true
⇒ execute if ... run say true
Just temporary, will be done with tags later...
With this knowledge we can build pretty complex logical conditions:
If.not(
Condition.and([
Condition.not(Entity.Player()),
Condition.or([
Entity.Random(),
Condition.blocks(
Area(x1: 0, y1: 0, z1: 0, x2: 10, y2: 10, z2: 10),
compare: Location('~ ~ ~'),
),
Condition.not(
Condition.score(
Score(Entity.Selected(),"test")
.matchesRange(Range(from:0,to:5))
),
),
]),
]),
Then: [Say(msg:"I'm done")]
)
⇒ execute unless entity @p if entity @r run say I'm done
⇒ execute unless entity @p if blocks 0 0 0 10 10 10 ~ ~ ~ run say I'm done
⇒ execute unless entity @p unless score @s test matches 0..5 run say I'm done
SetBlock #
The SetBlock Command Class sets a Block at the specified location:
constructor | |
---|---|
Block | the Block type you want to set |
location | where you want to set the block |
Example:
SetBlock(
Block.stone,
location: Location.glob(
x: 5,
y: 0,
z: 20
)
)
⇒ setblock 5 0 20 minecraft:stone
Fill #
Fill acts similar to setblock, but fills a whole area instead.
constructor | |
---|---|
Block | the fill material |
area | the Area to fill |
Tip: There are also constructors for Fill.destroy, Fill.hollow, Fill.outline and Fill.keep
Example:
Fill(
Block.dirt,
area: Area.fromLocations(
Location.glob(x: 0, y: 0, z: 0),
Location.glob(x: 10, y: 20, z: 10)
),
)
⇒ fill 0 0 0 10 20 10 minecraft:dirt
You can also just replace specific other blocks:
Fill.replace | |
---|---|
... | Everything the same |
replace | the Block type you want to replace |
Example:
Fill.replace(
Block.dirt,
area: Area.fromLocations(
Location.glob(x: 0, y: 0, z: 0),
Location.glob(x: 10, y: 20, z: 10)
),
replace: Block.stone,
)
⇒ fill 0 0 0 10 20 10 minecraft:dirt replace minecraft:stone
Say #
The Say Class writes a simple message or an entity in the chat.
constructor | |
---|---|
msg | Message as String |
entity | enity of type Entity |
You can't put both parameters in Say!
Example:
Say(
msg: "Hello"
)
⇒ say Hello
Say(
entity: Entity.Player()
)
⇒ say @p
Give #
Gives a item to a player.
constructor | |
---|---|
Entity | The player |
item | the Item you want to give(required) |
Example:
Give(Entity.Player(),
item: Item(
ItemType.apple,
count: 5
)
)
⇒ give @s minecraft:apple 5
Replaceitem #
Sets a specific container slot to a item.
- for Entities:
constructor | |
---|---|
Entity | The entity |
item | the Item you want to set(required) |
slot | a String representation of the slot(required) |
Example:
Replaceitem(Entity.Player(),
slot: "hotbar.5"
item: Item(
ItemType.apple,
count: 5,
model: 339001
)
)
⇒ replaceitem entity @p hotbar.5 minecraft:apple{"CustomModelData":339001} 5
replaceitem block will follow
Summon #
The summon class creates a new entity at a given location.
constructor | |
---|---|
EntityType | the type of entity(required) |
location | the location as type Location(default Location.here()) |
name | a TextComponent respresenting the name of the entity |
nbt | additional nbt as Map(key-value pairs) |
This version is not final, there will be more properties in the future!
Example:
Summon(
EntityType.armor_stand,
location: Location.rel(x: 0,y:1,z:0),
name: TextComponent("this is my name",color: Color.DarkBlue),
nbt: {"Invisible":1}
)
⇒ summon armor_stand ~ ~1 ~ {"Invisible":1,"CustomName":"{\"text\":\"this is my name\",\"color\":\"dark_blue\"}"}
Teleport #
Sets the location of an Entity to a new Location and Rotation(optional).
constructor | |
---|---|
Entity | the entity you want to teleport(required) |
to | the target Location(required) |
facing | a Location or Entity to face |
rotation | a Rotation object defining the new rotation |
Example:
Teleport(
Entity.Player(),
to: Location.glob(x: 5, y: 10, z: 5),
facing: Location.here()
)
⇒ tp @p 5 10 5 facing ~ ~ ~
And you can also teleport to another entity:
Teleport.entity | |
---|---|
Entity | the entity you want to teleport(required) |
to | the target entity(required) |
facing | a Location or Entity to face |
Teleport(
Entity.Player(),
to: Entity(name: "target", limit: 1)
)
⇒ tp @p @e[name="target",limit=1]
Texts and Strings #
In Minecraft text in the chat or as title is defined with JSON-data. objD makes the JSON part of it easier by utilizing a few classes:
TextComponent | |
---|---|
String | the text displayed (required) |
color | a the color of the type Color |
bold | bool whether it is bold |
italic | bool whether it is italic |
underlined | bool whether it is underlined |
strikethrough | bool whether it is strikethrough |
obfuscated | bool whether it is obfuscated |
clickEvent | A TextClickEvent to handle left clicks |
hoverEvent | A TextHoverEvent to handle mouse overs |
insertion | a String witch is inserted into the input if shift left clicked |
Puuh, that are a lot of properties, we'll come to Color, TextClickEvent and TextHoverEvent in a bit.
Example
Title(
Entity.Player(),
show: [
TextComponent("Hello",
color: Color.White,
bold: true,
italic:true,
underlined: true,
strikethrough: false,
obfuscated: false,
clickEvent: TextClickEvent.open_url("https://stevertus.com"),
hoverEvent: TextHoverEvent.text([TextComponent("hover me")]),
insertion: "panic"
)
]
)
⇒ title @p title [{"text":"Hello","color":"white","bold":true,"italic":true,"underlined":true,"clickEvent":{"action":"open_url","value":"https://stevertus.com"},"hoverEvent":{"action":"text","value":[{text:"hover me"}]}}]
Now, its up to you to decide which is easier to read. There are also some other data sources: TODO: new 1.14 types!
TextComponent.translate | |
---|---|
String | the translate key (required) |
conversionFlags | a List of strings that replace placeholder values(e.g $s) |
...same properties... | from TextComponent |
TextComponent.score | |
---|---|
Entity | the entity with the score(required) |
objective | Name of the Scoreboard Objective(required) |
...same properties... | from TextComponent |
TextComponent.score(
Entity.Selected(),
objective: "myscores",
color:Color.Black
)
⇒ {"score":{"name": "@s","objective":"myscores"},"color":"black"}
TextComponent.selector | |
---|---|
Entity | the entity whose name you want to display(required) |
...same properties... | from TextComponent |
TextComponent.selector(
Entity(name:"hello"),
color:Color.Black
)
⇒ {"selector":"@e[name=hello]","color":"black"}
Colors #
Color([color_name]) | or |
---|---|
Color.[color_name] | Uppercase! |
See all available colors: https://minecraft.gamepedia.com/Formatting_codes#Color_codes
Examples:
Color.Black,
Color.DarkPurple
Color("gold")
Color('dark_green')
TextClickEvent #
Fires on left click, Part of TextComponent.
constructors | |
---|---|
TextClickEvent.open_url(String) | Opens the specified web url |
TextClickEvent.run_command(Command) | runs the command |
TextClickEvent.suggest(Command) | puts the command in the chat input |
TextClickEvent.change_page(int) | turns a books page to the value(just Books!) |
TextHoverEvent #
Fires on mouse over, Part of TextComponent.
constructors | |
---|---|
TextClickEvent.text(List<TextComponent>) | Accepts a new List of TextComponents to display |
TextClickEvent.achievement(String) | shows achievement |
TextClickEvent.item(Item) | shows item |
TextClickEvent.entity(String,String,String) | displays a dummy entity with name, type and UUID(in this order)) |
Title #
To display our TextComponent, we need the /title
command and the Title class wrapper.
constructor | |
---|---|
selector | the Entity for the title to show |
show | A List of TextComponents to show |
Example
Title(
Entity.Player(),
show: List<TextComponent>[
TextComponent(
"hey",
color: Color.Black
)
]
)
⇒ title @p title [{"text":"hey","color":"black"}]
The same goes also for subtitle and actionbar:
Title.subtitle or Title.actionbar | |
---|---|
selector | the Entity for the title to show |
show | A List of TextComponents to show |
Title.clear clears all titles again:
Title.clear | |
---|---|
selector | clears title for the selector |
Title.times sets the timings
Title.times | |
---|---|
selector | edit the durations for this selector |
fadein | the fadein time in ticks(default 20) |
display | the time the title stays in ticks(default 60) |
fadeout | the fadeout time in ticks(default 20) |
And also a resetter for that:
Title.resetTimes | |
---|---|
selector | resets times for this selector |
Examples:
Title.actionbar(
Entity.All(),
show: [
TextComponent("hey")
]
)
⇒ title @a actionbar [{"text":"hey"}]
Title.clear(Entity())
⇒ title @e clear
Title.times(Entity.All(),fadein:30,display:40,fadeout:20)
⇒ title @a times 30 40 20
Title.resetTimes(Entity.All())
⇒ title @a reset
Tellraw #
The Tellraw class is very similar to the Title class, but shows its texts in the chat:
constructor | |
---|---|
selector | the Entity for the text to show |
show | A List of TextComponents to show |
Example
Tellraw(
Entity.Player(),
show: List<TextComponent>[
TextComponent(
"hey",
color: Color.Black
)
]
)
⇒ tellraw @p [{"text":"hey","color":"black"}]