-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for custom tags in item meta (#1366)
This supports tags added by plugins using Bukkit's PersistantDataContainer.
- Loading branch information
1 parent
6a7749c
commit 1f6deb1
Showing
14 changed files
with
544 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 4 additions & 0 deletions
4
src/main/java/com/laytonsmith/abstraction/MCNamespacedKey.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package com.laytonsmith.abstraction; | ||
|
||
public interface MCNamespacedKey extends AbstractionObject { | ||
} |
65 changes: 65 additions & 0 deletions
65
src/main/java/com/laytonsmith/abstraction/MCTagContainer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package com.laytonsmith.abstraction; | ||
|
||
import com.laytonsmith.abstraction.enums.MCTagType; | ||
|
||
import java.util.Set; | ||
|
||
/** | ||
* Minecraft NBT containers that can be used to read and modify tags in supported game objects. | ||
* This includes item meta, entities, block entities, chunks, worlds, etc. | ||
*/ | ||
public interface MCTagContainer extends AbstractionObject { | ||
|
||
/** | ||
* Returns whether the tag container does not contain any tags. | ||
* @return whether container is empty | ||
*/ | ||
boolean isEmpty(); | ||
|
||
/** | ||
* Gets a set of namespaced keys for each tag that exists in this container. (e.g. "namespace:key") | ||
* @return a set of keys | ||
*/ | ||
Set<MCNamespacedKey> getKeys(); | ||
|
||
/** | ||
* Returns the tag type with the given key. | ||
* MCTagType can be used to convert tags to and from MethodScript constructs. | ||
* Returns null if a tag with that key does not exist. | ||
* @param key the tag key | ||
* @return the type for the tag | ||
*/ | ||
MCTagType getType(MCNamespacedKey key); | ||
|
||
/** | ||
* Returns the tag value with the given key and tag type. | ||
* Returns null if a tag with that key and type does not exist. | ||
* @param key the tag key | ||
* @param type the tag type | ||
* @return the value for the tag | ||
*/ | ||
Object get(MCNamespacedKey key, MCTagType type); | ||
|
||
/** | ||
* Sets the tag value with the given key and tag type. | ||
* Throws an IllegalArgumentException if the type and value do not match. | ||
* @param key the tag key | ||
* @param type the tag type | ||
* @param value the tag value | ||
*/ | ||
void set(MCNamespacedKey key, MCTagType type, Object value); | ||
|
||
/** | ||
* Deletes the tag with the given key from this container. | ||
* @param key the tag key | ||
*/ | ||
void remove(MCNamespacedKey key); | ||
|
||
/** | ||
* Creates a new tag container from this container context. | ||
* This can then be used to nest a tag container with the {@link #set} method. | ||
* @return a new tag container | ||
*/ | ||
MCTagContainer newContainer(); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCNamespacedKey.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.laytonsmith.abstraction.bukkit; | ||
|
||
import com.laytonsmith.abstraction.MCNamespacedKey; | ||
import org.bukkit.NamespacedKey; | ||
|
||
public class BukkitMCNamespacedKey implements MCNamespacedKey { | ||
|
||
NamespacedKey nsk; | ||
|
||
public BukkitMCNamespacedKey(NamespacedKey nsk) { | ||
this.nsk = nsk; | ||
} | ||
|
||
@Override | ||
public Object getHandle() { | ||
return this.nsk; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return this.nsk.toString(); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
return obj instanceof MCNamespacedKey && this.nsk.equals(((MCNamespacedKey) obj).getHandle()); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return this.nsk.hashCode(); | ||
} | ||
} |
157 changes: 157 additions & 0 deletions
157
src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCTagContainer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
package com.laytonsmith.abstraction.bukkit; | ||
|
||
import com.laytonsmith.abstraction.MCNamespacedKey; | ||
import com.laytonsmith.abstraction.MCTagContainer; | ||
import com.laytonsmith.abstraction.enums.MCTagType; | ||
import org.bukkit.NamespacedKey; | ||
import org.bukkit.persistence.PersistentDataContainer; | ||
import org.bukkit.persistence.PersistentDataType; | ||
|
||
import java.util.HashSet; | ||
import java.util.Set; | ||
|
||
public class BukkitMCTagContainer implements MCTagContainer { | ||
|
||
PersistentDataContainer pdc; | ||
|
||
public BukkitMCTagContainer(PersistentDataContainer pdc) { | ||
this.pdc = pdc; | ||
} | ||
|
||
@Override | ||
public MCTagContainer newContainer() { | ||
return new BukkitMCTagContainer(this.pdc.getAdapterContext().newPersistentDataContainer()); | ||
} | ||
|
||
@Override | ||
public boolean isEmpty() { | ||
return this.pdc.isEmpty(); | ||
} | ||
|
||
@Override | ||
public Set<MCNamespacedKey> getKeys() { | ||
Set<MCNamespacedKey> keys = new HashSet<>(); | ||
for(NamespacedKey key : this.pdc.getKeys()) { | ||
keys.add(new BukkitMCNamespacedKey(key)); | ||
} | ||
return keys; | ||
} | ||
|
||
@Override | ||
public MCTagType getType(MCNamespacedKey key) { | ||
NamespacedKey namespacedKey = (NamespacedKey) key.getHandle(); | ||
// Check tag types in order of most frequently used | ||
if(this.pdc.has(namespacedKey, PersistentDataType.STRING)) { | ||
return MCTagType.STRING; | ||
} else if(this.pdc.has(namespacedKey, PersistentDataType.INTEGER)) { | ||
return MCTagType.INTEGER; | ||
} else if(this.pdc.has(namespacedKey, PersistentDataType.BYTE)) { | ||
return MCTagType.BYTE; | ||
} else if(this.pdc.has(namespacedKey, PersistentDataType.DOUBLE)) { | ||
return MCTagType.DOUBLE; | ||
} else if(this.pdc.has(namespacedKey, PersistentDataType.LONG)) { | ||
return MCTagType.LONG; | ||
} else if(this.pdc.has(namespacedKey, PersistentDataType.FLOAT)) { | ||
return MCTagType.FLOAT; | ||
} else if(this.pdc.has(namespacedKey, PersistentDataType.TAG_CONTAINER)) { | ||
return MCTagType.TAG_CONTAINER; | ||
} else if(this.pdc.has(namespacedKey, PersistentDataType.BYTE_ARRAY)) { | ||
return MCTagType.BYTE_ARRAY; | ||
} else if(this.pdc.has(namespacedKey, PersistentDataType.SHORT)) { | ||
return MCTagType.SHORT; | ||
} else if(this.pdc.has(namespacedKey, PersistentDataType.INTEGER_ARRAY)) { | ||
return MCTagType.INTEGER_ARRAY; | ||
} else if(this.pdc.has(namespacedKey, PersistentDataType.LONG_ARRAY)) { | ||
return MCTagType.LONG_ARRAY; | ||
} else if(this.pdc.has(namespacedKey, PersistentDataType.TAG_CONTAINER_ARRAY)) { | ||
return MCTagType.TAG_CONTAINER_ARRAY; | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public Object get(MCNamespacedKey key, MCTagType type) { | ||
PersistentDataType bukkitType = GetPersistentDataType(type); | ||
Object value = this.pdc.get((NamespacedKey) key.getHandle(), bukkitType); | ||
if(value instanceof PersistentDataContainer) { | ||
return new BukkitMCTagContainer((PersistentDataContainer) value); | ||
} else if(value instanceof PersistentDataContainer[] concreteContainers) { | ||
MCTagContainer[] abstractContainers = new MCTagContainer[concreteContainers.length]; | ||
for(int i = 0; i < concreteContainers.length; i++) { | ||
abstractContainers[i] = new BukkitMCTagContainer(concreteContainers[i]); | ||
} | ||
return abstractContainers; | ||
} | ||
return value; | ||
} | ||
|
||
@Override | ||
public void set(MCNamespacedKey key, MCTagType type, Object value) { | ||
PersistentDataType bukkitType = GetPersistentDataType(type); | ||
if(value instanceof MCTagContainer) { | ||
value = ((MCTagContainer) value).getHandle(); | ||
} else if(value instanceof MCTagContainer[] abstractContainers) { | ||
PersistentDataContainer[] concreteContainers = new PersistentDataContainer[abstractContainers.length]; | ||
for(int i = 0; i < abstractContainers.length; i++) { | ||
concreteContainers[i] = (PersistentDataContainer) abstractContainers[i].getHandle(); | ||
} | ||
value = concreteContainers; | ||
} | ||
this.pdc.set((NamespacedKey) key.getHandle(), bukkitType, value); | ||
} | ||
|
||
@Override | ||
public void remove(MCNamespacedKey key) { | ||
this.pdc.remove((NamespacedKey) key.getHandle()); | ||
} | ||
|
||
private static PersistentDataType GetPersistentDataType(MCTagType type) { | ||
switch(type) { | ||
case BYTE: | ||
return PersistentDataType.BYTE; | ||
case BYTE_ARRAY: | ||
return PersistentDataType.BYTE_ARRAY; | ||
case DOUBLE: | ||
return PersistentDataType.DOUBLE; | ||
case FLOAT: | ||
return PersistentDataType.FLOAT; | ||
case INTEGER: | ||
return PersistentDataType.INTEGER; | ||
case INTEGER_ARRAY: | ||
return PersistentDataType.INTEGER_ARRAY; | ||
case LONG: | ||
return PersistentDataType.LONG; | ||
case LONG_ARRAY: | ||
return PersistentDataType.LONG_ARRAY; | ||
case SHORT: | ||
return PersistentDataType.SHORT; | ||
case STRING: | ||
return PersistentDataType.STRING; | ||
case TAG_CONTAINER: | ||
return PersistentDataType.TAG_CONTAINER; | ||
case TAG_CONTAINER_ARRAY: | ||
return PersistentDataType.TAG_CONTAINER_ARRAY; | ||
} | ||
throw new IllegalArgumentException("Invalid persistent data type: " + type.name()); | ||
} | ||
|
||
@Override | ||
public Object getHandle() { | ||
return this.pdc; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
return o instanceof MCTagContainer && this.pdc.equals(((MCTagContainer) o).getHandle()); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return this.pdc.hashCode(); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return this.pdc.toString(); | ||
} | ||
} |
Oops, something went wrong.