objd 0.0.4
objd: ^0.0.4 copied to clipboard

outdated

objd is a Object Oriented framework for Building Minecraft Datapacks with ease

ObjectiveD 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.4

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/code.dart';

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 objectiveD.

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')
	}
}

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
namethe name of the datapack folder
generatea 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
namethe 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, therefore this is the definition. The File constructor has two required arguments:

constructor
paththe desired file path going from /data/:packId:/functions/ on
childthe 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(...)
		)
	),
)

Command #

A Command is a raw action, that is executed by Minecraft directly.

constructor
Stringthe 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
tothe ending index including itself
createa 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 Widgetsloops 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
Lista 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
Stringlist of commands each on a seperate line
CommandList.str("""
	/say 1
	/say 2
	/say 3
"""),

The tabs are automatically filtered.

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
prefixa prefix type of String
childrenthe 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
),

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
childrena List of children that should be executed
[encapsulate]weither the children should be in an extra file for a certain length
[as]an Entity that runs the command
[at]an Entity from where the command should run

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.self(),
	children: List<Widget> [
		Command("/say I get executed")
	]
),

⇒ execute as @p at @s run say I get executed
Execute. as
Entitythe entity from which the children should run
childrena 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
Entitythe entity from where the children should run
childrena 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
Entitythe entity from which and where the children should run
childrena 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

Entity #

constructorarguments are optional
selectorthe entity selector(e.g p,s,e or r)
limitnumber of matched entities
typeEntityType, id of the entity
distanceRange to the entity
levelRange of experience levels
gamemodeGamemode type(e.g Gamemode.creative, Gamemode.survival)
horizontalRotationRange of the horizontal facing direction
verticalRotationRange of the vertical facing direction
Methods
sortadds a sort attribute of type Sort
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
StringString 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),
		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,level=1..,gamemode=creative,y_rotation=1..,x_rotation=20..80,sort=random]

Block #

There is also a util class called Block which provides a wrapper for all available blocks in Minecraft. Usage:

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
Stringthe minecraft coordinate string(e.g "~ ~ ~")
SetBlock(Block.stone,location: Location("~ 5 ~"))

There is also a shortcut for " ~ ~ ~ ": |Location.here| Selects the current Position | |--|--|

But the Location class also provides a wrapper for global coordinates:

Location.glob
xa double defining the absolute x coordinate
ya double defining the absolute y coordinate
za 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
xa double defining the relative x coordinate
ya double defining the relative y coordinate
za 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.rel
xa double defining the local x coordinate
ya double defining the local y coordinate
za double defining the local z coordinate
Location.local(x: 0,y: 1,z: 2.5)
⇒ ^ ^1 ^2.5

Command Wrappers #

In this section are a few classes that build commands with inputs(Entities, Texts, Blocks, Locations).

SetBlock #

The SetBlock Command Class sets a Block at the specified location:

constructor
Blockthe Block type you want to set
locationwhere 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

Say #

The Say Class writes a simple message or an entity in the chat.

constructor
msgMessage as String
entityenity of type Entity

You can't put both parameters in Say!

Example:

Say(
	msg: "Hello"
)
⇒ say Hello
Say(
	entity: Entity.Player()
)
⇒ say @p

Summon #

The summon class creates a new entity at a given location.

constructor
EntityTypethe type of entity(required)
locationthe location as type Location(default Location.here())
namea TextComponent respresenting the name of the entity
nbtadditional 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\"}"}

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
Stringthe translate key (required)
conversionFlagsa List of strings that replace placeholder values(e.g $s)
...same properties...from TextComponent
TextComponent.score
Entitythe entity with the score(required)
objectiveName of the Scoreboard Objective(required)
...same properties...from TextComponent
TextComponent.score(
	Entity.Self(),
	objective: "myscores",
	color:Color.Black
)
⇒ {"score":{"name": "@s","objective":"myscores"},"color":"black"}
TextComponent.selector
Entitythe 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(String)shows item(Warning!: Not final)
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
selectorthe Entity for the title to show
showA 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
selectorthe Entity for the title to show
showA List of TextComponents to show

Title.clear clears all titles again:

Title.clear
selectorclears title for the selector

Title.times sets the times

Title.times
selectoredit the durations for this selector
fadeinthe fadein time in ticks(default 20)
displaythe time the title stays in ticks(default 60)
fadeoutthe fadeout time in ticks(default 20)

And also a resetter for that:

Title.resetTimes
selectorresets 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
selectorthe Entity for the text to show
showA List of TextComponents to show

Example

Tellraw(
	Entity.Player(),
	show: List<TextComponent>[
		TextComponent(
			"hey",
			color: Color.Black
		)
	]
)
⇒ tellraw @p [{"text":"hey","color":"black"}]
2
likes
0
pub points
52%
popularity

Publisher

stevertus.com

objd is a Object Oriented framework for Building Minecraft Datapacks with ease

Homepage

Documentation

Documentation

License

unknown (LICENSE)

Dependencies

colorize, meta

More

Packages that depend on objd