Compare commits

...

2 Commits

Author SHA1 Message Date
TONY_All ef8b5c973f
format code 2024-08-08 20:12:34 +08:00
TONY_All ff96cf59da
fix 重生后村民不可见
finish 方块禁止破坏
update 计分板显示
finish TNT自动点燃
finish 优化传送体验
finish 防止重复加入检测
2024-08-08 20:11:55 +08:00
16 changed files with 453 additions and 373 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
.idea .idea
build/ build/
test_server

View File

@ -40,7 +40,7 @@ taboolib {
// classifier = null // classifier = null
// options("skip-kotlin-relocate") // options("skip-kotlin-relocate")
version { version {
taboolib = "6.1.1" taboolib = "6.1.2-beta2"
} }
} }

View File

@ -25,8 +25,8 @@
package cc.maxmc.blastingcrisis.misc; package cc.maxmc.blastingcrisis.misc;
import java.util.function.Consumer;
import java.util.*; import java.util.*;
import java.util.function.Consumer;
/** /**
* Doubly-linked list implementation of the {@code List} and {@code Deque} * Doubly-linked list implementation of the {@code List} and {@code Deque}
@ -73,26 +73,24 @@ import java.util.*;
* <a href="{@docRoot}/../technotes/guides/collections/index.html"> * <a href="{@docRoot}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>. * Java Collections Framework</a>.
* *
* @param <E> the type of elements held in this collection
* @author Josh Bloch * @author Josh Bloch
* @see List * @see List
* @see ArrayList * @see ArrayList
* @since 1.2 * @since 1.2
* @param <E> the type of elements held in this collection
*/ */
public class EnhancedLinkedList<E> public class EnhancedLinkedList<E>
extends AbstractSequentialList<E> extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
{ private static final long serialVersionUID = 876323262645176354L;
transient int size = 0; transient int size = 0;
/** /**
* Pointer to first node. * Pointer to first node.
* Invariant: (first == null && last == null) || * Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null) * (first.prev == null && first.item != null)
*/ */
transient Node<E> first; transient Node<E> first;
/** /**
* Pointer to last node. * Pointer to last node.
* Invariant: (first == null && last == null) || * Invariant: (first == null && last == null) ||
@ -441,6 +439,9 @@ public class EnhancedLinkedList<E>
return true; return true;
} }
// Positional Access Operations
/** /**
* Removes all of the elements from this list. * Removes all of the elements from this list.
* The list will be empty after this call returns. * The list will be empty after this call returns.
@ -462,9 +463,6 @@ public class EnhancedLinkedList<E>
modCount++; modCount++;
} }
// Positional Access Operations
/** /**
* Returns the element at the specified position in this list. * Returns the element at the specified position in this list.
* *
@ -565,7 +563,7 @@ public class EnhancedLinkedList<E>
* this "outlining" performs best with both server and client VMs. * this "outlining" performs best with both server and client VMs.
*/ */
private String outOfBoundsMsg(int index) { private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size; return "Index: " + index + ", Size: " + size;
} }
private void checkElementIndex(int index) { private void checkElementIndex(int index) {
@ -578,6 +576,8 @@ public class EnhancedLinkedList<E>
throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
} }
// Search Operations
/** /**
* Returns the (non-null) Node at the specified element index. * Returns the (non-null) Node at the specified element index.
*/ */
@ -597,8 +597,6 @@ public class EnhancedLinkedList<E>
} }
} }
// Search Operations
/** /**
* Returns the index of the first occurrence of the specified element * Returns the index of the first occurrence of the specified element
* in this list, or -1 if this list does not contain the element. * in this list, or -1 if this list does not contain the element.
@ -643,6 +641,8 @@ public class EnhancedLinkedList<E>
return null; return null;
} }
// Queue operations.
/** /**
* Returns the index of the last occurrence of the specified element * Returns the index of the last occurrence of the specified element
* in this list, or -1 if this list does not contain the element. * in this list, or -1 if this list does not contain the element.
@ -672,8 +672,6 @@ public class EnhancedLinkedList<E>
return -1; return -1;
} }
// Queue operations.
/** /**
* Retrieves, but does not remove, the head (first element) of this list. * Retrieves, but does not remove, the head (first element) of this list.
* *
@ -718,6 +716,8 @@ public class EnhancedLinkedList<E>
return removeFirst(); return removeFirst();
} }
// Deque operations
/** /**
* Adds the specified element as the tail (last element) of this list. * Adds the specified element as the tail (last element) of this list.
* *
@ -729,7 +729,6 @@ public class EnhancedLinkedList<E>
return add(e); return add(e);
} }
// Deque operations
/** /**
* Inserts the specified element at the front of this list. * Inserts the specified element at the front of this list.
* *
@ -879,7 +878,7 @@ public class EnhancedLinkedList<E>
* Returns a list-iterator of the elements in this list (in proper * Returns a list-iterator of the elements in this list (in proper
* sequence), starting at the specified position in the list. * sequence), starting at the specified position in the list.
* Obeys the general contract of {@code List.listIterator(int)}.<p> * Obeys the general contract of {@code List.listIterator(int)}.<p>
* * <p>
* The list-iterator is <i>fail-fast</i>: if the list is structurally * The list-iterator is <i>fail-fast</i>: if the list is structurally
* modified at any time after the Iterator is created, in any way except * modified at any time after the Iterator is created, in any way except
* through the list-iterator's own {@code remove} or {@code add} * through the list-iterator's own {@code remove} or {@code add}
@ -901,6 +900,286 @@ public class EnhancedLinkedList<E>
return new ListItr(index); return new ListItr(index);
} }
/**
* @since 1.6
*/
public Iterator<E> descendingIterator() {
return new DescendingIterator();
}
@SuppressWarnings("unchecked")
private EnhancedLinkedList<E> superClone() {
try {
return (EnhancedLinkedList<E>) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
/**
* Returns a shallow copy of this {@code LinkedList}. (The elements
* themselves are not cloned.)
*
* @return a shallow copy of this {@code LinkedList} instance
*/
@Override
public Object clone() {
EnhancedLinkedList<E> clone = superClone();
// Put clone into "virgin" state
clone.first = clone.last = null;
clone.size = 0;
clone.modCount = 0;
// Initialize clone with our elements
for (Node<E> x = first; x != null; x = x.next)
clone.add(x.item);
return clone;
}
/**
* Returns an array containing all of the elements in this list
* in proper sequence (from first to last element).
*
* <p>The returned array will be "safe" in that no references to it are
* maintained by this list. (In other words, this method must allocate
* a new array). The caller is thus free to modify the returned array.
*
* <p>This method acts as bridge between array-based and collection-based
* APIs.
*
* @return an array containing all of the elements in this list
* in proper sequence
*/
public Object[] toArray() {
Object[] result = new Object[size];
int i = 0;
for (Node<E> x = first; x != null; x = x.next)
result[i++] = x.item;
return result;
}
/**
* Returns an array containing all of the elements in this list in
* proper sequence (from first to last element); the runtime type of
* the returned array is that of the specified array. If the list fits
* in the specified array, it is returned therein. Otherwise, a new
* array is allocated with the runtime type of the specified array and
* the size of this list.
*
* <p>If the list fits in the specified array with room to spare (i.e.,
* the array has more elements than the list), the element in the array
* immediately following the end of the list is set to {@code null}.
* (This is useful in determining the length of the list <i>only</i> if
* the caller knows that the list does not contain any null elements.)
*
* <p>Like the {@link #toArray()} method, this method acts as bridge between
* array-based and collection-based APIs. Further, this method allows
* precise control over the runtime type of the output array, and may,
* under certain circumstances, be used to save allocation costs.
*
* <p>Suppose {@code x} is a list known to contain only strings.
* The following code can be used to dump the list into a newly
* allocated array of {@code String}:
*
* <pre>
* String[] y = x.toArray(new String[0]);</pre>
* <p>
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
*
* @param a the array into which the elements of the list are to
* be stored, if it is big enough; otherwise, a new array of the
* same runtime type is allocated for this purpose.
* @return an array containing the elements of the list
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in
* this list
* @throws NullPointerException if the specified array is null
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size)
a = (T[]) java.lang.reflect.Array.newInstance(
a.getClass().getComponentType(), size);
int i = 0;
Object[] result = a;
for (Node<E> x = first; x != null; x = x.next)
result[i++] = x.item;
if (a.length > size)
a[size] = null;
return a;
}
/**
* Saves the state of this {@code LinkedList} instance to a stream
* (that is, serializes it).
*
* @serialData The size of the list (the number of elements it
* contains) is emitted (int), followed by all of its
* elements (each an Object) in the proper order.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out any hidden serialization magic
s.defaultWriteObject();
// Write out size
s.writeInt(size);
// Write out all elements in the proper order.
for (Node<E> x = first; x != null; x = x.next)
s.writeObject(x.item);
}
/**
* Reconstitutes this {@code LinkedList} instance from a stream
* (that is, deserializes it).
*/
@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in any hidden serialization magic
s.defaultReadObject();
// Read in size
int size = s.readInt();
// Read in all elements in the proper order.
for (int i = 0; i < size; i++)
linkLast((E) s.readObject());
}
/**
* Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
* and <em>fail-fast</em> {@link Spliterator} over the elements in this
* list.
*
* <p>The {@code Spliterator} reports {@link Spliterator#SIZED} and
* {@link Spliterator#ORDERED}. Overriding implementations should document
* the reporting of additional characteristic values.
*
* @return a {@code Spliterator} over the elements in this list
* @implNote The {@code Spliterator} additionally reports {@link Spliterator#SUBSIZED}
* and implements {@code trySplit} to permit limited parallelism..
* @since 1.8
*/
@Override
public Spliterator<E> spliterator() {
return new LLSpliterator<>(this, -1, 0);
}
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
/**
* A customized variant of Spliterators.IteratorSpliterator
*/
static final class LLSpliterator<E> implements Spliterator<E> {
static final int BATCH_UNIT = 1 << 10; // batch array size increment
static final int MAX_BATCH = 1 << 25; // max batch array size;
final EnhancedLinkedList<E> list; // null OK unless traversed
Node<E> current; // current node; null until initialized
int est; // size estimate; -1 until first needed
int expectedModCount; // initialized when est set
int batch; // batch size for splits
LLSpliterator(EnhancedLinkedList<E> list, int est, int expectedModCount) {
this.list = list;
this.est = est;
this.expectedModCount = expectedModCount;
}
int getEst() {
int s; // force initialization
final EnhancedLinkedList<E> lst;
if ((s = est) < 0) {
if ((lst = list) == null)
s = est = 0;
else {
expectedModCount = lst.modCount;
current = lst.first;
s = est = lst.size;
}
}
return s;
}
public long estimateSize() {
return getEst();
}
public Spliterator<E> trySplit() {
Node<E> p;
int s = getEst();
if (s > 1 && (p = current) != null) {
int n = batch + BATCH_UNIT;
if (n > s)
n = s;
if (n > MAX_BATCH)
n = MAX_BATCH;
Object[] a = new Object[n];
int j = 0;
do {
a[j++] = p.item;
} while ((p = p.next) != null && j < n);
current = p;
batch = j;
est = s - j;
return Spliterators.spliterator(a, 0, j, Spliterator.ORDERED);
}
return null;
}
public void forEachRemaining(Consumer<? super E> action) {
Node<E> p;
int n;
if (action == null) throw new NullPointerException();
if ((n = getEst()) > 0 && (p = current) != null) {
current = null;
est = 0;
do {
E e = p.item;
p = p.next;
action.accept(e);
} while (p != null && --n > 0);
}
if (list.modCount != expectedModCount)
throw new ConcurrentModificationException();
}
public boolean tryAdvance(Consumer<? super E> action) {
Node<E> p;
if (action == null) throw new NullPointerException();
if (getEst() > 0 && (p = current) != null) {
--est;
E e = p.item;
current = p.next;
action.accept(e);
if (list.modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
return false;
}
public int characteristics() {
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
}
private class ListItr implements ListIterator<E> { private class ListItr implements ListIterator<E> {
private Node<E> lastReturned; private Node<E> lastReturned;
private Node<E> next; private Node<E> next;
@ -1000,297 +1279,23 @@ public class EnhancedLinkedList<E>
} }
} }
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
/**
* @since 1.6
*/
public Iterator<E> descendingIterator() {
return new DescendingIterator();
}
/** /**
* Adapter to provide descending iterators via ListItr.previous * Adapter to provide descending iterators via ListItr.previous
*/ */
private class DescendingIterator implements Iterator<E> { private class DescendingIterator implements Iterator<E> {
private final ListItr itr = new ListItr(size()); private final ListItr itr = new ListItr(size());
public boolean hasNext() { public boolean hasNext() {
return itr.hasPrevious(); return itr.hasPrevious();
} }
public E next() { public E next() {
return itr.previous(); return itr.previous();
} }
public void remove() { public void remove() {
itr.remove(); itr.remove();
} }
} }
@SuppressWarnings("unchecked")
private EnhancedLinkedList<E> superClone() {
try {
return (EnhancedLinkedList<E>) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
/**
* Returns a shallow copy of this {@code LinkedList}. (The elements
* themselves are not cloned.)
*
* @return a shallow copy of this {@code LinkedList} instance
*/
@Override
public Object clone() {
EnhancedLinkedList<E> clone = superClone();
// Put clone into "virgin" state
clone.first = clone.last = null;
clone.size = 0;
clone.modCount = 0;
// Initialize clone with our elements
for (Node<E> x = first; x != null; x = x.next)
clone.add(x.item);
return clone;
}
/**
* Returns an array containing all of the elements in this list
* in proper sequence (from first to last element).
*
* <p>The returned array will be "safe" in that no references to it are
* maintained by this list. (In other words, this method must allocate
* a new array). The caller is thus free to modify the returned array.
*
* <p>This method acts as bridge between array-based and collection-based
* APIs.
*
* @return an array containing all of the elements in this list
* in proper sequence
*/
public Object[] toArray() {
Object[] result = new Object[size];
int i = 0;
for (Node<E> x = first; x != null; x = x.next)
result[i++] = x.item;
return result;
}
/**
* Returns an array containing all of the elements in this list in
* proper sequence (from first to last element); the runtime type of
* the returned array is that of the specified array. If the list fits
* in the specified array, it is returned therein. Otherwise, a new
* array is allocated with the runtime type of the specified array and
* the size of this list.
*
* <p>If the list fits in the specified array with room to spare (i.e.,
* the array has more elements than the list), the element in the array
* immediately following the end of the list is set to {@code null}.
* (This is useful in determining the length of the list <i>only</i> if
* the caller knows that the list does not contain any null elements.)
*
* <p>Like the {@link #toArray()} method, this method acts as bridge between
* array-based and collection-based APIs. Further, this method allows
* precise control over the runtime type of the output array, and may,
* under certain circumstances, be used to save allocation costs.
*
* <p>Suppose {@code x} is a list known to contain only strings.
* The following code can be used to dump the list into a newly
* allocated array of {@code String}:
*
* <pre>
* String[] y = x.toArray(new String[0]);</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
*
* @param a the array into which the elements of the list are to
* be stored, if it is big enough; otherwise, a new array of the
* same runtime type is allocated for this purpose.
* @return an array containing the elements of the list
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in
* this list
* @throws NullPointerException if the specified array is null
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size)
a = (T[])java.lang.reflect.Array.newInstance(
a.getClass().getComponentType(), size);
int i = 0;
Object[] result = a;
for (Node<E> x = first; x != null; x = x.next)
result[i++] = x.item;
if (a.length > size)
a[size] = null;
return a;
}
private static final long serialVersionUID = 876323262645176354L;
/**
* Saves the state of this {@code LinkedList} instance to a stream
* (that is, serializes it).
*
* @serialData The size of the list (the number of elements it
* contains) is emitted (int), followed by all of its
* elements (each an Object) in the proper order.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out any hidden serialization magic
s.defaultWriteObject();
// Write out size
s.writeInt(size);
// Write out all elements in the proper order.
for (Node<E> x = first; x != null; x = x.next)
s.writeObject(x.item);
}
/**
* Reconstitutes this {@code LinkedList} instance from a stream
* (that is, deserializes it).
*/
@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in any hidden serialization magic
s.defaultReadObject();
// Read in size
int size = s.readInt();
// Read in all elements in the proper order.
for (int i = 0; i < size; i++)
linkLast((E)s.readObject());
}
/**
* Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
* and <em>fail-fast</em> {@link Spliterator} over the elements in this
* list.
*
* <p>The {@code Spliterator} reports {@link Spliterator#SIZED} and
* {@link Spliterator#ORDERED}. Overriding implementations should document
* the reporting of additional characteristic values.
*
* @implNote
* The {@code Spliterator} additionally reports {@link Spliterator#SUBSIZED}
* and implements {@code trySplit} to permit limited parallelism..
*
* @return a {@code Spliterator} over the elements in this list
* @since 1.8
*/
@Override
public Spliterator<E> spliterator() {
return new LLSpliterator<>(this, -1, 0);
}
/** A customized variant of Spliterators.IteratorSpliterator */
static final class LLSpliterator<E> implements Spliterator<E> {
static final int BATCH_UNIT = 1 << 10; // batch array size increment
static final int MAX_BATCH = 1 << 25; // max batch array size;
final EnhancedLinkedList<E> list; // null OK unless traversed
Node<E> current; // current node; null until initialized
int est; // size estimate; -1 until first needed
int expectedModCount; // initialized when est set
int batch; // batch size for splits
LLSpliterator(EnhancedLinkedList<E> list, int est, int expectedModCount) {
this.list = list;
this.est = est;
this.expectedModCount = expectedModCount;
}
int getEst() {
int s; // force initialization
final EnhancedLinkedList<E> lst;
if ((s = est) < 0) {
if ((lst = list) == null)
s = est = 0;
else {
expectedModCount = lst.modCount;
current = lst.first;
s = est = lst.size;
}
}
return s;
}
public long estimateSize() { return getEst(); }
public Spliterator<E> trySplit() {
Node<E> p;
int s = getEst();
if (s > 1 && (p = current) != null) {
int n = batch + BATCH_UNIT;
if (n > s)
n = s;
if (n > MAX_BATCH)
n = MAX_BATCH;
Object[] a = new Object[n];
int j = 0;
do { a[j++] = p.item; } while ((p = p.next) != null && j < n);
current = p;
batch = j;
est = s - j;
return Spliterators.spliterator(a, 0, j, Spliterator.ORDERED);
}
return null;
}
public void forEachRemaining(Consumer<? super E> action) {
Node<E> p; int n;
if (action == null) throw new NullPointerException();
if ((n = getEst()) > 0 && (p = current) != null) {
current = null;
est = 0;
do {
E e = p.item;
p = p.next;
action.accept(e);
} while (p != null && --n > 0);
}
if (list.modCount != expectedModCount)
throw new ConcurrentModificationException();
}
public boolean tryAdvance(Consumer<? super E> action) {
Node<E> p;
if (action == null) throw new NullPointerException();
if (getEst() > 0 && (p = current) != null) {
--est;
E e = p.item;
current = p.next;
action.accept(e);
if (list.modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
return false;
}
public int characteristics() {
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
}
} }

View File

@ -48,16 +48,16 @@ object BlastingCrisis : Plugin() {
Location(Bukkit.getWorlds().first(), x.toDouble(), y.toDouble(), z.toDouble()) Location(Bukkit.getWorlds().first(), x.toDouble(), y.toDouble(), z.toDouble())
val teamRed = MapTeam( val teamRed = MapTeam(
"红队", name = "红队",
ChatColor.RED, color = ChatColor.RED,
location(0, 72, -44), spawn = location(0, 72, -44),
location(0, 72, -44), villager = location(0, 72, -44),
location(-8, 73, -47), upgrade = location(-8, 73, -47),
Area(location(14, 72, -48), location(-14, 78, -34)), home = Area(location(14, 72, -48), location(-14, 78, -34)),
Area(location(-13, 78, -33), location(13, 72, -33)), wall = Area(location(-13, 78, -33), location(13, 72, -33)),
Area(location(-13, 78, -32), location(13, 72, -1)), mine = Area(location(-13, 78, -32), location(13, 72, -1)),
Area(location(7, 72, -45), location(9, 74, -48)), teleport = Area(location(7, 72, -45), location(9, 74, -48)),
listOf( sides = listOf(
Area(location(15, 72, -1), location(19, 78, -48)), Area(location(-19, 78, -48), location(-15, 72, -1)) Area(location(15, 72, -1), location(19, 78, -48)), Area(location(-19, 78, -48), location(-15, 72, -1))
), ),
) )
@ -70,7 +70,8 @@ object BlastingCrisis : Plugin() {
Area(location(-14, 72, 48), location(14, 78, 34)), Area(location(-14, 72, 48), location(14, 78, 34)),
Area(location(13, 78, 33), location(-13, 72, 33)), Area(location(13, 78, 33), location(-13, 72, 33)),
Area(location(13, 78, 32), location(-13, 72, 1)), Area(location(13, 78, 32), location(-13, 72, 1)),
Area(location(-7, 72, 45), location(-9, 74, 48)), Area(location(-7, 71, 48), location(-9, 71, 46)),
// Area(location(-7, 72, 45), location(-9, 74, 48)),
listOf( listOf(
Area(location(-15, 72, 1), location(-19, 78, 48)), Area(location(19, 78, 48), location(15, 72, 1)) Area(location(-15, 72, 1), location(-19, 78, 48)), Area(location(19, 78, 48), location(15, 72, 1))
), ),

View File

@ -2,8 +2,10 @@ package cc.maxmc.blastingcrisis.command
import cc.maxmc.blastingcrisis.game.Game import cc.maxmc.blastingcrisis.game.Game
import cc.maxmc.blastingcrisis.game.GameOreGenerator import cc.maxmc.blastingcrisis.game.GameOreGenerator
import cc.maxmc.blastingcrisis.game.GamePlaceBreakRule.MatchResult
import cc.maxmc.blastingcrisis.game.GameState import cc.maxmc.blastingcrisis.game.GameState
import cc.maxmc.blastingcrisis.misc.Area import cc.maxmc.blastingcrisis.misc.Area
import cc.maxmc.blastingcrisis.misc.GameManager
import cc.maxmc.blastingcrisis.misc.UniArea import cc.maxmc.blastingcrisis.misc.UniArea
import cc.maxmc.blastingcrisis.packet.BEntityVillager import cc.maxmc.blastingcrisis.packet.BEntityVillager
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
@ -17,11 +19,25 @@ import taboolib.module.configuration.Configuration
import taboolib.platform.BukkitPlugin import taboolib.platform.BukkitPlugin
import taboolib.platform.util.sendActionBar import taboolib.platform.util.sendActionBar
import java.io.File import java.io.File
import java.util.*
import cc.maxmc.blastingcrisis.misc.debug as debuglog
object DebugCommand { object DebugCommand {
lateinit var game: Game lateinit var game: Game
lateinit var villager: BEntityVillager lateinit var villager: BEntityVillager
var autoRespawn = false
val builders = ArrayList<UUID>()
private val init by lazy {
// allow builders
debuglog("init builder rule")
GameManager.currentGame.placeBreakRule.addRuleFirst("builder") { (player, _, _, _) ->
// cc.maxmc.blastingcrisis.misc.debug("matching builder rule")
if (builders.contains(player.uniqueId)) MatchResult.ALLOW else MatchResult.DEFAULT
}
}
fun debug(cmd: String) = command(cmd) { fun debug(cmd: String) = command(cmd) {
literal("game") { literal("game") {
literal("join") { literal("join") {
execute<Player> { sender, _, _ -> execute<Player> { sender, _, _ ->
@ -80,7 +96,15 @@ object DebugCommand {
literal("respawn") { literal("respawn") {
execute<Player> { sender, _, _ -> execute<Player> { sender, _, _ ->
villager.spawnForPlayer(sender) villager.removeViewer(sender)
villager.addViewer(sender)
}
}
literal("autoRespawn") {
execute<Player> { sender, _, _ ->
autoRespawn = !autoRespawn
sender.sendMessage("Auto Respawn is now $autoRespawn.")
} }
} }
@ -129,5 +153,18 @@ object DebugCommand {
}, 60 * 20) }, 60 * 20)
} }
} }
literal("build_mode") {
execute<Player> { sender, _, _ ->
init
if (builders.contains(sender.uniqueId)) {
builders.remove(sender.uniqueId)
sender.sendMessage("U r no longer in build mode")
return@execute
}
sender.sendMessage("U r now in build mode")
builders.add(sender.uniqueId)
}
}
} }
} }

View File

@ -1,9 +1,13 @@
package cc.maxmc.blastingcrisis.debug package cc.maxmc.blastingcrisis.debug
import cc.maxmc.blastingcrisis.command.DebugCommand
import cc.maxmc.blastingcrisis.command.DebugCommand.villager
import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy
import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntityLiving import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntityLiving
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.event.player.PlayerRespawnEvent
import taboolib.common.platform.event.SubscribeEvent import taboolib.common.platform.event.SubscribeEvent
import taboolib.common.platform.function.submit
import taboolib.library.reflex.Reflex.Companion.getProperty import taboolib.library.reflex.Reflex.Companion.getProperty
import taboolib.module.nms.PacketSendEvent import taboolib.module.nms.PacketSendEvent
import taboolib.platform.BukkitPlugin import taboolib.platform.BukkitPlugin
@ -29,4 +33,15 @@ object DListener {
} }
} }
} }
@SubscribeEvent
fun debugRespawn(respawnE: PlayerRespawnEvent) {
if (DebugCommand.autoRespawn) {
submit(delay = 1L) {
villager.removeViewer(respawnE.player)
"Respawning".broadcast()
villager.addViewer(respawnE.player)
}
}
}
} }

