mirror of
https://github.com/plexusorg/Module-Guilds.git
synced 2026-07-14 19:34:54 +00:00
Merge pull request #1 from plexusorg/codex/guild-worlds-gui
Add ASP guild worlds and management GUIs
This commit is contained in:
@@ -1,9 +1,12 @@
|
|||||||
plugins {
|
plugins {
|
||||||
java
|
java
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
|
id("com.gradleup.shadow") version "9.2.2"
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
|
||||||
maven {
|
maven {
|
||||||
url = uri("https://repo.papermc.io/repository/maven-public/")
|
url = uri("https://repo.papermc.io/repository/maven-public/")
|
||||||
}
|
}
|
||||||
@@ -13,6 +16,10 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
||||||
|
maven {
|
||||||
|
url = uri("https://repo.infernalsuite.com/repository/maven-snapshots/")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -21,6 +28,8 @@ dependencies {
|
|||||||
compileOnly("io.papermc.paper:paper-api:26.1.2.build.+")
|
compileOnly("io.papermc.paper:paper-api:26.1.2.build.+")
|
||||||
implementation("org.apache.commons:commons-lang3:3.20.0")
|
implementation("org.apache.commons:commons-lang3:3.20.0")
|
||||||
compileOnly("dev.plex:api:2.0-SNAPSHOT")
|
compileOnly("dev.plex:api:2.0-SNAPSHOT")
|
||||||
|
compileOnly("com.infernalsuite.asp:api:4.0.0-SNAPSHOT")
|
||||||
|
implementation("com.infernalsuite.asp:file-loader:4.0.0-SNAPSHOT")
|
||||||
implementation("org.jetbrains:annotations:26.1.0")
|
implementation("org.jetbrains:annotations:26.1.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +54,16 @@ tasks.getByName<Jar>("jar") {
|
|||||||
archiveVersion.set("")
|
archiveVersion.set("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.shadowJar {
|
||||||
|
archiveBaseName.set("Module-Guilds")
|
||||||
|
archiveClassifier.set("")
|
||||||
|
archiveVersion.set("")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.build {
|
||||||
|
dependsOn(tasks.shadowJar)
|
||||||
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
compileJava {
|
compileJava {
|
||||||
options.encoding = Charsets.UTF_8.name()
|
options.encoding = Charsets.UTF_8.name()
|
||||||
|
|||||||
@@ -4,10 +4,14 @@ import dev.plex.command.GuildCommand;
|
|||||||
import dev.plex.config.ModuleConfig;
|
import dev.plex.config.ModuleConfig;
|
||||||
import dev.plex.guild.GuildHolder;
|
import dev.plex.guild.GuildHolder;
|
||||||
import dev.plex.handler.ChatHandlerImpl;
|
import dev.plex.handler.ChatHandlerImpl;
|
||||||
|
import dev.plex.handler.GuildMenuListener;
|
||||||
|
import dev.plex.handler.GuildWorldProtectionListener;
|
||||||
|
import dev.plex.handler.RankPermissionMenuListener;
|
||||||
import dev.plex.module.PlexModule;
|
import dev.plex.module.PlexModule;
|
||||||
import dev.plex.api.storage.ModuleStorage;
|
import dev.plex.api.storage.ModuleStorage;
|
||||||
import dev.plex.storage.GuildRepository;
|
import dev.plex.storage.GuildRepository;
|
||||||
import dev.plex.storage.JdbiGuildRepository;
|
import dev.plex.storage.JdbiGuildRepository;
|
||||||
|
import dev.plex.world.GuildWorldService;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@@ -18,6 +22,10 @@ public class Guilds extends PlexModule
|
|||||||
{
|
{
|
||||||
private static Guilds module;
|
private static Guilds module;
|
||||||
private final GuildHolder guildHolder = new GuildHolder();
|
private final GuildHolder guildHolder = new GuildHolder();
|
||||||
|
private final GuildMenuListener guildMenuListener = new GuildMenuListener();
|
||||||
|
private final GuildWorldProtectionListener guildWorldProtectionListener = new GuildWorldProtectionListener();
|
||||||
|
private final RankPermissionMenuListener rankPermissionMenuListener = new RankPermissionMenuListener();
|
||||||
|
private final GuildWorldService guildWorldService = new GuildWorldService();
|
||||||
|
|
||||||
private GuildRepository guildRepository;
|
private GuildRepository guildRepository;
|
||||||
|
|
||||||
@@ -36,10 +44,11 @@ public class Guilds extends PlexModule
|
|||||||
@Override
|
@Override
|
||||||
public void enable()
|
public void enable()
|
||||||
{
|
{
|
||||||
|
guildWorldService.enable();
|
||||||
ModuleStorage storage = api().storage().forModule(this);
|
ModuleStorage storage = api().storage().forModule(this);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
storage.migrations().run(List.of("001_initial_schema"));
|
storage.migrations().run(List.of("001_initial_schema", "002_guild_world_permissions"));
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (SQLException e)
|
||||||
{
|
{
|
||||||
@@ -62,11 +71,15 @@ public class Guilds extends PlexModule
|
|||||||
guildHolder.replaceAll(guilds);
|
guildHolder.replaceAll(guilds);
|
||||||
});
|
});
|
||||||
registerListener(new ChatHandlerImpl());
|
registerListener(new ChatHandlerImpl());
|
||||||
|
registerListener(guildMenuListener);
|
||||||
|
registerListener(guildWorldProtectionListener);
|
||||||
|
registerListener(rankPermissionMenuListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disable()
|
public void disable()
|
||||||
{
|
{
|
||||||
|
guildWorldService.disable();
|
||||||
guildHolder.clear();
|
guildHolder.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,10 +40,13 @@ public class GuildCommand extends SimplePlexCommand
|
|||||||
this.registerSubCommand(new ChatSubCommand());
|
this.registerSubCommand(new ChatSubCommand());
|
||||||
this.registerSubCommand(new SetHomeSubCommand());
|
this.registerSubCommand(new SetHomeSubCommand());
|
||||||
this.registerSubCommand(new HomeSubCommand());
|
this.registerSubCommand(new HomeSubCommand());
|
||||||
|
this.registerSubCommand(new WorldSubCommand());
|
||||||
|
this.registerSubCommand(new PermissionsSubCommand());
|
||||||
this.registerSubCommand(new OwnerSubCommand());
|
this.registerSubCommand(new OwnerSubCommand());
|
||||||
this.registerSubCommand(new InviteSubCommand());
|
this.registerSubCommand(new InviteSubCommand());
|
||||||
this.registerSubCommand(new AcceptSubCommand());
|
this.registerSubCommand(new AcceptSubCommand());
|
||||||
this.registerSubCommand(new DenySubCommand());
|
this.registerSubCommand(new DenySubCommand());
|
||||||
|
this.registerSubCommand(new MenuSubCommand());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -51,7 +54,15 @@ public class GuildCommand extends SimplePlexCommand
|
|||||||
{
|
{
|
||||||
if (args.length == 0)
|
if (args.length == 0)
|
||||||
{
|
{
|
||||||
return getSubs();
|
if (player == null)
|
||||||
|
{
|
||||||
|
return getSubs();
|
||||||
|
}
|
||||||
|
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(
|
||||||
|
guild -> Guilds.get().getGuildMenuListener().openHome(player, guild),
|
||||||
|
() -> player.sendMessage(messageComponent("guildNotFound"))
|
||||||
|
);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
if (args[0].equalsIgnoreCase("help"))
|
if (args[0].equalsIgnoreCase("help"))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ public class CreateSubCommand extends GuildSubCommand
|
|||||||
{
|
{
|
||||||
return messageComponent("alreadyInGuild");
|
return messageComponent("alreadyInGuild");
|
||||||
}
|
}
|
||||||
Guilds.get().getGuildRepository().createGuild(player, StringUtils.join(args, " ")).whenComplete((guild, throwable) ->
|
Guilds.get().getGuildRepository().createGuild(player, StringUtils.join(args, " "))
|
||||||
|
.thenCompose(guild -> Guilds.get().getGuildWorldService().ensureWorld(guild).thenApply(world -> guild))
|
||||||
|
.whenComplete((guild, throwable) ->
|
||||||
{
|
{
|
||||||
if (throwable != null)
|
if (throwable != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package dev.plex.command.sub;
|
||||||
|
|
||||||
|
import dev.plex.Guilds;
|
||||||
|
import dev.plex.command.source.RequiredCommandSource;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class MenuSubCommand extends GuildSubCommand
|
||||||
|
{
|
||||||
|
public MenuSubCommand()
|
||||||
|
{
|
||||||
|
super(command("menu")
|
||||||
|
.description("Opens the guild management menu")
|
||||||
|
.usage("/guild <command>")
|
||||||
|
.aliases("gui,panel")
|
||||||
|
.permission("plex.guilds.menu")
|
||||||
|
.source(RequiredCommandSource.IN_GAME)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args)
|
||||||
|
{
|
||||||
|
assert player != null;
|
||||||
|
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(
|
||||||
|
guild -> Guilds.get().getGuildMenuListener().openHome(player, guild),
|
||||||
|
() -> send(player, messageComponent("guildNotFound"))
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package dev.plex.command.sub;
|
||||||
|
|
||||||
|
import dev.plex.Guilds;
|
||||||
|
import dev.plex.command.source.RequiredCommandSource;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class PermissionsSubCommand extends GuildSubCommand
|
||||||
|
{
|
||||||
|
public PermissionsSubCommand()
|
||||||
|
{
|
||||||
|
super(command("permissions")
|
||||||
|
.description("Opens the rank permissions GUI")
|
||||||
|
.usage("/guild <command>")
|
||||||
|
.aliases("perms")
|
||||||
|
.permission("plex.guilds.permissions")
|
||||||
|
.source(RequiredCommandSource.IN_GAME)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args)
|
||||||
|
{
|
||||||
|
assert player != null;
|
||||||
|
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild ->
|
||||||
|
{
|
||||||
|
if (!guild.isOwner(player.getUniqueId()))
|
||||||
|
{
|
||||||
|
send(player, messageComponent("guildNotOwner"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Guilds.get().getRankPermissionMenuListener().openRankList(player, guild);
|
||||||
|
}, () -> send(player, messageComponent("guildNotFound")));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package dev.plex.command.sub;
|
||||||
|
|
||||||
|
import dev.plex.Guilds;
|
||||||
|
import dev.plex.command.source.RequiredCommandSource;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class WorldSubCommand extends GuildSubCommand
|
||||||
|
{
|
||||||
|
public WorldSubCommand()
|
||||||
|
{
|
||||||
|
super(command("world")
|
||||||
|
.description("Teleports to your guild world")
|
||||||
|
.usage("/guild <command>")
|
||||||
|
.aliases("base")
|
||||||
|
.permission("plex.guilds.world")
|
||||||
|
.source(RequiredCommandSource.IN_GAME)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Component execute(@NotNull CommandSender commandSender, @Nullable Player player, @NotNull String[] args)
|
||||||
|
{
|
||||||
|
assert player != null;
|
||||||
|
Guilds.get().getGuildHolder().getGuild(player.getUniqueId()).ifPresentOrElse(guild ->
|
||||||
|
{
|
||||||
|
send(player, messageComponent("guildWorldLoading"));
|
||||||
|
Guilds.get().getGuildWorldService().ensureWorld(guild).whenComplete((world, throwable) ->
|
||||||
|
{
|
||||||
|
if (throwable != null)
|
||||||
|
{
|
||||||
|
Guilds.get().api().scheduler().executeGlobal(() ->
|
||||||
|
{
|
||||||
|
throwable.printStackTrace();
|
||||||
|
send(player, messageComponent("guildWorldLoadFailed"));
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Guilds.get().api().scheduler().executeEntity(player, () -> teleport(player, world), 1L);
|
||||||
|
});
|
||||||
|
}, () -> send(player, messageComponent("guildNotFound")));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void teleport(Player player, World world)
|
||||||
|
{
|
||||||
|
Location spawnLocation = world.getSpawnLocation().toCenterLocation();
|
||||||
|
player.teleportAsync(spawnLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package dev.plex.gui;
|
||||||
|
|
||||||
|
import dev.plex.guild.Guild;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public record GuildMenuInventoryHolder(Guild guild, GuildMenuView view, UUID memberUuid) implements InventoryHolder
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public @NotNull Inventory getInventory()
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package dev.plex.gui;
|
||||||
|
|
||||||
|
public enum GuildMenuView
|
||||||
|
{
|
||||||
|
HOME,
|
||||||
|
MEMBERS,
|
||||||
|
MEMBER
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package dev.plex.gui;
|
||||||
|
|
||||||
|
import dev.plex.guild.Guild;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public record RankPermissionInventoryHolder(Guild guild, String rankName) implements InventoryHolder
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public @NotNull Inventory getInventory()
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,8 +3,10 @@ package dev.plex.guild;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import dev.plex.Guilds;
|
import dev.plex.Guilds;
|
||||||
|
import dev.plex.guild.data.GuildPermission;
|
||||||
import dev.plex.guild.data.GuildRole;
|
import dev.plex.guild.data.GuildRole;
|
||||||
import dev.plex.guild.data.Member;
|
import dev.plex.guild.data.Member;
|
||||||
|
import dev.plex.api.player.PlexPlayerView;
|
||||||
import dev.plex.util.CustomLocation;
|
import dev.plex.util.CustomLocation;
|
||||||
import dev.plex.util.GuildUtil;
|
import dev.plex.util.GuildUtil;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -15,6 +17,7 @@ import java.time.ZoneId;
|
|||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@@ -31,6 +34,9 @@ public class Guild
|
|||||||
private CustomLocation home;
|
private CustomLocation home;
|
||||||
private boolean tagEnabled = true;
|
private boolean tagEnabled = true;
|
||||||
private boolean isPublic;
|
private boolean isPublic;
|
||||||
|
private boolean memberBlockBreaking;
|
||||||
|
private boolean memberBlockPlacing;
|
||||||
|
private boolean memberInteracting;
|
||||||
|
|
||||||
public static Guild create(Player player, String guildName)
|
public static Guild create(Player player, String guildName)
|
||||||
{
|
{
|
||||||
@@ -62,4 +68,63 @@ public class Guild
|
|||||||
{
|
{
|
||||||
return ownerUuid != null && ownerUuid.equals(uuid);
|
return ownerUuid != null && ownerUuid.equals(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isMember(UUID uuid)
|
||||||
|
{
|
||||||
|
return getMember(uuid) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeMember(UUID uuid)
|
||||||
|
{
|
||||||
|
members.removeIf(member -> member.getUuid().equals(uuid));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<? extends PlexPlayerView> getPlexPlayers()
|
||||||
|
{
|
||||||
|
return members.stream()
|
||||||
|
.map(Member::getPlexPlayer)
|
||||||
|
.flatMap(java.util.Optional::stream)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Player> getOnlinePlayers()
|
||||||
|
{
|
||||||
|
return getPlexPlayers().stream()
|
||||||
|
.map(PlexPlayerView::bukkitPlayer)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWorldName()
|
||||||
|
{
|
||||||
|
return "guild_" + guildUuid.toString().replace("-", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPermission(UUID uuid, GuildPermission permission)
|
||||||
|
{
|
||||||
|
if (isOwner(uuid))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!isMember(uuid))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return switch (permission)
|
||||||
|
{
|
||||||
|
case BLOCK_BREAKING -> memberBlockBreaking;
|
||||||
|
case BLOCK_PLACING -> memberBlockPlacing;
|
||||||
|
case INTERACTING -> memberInteracting;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPermission(GuildPermission permission, boolean enabled)
|
||||||
|
{
|
||||||
|
switch (permission)
|
||||||
|
{
|
||||||
|
case BLOCK_BREAKING -> memberBlockBreaking = enabled;
|
||||||
|
case BLOCK_PLACING -> memberBlockPlacing = enabled;
|
||||||
|
case INTERACTING -> memberInteracting = enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package dev.plex.guild.data;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
|
||||||
|
public enum GuildPermission
|
||||||
|
{
|
||||||
|
BLOCK_BREAKING("Block Breaking", Material.DIAMOND_PICKAXE),
|
||||||
|
BLOCK_PLACING("Block Placing", Material.GRASS_BLOCK),
|
||||||
|
INTERACTING("Interacting", Material.OAK_BUTTON);
|
||||||
|
|
||||||
|
private final String displayName;
|
||||||
|
private final Material material;
|
||||||
|
|
||||||
|
GuildPermission(String displayName, Material material)
|
||||||
|
{
|
||||||
|
this.displayName = displayName;
|
||||||
|
this.material = material;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String displayName()
|
||||||
|
{
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Material material()
|
||||||
|
{
|
||||||
|
return material;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
package dev.plex.guild.data;
|
package dev.plex.guild.data;
|
||||||
|
|
||||||
|
import dev.plex.Guilds;
|
||||||
|
import dev.plex.api.player.PlexPlayerView;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@@ -28,4 +31,16 @@ public class Member
|
|||||||
{
|
{
|
||||||
return Bukkit.getPlayer(this.uuid);
|
return Bukkit.getPlayer(this.uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<? extends PlexPlayerView> getPlexPlayer()
|
||||||
|
{
|
||||||
|
return Guilds.get().api().players().player(this.uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return getPlexPlayer()
|
||||||
|
.map(PlexPlayerView::name)
|
||||||
|
.orElse(this.uuid.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,290 @@
|
|||||||
|
package dev.plex.handler;
|
||||||
|
|
||||||
|
import dev.plex.Guilds;
|
||||||
|
import dev.plex.guild.Guild;
|
||||||
|
import dev.plex.guild.data.GuildRole;
|
||||||
|
import dev.plex.guild.data.Member;
|
||||||
|
import dev.plex.gui.GuildMenuInventoryHolder;
|
||||||
|
import dev.plex.gui.GuildMenuView;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.ItemFlag;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class GuildMenuListener implements Listener
|
||||||
|
{
|
||||||
|
private static final int MEMBERS_SLOT = 11;
|
||||||
|
private static final int WORLD_SLOT = 13;
|
||||||
|
private static final int PERMISSIONS_SLOT = 15;
|
||||||
|
private static final int BACK_SLOT = 26;
|
||||||
|
private static final int KICK_SLOT = 11;
|
||||||
|
private static final int OWNER_SLOT = 13;
|
||||||
|
private static final int RANK_PERMISSIONS_SLOT = 15;
|
||||||
|
|
||||||
|
public void openHome(Player player, Guild guild)
|
||||||
|
{
|
||||||
|
Inventory inventory = Bukkit.createInventory(new GuildMenuInventoryHolder(guild, GuildMenuView.HOME, null), 27, title("* " + guild.getName()));
|
||||||
|
inventory.setItem(MEMBERS_SLOT, item(Material.PLAYER_HEAD, "Guild Members", NamedTextColor.AQUA, List.of(
|
||||||
|
line("View online status", NamedTextColor.GRAY),
|
||||||
|
line("Click to manage members", NamedTextColor.YELLOW)
|
||||||
|
)));
|
||||||
|
inventory.setItem(WORLD_SLOT, item(Material.GRASS_BLOCK, "Guild World", NamedTextColor.GREEN, List.of(
|
||||||
|
line("Load and enter your guild world", NamedTextColor.GRAY),
|
||||||
|
line("Only guild members can access it", NamedTextColor.DARK_AQUA)
|
||||||
|
)));
|
||||||
|
if (guild.isOwner(player.getUniqueId()))
|
||||||
|
{
|
||||||
|
inventory.setItem(PERMISSIONS_SLOT, item(Material.COMPARATOR, "Rank Permissions", NamedTextColor.GOLD, List.of(
|
||||||
|
line("Configure member build permissions", NamedTextColor.GRAY),
|
||||||
|
line("Break - Place - Interact", NamedTextColor.YELLOW)
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
player.openInventory(inventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openMembers(Player player, Guild guild)
|
||||||
|
{
|
||||||
|
Inventory inventory = Bukkit.createInventory(new GuildMenuInventoryHolder(guild, GuildMenuView.MEMBERS, null), 54, title("* " + guild.getName() + " Members"));
|
||||||
|
List<Member> members = guild.getMembers();
|
||||||
|
for (int i = 0; i < members.size() && i < 45; i++)
|
||||||
|
{
|
||||||
|
inventory.setItem(i, memberItem(guild, members.get(i)));
|
||||||
|
}
|
||||||
|
inventory.setItem(BACK_SLOT, item(Material.ARROW, "Back", NamedTextColor.YELLOW, List.of(line("Return to the guild menu", NamedTextColor.GRAY))));
|
||||||
|
player.openInventory(inventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openMember(Player player, Guild guild, Member member)
|
||||||
|
{
|
||||||
|
Inventory inventory = Bukkit.createInventory(new GuildMenuInventoryHolder(guild, GuildMenuView.MEMBER, member.getUuid()), 27, title("* " + member.getName()));
|
||||||
|
inventory.setItem(4, memberItem(guild, member));
|
||||||
|
if (guild.isOwner(player.getUniqueId()) && !guild.isOwner(member.getUuid()))
|
||||||
|
{
|
||||||
|
inventory.setItem(KICK_SLOT, item(Material.BARRIER, "Kick Member", NamedTextColor.RED, List.of(
|
||||||
|
line("Remove this player from the guild", NamedTextColor.GRAY),
|
||||||
|
line("They will lose guild world access", NamedTextColor.DARK_RED)
|
||||||
|
)));
|
||||||
|
inventory.setItem(OWNER_SLOT, item(Material.GOLDEN_HELMET, "Transfer Ownership", NamedTextColor.GOLD, List.of(
|
||||||
|
line("Make this player the guild owner", NamedTextColor.GRAY),
|
||||||
|
line("You will become a regular member", NamedTextColor.YELLOW)
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
if (guild.isOwner(player.getUniqueId()))
|
||||||
|
{
|
||||||
|
inventory.setItem(RANK_PERMISSIONS_SLOT, item(Material.COMPARATOR, "Rank Permissions", NamedTextColor.AQUA, List.of(
|
||||||
|
line("Open the rank permission editor", NamedTextColor.GRAY)
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
inventory.setItem(BACK_SLOT, item(Material.ARROW, "Back", NamedTextColor.YELLOW, List.of(line("Return to member list", NamedTextColor.GRAY))));
|
||||||
|
player.openInventory(inventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGH)
|
||||||
|
public void onClick(InventoryClickEvent event)
|
||||||
|
{
|
||||||
|
if (!(event.getWhoClicked() instanceof Player player) || !(event.getInventory().getHolder() instanceof GuildMenuInventoryHolder holder))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event.setCancelled(true);
|
||||||
|
if (!holder.guild().isMember(player.getUniqueId()))
|
||||||
|
{
|
||||||
|
player.closeInventory();
|
||||||
|
player.sendMessage(Guilds.get().messageComponent("guildNotFound"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ItemStack clickedItem = event.getCurrentItem();
|
||||||
|
if (clickedItem == null || clickedItem.getType() == Material.AIR)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (holder.view())
|
||||||
|
{
|
||||||
|
case HOME -> clickHome(player, holder.guild(), event.getRawSlot());
|
||||||
|
case MEMBERS -> clickMembers(player, holder.guild(), clickedItem, event.getRawSlot());
|
||||||
|
case MEMBER -> clickMember(player, holder.guild(), holder.memberUuid(), event.getRawSlot());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clickHome(Player player, Guild guild, int slot)
|
||||||
|
{
|
||||||
|
if (slot == MEMBERS_SLOT)
|
||||||
|
{
|
||||||
|
openMembers(player, guild);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (slot == WORLD_SLOT)
|
||||||
|
{
|
||||||
|
player.closeInventory();
|
||||||
|
Guilds.get().getGuildWorldService().ensureWorld(guild).whenComplete((world, throwable) ->
|
||||||
|
{
|
||||||
|
if (throwable != null)
|
||||||
|
{
|
||||||
|
Guilds.get().api().scheduler().executeGlobal(() -> player.sendMessage(Guilds.get().messageComponent("guildWorldLoadFailed")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Guilds.get().api().scheduler().executeEntity(player, () -> player.teleportAsync(world.getSpawnLocation().toCenterLocation()), 1L);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (slot == PERMISSIONS_SLOT && guild.isOwner(player.getUniqueId()))
|
||||||
|
{
|
||||||
|
Guilds.get().getRankPermissionMenuListener().openRankList(player, guild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clickMembers(Player player, Guild guild, ItemStack clickedItem, int slot)
|
||||||
|
{
|
||||||
|
if (slot == BACK_SLOT)
|
||||||
|
{
|
||||||
|
openHome(player, guild);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memberUuid(clickedItem).map(guild::getMember).filter(Objects::nonNull).ifPresent(member -> openMember(player, guild, member));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clickMember(Player player, Guild guild, UUID memberUuid, int slot)
|
||||||
|
{
|
||||||
|
Member member = guild.getMember(memberUuid);
|
||||||
|
if (member == null)
|
||||||
|
{
|
||||||
|
openMembers(player, guild);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (slot == BACK_SLOT)
|
||||||
|
{
|
||||||
|
openMembers(player, guild);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!guild.isOwner(player.getUniqueId()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (slot == KICK_SLOT && !guild.isOwner(memberUuid))
|
||||||
|
{
|
||||||
|
Guilds.get().getGuildRepository().removeMember(guild.getGuildUuid(), memberUuid).whenComplete((unused, throwable) ->
|
||||||
|
{
|
||||||
|
if (throwable != null)
|
||||||
|
{
|
||||||
|
player.sendMessage(Guilds.get().messageComponent("guildStorageFailed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
guild.removeMember(memberUuid);
|
||||||
|
Guilds.get().getGuildHolder().unindexMember(memberUuid);
|
||||||
|
Guilds.get().getGuildWorldService().ejectNonMembers(guild);
|
||||||
|
player.sendMessage(Guilds.get().messageComponent("guildMemberKicked", member.getName()));
|
||||||
|
openMembers(player, guild);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (slot == OWNER_SLOT && !guild.isOwner(memberUuid))
|
||||||
|
{
|
||||||
|
Member previousOwner = guild.getMember(player.getUniqueId());
|
||||||
|
Guilds.get().getGuildRepository().transferOwner(guild.getGuildUuid(), memberUuid, player.getUniqueId()).whenComplete((unused, throwable) ->
|
||||||
|
{
|
||||||
|
if (throwable != null)
|
||||||
|
{
|
||||||
|
player.sendMessage(Guilds.get().messageComponent("guildStorageFailed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
guild.setOwnerUuid(memberUuid);
|
||||||
|
member.setRole(GuildRole.OWNER);
|
||||||
|
if (previousOwner != null)
|
||||||
|
{
|
||||||
|
previousOwner.setRole(GuildRole.MEMBER);
|
||||||
|
}
|
||||||
|
player.sendMessage(Guilds.get().messageComponent("guildOwnerSet", member.getName()));
|
||||||
|
openMember(player, guild, previousOwner == null ? member : previousOwner);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (slot == RANK_PERMISSIONS_SLOT)
|
||||||
|
{
|
||||||
|
Guilds.get().getRankPermissionMenuListener().openRankList(player, guild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack memberItem(Guild guild, Member member)
|
||||||
|
{
|
||||||
|
boolean online = Bukkit.getPlayer(member.getUuid()) != null;
|
||||||
|
ItemStack itemStack = new ItemStack(online ? Material.LIME_WOOL : Material.GRAY_WOOL);
|
||||||
|
ItemMeta itemMeta = itemStack.getItemMeta();
|
||||||
|
itemMeta.displayName(text(member.getName(), online ? NamedTextColor.GREEN : NamedTextColor.GRAY));
|
||||||
|
List<Component> lore = new ArrayList<>();
|
||||||
|
lore.add(label("Status", online ? "Online" : "Offline", online ? NamedTextColor.GREEN : NamedTextColor.GRAY));
|
||||||
|
lore.add(label("Role", guild.isOwner(member.getUuid()) ? "Owner" : "Member", guild.isOwner(member.getUuid()) ? NamedTextColor.GOLD : NamedTextColor.AQUA));
|
||||||
|
lore.add(label("Rank", guild.isOwner(member.getUuid()) ? "Owner" : "Member", NamedTextColor.LIGHT_PURPLE));
|
||||||
|
lore.add(Component.empty());
|
||||||
|
lore.add(line("Click to manage", NamedTextColor.YELLOW));
|
||||||
|
itemMeta.lore(lore);
|
||||||
|
itemMeta.addItemFlags(ItemFlag.values());
|
||||||
|
itemMeta.getPersistentDataContainer().set(Keys.MEMBER_UUID, org.bukkit.persistence.PersistentDataType.STRING, member.getUuid().toString());
|
||||||
|
itemStack.setItemMeta(itemMeta);
|
||||||
|
return itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack item(Material material, String name, NamedTextColor color, List<Component> lore)
|
||||||
|
{
|
||||||
|
ItemStack itemStack = new ItemStack(material);
|
||||||
|
ItemMeta itemMeta = itemStack.getItemMeta();
|
||||||
|
itemMeta.displayName(text(name, color));
|
||||||
|
itemMeta.lore(lore);
|
||||||
|
itemMeta.addItemFlags(ItemFlag.values());
|
||||||
|
itemStack.setItemMeta(itemMeta);
|
||||||
|
return itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component title(String value)
|
||||||
|
{
|
||||||
|
return text(value, NamedTextColor.DARK_AQUA);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component text(String value, NamedTextColor color)
|
||||||
|
{
|
||||||
|
return Component.text(value, color).decoration(TextDecoration.ITALIC, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component line(String value, NamedTextColor color)
|
||||||
|
{
|
||||||
|
return text("> " + value, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component label(String label, String value, NamedTextColor valueColor)
|
||||||
|
{
|
||||||
|
return text(label + ": ", NamedTextColor.GRAY).append(text(value, valueColor));
|
||||||
|
}
|
||||||
|
|
||||||
|
private java.util.Optional<UUID> memberUuid(ItemStack itemStack)
|
||||||
|
{
|
||||||
|
if (!itemStack.hasItemMeta())
|
||||||
|
{
|
||||||
|
return java.util.Optional.empty();
|
||||||
|
}
|
||||||
|
String value = itemStack.getItemMeta().getPersistentDataContainer().get(Keys.MEMBER_UUID, org.bukkit.persistence.PersistentDataType.STRING);
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
return java.util.Optional.empty();
|
||||||
|
}
|
||||||
|
return java.util.Optional.of(UUID.fromString(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Keys
|
||||||
|
{
|
||||||
|
private static final org.bukkit.NamespacedKey MEMBER_UUID = new org.bukkit.NamespacedKey("plex_guilds", "member_uuid");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package dev.plex.handler;
|
||||||
|
|
||||||
|
import dev.plex.Guilds;
|
||||||
|
import dev.plex.guild.Guild;
|
||||||
|
import dev.plex.guild.data.GuildPermission;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
|
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class GuildWorldProtectionListener implements Listener
|
||||||
|
{
|
||||||
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||||
|
public void onTeleport(PlayerTeleportEvent event)
|
||||||
|
{
|
||||||
|
if (event.getTo() == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Optional<Guild> guild = guildByWorld(event.getTo().getWorld());
|
||||||
|
if (guild.isPresent() && !guild.get().isMember(event.getPlayer().getUniqueId()))
|
||||||
|
{
|
||||||
|
event.setCancelled(true);
|
||||||
|
event.getPlayer().sendMessage(Guilds.get().messageComponent("guildWorldNoAccess"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
|
public void onChangedWorld(PlayerChangedWorldEvent event)
|
||||||
|
{
|
||||||
|
Optional<Guild> guild = guildByWorld(event.getPlayer().getWorld());
|
||||||
|
if (guild.isPresent() && !guild.get().isMember(event.getPlayer().getUniqueId()))
|
||||||
|
{
|
||||||
|
World fallback = Bukkit.getWorlds().getFirst();
|
||||||
|
event.getPlayer().teleportAsync(fallback.getSpawnLocation());
|
||||||
|
event.getPlayer().sendMessage(Guilds.get().messageComponent("guildWorldNoAccess"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||||
|
public void onBlockBreak(BlockBreakEvent event)
|
||||||
|
{
|
||||||
|
if (!canUse(event.getPlayer(), event.getBlock().getWorld(), GuildPermission.BLOCK_BREAKING))
|
||||||
|
{
|
||||||
|
event.setCancelled(true);
|
||||||
|
event.getPlayer().sendMessage(Guilds.get().messageComponent("guildWorldPermissionDenied"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||||
|
public void onBlockPlace(BlockPlaceEvent event)
|
||||||
|
{
|
||||||
|
if (!canUse(event.getPlayer(), event.getBlock().getWorld(), GuildPermission.BLOCK_PLACING))
|
||||||
|
{
|
||||||
|
event.setCancelled(true);
|
||||||
|
event.getPlayer().sendMessage(Guilds.get().messageComponent("guildWorldPermissionDenied"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||||
|
public void onInteract(PlayerInteractEvent event)
|
||||||
|
{
|
||||||
|
if (event.getClickedBlock() == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!canUse(event.getPlayer(), event.getClickedBlock().getWorld(), GuildPermission.INTERACTING))
|
||||||
|
{
|
||||||
|
event.setCancelled(true);
|
||||||
|
event.getPlayer().sendMessage(Guilds.get().messageComponent("guildWorldPermissionDenied"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canUse(Player player, World world, GuildPermission permission)
|
||||||
|
{
|
||||||
|
Optional<Guild> guild = guildByWorld(world);
|
||||||
|
return guild.map(value -> value.hasPermission(player.getUniqueId(), permission)).orElse(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<Guild> guildByWorld(World world)
|
||||||
|
{
|
||||||
|
if (world == null)
|
||||||
|
{
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
return Guilds.get().getGuildHolder().getGuilds().stream()
|
||||||
|
.filter(guild -> guild.getWorldName().equals(world.getName()))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
package dev.plex.handler;
|
||||||
|
|
||||||
|
import dev.plex.Guilds;
|
||||||
|
import dev.plex.guild.Guild;
|
||||||
|
import dev.plex.guild.data.GuildPermission;
|
||||||
|
import dev.plex.gui.RankPermissionInventoryHolder;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class RankPermissionMenuListener implements Listener
|
||||||
|
{
|
||||||
|
private static final UUID MEMBER_PERMISSION_PROBE = new UUID(0L, 0L);
|
||||||
|
|
||||||
|
public void openRankList(Player player, Guild guild)
|
||||||
|
{
|
||||||
|
Inventory inventory = Bukkit.createInventory(new RankPermissionInventoryHolder(guild, null), 27, title("* Guild Rank Permissions"));
|
||||||
|
inventory.setItem(13, rankItem());
|
||||||
|
player.openInventory(inventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGH)
|
||||||
|
public void onClick(InventoryClickEvent event)
|
||||||
|
{
|
||||||
|
if (!(event.getWhoClicked() instanceof Player player) || !(event.getInventory().getHolder() instanceof RankPermissionInventoryHolder holder))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event.setCancelled(true);
|
||||||
|
if (!holder.guild().isOwner(player.getUniqueId()))
|
||||||
|
{
|
||||||
|
player.closeInventory();
|
||||||
|
player.sendMessage(Guilds.get().messageComponent("guildNotOwner"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ItemStack clickedItem = event.getCurrentItem();
|
||||||
|
if (clickedItem == null || clickedItem.getType() == Material.AIR)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (holder.rankName() == null)
|
||||||
|
{
|
||||||
|
openPermissionEditor(player, holder.guild());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GuildPermission permission = permissionBySlot(event.getRawSlot());
|
||||||
|
if (permission == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean enabled = !holder.guild().hasPermission(MEMBER_PERMISSION_PROBE, permission);
|
||||||
|
holder.guild().setPermission(permission, enabled);
|
||||||
|
Guilds.get().getGuildRepository().updateMemberPermission(holder.guild().getGuildUuid(), permission, enabled);
|
||||||
|
openPermissionEditor(player, holder.guild());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openPermissionEditor(Player player, Guild guild)
|
||||||
|
{
|
||||||
|
Inventory inventory = Bukkit.createInventory(new RankPermissionInventoryHolder(guild, "MEMBER"), 27, title("* Member Permissions"));
|
||||||
|
GuildPermission[] permissions = GuildPermission.values();
|
||||||
|
for (int i = 0; i < permissions.length; i++)
|
||||||
|
{
|
||||||
|
inventory.setItem(11 + i * 2, permissionItem(guild, permissions[i]));
|
||||||
|
}
|
||||||
|
player.openInventory(inventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GuildPermission permissionBySlot(int slot)
|
||||||
|
{
|
||||||
|
return switch (slot)
|
||||||
|
{
|
||||||
|
case 11 -> GuildPermission.BLOCK_BREAKING;
|
||||||
|
case 13 -> GuildPermission.BLOCK_PLACING;
|
||||||
|
case 15 -> GuildPermission.INTERACTING;
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack rankItem()
|
||||||
|
{
|
||||||
|
ItemStack itemStack = new ItemStack(Material.NAME_TAG);
|
||||||
|
ItemMeta itemMeta = itemStack.getItemMeta();
|
||||||
|
itemMeta.displayName(text("Member", NamedTextColor.AQUA));
|
||||||
|
itemMeta.lore(List.of(
|
||||||
|
line("Manage member guild world access", NamedTextColor.GRAY),
|
||||||
|
line("Click to edit permissions", NamedTextColor.YELLOW)
|
||||||
|
));
|
||||||
|
itemStack.setItemMeta(itemMeta);
|
||||||
|
return itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack permissionItem(Guild guild, GuildPermission permission)
|
||||||
|
{
|
||||||
|
ItemStack itemStack = new ItemStack(permission.material());
|
||||||
|
ItemMeta itemMeta = itemStack.getItemMeta();
|
||||||
|
boolean enabled = guild.hasPermission(MEMBER_PERMISSION_PROBE, permission);
|
||||||
|
itemMeta.displayName(text(permission.displayName(), enabled ? NamedTextColor.GREEN : NamedTextColor.RED));
|
||||||
|
itemMeta.lore(List.of(
|
||||||
|
text("Status: ", NamedTextColor.GRAY).append(text(enabled ? "Enabled" : "Disabled", enabled ? NamedTextColor.GREEN : NamedTextColor.RED)),
|
||||||
|
Component.empty(),
|
||||||
|
line("Click to toggle", NamedTextColor.YELLOW)
|
||||||
|
));
|
||||||
|
itemStack.setItemMeta(itemMeta);
|
||||||
|
return itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component title(String value)
|
||||||
|
{
|
||||||
|
return text(value, NamedTextColor.DARK_AQUA);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component text(String value, NamedTextColor color)
|
||||||
|
{
|
||||||
|
return Component.text(value, color).decoration(TextDecoration.ITALIC, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component line(String value, NamedTextColor color)
|
||||||
|
{
|
||||||
|
return text("> " + value, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package dev.plex.storage;
|
package dev.plex.storage;
|
||||||
|
|
||||||
import dev.plex.guild.Guild;
|
import dev.plex.guild.Guild;
|
||||||
|
import dev.plex.guild.data.GuildPermission;
|
||||||
import dev.plex.guild.data.GuildRole;
|
import dev.plex.guild.data.GuildRole;
|
||||||
import dev.plex.storage.entity.GuildInviteEntity;
|
import dev.plex.storage.entity.GuildInviteEntity;
|
||||||
import dev.plex.util.CustomLocation;
|
import dev.plex.util.CustomLocation;
|
||||||
@@ -25,6 +26,8 @@ public interface GuildRepository
|
|||||||
|
|
||||||
CompletableFuture<Void> transferOwner(UUID guildUuid, UUID newOwnerUuid, UUID oldOwnerUuid);
|
CompletableFuture<Void> transferOwner(UUID guildUuid, UUID newOwnerUuid, UUID oldOwnerUuid);
|
||||||
|
|
||||||
|
CompletableFuture<Void> updateMemberPermission(UUID guildUuid, GuildPermission permission, boolean enabled);
|
||||||
|
|
||||||
CompletableFuture<Void> updatePrefix(UUID guildUuid, String prefix);
|
CompletableFuture<Void> updatePrefix(UUID guildUuid, String prefix);
|
||||||
|
|
||||||
CompletableFuture<Void> updateHome(UUID guildUuid, CustomLocation home);
|
CompletableFuture<Void> updateHome(UUID guildUuid, CustomLocation home);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package dev.plex.storage;
|
|||||||
import dev.plex.Guilds;
|
import dev.plex.Guilds;
|
||||||
import dev.plex.api.storage.ModuleStorage;
|
import dev.plex.api.storage.ModuleStorage;
|
||||||
import dev.plex.guild.Guild;
|
import dev.plex.guild.Guild;
|
||||||
|
import dev.plex.guild.data.GuildPermission;
|
||||||
import dev.plex.guild.data.GuildRole;
|
import dev.plex.guild.data.GuildRole;
|
||||||
import dev.plex.guild.data.Member;
|
import dev.plex.guild.data.Member;
|
||||||
import dev.plex.storage.entity.GuildEntity;
|
import dev.plex.storage.entity.GuildEntity;
|
||||||
@@ -92,9 +93,10 @@ public class JdbiGuildRepository implements GuildRepository
|
|||||||
jdbi.useTransaction(h ->
|
jdbi.useTransaction(h ->
|
||||||
{
|
{
|
||||||
h.createUpdate("INSERT INTO " + guildsTable + " (guild_uuid, name, prefix, owner_uuid, created_at, " +
|
h.createUpdate("INSERT INTO " + guildsTable + " (guild_uuid, name, prefix, owner_uuid, created_at, " +
|
||||||
"home_world, home_x, home_y, home_z, home_yaw, home_pitch, motd, tag_enabled, is_public) " +
|
"home_world, home_x, home_y, home_z, home_yaw, home_pitch, motd, tag_enabled, is_public, " +
|
||||||
|
"member_block_breaking, member_block_placing, member_interacting) " +
|
||||||
"VALUES (:guildUuid, :name, :prefix, :ownerUuid, :createdAt, :homeWorld, :homeX, :homeY, :homeZ, " +
|
"VALUES (:guildUuid, :name, :prefix, :ownerUuid, :createdAt, :homeWorld, :homeX, :homeY, :homeZ, " +
|
||||||
":homeYaw, :homePitch, :motd, :tagEnabled, :isPublic)")
|
":homeYaw, :homePitch, :motd, :tagEnabled, :isPublic, :memberBlockBreaking, :memberBlockPlacing, :memberInteracting)")
|
||||||
.bind("guildUuid", e.getGuildUuid())
|
.bind("guildUuid", e.getGuildUuid())
|
||||||
.bind("name", e.getName())
|
.bind("name", e.getName())
|
||||||
.bind("prefix", e.getPrefix())
|
.bind("prefix", e.getPrefix())
|
||||||
@@ -109,6 +111,9 @@ public class JdbiGuildRepository implements GuildRepository
|
|||||||
.bind("motd", e.getMotd())
|
.bind("motd", e.getMotd())
|
||||||
.bind("tagEnabled", e.isTagEnabled())
|
.bind("tagEnabled", e.isTagEnabled())
|
||||||
.bind("isPublic", e.isPublicGuild())
|
.bind("isPublic", e.isPublicGuild())
|
||||||
|
.bind("memberBlockBreaking", e.isMemberBlockBreaking())
|
||||||
|
.bind("memberBlockPlacing", e.isMemberBlockPlacing())
|
||||||
|
.bind("memberInteracting", e.isMemberInteracting())
|
||||||
.execute();
|
.execute();
|
||||||
insertMember(h, guild.getGuildUuid(), owner.getUniqueId(), GuildRole.OWNER);
|
insertMember(h, guild.getGuildUuid(), owner.getUniqueId(), GuildRole.OWNER);
|
||||||
});
|
});
|
||||||
@@ -162,6 +167,21 @@ public class JdbiGuildRepository implements GuildRepository
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Void> updateMemberPermission(UUID guildUuid, GuildPermission permission, boolean enabled)
|
||||||
|
{
|
||||||
|
String column = switch (permission)
|
||||||
|
{
|
||||||
|
case BLOCK_BREAKING -> "member_block_breaking";
|
||||||
|
case BLOCK_PLACING -> "member_block_placing";
|
||||||
|
case INTERACTING -> "member_interacting";
|
||||||
|
};
|
||||||
|
return runAsync(() -> jdbi.useHandle(h -> h.createUpdate("UPDATE " + guildsTable + " SET " + column + " = :enabled WHERE guild_uuid = :g")
|
||||||
|
.bind("enabled", enabled)
|
||||||
|
.bind("g", guildUuid.toString())
|
||||||
|
.execute()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Void> updatePrefix(UUID guildUuid, String prefix)
|
public CompletableFuture<Void> updatePrefix(UUID guildUuid, String prefix)
|
||||||
{
|
{
|
||||||
@@ -303,6 +323,9 @@ public class JdbiGuildRepository implements GuildRepository
|
|||||||
e.setMotd(rs.getString("motd"));
|
e.setMotd(rs.getString("motd"));
|
||||||
e.setTagEnabled(rs.getBoolean("tag_enabled"));
|
e.setTagEnabled(rs.getBoolean("tag_enabled"));
|
||||||
e.setPublicGuild(rs.getBoolean("is_public"));
|
e.setPublicGuild(rs.getBoolean("is_public"));
|
||||||
|
e.setMemberBlockBreaking(rs.getBoolean("member_block_breaking"));
|
||||||
|
e.setMemberBlockPlacing(rs.getBoolean("member_block_placing"));
|
||||||
|
e.setMemberInteracting(rs.getBoolean("member_interacting"));
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,6 +376,9 @@ public class JdbiGuildRepository implements GuildRepository
|
|||||||
guild.setMotd(entity.getMotd());
|
guild.setMotd(entity.getMotd());
|
||||||
guild.setTagEnabled(entity.isTagEnabled());
|
guild.setTagEnabled(entity.isTagEnabled());
|
||||||
guild.setPublic(entity.isPublicGuild());
|
guild.setPublic(entity.isPublicGuild());
|
||||||
|
guild.setMemberBlockBreaking(entity.isMemberBlockBreaking());
|
||||||
|
guild.setMemberBlockPlacing(entity.isMemberBlockPlacing());
|
||||||
|
guild.setMemberInteracting(entity.isMemberInteracting());
|
||||||
guild.setHome(toLocation(entity));
|
guild.setHome(toLocation(entity));
|
||||||
return guild;
|
return guild;
|
||||||
}
|
}
|
||||||
@@ -368,6 +394,9 @@ public class JdbiGuildRepository implements GuildRepository
|
|||||||
entity.setMotd(guild.getMotd());
|
entity.setMotd(guild.getMotd());
|
||||||
entity.setTagEnabled(guild.isTagEnabled());
|
entity.setTagEnabled(guild.isTagEnabled());
|
||||||
entity.setPublicGuild(guild.isPublic());
|
entity.setPublicGuild(guild.isPublic());
|
||||||
|
entity.setMemberBlockBreaking(guild.isMemberBlockBreaking());
|
||||||
|
entity.setMemberBlockPlacing(guild.isMemberBlockPlacing());
|
||||||
|
entity.setMemberInteracting(guild.isMemberInteracting());
|
||||||
setHome(entity, guild.getHome());
|
setHome(entity, guild.getHome());
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ public class GuildEntity
|
|||||||
private String motd;
|
private String motd;
|
||||||
private boolean tagEnabled = true;
|
private boolean tagEnabled = true;
|
||||||
private boolean publicGuild;
|
private boolean publicGuild;
|
||||||
|
private boolean memberBlockBreaking;
|
||||||
|
private boolean memberBlockPlacing;
|
||||||
|
private boolean memberInteracting;
|
||||||
|
|
||||||
public GuildEntity()
|
public GuildEntity()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,184 @@
|
|||||||
|
package dev.plex.world;
|
||||||
|
|
||||||
|
import com.infernalsuite.asp.api.AdvancedSlimePaperAPI;
|
||||||
|
import com.infernalsuite.asp.api.exceptions.CorruptedWorldException;
|
||||||
|
import com.infernalsuite.asp.api.exceptions.NewerFormatException;
|
||||||
|
import com.infernalsuite.asp.api.exceptions.UnknownWorldException;
|
||||||
|
import com.infernalsuite.asp.api.loaders.SlimeLoader;
|
||||||
|
import com.infernalsuite.asp.api.world.SlimeWorld;
|
||||||
|
import com.infernalsuite.asp.api.world.SlimeWorldInstance;
|
||||||
|
import com.infernalsuite.asp.api.world.properties.SlimeProperties;
|
||||||
|
import com.infernalsuite.asp.api.world.properties.SlimePropertyMap;
|
||||||
|
import com.infernalsuite.asp.loaders.file.FileLoader;
|
||||||
|
import dev.plex.Guilds;
|
||||||
|
import dev.plex.guild.Guild;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class GuildWorldService
|
||||||
|
{
|
||||||
|
private final AdvancedSlimePaperAPI asp = AdvancedSlimePaperAPI.instance();
|
||||||
|
private final Map<UUID, SlimeWorldInstance> loadedWorlds = new ConcurrentHashMap<>();
|
||||||
|
private SlimeLoader loader;
|
||||||
|
|
||||||
|
public void enable()
|
||||||
|
{
|
||||||
|
File worldDirectory = new File(Guilds.get().getDataFolder(), "slime-worlds");
|
||||||
|
loader = new FileLoader(worldDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<World> ensureWorld(Guild guild)
|
||||||
|
{
|
||||||
|
SlimeWorldInstance loadedWorld = loadedWorlds.get(guild.getGuildUuid());
|
||||||
|
if (loadedWorld != null)
|
||||||
|
{
|
||||||
|
return CompletableFuture.completedFuture(loadedWorld.getBukkitWorld());
|
||||||
|
}
|
||||||
|
|
||||||
|
SlimeWorldInstance aspLoadedWorld = asp.getLoadedWorld(guild.getWorldName());
|
||||||
|
if (aspLoadedWorld != null)
|
||||||
|
{
|
||||||
|
loadedWorlds.put(guild.getGuildUuid(), aspLoadedWorld);
|
||||||
|
return CompletableFuture.completedFuture(aspLoadedWorld.getBukkitWorld());
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompletableFuture.supplyAsync(() -> readOrCreateWorld(guild), Guilds.get().api().scheduler().asyncExecutor())
|
||||||
|
.thenCompose(slimeWorld -> loadWorld(guild, slimeWorld))
|
||||||
|
.thenApply(world ->
|
||||||
|
{
|
||||||
|
initializeWorld(world);
|
||||||
|
saveWorld(guild);
|
||||||
|
return world;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveWorld(Guild guild)
|
||||||
|
{
|
||||||
|
SlimeWorldInstance loadedWorld = loadedWorlds.get(guild.getGuildUuid());
|
||||||
|
if (loadedWorld == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CompletableFuture.runAsync(() -> saveLoadedWorld(loadedWorld), Guilds.get().api().scheduler().asyncExecutor());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ejectNonMembers(Guild guild)
|
||||||
|
{
|
||||||
|
SlimeWorldInstance loadedWorld = loadedWorlds.get(guild.getGuildUuid());
|
||||||
|
if (loadedWorld == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Guilds.get().api().scheduler().executeGlobal(() ->
|
||||||
|
{
|
||||||
|
World fallback = Bukkit.getWorlds().getFirst();
|
||||||
|
loadedWorld.getBukkitWorld().getPlayers().stream()
|
||||||
|
.filter(player -> !guild.isMember(player.getUniqueId()))
|
||||||
|
.forEach(player ->
|
||||||
|
{
|
||||||
|
player.teleportAsync(fallback.getSpawnLocation());
|
||||||
|
player.sendMessage(Guilds.get().messageComponent("guildWorldNoAccess"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disable()
|
||||||
|
{
|
||||||
|
loadedWorlds.values().forEach(loadedWorld ->
|
||||||
|
{
|
||||||
|
saveLoadedWorld(loadedWorld);
|
||||||
|
Bukkit.unloadWorld(loadedWorld.getBukkitWorld(), false);
|
||||||
|
});
|
||||||
|
loadedWorlds.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SlimeWorld readOrCreateWorld(Guild guild)
|
||||||
|
{
|
||||||
|
SlimePropertyMap propertyMap = createPropertyMap();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return asp.readWorld(loader, guild.getWorldName(), false, propertyMap);
|
||||||
|
}
|
||||||
|
catch (UnknownWorldException ignored)
|
||||||
|
{
|
||||||
|
return asp.createEmptyWorld(guild.getWorldName(), false, propertyMap, loader);
|
||||||
|
}
|
||||||
|
catch (IOException | CorruptedWorldException | NewerFormatException e)
|
||||||
|
{
|
||||||
|
throw new GuildWorldException("Failed to read guild world " + guild.getWorldName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CompletableFuture<World> loadWorld(Guild guild, SlimeWorld slimeWorld)
|
||||||
|
{
|
||||||
|
CompletableFuture<World> future = new CompletableFuture<>();
|
||||||
|
Guilds.get().api().scheduler().executeGlobal(() ->
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SlimeWorldInstance loadedWorld = asp.loadWorld(slimeWorld, true);
|
||||||
|
loadedWorlds.put(guild.getGuildUuid(), loadedWorld);
|
||||||
|
future.complete(loadedWorld.getBukkitWorld());
|
||||||
|
}
|
||||||
|
catch (Throwable throwable)
|
||||||
|
{
|
||||||
|
future.completeExceptionally(throwable);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeWorld(World world)
|
||||||
|
{
|
||||||
|
int y = world.getMaxHeight() / 2;
|
||||||
|
Location spawn = new Location(world, 0.5, y + 1, 0.5);
|
||||||
|
world.getBlockAt(0, y, 0).setType(Material.GRASS_BLOCK, false);
|
||||||
|
world.setSpawnLocation(spawn);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveLoadedWorld(SlimeWorldInstance loadedWorld)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
asp.saveWorld(loadedWorld.getSerializableCopy());
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new GuildWorldException("Failed to save guild world " + loadedWorld.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SlimePropertyMap createPropertyMap()
|
||||||
|
{
|
||||||
|
SlimePropertyMap propertyMap = new SlimePropertyMap();
|
||||||
|
propertyMap.setValue(SlimeProperties.DIFFICULTY, "peaceful");
|
||||||
|
propertyMap.setValue(SlimeProperties.SPAWN_X, 0);
|
||||||
|
propertyMap.setValue(SlimeProperties.SPAWN_Y, 65);
|
||||||
|
propertyMap.setValue(SlimeProperties.SPAWN_Z, 0);
|
||||||
|
propertyMap.setValue(SlimeProperties.ALLOW_ANIMALS, false);
|
||||||
|
propertyMap.setValue(SlimeProperties.ALLOW_MONSTERS, false);
|
||||||
|
propertyMap.setValue(SlimeProperties.DRAGON_BATTLE, false);
|
||||||
|
propertyMap.setValue(SlimeProperties.PVP, false);
|
||||||
|
propertyMap.setValue(SlimeProperties.ENVIRONMENT, "normal");
|
||||||
|
propertyMap.setValue(SlimeProperties.WORLD_TYPE, "FLAT");
|
||||||
|
propertyMap.setValue(SlimeProperties.DEFAULT_BIOME, "minecraft:plains");
|
||||||
|
return propertyMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GuildWorldException extends RuntimeException
|
||||||
|
{
|
||||||
|
public GuildWorldException(String message, Throwable cause)
|
||||||
|
{
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE {{table:guilds}} ADD COLUMN `member_block_breaking` BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
|
ALTER TABLE {{table:guilds}} ADD COLUMN `member_block_placing` BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
|
ALTER TABLE {{table:guilds}} ADD COLUMN `member_interacting` BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE {{table:guilds}} ADD COLUMN member_block_breaking BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
|
ALTER TABLE {{table:guilds}} ADD COLUMN member_block_placing BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
|
ALTER TABLE {{table:guilds}} ADD COLUMN member_interacting BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE {{table:guilds}} ADD COLUMN member_block_breaking BOOLEAN NOT NULL DEFAULT 0;
|
||||||
|
ALTER TABLE {{table:guilds}} ADD COLUMN member_block_placing BOOLEAN NOT NULL DEFAULT 0;
|
||||||
|
ALTER TABLE {{table:guilds}} ADD COLUMN member_interacting BOOLEAN NOT NULL DEFAULT 0;
|
||||||
@@ -37,3 +37,8 @@ guildInviteExpired: "<red>This guild invite has expired."
|
|||||||
guildTargetAlreadyInGuild: "<red>That player is already in a guild."
|
guildTargetAlreadyInGuild: "<red>That player is already in a guild."
|
||||||
guildCannotInviteSelf: "<red>You cannot invite yourself."
|
guildCannotInviteSelf: "<red>You cannot invite yourself."
|
||||||
guildStorageFailed: "<red>The guild storage operation failed."
|
guildStorageFailed: "<red>The guild storage operation failed."
|
||||||
|
guildWorldLoading: "<green>Loading your guild world..."
|
||||||
|
guildWorldLoadFailed: "<red>Your guild world could not be loaded."
|
||||||
|
guildWorldNoAccess: "<red>You cannot access this guild world."
|
||||||
|
guildWorldPermissionDenied: "<red>Your guild rank cannot do that here."
|
||||||
|
guildMemberKicked: "<green>You removed <dark_green>{0}<green> from the guild."
|
||||||
|
|||||||
Reference in New Issue
Block a user