Skip to content
Open
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
472e534
created custom team class;
PrinzPizza42 Jan 21, 2025
d69287b
fixed and finished TeamsMainMenuGUI
PrinzPizza42 Jan 22, 2025
863c42e
fix MainMenuGUI name not showing actual page
PrinzPizza42 Jan 22, 2025
d09995f
implement TeamSettingsGUI
PrinzPizza42 Jan 22, 2025
e921fe2
finished color changer implementation
PrinzPizza42 Jan 23, 2025
328cebb
implement locking team settings
PrinzPizza42 Jan 23, 2025
51d86c5
finish TeamsMainMenuGUI teams implementation
PrinzPizza42 Jan 23, 2025
37c928c
team chest implementation;
PrinzPizza42 Jan 23, 2025
ce16f52
implement TeamPlayerSettingsGUI
PrinzPizza42 Jan 24, 2025
4c35fc6
implemented reloading mechanic for team menus to reload to everyone a…
PrinzPizza42 Jan 28, 2025
2476e18
safe teams in database;
PrinzPizza42 Feb 15, 2025
436deab
change locked state of team to unlocked when no operator is present a…
PrinzPizza42 Feb 15, 2025
a3c7127
save and read team enderchest content from and to DB
PrinzPizza42 Feb 27, 2025
45c6b9e
add fast access to team enderchest via command
PrinzPizza42 Feb 27, 2025
bffbba4
add claiming chunks for the team via TeamSettings
PrinzPizza42 Mar 8, 2025
20a8c02
cancel event of putting in items with enchants and send the player a …
PrinzPizza42 Mar 8, 2025
7583757
cancel event of putting in items with enchants and send the player a …
PrinzPizza42 Mar 8, 2025
079c5f5
Merge remote-tracking branch 'origin/Create-team-system' into Create-…
PrinzPizza42 Mar 18, 2025
283ad37
get and safe coordinates of protected team base
PrinzPizza42 Mar 20, 2025
8527255
create break and use block listener and cancel in protected areas fro…
PrinzPizza42 Mar 21, 2025
e2c1fa0
fix bug causing removal of members from team on plugin shutdown;
PrinzPizza42 Mar 26, 2025
8edf4cb
replace debug messages of team system with messages meant for the player
PrinzPizza42 Mar 26, 2025
25ba14b
bugfixes;
PrinzPizza42 Mar 30, 2025
8ba69ae
show the protected location in teamsmainmenu gui;
PrinzPizza42 Apr 3, 2025
2bde5dc
add option in config to change how big the claiming radius is
PrinzPizza42 Apr 4, 2025
fae4541
display the team name before the player name in the tab menu
PrinzPizza42 Apr 17, 2025
fcbe099
fix protected Location radius not getting saved anywhere
PrinzPizza42 Apr 17, 2025
47dce7b
fix protected Location radius not getting saved anywhere
PrinzPizza42 Apr 17, 2025
52f62f1
add shortcut for getting to your own team's settings
PrinzPizza42 Apr 17, 2025
67c003a
show the player the whole protected location via particles;
PrinzPizza42 Apr 20, 2025
2c65984
change detection of protected location when trying to claim one
PrinzPizza42 Apr 20, 2025
0a13177
fix bug
PrinzPizza42 Apr 20, 2025
70e55d9
Add sound effects for the menu interactions;
PrinzPizza42 Apr 20, 2025
09d7308
edit ReadMe
PrinzPizza42 Apr 21, 2025
d87afe9
fix
PrinzPizza42 Apr 21, 2025
97aebe5
Merge branch 'master' into Create-team-system
PrinzPizza42 Apr 21, 2025
794087f
Remove publish to repo
JonasFranke Jun 1, 2025
6db3cc7
Update src/main/java/de/j/deathMinigames/main/HandlePlayers.java
PrinzPizza42 Jun 1, 2025
39d56e4
Update src/main/java/de/j/stationofdoom/teams/TeamCMD.java
PrinzPizza42 Jun 1, 2025
5143a93
fix
PrinzPizza42 Jun 6, 2025
3fde6ae
fix
PrinzPizza42 Jun 6, 2025
31210b9
fix
PrinzPizza42 Jun 6, 2025
dc56c73
resolved conflicts
PrinzPizza42 Jun 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,31 +59,6 @@ jobs:
name: StationofdoomPlugin
path: build/libs