View File

@ -32,6 +32,10 @@ class Game(
} }
fun join(player: Player) { fun join(player: Player) {
if (players.map { it.uniqueId }.contains(player.uniqueId)) {
player.sendLang("game_already_join")
return
}
players += player players += player
broadcast { broadcast {
it.sendLang("game_join", player.name) it.sendLang("game_join", player.name)
@ -54,14 +58,16 @@ class Game(
} }
fun respawnPlayer(player: Player) { fun respawnPlayer(player: Player) {
submit(delay = 1L) {
teams.forEach { it.villager.respawn(player) } teams.forEach { it.villager.respawn(player) }
} }
}
fun start() { fun start() {
debug("game ${map.name} started.") debug("game ${map.name} started.")
placeBreakRule.loadDefaultRule() placeBreakRule.loadDefaultRule()
// startOreGen() startOreGen()
// startItemGen() startItemGen()
state = GameState.START state = GameState.START
timer.startTimer() timer.startTimer()
timer.submitEvent("wall_fall", Duration.ofMinutes(1)) { timer.submitEvent("wall_fall", Duration.ofMinutes(1)) {
@ -115,12 +121,13 @@ class Game(
return return
} }
broadcast { it.sendLang("game_end") } broadcast {
it.sendLang("game_end")
}
//TODO restart game logic //TODO restart game logic
} }
fun broadcast(action: (Player) -> Unit) { fun broadcast(action: (Player) -> Unit) {
players.forEach(action) players.forEach(action)
} }
} }

View File

@ -15,17 +15,19 @@ typealias PlaceBreakRule = (GamePlaceBreakRule.GamePlaceBreakEvent) -> GamePlace
class GamePlaceBreakRule(val game: Game) { class GamePlaceBreakRule(val game: Game) {
enum class ActionType { enum class ActionType {
PLACE, PLACE, BREAK
BREAK
} }
enum class MatchResult { enum class MatchResult {
DEFAULT, DEFAULT, ALLOW, DENY
ALLOW,
DENY
} }
data class GamePlaceBreakEvent(val player: Player, val actionType: ActionType, val loc: Location, val type: XMaterial) data class GamePlaceBreakEvent(
val player: Player,
val actionType: ActionType,
val loc: Location,
val type: XMaterial
)
private val rules = HashMap<String, PlaceBreakRule>() private val rules = HashMap<String, PlaceBreakRule>()
private val rulesPriority = EnhancedLinkedList<String>() private val rulesPriority = EnhancedLinkedList<String>()
@ -52,25 +54,21 @@ class GamePlaceBreakRule(val game: Game) {
} }
fun addRuleLast( fun addRuleLast(
name: String, name: String, rule: PlaceBreakRule
rule: PlaceBreakRule
) { ) {
recordRule(name, rule) recordRule(name, rule)
rulesPriority.addLast(name) rulesPriority.addLast(name)
} }
fun addRuleFirst( fun addRuleFirst(
name: String, name: String, rule: PlaceBreakRule
rule: PlaceBreakRule
) { ) {
recordRule(name, rule) recordRule(name, rule)
rulesPriority.addFirst(name) rulesPriority.addFirst(name)
} }
fun addRuleBefore( fun addRuleBefore(
base: String, base: String, name: String, rule: PlaceBreakRule
name: String,
rule: PlaceBreakRule
) { ) {
recordRule(name, rule) recordRule(name, rule)
rulesPriority.addBefore(base, name) rulesPriority.addBefore(base, name)
@ -78,9 +76,7 @@ class GamePlaceBreakRule(val game: Game) {
fun addRuleAfter( fun addRuleAfter(
base: String, base: String, name: String, rule: PlaceBreakRule
name: String,
rule: PlaceBreakRule
) { ) {
recordRule(name, rule) recordRule(name, rule)
rulesPriority.addAfter(base, name) rulesPriority.addAfter(base, name)
@ -100,12 +96,10 @@ class GamePlaceBreakRule(val game: Game) {
// allow enemy wall // allow enemy wall
addRuleLast("allow_wall_conditional") { (player, actionType, loc, _) -> addRuleLast("allow_wall_conditional") { (player, actionType, loc, _) ->
val team = player.team ?: return@addRuleLast MatchResult.DENY val team = player.team ?: return@addRuleLast MatchResult.DENY
val isWall = game.teams val isWall = game.teams.map {
.map {
it.teamInfo.wall.containsBlock(loc) it.teamInfo.wall.containsBlock(loc)
.also { result -> debug("area ${it.teamInfo.wall} contains $loc is $result") } .also { result -> debug("area ${it.teamInfo.wall} contains $loc is $result") }
} }.reduce { a, b -> a || b }
.reduce { a, b -> a || b }
if (!isWall) return@addRuleLast MatchResult.DEFAULT if (!isWall) return@addRuleLast MatchResult.DEFAULT
val isHome = team.teamInfo.wall.containsBlock(loc) val isHome = team.teamInfo.wall.containsBlock(loc)
if ((actionType == BREAK) xor isHome) MatchResult.ALLOW else MatchResult.DENY if ((actionType == BREAK) xor isHome) MatchResult.ALLOW else MatchResult.DENY
@ -115,16 +109,13 @@ class GamePlaceBreakRule(val game: Game) {
addRuleFirst("allow_tnt_conditional") { (player, actionType, loc, type) -> addRuleFirst("allow_tnt_conditional") { (player, actionType, loc, type) ->
if (type != XMaterial.TNT) return@addRuleFirst MatchResult.DEFAULT if (type != XMaterial.TNT) return@addRuleFirst MatchResult.DEFAULT
val team = player.team ?: return@addRuleFirst MatchResult.DENY val team = player.team ?: return@addRuleFirst MatchResult.DENY
val isHome = game.teams val isHome = game.teams.map {
.map {
it.teamInfo.home.containsBlock(loc) it.teamInfo.home.containsBlock(loc)
.also { result -> debug("area ${it.teamInfo.home} contains $loc is $result") } .also { result -> debug("area ${it.teamInfo.home} contains $loc is $result") }
} }.reduce { a, b -> a || b }
.reduce { a, b -> a || b }
if (!isHome) return@addRuleFirst MatchResult.DENY if (!isHome) return@addRuleFirst MatchResult.DENY
val isSelf = team.teamInfo.home.containsBlock(loc) val isSelf = team.teamInfo.home.containsBlock(loc)
if ((actionType == PLACE) xor isSelf) MatchResult.ALLOW else MatchResult.DENY if ((actionType == PLACE) xor isSelf) MatchResult.ALLOW else MatchResult.DENY
} }
} }
} }

View File

@ -29,9 +29,10 @@ class GameScoreboard(val game: Game) {
appendLine(player.asLangText("scoreboard_team_info", it.teamInfo.name, it.villager.health)) appendLine(player.asLangText("scoreboard_team_info", it.teamInfo.name, it.villager.health))
} }
} }
val eventName = player.asLangText("event_${event.second}")
player.asLangText( player.asLangText(
"scoreboard_start", "scoreboard_start",
event.second, eventName,
"${event.first.inWholeMinutes}:${event.first.inWholeSeconds}", "${event.first.inWholeMinutes}:${event.first.inWholeSeconds}",
teamMessage, teamMessage,
player.team?.villager?.health ?: throw IllegalStateException("player ${player.name} has no team."), player.team?.villager?.health ?: throw IllegalStateException("player ${player.name} has no team."),
@ -43,7 +44,5 @@ class GameScoreboard(val game: Game) {
} }
player.sendScoreboard(*scoreboardText.lines().toTypedArray()) player.sendScoreboard(*scoreboardText.lines().toTypedArray())
} }
} }

View File

@ -1,6 +1,7 @@
package cc.maxmc.blastingcrisis.game package cc.maxmc.blastingcrisis.game
import cc.maxmc.blastingcrisis.configuration.GlobalSettings import cc.maxmc.blastingcrisis.configuration.GlobalSettings
import cc.maxmc.blastingcrisis.misc.debug
import cc.maxmc.blastingcrisis.misc.toEntityLocation import cc.maxmc.blastingcrisis.misc.toEntityLocation
import cc.maxmc.blastingcrisis.packet.BEntityVillager import cc.maxmc.blastingcrisis.packet.BEntityVillager
import org.bukkit.Bukkit import org.bukkit.Bukkit
@ -42,6 +43,7 @@ class TeamVillager(private val team: GameTeam) {
} }
fun respawn(player: Player) { fun respawn(player: Player) {
debug("respawning for ${player.name}")
packetVillager.respawnForPlayer(player) packetVillager.respawnForPlayer(player)
} }

View File

@ -17,10 +17,12 @@ import org.bukkit.event.entity.ExplosionPrimeEvent
import org.bukkit.event.entity.FoodLevelChangeEvent import org.bukkit.event.entity.FoodLevelChangeEvent
import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.player.PlayerMoveEvent import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.event.player.PlayerQuitEvent
import org.bukkit.event.player.PlayerRespawnEvent import org.bukkit.event.player.PlayerRespawnEvent
import taboolib.common.platform.event.EventPriority import taboolib.common.platform.event.EventPriority
import taboolib.common.platform.event.SubscribeEvent import taboolib.common.platform.event.SubscribeEvent
import taboolib.library.xseries.XMaterial import taboolib.library.xseries.XMaterial
import taboolib.platform.util.buildItem
import taboolib.platform.util.sendLang import taboolib.platform.util.sendLang
object GameListener { object GameListener {
@ -57,7 +59,7 @@ object GameListener {
} }
} }
@SubscribeEvent @SubscribeEvent(priority = EventPriority.LOW)
fun onBreak(breakEvent: BlockBreakEvent) { fun onBreak(breakEvent: BlockBreakEvent) {
val loc = breakEvent.block.location ?: return val loc = breakEvent.block.location ?: return
val player = breakEvent.player ?: return val player = breakEvent.player ?: return
@ -72,7 +74,7 @@ object GameListener {
player.sendLang("game_cant_break_block") player.sendLang("game_cant_break_block")
} }
@SubscribeEvent @SubscribeEvent(priority = EventPriority.LOW)
fun onPlace(placeEvent: BlockPlaceEvent) { fun onPlace(placeEvent: BlockPlaceEvent) {
val loc = placeEvent.block.location ?: return val loc = placeEvent.block.location ?: return
val player = placeEvent.player ?: return val player = placeEvent.player ?: return
@ -90,11 +92,11 @@ object GameListener {
@SubscribeEvent @SubscribeEvent
fun onRespawn(respawnEvent: PlayerRespawnEvent) { fun onRespawn(respawnEvent: PlayerRespawnEvent) {
val team = respawnEvent.player.team ?: return // ignore none game player val team = respawnEvent.player.team ?: return // ignore none game player
GameManager.currentGame.respawnPlayer(respawnEvent.player)
respawnEvent.respawnLocation = team.teamInfo.spawn.toEntityLocation() respawnEvent.respawnLocation = team.teamInfo.spawn.toEntityLocation()
GameManager.currentGame.respawnPlayer(respawnEvent.player)
} }
// @SubscribeEvent // @SubscribeEvent
fun protectDamageBeforeGame(damageEvent: EntityDamageEvent) { fun protectDamageBeforeGame(damageEvent: EntityDamageEvent) {
if (damageEvent.entity !is Player) return // ignore none player entity if (damageEvent.entity !is Player) return // ignore none player entity
if (GameManager.currentGame.state.isStarted()) return if (GameManager.currentGame.state.isStarted()) return
@ -117,4 +119,25 @@ object GameListener {
tntPlace.block.type = Material.AIR tntPlace.block.type = Material.AIR
loc.world.spawnEntity(loc.clone().apply { y += 0.5 }, EntityType.PRIMED_TNT) loc.world.spawnEntity(loc.clone().apply { y += 0.5 }, EntityType.PRIMED_TNT)
} }
@SubscribeEvent
fun onLeft(leftEvent: PlayerQuitEvent) {
if (!GameManager.currentGame.players.contains(leftEvent.player)) return
GameManager.currentGame.leave(leftEvent.player)
}
private val ores = mapOf(Material.IRON_ORE to Material.IRON_INGOT, Material.GOLD_ORE to Material.GOLD_INGOT)
@SubscribeEvent(ignoreCancelled = true)
fun autoSmelt(breakEvent: BlockBreakEvent) {
if (!GameManager.currentGame.players.contains(breakEvent.player)) return
val type = breakEvent.block.type
val loc = breakEvent.block.location
if (!ores.containsKey(type)) return
debug("Auto Smelting: ${breakEvent.block.type}")
breakEvent.block.type = Material.AIR
breakEvent.isCancelled = true
loc.world.dropItemNaturally(loc.toEntityLocation().apply { y += 0.5 }, buildItem(ores[type]!!))
}
} }

View File

@ -32,9 +32,9 @@ class Area(loc1: Location, loc2: Location) : ConfigurationSerializable {
*/ */
fun contains(location: Location): Boolean { fun contains(location: Location): Boolean {
if (location.world != locTop.world) return false if (location.world != locTop.world) return false
if (location.x !in (locMin.x - 1)..(locTop.x + 1)) return false if (location.x !in (locMin.x)..(locTop.x + 1)) return false
if (location.y !in locMin.y..locTop.y + 1) return false if (location.y !in locMin.y..locTop.y + 1) return false
return location.z in (locMin.z - 1)..(locTop.z + 1) return location.z in (locMin.z)..(locTop.z + 1)
} }
fun containsBlock(location: Location): Boolean { fun containsBlock(location: Location): Boolean {

View File

@ -1,6 +1,7 @@
package cc.maxmc.blastingcrisis.packet package cc.maxmc.blastingcrisis.packet
import cc.maxmc.blastingcrisis.listener.BEntityInteract import cc.maxmc.blastingcrisis.listener.BEntityInteract
import cc.maxmc.blastingcrisis.misc.debug
import gnu.trove.TDecorators import gnu.trove.TDecorators
import gnu.trove.map.hash.TIntObjectHashMap import gnu.trove.map.hash.TIntObjectHashMap
import net.minecraft.server.v1_8_R3.* import net.minecraft.server.v1_8_R3.*
@ -73,9 +74,9 @@ abstract class BEntity(var loc: Location, val entityType: Int) {
} }
fun respawnForPlayer(player: Player) { fun respawnForPlayer(player: Player) {
println(viewers) debug(viewers.toString())
if (!viewers.contains(player)) return if (!viewers.contains(player)) return
println("Respawning?") debug("Respawning?")
removeViewer(player) removeViewer(player)
addViewer(player) addViewer(player)
} }

View File

@ -31,7 +31,6 @@ class BEntityVillager private constructor(loc: Location) : BEntity(loc, 120) {
} }
override fun DataWatcher.initEntity() { override fun DataWatcher.initEntity() {
a(6, 1.0f) // Health a(6, 1.0f) // Health
a(7, 0) // Potion Effect Color a(7, 0) // Potion Effect Color

View File

@ -1,4 +1,3 @@
# Time before game start # Time before game start
# Unit: second # Unit: second
time_to_start: 15 time_to_start: 15

Binary file not shown.