Added AbstractUserClass, fixes
- Fixed ID problem - Fixed connectWith - Other fixes and improvements
This commit is contained in:
parent
ced3bd10a4
commit
1497a487a4
5 changed files with 68 additions and 38 deletions
|
@ -0,0 +1,28 @@
|
|||
package buttondevteam.lib.player;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Specifies a {@link ChromaGamerBase} direct subclass which's abstract. For Minecraft data, use {@link PlayerClass}
|
||||
*
|
||||
* @author NorbiPeti
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Inherited
|
||||
public @interface AbstractUserClass {
|
||||
/**
|
||||
* Indicates which folder should the player files be saved in.
|
||||
*/
|
||||
String foldername();
|
||||
|
||||
/**
|
||||
* Indicates the class to create when connecting accounts.
|
||||
*/
|
||||
Class<?> prototype();
|
||||
}
|
|
@ -21,7 +21,10 @@ public abstract class ChromaGamerBase implements AutoCloseable {
|
|||
public static void RegisterPluginUserClass(Class<? extends ChromaGamerBase> userclass) {
|
||||
if (userclass.isAnnotationPresent(UserClass.class))
|
||||
playerTypes.put(userclass, userclass.getAnnotation(UserClass.class).foldername());
|
||||
else //<-- Really important
|
||||
else if (userclass.isAnnotationPresent(AbstractUserClass.class))
|
||||
playerTypes.put(userclass.getAnnotation(AbstractUserClass.class).prototype(),
|
||||
userclass.getAnnotation(AbstractUserClass.class).foldername());
|
||||
else // <-- Really important
|
||||
throw new RuntimeException("Class not registered as a user class! Use @UserClass or TBMCPlayerBase");
|
||||
}
|
||||
|
||||
|
@ -37,24 +40,24 @@ public abstract class ChromaGamerBase implements AutoCloseable {
|
|||
public static <T extends ChromaGamerBase> String getFolderForType(Class<T> cl) {
|
||||
if (cl.isAnnotationPresent(UserClass.class))
|
||||
return cl.getAnnotation(UserClass.class).foldername();
|
||||
throw new RuntimeException("Class not registered as a user class! Use @UserClass");
|
||||
else if (cl.isAnnotationPresent(AbstractUserClass.class))
|
||||
return cl.getAnnotation(AbstractUserClass.class).foldername();
|
||||
throw new RuntimeException("Class not registered as a user class! Use @UserClass or @AbstractUserClass");
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the filename for this player data. For example, for Minecraft-related data, use MC UUIDs, for Discord data, use Discord IDs, etc.<br>
|
||||
* This method returns the filename for this player data. For example, for Minecraft-related data, MC UUIDs, for Discord data, use Discord IDs, etc.<br>
|
||||
* <b>Does not include .yml</b>
|
||||
*/
|
||||
public abstract String getFileName();
|
||||
public final String getFileName() {
|
||||
return plugindata.getString(getFolder() + "_id");
|
||||
}
|
||||
|
||||
/**
|
||||
* Use {@link #data()} or {@link #data(String)} where possible; the 'id' must be always set
|
||||
*/
|
||||
protected YamlConfiguration plugindata;
|
||||
|
||||
public String getID() {
|
||||
return plugindata != null ? plugindata.getString("id") : null;
|
||||
}
|
||||
|
||||
/***
|
||||
* Loads a user from disk and returns the user object. Make sure to use the subclasses' methods, where possible, like {@link TBMCPlayerBase#getPlayer(java.util.UUID, Class)}
|
||||
*
|
||||
|
@ -69,7 +72,7 @@ public abstract class ChromaGamerBase implements AutoCloseable {
|
|||
final File file = new File(TBMC_PLAYERS_DIR + folder, fname + ".yml");
|
||||
file.getParentFile().mkdirs();
|
||||
obj.plugindata = YamlConfiguration.loadConfiguration(file);
|
||||
obj.plugindata.set(folder + "_id", obj.getID());
|
||||
obj.plugindata.set(folder + "_id", fname);
|
||||
return obj;
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("An error occured while loading a " + cl.getSimpleName() + "!", e);
|
||||
|
@ -110,13 +113,16 @@ public abstract class ChromaGamerBase implements AutoCloseable {
|
|||
// Set the ID, go through all linked files and connect them as well
|
||||
if (!playerTypes.containsKey(getClass()))
|
||||
throw new RuntimeException("Class not registered as a user class! Use TBMCCoreAPI.RegisterUserClass");
|
||||
plugindata.set(user.getFolder() + "_id", user.plugindata.getString("id"));
|
||||
final String ownFolder = user.getFolder();
|
||||
user.plugindata.set(ownFolder + "_id", plugindata.getString("id"));
|
||||
final String ownFolder = getFolder();
|
||||
user.plugindata.set(ownFolder + "_id", plugindata.getString(ownFolder + "_id"));
|
||||
final String userFolder = user.getFolder();
|
||||
plugindata.set(userFolder + "_id", user.plugindata.getString(userFolder + "_id"));
|
||||
Consumer<YamlConfiguration> sync = sourcedata -> {
|
||||
final String sourcefolder = sourcedata == plugindata ? ownFolder : user.getFolder();
|
||||
final String id = sourcedata.getString("id");
|
||||
final String sourcefolder = sourcedata == plugindata ? ownFolder : userFolder;
|
||||
final String id = sourcedata.getString(sourcefolder + "_id");
|
||||
for (Entry<Class<?>, String> entry : playerTypes.entrySet()) { // Set our ID in all files we can find, both from our connections and the new ones
|
||||
if (entry.getKey() == getClass() || entry.getKey() == user.getClass())
|
||||
continue;
|
||||
final String otherid = sourcedata.getString(entry.getValue() + "_id");
|
||||
if (otherid == null)
|
||||
continue;
|
||||
|
@ -157,13 +163,13 @@ public abstract class ChromaGamerBase implements AutoCloseable {
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends ChromaGamerBase> T getAs(Class<T> cl) { // TODO: Provide a way to use TBMCPlayerBase's loaded players
|
||||
//System.out.println("getAs cls: " + cl.getSimpleName() + " =? " + getClass().getSimpleName()); // TODO: TMP - Don't be tired when programming
|
||||
if (cl.getSimpleName().equals(getClass().getSimpleName()))
|
||||
return (T) this;
|
||||
String newfolder = getFolderForType(cl);
|
||||
if (newfolder == null)
|
||||
throw new RuntimeException("The specified class " + cl.getSimpleName() + " isn't registered!");
|
||||
System.out.println("getAs newfolder: " + newfolder);
|
||||
if (newfolder.equals(getFolder())) // If in the same folder, the same filename is used
|
||||
return getUser(getFileName(), cl);
|
||||
if (!plugindata.contains(newfolder + "_id"))
|
||||
return null;
|
||||
return getUser(plugindata.getString(newfolder + "_id"), cl);
|
||||
|
@ -173,6 +179,12 @@ public abstract class ChromaGamerBase implements AutoCloseable {
|
|||
return getFolderForType(getClass());
|
||||
}
|
||||
|
||||
private void ThrowIfNoUser() {
|
||||
if (!getClass().isAnnotationPresent(UserClass.class)
|
||||
&& !getClass().isAnnotationPresent(AbstractUserClass.class))
|
||||
throw new RuntimeException("Class not registered as a user class! Use @UserClass");
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private HashMap<String, PlayerData> datamap = new HashMap<>();
|
||||
|
||||
|
@ -183,8 +195,7 @@ public abstract class ChromaGamerBase implements AutoCloseable {
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> PlayerData<T> data(String sectionname) {
|
||||
if (!getClass().isAnnotationPresent(UserClass.class))
|
||||
throw new RuntimeException("Class not registered as a user class! Use @UserClass");
|
||||
ThrowIfNoUser();
|
||||
String mname = sectionname + "." + new Exception().getStackTrace()[2].getMethodName();
|
||||
if (!datamap.containsKey(mname))
|
||||
datamap.put(mname, new PlayerData<T>(mname, plugindata));
|
||||
|
@ -198,9 +209,7 @@ public abstract class ChromaGamerBase implements AutoCloseable {
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> PlayerData<T> data() {
|
||||
//System.out.println("Calling ChromaGamerBase data"); // TODO: TMP - Debugged for hours
|
||||
if (!getClass().isAnnotationPresent(UserClass.class))
|
||||
throw new RuntimeException("Class not registered as a user class! Use @UserClass");
|
||||
ThrowIfNoUser();
|
||||
String mname = new Exception().getStackTrace()[1].getMethodName();
|
||||
if (!datamap.containsKey(mname))
|
||||
datamap.put(mname, new PlayerData<T>(mname, plugindata));
|
||||
|
@ -217,8 +226,7 @@ public abstract class ChromaGamerBase implements AutoCloseable {
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends Enum<T>> EnumPlayerData<T> dataEnum(String sectionname, Class<T> cl) {
|
||||
if (!getClass().isAnnotationPresent(UserClass.class))
|
||||
throw new RuntimeException("Class not registered as a user class! Use @UserClass");
|
||||
ThrowIfNoUser();
|
||||
String mname = sectionname + "." + new Exception().getStackTrace()[2].getMethodName();
|
||||
if (!dataenummap.containsKey(mname))
|
||||
dataenummap.put(mname, new EnumPlayerData<T>(mname, plugindata, cl));
|
||||
|
@ -232,8 +240,7 @@ public abstract class ChromaGamerBase implements AutoCloseable {
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends Enum<T>> EnumPlayerData<T> dataEnum(Class<T> cl) {
|
||||
if (!getClass().isAnnotationPresent(UserClass.class))
|
||||
throw new RuntimeException("Class not registered as a user class! Use @UserClass");
|
||||
ThrowIfNoUser();
|
||||
String mname = new Exception().getStackTrace()[1].getMethodName();
|
||||
if (!dataenummap.containsKey(mname))
|
||||
dataenummap.put(mname, new EnumPlayerData<T>(mname, plugindata, cl));
|
||||
|
|
|
@ -17,7 +17,7 @@ import com.palmergames.bukkit.towny.object.TownyUniverse;
|
|||
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
|
||||
@UserClass(foldername = "minecraft")
|
||||
@AbstractUserClass(foldername = "minecraft", prototype = TBMCPlayer.class)
|
||||
public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
||||
protected UUID uuid;
|
||||
|
||||
|
@ -31,19 +31,15 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
|||
}
|
||||
|
||||
public UUID getUUID() {
|
||||
if (uuid == null)
|
||||
uuid = UUID.fromString(getFileName());
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public PlayerData<String> PlayerName() {
|
||||
//System.out.println("Calling playername"); // TODO: TMP - The data will only get stored if it's changed
|
||||
return super.data();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileName() {
|
||||
return getUUID().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Use from a method with the name of the key. For example, use flair() for the enclosing method to save to and load from "flair"
|
||||
*
|
||||
|
@ -51,7 +47,6 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
|||
*/
|
||||
@Override
|
||||
protected <T> PlayerData<T> data() {
|
||||
//System.out.println("Calling TMBCPlayerBase data"); // TODO: TMP - Sigh
|
||||
return super.data(pluginname);
|
||||
}
|
||||
|
||||
|
@ -78,17 +73,17 @@ public abstract class TBMCPlayerBase extends ChromaGamerBase {
|
|||
public static <T extends TBMCPlayerBase> T getPlayer(UUID uuid, Class<T> cl) {
|
||||
if (playermap.containsKey(uuid + "-" + cl.getSimpleName()))
|
||||
return (T) playermap.get(uuid + "-" + cl.getSimpleName());
|
||||
//System.out.println("A");
|
||||
// System.out.println("A");
|
||||
try {
|
||||
T player;
|
||||
if (playermap.containsKey(uuid + "-" + TBMCPlayer.class.getSimpleName())) {
|
||||
//System.out.println("B"); - Don't program when tired
|
||||
// System.out.println("B"); - Don't program when tired
|
||||
player = cl.newInstance();
|
||||
player.plugindata = playermap.get(uuid + "-" + TBMCPlayer.class.getSimpleName()).plugindata;
|
||||
playermap.put(uuid + "-" + cl.getSimpleName(), player); // It will get removed on player quit
|
||||
} else
|
||||
player = ChromaGamerBase.getUser(uuid.toString(), cl);
|
||||
//System.out.println("C");
|
||||
// System.out.println("C");
|
||||
player.uuid = uuid;
|
||||
return player;
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -7,7 +7,7 @@ import java.lang.annotation.RetentionPolicy;
|
|||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Specifies a {@link ChromaGamerBase} direct subclass. For Minecraft data, use {@link PlayerClass}
|
||||
* Specifies a {@link ChromaGamerBase} direct subclass which can be instantiated. For Minecraft data, use {@link PlayerClass}
|
||||
*
|
||||
* @author NorbiPeti
|
||||
*
|
||||
|
|
|
@ -48,7 +48,7 @@ public class PlayerDataTest extends TestCase {
|
|||
try (TestPlayerClass p = TBMCPlayerBase.getPlayer(uuid, TestPlayerClass.class)) {
|
||||
p.PlayerName().set("Test");
|
||||
assertEquals("Test", p.PlayerName().get());
|
||||
p.testenum().set(TestEnum.A); // TODO: Fix enum saving
|
||||
p.testenum().set(TestEnum.A);
|
||||
assertEquals(TestEnum.A, p.testenum().get());
|
||||
// p.TestShort().set((short) 5);
|
||||
// assertEquals((short) 5, (short) (int) p.TestShort().get());
|
||||
|
|
Loading…
Reference in a new issue