From 9d1e772779723320d67e74f30b3daf1b2c550d83 Mon Sep 17 00:00:00 2001 From: Stevertus Date: Wed, 18 Oct 2023 17:50:53 +0200 Subject: [PATCH 1/8] base score operation setup --- example/score_test.dart | 6 + lib/src/basic/score/score.dart | 520 +++++++++++++++++++++++ lib/src/basic/score/score_builder.dart | 14 + lib/src/basic/score/score_export.dart | 4 + lib/src/basic/score/score_operation.dart | 108 +++++ lib/src/basic/types/param.dart | 1 + 6 files changed, 653 insertions(+) create mode 100644 example/score_test.dart create mode 100644 lib/src/basic/score/score.dart create mode 100644 lib/src/basic/score/score_builder.dart create mode 100644 lib/src/basic/score/score_export.dart create mode 100644 lib/src/basic/score/score_operation.dart create mode 100644 lib/src/basic/types/param.dart diff --git a/example/score_test.dart b/example/score_test.dart new file mode 100644 index 0000000..f54eda5 --- /dev/null +++ b/example/score_test.dart @@ -0,0 +1,6 @@ +import 'package:objd/core.dart'; +import 'package:objd/src/basic/score/score_operation.dart'; + +void main(List args) { + ScoreOperation t = Score(Entity.All(), "test"); +} diff --git a/lib/src/basic/score/score.dart b/lib/src/basic/score/score.dart new file mode 100644 index 0000000..96fc8c1 --- /dev/null +++ b/lib/src/basic/score/score.dart @@ -0,0 +1,520 @@ +library score; + +import 'package:objd/src/basic/file.dart'; +import 'package:objd/src/basic/group.dart'; +import 'package:objd/src/basic/rest_action.dart'; +import 'package:objd/src/basic/score/score_operation.dart'; +import 'package:objd/src/basic/widget.dart'; +import 'package:objd/src/wrappers/data.dart'; +import 'package:objd/src/basic/command.dart'; +import 'package:objd/src/basic/for_list.dart'; +import 'package:objd/src/basic/types/entity.dart'; +import 'package:objd/src/basic/types/condition.dart'; +import 'package:objd/src/basic/scoreboard.dart'; +import 'package:objd/src/build/build.dart'; +import 'package:objd/src/wrappers/if.dart'; + +import '../builder.dart'; + +class Score extends ScoreOperation { + List _commands = []; + + /// Get commands + List get commands => _commands; + final Entity entity; + String score; + String type; + String _strGen = ''; + + /// 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)| + /// + ///```dart + /// Score(Entity.Selected(),'score',addNew: true) + ///``` + + Score( + this.entity, + this.score, { + bool addNew = true, + List? commands, + this.type = 'dummy', + }) { + if (commands != null) _commands = commands; + if (addNew) { + _commands.add( + Scoreboard(score, type: type), + ); + } + if (Scoreboard.prefix != null && !score.contains(Scoreboard.prefix!)) { + score = Scoreboard.prefix! + 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, + this.type = 'dummy', + }) : entity = Entity.Self() { + if (addNew) { + _commands.add( + Scoreboard(score, type: type), + ); + } + if (Scoreboard.prefix != null && !score.contains(Scoreboard.prefix!)) { + score = Scoreboard.prefix! + score; + } + } + Score.str(this._strGen, + {this.score = '', String match = '0', this.type = 'dummy'}) + : entity = Entity.Self() { + _match = match; + } + + /// Do you need constant values with scores? objD got you covered with `Score.con`: + /// + /// |Score.con| | + /// |--|--| + /// |int| a constant number | + /// |addNew|bool whether it should add objd_consts itself if it does not exist(default = true)| + + /// This will automatically create a scoreboard called `objd_consts` and set the value to the fake entity `#[value]` + /// + /// **Example:** + /// ```dart + /// Score.con(5) + /// ⇒ scoreboard players set #5 objd_consts 5 + /// ``` + Score.con( + int number, { + bool addNew = true, + this.type = 'dummy', + }) : score = 'objd_consts', + entity = Entity.PlayerName( + '#$number', + ) { + if (Scoreboard.prefix != null && !score.contains(Scoreboard.prefix!)) { + score = Scoreboard.prefix! + score; + } + + if (addNew) { + _commands.add( + Scoreboard(score, type: type), + ); + } + _commands.add( + set(number), + ); + } + + String _getESStr({Entity? entity, String? score}) { + entity ??= this.entity; + score ??= this.score; + return '$entity $score'; + } + + String toString({Entity? entity, String? score}) { + entity ??= this.entity; + score ??= this.score; + return '$entity $score'; + } + + Score addCommandRet(Widget command) { + var commands = List.from(_commands); + commands.add(command); + return Score(entity, score, addNew: false, commands: commands, type: type); + } + + /// add + Score operator +(dynamic other) { + if (other is int) return add(other); + if (other is Score) return addScore(other); + throw ('Please use either a Score or an Int in the operator +'); + } + + /// subtract + Score operator -(dynamic other) { + if (other is int) return subtract(other); + if (other is Score) return subtractScore(other); + throw ('Please use either a Score or an Int in the operator -'); + } + + /// modulo by + Score operator %(dynamic other) { + if (other is int) { + return modulo( + Score.con(other), + ); + } + if (other is Score) return modulo(other); + throw ('Please use either a Score or an Int in the operator %'); + } + + /// divide by + Score operator /(dynamic other) { + if (other is int) { + return divideByScore( + Score.con(other), + ); + } + if (other is Score) return divideByScore(other); + throw ('Please use either a Score or an Int in the operator /'); + } + + /// multiply by + Score operator *(dynamic other) { + if (other is int) { + return multiplyByScore( + Score.con(other), + ); + } + if (other is Score) return multiplyByScore(other); + throw ('Please use either a Score or an Int in the operator /'); + } + + /// greater than + Score operator >(dynamic other) { + if (other is int) { + return matchesRange( + Range.from(other + 1), + ); + } + if (other is Score) return isBigger(other); + throw ('Please use either a Score or an Int in the operator >'); + } + + /// less than + Score operator <(dynamic other) { + if (other is int) { + return matchesRange( + Range.to(other + -1), + ); + } + if (other is Score) return isSmaller(other); + throw ('Please use either a Score or an Int in the operator >'); + } + + /// bigger or equal + Score operator >=(dynamic other) { + if (other is int) { + return matchesRange( + Range.from(other), + ); + } + if (other is Score) return isBiggerOrEqual(other); + throw ('Please use either a Score or an Int in the operator >='); + } + + /// less or equal + Score operator <=(dynamic other) { + if (other is int) { + return matchesRange( + Range.to(other), + ); + } + if (other is Score) return isSmallerOrEqual(other); + throw ('Please use either a Score or an Int in the operator <='); + } + + /// matches + Score operator &(dynamic other) { + if (other is int) return matches(other); + if (other is Range) return matchesRange(other); + if (other is Score) return isEqual(other); + throw ('Please use either a Score, Range or an Int in the operator &'); + } + + /// assign value(int, Score, Data or Condition) + Widget setTo(dynamic other) { + if (other is int) return set(other); + if (other is Score) return setEqual(other); + if (other is Data) return setToData(other); + if (other is Condition) return setToCondition(other); + if (other is Command) return setToResult(other); + if (other is File) return setToFunction(other); + if (other is Widget) return setToWidget(other); + throw ('Please use either a Score, Data, Condition, Command or an Int in the operator >>'); + } + + Widget operator >>(dynamic other) => setTo(other); + Widget operator <<(dynamic other) => setTo(other); + + /// sets the score to a given value of int + Score set(int val) { + return addCommandRet( + Command( + 'scoreboard players set ${_getESStr()} $val', + ), + ); + } + + /// resets the value of a score + Score reset() { + return addCommandRet( + Command( + 'scoreboard players reset ${_getESStr()}', + ), + ); + } + + /// adds a value to the score + Score add([int val = 1]) { + return addCommandRet( + Command( + 'scoreboard players add ${_getESStr()} $val', + ), + ); + } + + /// subtracts a value from the score + Score subtract([int val = 1]) { + return addCommandRet( + Command( + 'scoreboard players remove ${_getESStr()} $val', + ), + ); + } + + /// gets the value of the score to work with it further + Score get() { + return addCommandRet( + Command( + 'scoreboard players get ${_getESStr()}', + ), + ); + } + + // all operations + /// sets this score equal to another + Score setEqual(Score score) { + return addCommandRet( + Command( + 'scoreboard players operation ${isEqual(score).getString()}', + ), + ); + } + + /// swaps two scores + Score swapWith(Score score) { + return addCommandRet( + Command( + 'scoreboard players operation ${_getESStr()} >< ${_getESStr(entity: score.entity, score: score.score)}', + ), + ); + } + + /// compares two scores and sets the smallest to this one + Score setToSmallest(Score score) { + return addCommandRet( + Command( + 'scoreboard players operation ${isSmaller(score).getString()}', + ), + ); + } + + /// compares two scores and sets the biggest to this one + Score setToBiggest(Score score) { + return addCommandRet( + Command( + 'scoreboard players operation ${isBigger(score).getString()}', + ), + ); + } + + /// adds another score to this one + Score addScore(Score score) { + return addCommandRet( + Command( + 'scoreboard players operation ${_getESStr()} += ${_getESStr(entity: score.entity, score: score.score)}', + ), + ); + } + + /// subtracts another score from this one + Score subtractScore(Score score) { + return addCommandRet( + Command( + 'scoreboard players operation ${_getESStr()} -= ${_getESStr(entity: score.entity, score: score.score)}', + ), + ); + } + + /// sets this score to the result of the multiplication + Score multiplyByScore(Score score) { + return addCommandRet( + Command( + 'scoreboard players operation ${_getESStr()} *= ${_getESStr(entity: score.entity, score: score.score)}', + ), + ); + } + + /// sets this score to the result of the division + Score divideByScore(Score score) { + return addCommandRet( + Command( + 'scoreboard players operation ${_getESStr()} /= ${_getESStr(entity: score.entity, score: score.score)}', + ), + ); + } + + /// sets this score to the remainder of the division + Score modulo(Score score) { + return addCommandRet( + Command( + 'scoreboard players operation ${_getESStr()} %= ${_getESStr(entity: score.entity, score: score.score)}', + ), + ); + } + + /// sets the score to an nbt value + Score setToData(Data data) { + if (!data.isGetting) { + throw ('Please set a score to Data.get and not Data.${data.subcommand}'); + } + return addCommandRet( + Builder( + (c) => Command( + 'execute store result score ${_getESStr()} run data get ${data.getTarget(c)} ${data.path} ${data.scale ?? 1}', + ), + ), + ); + } + + /// set to functions return value(or number of commands) + Group setToFunction(File file) => setToWidget(file.run(create: true)); + + /// sets the score to the success of the given Command + Score setToResult(Command commmand, {bool useSuccess = false}) { + return addCommandRet( + Command( + 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} run $commmand', + ), + ); + } + + /// sets the score to the result of the given Widget + /// JUST one Command should be the input + Group setToWidget(Widget widget, {bool useSuccess = false}) { + return Group( + prefix: + 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} run', + children: [widget], + ); + } + + /// sets the score to the success of the given condition result + Score setToCondition(Condition cond, {bool useSuccess = false}) { + return addCommandRet( + Command( + 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} ${Condition.getPrefixes(cond.getList())[0]}', + ), + ); + } + + /// finds the smallest value in a list of scores + Widget findSmallest(List scores, {int? min}) { + return For( + to: scores.length - 1, + create: (int i) { + var ret = setToSmallest(scores[i]); + if (min != null) { + return If( + scores[i].matchesRange( + Range.from(min), + ), + then: [ret], + ); + } + return ret; + }); + } + + /// finds the biggest value in a list of scores + Widget findBiggest(List scores, {int? max}) { + return For( + to: scores.length - 1, + create: (int i) { + var ret = setToBiggest(scores[i]); + if (max != null) { + return If( + scores[i].matchesRange( + Range.to(max), + ), + then: [ret], + ); + } + return ret; + }); + } + + /// tests + + Score isEqual(Score score) { + return Score.str( + '${_getESStr()} = ${_getESStr(entity: score.entity, score: score.score)}', + ); + } + + Score isSmaller(Score score) { + return Score.str( + '${_getESStr()} < ${_getESStr(entity: score.entity, score: score.score)}', + ); + } + + Score isSmallerOrEqual(Score score) { + return Score.str( + '${_getESStr()} <= ${_getESStr(entity: score.entity, score: score.score)}', + ); + } + + Score isBiggerOrEqual(Score score) { + return Score.str( + '${_getESStr()} >= ${_getESStr(entity: score.entity, score: score.score)}', + ); + } + + Score isBigger(Score score) { + return Score.str( + '${_getESStr()} > ${_getESStr(entity: score.entity, score: score.score)}', + ); + } + + String _match = '0'; + String getMatch() => _match; + Score matches(int value) { + _match = value.toString(); + return Score.str('${_getESStr()} matches $_match', + score: score, match: _match); + } + + Score matchesRange(Range range) { + _match = range.toString(); + return Score.str('${_getESStr()} matches $_match', + score: score, match: _match); + } + + @override + Widget generate(Context context) { + return For.of(_commands); + } + + @override + Map toMap() { + return {'Score': For.of(_commands).toMap()}; + } + + String getString() { + return _strGen; + } +} diff --git a/lib/src/basic/score/score_builder.dart b/lib/src/basic/score/score_builder.dart new file mode 100644 index 0000000..6bcf0f6 --- /dev/null +++ b/lib/src/basic/score/score_builder.dart @@ -0,0 +1,14 @@ +import 'package:objd/src/basic/score/score_operation.dart'; + +class ScoreBuilder { + final ScoreOperation input; + + ScoreBuilder(this.input); + + List compile() { + if (input is ElementaryScoreOperation) { + return [input as ElementaryScoreOperation]; + } + return []; + } +} diff --git a/lib/src/basic/score/score_export.dart b/lib/src/basic/score/score_export.dart new file mode 100644 index 0000000..c76195d --- /dev/null +++ b/lib/src/basic/score/score_export.dart @@ -0,0 +1,4 @@ +library score; + +export 'score.dart'; +export 'score_operation.dart'; diff --git a/lib/src/basic/score/score_operation.dart b/lib/src/basic/score/score_operation.dart new file mode 100644 index 0000000..b73f5a3 --- /dev/null +++ b/lib/src/basic/score/score_operation.dart @@ -0,0 +1,108 @@ +library score; + +import 'package:objd/src/basic/command.dart'; +import 'package:objd/src/basic/score/score.dart'; +import 'package:objd/src/basic/widget.dart'; +import 'package:objd/src/build/context.dart'; + +abstract interface class ScoreAssignable { + // block, bossbar, entity, score, storage + String get_assignable_right(); +} + +sealed class ScoreOperation extends Widget implements ScoreAssignable { + void build() { + print('test'); + } + + @override + String get_assignable_right() { + throw UnimplementedError(); + } +} + +sealed class ElementaryScoreOperation extends ScoreOperation {} + +sealed class BinaryScoreOperation extends ScoreOperation { + final ScoreOperation left; + final ScoreOperation right; + + BinaryScoreOperation(this.left, this.right); +} + +final class IncrementScoreOperation extends ElementaryScoreOperation { + final Score score; + final int increment; + + IncrementScoreOperation(this.score, this.increment); + + @override + generate(Context context) => Command( + increment > 0 + ? 'scoreboard players add $score $increment' + : 'scoreboard players remove $score ${-increment}', + ); +} + +final class StoreScoreOperation extends ElementaryScoreOperation { + final ScoreAssignable left; + final ScoreAssignable right; + + StoreScoreOperation(this.left, this.right); + + @override + generate(Context context) => Command('execute store result ' // TODO: + ); +} + +final class AssignScoreOperation extends ElementaryScoreOperation { + final Score left; + final Score right; + + AssignScoreOperation(this.left, this.right); + + @override + generate(Context context) => + Command('scoreboard players operation $left = $right'); +} + +final class ElementaryBinaryScoreOperation extends ElementaryScoreOperation { + final Score left; + final Score right; + + final ScoreOperator operation; + + ElementaryBinaryScoreOperation({required this.left, required this.right, required this.operation); + + @override + generate(Context context) => + Command('scoreboard players operation $left ${operation.op} $right'); +} + +final class AddScoreOperation extends BinaryScoreOperation { + final ScoreOperation left; + final ScoreOperation right; + + AddScoreOperation(this.left, this.right) : super(left, right); + + @override + generate(Context context) { + // TODO: implement generate + throw UnimplementedError(); + } +} + +enum ScoreOperator { + Addition("+="), + Subtraction("-="), + Multiplication("*="), + Division("/="), + Modulus("%="), + Assign("="), + Min("<"), + Max(">"), + Swap("><"); + + final String op; + const ScoreOperator(this.op); +} diff --git a/lib/src/basic/types/param.dart b/lib/src/basic/types/param.dart new file mode 100644 index 0000000..dc5c09f --- /dev/null +++ b/lib/src/basic/types/param.dart @@ -0,0 +1 @@ +class Param {} From 63ad5411dd766a332811a559f02cd63072cd7ca9 Mon Sep 17 00:00:00 2001 From: Stevertus Date: Tue, 31 Oct 2023 00:55:21 +0100 Subject: [PATCH 2/8] new operations + first builder --- example/score_test.dart | 10 +- lib/src/basic/score.dart | 511 --------------- lib/src/basic/score/score.dart | 800 +++++++++++++---------- lib/src/basic/score/score_builder.dart | 85 ++- lib/src/basic/score/score_condition.dart | 57 ++ lib/src/basic/score/score_export.dart | 2 +- lib/src/basic/score/score_operation.dart | 108 --- lib/src/basic/scoreboard.dart | 20 +- lib/src/basic/text_components.dart | 2 +- lib/src/basic/types/condition.dart | 6 +- lib/src/basic/types/entity.dart | 24 +- lib/src/basic/types/selector.dart | 11 +- lib/src/basic/widgets.dart | 2 +- lib/src/utils/log.dart | 2 +- lib/src/utils/random_score.dart | 15 +- 15 files changed, 636 insertions(+), 1019 deletions(-) delete mode 100644 lib/src/basic/score.dart create mode 100644 lib/src/basic/score/score_condition.dart delete mode 100644 lib/src/basic/score/score_operation.dart diff --git a/example/score_test.dart b/example/score_test.dart index f54eda5..c08b2ad 100644 --- a/example/score_test.dart +++ b/example/score_test.dart @@ -1,6 +1,12 @@ import 'package:objd/core.dart'; -import 'package:objd/src/basic/score/score_operation.dart'; void main(List args) { - ScoreOperation t = Score(Entity.All(), "test"); + var s1 = Score(Entity.All(), "s1"); + var s2 = Score.Self('s2'); + var t = (s1 + s2) + s1 / (s2 + 2); + + print(t); + + final (_, ops) = t.copy(); + print(ops.join('\n\n')); } diff --git a/lib/src/basic/score.dart b/lib/src/basic/score.dart deleted file mode 100644 index 8009b1e..0000000 --- a/lib/src/basic/score.dart +++ /dev/null @@ -1,511 +0,0 @@ -import 'package:objd/src/basic/file.dart'; -import 'package:objd/src/basic/group.dart'; -import 'package:objd/src/basic/rest_action.dart'; -import 'package:objd/src/basic/widget.dart'; -import 'package:objd/src/wrappers/data.dart'; -import 'package:objd/src/basic/command.dart'; -import 'package:objd/src/basic/for_list.dart'; -import 'package:objd/src/basic/types/entity.dart'; -import 'package:objd/src/basic/types/condition.dart'; -import 'package:objd/src/basic/scoreboard.dart'; -import 'package:objd/src/build/build.dart'; -import 'package:objd/src/wrappers/if.dart'; - -import 'builder.dart'; - -class Score extends RestActionAble { - List _commands = []; - - /// Get commands - List get commands => _commands; - final Entity entity; - String score; - String type; - String _strGen = ''; - - /// 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)| - /// - ///```dart - /// Score(Entity.Selected(),'score',addNew: true) - ///``` - - Score( - this.entity, - this.score, { - bool addNew = true, - List? commands, - this.type = 'dummy', - }) { - if (commands != null) _commands = commands; - if (addNew) { - _commands.add( - Scoreboard(score, type: type), - ); - } - if (Scoreboard.prefix != null && !score.contains(Scoreboard.prefix!)) { - score = Scoreboard.prefix! + 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, - this.type = 'dummy', - }) : entity = Entity.Self() { - if (addNew) { - _commands.add( - Scoreboard(score, type: type), - ); - } - if (Scoreboard.prefix != null && !score.contains(Scoreboard.prefix!)) { - score = Scoreboard.prefix! + score; - } - } - Score.str(this._strGen, - {this.score = '', String match = '0', this.type = 'dummy'}) - : entity = Entity.Self() { - _match = match; - } - - /// Do you need constant values with scores? objD got you covered with `Score.con`: - /// - /// |Score.con| | - /// |--|--| - /// |int| a constant number | - /// |addNew|bool whether it should add objd_consts itself if it does not exist(default = true)| - - /// This will automatically create a scoreboard called `objd_consts` and set the value to the fake entity `#[value]` - /// - /// **Example:** - /// ```dart - /// Score.con(5) - /// ⇒ scoreboard players set #5 objd_consts 5 - /// ``` - Score.con( - int number, { - bool addNew = true, - this.type = 'dummy', - }) : score = 'objd_consts', - entity = Entity.PlayerName( - '#$number', - ) { - if (Scoreboard.prefix != null && !score.contains(Scoreboard.prefix!)) { - score = Scoreboard.prefix! + score; - } - - if (addNew) { - _commands.add( - Scoreboard(score, type: type), - ); - } - _commands.add( - set(number), - ); - } - - String _getESStr({Entity? entity, String? score}) { - entity ??= this.entity; - score ??= this.score; - return '$entity $score'; - } - - Score addCommandRet(Widget command) { - var commands = List.from(_commands); - commands.add(command); - return Score(entity, score, addNew: false, commands: commands, type: type); - } - - /// add - Score operator +(dynamic other) { - if (other is int) return add(other); - if (other is Score) return addScore(other); - throw ('Please use either a Score or an Int in the operator +'); - } - - /// subtract - Score operator -(dynamic other) { - if (other is int) return subtract(other); - if (other is Score) return subtractScore(other); - throw ('Please use either a Score or an Int in the operator -'); - } - - /// modulo by - Score operator %(dynamic other) { - if (other is int) { - return modulo( - Score.con(other), - ); - } - if (other is Score) return modulo(other); - throw ('Please use either a Score or an Int in the operator %'); - } - - /// divide by - Score operator /(dynamic other) { - if (other is int) { - return divideByScore( - Score.con(other), - ); - } - if (other is Score) return divideByScore(other); - throw ('Please use either a Score or an Int in the operator /'); - } - - /// multiply by - Score operator *(dynamic other) { - if (other is int) { - return multiplyByScore( - Score.con(other), - ); - } - if (other is Score) return multiplyByScore(other); - throw ('Please use either a Score or an Int in the operator /'); - } - - /// greater than - Score operator >(dynamic other) { - if (other is int) { - return matchesRange( - Range.from(other + 1), - ); - } - if (other is Score) return isBigger(other); - throw ('Please use either a Score or an Int in the operator >'); - } - - /// less than - Score operator <(dynamic other) { - if (other is int) { - return matchesRange( - Range.to(other + -1), - ); - } - if (other is Score) return isSmaller(other); - throw ('Please use either a Score or an Int in the operator >'); - } - - /// bigger or equal - Score operator >=(dynamic other) { - if (other is int) { - return matchesRange( - Range.from(other), - ); - } - if (other is Score) return isBiggerOrEqual(other); - throw ('Please use either a Score or an Int in the operator >='); - } - - /// less or equal - Score operator <=(dynamic other) { - if (other is int) { - return matchesRange( - Range.to(other), - ); - } - if (other is Score) return isSmallerOrEqual(other); - throw ('Please use either a Score or an Int in the operator <='); - } - - /// matches - Score operator &(dynamic other) { - if (other is int) return matches(other); - if (other is Range) return matchesRange(other); - if (other is Score) return isEqual(other); - throw ('Please use either a Score, Range or an Int in the operator &'); - } - - /// assign value(int, Score, Data or Condition) - Widget setTo(dynamic other) { - if (other is int) return set(other); - if (other is Score) return setEqual(other); - if (other is Data) return setToData(other); - if (other is Condition) return setToCondition(other); - if (other is Command) return setToResult(other); - if (other is File) return setToFunction(other); - if (other is Widget) return setToWidget(other); - throw ('Please use either a Score, Data, Condition, Command or an Int in the operator >>'); - } - - Widget operator >>(dynamic other) => setTo(other); - Widget operator <<(dynamic other) => setTo(other); - - /// sets the score to a given value of int - Score set(int val) { - return addCommandRet( - Command( - 'scoreboard players set ${_getESStr()} $val', - ), - ); - } - - /// resets the value of a score - Score reset() { - return addCommandRet( - Command( - 'scoreboard players reset ${_getESStr()}', - ), - ); - } - - /// adds a value to the score - Score add([int val = 1]) { - return addCommandRet( - Command( - 'scoreboard players add ${_getESStr()} $val', - ), - ); - } - - /// subtracts a value from the score - Score subtract([int val = 1]) { - return addCommandRet( - Command( - 'scoreboard players remove ${_getESStr()} $val', - ), - ); - } - - /// gets the value of the score to work with it further - Score get() { - return addCommandRet( - Command( - 'scoreboard players get ${_getESStr()}', - ), - ); - } - - // all operations - /// sets this score equal to another - Score setEqual(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${isEqual(score).getString()}', - ), - ); - } - - /// swaps two scores - Score swapWith(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${_getESStr()} >< ${_getESStr(entity: score.entity, score: score.score)}', - ), - ); - } - - /// compares two scores and sets the smallest to this one - Score setToSmallest(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${isSmaller(score).getString()}', - ), - ); - } - - /// compares two scores and sets the biggest to this one - Score setToBiggest(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${isBigger(score).getString()}', - ), - ); - } - - /// adds another score to this one - Score addScore(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${_getESStr()} += ${_getESStr(entity: score.entity, score: score.score)}', - ), - ); - } - - /// subtracts another score from this one - Score subtractScore(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${_getESStr()} -= ${_getESStr(entity: score.entity, score: score.score)}', - ), - ); - } - - /// sets this score to the result of the multiplication - Score multiplyByScore(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${_getESStr()} *= ${_getESStr(entity: score.entity, score: score.score)}', - ), - ); - } - - /// sets this score to the result of the division - Score divideByScore(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${_getESStr()} /= ${_getESStr(entity: score.entity, score: score.score)}', - ), - ); - } - - /// sets this score to the remainder of the division - Score modulo(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${_getESStr()} %= ${_getESStr(entity: score.entity, score: score.score)}', - ), - ); - } - - /// sets the score to an nbt value - Score setToData(Data data) { - if (!data.isGetting) { - throw ('Please set a score to Data.get and not Data.${data.subcommand}'); - } - return addCommandRet( - Builder( - (c) => Command( - 'execute store result score ${_getESStr()} run data get ${data.getTarget(c)} ${data.path} ${data.scale ?? 1}', - ), - ), - ); - } - - /// set to functions return value(or number of commands) - Group setToFunction(File file) => setToWidget(file.run(create: true)); - - /// sets the score to the success of the given Command - Score setToResult(Command commmand, {bool useSuccess = false}) { - return addCommandRet( - Command( - 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} run $commmand', - ), - ); - } - - /// sets the score to the result of the given Widget - /// JUST one Command should be the input - Group setToWidget(Widget widget, {bool useSuccess = false}) { - return Group( - prefix: - 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} run', - children: [widget], - ); - } - - /// sets the score to the success of the given condition result - Score setToCondition(Condition cond, {bool useSuccess = false}) { - return addCommandRet( - Command( - 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} ${Condition.getPrefixes(cond.getList())[0]}', - ), - ); - } - - /// finds the smallest value in a list of scores - Widget findSmallest(List scores, {int? min}) { - return For( - to: scores.length - 1, - create: (int i) { - var ret = setToSmallest(scores[i]); - if (min != null) { - return If( - scores[i].matchesRange( - Range.from(min), - ), - then: [ret], - ); - } - return ret; - }); - } - - /// finds the biggest value in a list of scores - Widget findBiggest(List scores, {int? max}) { - return For( - to: scores.length - 1, - create: (int i) { - var ret = setToBiggest(scores[i]); - if (max != null) { - return If( - scores[i].matchesRange( - Range.to(max), - ), - then: [ret], - ); - } - return ret; - }); - } - - /// tests - - Score isEqual(Score score) { - return Score.str( - '${_getESStr()} = ${_getESStr(entity: score.entity, score: score.score)}', - ); - } - - Score isSmaller(Score score) { - return Score.str( - '${_getESStr()} < ${_getESStr(entity: score.entity, score: score.score)}', - ); - } - - Score isSmallerOrEqual(Score score) { - return Score.str( - '${_getESStr()} <= ${_getESStr(entity: score.entity, score: score.score)}', - ); - } - - Score isBiggerOrEqual(Score score) { - return Score.str( - '${_getESStr()} >= ${_getESStr(entity: score.entity, score: score.score)}', - ); - } - - Score isBigger(Score score) { - return Score.str( - '${_getESStr()} > ${_getESStr(entity: score.entity, score: score.score)}', - ); - } - - String _match = '0'; - String getMatch() => _match; - Score matches(int value) { - _match = value.toString(); - return Score.str('${_getESStr()} matches $_match', - score: score, match: _match); - } - - Score matchesRange(Range range) { - _match = range.toString(); - return Score.str('${_getESStr()} matches $_match', - score: score, match: _match); - } - - @override - Widget generate(Context context) { - return For.of(_commands); - } - - @override - Map toMap() { - return {'Score': For.of(_commands).toMap()}; - } - - String getString() { - return _strGen; - } -} diff --git a/lib/src/basic/score/score.dart b/lib/src/basic/score/score.dart index 96fc8c1..8e77be4 100644 --- a/lib/src/basic/score/score.dart +++ b/lib/src/basic/score/score.dart @@ -1,427 +1,557 @@ +// ignore_for_file: public_member_api_docs, sort_constructors_first library score; -import 'package:objd/src/basic/file.dart'; -import 'package:objd/src/basic/group.dart'; -import 'package:objd/src/basic/rest_action.dart'; -import 'package:objd/src/basic/score/score_operation.dart'; -import 'package:objd/src/basic/widget.dart'; -import 'package:objd/src/wrappers/data.dart'; +import 'package:objd/core.dart'; import 'package:objd/src/basic/command.dart'; -import 'package:objd/src/basic/for_list.dart'; -import 'package:objd/src/basic/types/entity.dart'; -import 'package:objd/src/basic/types/condition.dart'; +import 'package:objd/src/basic/score/score.dart'; +import 'package:objd/src/basic/score/score_builder.dart'; +import 'package:objd/src/basic/score/score_condition.dart'; +import 'package:objd/src/basic/score/score_export.dart'; import 'package:objd/src/basic/scoreboard.dart'; -import 'package:objd/src/build/build.dart'; -import 'package:objd/src/wrappers/if.dart'; - -import '../builder.dart'; - -class Score extends ScoreOperation { - List _commands = []; - - /// Get commands - List get commands => _commands; - final Entity entity; - String score; - String type; - String _strGen = ''; - - /// 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)| - /// - ///```dart - /// Score(Entity.Selected(),'score',addNew: true) - ///``` - - Score( - this.entity, - this.score, { - bool addNew = true, - List? commands, - this.type = 'dummy', - }) { - if (commands != null) _commands = commands; - if (addNew) { - _commands.add( - Scoreboard(score, type: type), - ); - } - if (Scoreboard.prefix != null && !score.contains(Scoreboard.prefix!)) { - score = Scoreboard.prefix! + 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, - this.type = 'dummy', - }) : entity = Entity.Self() { - if (addNew) { - _commands.add( - Scoreboard(score, type: type), - ); - } - if (Scoreboard.prefix != null && !score.contains(Scoreboard.prefix!)) { - score = Scoreboard.prefix! + score; - } - } - Score.str(this._strGen, - {this.score = '', String match = '0', this.type = 'dummy'}) - : entity = Entity.Self() { - _match = match; - } - - /// Do you need constant values with scores? objD got you covered with `Score.con`: - /// - /// |Score.con| | - /// |--|--| - /// |int| a constant number | - /// |addNew|bool whether it should add objd_consts itself if it does not exist(default = true)| - - /// This will automatically create a scoreboard called `objd_consts` and set the value to the fake entity `#[value]` - /// - /// **Example:** - /// ```dart - /// Score.con(5) - /// ⇒ scoreboard players set #5 objd_consts 5 - /// ``` - Score.con( - int number, { - bool addNew = true, - this.type = 'dummy', - }) : score = 'objd_consts', - entity = Entity.PlayerName( - '#$number', - ) { - if (Scoreboard.prefix != null && !score.contains(Scoreboard.prefix!)) { - score = Scoreboard.prefix! + score; - } - - if (addNew) { - _commands.add( - Scoreboard(score, type: type), - ); - } - _commands.add( - set(number), - ); - } - - String _getESStr({Entity? entity, String? score}) { - entity ??= this.entity; - score ??= this.score; - return '$entity $score'; - } +import 'package:objd/src/basic/types/entity.dart'; +import 'package:objd/src/basic/widget.dart'; +import 'package:objd/src/build/context.dart'; - String toString({Entity? entity, String? score}) { - entity ??= this.entity; - score ??= this.score; - return '$entity $score'; - } +abstract interface class ScoreAssignable { + // block, bossbar, entity, score, storage + String get_assignable_right(); +} - Score addCommandRet(Widget command) { - var commands = List.from(_commands); - commands.add(command); - return Score(entity, score, addNew: false, commands: commands, type: type); - } +abstract interface class ScoreStoreable extends ScoreAssignable { + // block, bossbar, entity, score, storage + String get_assignable_left(); +} +sealed class ScoreOperation extends Widget implements ScoreAssignable { /// add - Score operator +(dynamic other) { + BinaryScoreOperation operator +(dynamic other) { if (other is int) return add(other); - if (other is Score) return addScore(other); + if (other is ScoreOperation) return addScore(other); throw ('Please use either a Score or an Int in the operator +'); } /// subtract - Score operator -(dynamic other) { + BinaryScoreOperation operator -(dynamic other) { if (other is int) return subtract(other); - if (other is Score) return subtractScore(other); + if (other is ScoreOperation) return subtractScore(other); throw ('Please use either a Score or an Int in the operator -'); } /// modulo by - Score operator %(dynamic other) { + BinaryScoreOperation operator %(dynamic other) { if (other is int) { return modulo( Score.con(other), ); } - if (other is Score) return modulo(other); + if (other is ScoreOperation) return modulo(other); throw ('Please use either a Score or an Int in the operator %'); } /// divide by - Score operator /(dynamic other) { + BinaryScoreOperation operator /(dynamic other) { if (other is int) { return divideByScore( Score.con(other), ); } - if (other is Score) return divideByScore(other); + if (other is ScoreOperation) return divideByScore(other); throw ('Please use either a Score or an Int in the operator /'); } /// multiply by - Score operator *(dynamic other) { + BinaryScoreOperation operator *(dynamic other) { if (other is int) { return multiplyByScore( Score.con(other), ); } - if (other is Score) return multiplyByScore(other); + if (other is ScoreOperation) return multiplyByScore(other); throw ('Please use either a Score or an Int in the operator /'); } /// greater than - Score operator >(dynamic other) { + ScoreCondition operator >(dynamic other) { if (other is int) { return matchesRange( Range.from(other + 1), ); } - if (other is Score) return isBigger(other); + if (other is ScoreOperation) return isBigger(other); throw ('Please use either a Score or an Int in the operator >'); } /// less than - Score operator <(dynamic other) { + ScoreCondition operator <(dynamic other) { if (other is int) { return matchesRange( Range.to(other + -1), ); } - if (other is Score) return isSmaller(other); + if (other is ScoreOperation) return isSmaller(other); throw ('Please use either a Score or an Int in the operator >'); } /// bigger or equal - Score operator >=(dynamic other) { + ScoreCondition operator >=(dynamic other) { if (other is int) { return matchesRange( Range.from(other), ); } - if (other is Score) return isBiggerOrEqual(other); + if (other is ScoreOperation) return isBiggerOrEqual(other); throw ('Please use either a Score or an Int in the operator >='); } /// less or equal - Score operator <=(dynamic other) { + ScoreCondition operator <=(dynamic other) { if (other is int) { return matchesRange( Range.to(other), ); } - if (other is Score) return isSmallerOrEqual(other); + if (other is ScoreOperation) return isSmallerOrEqual(other); throw ('Please use either a Score or an Int in the operator <='); } /// matches - Score operator &(dynamic other) { + ScoreCondition operator &(dynamic other) { if (other is int) return matches(other); if (other is Range) return matchesRange(other); - if (other is Score) return isEqual(other); + if (other is ScoreOperation) return isEqual(other); throw ('Please use either a Score, Range or an Int in the operator &'); } - /// assign value(int, Score, Data or Condition) - Widget setTo(dynamic other) { - if (other is int) return set(other); - if (other is Score) return setEqual(other); - if (other is Data) return setToData(other); - if (other is Condition) return setToCondition(other); - if (other is Command) return setToResult(other); - if (other is File) return setToFunction(other); - if (other is Widget) return setToWidget(other); - throw ('Please use either a Score, Data, Condition, Command or an Int in the operator >>'); - } + /// adds a value to the score + BinaryScoreOperation add([int val = 1]) => BinaryScoreOperation( + this, + val >= 0 ? ScoreOperator.Addition : ScoreOperator.Subtraction, + Score.con(val.abs()), + ); - Widget operator >>(dynamic other) => setTo(other); - Widget operator <<(dynamic other) => setTo(other); + /// subtracts a value from the score + BinaryScoreOperation subtract([int val = 1]) => BinaryScoreOperation( + this, + val >= 0 ? ScoreOperator.Subtraction : ScoreOperator.Addition, + Score.con(val.abs()), + ); - /// sets the score to a given value of int - Score set(int val) { - return addCommandRet( - Command( - 'scoreboard players set ${_getESStr()} $val', - ), - ); - } + /// gets the value of the score to work with it further + // TODO + // Score get() { + // return addCommandRet( + // Command( + // 'scoreboard players get ${_getESStr()}', + // ), + // ); + // } - /// resets the value of a score - Score reset() { - return addCommandRet( - Command( - 'scoreboard players reset ${_getESStr()}', - ), - ); - } + // binary operations - /// adds a value to the score - Score add([int val = 1]) { - return addCommandRet( - Command( - 'scoreboard players add ${_getESStr()} $val', - ), - ); - } + /// adds another score to this one + BinaryScoreOperation addScore(ScoreOperation score) => + BinaryScoreOperation(this, ScoreOperator.Addition, score); - /// subtracts a value from the score - Score subtract([int val = 1]) { - return addCommandRet( - Command( - 'scoreboard players remove ${_getESStr()} $val', - ), - ); - } + /// subtracts another score from this one + BinaryScoreOperation subtractScore(ScoreOperation score) => + BinaryScoreOperation(this, ScoreOperator.Subtraction, score); - /// gets the value of the score to work with it further - Score get() { - return addCommandRet( - Command( - 'scoreboard players get ${_getESStr()}', - ), - ); - } + /// sets this score to the result of the multiplication + BinaryScoreOperation multiplyByScore(ScoreOperation score) => + BinaryScoreOperation(this, ScoreOperator.Multiplication, score); - // all operations - /// sets this score equal to another - Score setEqual(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${isEqual(score).getString()}', - ), - ); - } + /// sets this score to the result of the division + BinaryScoreOperation divideByScore(ScoreOperation score) => + BinaryScoreOperation(this, ScoreOperator.Division, score); - /// swaps two scores - Score swapWith(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${_getESStr()} >< ${_getESStr(entity: score.entity, score: score.score)}', - ), - ); - } + /// sets this score to the remainder of the division + BinaryScoreOperation modulo(ScoreOperation score) => + BinaryScoreOperation(this, ScoreOperator.Modulo, score); - /// compares two scores and sets the smallest to this one - Score setToSmallest(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${isSmaller(score).getString()}', - ), + /// sets the score to an nbt value + // Score setToData(Data data) { + // if (!data.isGetting) { + // throw ('Please set a score to Data.get and not Data.${data.subcommand}'); + // } + // return addCommandRet( + // Builder( + // (c) => Command( + // 'execute store result score ${_getESStr()} run data get ${data.getTarget(c)} ${data.path} ${data.scale ?? 1}', + // ), + // ), + // ); + // } + + // /// set to functions return value(or number of commands) + // Group setToFunction(File file) => setToWidget(file.run(create: true)); + + // /// sets the score to the success of the given Command + // Score setToResult(Command commmand, {bool useSuccess = false}) { + // return addCommandRet( + // Command( + // 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} run $commmand', + // ), + // ); + // } + + // /// sets the score to the result of the given Widget + // /// JUST one Command should be the input + // Group setToWidget(Widget widget, {bool useSuccess = false}) { + // return Group( + // prefix: + // 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} run', + // children: [widget], + // ); + // } + + // /// sets the score to the success of the given condition result + // Score setToCondition(Condition cond, {bool useSuccess = false}) { + // return addCommandRet( + // Command( + // 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} ${Condition.getPrefixes(cond.getList())[0]}', + // ), + // ); + // } + + /// tests + + BinaryScoreCondition isEqual(ScoreOperation score) => + BinaryScoreCondition(this, ConditionalOperator.Equal, score); + BinaryScoreCondition isSmaller(ScoreOperation score) => + BinaryScoreCondition(this, ConditionalOperator.Less, score); + BinaryScoreCondition isSmallerOrEqual(ScoreOperation score) => + BinaryScoreCondition(this, ConditionalOperator.LessEqual, score); + BinaryScoreCondition isBiggerOrEqual(ScoreOperation score) => + BinaryScoreCondition(this, ConditionalOperator.BiggerEqual, score); + BinaryScoreCondition isBigger(ScoreOperation score) => + BinaryScoreCondition(this, ConditionalOperator.Bigger, score); + + MatchesScoreCondition matches(int value) => + MatchesScoreCondition(this, Range.exact(value)); + MatchesScoreCondition matchesRange(Range range) => + MatchesScoreCondition(this, range); + + void build() { + print('test'); + } + + (Score, List) copy({ + Score? out, + ScoreBuilder? builder, + bool compact = false, + }) { + out ??= Score( + Entity.PlayerName('#${Scoreboard.generateNewTempPlayerName()}'), + 'objd_temp', ); + + builder ??= ScoreBuilder(); + + return (out, builder.compile(this, out: out)); } - /// compares two scores and sets the biggest to this one - Score setToBiggest(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${isBigger(score).getString()}', - ), - ); + @override + String get_assignable_right() { + throw UnimplementedError(); } +} - /// adds another score to this one - Score addScore(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${_getESStr()} += ${_getESStr(entity: score.entity, score: score.score)}', - ), - ); +sealed class ElementaryScoreOperation extends ScoreOperation {} + +final class IncrementScoreOperation extends ElementaryScoreOperation { + final Score score; + final int increment; + + IncrementScoreOperation(this.score, this.increment); + + @override + generate(Context context) => Command( + increment > 0 + ? 'scoreboard players add $score $increment' + : 'scoreboard players remove $score ${-increment}', + ); + + @override + String toString() => '$score += $increment'; +} + +final class SetScoreOperation extends ElementaryScoreOperation { + final Score score; + final int value; + + SetScoreOperation(this.score, this.value); + + @override + generate(Context context) => Command('scoreboard players set $score $value'); + + @override + String toString() => 'set $score = $value'; +} + +final class ResetScoreOperation extends ElementaryScoreOperation { + final Score score; + + ResetScoreOperation(this.score); + + @override + generate(Context context) => Command('scoreboard players reset $score'); + + @override + String toString() => 'reset $score'; +} + +final class StoreScoreOperation extends ElementaryScoreOperation { + final ScoreStoreable left; + final ScoreAssignable right; + + StoreScoreOperation(this.left, this.right); + + @override + generate(Context context) => Command('execute store result ' // TODO: + ); + + @override + String toString() => [ + ' | ${left.get_assignable_left()}', + '<<', + ' | ${right.get_assignable_right()}', + ].join('\n'); +} + +final class ElementaryBinaryScoreOperation extends ElementaryScoreOperation { + final Score left; + final Score right; + + final ScoreOperator operation; + + ElementaryBinaryScoreOperation({ + required this.left, + required this.right, + required this.operation, + }); + + @override + Widget generate(Context context) => + Command('scoreboard players operation $left ${operation.op} $right'); + + @override + String toString() => '$left ${operation.op} $right'; +} + +final class AssignScoreOperation extends ElementaryScoreOperation { + final Score left; + final ScoreAssignable right; + + AssignScoreOperation(this.left, this.right); + + @override + Widget generate(Context context) => Command( + 'scoreboard players operation $left = ${right.get_assignable_right()}', + ); + + @override + String toString() => [ + ' | $left', + '<<', + ' | ${right.get_assignable_right()}', + ].join('\n'); +} + +class BinaryScoreOperation extends ScoreOperation { + final ScoreOperation left; + final ScoreOperation right; + + final ScoreOperator operation; + + BinaryScoreOperation(this.left, this.operation, this.right); + + @override + generate(Context context) { + // TODO: implement generate + throw UnimplementedError(); } - /// subtracts another score from this one - Score subtractScore(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${_getESStr()} -= ${_getESStr(entity: score.entity, score: score.score)}', - ), - ); + @override + String toString() { + final lStr = left.toString().splitMapJoin('\n', onNonMatch: (s) => ' | $s'); + final rStr = + right.toString().splitMapJoin('\n', onNonMatch: (s) => ' | $s'); + + return [lStr, operation.op, rStr].join('\n'); } +} - /// sets this score to the result of the multiplication - Score multiplyByScore(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${_getESStr()} *= ${_getESStr(entity: score.entity, score: score.score)}', - ), - ); +enum ScoreOperator { + Addition("+="), + Subtraction("-="), + Multiplication("*="), + Division("/="), + Modulo("%="), + Assign("="), + Min("<"), + Max(">"), + Swap("><"); + + final String op; + const ScoreOperator(this.op); +} + +class ConstScore extends Score { + final int value; + + ConstScore( + this.value, { + bool addNew = true, + String type = 'dummy', + }) : super( + Entity.PlayerName( + '#$value', + ), + 'objd_consts', + addNew: addNew, + type: type, + ); +} + +class Score extends ElementaryScoreOperation implements ScoreStoreable { + final Entity entity; + String score; + final String type; + final bool addNew; + + /// 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)| + /// + ///```dart + /// Score(Entity.Selected(),'score',addNew: true) + ///``` + + Score( + this.entity, + this.score, { + this.addNew = true, + this.type = 'dummy', + }) { + if (Scoreboard.prefix != null && !score.contains(Scoreboard.prefix!)) { + score = Scoreboard.prefix! + score; + } } - /// sets this score to the result of the division - Score divideByScore(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${_getESStr()} /= ${_getESStr(entity: score.entity, score: score.score)}', - ), - ); + /// same as Score() but with a predefined entity(Entity.Selected(),) + /// ```dart + /// Score.fromSelected('objective').set(3) + /// ⇒ scoreboard players set @s objective 3 + /// ``` + factory Score.fromSelected( + String score, { + bool addNew = true, + String type = 'dummy', + }) => + Score(Entity.Self(), score, addNew: addNew, type: type); + + /// same as Score() but with a predefined entity(Entity.Selected(),) + /// ```dart + /// Score.fromSelected('objective').set(3) + /// ⇒ scoreboard players set @s objective 3 + /// ``` + factory Score.Self( + String score, { + bool addNew = true, + String type = 'dummy', + }) => + Score(Entity.Self(), score, addNew: addNew, type: type); + + /// Do you need constant values with scores? objD got you covered with `Score.con`: + /// + /// |Score.con| | + /// |--|--| + /// |int| a constant number | + /// |addNew|bool whether it should add objd_consts itself if it does not exist(default = true)| + + /// This will automatically create a scoreboard called `objd_consts` and set the value to the fake entity `#[value]` + /// + /// **Example:** + /// ```dart + /// Score.con(5) + /// ⇒ scoreboard players set #5 objd_consts 5 + /// ``` + static ConstScore con( + int number, { + bool addNew = true, + String type = 'dummy', + }) => + ConstScore(number, addNew: addNew, type: type); + + String toString({Entity? entity, String? score}) { + entity ??= this.entity; + score ??= this.score; + return '$entity $score'; } - /// sets this score to the remainder of the division - Score modulo(Score score) { - return addCommandRet( - Command( - 'scoreboard players operation ${_getESStr()} %= ${_getESStr(entity: score.entity, score: score.score)}', - ), - ); + (Score, List) copy({ + Score? out, + ScoreBuilder? builder, + bool compact = false, + }) { + print("Score!"); + if (compact && out == null) return (this, []); + if (out != null) return (out, [AssignScoreOperation(out, this)]); + return super.copy(out: out, builder: builder, compact: false); } - /// sets the score to an nbt value - Score setToData(Data data) { - if (!data.isGetting) { - throw ('Please set a score to Data.get and not Data.${data.subcommand}'); + /// assign value(int, Score, Data or Condition) + ScoreOperation setTo(dynamic other) { + if (this is! ScoreStoreable) { + throw Exception('$other can not be assigned to left Hand Side $this'); } - return addCommandRet( - Builder( - (c) => Command( - 'execute store result score ${_getESStr()} run data get ${data.getTarget(c)} ${data.path} ${data.scale ?? 1}', - ), - ), - ); - } - /// set to functions return value(or number of commands) - Group setToFunction(File file) => setToWidget(file.run(create: true)); + if (other is int) return set(other); + if (other is Score) return setEqual(other); - /// sets the score to the success of the given Command - Score setToResult(Command commmand, {bool useSuccess = false}) { - return addCommandRet( - Command( - 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} run $commmand', - ), - ); + ///if (other is Data) return setToData(other); + // if (other is Condition) return setToCondition(other); + // if (other is Command) return setToResult(other); + // if (other is File) return setToFunction(other); + // if (other is Widget) return setToWidget(other); + throw ('Please use either a Score, Data, Condition, Command or an Int in the operator >>'); } - /// sets the score to the result of the given Widget - /// JUST one Command should be the input - Group setToWidget(Widget widget, {bool useSuccess = false}) { - return Group( - prefix: - 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} run', - children: [widget], - ); - } + Widget operator >>(dynamic other) => setTo(other); + Widget operator <<(dynamic other) => setTo(other); - /// sets the score to the success of the given condition result - Score setToCondition(Condition cond, {bool useSuccess = false}) { - return addCommandRet( - Command( - 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} ${Condition.getPrefixes(cond.getList())[0]}', - ), - ); + /// sets the score to a given value of int + BinaryScoreOperation set(int val) { + if (this is! ScoreStoreable) { + throw Exception('$val can not be assigned to left Hand Side $this'); + } + + return BinaryScoreOperation(this, ScoreOperator.Assign, Score.con(val)); } + ResetScoreOperation reset() => ResetScoreOperation(this); + + /// sets this score equal to another + BinaryScoreOperation setEqual(ScoreOperation score) => + BinaryScoreOperation(this, ScoreOperator.Assign, score); + + /// swaps two scores + BinaryScoreOperation swapWith(ScoreOperation score) => + BinaryScoreOperation(this, ScoreOperator.Swap, score); + + /// compares two scores and sets the smallest to this one + BinaryScoreOperation setToSmallest(ScoreOperation score) => + BinaryScoreOperation(this, ScoreOperator.Min, score); + + /// compares two scores and sets the biggest to this one + BinaryScoreOperation setToBiggest(ScoreOperation score) => + BinaryScoreOperation(this, ScoreOperator.Max, score); + /// finds the smallest value in a list of scores Widget findSmallest(List scores, {int? min}) { return For( @@ -458,63 +588,17 @@ class Score extends ScoreOperation { }); } - /// tests - - Score isEqual(Score score) { - return Score.str( - '${_getESStr()} = ${_getESStr(entity: score.entity, score: score.score)}', - ); - } - - Score isSmaller(Score score) { - return Score.str( - '${_getESStr()} < ${_getESStr(entity: score.entity, score: score.score)}', - ); - } - - Score isSmallerOrEqual(Score score) { - return Score.str( - '${_getESStr()} <= ${_getESStr(entity: score.entity, score: score.score)}', - ); - } - - Score isBiggerOrEqual(Score score) { - return Score.str( - '${_getESStr()} >= ${_getESStr(entity: score.entity, score: score.score)}', - ); - } - - Score isBigger(Score score) { - return Score.str( - '${_getESStr()} > ${_getESStr(entity: score.entity, score: score.score)}', - ); - } - - String _match = '0'; - String getMatch() => _match; - Score matches(int value) { - _match = value.toString(); - return Score.str('${_getESStr()} matches $_match', - score: score, match: _match); - } - - Score matchesRange(Range range) { - _match = range.toString(); - return Score.str('${_getESStr()} matches $_match', - score: score, match: _match); - } - @override Widget generate(Context context) { - return For.of(_commands); + return addNew ? Scoreboard.add(score, type: type) : Comment.Null(); } @override - Map toMap() { - return {'Score': For.of(_commands).toMap()}; + String get_assignable_left() { + // TODO: implement get_assignable_left + throw UnimplementedError(); } - String getString() { - return _strGen; - } + @override + String get_assignable_right() => 'scoreboard players get $this'; } diff --git a/lib/src/basic/score/score_builder.dart b/lib/src/basic/score/score_builder.dart index 6bcf0f6..c4e8064 100644 --- a/lib/src/basic/score/score_builder.dart +++ b/lib/src/basic/score/score_builder.dart @@ -1,14 +1,85 @@ -import 'package:objd/src/basic/score/score_operation.dart'; +import 'package:objd/src/basic/score/score.dart'; class ScoreBuilder { - final ScoreOperation input; + List compile(ScoreOperation input, {Score? out}) { + return switch (input) { + BinaryScoreOperation( + left: final left, + operation: final operation, + right: final right + ) => + compileBinary(left, operation, right, out: out), + IncrementScoreOperation(score: final score) => [ + input, + if (out != null) AssignScoreOperation(out, score), + ], + SetScoreOperation(score: final score) => [ + input, + if (out != null) AssignScoreOperation(out, score), + ], + ResetScoreOperation(score: final score) => [ + input, + if (out != null) AssignScoreOperation(out, score), + ], + StoreScoreOperation(left: final left) => [ + input, + if (out != null) StoreScoreOperation(out, left) + ], + ElementaryBinaryScoreOperation(left: final left) => [ + input, + if (out != null) AssignScoreOperation(out, left) + ], + AssignScoreOperation(left: final left) => [ + input, + if (out != null) AssignScoreOperation(out, left), + ], + Score score => [ + score, + if (out != null) AssignScoreOperation(out, score), + ], + }; + } + + List compileBinary( + ScoreOperation left, ScoreOperator operator, ScoreOperation right, + {Score? out}) { + if (operator == ScoreOperator.Assign) { + assert(left is ScoreStoreable, "Tried to assign $right to $left"); + final (tmpRight, prevactions) = right.copy(compact: true); + + if (left is Score) { + if (right is ConstScore) { + return [SetScoreOperation(left, right.value)]; + } - ScoreBuilder(this.input); + return [...prevactions, AssignScoreOperation(left, tmpRight)]; + } + return [ + ...prevactions, + StoreScoreOperation(left as ScoreStoreable, tmpRight) + ]; + } - List compile() { - if (input is ElementaryScoreOperation) { - return [input as ElementaryScoreOperation]; + var leftActions = compile(left, out: out); + if (out == null) { + if (left is Score) { + out ??= left; + } else { + (out, leftActions) = left.copy(); + } } - return []; + + final (tmpRight, rightActions) = right.copy(compact: true); + + // other operators + return [ + ...leftActions, + ...rightActions, + ElementaryBinaryScoreOperation( + left: out, + right: tmpRight, + operation: operator, + ) + ]; } } diff --git a/lib/src/basic/score/score_condition.dart b/lib/src/basic/score/score_condition.dart new file mode 100644 index 0000000..e2905af --- /dev/null +++ b/lib/src/basic/score/score_condition.dart @@ -0,0 +1,57 @@ +// ignore_for_file: public_member_api_docs, sort_constructors_first +import 'package:objd/src/basic/score/score_export.dart'; +import 'package:objd/src/basic/types/condition.dart'; +import 'package:objd/src/basic/types/entity.dart'; + +sealed class ScoreCondition extends Condition { + ScoreCondition() : super(null); +} + +class MatchesScoreCondition extends ScoreCondition { + final ScoreOperation score; + final Range range; + + MatchesScoreCondition( + this.score, + this.range, + ); + + String getMatch() => range.toString(); + + @override + String toString() { + final lStr = + score.toString().splitMapJoin('\n', onNonMatch: (s) => ' | $s'); + final rStr = range.toString(); + + return [lStr, 'matches', rStr].join('\n'); + } +} + +class BinaryScoreCondition extends ScoreCondition { + final ScoreOperation left; + final ConditionalOperator operation; + final ScoreOperation right; + + BinaryScoreCondition(this.left, this.operation, this.right); + + @override + String toString() { + final lStr = left.toString().splitMapJoin('\n', onNonMatch: (s) => ' | $s'); + final rStr = + right.toString().splitMapJoin('\n', onNonMatch: (s) => ' | $s'); + + return [lStr, operation.op, rStr].join('\n'); + } +} + +enum ConditionalOperator { + Bigger(">"), + BiggerEqual(">="), + Equal("="), + LessEqual("<="), + Less("<"); + + final String op; + const ConditionalOperator(this.op); +} diff --git a/lib/src/basic/score/score_export.dart b/lib/src/basic/score/score_export.dart index c76195d..9377c17 100644 --- a/lib/src/basic/score/score_export.dart +++ b/lib/src/basic/score/score_export.dart @@ -1,4 +1,4 @@ library score; export 'score.dart'; -export 'score_operation.dart'; +export 'score_condition.dart'; diff --git a/lib/src/basic/score/score_operation.dart b/lib/src/basic/score/score_operation.dart deleted file mode 100644 index b73f5a3..0000000 --- a/lib/src/basic/score/score_operation.dart +++ /dev/null @@ -1,108 +0,0 @@ -library score; - -import 'package:objd/src/basic/command.dart'; -import 'package:objd/src/basic/score/score.dart'; -import 'package:objd/src/basic/widget.dart'; -import 'package:objd/src/build/context.dart'; - -abstract interface class ScoreAssignable { - // block, bossbar, entity, score, storage - String get_assignable_right(); -} - -sealed class ScoreOperation extends Widget implements ScoreAssignable { - void build() { - print('test'); - } - - @override - String get_assignable_right() { - throw UnimplementedError(); - } -} - -sealed class ElementaryScoreOperation extends ScoreOperation {} - -sealed class BinaryScoreOperation extends ScoreOperation { - final ScoreOperation left; - final ScoreOperation right; - - BinaryScoreOperation(this.left, this.right); -} - -final class IncrementScoreOperation extends ElementaryScoreOperation { - final Score score; - final int increment; - - IncrementScoreOperation(this.score, this.increment); - - @override - generate(Context context) => Command( - increment > 0 - ? 'scoreboard players add $score $increment' - : 'scoreboard players remove $score ${-increment}', - ); -} - -final class StoreScoreOperation extends ElementaryScoreOperation { - final ScoreAssignable left; - final ScoreAssignable right; - - StoreScoreOperation(this.left, this.right); - - @override - generate(Context context) => Command('execute store result ' // TODO: - ); -} - -final class AssignScoreOperation extends ElementaryScoreOperation { - final Score left; - final Score right; - - AssignScoreOperation(this.left, this.right); - - @override - generate(Context context) => - Command('scoreboard players operation $left = $right'); -} - -final class ElementaryBinaryScoreOperation extends ElementaryScoreOperation { - final Score left; - final Score right; - - final ScoreOperator operation; - - ElementaryBinaryScoreOperation({required this.left, required this.right, required this.operation); - - @override - generate(Context context) => - Command('scoreboard players operation $left ${operation.op} $right'); -} - -final class AddScoreOperation extends BinaryScoreOperation { - final ScoreOperation left; - final ScoreOperation right; - - AddScoreOperation(this.left, this.right) : super(left, right); - - @override - generate(Context context) { - // TODO: implement generate - throw UnimplementedError(); - } -} - -enum ScoreOperator { - Addition("+="), - Subtraction("-="), - Multiplication("*="), - Division("/="), - Modulus("%="), - Assign("="), - Min("<"), - Max(">"), - Swap("><"); - - final String op; - const ScoreOperator(this.op); -} diff --git a/lib/src/basic/scoreboard.dart b/lib/src/basic/scoreboard.dart index 0b7fa5a..537ce6c 100644 --- a/lib/src/basic/scoreboard.dart +++ b/lib/src/basic/scoreboard.dart @@ -1,6 +1,8 @@ +import 'dart:math'; + +import 'package:objd/src/basic/score/score.dart'; import 'package:objd/src/basic/types/entity.dart'; import 'package:objd/src/basic/rest_action.dart'; -import 'package:objd/src/basic/score.dart'; import 'package:objd/src/basic/widget.dart'; import 'package:objd/src/basic/command.dart'; import 'package:objd/src/basic/text_components.dart'; @@ -13,6 +15,22 @@ class Scoreboard extends RestActionAble { static String? prefix; + static final Set _tempScores = {}; + + static String generateNewTempPlayerName({int len = 10}) { + var r = Random(); + String name = ''; + + do { + name = String.fromCharCodes( + List.generate(len, (index) => r.nextInt(33) + 89), + ); + } while (_tempScores.contains(name)); + + _tempScores.add(name); + return name; + } + final String subcommand; String name; late String type; diff --git a/lib/src/basic/text_components.dart b/lib/src/basic/text_components.dart index 2414bb6..8cd0c55 100644 --- a/lib/src/basic/text_components.dart +++ b/lib/src/basic/text_components.dart @@ -2,12 +2,12 @@ import 'package:gson/values.dart'; import 'package:objd/src/basic/command.dart'; +import 'package:objd/src/basic/score/score.dart'; import 'package:objd/src/basic/types/entity.dart'; import 'dart:convert'; import 'package:objd/src/basic/types/item.dart'; import 'package:objd/src/basic/types/location.dart'; -import 'package:objd/src/basic/score.dart'; class TextComponent extends GsonValue { late Map value; diff --git a/lib/src/basic/types/condition.dart b/lib/src/basic/types/condition.dart index 26e54d1..47baf56 100644 --- a/lib/src/basic/types/condition.dart +++ b/lib/src/basic/types/condition.dart @@ -1,10 +1,10 @@ +import 'package:objd/src/basic/score/score_export.dart'; import 'package:objd/src/basic/types/area.dart'; import 'package:objd/src/basic/types/biomes.dart'; import 'package:objd/src/basic/types/block.dart'; import 'package:objd/src/basic/types/entity.dart'; import 'package:objd/src/basic/types/location.dart'; import 'package:objd/src/basic/predicate.dart'; -import 'package:objd/src/basic/score.dart'; import 'package:objd/src/basic/tag.dart'; import 'package:objd/src/wrappers/data.dart'; import 'package:objd/src/wrappers/execute.dart'; @@ -156,10 +156,10 @@ class Condition { } if (cond is Score) { - if (cond.getString().isEmpty) { + if (cond.toString().isEmpty) { throw ('Please insert a score condition method into a condition!'); } - _generated = _ConditionUtil('score ${cond.getString()}', invert: invert); + _generated = _ConditionUtil('score ${cond.toString()}', invert: invert); return; } diff --git a/lib/src/basic/types/entity.dart b/lib/src/basic/types/entity.dart index 48c19c6..060795c 100644 --- a/lib/src/basic/types/entity.dart +++ b/lib/src/basic/types/entity.dart @@ -22,7 +22,7 @@ class Entity extends GsonValue implements EntityClass { Team? team, String? strNbt, Map? nbt, - List? scores, + List? scores, Range? level, Gamemode? gamemode, Area? area, @@ -64,7 +64,7 @@ class Entity extends GsonValue implements EntityClass { String? strNbt, Map? nbt, int? limit, - List? scores, + List? scores, Range? level, Gamemode? gamemode, Area? area, @@ -104,7 +104,7 @@ class Entity extends GsonValue implements EntityClass { String? strNbt, Map? nbt, int? limit, - List? scores, + List? scores, Range? level, Gamemode? gamemode, Area? area, @@ -143,7 +143,7 @@ class Entity extends GsonValue implements EntityClass { Team? team, String? strNbt, Map? nbt, - List? scores, + List? scores, Range? level, Gamemode? gamemode, Area? area, @@ -182,7 +182,7 @@ class Entity extends GsonValue implements EntityClass { String? strNbt, Map? nbt, Map? data, - List? scores, + List? scores, Range? level, Gamemode? gamemode, Area? area, @@ -226,7 +226,7 @@ class Entity extends GsonValue implements EntityClass { Team? team, String? strNbt, Map? nbt, - List? scores, + List? scores, Range? level, Gamemode? gamemode, Area? area, @@ -295,7 +295,7 @@ class Entity extends GsonValue implements EntityClass { int? limit, List? tags, Team? team, - List? scores, + List? scores, Map? nbt, String? strNbt, EntityType? type, @@ -336,7 +336,7 @@ class Entity extends GsonValue implements EntityClass { int? limit, List? tags, Team? team, - List? scores, + List? scores, Map? nbt, String? strNbt, EntityType? type, @@ -375,7 +375,7 @@ class Entity extends GsonValue implements EntityClass { int? limit, List? tags, Team? team, - List? scores, + List? scores, Map? nbt, String? strNbt, EntityType? type, @@ -455,7 +455,7 @@ class Entity extends GsonValue implements EntityClass { if (scores != null) { var ret = []; for (var score in scores) { - if (score.getMatch().isEmpty) { + if (score is! MatchesScoreCondition) { throw ('Please insert a match method in the scores value for an entity!'); } ret.add('${score.score}=${score.getMatch()}'); @@ -480,7 +480,7 @@ class Entity extends GsonValue implements EntityClass { int? limit, List? tags, Team? team, - List? scores, + List? scores, Map? nbt, String? strNbt, EntityType? type, @@ -543,7 +543,7 @@ class Entity extends GsonValue implements EntityClass { int? limit, List? tags, Team? team, - List? scores, + List? scores, Map? nbt, String? strNbt, EntityType? type, diff --git a/lib/src/basic/types/selector.dart b/lib/src/basic/types/selector.dart index 0c86191..0b81437 100644 --- a/lib/src/basic/types/selector.dart +++ b/lib/src/basic/types/selector.dart @@ -1,6 +1,6 @@ import 'package:gson/gson.dart'; import 'package:objd/src/basic/parsable.dart'; -import 'package:objd/src/basic/score.dart'; +import 'package:objd/src/basic/score/score_export.dart'; import 'package:objd/src/basic/types/area.dart'; import 'package:objd/src/basic/types/entity.dart'; import 'package:objd/src/basic/types/rotation.dart'; @@ -12,7 +12,7 @@ class Selector { int? limit; List? tags; Team? team; - List? scores; + List? scores; Map? nbt; String? strNbt; EntityType? type; @@ -151,13 +151,12 @@ class Selector { /// Copy a selector Selector.clone(Selector s) { - List? scores; + List? scores; if (s.scores != null) { scores = []; - for (var score in s.scores!) { + for (var cond in s.scores!) { scores.add( - Score(score.entity, score.score, - addNew: false, commands: score.commands), + MatchesScoreCondition(cond.score, cond.range), ); } } diff --git a/lib/src/basic/widgets.dart b/lib/src/basic/widgets.dart index b43d0b5..03f88d2 100644 --- a/lib/src/basic/widgets.dart +++ b/lib/src/basic/widgets.dart @@ -5,7 +5,7 @@ export 'command_builder.dart'; export 'pack.dart'; export 'group.dart'; export 'scoreboard.dart'; -export 'score.dart'; +export 'score/score_export.dart'; export 'tag.dart'; export 'text_components.dart'; export 'file.dart'; diff --git a/lib/src/utils/log.dart b/lib/src/utils/log.dart index b811bbc..4f6726a 100644 --- a/lib/src/utils/log.dart +++ b/lib/src/utils/log.dart @@ -1,6 +1,6 @@ +import 'package:objd/src/basic/score/score.dart'; import 'package:objd/src/basic/types/entity.dart'; import 'package:objd/src/basic/rest_action.dart'; -import 'package:objd/src/basic/score.dart'; import 'package:objd/src/basic/text_components.dart'; import 'package:objd/src/basic/widget.dart'; import 'package:objd/src/build/context.dart'; diff --git a/lib/src/utils/random_score.dart b/lib/src/utils/random_score.dart index 34435cc..e6bc848 100644 --- a/lib/src/utils/random_score.dart +++ b/lib/src/utils/random_score.dart @@ -36,13 +36,14 @@ class RandomScore extends RestActionAble { children: [ Comment('Random UUID Generator from ${context.file}'), AreaEffectCloud(Location.here(), tags: ['objd_random']), - s[entity].setToWidget( - Data.get( - Entity(tags: ['objd_random'], limit: 1).sort(Sort.nearest), - path: context.version > 15 ? 'UUID[0]' : 'UUIDMost', - scale: (context.version > 15 ? 1000 : 1) * 0.0000000001, - ), - ), + // TODO: Add back in + // s[entity].setToWidget( + // Data.get( + // Entity(tags: ['objd_random'], limit: 1).sort(Sort.nearest), + // path: context.version > 15 ? 'UUID[0]' : 'UUIDMost', + // scale: (context.version > 15 ? 1000 : 1) * 0.0000000001, + // ), + // ), s[entity].modulo( s['#max'], ), From 82b1b75c0f039069f17d78ab6d092d07d66fbdaa Mon Sep 17 00:00:00 2001 From: Stevertus Date: Wed, 1 Nov 2023 20:29:30 +0100 Subject: [PATCH 3/8] remove AssignScoreOperation + better ConstScore --- example/score_test.dart | 2 +- lib/src/basic/score/score.dart | 68 +++++++++++++------------- lib/src/basic/score/score_builder.dart | 36 +++++++++----- lib/src/basic/scoreboard.dart | 13 +++-- 4 files changed, 69 insertions(+), 50 deletions(-) diff --git a/example/score_test.dart b/example/score_test.dart index c08b2ad..7a15aa6 100644 --- a/example/score_test.dart +++ b/example/score_test.dart @@ -8,5 +8,5 @@ void main(List args) { print(t); final (_, ops) = t.copy(); - print(ops.join('\n\n')); + print(getCommands(For.of(ops)).join('\n')); } diff --git a/lib/src/basic/score/score.dart b/lib/src/basic/score/score.dart index 8e77be4..f475610 100644 --- a/lib/src/basic/score/score.dart +++ b/lib/src/basic/score/score.dart @@ -12,17 +12,20 @@ import 'package:objd/src/basic/types/entity.dart'; import 'package:objd/src/basic/widget.dart'; import 'package:objd/src/build/context.dart'; -abstract interface class ScoreAssignable { +abstract interface class ScoreStoreable { // block, bossbar, entity, score, storage String get_assignable_right(); } -abstract interface class ScoreStoreable extends ScoreAssignable { +abstract interface class ScoreAssignable extends ScoreStoreable { // block, bossbar, entity, score, storage String get_assignable_left(); + + Widget operator >>(dynamic other); + Widget operator <<(dynamic other); } -sealed class ScoreOperation extends Widget implements ScoreAssignable { +sealed class ScoreOperation extends Widget implements ScoreStoreable { /// add BinaryScoreOperation operator +(dynamic other) { if (other is int) return add(other); @@ -301,8 +304,8 @@ final class ResetScoreOperation extends ElementaryScoreOperation { } final class StoreScoreOperation extends ElementaryScoreOperation { - final ScoreStoreable left; - final ScoreAssignable right; + final ScoreAssignable left; + final ScoreStoreable right; StoreScoreOperation(this.left, this.right); @@ -330,6 +333,9 @@ final class ElementaryBinaryScoreOperation extends ElementaryScoreOperation { required this.operation, }); + ElementaryBinaryScoreOperation.assign(this.left, this.right) + : operation = ScoreOperator.Assign; + @override Widget generate(Context context) => Command('scoreboard players operation $left ${operation.op} $right'); @@ -338,24 +344,24 @@ final class ElementaryBinaryScoreOperation extends ElementaryScoreOperation { String toString() => '$left ${operation.op} $right'; } -final class AssignScoreOperation extends ElementaryScoreOperation { - final Score left; - final ScoreAssignable right; +// final class AssignScoreOperation extends ElementaryScoreOperation { +// final Score left; +// final ScoreAssignable right; - AssignScoreOperation(this.left, this.right); +// AssignScoreOperation(this.left, this.right); - @override - Widget generate(Context context) => Command( - 'scoreboard players operation $left = ${right.get_assignable_right()}', - ); +// @override +// Widget generate(Context context) => Command( +// 'scoreboard players operation $left = ${right.get_assignable_right()}', +// ); - @override - String toString() => [ - ' | $left', - '<<', - ' | ${right.get_assignable_right()}', - ].join('\n'); -} +// @override +// String toString() => [ +// ' | $left', +// '<<', +// ' | ${right.get_assignable_right()}', +// ].join('\n'); +// } class BinaryScoreOperation extends ScoreOperation { final ScoreOperation left; @@ -365,6 +371,9 @@ class BinaryScoreOperation extends ScoreOperation { BinaryScoreOperation(this.left, this.operation, this.right); + BinaryScoreOperation.assign(this.left, this.right) + : this.operation = ScoreOperator.Assign; + @override generate(Context context) { // TODO: implement generate @@ -413,7 +422,7 @@ class ConstScore extends Score { ); } -class Score extends ElementaryScoreOperation implements ScoreStoreable { +class Score extends ElementaryScoreOperation implements ScoreAssignable { final Entity entity; String score; final String type; @@ -499,18 +508,14 @@ class Score extends ElementaryScoreOperation implements ScoreStoreable { ScoreBuilder? builder, bool compact = false, }) { - print("Score!"); if (compact && out == null) return (this, []); - if (out != null) return (out, [AssignScoreOperation(out, this)]); + if (out != null) + return (out, [ElementaryBinaryScoreOperation.assign(out, this)]); return super.copy(out: out, builder: builder, compact: false); } /// assign value(int, Score, Data or Condition) ScoreOperation setTo(dynamic other) { - if (this is! ScoreStoreable) { - throw Exception('$other can not be assigned to left Hand Side $this'); - } - if (other is int) return set(other); if (other is Score) return setEqual(other); @@ -527,7 +532,7 @@ class Score extends ElementaryScoreOperation implements ScoreStoreable { /// sets the score to a given value of int BinaryScoreOperation set(int val) { - if (this is! ScoreStoreable) { + if (this is! ScoreAssignable) { throw Exception('$val can not be assigned to left Hand Side $this'); } @@ -590,14 +595,11 @@ class Score extends ElementaryScoreOperation implements ScoreStoreable { @override Widget generate(Context context) { - return addNew ? Scoreboard.add(score, type: type) : Comment.Null(); + return addNew ? Scoreboard(score, type: type) : Comment.Null(); } @override - String get_assignable_left() { - // TODO: implement get_assignable_left - throw UnimplementedError(); - } + String get_assignable_left() => 'score $this'; @override String get_assignable_right() => 'scoreboard players get $this'; diff --git a/lib/src/basic/score/score_builder.dart b/lib/src/basic/score/score_builder.dart index c4e8064..0d8ff4b 100644 --- a/lib/src/basic/score/score_builder.dart +++ b/lib/src/basic/score/score_builder.dart @@ -11,15 +11,15 @@ class ScoreBuilder { compileBinary(left, operation, right, out: out), IncrementScoreOperation(score: final score) => [ input, - if (out != null) AssignScoreOperation(out, score), + if (out != null) ElementaryBinaryScoreOperation.assign(out, score), ], SetScoreOperation(score: final score) => [ input, - if (out != null) AssignScoreOperation(out, score), + if (out != null) ElementaryBinaryScoreOperation.assign(out, score), ], ResetScoreOperation(score: final score) => [ input, - if (out != null) AssignScoreOperation(out, score), + if (out != null) ElementaryBinaryScoreOperation.assign(out, score), ], StoreScoreOperation(left: final left) => [ input, @@ -27,15 +27,11 @@ class ScoreBuilder { ], ElementaryBinaryScoreOperation(left: final left) => [ input, - if (out != null) AssignScoreOperation(out, left) - ], - AssignScoreOperation(left: final left) => [ - input, - if (out != null) AssignScoreOperation(out, left), + if (out != null) ElementaryBinaryScoreOperation.assign(out, left) ], Score score => [ score, - if (out != null) AssignScoreOperation(out, score), + if (out != null) ElementaryBinaryScoreOperation.assign(out, score), ], }; } @@ -44,7 +40,7 @@ class ScoreBuilder { ScoreOperation left, ScoreOperator operator, ScoreOperation right, {Score? out}) { if (operator == ScoreOperator.Assign) { - assert(left is ScoreStoreable, "Tried to assign $right to $left"); + assert(left is ScoreAssignable, "Tried to assign $right to $left"); final (tmpRight, prevactions) = right.copy(compact: true); if (left is Score) { @@ -52,11 +48,14 @@ class ScoreBuilder { return [SetScoreOperation(left, right.value)]; } - return [...prevactions, AssignScoreOperation(left, tmpRight)]; + return [ + ...prevactions, + ElementaryBinaryScoreOperation.assign(left, tmpRight) + ]; } return [ ...prevactions, - StoreScoreOperation(left as ScoreStoreable, tmpRight) + StoreScoreOperation(left as ScoreAssignable, tmpRight) ]; } @@ -69,6 +68,19 @@ class ScoreBuilder { } } + if (right is ConstScore) { + switch (operator) { + case ScoreOperator.Assign: + return [...leftActions, SetScoreOperation(out, right.value)]; + + case ScoreOperator.Addition: + return [...leftActions, IncrementScoreOperation(out, right.value)]; + case ScoreOperator.Subtraction: + return [...leftActions, IncrementScoreOperation(out, -right.value)]; + default: + } + } + final (tmpRight, rightActions) = right.copy(compact: true); // other operators diff --git a/lib/src/basic/scoreboard.dart b/lib/src/basic/scoreboard.dart index 537ce6c..5f29040 100644 --- a/lib/src/basic/scoreboard.dart +++ b/lib/src/basic/scoreboard.dart @@ -10,6 +10,9 @@ import 'package:objd/src/basic/extend.dart'; import 'package:objd/src/build/build.dart'; import 'package:objd/src/wrappers/comment.dart'; +const _SCORE_PLAYERNAME_ALPHABET = + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'; + class Scoreboard extends RestActionAble { /// Often you find yourself giving all scoreboards a prefix especially for your project. This can get very repetitive and annoying, so objD has this prefix built in. @@ -17,14 +20,16 @@ class Scoreboard extends RestActionAble { static final Set _tempScores = {}; - static String generateNewTempPlayerName({int len = 10}) { + static String generateNewTempPlayerName({int len = 8}) { var r = Random(); String name = ''; do { - name = String.fromCharCodes( - List.generate(len, (index) => r.nextInt(33) + 89), - ); + name = List.generate( + len, + (index) => _SCORE_PLAYERNAME_ALPHABET[ + r.nextInt(_SCORE_PLAYERNAME_ALPHABET.length)], + ).join(); } while (_tempScores.contains(name)); _tempScores.add(name); From 020ff8138d90c18cd0da1f6f6ee32aface37cebe Mon Sep 17 00:00:00 2001 From: Stevertus Date: Wed, 1 Nov 2023 22:02:38 +0100 Subject: [PATCH 4/8] ScoreStoreable Operators --- example/score_test.dart | 5 +- lib/src/basic/score/score.dart | 239 +++++++++++++++---------- lib/src/basic/score/score_builder.dart | 2 +- lib/src/basic/scoreboard.dart | 5 +- lib/src/wrappers/bossbar.dart | 40 ++++- 5 files changed, 191 insertions(+), 100 deletions(-) diff --git a/example/score_test.dart b/example/score_test.dart index 7a15aa6..46d855b 100644 --- a/example/score_test.dart +++ b/example/score_test.dart @@ -3,7 +3,10 @@ import 'package:objd/core.dart'; void main(List args) { var s1 = Score(Entity.All(), "s1"); var s2 = Score.Self('s2'); - var t = (s1 + s2) + s1 / (s2 + 2); + var t = (s1 + s2) + + s1 / (s2 + 2) + + (Bossbar("test") << s1) + + Bossbar("test").get(BossbarOption.value); print(t); diff --git a/lib/src/basic/score/score.dart b/lib/src/basic/score/score.dart index f475610..52cde84 100644 --- a/lib/src/basic/score/score.dart +++ b/lib/src/basic/score/score.dart @@ -12,118 +12,123 @@ import 'package:objd/src/basic/types/entity.dart'; import 'package:objd/src/basic/widget.dart'; import 'package:objd/src/build/context.dart'; -abstract interface class ScoreStoreable { +abstract mixin class ScoreStoreable { // block, bossbar, entity, score, storage String get_assignable_right(); + + ScoreOperation asScore() => StoreScoreOperation(Score.tmp(), this); + + BinaryScoreOperation operator +(dynamic other) => asScore() + other; + BinaryScoreOperation operator -(dynamic other) => asScore() - other; + BinaryScoreOperation operator %(dynamic other) => asScore() % other; + BinaryScoreOperation operator /(dynamic other) => asScore() / other; + BinaryScoreOperation operator *(dynamic other) => asScore() * other; + ScoreCondition operator >(dynamic other) => asScore() > other; + ScoreCondition operator >=(dynamic other) => asScore() >= other; + ScoreCondition operator <=(dynamic other) => asScore() <= other; + ScoreCondition operator <(dynamic other) => asScore() < other; + ScoreCondition operator &(dynamic other) => asScore() & other; } -abstract interface class ScoreAssignable extends ScoreStoreable { +abstract mixin class ScoreAssignable { // block, bossbar, entity, score, storage String get_assignable_left(); - Widget operator >>(dynamic other); - Widget operator <<(dynamic other); + ScoreStoreable toStorable(); + + Widget setTo(dynamic other); + Widget operator >>(dynamic other) => setTo(other); + Widget operator <<(dynamic other) => setTo(other); } sealed class ScoreOperation extends Widget implements ScoreStoreable { /// add - BinaryScoreOperation operator +(dynamic other) { - if (other is int) return add(other); - if (other is ScoreOperation) return addScore(other); - throw ('Please use either a Score or an Int in the operator +'); - } + BinaryScoreOperation operator +(dynamic other) => switch (other) { + int val => add(val), + ScoreOperation s => addScore(s), + ScoreStoreable s => addScore(s.asScore()), + _ => throw ('Please use either a Score or an Int in the operator +') + }; /// subtract - BinaryScoreOperation operator -(dynamic other) { - if (other is int) return subtract(other); - if (other is ScoreOperation) return subtractScore(other); - throw ('Please use either a Score or an Int in the operator -'); - } + BinaryScoreOperation operator -(dynamic other) => switch (other) { + int val => subtract(val), + ScoreOperation s => subtractScore(s), + ScoreStoreable s => subtractScore(s.asScore()), + _ => throw ('Please use either a Score or an Int in the operator -') + }; /// modulo by - BinaryScoreOperation operator %(dynamic other) { - if (other is int) { - return modulo( - Score.con(other), - ); - } - if (other is ScoreOperation) return modulo(other); - throw ('Please use either a Score or an Int in the operator %'); - } + BinaryScoreOperation operator %(dynamic other) => switch (other) { + int val => modulo(Score.con(val)), + ScoreOperation s => modulo(s), + ScoreStoreable s => modulo(s.asScore()), + _ => throw ('Please use either a Score or an Int in the operator %') + }; /// divide by - BinaryScoreOperation operator /(dynamic other) { - if (other is int) { - return divideByScore( - Score.con(other), - ); - } - if (other is ScoreOperation) return divideByScore(other); - throw ('Please use either a Score or an Int in the operator /'); - } + BinaryScoreOperation operator /(dynamic other) => switch (other) { + int val => divideByScore(Score.con(val)), + ScoreOperation s => divideByScore(s), + ScoreStoreable s => divideByScore(s.asScore()), + _ => throw ('Please use either a Score or an Int in the operator /') + }; /// multiply by - BinaryScoreOperation operator *(dynamic other) { - if (other is int) { - return multiplyByScore( - Score.con(other), - ); - } - if (other is ScoreOperation) return multiplyByScore(other); - throw ('Please use either a Score or an Int in the operator /'); - } + BinaryScoreOperation operator *(dynamic other) => switch (other) { + int val => multiplyByScore(Score.con(val)), + ScoreOperation s => multiplyByScore(s), + ScoreStoreable s => multiplyByScore(s.asScore()), + _ => throw ('Please use either a Score or an Int in the operator *') + }; /// greater than - ScoreCondition operator >(dynamic other) { - if (other is int) { - return matchesRange( - Range.from(other + 1), - ); - } - if (other is ScoreOperation) return isBigger(other); - throw ('Please use either a Score or an Int in the operator >'); - } + ScoreCondition operator >(dynamic other) => switch (other) { + int val => matchesRange(Range.from(val + 1)), + ScoreOperation s => isBigger(s), + ScoreStoreable s => isBigger(s.asScore()), + _ => throw ('Please use either a Score or an Int in the operator >') + }; /// less than - ScoreCondition operator <(dynamic other) { - if (other is int) { - return matchesRange( - Range.to(other + -1), - ); - } - if (other is ScoreOperation) return isSmaller(other); - throw ('Please use either a Score or an Int in the operator >'); - } + ScoreCondition operator <(dynamic other) => switch (other) { + int val => matchesRange(Range.to(val - 1)), + ScoreOperation s => isSmaller(s), + ScoreStoreable s => isSmaller(s.asScore()), + _ => throw ('Please use either a Score or an Int in the operator <') + }; /// bigger or equal - ScoreCondition operator >=(dynamic other) { - if (other is int) { - return matchesRange( - Range.from(other), - ); - } - if (other is ScoreOperation) return isBiggerOrEqual(other); - throw ('Please use either a Score or an Int in the operator >='); - } + ScoreCondition operator >=(dynamic other) => switch (other) { + int val => matchesRange(Range.from(val)), + ScoreOperation s => isBiggerOrEqual(s), + ScoreStoreable s => isBiggerOrEqual( + s.asScore(), + ), + _ => throw ('Please use either a Score or an Int in the operator >=') + }; /// less or equal - ScoreCondition operator <=(dynamic other) { - if (other is int) { - return matchesRange( - Range.to(other), - ); - } - if (other is ScoreOperation) return isSmallerOrEqual(other); - throw ('Please use either a Score or an Int in the operator <='); - } + ScoreCondition operator <=(dynamic other) => switch (other) { + int val => matchesRange(Range.to(val)), + ScoreOperation s => isSmallerOrEqual(s), + ScoreStoreable s => isSmallerOrEqual( + s.asScore(), + ), + _ => throw ('Please use either a Score or an Int in the operator <=') + }; /// matches - ScoreCondition operator &(dynamic other) { - if (other is int) return matches(other); - if (other is Range) return matchesRange(other); - if (other is ScoreOperation) return isEqual(other); - throw ('Please use either a Score, Range or an Int in the operator &'); - } + ScoreCondition operator &(dynamic other) => switch (other) { + int val => matches(val), + Range r => matchesRange(r), + ScoreOperation s => isEqual(s), + ScoreStoreable s => isEqual( + s.asScore(), + ), + _ => + throw ('Please use either a Score, Range or an Int in the operator &') + }; /// adds a value to the score BinaryScoreOperation add([int val = 1]) => BinaryScoreOperation( @@ -243,20 +248,20 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { ScoreBuilder? builder, bool compact = false, }) { - out ??= Score( - Entity.PlayerName('#${Scoreboard.generateNewTempPlayerName()}'), - 'objd_temp', - ); + out ??= Score.tmp(); builder ??= ScoreBuilder(); - return (out, builder.compile(this, out: out)); + return (out, [out, ...builder.compile(this, out: out)]); } @override String get_assignable_right() { throw UnimplementedError(); } + + @override + ScoreOperation asScore() => this; } sealed class ElementaryScoreOperation extends ScoreOperation {} @@ -306,19 +311,32 @@ final class ResetScoreOperation extends ElementaryScoreOperation { final class StoreScoreOperation extends ElementaryScoreOperation { final ScoreAssignable left; final ScoreStoreable right; + final bool storeResult; - StoreScoreOperation(this.left, this.right); + StoreScoreOperation(this.left, this.right, {this.storeResult = true}); @override - generate(Context context) => Command('execute store result ' // TODO: + generate(Context context) => Command( + 'execute store ${storeResult ? "result" : "success"} ${left.get_assignable_left()} run ${right.get_assignable_right()}' // TODO: right operation? ); @override String toString() => [ - ' | ${left.get_assignable_left()}', + ' | store ${left.get_assignable_left()}', '<<', ' | ${right.get_assignable_right()}', ].join('\n'); + + @override + (Score, List) copy({ + Score? out, + ScoreBuilder? builder, + bool compact = false, + }) => + switch ((left, compact)) { + (Score s, true) => s.copy(out: out, builder: builder, compact: compact), + _ => super.copy(out: out, builder: builder, compact: compact) + }; } final class ElementaryBinaryScoreOperation extends ElementaryScoreOperation { @@ -422,7 +440,8 @@ class ConstScore extends Score { ); } -class Score extends ElementaryScoreOperation implements ScoreAssignable { +class Score extends ElementaryScoreOperation + with ScoreAssignable, ScoreStoreable { final Entity entity; String score; final String type; @@ -497,6 +516,32 @@ class Score extends ElementaryScoreOperation implements ScoreAssignable { }) => ConstScore(number, addNew: addNew, type: type); + factory Score.PlayerName( + String name, + String score, { + bool addNew = true, + String type = 'dummy', + }) => + Score( + Entity.PlayerName(name), + score, + addNew: addNew, + type: type, + ); + + factory Score.tmp({ + int len = 8, + String score = "objd_temp", + String alphabet = + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_', + }) => + Score( + Entity.PlayerName( + '#${Scoreboard.generateNewTempPlayerName(len: len, alphabet: alphabet)}', + ), + score, + ); + String toString({Entity? entity, String? score}) { entity ??= this.entity; score ??= this.score; @@ -509,9 +554,10 @@ class Score extends ElementaryScoreOperation implements ScoreAssignable { bool compact = false, }) { if (compact && out == null) return (this, []); - if (out != null) - return (out, [ElementaryBinaryScoreOperation.assign(out, this)]); - return super.copy(out: out, builder: builder, compact: false); + if (out != null) { + return (out, [out, ElementaryBinaryScoreOperation.assign(out, this)]); + } + return super.copy(out: out, builder: builder, compact: compact); } /// assign value(int, Score, Data or Condition) @@ -603,4 +649,7 @@ class Score extends ElementaryScoreOperation implements ScoreAssignable { @override String get_assignable_right() => 'scoreboard players get $this'; + + @override + ScoreStoreable toStorable() => this; } diff --git a/lib/src/basic/score/score_builder.dart b/lib/src/basic/score/score_builder.dart index 0d8ff4b..8b71934 100644 --- a/lib/src/basic/score/score_builder.dart +++ b/lib/src/basic/score/score_builder.dart @@ -23,7 +23,7 @@ class ScoreBuilder { ], StoreScoreOperation(left: final left) => [ input, - if (out != null) StoreScoreOperation(out, left) + if (out != null) StoreScoreOperation(out, left.toStorable()) ], ElementaryBinaryScoreOperation(left: final left) => [ input, diff --git a/lib/src/basic/scoreboard.dart b/lib/src/basic/scoreboard.dart index 5f29040..bb50e1f 100644 --- a/lib/src/basic/scoreboard.dart +++ b/lib/src/basic/scoreboard.dart @@ -20,7 +20,10 @@ class Scoreboard extends RestActionAble { static final Set _tempScores = {}; - static String generateNewTempPlayerName({int len = 8}) { + static String generateNewTempPlayerName({ + int len = 8, + String alphabet = _SCORE_PLAYERNAME_ALPHABET, + }) { var r = Random(); String name = ''; diff --git a/lib/src/wrappers/bossbar.dart b/lib/src/wrappers/bossbar.dart index 01188eb..697e9b0 100644 --- a/lib/src/wrappers/bossbar.dart +++ b/lib/src/wrappers/bossbar.dart @@ -4,7 +4,7 @@ import 'package:objd/src/basic/widgets.dart'; import 'package:objd/src/build/context.dart'; import 'package:objd/src/wrappers/execute.dart'; -class Bossbar extends RestActionAble { +class Bossbar extends RestActionAble with ScoreAssignable, ScoreStoreable { final BossbarType type; final String id; @@ -16,6 +16,14 @@ class Bossbar extends RestActionAble { Bossbar(this.id, {this.name, this.type = BossbarType.add}) { name ??= id; } + Bossbar._( + this.id, { + this.name, + this.type = BossbarType.add, + this.nameTexts, + this.option, + this.modifiers = const {}, + }); Bossbar remove() => copyWith(type: BossbarType.remove); @@ -110,14 +118,42 @@ class Bossbar extends RestActionAble { Bossbar copyWith({ BossbarType? type, + BossbarOption? option, String? id, }) { - return Bossbar( + return Bossbar._( id ?? this.id, name: name, type: type ?? this.type, + option: option, ); } + + Widget setTo(dynamic other, {BossbarOption option = BossbarOption.value}) { + print(other); + if (other is int) return set(value: other); + if (other is ScoreStoreable) { + return StoreScoreOperation(this.copyWith(option: option), other); + } + + throw UnimplementedError("setTo is not implemented for $other"); + } + + @override + String get_assignable_left() => + 'bossbar $id ${(option ?? BossbarOption.value).name}'; + + @override + String get_assignable_right() { + assert( + type == BossbarType.get, + "You can only assign Bossbar.get to something else", + ); + return 'bossbar get $id ${option!.name}'; + } + + @override + ScoreStoreable toStorable() => get(BossbarOption.value); } enum BossbarOption { max, players, value, visible } From a51671c3c75158de042eae4c3a7b226b698996e6 Mon Sep 17 00:00:00 2001 From: Stevertus Date: Wed, 1 Nov 2023 22:48:12 +0100 Subject: [PATCH 5/8] fix Score operators + BinaryScore generate --- example/score_test.dart | 6 +- lib/src/basic/score/score.dart | 107 +++++++++++++++++-------- lib/src/basic/score/score_builder.dart | 6 +- test/score_test.dart | 5 -- 4 files changed, 79 insertions(+), 45 deletions(-) diff --git a/example/score_test.dart b/example/score_test.dart index 46d855b..a8dc61f 100644 --- a/example/score_test.dart +++ b/example/score_test.dart @@ -8,8 +8,10 @@ void main(List args) { (Bossbar("test") << s1) + Bossbar("test").get(BossbarOption.value); - print(t); + //print(t); + print(s1 + (s2 + s1)); final (_, ops) = t.copy(); - print(getCommands(For.of(ops)).join('\n')); + //print(getCommands(For.of(ops)).join('\n')); + print(getCommands(s1 + s2 + s1).join('\n')); //TODO: Caveat s1 + s2 != s2 + s1 } diff --git a/lib/src/basic/score/score.dart b/lib/src/basic/score/score.dart index 52cde84..3f1f259 100644 --- a/lib/src/basic/score/score.dart +++ b/lib/src/basic/score/score.dart @@ -16,18 +16,21 @@ abstract mixin class ScoreStoreable { // block, bossbar, entity, score, storage String get_assignable_right(); - ScoreOperation asScore() => StoreScoreOperation(Score.tmp(), this); - - BinaryScoreOperation operator +(dynamic other) => asScore() + other; - BinaryScoreOperation operator -(dynamic other) => asScore() - other; - BinaryScoreOperation operator %(dynamic other) => asScore() % other; - BinaryScoreOperation operator /(dynamic other) => asScore() / other; - BinaryScoreOperation operator *(dynamic other) => asScore() * other; - ScoreCondition operator >(dynamic other) => asScore() > other; - ScoreCondition operator >=(dynamic other) => asScore() >= other; - ScoreCondition operator <=(dynamic other) => asScore() <= other; - ScoreCondition operator <(dynamic other) => asScore() < other; - ScoreCondition operator &(dynamic other) => asScore() & other; + ScoreOperation toScore({Score? out}) => StoreScoreOperation( + out ?? Score.tmp(), + this, + ); + + BinaryScoreOperation operator +(dynamic other) => toScore() + other; + BinaryScoreOperation operator -(dynamic other) => toScore() - other; + BinaryScoreOperation operator %(dynamic other) => toScore() % other; + BinaryScoreOperation operator /(dynamic other) => toScore() / other; + BinaryScoreOperation operator *(dynamic other) => toScore() * other; + ScoreCondition operator >(dynamic other) => toScore() > other; + ScoreCondition operator >=(dynamic other) => toScore() >= other; + ScoreCondition operator <=(dynamic other) => toScore() <= other; + ScoreCondition operator <(dynamic other) => toScore() < other; + ScoreCondition operator &(dynamic other) => toScore() & other; } abstract mixin class ScoreAssignable { @@ -43,10 +46,11 @@ abstract mixin class ScoreAssignable { sealed class ScoreOperation extends Widget implements ScoreStoreable { /// add + @override BinaryScoreOperation operator +(dynamic other) => switch (other) { int val => add(val), ScoreOperation s => addScore(s), - ScoreStoreable s => addScore(s.asScore()), + ScoreStoreable s => addScore(s.toScore()), _ => throw ('Please use either a Score or an Int in the operator +') }; @@ -54,7 +58,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { BinaryScoreOperation operator -(dynamic other) => switch (other) { int val => subtract(val), ScoreOperation s => subtractScore(s), - ScoreStoreable s => subtractScore(s.asScore()), + ScoreStoreable s => subtractScore(s.toScore()), _ => throw ('Please use either a Score or an Int in the operator -') }; @@ -62,7 +66,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { BinaryScoreOperation operator %(dynamic other) => switch (other) { int val => modulo(Score.con(val)), ScoreOperation s => modulo(s), - ScoreStoreable s => modulo(s.asScore()), + ScoreStoreable s => modulo(s.toScore()), _ => throw ('Please use either a Score or an Int in the operator %') }; @@ -70,7 +74,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { BinaryScoreOperation operator /(dynamic other) => switch (other) { int val => divideByScore(Score.con(val)), ScoreOperation s => divideByScore(s), - ScoreStoreable s => divideByScore(s.asScore()), + ScoreStoreable s => divideByScore(s.toScore()), _ => throw ('Please use either a Score or an Int in the operator /') }; @@ -78,7 +82,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { BinaryScoreOperation operator *(dynamic other) => switch (other) { int val => multiplyByScore(Score.con(val)), ScoreOperation s => multiplyByScore(s), - ScoreStoreable s => multiplyByScore(s.asScore()), + ScoreStoreable s => multiplyByScore(s.toScore()), _ => throw ('Please use either a Score or an Int in the operator *') }; @@ -86,7 +90,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { ScoreCondition operator >(dynamic other) => switch (other) { int val => matchesRange(Range.from(val + 1)), ScoreOperation s => isBigger(s), - ScoreStoreable s => isBigger(s.asScore()), + ScoreStoreable s => isBigger(s.toScore()), _ => throw ('Please use either a Score or an Int in the operator >') }; @@ -94,7 +98,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { ScoreCondition operator <(dynamic other) => switch (other) { int val => matchesRange(Range.to(val - 1)), ScoreOperation s => isSmaller(s), - ScoreStoreable s => isSmaller(s.asScore()), + ScoreStoreable s => isSmaller(s.toScore()), _ => throw ('Please use either a Score or an Int in the operator <') }; @@ -103,7 +107,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { int val => matchesRange(Range.from(val)), ScoreOperation s => isBiggerOrEqual(s), ScoreStoreable s => isBiggerOrEqual( - s.asScore(), + s.toScore(), ), _ => throw ('Please use either a Score or an Int in the operator >=') }; @@ -113,7 +117,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { int val => matchesRange(Range.to(val)), ScoreOperation s => isSmallerOrEqual(s), ScoreStoreable s => isSmallerOrEqual( - s.asScore(), + s.toScore(), ), _ => throw ('Please use either a Score or an Int in the operator <=') }; @@ -124,7 +128,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { Range r => matchesRange(r), ScoreOperation s => isEqual(s), ScoreStoreable s => isEqual( - s.asScore(), + s.toScore(), ), _ => throw ('Please use either a Score, Range or an Int in the operator &') @@ -261,7 +265,8 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { } @override - ScoreOperation asScore() => this; + ScoreOperation toScore({Score? out}) => + out == null ? this : BinaryScoreOperation.assign(out, this); } sealed class ElementaryScoreOperation extends ScoreOperation {} @@ -302,7 +307,10 @@ final class ResetScoreOperation extends ElementaryScoreOperation { ResetScoreOperation(this.score); @override - generate(Context context) => Command('scoreboard players reset $score'); + generate(Context context) => For.of([ + score, + Command('scoreboard players reset $score'), + ]); @override String toString() => 'reset $score'; @@ -345,11 +353,11 @@ final class ElementaryBinaryScoreOperation extends ElementaryScoreOperation { final ScoreOperator operation; - ElementaryBinaryScoreOperation({ - required this.left, - required this.right, - required this.operation, - }); + ElementaryBinaryScoreOperation( + this.left, + this.operation, + this.right, + ); ElementaryBinaryScoreOperation.assign(this.left, this.right) : operation = ScoreOperator.Assign; @@ -390,12 +398,41 @@ class BinaryScoreOperation extends ScoreOperation { BinaryScoreOperation(this.left, this.operation, this.right); BinaryScoreOperation.assign(this.left, this.right) - : this.operation = ScoreOperator.Assign; + : operation = ScoreOperator.Assign; @override - generate(Context context) { - // TODO: implement generate - throw UnimplementedError(); + Widget generate(Context context) { + final ScoreBuilder builder = ScoreBuilder(); + + final (rScore, rActions) = right.copy(compact: true, builder: builder); + + print(left); + + if (left is Score) { + return For.of([ + left, + ...rActions, + ...builder.compileBinary(left, operation, rScore), + ]); + } + + if (left case StoreScoreOperation(right: ScoreAssignable store)) { + final (lScore, lActions) = left.copy(compact: true, builder: builder); + return For.of([ + ...lActions, + ...rActions, + ...builder.compileBinary(lScore, operation, rScore), + store << lScore + ]); + } + + final (lScore, lActions) = left.copy(builder: builder); + + return For.of([ + ...lActions, + ...rActions, + ...builder.compileBinary(lScore, operation, rScore), + ]); } @override @@ -441,7 +478,7 @@ class ConstScore extends Score { } class Score extends ElementaryScoreOperation - with ScoreAssignable, ScoreStoreable { + implements ScoreAssignable, ScoreStoreable { final Entity entity; String score; final String type; @@ -563,7 +600,7 @@ class Score extends ElementaryScoreOperation /// assign value(int, Score, Data or Condition) ScoreOperation setTo(dynamic other) { if (other is int) return set(other); - if (other is Score) return setEqual(other); + if (other is ScoreOperation) return setEqual(other); ///if (other is Data) return setToData(other); // if (other is Condition) return setToCondition(other); diff --git a/lib/src/basic/score/score_builder.dart b/lib/src/basic/score/score_builder.dart index 8b71934..87e710c 100644 --- a/lib/src/basic/score/score_builder.dart +++ b/lib/src/basic/score/score_builder.dart @@ -88,9 +88,9 @@ class ScoreBuilder { ...leftActions, ...rightActions, ElementaryBinaryScoreOperation( - left: out, - right: tmpRight, - operation: operator, + out, + operator, + tmpRight, ) ]; } diff --git a/test/score_test.dart b/test/score_test.dart index bdaebec..20fd1f8 100644 --- a/test/score_test.dart +++ b/test/score_test.dart @@ -37,11 +37,6 @@ void main() { }); group('Score Conditions', () { - commands( - "empty", - Score(Entity.All(), "test").isBigger(Score(Entity.Self(), "new")), - [], - ); command( "simple if", If( From e57e0c1311aae6de17742eb26ff03337e9ff0d3b Mon Sep 17 00:00:00 2001 From: Stevertus Date: Mon, 27 Nov 2023 22:52:54 +0100 Subject: [PATCH 6/8] Data Storage improvements --- .github/workflows/dart.yml | 9 +- example/files/load.dart | 3 +- example/score_test.dart | 12 +- .../data/minecraft/tags/functions/load.json | 1 + .../data/minecraft/tags/functions/tick.json | 1 + .../data/mypack/functions/load.mcfunction | 3 + .../data/mypack/functions/main.mcfunction | 0 folder name/pack.mcmeta | 1 + lib/src/basic/pack.dart | 5 +- lib/src/basic/parsable.dart | 2 +- lib/src/basic/score/score.dart | 165 +++++++++--------- lib/src/basic/scoreboard.dart | 30 ++-- lib/src/utils/storage.dart | 49 +++++- lib/src/wrappers/bossbar.dart | 17 +- lib/src/wrappers/data.dart | 41 +++-- lib/src/wrappers/execute.dart | 2 +- pubspec.yaml | 3 +- test/data_test.dart | 5 + test/score_test.dart | 24 +++ 19 files changed, 237 insertions(+), 136 deletions(-) create mode 100644 folder name/data/minecraft/tags/functions/load.json create mode 100644 folder name/data/minecraft/tags/functions/tick.json create mode 100644 folder name/data/mypack/functions/load.mcfunction create mode 100644 folder name/data/mypack/functions/main.mcfunction create mode 100644 folder name/pack.mcmeta diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 6c9c45f..8a9474d 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -23,4 +23,11 @@ jobs: - name: Install dependencies run: dart pub get - name: Run tests - run: dart run test + run: pub run test --coverage="coverage" + - name: Convert coverage to ICOV + run: pub run coverage:format_coverage --lcov --in=coverage --out=coverage.lcov --packages=.packages --report-on=lib + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v1.0.2 + with: + token: ${{secrets.CODECOV_TOKEN}} + file: coverage.lcov \ No newline at end of file diff --git a/example/files/load.dart b/example/files/load.dart index 46c2085..951dcec 100644 --- a/example/files/load.dart +++ b/example/files/load.dart @@ -10,7 +10,8 @@ class LoadFile extends Widget { Data.merge(Entity.All(), nbt: { "uuid": UUID(1, 2, 3, 4), 'name': TextComponent('name'), - }) + }), + Bossbar("test").get(BossbarOption.value) + 1 ]); } } diff --git a/example/score_test.dart b/example/score_test.dart index a8dc61f..4ad603e 100644 --- a/example/score_test.dart +++ b/example/score_test.dart @@ -3,15 +3,13 @@ import 'package:objd/core.dart'; void main(List args) { var s1 = Score(Entity.All(), "s1"); var s2 = Score.Self('s2'); - var t = (s1 + s2) + - s1 / (s2 + 2) + - (Bossbar("test") << s1) + - Bossbar("test").get(BossbarOption.value); + var t = Bossbar("test").get(BossbarOption.value) + 1; - //print(t); - print(s1 + (s2 + s1)); + print(t); + // print(s1 + (s2 + s1)); final (_, ops) = t.copy(); + print(ops); //print(getCommands(For.of(ops)).join('\n')); - print(getCommands(s1 + s2 + s1).join('\n')); //TODO: Caveat s1 + s2 != s2 + s1 + print(getCommands(t).join('\n')); //TODO: Caveat s1 + s2 != s2 + s1 } diff --git a/folder name/data/minecraft/tags/functions/load.json b/folder name/data/minecraft/tags/functions/load.json new file mode 100644 index 0000000..83044f1 --- /dev/null +++ b/folder name/data/minecraft/tags/functions/load.json @@ -0,0 +1 @@ +{"values":["mypack:load"]} \ No newline at end of file diff --git a/folder name/data/minecraft/tags/functions/tick.json b/folder name/data/minecraft/tags/functions/tick.json new file mode 100644 index 0000000..05aec44 --- /dev/null +++ b/folder name/data/minecraft/tags/functions/tick.json @@ -0,0 +1 @@ +{"values":["mypack:main"]} \ No newline at end of file diff --git a/folder name/data/mypack/functions/load.mcfunction b/folder name/data/mypack/functions/load.mcfunction new file mode 100644 index 0000000..b0cd501 --- /dev/null +++ b/folder name/data/mypack/functions/load.mcfunction @@ -0,0 +1,3 @@ +scoreboard objectives add objd_temp dummy +data merge entity @a {uuid:[I;1,2,3,4],name:{"text":"name"}} +scoreboard players add #at6AbnE8 objd_temp 1 diff --git a/folder name/data/mypack/functions/main.mcfunction b/folder name/data/mypack/functions/main.mcfunction new file mode 100644 index 0000000..e69de29 diff --git a/folder name/pack.mcmeta b/folder name/pack.mcmeta new file mode 100644 index 0000000..e728709 --- /dev/null +++ b/folder name/pack.mcmeta @@ -0,0 +1 @@ +{"pack":{"pack_format":8,"description":"This is a datapack generated with objd by Stevertus"}} \ No newline at end of file diff --git a/lib/src/basic/pack.dart b/lib/src/basic/pack.dart index 073e6ba..b193db8 100644 --- a/lib/src/basic/pack.dart +++ b/lib/src/basic/pack.dart @@ -57,9 +57,8 @@ class Pack extends Widget { 'name': name, 'main': main?.toMap(), 'load': load?.toMap(), - 'modules': - modules == null ? null : modules!.map((x) => x.toMap()).toList(), - 'files': files == null ? null : files!.map((x) => x.toMap()).toList(), + 'modules': modules?.map((x) => x.toMap()).toList(), + 'files': files?.map((x) => x.toMap()).toList(), } }; } diff --git a/lib/src/basic/parsable.dart b/lib/src/basic/parsable.dart index f80b1e3..bf1fa77 100644 --- a/lib/src/basic/parsable.dart +++ b/lib/src/basic/parsable.dart @@ -2,5 +2,5 @@ import 'package:gson/parsable.dart'; class Parsable extends GsonParsable { /// ObjD's own type of a Parsable - Parsable(String parsable) : super(parsable); + Parsable(super.parsable); } diff --git a/lib/src/basic/score/score.dart b/lib/src/basic/score/score.dart index 3f1f259..b9f40f1 100644 --- a/lib/src/basic/score/score.dart +++ b/lib/src/basic/score/score.dart @@ -12,9 +12,9 @@ import 'package:objd/src/basic/types/entity.dart'; import 'package:objd/src/basic/widget.dart'; import 'package:objd/src/build/context.dart'; -abstract mixin class ScoreStoreable { +abstract mixin class ScoreStoreable implements Widget { // block, bossbar, entity, score, storage - String get_assignable_right(); + Widget get_assignable_right(Context context) => generate(context); ScoreOperation toScore({Score? out}) => StoreScoreOperation( out ?? Score.tmp(), @@ -47,6 +47,7 @@ abstract mixin class ScoreAssignable { sealed class ScoreOperation extends Widget implements ScoreStoreable { /// add @override + @override BinaryScoreOperation operator +(dynamic other) => switch (other) { int val => add(val), ScoreOperation s => addScore(s), @@ -55,6 +56,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { }; /// subtract + @override BinaryScoreOperation operator -(dynamic other) => switch (other) { int val => subtract(val), ScoreOperation s => subtractScore(s), @@ -63,6 +65,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { }; /// modulo by + @override BinaryScoreOperation operator %(dynamic other) => switch (other) { int val => modulo(Score.con(val)), ScoreOperation s => modulo(s), @@ -71,6 +74,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { }; /// divide by + @override BinaryScoreOperation operator /(dynamic other) => switch (other) { int val => divideByScore(Score.con(val)), ScoreOperation s => divideByScore(s), @@ -79,6 +83,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { }; /// multiply by + @override BinaryScoreOperation operator *(dynamic other) => switch (other) { int val => multiplyByScore(Score.con(val)), ScoreOperation s => multiplyByScore(s), @@ -87,6 +92,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { }; /// greater than + @override ScoreCondition operator >(dynamic other) => switch (other) { int val => matchesRange(Range.from(val + 1)), ScoreOperation s => isBigger(s), @@ -95,6 +101,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { }; /// less than + @override ScoreCondition operator <(dynamic other) => switch (other) { int val => matchesRange(Range.to(val - 1)), ScoreOperation s => isSmaller(s), @@ -103,6 +110,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { }; /// bigger or equal + @override ScoreCondition operator >=(dynamic other) => switch (other) { int val => matchesRange(Range.from(val)), ScoreOperation s => isBiggerOrEqual(s), @@ -113,6 +121,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { }; /// less or equal + @override ScoreCondition operator <=(dynamic other) => switch (other) { int val => matchesRange(Range.to(val)), ScoreOperation s => isSmallerOrEqual(s), @@ -123,6 +132,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { }; /// matches + @override ScoreCondition operator &(dynamic other) => switch (other) { int val => matches(val), Range r => matchesRange(r), @@ -150,13 +160,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { /// gets the value of the score to work with it further // TODO - // Score get() { - // return addCommandRet( - // Command( - // 'scoreboard players get ${_getESStr()}', - // ), - // ); - // } + Command get() => Command('scoreboard players get $this'); // binary operations @@ -180,51 +184,6 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { BinaryScoreOperation modulo(ScoreOperation score) => BinaryScoreOperation(this, ScoreOperator.Modulo, score); - /// sets the score to an nbt value - // Score setToData(Data data) { - // if (!data.isGetting) { - // throw ('Please set a score to Data.get and not Data.${data.subcommand}'); - // } - // return addCommandRet( - // Builder( - // (c) => Command( - // 'execute store result score ${_getESStr()} run data get ${data.getTarget(c)} ${data.path} ${data.scale ?? 1}', - // ), - // ), - // ); - // } - - // /// set to functions return value(or number of commands) - // Group setToFunction(File file) => setToWidget(file.run(create: true)); - - // /// sets the score to the success of the given Command - // Score setToResult(Command commmand, {bool useSuccess = false}) { - // return addCommandRet( - // Command( - // 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} run $commmand', - // ), - // ); - // } - - // /// sets the score to the result of the given Widget - // /// JUST one Command should be the input - // Group setToWidget(Widget widget, {bool useSuccess = false}) { - // return Group( - // prefix: - // 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} run', - // children: [widget], - // ); - // } - - // /// sets the score to the success of the given condition result - // Score setToCondition(Condition cond, {bool useSuccess = false}) { - // return addCommandRet( - // Command( - // 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} ${Condition.getPrefixes(cond.getList())[0]}', - // ), - // ); - // } - /// tests BinaryScoreCondition isEqual(ScoreOperation score) => @@ -259,14 +218,13 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { return (out, [out, ...builder.compile(this, out: out)]); } - @override - String get_assignable_right() { - throw UnimplementedError(); - } - @override ScoreOperation toScore({Score? out}) => out == null ? this : BinaryScoreOperation.assign(out, this); + + //TODO: Multistep + @override + Widget get_assignable_right(Context context) => generate(context); } sealed class ElementaryScoreOperation extends ScoreOperation {} @@ -319,20 +277,22 @@ final class ResetScoreOperation extends ElementaryScoreOperation { final class StoreScoreOperation extends ElementaryScoreOperation { final ScoreAssignable left; final ScoreStoreable right; - final bool storeResult; + final bool useSuccess; - StoreScoreOperation(this.left, this.right, {this.storeResult = true}); + StoreScoreOperation(this.left, this.right, {this.useSuccess = false}); @override - generate(Context context) => Command( - 'execute store ${storeResult ? "result" : "success"} ${left.get_assignable_left()} run ${right.get_assignable_right()}' // TODO: right operation? + Group generate(Context context) => Execute.internal_store_command( + left.get_assignable_left(), + right.get_assignable_right(context), + useSuccess, ); @override String toString() => [ ' | store ${left.get_assignable_left()}', '<<', - ' | ${right.get_assignable_right()}', + ' | $right', ].join('\n'); @override @@ -340,11 +300,13 @@ final class StoreScoreOperation extends ElementaryScoreOperation { Score? out, ScoreBuilder? builder, bool compact = false, - }) => - switch ((left, compact)) { - (Score s, true) => s.copy(out: out, builder: builder, compact: compact), - _ => super.copy(out: out, builder: builder, compact: compact) - }; + }) { + final (copyScore, ops) = switch ((left, compact)) { + (Score s, true) => s.copy(out: out, builder: builder, compact: compact), + _ => super.copy(out: out, builder: builder, compact: compact) + }; + return (copyScore, [StoreScoreOperation(copyScore, right), ...ops]); + } } final class ElementaryBinaryScoreOperation extends ElementaryScoreOperation { @@ -579,12 +541,14 @@ class Score extends ElementaryScoreOperation score, ); + @override String toString({Entity? entity, String? score}) { entity ??= this.entity; score ??= this.score; return '$entity $score'; } + @override (Score, List) copy({ Score? out, ScoreBuilder? builder, @@ -597,21 +561,56 @@ class Score extends ElementaryScoreOperation return super.copy(out: out, builder: builder, compact: compact); } + /// sets the score to an nbt value + StoreScoreOperation setToData(DataGet data) => + StoreScoreOperation(this, data); + + // /// set to functions return value(or number of commands) + // Group setToFunction(File file) => setToWidget(file.run(create: true)); + + // /// sets the score to the success of the given Command + // Score setToResult(Command commmand, {bool useSuccess = false}) { + // return addCommandRet( + // Command( + // 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} run $commmand', + // ), + // ); + // } + + // /// sets the score to the result of the given Widget + // /// JUST one Command should be the input + // Group setToWidget(Widget widget, {bool useSuccess = false}) { + // return Group( + // prefix: + // 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} run', + // children: [widget], + // ); + // } + + // /// sets the score to the success of the given condition result + // Score setToCondition(Condition cond, {bool useSuccess = false}) { + // return addCommandRet( + // Command( + // 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} ${Condition.getPrefixes(cond.getList())[0]}', + // ), + // ); + // } + /// assign value(int, Score, Data or Condition) - ScoreOperation setTo(dynamic other) { - if (other is int) return set(other); - if (other is ScoreOperation) return setEqual(other); - - ///if (other is Data) return setToData(other); - // if (other is Condition) return setToCondition(other); - // if (other is Command) return setToResult(other); - // if (other is File) return setToFunction(other); - // if (other is Widget) return setToWidget(other); - throw ('Please use either a Score, Data, Condition, Command or an Int in the operator >>'); - } + @override + ScoreOperation setTo(dynamic other) => switch (other) { + int val => set(val), + ScoreOperation s => setEqual(s), + DataGet s => setToData(s), + ScoreStoreable s => StoreScoreOperation(this, s), + _ => + throw ('Please use either a Score, Data, Condition, Command or an Int in the operator >>'), + }; - Widget operator >>(dynamic other) => setTo(other); - Widget operator <<(dynamic other) => setTo(other); + @override + ScoreOperation operator >>(dynamic other) => setTo(other); + @override + ScoreOperation operator <<(dynamic other) => setTo(other); /// sets the score to a given value of int BinaryScoreOperation set(int val) { @@ -685,7 +684,7 @@ class Score extends ElementaryScoreOperation String get_assignable_left() => 'score $this'; @override - String get_assignable_right() => 'scoreboard players get $this'; + Widget get_assignable_right(Context _) => get(); @override ScoreStoreable toStorable() => this; diff --git a/lib/src/basic/scoreboard.dart b/lib/src/basic/scoreboard.dart index bb50e1f..2efad54 100644 --- a/lib/src/basic/scoreboard.dart +++ b/lib/src/basic/scoreboard.dart @@ -18,7 +18,13 @@ class Scoreboard extends RestActionAble { static String? prefix; - static final Set _tempScores = {}; + static Set _tempScores = {}; + static List? _override_playernames; + + static void overrideTempPlayerNames(List names) { + _override_playernames = names; + _tempScores = {}; + } static String generateNewTempPlayerName({ int len = 8, @@ -26,15 +32,19 @@ class Scoreboard extends RestActionAble { }) { var r = Random(); String name = ''; - - do { - name = List.generate( - len, - (index) => _SCORE_PLAYERNAME_ALPHABET[ - r.nextInt(_SCORE_PLAYERNAME_ALPHABET.length)], - ).join(); - } while (_tempScores.contains(name)); - + if (_override_playernames != null) { + assert(_override_playernames!.length > _tempScores.length, + "No more overrides left"); + name = _override_playernames![_tempScores.length]; + } else { + do { + name = List.generate( + len, + (index) => _SCORE_PLAYERNAME_ALPHABET[ + r.nextInt(_SCORE_PLAYERNAME_ALPHABET.length)], + ).join(); + } while (_tempScores.contains(name)); + } _tempScores.add(name); return name; } diff --git a/lib/src/utils/storage.dart b/lib/src/utils/storage.dart index 3b178f9..a5f5fd0 100644 --- a/lib/src/utils/storage.dart +++ b/lib/src/utils/storage.dart @@ -1,14 +1,14 @@ import 'package:objd/core.dart'; //// The Storage Widget gives you easy tools to store and receive nbt data globally. -class Storage extends Widget { +class Storage extends Widget with ScoreAssignable, ScoreStoreable { _StorageType? _type; final String name; final bool autoNamespace; Map? nbt; String? key; DataModify? _modify; - Data? data; + DataGet? data; Score? score; double? scale; String? datatype; @@ -23,6 +23,9 @@ class Storage extends Widget { Storage( this.name, { this.autoNamespace = true, + this.key, + this.datatype, + this.scale, }); /// Here you can set one key to a specific value. @@ -76,10 +79,8 @@ class Storage extends Widget { this.name, { this.autoNamespace = true, required this.key, - required Data data, + required DataGet data, }) : assert(key != null), - assert(data.subcommand == 'get', - 'You have to insert a Data.get into copyData!'), // ignore: prefer_initializing_formals data = data, _type = _StorageType.data; @@ -136,7 +137,7 @@ class Storage extends Widget { ///Copies Nbt Data from a **Data.get** Widget. Storage copyData( String key, { - required Data data, + required DataGet data, }) => Storage.copyData( name, @@ -195,6 +196,42 @@ class Storage extends Widget { @override Widget generate(Context context) => toData(); + + @override + Widget setTo(dynamic other, {BossbarOption option = BossbarOption.value}) { + if (other is ScoreStoreable) { + return StoreScoreOperation(this, other); + } + + return set(name, other); + } + + @override + String get_assignable_left() { + assert( + key != null, + "You must to provide a key to assign to storage", + ); + return 'storage $name $key ${datatype ?? "byte"} ${scale ?? 1}'; + } + + @override + Data get_assignable_right(Context _) { + assert( + _type == _StorageType.get, + "Only Storage.get is allowed", + ); + return toData(); + } + + @override + ScoreStoreable toStorable() { + assert( + key != null, + "You must to provide a key to retrieve data from storage", + ); + return get(key!); + } } enum _StorageType { diff --git a/lib/src/wrappers/bossbar.dart b/lib/src/wrappers/bossbar.dart index 697e9b0..368334b 100644 --- a/lib/src/wrappers/bossbar.dart +++ b/lib/src/wrappers/bossbar.dart @@ -20,10 +20,10 @@ class Bossbar extends RestActionAble with ScoreAssignable, ScoreStoreable { this.id, { this.name, this.type = BossbarType.add, - this.nameTexts, + //this.nameTexts, this.option, - this.modifiers = const {}, - }); + //this.modifiers = const {}, + }) : modifiers = const {}; Bossbar remove() => copyWith(type: BossbarType.remove); @@ -63,7 +63,7 @@ class Bossbar extends RestActionAble with ScoreAssignable, ScoreStoreable { } @override - Widget? generate(Context context) { + Widget generate(Context context) { switch (type) { case BossbarType.add: return Command('bossbar add $id {"text":"$name"}'); @@ -82,8 +82,6 @@ class Bossbar extends RestActionAble with ScoreAssignable, ScoreStoreable { }); return For.of(widgets); } - default: - return null; } } @@ -129,11 +127,12 @@ class Bossbar extends RestActionAble with ScoreAssignable, ScoreStoreable { ); } + @override Widget setTo(dynamic other, {BossbarOption option = BossbarOption.value}) { print(other); if (other is int) return set(value: other); if (other is ScoreStoreable) { - return StoreScoreOperation(this.copyWith(option: option), other); + return StoreScoreOperation(copyWith(option: option), other); } throw UnimplementedError("setTo is not implemented for $other"); @@ -144,12 +143,12 @@ class Bossbar extends RestActionAble with ScoreAssignable, ScoreStoreable { 'bossbar $id ${(option ?? BossbarOption.value).name}'; @override - String get_assignable_right() { + Widget get_assignable_right(Context context) { assert( type == BossbarType.get, "You can only assign Bossbar.get to something else", ); - return 'bossbar get $id ${option!.name}'; + return generate(context); } @override diff --git a/lib/src/wrappers/data.dart b/lib/src/wrappers/data.dart index 855855c..6f71e9d 100644 --- a/lib/src/wrappers/data.dart +++ b/lib/src/wrappers/data.dart @@ -19,7 +19,6 @@ class Data extends RestActionAble { String get type => _type; String get typeValue => _typeValue; - bool get isGetting => subcommand == 'get'; /// The Data Widgets allows you to edit nbt data of Entities or Blocks. /// ```dart @@ -32,7 +31,8 @@ class Data extends RestActionAble { /// ) /// ⇒ data merge entity @s {'Invisible':1,'NoGravity':1} /// ``` - Data(this.target, {this.nbt = const {}, String type = 'merge'}) + Data(this.target, + {this.nbt = const {}, String type = 'merge', this.path = '', this.scale}) : _subcommand = type { handleTarget(target); } @@ -40,14 +40,20 @@ class Data extends RestActionAble { : _subcommand = 'merge' { handleTarget(target); } - Data.get(this.target, {required this.path, this.scale}) - : _subcommand = 'get' { + Data._(this.target, {required this.path, this.scale}) : _subcommand = 'get' { handleTarget(target); } Data.remove(this.target, {required this.path}) : _subcommand = 'remove' { handleTarget(target); } + static DataGet get(dynamic target, {required String path, num? scale}) => + DataGet( + target, + path: path, + scale: scale, + ); + /// You can also convert a score directly to a nbt field with Data.fromScore: /// /// |Data.fromScore| | @@ -122,15 +128,7 @@ class Data extends RestActionAble { case 'merge': return Command('data merge ${getTarget(context)} ${_getNbt()}'); case 'get': - final cmd = ['data get', getTarget(context), path]; - - if (scale != null) { - cmd.add( - scale! < 0.000001 ? scale!.toStringAsFixed(10) : scale.toString(), - ); - } - - return Command(cmd.join(' ')); + throw Deprecated("Moved to DataGet"); case 'remove': return Command('data remove ${getTarget(context)} $path'); case 'modify': @@ -149,6 +147,23 @@ class Data extends RestActionAble { } } +class DataGet extends Data with ScoreStoreable { + DataGet(super.target, {required super.path, super.scale}); + + @override + Command generate(Context context) { + final cmd = ['data get', getTarget(context), path]; + + if (scale != null) { + cmd.add( + scale! < 0.000001 ? scale!.toStringAsFixed(10) : scale.toString(), + ); + } + + return Command(cmd.join(' ')); + } +} + /// There are five sub operations again: set, merge, prepend, append and insert. class DataModify { String type; diff --git a/lib/src/wrappers/execute.dart b/lib/src/wrappers/execute.dart index ee6e6c3..27035eb 100644 --- a/lib/src/wrappers/execute.dart +++ b/lib/src/wrappers/execute.dart @@ -405,7 +405,7 @@ class Execute extends RestActionAble { /// just for internal use static Group internal_store_command(String type, Widget w, bool useSuccess) => Group( - prefix: 'execute store ${useSuccess ? 'success ' : 'result '}$type run', + prefix: 'execute store ${useSuccess ? 'success' : 'result'} $type run', groupMin: 1000, children: [w], ); diff --git a/pubspec.yaml b/pubspec.yaml index e3f7974..c46387b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,6 +13,7 @@ dependencies: archive: ^3.3.7 gson: ^0.1.6-dev dev_dependencies: - lints: ^2.1.1 + lints: ^3.0.0 test: ^1.24.3 + coverage: ^1.7.1 meta: ^1.9.1 \ No newline at end of file diff --git a/test/data_test.dart b/test/data_test.dart index 468b064..773c27c 100644 --- a/test/data_test.dart +++ b/test/data_test.dart @@ -10,6 +10,11 @@ void main() { Data.get(Location.here(), path: "test"), "data get block ~ ~ ~ test", ); + command( + 'assign to score', + Score(Entity.All(), "test") << Data.get(Location.here(), path: "test"), + "execute store result score @a test run data get block ~ ~ ~ test", + ); command( 'simple merge', diff --git a/test/score_test.dart b/test/score_test.dart index 20fd1f8..d5565de 100644 --- a/test/score_test.dart +++ b/test/score_test.dart @@ -5,6 +5,20 @@ import 'test_widget.dart'; void main() { group('Score', () { + test('constant', () { + expect( + Score.con(5).toString(), + "#5 objd_consts", + ); + }); + test('temp', () { + // mock temp name generation + Scoreboard.overrideTempPlayerNames(["mock1"]); + expect( + Score.tmp().toString(), + "#mock1 objd_temp", + ); + }); command( 'register', Score(Entity.All(), "test"), @@ -36,6 +50,16 @@ void main() { ]); }); + group("Score Bossbar", () { + Scoreboard.overrideTempPlayerNames(["mock1"]); + commands('add', Bossbar("test").get(BossbarOption.value) + 1, [ + "execute store result score #mock1 objd_temp run bossbar get test value", + "scoreboard objectives add objd_temp dummy", + "scoreboard players add #mock1 objd_temp 1", + "execute store result bossbar test value run scoreboard players get #mock1 objd_temp" + ]); + }); + group('Score Conditions', () { command( "simple if", From 605ca80567e5913a9f074a0f76c9b47f2a88f31c Mon Sep 17 00:00:00 2001 From: Stevertus Date: Wed, 29 Nov 2023 21:57:06 +0100 Subject: [PATCH 7/8] temporary solution for score conditions --- lib/src/basic/score/score.dart | 272 +++++++++++++---------- lib/src/basic/score/score_builder.dart | 7 +- lib/src/basic/score/score_condition.dart | 23 +- lib/src/basic/types/condition.dart | 9 + test/score_test.dart | 12 +- 5 files changed, 188 insertions(+), 135 deletions(-) diff --git a/lib/src/basic/score/score.dart b/lib/src/basic/score/score.dart index b9f40f1..90a0b81 100644 --- a/lib/src/basic/score/score.dart +++ b/lib/src/basic/score/score.dart @@ -26,11 +26,12 @@ abstract mixin class ScoreStoreable implements Widget { BinaryScoreOperation operator %(dynamic other) => toScore() % other; BinaryScoreOperation operator /(dynamic other) => toScore() / other; BinaryScoreOperation operator *(dynamic other) => toScore() * other; - ScoreCondition operator >(dynamic other) => toScore() > other; - ScoreCondition operator >=(dynamic other) => toScore() >= other; - ScoreCondition operator <=(dynamic other) => toScore() <= other; - ScoreCondition operator <(dynamic other) => toScore() < other; - ScoreCondition operator &(dynamic other) => toScore() & other; + // TODO: Not finished, refactor of If needed + // ScoreCondition operator >(dynamic other) => toScore() > other; + // ScoreCondition operator >=(dynamic other) => toScore() >= other; + // ScoreCondition operator <=(dynamic other) => toScore() <= other; + // ScoreCondition operator <(dynamic other) => toScore() < other; + // ScoreCondition operator &(dynamic other) => toScore() & other; } abstract mixin class ScoreAssignable { @@ -91,59 +92,6 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { _ => throw ('Please use either a Score or an Int in the operator *') }; - /// greater than - @override - ScoreCondition operator >(dynamic other) => switch (other) { - int val => matchesRange(Range.from(val + 1)), - ScoreOperation s => isBigger(s), - ScoreStoreable s => isBigger(s.toScore()), - _ => throw ('Please use either a Score or an Int in the operator >') - }; - - /// less than - @override - ScoreCondition operator <(dynamic other) => switch (other) { - int val => matchesRange(Range.to(val - 1)), - ScoreOperation s => isSmaller(s), - ScoreStoreable s => isSmaller(s.toScore()), - _ => throw ('Please use either a Score or an Int in the operator <') - }; - - /// bigger or equal - @override - ScoreCondition operator >=(dynamic other) => switch (other) { - int val => matchesRange(Range.from(val)), - ScoreOperation s => isBiggerOrEqual(s), - ScoreStoreable s => isBiggerOrEqual( - s.toScore(), - ), - _ => throw ('Please use either a Score or an Int in the operator >=') - }; - - /// less or equal - @override - ScoreCondition operator <=(dynamic other) => switch (other) { - int val => matchesRange(Range.to(val)), - ScoreOperation s => isSmallerOrEqual(s), - ScoreStoreable s => isSmallerOrEqual( - s.toScore(), - ), - _ => throw ('Please use either a Score or an Int in the operator <=') - }; - - /// matches - @override - ScoreCondition operator &(dynamic other) => switch (other) { - int val => matches(val), - Range r => matchesRange(r), - ScoreOperation s => isEqual(s), - ScoreStoreable s => isEqual( - s.toScore(), - ), - _ => - throw ('Please use either a Score, Range or an Int in the operator &') - }; - /// adds a value to the score BinaryScoreOperation add([int val = 1]) => BinaryScoreOperation( this, @@ -160,7 +108,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { /// gets the value of the score to work with it further // TODO - Command get() => Command('scoreboard players get $this'); + Widget get() => For.of([this, Command('scoreboard players get $this')]); // binary operations @@ -184,23 +132,7 @@ sealed class ScoreOperation extends Widget implements ScoreStoreable { BinaryScoreOperation modulo(ScoreOperation score) => BinaryScoreOperation(this, ScoreOperator.Modulo, score); - /// tests - - BinaryScoreCondition isEqual(ScoreOperation score) => - BinaryScoreCondition(this, ConditionalOperator.Equal, score); - BinaryScoreCondition isSmaller(ScoreOperation score) => - BinaryScoreCondition(this, ConditionalOperator.Less, score); - BinaryScoreCondition isSmallerOrEqual(ScoreOperation score) => - BinaryScoreCondition(this, ConditionalOperator.LessEqual, score); - BinaryScoreCondition isBiggerOrEqual(ScoreOperation score) => - BinaryScoreCondition(this, ConditionalOperator.BiggerEqual, score); - BinaryScoreCondition isBigger(ScoreOperation score) => - BinaryScoreCondition(this, ConditionalOperator.Bigger, score); - - MatchesScoreCondition matches(int value) => - MatchesScoreCondition(this, Range.exact(value)); - MatchesScoreCondition matchesRange(Range range) => - MatchesScoreCondition(this, range); + //TODO: Move Condition Operators here void build() { print('test'); @@ -276,17 +208,22 @@ final class ResetScoreOperation extends ElementaryScoreOperation { final class StoreScoreOperation extends ElementaryScoreOperation { final ScoreAssignable left; - final ScoreStoreable right; + final Widget right; final bool useSuccess; StoreScoreOperation(this.left, this.right, {this.useSuccess = false}); @override - Group generate(Context context) => Execute.internal_store_command( - left.get_assignable_left(), - right.get_assignable_right(context), - useSuccess, - ); + Widget generate(Context context) => For.of([ + if (left is Score) left as Score, + Execute.internal_store_command( + left.get_assignable_left(), + right is ScoreStoreable + ? (right as ScoreStoreable).get_assignable_right(context) + : right.generate(context), + useSuccess, + ) + ]); @override String toString() => [ @@ -309,6 +246,46 @@ final class StoreScoreOperation extends ElementaryScoreOperation { } } +final class StoreConditionScoreOperation extends ElementaryScoreOperation { + final ScoreAssignable left; + final Condition right; + final bool useSuccess; + + StoreConditionScoreOperation(this.left, this.right, + {this.useSuccess = false}); + + @override + Widget generate(Context context) => For.of([ + if (left is Score) left as Score, + Command( + 'execute store ${useSuccess ? 'success' : 'result'} ${left.get_assignable_left()} ${Condition.getPrefixes(right.getList())[0]}', + ) + ]); + + @override + String toString() => [ + ' | store ${left.get_assignable_left()}', + '<<', + ' | $right', + ].join('\n'); + + @override + (Score, List) copy({ + Score? out, + ScoreBuilder? builder, + bool compact = false, + }) { + final (copyScore, ops) = switch ((left, compact)) { + (Score s, true) => s.copy(out: out, builder: builder, compact: compact), + _ => super.copy(out: out, builder: builder, compact: compact) + }; + return ( + copyScore, + [StoreConditionScoreOperation(copyScore, right), ...ops] + ); + } +} + final class ElementaryBinaryScoreOperation extends ElementaryScoreOperation { final Score left; final Score right; @@ -562,49 +539,41 @@ class Score extends ElementaryScoreOperation } /// sets the score to an nbt value - StoreScoreOperation setToData(DataGet data) => - StoreScoreOperation(this, data); - - // /// set to functions return value(or number of commands) - // Group setToFunction(File file) => setToWidget(file.run(create: true)); - - // /// sets the score to the success of the given Command - // Score setToResult(Command commmand, {bool useSuccess = false}) { - // return addCommandRet( - // Command( - // 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} run $commmand', - // ), - // ); - // } - - // /// sets the score to the result of the given Widget - // /// JUST one Command should be the input - // Group setToWidget(Widget widget, {bool useSuccess = false}) { - // return Group( - // prefix: - // 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} run', - // children: [widget], - // ); - // } - - // /// sets the score to the success of the given condition result - // Score setToCondition(Condition cond, {bool useSuccess = false}) { - // return addCommandRet( - // Command( - // 'execute store ${useSuccess ? 'success' : 'result'} score ${_getESStr()} ${Condition.getPrefixes(cond.getList())[0]}', - // ), - // ); - // } + StoreScoreOperation setToData(DataGet data, {bool useSuccess = false}) => + StoreScoreOperation(this, data, useSuccess: useSuccess); + + /// set to functions return value(or number of commands) + StoreScoreOperation setToFunction(File file, {bool useSuccess = false}) => + setToWidget(file.run(create: true)); + + /// sets the score to the success of the given Command + StoreScoreOperation setToResult(Command commmand, + {bool useSuccess = false}) => + setToWidget(commmand, useSuccess: useSuccess); + + /// sets the score to the result of the given Widget + /// JUST one Command should be the input + StoreScoreOperation setToWidget(Widget widget, {bool useSuccess = false}) => + StoreScoreOperation(this, widget, useSuccess: useSuccess); + + /// sets the score to the success of the given condition result + StoreConditionScoreOperation setToCondition(Condition cond, + {bool useSuccess = false}) => + StoreConditionScoreOperation(this, cond, useSuccess: useSuccess); /// assign value(int, Score, Data or Condition) @override - ScoreOperation setTo(dynamic other) => switch (other) { + ScoreOperation setTo(dynamic other, {bool useSuccess = false}) => + switch (other) { int val => set(val), ScoreOperation s => setEqual(s), - DataGet s => setToData(s), - ScoreStoreable s => StoreScoreOperation(this, s), + DataGet s => setToData(s, useSuccess: useSuccess), + ScoreStoreable s => + StoreScoreOperation(this, s, useSuccess: useSuccess), + Condition c => setToCondition(c, useSuccess: useSuccess), + Widget w => setToWidget(w, useSuccess: useSuccess), _ => - throw ('Please use either a Score, Data, Condition, Command or an Int in the operator >>'), + throw ('Please use either a Score, Data, Condition, Command or an Int in the operator >>, got $other'), }; @override @@ -639,6 +608,71 @@ class Score extends ElementaryScoreOperation BinaryScoreOperation setToBiggest(ScoreOperation score) => BinaryScoreOperation(this, ScoreOperator.Max, score); + /// tests + + /// greater than + @override + ScoreCondition operator >(dynamic other) => switch (other) { + int val => matchesRange(Range.from(val + 1)), + Score s => isBigger(s), + // ScoreStoreable s => isBigger(s.toScore()), + _ => throw ('Please use either a Score or an Int in the operator >') + }; + + /// less than + @override + ScoreCondition operator <(dynamic other) => switch (other) { + int val => matchesRange(Range.to(val - 1)), + Score s => isSmaller(s), + //ScoreStoreable s => isSmaller(s.toScore()), + _ => throw ('Please use either a Score or an Int in the operator <') + }; + + /// bigger or equal + @override + ScoreCondition operator >=(dynamic other) => switch (other) { + int val => matchesRange(Range.from(val)), + Score s => isBiggerOrEqual(s), + //ScoreStoreable s => isBiggerOrEqual(s.toScore()), + _ => throw ('Please use either a Score or an Int in the operator >=') + }; + + /// less or equal + @override + ScoreCondition operator <=(dynamic other) => switch (other) { + int val => matchesRange(Range.to(val)), + Score s => isSmallerOrEqual(s), + //ScoreStoreable s => isSmallerOrEqual(s.toScore()), + _ => throw ('Please use either a Score or an Int in the operator <=') + }; + + /// matches + @override + ScoreCondition operator &(dynamic other) => switch (other) { + int val => matches(val), + Range r => matchesRange(r), + Score s => isEqual(s), + //ScoreStoreable s => isEqual(s.toScore()), + _ => + throw ('Please use either a Score, Range or an Int in the operator &') + }; + + BinaryScoreCondition isEqual(Score score) => + BinaryScoreCondition(this, ConditionalOperator.Equal, score); + BinaryScoreCondition isSmaller(Score score) => + BinaryScoreCondition(this, ConditionalOperator.Less, score); + BinaryScoreCondition isSmallerOrEqual(Score score) => + BinaryScoreCondition(this, ConditionalOperator.LessEqual, score); + BinaryScoreCondition isBiggerOrEqual(Score score) => + BinaryScoreCondition(this, ConditionalOperator.BiggerEqual, score); + BinaryScoreCondition isBigger(Score score) => + BinaryScoreCondition(this, ConditionalOperator.Bigger, score); + + MatchesScoreCondition matches(int value) => + MatchesScoreCondition(this, Range.exact(value)); + MatchesScoreCondition matchesRange(Range range) => + MatchesScoreCondition(this, range); + /// finds the smallest value in a list of scores Widget findSmallest(List scores, {int? min}) { return For( diff --git a/lib/src/basic/score/score_builder.dart b/lib/src/basic/score/score_builder.dart index 87e710c..445b395 100644 --- a/lib/src/basic/score/score_builder.dart +++ b/lib/src/basic/score/score_builder.dart @@ -21,6 +21,10 @@ class ScoreBuilder { input, if (out != null) ElementaryBinaryScoreOperation.assign(out, score), ], + StoreConditionScoreOperation(left: final left) => [ + input, + if (out != null) StoreScoreOperation(out, left.toStorable()) + ], StoreScoreOperation(left: final left) => [ input, if (out != null) StoreScoreOperation(out, left.toStorable()) @@ -45,10 +49,11 @@ class ScoreBuilder { if (left is Score) { if (right is ConstScore) { - return [SetScoreOperation(left, right.value)]; + return [left, SetScoreOperation(left, right.value)]; } return [ + left, ...prevactions, ElementaryBinaryScoreOperation.assign(left, tmpRight) ]; diff --git a/lib/src/basic/score/score_condition.dart b/lib/src/basic/score/score_condition.dart index e2905af..20a86bb 100644 --- a/lib/src/basic/score/score_condition.dart +++ b/lib/src/basic/score/score_condition.dart @@ -4,17 +4,20 @@ import 'package:objd/src/basic/types/condition.dart'; import 'package:objd/src/basic/types/entity.dart'; sealed class ScoreCondition extends Condition { - ScoreCondition() : super(null); + final bool invert; + //TODO: refactor + ScoreCondition._(String generated, {this.invert = false}) + // ignore: deprecated_member_use_from_same_package + : super.raw(generated, invert: invert); } class MatchesScoreCondition extends ScoreCondition { - final ScoreOperation score; + // TODO: Implement for general ScoreOperations, refactor of If necessary + final Score score; final Range range; - MatchesScoreCondition( - this.score, - this.range, - ); + MatchesScoreCondition(this.score, this.range, {super.invert = false}) + : super._('score $score matches $range'); String getMatch() => range.toString(); @@ -29,11 +32,13 @@ class MatchesScoreCondition extends ScoreCondition { } class BinaryScoreCondition extends ScoreCondition { - final ScoreOperation left; + // TODO: Implement for general ScoreOperations, refactor of If necessary + final Score left; final ConditionalOperator operation; - final ScoreOperation right; + final Score right; - BinaryScoreCondition(this.left, this.operation, this.right); + BinaryScoreCondition(this.left, this.operation, this.right) + : super._('score $left ${operation.op} $right'); @override String toString() { diff --git a/lib/src/basic/types/condition.dart b/lib/src/basic/types/condition.dart index 47baf56..7f702b8 100644 --- a/lib/src/basic/types/condition.dart +++ b/lib/src/basic/types/condition.dart @@ -15,6 +15,15 @@ class Condition { _ConditionType? _type; _ConditionUtil? _generated; + // ignore: library_private_types_in_public_api + + @Deprecated("Will be removed with Conditon refactor, not for public use") + Condition.raw(String generated, {bool invert = false}) + : _generated = _ConditionUtil( + generated, + invert: invert, + ); + /// The Condition class defines conditions for the if widget and more. It can also combines conditions and generates an argument list. /// A condition can accept many values and this makes the Condition very complex. /// diff --git a/test/score_test.dart b/test/score_test.dart index 90a56a3..23b6821 100644 --- a/test/score_test.dart +++ b/test/score_test.dart @@ -132,7 +132,7 @@ void main() { ]); commands('setTo Data', s1 << Data.get(Entity.Self(), path: "test"), [ "scoreboard objectives add test dummy", - "execute store result score @a test run data get entity @s test 1" + "execute store result score @a test run data get entity @s test" ]); commands( 'setTo File', @@ -165,11 +165,11 @@ void main() { }); group('Score Conditions', () { - commands( - "empty", - s1.isBigger(Score(Entity.Self(), "new")), - [], - ); + // commands( + // "empty", + // s1.isBigger(Score(Entity.Self(), "new")), + // [], + // ); command( "simple if", If( From 400373780d28ef49665bb4b1b0a1ea95ec124ef8 Mon Sep 17 00:00:00 2001 From: Stevertus Date: Wed, 29 Nov 2023 22:22:48 +0100 Subject: [PATCH 8/8] fix tests --- test/data_test.dart | 7 +++++-- test/score_test.dart | 12 +++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/test/data_test.dart b/test/data_test.dart index 773c27c..4cc6678 100644 --- a/test/data_test.dart +++ b/test/data_test.dart @@ -10,10 +10,13 @@ void main() { Data.get(Location.here(), path: "test"), "data get block ~ ~ ~ test", ); - command( + commands( 'assign to score', Score(Entity.All(), "test") << Data.get(Location.here(), path: "test"), - "execute store result score @a test run data get block ~ ~ ~ test", + [ + 'scoreboard objectives add test dummy', + "execute store result score @a test run data get block ~ ~ ~ test" + ], ); command( diff --git a/test/score_test.dart b/test/score_test.dart index 23b6821..f9d7ca2 100644 --- a/test/score_test.dart +++ b/test/score_test.dart @@ -137,12 +137,18 @@ void main() { commands( 'setTo File', s1 << File("test"), - ["execute store result score @a test run function :test"], + [ + "scoreboard objectives add test dummy", + "execute store result score @a test run function :test" + ], ); commands( 'setTo Widget', s1 << Say("mock"), - ["execute store result score @a test run say mock"], + [ + "scoreboard objectives add test dummy", + "execute store result score @a test run say mock" + ], ); commands( 'setTo Condition', @@ -157,8 +163,8 @@ void main() { group("Score Bossbar", () { Scoreboard.overrideTempPlayerNames(["mock1"]); commands('add', Bossbar("test").get(BossbarOption.value) + 1, [ - "execute store result score #mock1 objd_temp run bossbar get test value", "scoreboard objectives add objd_temp dummy", + "execute store result score #mock1 objd_temp run bossbar get test value", "scoreboard players add #mock1 objd_temp 1", "execute store result bossbar test value run scoreboard players get #mock1 objd_temp" ]);