publishToRegistry:
runs-on: ubuntu-latest
needs: [build, paths-filter]
if: ${{ github.ref == 'refs/heads/master' && needs.paths-filter.outputs.output1 == 'true' }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up JDK 21
uses: actions/setup-java@v4.7.1
with:
java-version: 21
distribution: 'adopt'
cache: gradle
- name: Validate Gradle wrapper
uses: gradle/actions/wrapper-validation@v4.3.1
- name: Set env variables
run: |
echo "REPOSILITE_USER=${{ secrets.REPOSILITE_USER }}" >> $GITHUB_ENV
echo "REPOSILITE_PW=${{ secrets.REPOSILITE_PW }}" >> $GITHUB_ENV
- name: Publish
run: |
./gradlew publish -PtargetRepo=snapshots
env:
MAVEN_USERNAME: ${{ secrets.REPOSILITE_USER }}
MAVEN_PASSWORD: ${{ secrets.REPOSILITE_PW }}

releaseJar:
runs-on: ubuntu-latest
needs: [createJar, paths-filter]
Expand Down
30 changes: 0 additions & 30 deletions .github/workflows/repo.yml

This file was deleted.

15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,19 @@ A minecraft paper survival plugin for private servers
3. finished
</details>

- <details>
<summary>Team System</summary>

- Another feature of this plugin is its team system, which lets players create teams, to access it enter the command `/teams`. The teams are saved in the database if one is connected
- **List of Features**
1. create Teams
2. change appearance of the team (color & name)
3. rank system inside the teams to lock important settings of it
4. team enderchest
5. shortcut command to the players team menu (`/team`)
6. protect a location from interactions of players outside the team (the radius of the location can be configured in game settings or via the config file)
</details>

**Support and Project Discussion:**
- [Discord](https://discord.gg/uYwAKpRyak)

Expand Down Expand Up @@ -152,7 +165,7 @@ dependencies {
<repository>
<id>reposilite-repository</id>
<name>Jonas Franke Repository</name>
<url>https://repo.jonasfranke.xyz/<repository></url>
<url>https://repo.jonasfranke.xyz/</url>
</repository>

<dependency>
Expand Down
6 changes: 4 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ services:
postgres:
image: postgres:17-alpine
ports:
- 9667:5432
- 5432:5432
volumes:
- ./apps/postgres:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=65465
- POSTGRES_USER=mc
- POSTGRES_DB=stationofdoom
- POSTGRES_DB=stationofdoom
- POSTGRES_APPLICATION_NAME=stationofdoom
- POSTGRES_SCHEMA=public
15 changes: 15 additions & 0 deletions src/main/java/de/j/deathMinigames/database/DBTeamMember.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package de.j.deathMinigames.database;

import java.util.UUID;

public class DBTeamMember {
public boolean isInTeam;
public UUID uuid;
public boolean isTeamOperator;

public DBTeamMember(boolean isInTeam, String uuid, boolean isTeamOperator) {
this.isInTeam = isInTeam;
this.uuid = UUID.fromString(uuid);
this.isTeamOperator = isTeamOperator;
}
}
2 changes: 2 additions & 0 deletions src/main/java/de/j/deathMinigames/database/Database.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ public void initDatabase(){
isConnected = true;
configureDefaultQuery();
PlayerDataDatabase.getInstance().createTable();
TeamsDatabase.getInstance().createTable();
TeamEnderchestsDatabase.getInstance().createTable();
Main.getMainLogger().info("Database initialized");
}
catch(Exception e) {
Expand Down
105 changes: 76 additions & 29 deletions src/main/java/de/j/deathMinigames/database/PlayerDataDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
import de.j.deathMinigames.main.HandlePlayers;
import de.j.deathMinigames.main.PlayerData;
import de.j.stationofdoom.main.Main;
import de.j.stationofdoom.teams.HandleTeams;
import de.j.stationofdoom.teams.Team;
import org.bukkit.Bukkit;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
Expand Down Expand Up @@ -50,7 +50,7 @@ public static PlayerDataDatabase getInstance() {
*/
public void createTable() {
if(!Database.getInstance().isConnected) return;
Query.query("CREATE TABLE IF NOT EXISTS playerData (name VARCHAR(255), UUID VARCHAR(255), introduction BOOLEAN, usesPlugin BOOLEAN, difficulty INT, bestParkourTime FLOAT);")
Query.query("CREATE TABLE IF NOT EXISTS playerData (name VARCHAR(255), UUID VARCHAR(255), introduction BOOLEAN, usesPlugin BOOLEAN, difficulty INT, bestParkourTime FLOAT, isInTeam BOOLEAN, uuidOfTeam VARCHAR(255), isTeamOperator BOOLEAN);")
.single()
.insert();
}
Expand All @@ -65,19 +65,41 @@ public void createTable() {
*
* @return A list of PlayerData objects representing all players in the database.
*/
public List<PlayerData> getAllPlayerDatas() {
public List<PlayerData> getAllPlayerDataFromDB() {
if(!Database.getInstance().isConnected) return new ArrayList<>();
updatePlayerDataDatabase(HandlePlayers.getKnownPlayers().values());
return Query.query("SELECT * FROM playerdata;")
.single()
.map(row -> new PlayerData(row.getString("name"),
row.getString("uuid"),
row.getBoolean("introduction"),
row.getBoolean("usesPlugin"),
row.getInt("difficulty"),
row.getFloat("bestParkourTime")))
row.getFloat("bestParkourTime"),
row.getBoolean("isInTeam"),
row.getString("uuidOfTeam"),
row.getBoolean("isTeamOperator")))
.all();
}

public PlayerData getPlayerDataFromDB(UUID uuid) {
if(!Database.getInstance().isConnected) return null;
return Query.query("SELECT * FROM playerdata WHERE uuid = ?;")
.single(Call.of()
.bind(uuid, UUIDAdapter.AS_STRING))
.map(row -> new PlayerData(row.getString("name"),
row.getString("uuid"),
row.getBoolean("introduction"),
row.getBoolean("usesPlugin"),
row.getInt("difficulty"),
row.getFloat("bestParkourTime"),
row.getBoolean("isInTeam"),
row.getString("uuidOfTeam"),
row.getBoolean("isTeamOperator")))
.all()
.getFirst();
}

/**
* Updates the playerData database with the given player data collection.
*
Expand All @@ -88,20 +110,39 @@ public List<PlayerData> getAllPlayerDatas() {
* @param playerDatas The collection of player data to update the database with.
*/
public void updatePlayerDataDatabase(Collection<PlayerData> playerDatas) {
if(playerDatas.isEmpty()) return;
int newlyAddedPlayers = 0;
int updatedPlayers = 0;
if(!Database.getInstance().isConnected) return;
for (PlayerData playerData : playerDatas) {
if(checkIfPlayerIsInDatabase(playerData)) {
Query.query("UPDATE playerData SET name = :name, introduction = :introduction, usesPlugin = :usesPlugin, difficulty = :difficulty, bestParkourTime = :bestParkourTime WHERE uuid = :uuid;")
.single(Call.of()
.bind("name", playerData.getName())
.bind("introduction", playerData.getIntroduction())
.bind("usesPlugin", playerData.getUsesPlugin())
.bind("difficulty", playerData.getDifficulty())
.bind("bestParkourTime", playerData.getBestParkourTime())
.bind("uuid", playerData.getUUID(), UUIDAdapter.AS_STRING))
.update();
Team team = HandleTeams.getTeam(playerData);
if(team == null || !playerData.isInTeam()) {
Query.query("UPDATE playerData SET name = :name, introduction = :introduction, usesPlugin = :usesPlugin, difficulty = :difficulty, bestParkourTime = :bestParkourTime, isInTeam = :isInTeam WHERE uuid = :uuid;")
.single(Call.of()
.bind("name", playerData.getName())
.bind("introduction", playerData.getIntroduction())
.bind("usesPlugin", playerData.getUsesPlugin())
.bind("difficulty", playerData.getDifficulty())
.bind("bestParkourTime", playerData.getBestParkourTime())
.bind("isInTeam", false)
.bind("uuid", playerData.getUniqueId(), UUIDAdapter.AS_STRING))
.update();
}
else {
Query.query("UPDATE playerData SET name = :name, introduction = :introduction, usesPlugin = :usesPlugin, difficulty = :difficulty, bestParkourTime = :bestParkourTime, isInTeam = :isInTeam, uuidOfTeam = :uuidOfTeam, isTeamOperator = :isTeamOperator WHERE uuid = :uuid;")
.single(Call.of()
.bind("name", playerData.getName())
.bind("introduction", playerData.getIntroduction())
.bind("usesPlugin", playerData.getUsesPlugin())
.bind("difficulty", playerData.getDifficulty())
.bind("bestParkourTime", playerData.getBestParkourTime())
.bind("isInTeam", true)
.bind("uuidOfTeam", playerData.getUuidOfTeam(), UUIDAdapter.AS_STRING)
.bind("isTeamOperator", team.isTeamOperator(playerData))
.bind("uuid", playerData.getUniqueId(), UUIDAdapter.AS_STRING))
.update();
}
updatedPlayers++;
}
else {
Expand All @@ -122,14 +163,17 @@ public void updatePlayerDataDatabase(Collection<PlayerData> playerDatas) {
*/
public void addPlayerToDatabase(PlayerData playerData) {
if(!Database.getInstance().isConnected) return;
Query.query("INSERT INTO playerData (name, UUID, introduction, usesPlugin, difficulty, bestParkourTime) VALUES (:name, :uuid, :introduction, :usesPlugin, :difficulty, :bestParkourTime);")
Query.query("INSERT INTO playerData (name, UUID, introduction, usesPlugin, difficulty, bestParkourTime, isInTeam, uuidOfTeam, isTeamOperator) VALUES (:name, :uuid, :introduction, :usesPlugin, :difficulty, :bestParkourTime, :isInTeam, :uuidOfTeam, :isTeamOperator);")
.single(Call.of()
.bind("name", playerData.getName())
.bind("uuid", playerData.getUUID(), UUIDAdapter.AS_STRING)
.bind("uuid", playerData.getUniqueId(), UUIDAdapter.AS_STRING)
.bind("introduction", playerData.getIntroduction())
.bind("usesPlugin", playerData.getUsesPlugin())
.bind("difficulty", playerData.getDifficulty())
.bind("bestParkourTime", playerData.getBestParkourTime()))
.bind("bestParkourTime", playerData.getBestParkourTime())
.bind("isInTeam", playerData.isInTeam())
.bind("uuidOfTeam", playerData.getUuidOfTeam(), UUIDAdapter.AS_STRING)
.bind("isTeamOperator", playerData.isTeamOperator()))
.insert();
}

Expand All @@ -139,19 +183,22 @@ public void addPlayerToDatabase(PlayerData playerData) {
* <p>This method fetches all player data records from the database and checks
* if the player with the given UUID is present in the list.
*
* @param playerDataPlayerToCheck The player data to check.
* @param playerDataToCheck The player data to check.
* @return true if the player is in the database, false otherwise.
*/
public boolean checkIfPlayerIsInDatabase(PlayerData playerDataPlayerToCheck) {
if(!Database.getInstance().isConnected) return HandlePlayers.getKnownPlayers().containsKey(playerDataPlayerToCheck.getUUID()); // does not return false or true to prevent unpredictable behavior
List<PlayerData> playerDatas = getAllPlayerDatas();
boolean isInDatabase = false;
if(playerDatas.isEmpty()) return false;
for (PlayerData playerDataToCompare : playerDatas) {
if(playerDataToCompare.getUUID().equals(playerDataPlayerToCheck.getUUID())) {
isInDatabase = true;
}
}
return isInDatabase;
public boolean checkIfPlayerIsInDatabase(PlayerData playerDataToCheck) {
return checkIfPlayerIsInDatabase(playerDataToCheck.getUniqueId());
}

public boolean checkIfPlayerIsInDatabase(UUID uuidOfPlayerToCheck) {
if(!Database.getInstance().isConnected) return HandlePlayers.getKnownPlayers().containsKey(uuidOfPlayerToCheck); // does not return false or true to prevent unpredictable behavior
List<UUID> data = Query.query("SELECT UUID FROM playerData WHERE UUID = :UUID;")
.single(Call.of()
.bind("UUID", uuidOfPlayerToCheck, UUIDAdapter.AS_STRING))
.map(row -> UUID.fromString(row.getString("UUID")))
.all();

Main.getMainLogger().warning("CheckIfPlayerIsInDatabase for: " + Bukkit.getOfflinePlayer(uuidOfPlayerToCheck).getName() + ", found " + !data.isEmpty());
return !data.isEmpty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package de.j.deathMinigames.database;

import de.chojo.sadu.queries.api.call.Call;
import de.chojo.sadu.queries.api.query.Query;
import de.chojo.sadu.queries.call.adapter.UUIDAdapter;
import de.j.stationofdoom.main.Main;
import de.j.stationofdoom.teams.Team;
import de.j.stationofdoom.teams.TeamsMainMenuGUI;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import java.util.UUID;

public class TeamEnderchestsDatabase {
private static volatile TeamEnderchestsDatabase instance;

public TeamEnderchestsDatabase() {}

public static TeamEnderchestsDatabase getInstance() {
if (instance == null) {
synchronized (TeamEnderchestsDatabase.class) {
if (instance == null) {
instance = new TeamEnderchestsDatabase();
}
}
}
return instance;
}

public void createTable() {
if(!Database.getInstance().isConnected) return;
Query.query("CREATE TABLE IF NOT EXISTS teamEnderchests (uuidOfTeam VARCHAR(255), name VARCHAR(255), amount INTEGER, material VARCHAR(255));")
.single()
.insert();
}

public Inventory getTeamEnderchest(UUID uuidOfTeam) {
Inventory inv = Bukkit.createInventory(null, 27, "Team Enderchest");
if(!Database.getInstance().isConnected) return inv;
Query.query("SELECT * FROM teamEnderchests WHERE uuidOfTeam = ?;")
.single(Call.of()
.bind(uuidOfTeam, UUIDAdapter.AS_STRING))
.map(row -> {
ItemStack itemStack;
try {
itemStack = new ItemStack(Material.valueOf(row.getString("material")), row.getInt("amount"));
ItemMeta itemMeta = itemStack.getItemMeta();
if(row.getString("name") != null && !row.getString("name").isEmpty()) itemMeta.displayName(Component.text(row.getString("name")));
itemStack.setItemMeta(itemMeta);
}
catch (NullPointerException e) {
Main.getMainLogger().warning("Could not find material of " + row.getString("material") + " in team enderchests of team " + uuidOfTeam);
itemStack = new ItemStack(Material.STONE, 1);
itemStack.getItemMeta().displayName(Component.text("Could not find material of " + row.getString("material")));
}
inv.addItem(itemStack);
return itemStack;
})
.all();
return inv;
}

public void updateTeamEnderchestsOfAllTeams() {
if(!Database.getInstance().isConnected) return;
for (Team team : TeamsMainMenuGUI.teams) {
UUID uuidOfTeam = team.getUuid();
Query.query("DELETE FROM teamEnderchests WHERE uuidOfTeam = ?;")
.single(Call.of()
.bind(uuidOfTeam, UUIDAdapter.AS_STRING))
.delete();
if(team.inventory == null) continue;
for (ItemStack itemStack : team.inventory.getContents()) {
if(itemStack == null) continue;
Query.query("INSERT INTO teamEnderchests (uuidOfTeam, name, amount, material) VALUES (?, ?, ?, ?);")
.single(Call.of()
.bind(uuidOfTeam, UUIDAdapter.AS_STRING)
.bind(itemStack.getItemMeta().displayName() != null ? itemStack.getItemMeta().getDisplayName() : null)
.bind(itemStack.getAmount())
.bind(itemStack.getType().toString()))
.insert();
}
}
}
}
Loading