have multiple commands per command

Discussion in 'Plugin Development' started by EmpororerBaba, Aug 26, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    EmpororerBaba

    So for example, if you do something like /stop and I were to have a plugin ask you to /confirm it, how would you do that? (New to Java/Bukkit)
     
  2. Offline

    werter318

    Use Comphenix' ExpireHashMap for this:

    Code:java
    1.  
    2. import java.util.Collection;
    3. import java.util.HashMap;
    4. import java.util.Map;
    5. import java.util.Map.Entry;
    6. import java.util.PriorityQueue;
    7. import java.util.Set;
    8. import java.util.concurrent.TimeUnit;
    9.  
    10. import com.google.common.base.Function;
    11. import com.google.common.base.Objects;
    12. import com.google.common.base.Preconditions;
    13. import com.google.common.base.Ticker;
    14. import com.google.common.collect.Maps;
    15. import com.google.common.primitives.Longs;
    16.  
    17. /**
    18. * Represents a hash map where each association may expire after a given time
    19. * has elapsed.
    20. * <p>
    21. * Note that replaced key-value associations are only collected once the
    22. * original expiration time has elapsed.
    23. *
    24. * @author Kristian Stangeland
    25. *
    26. * @param <K>
    27. * - type of the keys.
    28. * @param <V>
    29. * - type of the values.
    30. */
    31. public class ExpireHashMap<K, V> {
    32. private class ExpireEntry implements Comparable<ExpireEntry> {
    33. public final long expireTime;
    34. public final K expireKey;
    35. public final V expireValue;
    36.  
    37. public ExpireEntry(long expireTime, K expireKey, V expireValue) {
    38. this.expireTime = expireTime;
    39. this.expireKey = expireKey;
    40. this.expireValue = expireValue;
    41. }
    42.  
    43. @Override
    44. public int compareTo(ExpireEntry o) {
    45. return Longs.compare(expireTime, o.expireTime);
    46. }
    47.  
    48. @Override
    49. public String toString() {
    50. return "ExpireEntry [expireTime=" + expireTime + ", expireKey=" + expireKey + ", expireValue=" + expireValue + "]";
    51. }
    52. }
    53.  
    54. private Map<K, ExpireEntry> keyLookup = new HashMap<K, ExpireEntry>();
    55. private PriorityQueue<ExpireEntry> expireQueue = new PriorityQueue<ExpireEntry>();
    56.  
    57. // View of keyLookup with direct values
    58. private Map<K, V> valueView = Maps.transformValues(keyLookup, new Function<ExpireEntry, V>() {
    59. @Override
    60. public V apply(ExpireEntry entry) {
    61. return entry.expireValue;
    62. }
    63. });
    64.  
    65. // Supplied by the constructor
    66. private Ticker ticker;
    67.  
    68. /**
    69. * Construct a new hash map where each entry may expire at a given time.
    70. */
    71. public ExpireHashMap() {
    72. this(Ticker.systemTicker());
    73. }
    74.  
    75. /**
    76. * Construct a new hash map where each entry may expire at a given time.
    77. *
    78. * @param ticker
    79. * - supplier of the current time.
    80. */
    81. public ExpireHashMap(Ticker ticker) {
    82. this.ticker = ticker;
    83. }
    84.  
    85. /**
    86. * Retrieve the value associated with the given key, if it has not expired.
    87. *
    88. * @param key
    89. * - the key.
    90. * @return The value, or NULL if not found or it has expired.
    91. */
    92. public V get(K key) {
    93. evictExpired();
    94.  
    95. ExpireEntry entry = keyLookup.get(key);
    96. return entry != null ? entry.expireValue : null;
    97. }
    98.  
    99. /**
    100. * Associate the given key with the given value, until the expire delay have
    101. * elapsed.
    102. *
    103. * @param key
    104. * - the key.
    105. * @param value
    106. * - the value.
    107. * @param expireDelay
    108. * - the amount of time until this association expires. Must be
    109. * greater than zero.
    110. * @param expireUnit
    111. * - the unit of the expiration.
    112. * @return Any previously unexpired association with this key, or NULL.
    113. */
    114. public V put(K key, V value, long expireDelay, TimeUnit expireUnit) {
    115. Preconditions.checkNotNull(expireUnit, "expireUnit cannot be NULL");
    116. Preconditions.checkState(expireDelay > 0, "expireDelay cannot be equal or less than zero.");
    117. evictExpired();
    118.  
    119. ExpireEntry entry = new ExpireEntry(ticker.read() + TimeUnit.NANOSECONDS.convert(expireDelay, expireUnit), key, value);
    120. ExpireEntry previous = keyLookup.put(key, entry);
    121.  
    122. // We enqueue its removal
    123. expireQueue.add(entry);
    124. return previous != null ? previous.expireValue : null;
    125. }
    126.  
    127. /**
    128. * Determine if the given key is referring to an unexpired association in
    129. * the map.
    130. *
    131. * @param key
    132. * - the key.
    133. * @return TRUE if it is, FALSE otherwise.
    134. */
    135. public boolean containsKey(K key) {
    136. evictExpired();
    137. return keyLookup.containsKey(key);
    138. }
    139.  
    140. /**
    141. * Determine if the given value is referring to an unexpired association in
    142. * the map.
    143. *
    144. * @param value
    145. * - the value.
    146. * @return TRUE if it is, FALSE otherwise.
    147. */
    148. public boolean containsValue(V value) {
    149. evictExpired();
    150.  
    151. // Linear scan is the best we've got
    152. for (ExpireEntry entry : keyLookup.values()) {
    153. if (Objects.equal(value, entry.expireValue)) {
    154. return true;
    155. }
    156. }
    157. return false;
    158. }
    159.  
    160. /**
    161. * Remove a key and its associated value from the map.
    162. *
    163. * @param key
    164. * - the key to remove.
    165. * @return Value of the removed association, NULL otherwise.
    166. */
    167. public V removeKey(K key) {
    168. evictExpired();
    169.  
    170. ExpireEntry entry = keyLookup.remove(key);
    171. return entry != null ? entry.expireValue : null;
    172. }
    173.  
    174. /**
    175. * Retrieve the number of entries in the map.
    176. *
    177. * @return The number of entries.
    178. */
    179. public int size() {
    180. evictExpired();
    181. return keyLookup.size();
    182. }
    183.  
    184. /**
    185. * Retrieve a view of the keys in the current map.
    186. *
    187. * @return View of the keys.
    188. */
    189. public Set<K> keySet() {
    190. evictExpired();
    191. return keyLookup.keySet();
    192. }
    193.  
    194. /**
    195. * Retrieve a view of all the values in the current map.
    196. *
    197. * @return All the values.
    198. */
    199. public Collection<V> values() {
    200. evictExpired();
    201. return valueView.values();
    202. }
    203.  
    204. /**
    205. * Retrieve a view of all the entries in the set.
    206. *
    207. * @return All the entries.
    208. */
    209. public Set<Entry<K, V>> entrySet() {
    210. evictExpired();
    211. return valueView.entrySet();
    212. }
    213.  
    214. /**
    215. * Retrieve a view of this expire map as an ordinary map that does not
    216. * support insertion.
    217. *
    218. * @return The map.
    219. */
    220. public Map<K, V> asMap() {
    221. evictExpired();
    222. return valueView;
    223. }
    224.  
    225. /**
    226. * Clear all references to key-value pairs that have been removed or
    227. * replaced before they were naturally evicted.
    228. * <p>
    229. * This operation requires a linear scan of the current entries in the map.
    230. */
    231. public void collect() {
    232. // First evict what we can
    233. evictExpired();
    234.  
    235. // Recreate the eviction queue - this is faster than removing entries in
    236. // the old queue
    237. expireQueue.clear();
    238. expireQueue.addAll(keyLookup.values());
    239. }
    240.  
    241. /**
    242. * Clear all the entries in the current map.
    243. */
    244. public void clear() {
    245. keyLookup.clear();
    246. expireQueue.clear();
    247. }
    248.  
    249. /**
    250. * Evict any expired entries in the map.
    251. * <p>
    252. * This is called automatically by any of the read or write operations.
    253. */
    254. protected void evictExpired() {
    255. long currentTime = ticker.read();
    256.  
    257. // Remove expired entries
    258. while (expireQueue.size() > 0 && expireQueue.peek().expireTime <= currentTime) {
    259. ExpireEntry entry = expireQueue.poll();
    260.  
    261. if (entry == keyLookup.get(entry.expireKey)) {
    262. keyLookup.remove(entry.expireKey);
    263. }
    264. }
    265. }
    266.  
    267. @Override
    268. public String toString() {
    269. return valueView.toString();
    270. }
    271. }


    Whenever they type /stop (You can overwrite /stop but you need NMS and Reflection to do so) add their UUID to that hashmap with the expiry. Then whenever they type /confirm check if their UUID is in that hashmap. I know you don't need a HashMap for this and I also have an ExpireArrayList class, but that's for private use only.
     
  3. Offline

    McMhz

    werter318
    Can't you just 'cancel' commands with that one event, and put your own code?
    Edit: Like the plugins that disable /pl
     
  4. Offline

    werter318

    McMhz You mean CommandPreprocces? If so, no you can't cancel the stop command.
     
Thread Status:
Not open for further replies.

Share This Page