From ba7d177c8d825e9e372eace43016761b8bb3cdb2 Mon Sep 17 00:00:00 2001 From: Stevertus Date: Sun, 17 Mar 2019 14:14:24 +0100 Subject: [PATCH] v0.1.2 --- .packages | 2 +- CHANGELOG.md | 18 ++ Documentation.md | 319 +++++++++++++++++++++++++++++++-- README.md | 2 +- example/files/main.dart | 1 - lib/basic/entity.dart | 29 +-- lib/basic/file.dart | 13 +- lib/basic/for_list.dart | 5 +- lib/basic/group.dart | 2 +- lib/basic/location.dart | 6 +- lib/basic/rotation.dart | 5 +- lib/basic/score.dart | 9 + lib/basic/tag.dart | 33 ++++ lib/basic/widgets.dart | 1 + lib/build/build.dart | 7 +- lib/utils/areaeffectcloud.dart | 72 ++++++++ lib/utils/armorstand.dart | 110 ++++++++++++ lib/utils/hologram.dart | 51 ++++++ lib/utils/log.dart | 32 ++++ lib/utils/randomScore.dart | 56 ++++++ lib/utils/repeat.dart | 30 ++++ lib/utils/widgets.dart | 6 + lib/wrappers/data.dart | 2 +- lib/wrappers/effect.dart | 74 ++++---- lib/wrappers/if.dart | 1 - lib/wrappers/setblock.dart | 7 +- lib/wrappers/summon.dart | 68 +++++-- lib/wrappers/team.dart | 122 +++++++++++++ lib/wrappers/teleport.dart | 13 +- lib/wrappers/widgets.dart | 3 +- pubspec.yaml | 5 +- 31 files changed, 1009 insertions(+), 95 deletions(-) create mode 100644 lib/utils/areaeffectcloud.dart create mode 100644 lib/utils/armorstand.dart create mode 100644 lib/utils/hologram.dart create mode 100644 lib/utils/log.dart create mode 100644 lib/utils/randomScore.dart create mode 100644 lib/utils/repeat.dart create mode 100644 lib/wrappers/team.dart diff --git a/.packages b/.packages index 5861422..f37bd99 100644 --- a/.packages +++ b/.packages @@ -1,4 +1,4 @@ -# Generated by pub on 2019-03-07 22:02:36.189436. +# Generated by pub on 2019-03-17 14:13:26.375439. async:file:///C:/Users/Marten/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/async-2.0.8/lib/ collection:file:///C:/Users/Marten/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/collection-1.14.11/lib/ colorize:file:///C:/Users/Marten/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/colorize-2.0.0/lib/ diff --git a/CHANGELOG.md b/CHANGELOG.md index a11187c..42ed0b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +## 0.1.2 +* added RandomScore +* added a Team wrapper +* added a team option for entities as well as joinTeam and leaveTeam methods +* added Repeat to repeat code with delay +* added Log Widget to quickly print Messages, Scores or Entities in the chat +* added ArmorStand Widget to create an armorstand +* added Hologram to display text +* added AreaEffectCloud +* added Tag.toggle +* added a create option to File +* added a nbt option for Setblock +* added Score.fromSelected to avoid annoying Entity.Selected +* changed summon arguments +* changed effect to also support nbt effects +* changed Location to optional arguments +* fixed when there are two identical files that they would extend + ## 0.1.1 * added AroundLocation widget * added Trigger wrapper diff --git a/Documentation.md b/Documentation.md index 72b419c..d175264 100644 --- a/Documentation.md +++ b/Documentation.md @@ -33,7 +33,7 @@ And inside of that create a file named `pubspec.yaml` and another folder called Open the pubspec.yaml file and add ```yaml dependencies: - objd: ^0.1.1 + objd: ^0.1.2 ``` And run ``` @@ -88,6 +88,7 @@ What we are doing right now is to generate a new subpack with a name(This will b 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. +We can use the Log Widget to display a message to the player. ```dart main: File( path: 'main', @@ -95,7 +96,7 @@ main: File( ) ``` But how to add a list of Actions then? Well there's also an Widget for that: -[For.of]() +`For.of` ```dart child: For.of(List[ Log('Hello World'), @@ -212,7 +213,8 @@ The File constructor has two required arguments: |--|--| | 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 | +| execute | bool if the function should be executed directly(optional) | +| create | bool if the file should be created or just interpreted with execute(optional, default = true)| 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:** @@ -392,9 +394,10 @@ Group( |limit|number of matched entities| |tags|a List of Strings or Tags that the entity should have| |scores|a List of Score matches that the entity should match| +|team|a Team the entity has to be part of| |type|[EntityType](), id of the entity| |nbt|a Map of required nbt properties| -|area|A List of two Locations marking an area where the entity should be| +|area|A 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)| @@ -404,6 +407,8 @@ Group( |**Methods** | | |sort|adds a sort attribute of type [Sort]()| | storeResult | Command, path, useSuccess | +|joinTeam|entity joins the given team| +|leaveTeam|entity leaves the current team| |addTag|adds a new tag to the entity| |addTags|adds multiple tags| |removeTag| removes tag again| @@ -446,15 +451,15 @@ Say( selector: "e", limit: 1, tags:["first","second"], - scores:[Score(score1).matches(10)] + scores:[Score(score1).matches(10)], + team: Team("my_team"), type: EntityType.armor_stand, distance: Range(to:2), - area: [ + area: Area.fromLocations( // 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), @@ -462,7 +467,7 @@ Say( ).sort(Sort.random) ) -⇒ say @e[limit=1,tag=first,tag=second,scores:{test=10},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] +⇒ say @e[limit=1,tag=first,tag=second,scores:{test=10},team=my_team,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| | @@ -499,6 +504,24 @@ mytag.remove() ⇒ tag @p remove firstTag ``` Also consider the addTag method on an entity. +### toggle +With the toggle method you can toggle the value(invert the tag). This is done with a temporary tag: +```dart +Tag("mytag",entity:Entity.Selected()).toggle() +⇒ execute if entity @s[tag=mytag] run tag @s add objd_temp +⇒ execute if entity @s[tag=objd_temp] run tag @s remove mytag +⇒ execute if entity @s[tag=!objd_temp] run tag @s add mytag +⇒ tag @s remove objd_temp +``` +### removeIfExists +The `removeIfExists` method removes the tag and may execute some action before if the tag exists. +```dart +Tag("mytag",entity:Entity.Selected()).removeIfExists( + then: Say(msg:"removed") +) // optional argument +⇒ execute if entity @s[tag=mytag] run say removed +⇒ execute if entity @s[tag=mytag] run tag @s remove mytag +``` [//]: # (basics/scoreboard) ## Scoreboard @@ -632,6 +655,13 @@ This will automatically create a scoreboard called `objd_consts` and set the val Score.con(5) ⇒ scoreboard players set #5 objd_consts 5 ``` +### Selected Score +Often times you want the score of a selected Entity(@s). Score.fromSelected is the same as Score but has a predefined entity. +**Example:** +```dart +Score.fromSelected("objective").set(3) +⇒ scoreboard players set @s objective 3 +``` [//]: # (basics/block) ## Block @@ -1284,6 +1314,51 @@ execute if entity @p if score @s test matches 0..5 run tag @p add objd_isTrue1 execute as @p if entity @s[tag=objd_isTrue1] run say I'm done tag @p remove objd_isTrue1 ``` +[//]: # (wrappers/team) +## Team +The team Wiget is a wrapper for the team command and allows you to group entities together and apply group rules. + +There are a few constructors: + +**Team(String)** - just adds a new team +**Team.add(String,[options])** - adds the team and also applies some modifiers to it(take a look at Team.modify) +**Team.empty(String)** - clears the team and removes all entities in it +**Team.join(String, Entity)** - adds the entity to the team(an entity can only be in one team at a time) +**Team.leave(Entity)** - the entity is removed from their current team + +|Team.modify or Team.add| | +|--|--| +|String|name of the team| +|display|TextComponent showing the team name in chat or scoreboard| +|color| the teams Color | +|nametag| Either ModifyTeam.[always,never,hideForOtherTeam,hideForOwnTeam] | +|collision| Either ModifyTeam.[always,never,pushOtherTeams,pushOwnTeam] | +|deathMessage|Either ModifyTeam.[always,never,hideForOtherTeam,hideForOwnTeam] | +|friendlyFire|Should a member be able to hit a team mate?(bool)| +|seeInvisisble|Should a member be able to see an invisible team mate?(bool)| +|prefix| a String showing in front of a player name | +|suffix| a String showing after a player name | + +**Example:** +```dart +Team.add( + "test", + collision:ModifyTeam.always, + color:Color.Red, + display: TextComponent("Hello"), + friendlyFire: true, + suffix: "Test", + deathMessage: ModifyTeam.hideForOwnTeam +) +⇒ team add test +⇒ team modify test displayName {"text":"Hello"} +⇒ team modify test color red +⇒ team modify test deathMessageVisibility hideForOwnTeam +⇒ team modify test friendlyFire true +⇒ team modify test collisionRule always +⇒ team modify test suffix Test +``` + [//]: # (wrappers/effect) ## Effect This command is used to give an entity a specific effect and affect their gameplay. @@ -1329,6 +1404,7 @@ The SetBlock Command Class sets a Block at the specified location: |--|--| |Block|the Block type you want to set| |location| where you want to set the block| +|nbt|nbt as Map for the block| Example: ```dart @@ -1544,8 +1620,21 @@ The summon class creates a new entity at a given location. |EntityType|the type of entity(required)| |location| the location as type Location(default Location.here())| |name|a TextComponent respresenting the name of the entity| +|nameVisible|bool if name is shown| +|invulnerable|bool| +|persistent|bool| +|noAI|bool| +|silent|bool| +|small|bool| +|gravity|bool (put negated value in NoGravity)| +|glowing|bool| +|passengers|List of Summon Widgets that ride the entity| +|effects|List of Effects| +|tags|List of tags as String| +|fire|ticks(int) the entity should be on fire| +|age|int| +|rotation|initial Rotation| |nbt|additional nbt as Map(key-value pairs)| -> This version is not final, there will be more properties in the future! **Example:** ```dart @@ -1553,10 +1642,17 @@ 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} + invulnerable:true, + small: true, + gravity: false, + fire: 100, + effects:[Effect(EffectType.glowing,duration: 10,showParticles:false)], + rotation: Rotation.abs(x: 10,y:100), + nbt: {"Invisible":1}, ) -⇒ summon armor_stand ~ ~1 ~ {"Invisible":1,"CustomName":"{\"text\":\"this is my name\",\"color\":\"dark_blue\"}"} +⇒ summon armor_stand ~ ~1 ~ {"Invisible":1,"CustomName":"{\"text\":\"this is my name\",\"color\":\"dark_blue\"}","Invulnerable":1,"Small":1,"NoGravity":1,"ActiveEffects":[{"Id":24,"Amplifier":0,"Duration":200,"ShowParticles":0}],"Fire":100,"Rotation":[10.0,100.0]} ``` + [//]: # (wrappers/schedule) ## Schedule Schedule schedules a file for the future. It delays its execution by the given ticks. @@ -1610,7 +1706,7 @@ Teleport( ⇒ tp @p @e[name="target",limit=1] ``` -[//]: # (text/trigger) +[//]: # (wrappers/trigger) ## Trigger Trigger is a way to give the player(without op) permission to change his score in a scoreboard. The permission must be granted with `Trigger.enable`: @@ -1761,6 +1857,23 @@ Fires on mouse over, Part of TextComponent. |TextClickEvent.item(Item)|shows item| |TextClickEvent.entity(String,String,String)|displays a dummy entity with name, type and UUID(in this order))| +[//]: # (text/log) +## Log +The log widgets displays a console logging in the players chat. That way you can quickly check execution times, score values and entities. + +|constructor|| +|--|--| +|String, Score or Entity| message to display | +|to|which player you want to send the log(default = `Entity.All()`) | +|color|the color of the console indicator(default = Color.DarkAqua)| + +**Example:** +```dart +Log("Hello there!",color:Color.White), +⇒ tellraw @a [{"text":"Console > ","color":"white"},{"text":"Hello there!"}] +Log(Score(Entity.Selected(),"objective"),to: Entity.Selected()) +⇒ tellraw @s [{"text":"Console > ","color":"dark_aqua"},{"score":{"name":"@s","objective":"objective"}}] +``` [//]: # (text/title) ## Title @@ -1920,6 +2033,186 @@ Timer.stop("timer2") ``` This uses a tag internally to stop scheduling the next timeout if the tag is existing. +[//]: # (utils/repeat) +## Repeat +The Repeat Widget repeats a given action multiple times with a tick delay. + +|constructor| | +|--|--| +|String|name of the Repeat| +|child|the action to perform(required)| +|to| times to repeat(required) | +|ticks| ticks between repetitions(default = 1 tick) | +|path|where to generate a new repeat file(default = timers)| +|counter|the objective used to hold the current iteration(default = objd_repeat)| + +**Example:** +```dart +Repeat("repeat1", + to: 10, + child: Log("test"), + ticks: 20 +) +⇒ scoreboard players set repeat1 objd_repeat 0 +⇒ function mypack:timers/repeat1 +``` +This would save the current iteration in a fake player repeat1 in objd_repeat and generate a schedule function: +```mcfunction +# timers/repeat1 +tellraw @a [{"text":"Console > ","color":"dark_aqua"},{"text":"test"}] +scoreboard players add repeat1 objd_repeat 1 +execute if score repeat1 objd_repeat matches ..10 run schedule function mypack:timers/repeat1 20t +``` +This function is executed until the score becomes 11. + +[//]: # (utils/armorstand) +## ArmorStand +An armorstand can be created with the Summon Widget, but there is also a specific Widget with special properties for an ArmorStand. + +|constructor| | +|--|--| +|Location| the location as type Location(default Location.here())| +|name|a TextComponent respresenting the name of the entity| +|nameVisible|bool if name is shown| +|invulnerable|bool| +|invisible|bool| +|marker|bool| +|basePlate|bool| +|hasArms|bool| +|small|bool| +|gravity|bool| +|glowing|bool| +|tags|List of tags as String| +|fire|ticks(int) the entity should be on fire| +|rotation|initial Rotation| +|mainHand| An Item placed in the main hand| +|offHand| An Item placed in the offhand| +|head| An Item placed in the head slot| +|chest| An Item placed in the chest slot| +|legs| An Item placed in the legs slot| +|boots| An Item placed in the boots slot| +|nbt|additional nbt as Map(key-value pairs)| + +> Pose is coming soon + +This generates a summon command: +```dart +ArmorStand( +Location.here(), +name: TextComponent("Test", color: Color.DarkPurple), +nameVisible: true, +marker: true, +mainHand: Item(ItemType.clock), +) +⇒ summon armor_stand ~ ~ ~ {"Marker":1,"HandItems":[{"id":"minecraft:clock"},{}],"CustomName":"{\"text\":\"Test\",\"color\":\"dark_purple\"}","CustomNameVisible":1} +``` +Often times you need a static armorstand that just acts as a marker for a location, there is ArmorStand.staticMarker that sets properties automatically. +```dart +ArmorStand.staticMarker(Location.glob(),tags:["experimental"]) +⇒ summon armor_stand 0 0 0 {"Marker":1,"Invisible":1,"Invulnerable":1,"NoGravity":1,"Tags":["experimental"]} +``` +[//]: # (utils/areaeffectcloud) +## AreaEffectCloud +An areaeffectcloud can be created with the Summon Widget, but there is also a specific Widget with special properties for an AreaEffectCloud. + +| constructor | | +|--|--| +|Location| the location as type Location(default Location.here())| +|name|a TextComponent respresenting the name of the entity| +|age|int| +|radius|the radius an effect applies| +|applicationDelay|int| +|tags|List of tags| +|duration|int| +|waitTime|int| +|nbt|additional nbt as Map| + +This would create an Areaeffectcloud that only lasts the current tick: +```dart +AreaEffectCloud( + Location.here(), + name: TextComponent("myname"), + waitTime: 10, +) +⇒ summon area_effect_cloud ~ ~ ~ {"WaitTime":10,"CustomName":"{\"text\":\"myname\"}"} +``` +To keep the entity alive there is`AreaEffectCloud.persistent` that sets the age to multiple years. + +| AreaEffectCloud.persistent| | +|--|--| +|Location| the location as type Location(default Location.here())| +|name|a TextComponent respresenting the name of the entity| +|radius|the radius an effect applies| +|applicationDelay|int| +|tags|List of tags| +|nbt|additional nbt as Map| + +**Example:** +```dart +AreaEffectCloud.persistent(Location.here(),tags:["new_tag"]) +⇒ summon area_effect_cloud ~ ~ ~ {"Duration":-1,"WaitTime":-2147483648,"Tags":["new_tag"],"Age":-2147483648} +``` +[//]: # (utils/hologram) +A Hologram shows a floating text at a specific Location using Armorstands. + +| constructor | | +|--|--| +|String|the text to display(can also be multiline string)| +|location|the position(required)| +|color|a Color| +|tags|additional tags for the armorstands| +|space|the space in between the lines(default = 0.25)| + +**Example:** +```dart +Hologram(""" +Hello, +World! +""", + location: Location.here(), + color:Color.Aqua, +) +⇒ summon armor_stand ~ ~0.25 ~ {"Marker":1,"Invisible":1,"CustomName":"{\"text\":\"Hello,\",\"color\":\"aqua\"}","Invulnerable":1,"CustomNameVisible":1,"NoGravity":1,"Tags":["objd_hologram"]} + +⇒ summon armor_stand ~ ~ ~ {"Marker":1,"Invisible":1,"CustomName":"{\"text\":\"World!\",\"color\":\"aqua\"}","Invulnerable":1,"CustomNameVisible":1,"NoGravity":1,"Tags":["objd_hologram"]} +``` +If you wish you can also assign each line a seperate TextComponent with `Hologram.multiple` + +| Hologram.multiple| | +|--|--| +|List of TextComponents|Component for each line| +|...| same as Hologram| +[//]: # (utils/randomscore) +## RandomScore +The RandomScore Widget assigns a random value to a score using the UUID of an areaeffectcloud. + +| constructor | | +|--|--| +|Entity| the entity to save the result to | +|to|the max value(required)| +|from|the minimum value(default = 0)| +|objective|The scoreboard objective to save the values(default = objd_random)| +|targetFileName|force a specific file| +|targetFilePath|force a specific folder(other than objd)| + +**Example:** +```dart +RandomScore( + Entity.Selected(), + from: 5 + to: 100, + targetFileName: "random" +) +⇒ scoreboard players set #max objd_random 96 +⇒ function mypack:objd/random +⇒ scoreboard players add @s objd_random 5 +``` +```mcfunction +# objd/random1 +summon area_effect_cloud ~ ~ ~ {"Tags":["objd_random"]} +execute store result score @s objd_random run data get entity @e[tag=objd_random,sort=nearest,limit=1] UUIDMost 0.0000000001 +scoreboard players operation @s objd_random %= #max objd_random +``` [//]: # (utils/aroundlocation) ## AroundLocation Often times you need to check blocks or entities around one Location. AroundLocation utilizes this by using just one build method for all sides: diff --git a/README.md b/README.md index aff6593..88328f8 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ And inside of that create a file named `pubspec.yaml` and another folder called Open the pubspec.yaml file and add ```yaml dependencies: - objd: ^0.1.1 + objd: ^0.1.2 ``` And run ``` diff --git a/example/files/main.dart b/example/files/main.dart index e40718c..7a164f5 100644 --- a/example/files/main.dart +++ b/example/files/main.dart @@ -8,7 +8,6 @@ class MainFile extends Widget { Widget generate(Context context) { return For.of([ // put your tick widgets here - Effect.clear(Entity(),EffectType.absorption) ]); } } \ No newline at end of file diff --git a/lib/basic/entity.dart b/lib/basic/entity.dart index daa69d8..95ae805 100644 --- a/lib/basic/entity.dart +++ b/lib/basic/entity.dart @@ -7,6 +7,7 @@ import 'package:objd/basic/score.dart'; import 'package:objd/basic/tag.dart'; import 'package:objd/wrappers/execute.dart'; import 'package:meta/meta.dart'; +import 'package:objd/wrappers/team.dart'; abstract class EntityClass { String selector; @@ -15,27 +16,28 @@ abstract class EntityClass { class Entity implements EntityClass{ String selector; /// creates an entity with @p - Entity.Player ({Range distance,List tags,Map nbt,List scores,Range level, Gamemode gamemode, Area area, String name, Range horizontalRotation, Range verticalRotation}) : - this(selector: 'p',distance:distance,tags:tags,scores:scores,nbt:nbt,level: level,area: area,gamemode: gamemode,name: name,horizontalRotation: horizontalRotation,verticalRotation: verticalRotation); + Entity.Player ({Range distance,List tags,Team team,Map nbt,List scores,Range level, Gamemode gamemode, Area area, String name, Range horizontalRotation, Range verticalRotation}) : + this(selector: 'p',distance:distance,tags:tags,team:team,scores:scores,nbt:nbt,level: level,area: area,gamemode: gamemode,name: name,horizontalRotation: horizontalRotation,verticalRotation: verticalRotation); /// creates an entity with an implicit name Entity.PlayerName (String name): this(playerName:name); /// creates an entity with @a - Entity.All ({Range distance,List tags,Map nbt,int limit,List scores,Range level, Gamemode gamemode, Area area, String name, Range horizontalRotation, Range verticalRotation}): - this(selector: 'a',limit:limit,distance:distance,tags:tags,nbt:nbt,scores:scores,level: level,area: area,gamemode: gamemode,name: name,horizontalRotation: horizontalRotation,verticalRotation: verticalRotation); + Entity.All ({Range distance,List tags,Team team,Map nbt,int limit,List scores,Range level, Gamemode gamemode, Area area, String name, Range horizontalRotation, Range verticalRotation}): + this(selector: 'a',limit:limit,distance:distance,tags:tags,team:team,nbt:nbt,scores:scores,level: level,area: area,gamemode: gamemode,name: name,horizontalRotation: horizontalRotation,verticalRotation: verticalRotation); /// creates an entity with @r - Entity.Random({EntityType type,Range distance,List tags,Map nbt,int limit,List scores,Range level, Gamemode gamemode, Area area, String name, Range horizontalRotation, Range verticalRotation}): - this(selector: 'r',type:type,limit:limit,distance:distance,tags:tags,nbt:nbt,scores:scores,level: level,area: area,gamemode: gamemode,name: name,horizontalRotation: horizontalRotation,verticalRotation: verticalRotation); + Entity.Random({EntityType type,Range distance,List tags,Team team,Map nbt,int limit,List scores,Range level, Gamemode gamemode, Area area, String name, Range horizontalRotation, Range verticalRotation}): + this(selector: 'r',type:type,limit:limit,distance:distance,tags:tags,team:team,nbt:nbt,scores:scores,level: level,area: area,gamemode: gamemode,name: name,horizontalRotation: horizontalRotation,verticalRotation: verticalRotation); /// creates an entity with @s - Entity.Selected ({EntityType type, Range distance,List tags,Map nbt,List scores,Range level, Gamemode gamemode, Area area, String name, Range horizontalRotation, Range verticalRotation}): - this(selector: 's',type:type,distance:distance,tags:tags,nbt:nbt,scores:scores,level: level,area: area,gamemode: gamemode,name: name,horizontalRotation: horizontalRotation,verticalRotation: verticalRotation); + Entity.Selected ({EntityType type, Range distance,List tags,Team team,Map nbt,List scores,Range level, Gamemode gamemode, Area area, String name, Range horizontalRotation, Range verticalRotation}): + this(selector: 's',type:type,distance:distance,tags:tags,team:team,nbt:nbt,scores:scores,level: level,area: area,gamemode: gamemode,name: name,horizontalRotation: horizontalRotation,verticalRotation: verticalRotation); // Todo: implement Scores, Tags, Area, Nbt /// Entity is an util class to convert an argument list into the Minecraft Entity format(@p...) Entity({ this.selector = 'e', int limit, List tags, + Team team, List scores, Map nbt, EntityType type, @@ -54,10 +56,11 @@ class Entity implements EntityClass{ if(type != null) arguments['type'] = type.toString(); if(gamemode != null) arguments['gamemode'] = gamemode.toString().split('.').last; if(name != null) arguments['name'] = name; - if(horizontalRotation != null) arguments['horizontalRotation'] = horizontalRotation.toString(); - if(verticalRotation != null) arguments['verticalRotation'] = verticalRotation.toString(); + if(horizontalRotation != null) arguments['y_rotation'] = horizontalRotation.toString(); + if(verticalRotation != null) arguments['x_rotation'] = verticalRotation.toString(); if(area != null) arguments.addAll(area.getRanges()); if(nbt != null) arguments['nbt'] = json.encode(nbt); + if(team != null) arguments['team'] = team.name; if(tags != null){ arguments['tag'] = []; tags.forEach((tag){ @@ -100,6 +103,12 @@ class Entity implements EntityClass{ Tag addTag(String tag){ return Tag(tag,entity: this,value: true); } + Team joinTeam(String team){ + return Team.join(team, this); + } + Team leaveTeam(){ + return Team.leave(this); + } For addTags(List tags){ return For.of(tags.map((tag) => Tag(tag,entity: this,value: true)).toList()); } diff --git a/lib/basic/file.dart b/lib/basic/file.dart index 1fbc26a..7e9d161 100644 --- a/lib/basic/file.dart +++ b/lib/basic/file.dart @@ -8,6 +8,8 @@ class File extends Widget { String path; String pack; bool execute; + bool create; + bool isRecursive; /// The file class simply generates a new mcfunction file with content and a path. /// /// 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. @@ -20,19 +22,26 @@ class File extends Widget { /// ) /// ) /// ``` - File({@required this.path, this.child, this.execute = false,this.pack}){ + File({@required this.path, this.child, this.execute = false,this.pack,this.create = true}){ this.path.replaceAll('.mcfunction', ''); if(this.path.substring(0,1) == '/') this.path = this.path.substring(1); } /// the execute subconstructor adds an execution statement forwarding to the new file into the original - File.execute({@required this.path, this.child,this.pack}){ + File.execute({@required this.path, this.child,this.pack,this.create = true}){ this.path.replaceAll('.mcfunction', ''); if(this.path.substring(0,1) == '/') this.path = this.path.substring(1); execute = true; } + File.recursive(){ + isRecursive = true; + execute = true; + create = false; + } @override Widget generate(Context context) { + if(this.isRecursive != null && isRecursive) path = context.file; + if(pack == null) pack = context.packId; return Command('function ${pack}:' + path); } diff --git a/lib/basic/for_list.dart b/lib/basic/for_list.dart index 1219f6c..f712257 100644 --- a/lib/basic/for_list.dart +++ b/lib/basic/for_list.dart @@ -17,8 +17,9 @@ class For extends Widget { /// ) /// ``` For({@required Function create, @required int to, int from = 0,int step =1}){ - for (var i = from; i <= to; i+= step) { - _list[i] = create(i); + _list = []; + for (var i = from; i <= to; i += step) { + _list.add(create(i)); } } /// There is an Constructor for looping through a given list of widgets: diff --git a/lib/basic/group.dart b/lib/basic/group.dart index 438b9e2..e59730e 100644 --- a/lib/basic/group.dart +++ b/lib/basic/group.dart @@ -29,7 +29,7 @@ class Group extends Widget { /// ), /// ``` Group( - {@required this.prefix, + {this.prefix, @required this.children, this.suffix, this.path = "objd", diff --git a/lib/basic/location.dart b/lib/basic/location.dart index c9adbb5..ca21ad1 100644 --- a/lib/basic/location.dart +++ b/lib/basic/location.dart @@ -11,11 +11,11 @@ class Location { x = y = z = 0; } /// The Location class provides a wrapper for global(9 9 9) coordinates: - Location.glob({@required this.x, @required this.y, @required this.z}) { + Location.glob({this.x = 0, this.y = 0, this.z = 0}) { _location = x.toString() + " " + y.toString() + " " + z.toString(); } /// The Location class provides a wrapper for relative(~ ~ ~) coordinates: - Location.rel({@required this.x, @required this.y, @required this.z}) { + Location.rel({this.x = 0, this.y = 0, this.z = 0}) { _location = "~" + (x == 0 ? "" : x.toString()) + " ~" + @@ -24,7 +24,7 @@ class Location { (z == 0 ? "" : z.toString()); } /// The Location class provides a wrapper for local(^ ^ ^) coordinates: - Location.local({@required this.x, @required this.y, @required this.z}) { + Location.local({this.x = 0, this.y = 0, this.z = 0}) { _location = "^" + (x == 0 ? "" : x.toString()) + " ^" + diff --git a/lib/basic/rotation.dart b/lib/basic/rotation.dart index c193674..10f9c38 100644 --- a/lib/basic/rotation.dart +++ b/lib/basic/rotation.dart @@ -1,14 +1,13 @@ -import 'package:meta/meta.dart'; class Rotation { double x,y = 0; String _rotation; /// The Rotation Widget is very similar to Location but takes in just two directions for an entities rotation: Rotation(this._rotation); - Rotation.glob({@required this.x,@required this.y}){ + Rotation.glob({this.x = 0,this.y = 0}){ _rotation = x.toString() + " " + y.toString(); } - Rotation.rel({@required this.x,@required this.y}){ + Rotation.rel({this.x = 0,this.y = 0}){ _rotation = "~" + (x == 0 ? "": x.toString()) + " ~" + (y == 0 ? "": y.toString() ); } Rotation.here(){ diff --git a/lib/basic/score.dart b/lib/basic/score.dart index 3212811..5058d8b 100644 --- a/lib/basic/score.dart +++ b/lib/basic/score.dart @@ -29,6 +29,15 @@ class Score extends Widget { if(commands != null) _commands = commands; if(addNew) _commands.add(Scoreboard(score)); } + /// same as Score() but with a predefined entity(Entity.Selected()) + /// ```dart +/// Score.fromSelected("objective").set(3) +/// ⇒ scoreboard players set @s objective 3 +/// ``` + Score.fromSelected(this.score,{bool addNew = true}){ + entity =Entity.Selected(); + if(addNew) _commands.add(Scoreboard(score)); + } Score.str(this._strGen,{this.score = "",String match = "0"}){ _match =match; } diff --git a/lib/basic/tag.dart b/lib/basic/tag.dart index 3eeebf5..0f0469d 100644 --- a/lib/basic/tag.dart +++ b/lib/basic/tag.dart @@ -1,8 +1,10 @@ import 'package:meta/meta.dart'; +import 'package:objd/basic/for_list.dart'; import 'package:objd/basic/widget.dart'; import 'package:objd/basic/command.dart'; import 'package:objd/basic/entity.dart'; import 'package:objd/build/build.dart'; +import 'package:objd/wrappers/if.dart'; class Tag extends Widget { bool value; @@ -16,6 +18,37 @@ class Tag extends Widget { add() => Tag(tag,entity: entity,value: true); remove() => Tag(tag,entity: entity,value: false); +/// With the toggle method you can toggle the value(invert the tag). This is done with a temporary tag: +/// ```dart +/// Tag("mytag",entity:Entity.Selected()).toggle() +/// ⇒ execute if entity @s[tag=mytag] run tag @s add objd_temp +/// ⇒ execute if entity @s[tag=objd_temp] run tag @s remove mytag +/// ⇒ execute if entity @s[tag=!objd_temp] run tag @s add mytag +/// ⇒ tag @s remove objd_temp +/// ``` + toggle({String temp = "objd_temp"}) { + var tempTag = Tag(temp,entity: entity); + return For.of([ + If(this,Then:[tempTag]), + If(tempTag,Then:[Tag(tag,entity: entity,value: false)]), + If(Tag("!"+temp,entity: entity),Then:[Tag(tag,entity: entity,value: true)]), + tempTag.remove() + ]); + } +/// The `removeIfExists` method removes the tag and may execute some action before if the tag exists. +/// ```dart +/// Tag("mytag",entity:Entity.Selected()).removeIfExists( +/// then: Say(msg:"removed") +/// ) // optional argument +/// ⇒ execute if entity @s[tag=mytag] run say removed +/// ⇒ execute if entity @s[tag=mytag] run tag @s remove mytag +/// ``` + removeIfExists({Widget then}){ + return If(this,Then:[ + then, + this.remove() + ]); + } String getEntity(){ var args = new Map.from(entity.arguments); diff --git a/lib/basic/widgets.dart b/lib/basic/widgets.dart index 43b3fdb..c2881e0 100644 --- a/lib/basic/widgets.dart +++ b/lib/basic/widgets.dart @@ -13,5 +13,6 @@ export 'entity.dart'; export 'item.dart'; export 'block.dart'; export 'location.dart'; +export 'rotation.dart'; export 'area.dart'; export 'condition.dart'; \ No newline at end of file diff --git a/lib/build/build.dart b/lib/build/build.dart index 1ab99fe..647f9f5 100644 --- a/lib/build/build.dart +++ b/lib/build/build.dart @@ -28,18 +28,21 @@ Map _getFiles(dynamic wid, Map ret, int currentPackIndex) { // does the current pack exist? assert(ret['packs'][currentPackIndex] != null); + // do we need to create this file? + if(wid is File && wid.create == false) return ret; + // is there already a file with this path? var fileIndex = ret['packs'][currentPackIndex]['files'] .indexWhere((file) => file.path == wid.path); - if (fileIndex >= 0) { + if (fileIndex >= 0 && wid is Extend) { List children = [ ret['packs'][currentPackIndex]['files'][fileIndex].child, wid.child ]; - if(wid is File || wid.first == true ){ + if(wid.first == true ){ children = children.reversed.toList(); } diff --git a/lib/utils/areaeffectcloud.dart b/lib/utils/areaeffectcloud.dart new file mode 100644 index 0000000..aa11fd5 --- /dev/null +++ b/lib/utils/areaeffectcloud.dart @@ -0,0 +1,72 @@ +import 'package:objd/basic/entity.dart'; +import 'package:objd/basic/location.dart'; +import 'package:objd/basic/text_components.dart'; +import 'package:objd/basic/widget.dart'; +import 'package:objd/build/context.dart'; +import 'package:objd/wrappers/summon.dart'; + +/// An areaeffectcloud can be created with the Summon Widget, but there is also a specific Widget with special properties for an AreaEffectCloud. +class AreaEffectCloud extends Widget { + TextComponent name; + Map nbt; + Location location; + + int age; + + List tags; + +/// An areaeffectcloud can be created with the Summon Widget, but there is also a specific Widget with special properties for an AreaEffectCloud. + AreaEffectCloud(this.location, + { + this.name, + this.nbt, + this.age, + this.tags, + int radius, + int applicationDelay, + int duration, + int waitTime, + + }) { + if(nbt == null) nbt = {}; + + _addIfExist(radius,"Radius"); + _addIfExist(applicationDelay,"ReapplicationDelay"); + _addIfExist(duration,"Duration"); + _addIfExist(waitTime,"WaitTime"); + + } + + _addIfExist(dynamic val,String tag){ + if(val != null) nbt[tag] = val; + } +/// To keep the entity alive there is `AreaEffectCloud.persistent` that sets the age to multiple years. + AreaEffectCloud.persistent(this.location, + { + this.name, + this.nbt, + this.tags, + int radius, + int applicationDelay, + }) { + if(nbt == null) nbt = {}; + var inf = -2147483648; + + age = inf; + _addIfExist(radius,"Radius"); + _addIfExist(applicationDelay,"ReapplicationDelay"); + _addIfExist(-1,"Duration"); + _addIfExist(inf,"WaitTime"); + + } + + @override + Widget generate(Context context) { + return Summon(EntityType.area_effect_cloud, + location: location, + tags: tags, + name: name, + nbt: nbt, + age:age); + } +} diff --git a/lib/utils/armorstand.dart b/lib/utils/armorstand.dart new file mode 100644 index 0000000..67a6ef6 --- /dev/null +++ b/lib/utils/armorstand.dart @@ -0,0 +1,110 @@ +import 'package:objd/basic/entity.dart'; +import 'package:objd/basic/item.dart'; +import 'package:objd/basic/location.dart'; +import 'package:objd/basic/rotation.dart'; +import 'package:objd/basic/text_components.dart'; +import 'package:objd/basic/widget.dart'; +import 'package:objd/build/context.dart'; +import 'package:objd/wrappers/summon.dart'; + +class ArmorStand extends Widget { + TextComponent name; + Map nbt; + Location location; + + bool invulnerable, gravity, small, nameVisible, glowing; + +Item mainHand,offHand,head,chest,legs,boots; + + List tags; + int fire; + Rotation rotation; + +/// An armorstand can be created with the Summon Widget, but there is also a specific Widget with special properties for an ArmorStand. + ArmorStand(this.location, + {this.name, + this.nameVisible, + this.nbt, + bool invisible, + this.invulnerable, + bool marker, + bool hasArms, + bool basePlate, + this.mainHand, + this.offHand, + this.head, + this.chest, + this.legs, + this.boots, + this.gravity, + this.glowing, + this.fire, + this.small, + this.tags, + this.rotation}) { + if(nbt == null) nbt = {}; + + _addBoolNbt(marker, "Marker"); + _addBoolNbt(hasArms, "ShowArms"); + if(basePlate != null) _addBoolNbt(!basePlate, "NoBasePlate"); + _addSlots(); + + + // TODO: Pose + } + _addSlots(){ + if((mainHand != null || offHand != null) && nbt["HandItems"] == null ) nbt["HandItems"] = [{},{}]; + if(!(head == null && chest == null && legs == null && boots == null) ) nbt["ArmorItems"] = [{},{},{},{}]; + + if(mainHand != null) nbt["HandItems"][0] = mainHand.getMap(); + if(offHand != null) nbt["HandItems"][1] = offHand.getMap(); + if(head != null) nbt["ArmorItems"][3] = head.getMap(); + if(chest != null) nbt["ArmorItems"][2] = chest.getMap(); + if(legs != null) nbt["ArmorItems"][1] = legs.getMap(); + if(boots != null) nbt["ArmorItems"][0] = boots.getMap(); + } +/// Often times you need a static armorstand that just acts as a marker for a location, there is ArmorStand.staticMarker that sets properties automatically. + ArmorStand.staticMarker(this.location, + {this.name, + this.nameVisible, + this.nbt, + bool invisible = true, + this.invulnerable = true, + this.gravity = false, + this.mainHand, + this.offHand, + this.head, + this.chest, + this.legs, + this.boots, + this.glowing, + this.fire, + this.small, + this.tags, + this.rotation}) { + if(nbt == null) nbt = {}; + + _addBoolNbt(true, "Marker"); + _addBoolNbt(invisible, "Invisible"); + _addSlots(); + } + + _addBoolNbt(bool value, String path) { + if (value != null) nbt[path] = value ? 1 : 0; + } + + @override + Widget generate(Context context) { + return Summon(EntityType.armor_stand, + location: location, + tags: tags, + name: name, + nameVisible: nameVisible, + nbt: nbt, + invulnerable: invulnerable, + glowing: glowing, + gravity: gravity, + small: small, + rotation: rotation); + } +} diff --git a/lib/utils/hologram.dart b/lib/utils/hologram.dart new file mode 100644 index 0000000..31b015f --- /dev/null +++ b/lib/utils/hologram.dart @@ -0,0 +1,51 @@ + + +import 'package:meta/meta.dart'; +import 'package:objd/basic/location.dart'; +import 'package:objd/basic/text_components.dart'; +import 'package:objd/basic/widget.dart'; +import 'package:objd/build/context.dart'; +import 'package:objd/utils/armorstand.dart'; +import 'package:objd/wrappers/execute.dart'; +/// A Hologram shows a floating text at a specific Location using Armorstands. +class Hologram extends Widget { + + List texts; + List tags; + Location location; + double space; + + /// A Hologram shows a floating text at a specific Location using Armorstands. + /// **Example:** +/// ```dart +/// Hologram(""" +/// Hello, +/// World! +/// """, +/// location: Location.here(), +/// color:Color.Aqua, +/// )``` + Hologram(String str,{@required this.location, Color color,this.tags,this.space = 0.25}){ + if(tags == null) tags = ["objd_hologram"]; + else tags.add("objd_hologram"); + + texts = str.split("\n").map((line) => line.isNotEmpty ? TextComponent(line,color:color): null).toList(); + } + /// If you wish you can assign each line a seperate TextComponent with `Hologram.multiple` + Hologram.multiple(this.texts,{@required this.location,this.tags,this.space = 0.25}){ + if(tags == null) tags = ["objd_hologram"]; + else tags.add("objd_hologram"); + } + + @override + Widget generate(Context context) { + int i = texts.length; + if(i == 1) return ArmorStand.staticMarker(location,name:texts[0],nameVisible: true,tags:tags); + return Execute.positioned(location,children:(texts.map((text){ + i--; + if(text != null){ + return ArmorStand.staticMarker(Location.rel(x:0,y:i * space,z:0),name:text,nameVisible: true,tags:tags); + } + }).toList())); + } +} \ No newline at end of file diff --git a/lib/utils/log.dart b/lib/utils/log.dart new file mode 100644 index 0000000..61c89df --- /dev/null +++ b/lib/utils/log.dart @@ -0,0 +1,32 @@ + +import 'package:objd/basic/entity.dart'; +import 'package:objd/basic/score.dart'; +import 'package:objd/basic/text_components.dart'; +import 'package:objd/basic/widget.dart'; +import 'package:objd/build/context.dart'; +import 'package:objd/wrappers/tellraw.dart'; + +class Log extends Widget { + dynamic msg; + Entity to; + Color color; + /// The log widgets displays a console logging in the players chat. That way you can quickly check execution times, score values and entities. + Log(this.msg,{this.to,this.color}){ + if(to == null) to =Entity.All(); + if(color == null) color =Color.DarkAqua; + } + + @override + Widget generate(Context context) { + + TextComponent text =TextComponent("undefined"); + if(msg is String) text =TextComponent(msg); + if(msg is Score) text =TextComponent.score(msg); + if(msg is Entity) text =TextComponent.selector(msg); + + return Tellraw(to,show: [ + TextComponent("Console > ",color:color), + text + ]); + } +} \ No newline at end of file diff --git a/lib/utils/randomScore.dart b/lib/utils/randomScore.dart new file mode 100644 index 0000000..285309d --- /dev/null +++ b/lib/utils/randomScore.dart @@ -0,0 +1,56 @@ +import 'package:meta/meta.dart'; +import 'package:objd/core.dart'; + +/// The RandomScore Widget assigns a random value to a score using the UUID of an areaeffectcloud. +class RandomScore extends Widget { + String targetFilePath; + String targetFileName; + + Entity entity; + String objective; + int to; + int from; + int _diff; + /// The RandomScore Widget assigns a random value to a score using the UUID of an areaeffectcloud. + RandomScore(this.entity, + {this.from = 0, + @required this.to, + this.objective = "objd_random", + this.targetFilePath = "objd", + this.targetFileName}) { + _diff = to - from + 1; + } + + Score get score => Score(entity, objective); + + @override + Widget generate(Context context) { + return For.of([ + Score(Entity.PlayerName("#max"), objective).set(_diff), + Group( + path: targetFilePath, + filename: targetFileName ?? "random", + generateIDs: targetFileName == null, + children: [ + Comment("Random UUID Generator from ${context.file}"), + AreaEffectCloud(Location.here(), tags: ["objd_random"]), + Score(entity, objective).setToResult(Command( + "data get entity @e[tag=objd_random,sort=nearest,limit=1] UUIDMost 0.0000000001")), + Score(entity, objective) + .modulo(Score(Entity.PlayerName("#max"), objective)) + ]), + from > 0 ? score.add(from) : null + // File.execute( + // path: targetFilePath.isNotEmpty + // ? targetFilePath + "/" + targetFileName + // : targetFileName, + // child: For.of([ + // Comment("Random UUID Generator from ${context.file}"), + // AreaEffectCloud(Location.here(), tags: ["objd_random"]), + // Score(entity, objective).setToResult(Command("data get entity @e[tag=objd_random,sort=nearest,limit=1] UUIDMost 0.0000000001")), + // Score(entity, objective) + // .modulo(Score(Entity.PlayerName("#max"), objective)) + // ])) + ]); + } +} diff --git a/lib/utils/repeat.dart b/lib/utils/repeat.dart new file mode 100644 index 0000000..682b2f9 --- /dev/null +++ b/lib/utils/repeat.dart @@ -0,0 +1,30 @@ +import 'package:meta/meta.dart'; +import 'package:objd/core.dart'; + + /// The Repeat Widget repeats a given action multiple times with a tick delay. +class Repeat extends Widget { + String name; + String path; + Widget child; + String counter; + int to; + int ticks; + /// The Repeat Widget repeats a given action multiple times with a tick delay. + Repeat(this.name,{@required this.child,@required this.to,this.counter = "objd_repeat", this.path = "timers",this.ticks = 1}); + + @override + Widget generate(Context context) { + Score score = Score(Entity.PlayerName(name),counter); + String filePath = path + "/" + name; + return For.of([ + score.set(0), + File.execute(path: filePath,child:For.of([ + child, + score.add(1), + If(score.matchesRange(Range(to:to)),Then:[ + Schedule(filePath,ticks: ticks) + ]) + ])) + ]); + } +} \ No newline at end of file diff --git a/lib/utils/widgets.dart b/lib/utils/widgets.dart index c6a5d45..2e5fce0 100644 --- a/lib/utils/widgets.dart +++ b/lib/utils/widgets.dart @@ -1,2 +1,8 @@ export 'timer.dart'; export 'aroundlocation.dart'; +export 'log.dart'; +export 'armorstand.dart'; +export 'areaeffectcloud.dart'; +export 'hologram.dart'; +export 'randomScore.dart'; +export 'repeat.dart'; diff --git a/lib/wrappers/data.dart b/lib/wrappers/data.dart index efbc906..f8adb66 100644 --- a/lib/wrappers/data.dart +++ b/lib/wrappers/data.dart @@ -87,7 +87,7 @@ class Data extends Widget { Widget generate(Context context){ switch (_subcommand) { case "merge": return new Command('data merge ' + getTarget() + ' ' + json.encode(nbt)); - case "get": return new Command('data get ' + getTarget() + ' ' + path + ' ' + scale.toString()); + case "get": return new Command('data get ' + getTarget() + ' ' + path + ' ' + (scale < 0.000001 ? scale.toStringAsFixed(10): scale.toString())); case "remove": return new Command('data remove ' + getTarget() + ' ' + path); case "modify": return new Command('data modify ' + getTarget() + ' ' + modify.toString()); } diff --git a/lib/wrappers/effect.dart b/lib/wrappers/effect.dart index fed8fc9..569c7fb 100644 --- a/lib/wrappers/effect.dart +++ b/lib/wrappers/effect.dart @@ -1,6 +1,5 @@ -import 'package:meta/meta.dart'; import 'package:objd/basic/command.dart'; import 'package:objd/basic/entity.dart'; import 'package:objd/basic/widget.dart'; @@ -25,7 +24,8 @@ class Effect extends Widget { /// ) /// ⇒ effect give @p minecraft:jump_boost 20 3 true /// ``` - Effect(this.effect,{@required this.entity,this.duration = 30,this.amplifier = 1,this.showParticles = true}){ + Effect(this.effect,{this.entity,this.duration = 30,this.amplifier = 1,this.showParticles = true}){ + if(entity == null) entity =Entity.Selected(); _type = "give"; } /// You can clear an effect again. @@ -36,7 +36,14 @@ class Effect extends Widget { Effect.clear(this.entity,[this.effect]){ _type = "clear"; } - + getMap(){ + Map ret = {}; + ret["Id"] = EffectType.values.indexOf(effect) + 1; + ret["Amplifier"] = amplifier != null ? amplifier - 1 : 0; + ret["Duration"] = duration != null ? duration * 20 : 0; + ret["ShowParticles"] = showParticles != null && showParticles ? 1 : 0; + return ret; + } @override Widget generate(Context context) { if(_type == "clear"){ @@ -48,33 +55,36 @@ class Effect extends Widget { } enum EffectType { - absorption, - unluck, - luck, - blindness, - conduit_power, - dolphins_grace, - fire_resistance, - glowing, - haste, - health_boost, - hunger, - instant_damage, - instant_health, - jump_boost, - levitation, - mining_fatigue, - nausea, - night_vision, - poison, - regeneration, - resistance, - saturation, - slow_falling, - slowness, - speed, - strength, - water_breathing, - weakness, - wither +speed, +slowness, +haste, +mining_fatique, +strength, +instant_health, +instant_damage, +jump_boost, +nausea, +regeneration, +resistance, +fire_resistance, +water_breathing, +invisibility, +blindness, +night_vision, +hunger, +weakness, +poison, +wither, +health_boost, +absorption, +saturation, +glowing, +levitation, +luck, +unluck, +slow_falling, +conduit_power, +dolphins_grace, +bad_omen, + } \ No newline at end of file diff --git a/lib/wrappers/if.dart b/lib/wrappers/if.dart index 3262e6b..22d1ec7 100644 --- a/lib/wrappers/if.dart +++ b/lib/wrappers/if.dart @@ -1,4 +1,3 @@ -import 'package:objd/basic/command.dart'; import 'package:objd/basic/condition.dart'; import 'package:objd/basic/entity.dart'; import 'package:objd/wrappers/comment.dart'; diff --git a/lib/wrappers/setblock.dart b/lib/wrappers/setblock.dart index aec6f0d..8233514 100644 --- a/lib/wrappers/setblock.dart +++ b/lib/wrappers/setblock.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:objd/basic/command.dart'; import 'package:meta/meta.dart'; import 'package:objd/basic/widget.dart'; @@ -8,11 +10,12 @@ import 'package:objd/build/build.dart'; class SetBlock extends Widget { Location location; Block block; + Map nbt; /// The SetBlock Command Class sets a Block at the specified location. - SetBlock(this.block,{@required this.location}); + SetBlock(this.block,{@required this.location,this.nbt}); @override Widget generate(Context context){ - return new Command('setblock ' + location.toString() + ' ' + block.toString()); + return new Command('setblock ' + location.toString() + ' ' + block.toString() + (nbt == null? '': json.encode(nbt))); } } diff --git a/lib/wrappers/summon.dart b/lib/wrappers/summon.dart index a496f0a..3fc1c5d 100644 --- a/lib/wrappers/summon.dart +++ b/lib/wrappers/summon.dart @@ -1,4 +1,5 @@ import 'package:objd/basic/command.dart'; +import 'package:objd/basic/rotation.dart'; import 'package:objd/basic/widget.dart'; import 'package:objd/basic/entity.dart'; import 'package:objd/basic/text_components.dart'; @@ -6,24 +7,69 @@ import 'package:objd/basic/location.dart'; import 'package:objd/build/build.dart'; import 'dart:convert'; +import 'package:objd/wrappers/effect.dart'; + class Summon extends Widget { - Map nbt; + Map nbt; Location location; EntityType type; + /// The summon class creates a new entity at a given location. - Summon(this.type,{TextComponent name, this.nbt, this.location}){ - if(location == null) location = Location.here(); - if(nbt == null) nbt = {}; + Summon(this.type, + {TextComponent name, + bool nameVisible, + this.nbt, + this.location, + bool invulnerable, + bool persistent, + bool noAI, + bool silent, + bool gravity, + bool glowing, + List passengers, + List effects, + List tags, + int fire, + bool small, + int age, + Rotation rotation}) { + if (location == null) location = Location.here(); + if (nbt == null) nbt = {}; + + if (name != null) nbt["CustomName"] = name.toJson(); + _addBoolNbt(invulnerable, "Invulnerable"); + _addBoolNbt(silent, "Silent"); + _addBoolNbt(small, "Small"); + _addBoolNbt(glowing, "Glowing"); + _addBoolNbt(nameVisible, "CustomNameVisible"); + _addBoolNbt(persistent, "PersistenceRequired"); + _addBoolNbt(noAI, "NoAI"); + if (gravity != null) _addBoolNbt(!gravity, "NoGravity"); + if (tags != null && tags.isNotEmpty) nbt["Tags"] = tags; + if (effects != null && effects.isNotEmpty) nbt["ActiveEffects"] = effects.map((effect) => effect.getMap()).toList(); + if (passengers != null) nbt["Passengers"] = passengers.map((pass) => pass.getMap()).toList(); + if (fire != null && fire > 0) nbt["Fire"] = fire; + if (rotation != null) nbt["Rotation"] = [rotation.x, rotation.y]; + if (age != null) nbt["Age"] = age; + } + + Map getMap(){ + Map ret = Map.from(nbt); + ret["id"] = type.type; + return ret; + } - if(name != null) nbt.addAll({ - "CustomName": name.toJson() - }); + _addBoolNbt(bool value, String path) { + if (value != null) nbt[path] = value ? 1 : 0; } - - // TODO: Tags, Scores etc @override - Widget generate(Context context){ - return new Command('summon ' + type.toString() + ' ' + location.toString() + ' ' + json.encode(nbt)); + Widget generate(Context context) { + return new Command('summon ' + + type.toString() + + ' ' + + location.toString() + + ' ' + + json.encode(nbt)); } } diff --git a/lib/wrappers/team.dart b/lib/wrappers/team.dart new file mode 100644 index 0000000..323f4f2 --- /dev/null +++ b/lib/wrappers/team.dart @@ -0,0 +1,122 @@ +import 'package:objd/basic/command.dart'; +import 'package:objd/basic/entity.dart'; +import 'package:objd/basic/for_list.dart'; +import 'package:objd/basic/text_components.dart'; +import 'package:objd/basic/widget.dart'; +import 'package:objd/build/context.dart'; + +class Team extends Widget { + String name; + Entity entity; + Map modifiers = {}; + _TeamAction _action; + + Team(this.name) { + _action = _TeamAction.add; + } + Team.add(this.name, + {TextComponent display, + Color color, + ModifyTeam nametag, + ModifyTeam collision, + ModifyTeam deathMessage, + bool friendlyFire, + String prefix, + String suffix, + bool seeInvisible}) { + _action =_TeamAction.add; + _setModifiers(display,color,nametag,collision,deathMessage,friendlyFire,prefix,suffix,seeInvisible); + } + + Team.empty(this.name) { + _action = _TeamAction.empty; + } + Team.join(this.name, this.entity) { + _action = _TeamAction.join; + } + Team.leave(this.entity) { + _action = _TeamAction.leave; + } + Team.modify(this.name, + {TextComponent display, + Color color, + ModifyTeam nametag, + ModifyTeam collision, + ModifyTeam deathMessage, + bool friendlyFire, + String prefix, + String suffix, + bool seeInvisible}) { + _action =_TeamAction.modify; + _setModifiers(display,color,nametag,collision,deathMessage,friendlyFire,prefix,suffix,seeInvisible); + } + _setModifiers( + TextComponent display, + Color color, + ModifyTeam nametag, + ModifyTeam collision, + ModifyTeam deathMessage, + bool friendlyFire, + String prefix, + String suffix, + bool seeInvisible) { + if(display != null) modifiers["displayName"] = display.toJson(); + if(color != null) modifiers["color"] = color.color; + if(deathMessage != null) modifiers["deathMessageVisibility"] = _genEnum(deathMessage); + if(friendlyFire != null) modifiers["friendlyFire"] = friendlyFire; + if(nametag != null) modifiers["nametagVisibility"] = _genEnum(nametag); + if(collision != null) modifiers["collisionRule"] = _genEnum(collision); + if(prefix != null) modifiers["prefix"] = prefix; + if(suffix != null) modifiers["suffix"] = suffix; + if(seeInvisible != null) modifiers["seeFriendlyInvisible"] = seeInvisible; + } + _genEnum(dynamic en){ + return en.toString().split(".")[1]; + } + + @override + Widget generate(Context context) { + List wids = []; + switch (_action) { + case _TeamAction.add: + wids.add(Command("team add ${name}")); + break; + case _TeamAction.empty: + wids.add(Command("team empty ${name}")); + break; + case _TeamAction.remove: + wids.add(Command("team remove ${name}")); + break; + case _TeamAction.join: + wids.add(Command("team join ${name} ${entity}")); + break; + case _TeamAction.leave: + wids.add(Command("team leave ${entity}")); + break; + default: + } + if(modifiers.length > 0){ + modifiers.keys.forEach((key) => wids.add(Command("team modify ${name} ${key} ${modifiers[key]}"))); + } + print(modifiers); + return For.of(wids); + } +} + +enum _TeamAction { + add, + remove, + modify, + join, + leave, + empty, +} + +enum ModifyTeam { + never, + always, + hideForOtherTeams, + hideForOwnTeam, + pushOtherTeams, + pushOwnTeam, +} diff --git a/lib/wrappers/teleport.dart b/lib/wrappers/teleport.dart index 1f78f61..67de4ad 100644 --- a/lib/wrappers/teleport.dart +++ b/lib/wrappers/teleport.dart @@ -13,16 +13,17 @@ class Teleport extends Widget { Teleport(this.entity,{@required Location to, dynamic facing, Rotation rot}){ this.to = to.toString(); if(rot != null) this.to += " " + rot.toString(); - if(facing != null){ - if(facing is Entity || facing is Location) this.to += " facing " + facing.toString(); - else throw("Please set the facing part either to a entity or location"); - } + _setFacing(facing); } Teleport.entity(this.entity,{Entity to, dynamic facing}){ this.to = to.toString(); - if(facing != null){ - if(facing is Entity || facing is Location) this.to += " facing " + facing.toString(); + _setFacing(facing); + } + _setFacing(facing){ + if(facing != null){ + if(facing is Location) this.to += " facing " + facing.toString(); + else if(facing is Entity) this.to += " facing entity " + facing.toString(); else throw("Please set the facing part either to a entity or location"); } } diff --git a/lib/wrappers/widgets.dart b/lib/wrappers/widgets.dart index 2da78c9..b6520e0 100644 --- a/lib/wrappers/widgets.dart +++ b/lib/wrappers/widgets.dart @@ -16,4 +16,5 @@ export 'kill.dart'; export 'schedule.dart'; export 'effect.dart'; export 'particle.dart'; -export 'trigger.dart'; \ No newline at end of file +export 'trigger.dart'; +export 'team.dart'; \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index d718d84..1c6e094 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: objd -version: 0.1.0 +version: 0.1.2 author: Stevertus homepage: https://stevertus.com/objD @@ -17,4 +17,5 @@ dependencies: executables: run: watch: - new: \ No newline at end of file + new: + objd: \ No newline at end of file