32
32
import ch .njol .util .Kleenean ;
33
33
import ch .njol .util .StringUtils ;
34
34
import ch .njol .util .coll .CollectionUtils ;
35
+ import com .google .common .collect .Iterators ;
35
36
import org .bukkit .event .Event ;
36
37
import org .eclipse .jdt .annotation .Nullable ;
37
38
38
39
import java .lang .reflect .Array ;
40
+ import java .util .Iterator ;
39
41
40
42
@ Name ("Element of" )
41
43
@ Description ({"The first, last or a random element of a set, e.g. a list variable." ,
42
44
"See also: <a href='#ExprRandom'>random</a>" })
43
45
@ Examples ("give a random element out of {free items::*} to the player" )
44
- @ Since ("2.0" )
46
+ @ Since ("2.0, INSERT VERSION (relative to last element) " )
45
47
public class ExprElement extends SimpleExpression <Object > {
46
48
47
49
static {
48
- Skript .registerExpression (ExprElement .class , Object .class , ExpressionType .PROPERTY , "(-1¦ [the] first|1¦ [the] last|0¦ [a] random|2¦ %-number%(st|nd|rd|th)) element [out] of %objects%" );
50
+ Skript .registerExpression (ExprElement .class , Object .class , ExpressionType .PROPERTY , "(0: [the] first|1: [the] last|2: [a] random|3:[the] %-number%(st|nd|rd|th)|4:[the] %-number%(st|nd|rd|th) [to] last ) element [out] of %objects%" );
49
51
}
50
52
51
- private int element ;
53
+ private enum ElementType {
54
+ FIRST , LAST , RANDOM , ORDINAL , TAIL_END_ORDINAL
55
+ }
56
+
57
+ private ElementType type ;
52
58
53
59
private Expression <?> expr ;
54
60
@@ -58,34 +64,56 @@ public class ExprElement extends SimpleExpression<Object> {
58
64
@ Override
59
65
@ SuppressWarnings ("unchecked" )
60
66
public boolean init (Expression <?>[] exprs , int matchedPattern , Kleenean isDelayed , ParseResult parseResult ) {
61
- expr = LiteralUtils .defendExpression (exprs [1 ]);
62
- number = ( Expression < Number >) exprs [ 0 ];
63
- element = parseResult . mark ;
67
+ expr = LiteralUtils .defendExpression (exprs [2 ]);
68
+ type = ElementType . values ()[ parseResult . mark ];
69
+ number = ( Expression < Number >) ( type == ElementType . ORDINAL ? exprs [ 0 ]: exprs [ 1 ]) ;
64
70
return LiteralUtils .canInitSafely (expr );
65
71
}
66
72
67
73
@ Override
68
74
@ Nullable
69
- protected Object [] get (Event e ) {
70
- Object [] os = expr .getArray ( e );
71
- if (os . length == 0 )
75
+ protected Object [] get (Event event ) {
76
+ Iterator <?> iter = expr .iterator ( event );
77
+ if (iter == null || ! iter . hasNext () )
72
78
return null ;
73
- Object o ;
74
- if (element == -1 ) {
75
- o = os [0 ];
76
- } else if (element == 1 ) {
77
- o = os [os .length - 1 ];
78
- } else if (element == 2 ) {
79
- Number number = this .number .getSingle (e );
80
- if (number == null || number .intValue () - 1 >= os .length || number .intValue () - 1 < 0 )
81
- return null ;
82
- o = os [number .intValue () - 1 ];
83
- } else {
84
- o = CollectionUtils .getRandom (os );
79
+ Object element = null ;
80
+ switch (type ) {
81
+ case FIRST :
82
+ element = iter .next ();
83
+ break ;
84
+ case LAST :
85
+ element = Iterators .getLast (iter );
86
+ break ;
87
+ case ORDINAL :
88
+ assert this .number != null ;
89
+ Number number = this .number .getSingle (event );
90
+ if (number == null )
91
+ return null ;
92
+ try {
93
+ element = Iterators .get (iter , number .intValue () - 1 );
94
+ } catch (IndexOutOfBoundsException exception ) {
95
+ return null ;
96
+ }
97
+ break ;
98
+ case RANDOM :
99
+ Object [] allIterValues = Iterators .toArray (iter , Object .class );
100
+ element = CollectionUtils .getRandom (allIterValues );
101
+ break ;
102
+ case TAIL_END_ORDINAL :
103
+ allIterValues = Iterators .toArray (iter , Object .class );
104
+ assert this .number != null ;
105
+ number = this .number .getSingle (event );
106
+ if (number == null )
107
+ return null ;
108
+ int ordinal = number .intValue ();
109
+ if (ordinal <= 0 || ordinal > allIterValues .length )
110
+ return null ;
111
+ element = allIterValues [allIterValues .length - ordinal ];
112
+ break ;
85
113
}
86
- Object [] r = (Object []) Array .newInstance (getReturnType (), 1 );
87
- r [0 ] = o ;
88
- return r ;
114
+ Object [] elementArray = (Object []) Array .newInstance (getReturnType (), 1 );
115
+ elementArray [0 ] = element ;
116
+ return elementArray ;
89
117
}
90
118
91
119
@ Override
@@ -97,7 +125,7 @@ public <R> Expression<? extends R> getConvertedExpression(Class<R>... to) {
97
125
return null ;
98
126
99
127
ExprElement exprElement = new ExprElement ();
100
- exprElement .element = this .element ;
128
+ exprElement .type = this .type ;
101
129
exprElement .expr = convExpr ;
102
130
exprElement .number = this .number ;
103
131
return (Expression <? extends R >) exprElement ;
@@ -116,17 +144,17 @@ public Class<?> getReturnType() {
116
144
@ Override
117
145
public String toString (@ Nullable Event e , boolean debug ) {
118
146
String prefix ;
119
- switch (element ) {
120
- case - 1 :
147
+ switch (type ) {
148
+ case FIRST :
121
149
prefix = "the first" ;
122
150
break ;
123
- case 1 :
151
+ case LAST :
124
152
prefix = "the last" ;
125
153
break ;
126
- case 0 :
154
+ case RANDOM :
127
155
prefix = "a random" ;
128
156
break ;
129
- case 2 :
157
+ case ORDINAL :
130
158
assert number != null ;
131
159
prefix = "the " ;
132
160
// Proper ordinal number
0 commit comments