diff --git a/ChestsPlusPlus-Database/pom.xml b/ChestsPlusPlus-Database/pom.xml
new file mode 100644
index 0000000..9361a15
--- /dev/null
+++ b/ChestsPlusPlus-Database/pom.xml
@@ -0,0 +1,97 @@
+
+
+
+ ChestsPlusPlus-Parent
+ com.jamesdpeters.minecraft.chests
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ ChestsPlusPlus-Database
+
+
+ 16
+ 16
+
+
+
+
+ maven-google
+ https://maven.google.com
+
+
+
+
+
+ org.hibernate
+ hibernate-core
+ 5.5.4.Final
+
+
+ org.hibernate
+ hibernate-jpamodelgen
+ 5.5.4.Final
+
+
+
+
+ com.h2database
+ h2
+ 1.4.200
+
+
+ org.projectlombok
+ lombok
+ 1.18.20
+
+
+
+ org.reflections
+ reflections
+ 0.9.12
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+
+
+ org.hibernate
+ hibernate-jpamodelgen
+ 5.5.4.Final
+
+
+ org.projectlombok
+ lombok
+ 1.18.20
+
+
+
+
+
+ maven-assembly-plugin
+
+
+ package
+
+ single
+
+
+
+
+
+ jar-with-dependencies
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ChestsPlusPlus-Database/src/main/java/com/jamesdpeters/minecraft/database/hibernate/Database.java b/ChestsPlusPlus-Database/src/main/java/com/jamesdpeters/minecraft/database/hibernate/Database.java
new file mode 100644
index 0000000..c6c5075
--- /dev/null
+++ b/ChestsPlusPlus-Database/src/main/java/com/jamesdpeters/minecraft/database/hibernate/Database.java
@@ -0,0 +1,62 @@
+package com.jamesdpeters.minecraft.database.hibernate;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Consumer;
+
+public class Database {
+
+ private final Class clazz;
+
+ public Database(Class clazz) {
+ this.clazz = clazz;
+ }
+
+ //** MEMBER METHODS **/
+ public void saveEntity(Object object) {
+ runTransaction(entityManager -> entityManager.persist(object));
+ }
+
+ public Optional findEntity(Object id) {
+ return Optional.ofNullable(HibernateUtil.getEntityManager().find(clazz, id));
+ }
+
+ public List findAll() {
+ var q = HibernateUtil.getCriteriaQuery(clazz);
+ q.select(q.from(clazz));
+ return HibernateUtil.getEntityManager().createQuery(q).getResultList();
+ }
+
+ public List findAll(String sql) {
+ var q = HibernateUtil.getEntityManager().createQuery(sql, clazz);
+ return q.getResultList();
+ }
+
+ public TypedQuery getQuery(String sql) {
+ return HibernateUtil.getEntityManager().createQuery(sql, clazz);
+ }
+
+ public void runTransaction(Consumer sessionConsumer) {
+ var entityManager = HibernateUtil.getEntityManager();
+ var transaction = entityManager.getTransaction();
+ try {
+ transaction.begin();
+ sessionConsumer.accept(entityManager);
+ transaction.commit();
+ } catch (RuntimeException e) {
+ transaction.rollback();
+ throw e;
+ }
+ }
+
+ public void refresh(T entity) {
+ HibernateUtil.getEntityManager().refresh(entity);
+ }
+
+ public Class clazz() {
+ return clazz;
+ }
+
+}
diff --git a/ChestsPlusPlus-Database/src/main/java/com/jamesdpeters/minecraft/database/hibernate/HibernateUtil.java b/ChestsPlusPlus-Database/src/main/java/com/jamesdpeters/minecraft/database/hibernate/HibernateUtil.java
new file mode 100644
index 0000000..2fcd3ba
--- /dev/null
+++ b/ChestsPlusPlus-Database/src/main/java/com/jamesdpeters/minecraft/database/hibernate/HibernateUtil.java
@@ -0,0 +1,76 @@
+package com.jamesdpeters.minecraft.database.hibernate;
+
+import lombok.experimental.UtilityClass;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+
+import javax.persistence.EntityManager;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import java.io.File;
+import java.util.Arrays;
+import java.util.Properties;
+
+@UtilityClass
+public class HibernateUtil {
+
+ private static SessionFactory sessionFactory;
+ private static EntityManager entityManager;
+
+ private static File databaseDirectory;
+
+ private static Properties hibernateProperties() {
+ Properties properties = new Properties();
+ properties.put(Environment.DRIVER, "org.h2.Driver");
+ properties.put(Environment.URL, "jdbc:h2:file:"+databaseDirectory.getAbsolutePath()+"/db;AUTO_SERVER=TRUE");
+ properties.put(Environment.USER, "sa");
+ properties.put(Environment.PASS, "sa");
+ properties.put(Environment.FORMAT_SQL, "true");
+ properties.put(Environment.DIALECT, "org.hibernate.dialect.H2Dialect");
+ properties.put(Environment.SHOW_SQL, "true");
+ properties.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread");
+ properties.put(Environment.HBM2DDL_AUTO, "update");
+ // properties.put(Environment.POOL_SIZE, "5");
+ return properties;
+ }
+
+ private static SessionFactory buildSessionFactory(Class>[] entities) {
+ try {
+ var config = new Configuration()
+ .addProperties(hibernateProperties())
+ .addPackage("com.jamesdpeters.minecraft.database.entities");
+ Arrays.stream(entities).forEach(config::addAnnotatedClass);
+ return config.buildSessionFactory();
+ } catch (Throwable ex) {
+ System.err.println("build SeesionFactory failed :" + ex);
+ throw new ExceptionInInitializerError(ex);
+ }
+ }
+
+ public void init(File databaseDirectory, Class>[] entities) {
+ HibernateUtil.databaseDirectory = databaseDirectory;
+ sessionFactory = buildSessionFactory(entities);
+ entityManager = sessionFactory.createEntityManager();
+ }
+
+ public EntityManager getEntityManager() {
+ return entityManager;
+ }
+
+ public CriteriaQuery getCriteriaQuery(Class clazz) {
+ return entityManager.getCriteriaBuilder().createQuery(clazz);
+ }
+
+ public CriteriaBuilder getCriteriaBuilder() {
+ return entityManager.getCriteriaBuilder();
+ }
+
+ public void close() {
+ if (sessionFactory != null)
+ sessionFactory.close();
+ if (entityManager != null)
+ entityManager.close();
+ }
+
+}
diff --git a/ChestsPlusPlus_Main/pom.xml b/ChestsPlusPlus_Main/pom.xml
index bd16a93..8511d5a 100644
--- a/ChestsPlusPlus_Main/pom.xml
+++ b/ChestsPlusPlus_Main/pom.xml
@@ -154,6 +154,14 @@
jar
compile
+
+
+
+
+
+
+
+
org.jetbrains
annotations
@@ -169,6 +177,12 @@
provided
+
+ com.jamesdpeters.minecraft.chests
+ ChestsPlusPlus-Database
+ 1.0-SNAPSHOT
+ jar-with-dependencies
+
@@ -190,6 +204,7 @@
net.wesjd:anvilgui*
org.bstats*:*
com.jamesdpeters.minecraft.chests
+ com.jamesdpeters*:*
diff --git a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/ChestsPlusPlus.java b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/ChestsPlusPlus.java
index 7f3f6fb..d64d8a6 100644
--- a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/ChestsPlusPlus.java
+++ b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/ChestsPlusPlus.java
@@ -5,6 +5,7 @@ import com.jamesdpeters.minecraft.chests.commands.AutoCraftCommand;
import com.jamesdpeters.minecraft.chests.commands.ChestLinkCommand;
import com.jamesdpeters.minecraft.chests.commands.ChestsPlusPlusCommand;
import com.jamesdpeters.minecraft.chests.crafting.Crafting;
+import com.jamesdpeters.minecraft.chests.database.DBUtil;
import com.jamesdpeters.minecraft.chests.lang.LangFileProperties;
import com.jamesdpeters.minecraft.chests.listeners.HopperListener;
import com.jamesdpeters.minecraft.chests.listeners.InventoryListener;
@@ -27,6 +28,7 @@ import com.jamesdpeters.minecraft.chests.serialize.SpigotConfig;
import com.jamesdpeters.minecraft.chests.storage.autocraft.AutoCraftingStorage;
import com.jamesdpeters.minecraft.chests.storage.chestlink.ChestLinkStorage;
import com.jamesdpeters.minecraft.chests.versionchecker.UpdateChecker;
+import com.jamesdpeters.minecraft.database.hibernate.HibernateUtil;
import fr.minuskube.inv.InventoryManager;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
@@ -42,6 +44,8 @@ import org.bukkit.plugin.java.annotation.plugin.Description;
import org.bukkit.plugin.java.annotation.plugin.Plugin;
import org.bukkit.plugin.java.annotation.plugin.author.Author;
+import java.util.UUID;
+
@Plugin(name = "ChestsPlusPlus", version = BuildConstants.VERSION)
@ApiVersion(ApiVersion.Target.v1_14)
@Description(value = "Minecraft Spigot mod that enhances chests and hoppers, with ChestLinks and Hopper filters!")
@@ -83,7 +87,6 @@ public class ChestsPlusPlus extends JavaPlugin {
}
- @SuppressWarnings("ConstantConditions")
@Override
public void onEnable() {
int pluginId = 7166;
@@ -133,6 +136,20 @@ public class ChestsPlusPlus extends JavaPlugin {
// Remove armour stands if disabled
Utils.fixEntities();
+ DBUtil.init();
+ var playerDb = DBUtil.PLAYER;
+ var partyDb = DBUtil.PARTIES;
+
+ var test = playerDb.findPlayer(UUID.fromString("e0e93eb6-2ca4-4ac2-803f-684ce0b69b2c"));
+ getLogger().info("Original parties: "+test.getOwnedParties());
+
+ var party = partyDb.findParty(test, "Test Party 2");
+ party = party == null ? partyDb.createParty(test, "Test Party 2") : party;
+
+ getLogger().info("Found party: "+party);
+ getLogger().info("Players parties: "+test.getOwnedParties());
+
+
//Load storages after load.
Bukkit.getScheduler().scheduleSyncDelayedTask(this, () -> {
Crafting.load();
@@ -153,6 +170,7 @@ public class ChestsPlusPlus extends JavaPlugin {
public void onDisable() {
super.onDisable();
Config.save();
+ HibernateUtil.close();
// //Remove entities that could have been left behind from bad save files/crashes etc.
// Utils.fixEntities();
}
diff --git a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/database/DBUtil.java b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/database/DBUtil.java
new file mode 100644
index 0000000..28e867a
--- /dev/null
+++ b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/database/DBUtil.java
@@ -0,0 +1,27 @@
+package com.jamesdpeters.minecraft.chests.database;
+
+import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
+import com.jamesdpeters.minecraft.chests.database.dao.PlayerDatabase;
+import com.jamesdpeters.minecraft.chests.database.dao.PlayerPartyDatabase;
+import com.jamesdpeters.minecraft.chests.database.entities.Player;
+import com.jamesdpeters.minecraft.chests.database.entities.PlayerParty;
+import com.jamesdpeters.minecraft.database.hibernate.HibernateUtil;
+
+public class DBUtil {
+
+ /**
+ * ALL HIBERNATE ENTITIES
+ */
+ private final static Class>[] entities = {
+ Player.class,
+ PlayerParty.class
+ };
+
+ public final static PlayerDatabase PLAYER = new PlayerDatabase();
+ public final static PlayerPartyDatabase PARTIES = new PlayerPartyDatabase();
+
+ public static void init() {
+ HibernateUtil.init(ChestsPlusPlus.PLUGIN.getDataFolder(), entities);
+ }
+
+}
diff --git a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/database/dao/PlayerDatabase.java b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/database/dao/PlayerDatabase.java
new file mode 100644
index 0000000..7a204a6
--- /dev/null
+++ b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/database/dao/PlayerDatabase.java
@@ -0,0 +1,22 @@
+package com.jamesdpeters.minecraft.chests.database.dao;
+
+import com.jamesdpeters.minecraft.chests.database.entities.Player;
+import com.jamesdpeters.minecraft.database.hibernate.Database;
+import org.bukkit.OfflinePlayer;
+
+import java.util.UUID;
+
+public class PlayerDatabase extends Database {
+
+ public PlayerDatabase() {
+ super(Player.class);
+ }
+
+ public Player findPlayer(UUID uuid) {
+ return findEntity(uuid).orElseGet(() -> new Player(uuid));
+ }
+
+ public Player findPlayer(OfflinePlayer player) {
+ return findPlayer(player.getUniqueId());
+ }
+}
diff --git a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/database/dao/PlayerPartyDatabase.java b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/database/dao/PlayerPartyDatabase.java
new file mode 100644
index 0000000..95e4b61
--- /dev/null
+++ b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/database/dao/PlayerPartyDatabase.java
@@ -0,0 +1,36 @@
+package com.jamesdpeters.minecraft.chests.database.dao;
+
+import com.jamesdpeters.minecraft.chests.database.DBUtil;
+import com.jamesdpeters.minecraft.chests.database.entities.Player;
+import com.jamesdpeters.minecraft.chests.database.entities.PlayerParty;
+import com.jamesdpeters.minecraft.database.hibernate.Database;
+
+public class PlayerPartyDatabase extends Database {
+
+ public PlayerPartyDatabase() {
+ super(PlayerParty.class);
+ }
+
+ public PlayerParty createParty(Player owner, String name) {
+ PlayerParty playerParty = findParty(owner, name);
+
+ if (playerParty != null)
+ return playerParty;
+
+ playerParty = new PlayerParty();
+ playerParty.setOwner(owner);
+ playerParty.setName(name);
+
+ saveEntity(playerParty);
+ DBUtil.PLAYER.refresh(owner);
+ return playerParty;
+ }
+
+ public PlayerParty findParty(Player owner, String name) {
+ var query = getQuery("from PlayerParty where owner.playerUUID = :ownerId and name = :name");
+ query.setParameter("ownerId", owner.getPlayerUUID());
+ query.setParameter("name", name);
+ return query.getSingleResult();
+ }
+
+}
diff --git a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/database/entities/Player.java b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/database/entities/Player.java
new file mode 100644
index 0000000..caf9e02
--- /dev/null
+++ b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/database/entities/Player.java
@@ -0,0 +1,40 @@
+package com.jamesdpeters.minecraft.chests.database.entities;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+import org.bukkit.Bukkit;
+import org.bukkit.OfflinePlayer;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+import javax.persistence.OneToMany;
+import java.util.List;
+import java.util.UUID;
+
+@Entity
+@Getter
+@ToString
+@NoArgsConstructor
+public class Player {
+
+ public Player(UUID uuid) {
+ playerUUID = uuid;
+ }
+
+ @Id
+ private UUID playerUUID;
+
+ @OneToMany(mappedBy = "owner")
+ @ToString.Exclude
+ private List ownedParties;
+
+ @ManyToMany(mappedBy = "members")
+ @ToString.Exclude
+ private List playerParties;
+
+ public OfflinePlayer getOfflinePlayer() {
+ return Bukkit.getOfflinePlayer(playerUUID);
+ }
+}
diff --git a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/database/entities/PlayerParty.java b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/database/entities/PlayerParty.java
new file mode 100644
index 0000000..be0a81d
--- /dev/null
+++ b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/database/entities/PlayerParty.java
@@ -0,0 +1,43 @@
+package com.jamesdpeters.minecraft.chests.database.entities;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+import java.util.List;
+
+@Entity
+@Getter
+@Setter
+@ToString
+@NoArgsConstructor
+@Table(uniqueConstraints = {
+ @UniqueConstraint(columnNames = {"NAME", "OWNER_PLAYERUUID"})
+})
+public class PlayerParty {
+
+ @Id
+ @GeneratedValue
+ private Long partyId;
+
+ @Column(nullable = false)
+ private String name;
+
+ @JoinColumn(nullable = false)
+ @ManyToOne(optional = false)
+ private Player owner;
+
+ @ManyToMany
+ @ToString.Exclude
+ private List members;
+}
diff --git a/pom.xml b/pom.xml
index 901dce9..106332b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,6 +15,7 @@
+ ChestsPlusPlus-Database
ChestsPlusPlusAPI
ChestsPlusPlus_1_17_R1
ChestsPlusPlus_1_16_R3