From 605ca80567e5913a9f074a0f76c9b47f2a88f31c Mon Sep 17 00:00:00 2001 From: Stevertus Date: Wed, 29 Nov 2023 21:57:06 +0100 Subject: [PATCH] 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(