Allow cross-server chat messages
This commit is contained in:
parent
ac0c821a90
commit
44481e4b63
|
@ -1,5 +1,6 @@
|
|||
package tc.oc.api;
|
||||
|
||||
import tc.oc.api.chat.ChatModelManifest;
|
||||
import tc.oc.api.document.DocumentsManifest;
|
||||
import tc.oc.api.engagement.EngagementModelManifest;
|
||||
import tc.oc.api.friendships.FriendshipModelManifest;
|
||||
|
@ -46,5 +47,6 @@ public final class ApiManifest extends HybridManifest {
|
|||
install(new TrophyModelManifest());
|
||||
install(new TournamentModelManifest());
|
||||
install(new FriendshipModelManifest());
|
||||
install(new ChatModelManifest());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package tc.oc.api.chat;
|
||||
|
||||
import tc.oc.api.docs.Chat;
|
||||
import tc.oc.api.docs.virtual.ChatDoc;
|
||||
import tc.oc.api.model.ModelBinders;
|
||||
import tc.oc.commons.core.inject.HybridManifest;
|
||||
|
||||
public class ChatModelManifest extends HybridManifest implements ModelBinders {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bindModel(Chat.class, ChatDoc.Partial.class, model -> {
|
||||
model.bindDefaultService().to(model.nullService());
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package tc.oc.api.docs;
|
||||
|
||||
import tc.oc.api.annotations.Serialize;
|
||||
import tc.oc.api.docs.virtual.ChatDoc;
|
||||
|
||||
@Serialize
|
||||
public interface Chat extends ChatDoc.Complete {}
|
|
@ -0,0 +1,52 @@
|
|||
package tc.oc.api.docs.virtual;
|
||||
|
||||
import tc.oc.api.annotations.Serialize;
|
||||
import tc.oc.api.docs.PlayerId;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.Instant;
|
||||
|
||||
public interface ChatDoc {
|
||||
interface Partial extends PartialModel {}
|
||||
|
||||
@Serialize
|
||||
interface Base extends Model, Partial {
|
||||
@Nonnull String message();
|
||||
@Nonnull String server_id();
|
||||
@Nullable String match_id();
|
||||
@Nonnull Type type();
|
||||
@Nonnull Instant sent_at();
|
||||
@Nullable Broadcast broadcast();
|
||||
}
|
||||
|
||||
@Serialize
|
||||
interface Broadcast extends Partial {
|
||||
@Nonnull Destination destination();
|
||||
@Nullable String id();
|
||||
}
|
||||
|
||||
@Serialize
|
||||
interface Creation extends Base {
|
||||
@Nullable String sender_id();
|
||||
}
|
||||
|
||||
@Serialize
|
||||
interface Complete extends Base {
|
||||
@Nullable PlayerId sender();
|
||||
}
|
||||
|
||||
enum Type {
|
||||
TEAM(true), SERVER(true), ADMIN(false), BROADCAST(false);
|
||||
|
||||
public boolean batchUpdate;
|
||||
|
||||
Type(boolean batchUpdate) {
|
||||
this.batchUpdate = batchUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
enum Destination {
|
||||
SERVER, FAMILY, GAME, NETWORK, GLOBAL
|
||||
}
|
||||
}
|
|
@ -125,6 +125,7 @@ public interface ServerDoc {
|
|||
@Nullable String resource_pack_url();
|
||||
@Nullable String resource_pack_sha1();
|
||||
boolean resource_pack_fast_update();
|
||||
@Nullable String cross_server_profile();
|
||||
}
|
||||
|
||||
@Serialize
|
||||
|
|
|
@ -43,6 +43,11 @@ public interface UserDoc {
|
|||
List<String> trophy_ids();
|
||||
}
|
||||
|
||||
@Serialize
|
||||
interface Channel extends Partial {
|
||||
@Nonnull ChatDoc.Type chat_channel();
|
||||
}
|
||||
|
||||
interface License {
|
||||
|
||||
@Serialize
|
||||
|
@ -79,7 +84,7 @@ public interface UserDoc {
|
|||
* Stuff we get from the API on login, and keep around for plugins to use
|
||||
*/
|
||||
@Serialize
|
||||
interface Login extends Identity, Locale, Trophies, DefaultServer, FriendTokens, DeathScreen, License.Complete {
|
||||
interface Login extends Identity, Locale, Trophies, DefaultServer, FriendTokens, DeathScreen, License.Complete, Channel {
|
||||
int raindrops();
|
||||
int maptokens();
|
||||
int mutationtokens();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package tc.oc.api.reports;
|
||||
|
||||
import java.util.Collection;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import tc.oc.api.annotations.Serialize;
|
||||
|
@ -15,39 +15,33 @@ import static com.google.common.base.Preconditions.checkState;
|
|||
public class ReportSearchRequest extends FindRequest<Report> {
|
||||
|
||||
@Serialize private final @Nullable String server_id;
|
||||
@Serialize private final @Nullable Collection<String> family_ids;
|
||||
@Serialize private final @Nullable String user_id;
|
||||
@Serialize private final boolean cross_server;
|
||||
|
||||
private final int page, perPage;
|
||||
|
||||
private ReportSearchRequest(String server_id, Collection<String> family_ids, String user_id, int page, int perPage) {
|
||||
private ReportSearchRequest(String server_id, String user_id, boolean cross_server, int page, int perPage) {
|
||||
checkArgument(page > 0);
|
||||
checkArgument(perPage > 0);
|
||||
|
||||
this.server_id = server_id;
|
||||
this.family_ids = family_ids;
|
||||
this.user_id = user_id;
|
||||
this.cross_server = cross_server;
|
||||
this.page = page;
|
||||
this.perPage = perPage;
|
||||
}
|
||||
|
||||
public static ReportSearchRequest create(int page, int perPage) {
|
||||
return new ReportSearchRequest(null, null, null, page, perPage);
|
||||
return new ReportSearchRequest(null, null, false, page, perPage);
|
||||
}
|
||||
|
||||
public ReportSearchRequest forServer(ServerDoc.Identity server) {
|
||||
checkState(server_id == null);
|
||||
return new ReportSearchRequest(server._id(), null, null, page, perPage);
|
||||
}
|
||||
|
||||
public ReportSearchRequest forFamilies(Collection<String> familyIds) {
|
||||
checkState(family_ids == null);
|
||||
return new ReportSearchRequest(null, familyIds, null, page, perPage);
|
||||
public ReportSearchRequest forServer(ServerDoc.Identity server, boolean cross_server) {
|
||||
return new ReportSearchRequest(server._id(), null, cross_server, page, perPage);
|
||||
}
|
||||
|
||||
public ReportSearchRequest forPlayer(PlayerId playerId) {
|
||||
checkState(user_id == null);
|
||||
return new ReportSearchRequest(server_id, family_ids, playerId._id(), page, perPage);
|
||||
return new ReportSearchRequest(server_id, playerId._id(), true, page, perPage);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -23,8 +23,11 @@ import static com.google.common.base.Preconditions.checkArgument;
|
|||
@Singleton
|
||||
public class ServerStore extends ModelStore<Server> {
|
||||
|
||||
private final SetMultimap<String, Server> byName = HashMultimap.create();
|
||||
private final Map<String, Server> byBungeeName = new HashMap<>();
|
||||
private final SetMultimap<ServerDoc.Role, Server> byRole = HashMultimap.create();
|
||||
private final SetMultimap<ServerDoc.Network, Server> byNetwork = HashMultimap.create();
|
||||
private final SetMultimap<String, Server> byFamily = HashMultimap.create();
|
||||
private final SetMultimap<String, Server> byArenaId = HashMultimap.create();
|
||||
|
||||
@Override
|
||||
|
@ -32,6 +35,18 @@ public class ServerStore extends ModelStore<Server> {
|
|||
return new ServerSearchRequest();
|
||||
}
|
||||
|
||||
public ImmutableSet<Server> byName(String name) {
|
||||
return ImmutableSet.copyOf(byName.get(name));
|
||||
}
|
||||
|
||||
public ImmutableSet<Server> byNetwork(ServerDoc.Network network) {
|
||||
return ImmutableSet.copyOf(byNetwork.get(network));
|
||||
}
|
||||
|
||||
public ImmutableSet<Server> byFamily(String family) {
|
||||
return ImmutableSet.copyOf(byFamily.get(family));
|
||||
}
|
||||
|
||||
public @Nullable Server tryBungeeName(String name) {
|
||||
checkArgument(!"default".equals(name), "Cannot lookup lobbies by bungee_name");
|
||||
return byBungeeName.get(name);
|
||||
|
@ -59,10 +74,20 @@ public class ServerStore extends ModelStore<Server> {
|
|||
return playerCount;
|
||||
}
|
||||
|
||||
public boolean canCommunicate(String serverIdA, String serverIdB) {
|
||||
if(serverIdA.equals(serverIdB)) return true;
|
||||
String profileA = byId(serverIdA).cross_server_profile();
|
||||
String profileB = byId(serverIdB).cross_server_profile();
|
||||
return profileA != null && profileB != null && profileA.equalsIgnoreCase(profileB);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void unindex(Server doc) {
|
||||
super.unindex(doc);
|
||||
byName.remove(doc.name(), doc);
|
||||
byRole.remove(doc.role(), doc);
|
||||
if(doc.network() != null) byNetwork.remove(doc.network(), doc);
|
||||
if(doc.family() != null) byFamily.remove(doc.family(), doc);
|
||||
if(doc.arena_id() != null) byArenaId.remove(doc.arena_id(), doc);
|
||||
if(doc.bungee_name() != null) byBungeeName.remove(doc.bungee_name());
|
||||
}
|
||||
|
@ -70,7 +95,10 @@ public class ServerStore extends ModelStore<Server> {
|
|||
@Override
|
||||
protected void reindex(Server doc) {
|
||||
super.reindex(doc);
|
||||
byName.put(doc.name(), doc);
|
||||
byRole.put(doc.role(), doc);
|
||||
if(doc.network() != null) byNetwork.put(doc.network(), doc);
|
||||
if(doc.family() != null) byFamily.put(doc.family(), doc);
|
||||
if(doc.arena_id() != null) byArenaId.put(doc.arena_id(), doc);
|
||||
if(doc.bungee_name() != null) byBungeeName.put(doc.bungee_name(), doc);
|
||||
}
|
||||
|
|
|
@ -1,22 +1,25 @@
|
|||
package tc.oc.api.util;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import tc.oc.minecraft.api.command.CommandSender;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class Permissions {
|
||||
public interface Permissions {
|
||||
|
||||
private Permissions() {}
|
||||
|
||||
public static final String CONSOLE = "ocn.console";
|
||||
public static final String LOGIN = "ocn.login";
|
||||
public static final String STAFF = "projectares.staff";
|
||||
public static final String OBSERVER = "ocn.observer";
|
||||
public static final String PARTICIPANT = "ocn.participant";
|
||||
public static final String MAPMAKER = "ocn.mapmaker";
|
||||
public static final String DEVELOPER = "ocn.developer";
|
||||
public static final String MAPDEV = "pgm.mapdev";
|
||||
public static final String MAPERRORS = "pgm.maperrors";
|
||||
String CONSOLE = "ocn.console";
|
||||
String LOGIN = "ocn.login";
|
||||
String STAFF = "projectares.staff";
|
||||
String OBSERVER = "ocn.observer";
|
||||
String PARTICIPANT = "ocn.participant";
|
||||
String MAPMAKER = "ocn.mapmaker";
|
||||
String DEVELOPER = "ocn.developer";
|
||||
String MAPDEV = "pgm.mapdev";
|
||||
String MAPERRORS = "pgm.maperrors";
|
||||
|
||||
/**
|
||||
* Merge the given by-realm permissions into a single set of permissions using the given (ordered) realms
|
||||
|
@ -24,7 +27,7 @@ public final class Permissions {
|
|||
* @param permsByRealm Permissions, grouped by realm
|
||||
* @return Effective permissions
|
||||
*/
|
||||
public static Map<String, Boolean> mergePermissions(Collection<String> realms, Map<String, Map<String, Boolean>> permsByRealm) {
|
||||
static Map<String, Boolean> mergePermissions(Collection<String> realms, Map<String, Map<String, Boolean>> permsByRealm) {
|
||||
Map<String, Boolean> effectivePerms = new HashMap<>();
|
||||
for(String realm : realms) {
|
||||
Map<String, Boolean> perms = permsByRealm.get(realm);
|
||||
|
@ -34,4 +37,42 @@ public final class Permissions {
|
|||
}
|
||||
return effectivePerms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of enums a {@link CommandSender} has permission to use.
|
||||
*
|
||||
* This is useful for enums that correspond to an action. Instead of granting permission
|
||||
* to a user for each node, they have access to any enum below the highest ordinal node.
|
||||
* <code>
|
||||
* enum Trig {
|
||||
* SOH, CAH, TOA
|
||||
* }
|
||||
* </code>
|
||||
* So if a sender has explicit permission to ocn.foo.cah, the sender has implicit
|
||||
* permission to use Trig.SOH and Trig.CAH.
|
||||
*
|
||||
* @param sender The command sender.
|
||||
* @param enumClass The class of the enum to get the values from.
|
||||
* @return List of {@link E}s that the {@param sender} is allowed to use, ascending order based on {@link E#ordinal()}.
|
||||
*/
|
||||
static <E extends Enum> List<E> enumPermissions(CommandSender sender, String base, Class<E> enumClass) {
|
||||
final List<E> enums = Lists.newArrayList(enumClass.getEnumConstants());
|
||||
final Function<E, String> normalizer = value -> base + "." + value.name().toLowerCase().replaceAll("_", "-");
|
||||
final int max = enums.stream()
|
||||
.filter(value -> sender.hasPermission(normalizer.apply(value)))
|
||||
.map(E::ordinal)
|
||||
.max(Integer::compare)
|
||||
.orElse(-1);
|
||||
return enums.subList(0, max + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether a {@link CommandSender} has permission to use a selected {@link E}.
|
||||
*
|
||||
* @see #enumPermissions(CommandSender, String, Class)
|
||||
* @return Whether the {@param sender} has permission.
|
||||
*/
|
||||
static <E extends Enum> boolean hasPermissionForEnum(CommandSender sender, String base, E selected) {
|
||||
return enumPermissions(sender, base, (Class<E>) selected.getClass()).contains(selected);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -223,6 +223,11 @@ public class LocalServerDocument extends StartupServerDocument implements Server
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String cross_server_profile() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<UUID, String> fake_usernames() {
|
||||
return Collections.emptyMap();
|
||||
|
|
|
@ -7,12 +7,14 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import tc.oc.api.docs.PlayerId;
|
||||
import tc.oc.api.docs.SimplePlayerId;
|
||||
import tc.oc.api.docs.User;
|
||||
import tc.oc.api.docs.virtual.ChatDoc;
|
||||
import tc.oc.api.docs.virtual.UserDoc;
|
||||
import tc.oc.api.minecraft.servers.DefaultPermissions;
|
||||
|
||||
|
@ -161,4 +163,9 @@ public class LocalUserDocument extends SimplePlayerId implements User {
|
|||
public String death_screen() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatDoc.Type chat_channel() {
|
||||
return ChatDoc.Type.TEAM;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package tc.oc.api.ocn;
|
||||
|
||||
import tc.oc.api.docs.Arena;
|
||||
import tc.oc.api.docs.Chat;
|
||||
import tc.oc.api.docs.Death;
|
||||
import tc.oc.api.docs.Game;
|
||||
import tc.oc.api.docs.Objective;
|
||||
|
@ -8,6 +9,7 @@ import tc.oc.api.docs.Participation;
|
|||
import tc.oc.api.docs.Punishment;
|
||||
import tc.oc.api.docs.Report;
|
||||
import tc.oc.api.docs.Trophy;
|
||||
import tc.oc.api.docs.virtual.ChatDoc;
|
||||
import tc.oc.api.docs.virtual.DeathDoc;
|
||||
import tc.oc.api.docs.virtual.MatchDoc;
|
||||
import tc.oc.api.docs.virtual.PunishmentDoc;
|
||||
|
@ -47,6 +49,9 @@ public class OCNModelsManifest extends HybridManifest implements ModelBinders {
|
|||
bindModel(Punishment.class, PunishmentDoc.Partial.class, model -> {
|
||||
model.bindService().to(model.httpService());
|
||||
});
|
||||
bindModel(Chat.class, ChatDoc.Partial.class, model -> {
|
||||
model.bindService().to(model.httpService());
|
||||
});
|
||||
bindModel(MatchDoc.class, model -> {
|
||||
model.bindService().to(model.httpService());
|
||||
});
|
||||
|
|
|
@ -41,18 +41,6 @@
|
|||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.rmsy.Channels</groupId>
|
||||
<artifactId>Channels</artifactId>
|
||||
<version>1.9-SNAPSHOT</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>me.anxuiz</groupId>
|
||||
<artifactId>bukkit-settings</artifactId>
|
||||
|
|
|
@ -12,7 +12,8 @@ import tc.oc.bukkit.analytics.BukkitPlayerReporter;
|
|||
import tc.oc.bukkit.analytics.LatencyReporter;
|
||||
import tc.oc.bukkit.analytics.TickReporter;
|
||||
import tc.oc.commons.bukkit.broadcast.BroadcastManifest;
|
||||
import tc.oc.commons.bukkit.channels.AdminChatManifest;
|
||||
import tc.oc.commons.bukkit.channels.ChannelManifest;
|
||||
import tc.oc.commons.bukkit.chat.ChatManifest;
|
||||
import tc.oc.commons.bukkit.chat.ComponentRenderContext;
|
||||
import tc.oc.commons.bukkit.chat.ComponentRendererRegistry;
|
||||
import tc.oc.commons.bukkit.chat.ComponentRenderers;
|
||||
|
@ -62,7 +63,6 @@ import tc.oc.commons.bukkit.respack.ResourcePackManager;
|
|||
import tc.oc.commons.bukkit.restart.RestartCommands;
|
||||
import tc.oc.commons.bukkit.sessions.SessionListener;
|
||||
import tc.oc.commons.bukkit.settings.SettingManifest;
|
||||
import tc.oc.commons.bukkit.stats.StatsCommands;
|
||||
import tc.oc.commons.bukkit.stats.StatsManifest;
|
||||
import tc.oc.commons.bukkit.suspend.SuspendListener;
|
||||
import tc.oc.commons.bukkit.tablist.PlayerTabEntry;
|
||||
|
@ -104,7 +104,8 @@ public final class CommonsBukkitManifest extends HybridManifest {
|
|||
install(new SettingManifest());
|
||||
install(new WhisperManifest());
|
||||
install(new JoinMessageManifest());
|
||||
install(new AdminChatManifest());
|
||||
install(new ChatManifest());
|
||||
install(new ChannelManifest());
|
||||
install(new BroadcastManifest());
|
||||
install(new LocalizationManifest());
|
||||
install(new NavigatorManifest());
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
package tc.oc.commons.bukkit.broadcast;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
|
||||
import com.sk89q.minecraft.util.commands.SuggestionContext;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.HoverEvent;
|
||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import tc.oc.api.bukkit.users.BukkitUserStore;
|
||||
import tc.oc.api.docs.Chat;
|
||||
import tc.oc.api.docs.Game;
|
||||
import tc.oc.api.docs.Server;
|
||||
import tc.oc.api.docs.User;
|
||||
import tc.oc.api.docs.virtual.ChatDoc;
|
||||
import tc.oc.api.games.GameStore;
|
||||
import tc.oc.api.servers.ServerStore;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.chat.BukkitSound;
|
||||
import tc.oc.commons.bukkit.chat.ChatCreator;
|
||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||
import tc.oc.commons.bukkit.chat.WarningComponent;
|
||||
import tc.oc.commons.bukkit.commands.CommandUtils;
|
||||
import tc.oc.commons.bukkit.nick.IdentityProvider;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
import tc.oc.commons.core.chat.Component;
|
||||
import tc.oc.commons.core.commands.Commands;
|
||||
import tc.oc.commons.core.formatting.StringUtils;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static tc.oc.api.util.Permissions.hasPermissionForEnum;
|
||||
import static tc.oc.commons.bukkit.commands.CommandUtils.newCommandException;
|
||||
import static tc.oc.commons.bukkit.commands.CommandUtils.tryEnum;
|
||||
|
||||
/**
|
||||
* Allows {@link User}s to broadcast {@link Chat} messages across multiple servers.
|
||||
*/
|
||||
@Singleton
|
||||
public class BroadcastSender implements Commands {
|
||||
|
||||
private final static String PERMISSION = "ocn.broadcast";
|
||||
|
||||
private final Server server;
|
||||
private final ServerStore serverStore;
|
||||
private final GameStore gameStore;
|
||||
private final ChatCreator chatCreator;
|
||||
private final Audiences audiences;
|
||||
private final BukkitUserStore userStore;
|
||||
private final IdentityProvider identityProvider;
|
||||
|
||||
@Inject BroadcastSender(Server server, ServerStore serverStore, GameStore gameStore, ChatCreator chatCreator, Audiences audiences, BukkitUserStore userStore, IdentityProvider identityProvider) {
|
||||
this.server = server;
|
||||
this.serverStore = serverStore;
|
||||
this.gameStore = gameStore;
|
||||
this.chatCreator = chatCreator;
|
||||
this.audiences = audiences;
|
||||
this.userStore = userStore;
|
||||
this.identityProvider = identityProvider;
|
||||
}
|
||||
|
||||
private Set<String> destinations(@Nullable ChatDoc.Destination type) {
|
||||
Stream<String> options = Stream.empty();
|
||||
if(type != null) {
|
||||
switch(type) {
|
||||
case SERVER:
|
||||
options = serverStore.all().map(Server::name);
|
||||
break;
|
||||
case FAMILY:
|
||||
options = serverStore.all().map(Server::family);
|
||||
break;
|
||||
case GAME:
|
||||
options = gameStore.all().map(Game::name);
|
||||
break;
|
||||
case NETWORK:
|
||||
options = serverStore.all().map(Server::network).map(Enum::name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return options.map(String::toLowerCase).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "broadcast", "b" },
|
||||
desc = "Broadcast a message to players across the network.",
|
||||
usage = "<destination type> <destination name> [message...]",
|
||||
min = 1
|
||||
)
|
||||
public List<String> broadcast(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
SuggestionContext suggest = args.getSuggestionContext();
|
||||
ChatDoc.Destination type = tryEnum(args.getString(0, ""), ChatDoc.Destination.class);
|
||||
Set<String> destinations = destinations(type);
|
||||
String message = "";
|
||||
String destination = "";
|
||||
|
||||
if(suggest != null) {
|
||||
switch(suggest.getIndex()) {
|
||||
case 0:
|
||||
return CommandUtils.completeEnum(args.getString(0), ChatDoc.Destination.class);
|
||||
case 1:
|
||||
if(type != null && type != ChatDoc.Destination.GLOBAL) {
|
||||
return StringUtils.complete(args.getString(1), destinations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(type == null) {
|
||||
type = ChatDoc.Destination.SERVER;
|
||||
destination = server._id();
|
||||
message = args.getRemainingString(0);
|
||||
} else if(args.argsLength() >= 2) {
|
||||
if(type == ChatDoc.Destination.GLOBAL) {
|
||||
destination = null;
|
||||
message = args.getRemainingString(1);
|
||||
} else if(args.argsLength() >= 3) {
|
||||
destination = args.getString(1);
|
||||
message = args.getRemainingString(2);
|
||||
if(!destinations.contains(destination)) {
|
||||
throw newCommandException(sender, new WarningComponent("command.error.invalidOption", destination, destinations));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CommandUtils.notEnoughArguments(sender);
|
||||
}
|
||||
|
||||
if(hasPermissionForEnum(sender, PERMISSION, type)) {
|
||||
chatCreator.broadcast(
|
||||
sender instanceof Player ? userStore.tryUser((Player) sender) : null,
|
||||
message,
|
||||
type,
|
||||
destination
|
||||
);
|
||||
} else {
|
||||
throw new CommandPermissionsException();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void show(Chat chat) {
|
||||
final Audience audience = audiences.all();
|
||||
audience.playSound(new BukkitSound(Sound.ENTITY_ENDERDRAGON_HURT, 1, 1));
|
||||
audience.sendMessage(
|
||||
new Component(
|
||||
Lists.newArrayList(
|
||||
new Component("["),
|
||||
new TranslatableComponent("broadcast.prefix"),
|
||||
new Component("] "),
|
||||
new Component(chat.message())
|
||||
), ChatColor.RED
|
||||
).hoverEvent(
|
||||
HoverEvent.Action.SHOW_TEXT,
|
||||
new TranslatableComponent(
|
||||
"tip.sentBy",
|
||||
new PlayerComponent(identityProvider.currentOrConsoleIdentity(chat.sender()))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -59,7 +59,6 @@ public class BroadcastSettings {
|
|||
break;
|
||||
|
||||
case NEWS:
|
||||
case ALERT:
|
||||
setting = NEWS;
|
||||
break;
|
||||
|
||||
|
@ -72,6 +71,7 @@ public class BroadcastSettings {
|
|||
setting = RANDOM;
|
||||
break;
|
||||
|
||||
case ALERT:
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,131 +0,0 @@
|
|||
package tc.oc.commons.bukkit.channels;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import com.github.rmsy.channels.Channel;
|
||||
import com.github.rmsy.channels.ChannelsPlugin;
|
||||
import com.github.rmsy.channels.PlayerManager;
|
||||
import com.github.rmsy.channels.event.ChannelMessageEvent;
|
||||
import com.github.rmsy.channels.impl.SimpleChannel;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
|
||||
import com.sk89q.minecraft.util.commands.CommandUsageException;
|
||||
import com.sk89q.minecraft.util.commands.Console;
|
||||
import me.anxuiz.settings.Setting;
|
||||
import me.anxuiz.settings.SettingBuilder;
|
||||
import me.anxuiz.settings.types.BooleanType;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import tc.oc.api.bukkit.users.OnlinePlayers;
|
||||
import tc.oc.commons.bukkit.settings.SettingManagerProvider;
|
||||
import tc.oc.commons.bukkit.util.ItemCreator;
|
||||
import tc.oc.commons.core.commands.Commands;
|
||||
|
||||
@Singleton
|
||||
public class AdminChannel extends SimpleChannel implements Commands {
|
||||
|
||||
static final Setting SETTING = new SettingBuilder()
|
||||
.name("AdminChat").alias("ac")
|
||||
.summary("Show confidential staff info")
|
||||
.type(new BooleanType())
|
||||
.defaultValue(true).get();
|
||||
|
||||
public static final String PERM_NODE = "chat.admin";
|
||||
public static final String PERM_SEND = PERM_NODE + ".send";
|
||||
public static final String PERM_RECEIVE = PERM_NODE + ".receive";
|
||||
|
||||
public static final String PREFIX = ChatColor.WHITE + "[" + ChatColor.GOLD + "A" + ChatColor.WHITE + "]";
|
||||
public static final String BROADCAST_FORMAT = PREFIX + " {2}";
|
||||
public static final String FORMAT = PREFIX + " {1}" + ChatColor.WHITE + ": {2}";
|
||||
|
||||
private final ConsoleCommandSender console;
|
||||
private final OnlinePlayers players;
|
||||
private final SettingManagerProvider settings;
|
||||
|
||||
@Inject AdminChannel(ConsoleCommandSender console, OnlinePlayers players, SettingManagerProvider settings) {
|
||||
super(FORMAT, BROADCAST_FORMAT, new Permission(PERM_RECEIVE, PermissionDefault.OP));
|
||||
this.players = players;
|
||||
this.settings = settings;
|
||||
this.console = console;
|
||||
}
|
||||
|
||||
@Command(aliases = "a",
|
||||
desc = "Sends a message to the staff channel (or sets the staff channel to your default channel).",
|
||||
max = -1,
|
||||
min = 0,
|
||||
anyFlags = true,
|
||||
usage = "[message...]")
|
||||
@Console
|
||||
@CommandPermissions({PERM_SEND, PERM_RECEIVE})
|
||||
public void onAdminChatCommand(final CommandContext arguments, final CommandSender sender) throws CommandException {
|
||||
if(arguments.argsLength() == 0) {
|
||||
if (sender.hasPermission(PERM_RECEIVE)) {
|
||||
if (sender instanceof Player) {
|
||||
Player player = (Player) sender;
|
||||
PlayerManager playerManager = ChannelsPlugin.get().getPlayerManager();
|
||||
Channel oldChannel = playerManager.getMembershipChannel(player);
|
||||
playerManager.setMembershipChannel(player, this);
|
||||
if (!oldChannel.equals(this)) {
|
||||
sender.sendMessage(org.bukkit.ChatColor.YELLOW + "Changed default channel to administrator chat");
|
||||
} else {
|
||||
throw new CommandException("Administrator chat is already your default channel");
|
||||
}
|
||||
} else {
|
||||
throw new CommandUsageException("You must provide a message.", "/a <message...>");
|
||||
}
|
||||
} else {
|
||||
throw new CommandPermissionsException();
|
||||
}
|
||||
} else if (sender.hasPermission(PERM_SEND)) {
|
||||
Player sendingPlayer = null;
|
||||
if (sender instanceof Player) {
|
||||
sendingPlayer = (Player) sender;
|
||||
}
|
||||
this.sendMessage(arguments.getJoinedStrings(0), sendingPlayer);
|
||||
if (!sender.hasPermission(PERM_RECEIVE)) {
|
||||
sender.sendMessage(org.bukkit.ChatColor.YELLOW + "Message sent");
|
||||
}
|
||||
} else {
|
||||
throw new CommandPermissionsException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessageToViewer(Player sender, CommandSender viewer, String sanitizedMessage, ChannelMessageEvent event) {
|
||||
if(viewer != null && !isEnabled(viewer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.sendMessageToViewer(sender, viewer, sanitizedMessage, event);
|
||||
}
|
||||
|
||||
public boolean isEnabled(Player viewer) {
|
||||
return (boolean) settings.getManager(viewer)
|
||||
.getValue(SETTING);
|
||||
}
|
||||
|
||||
public boolean isEnabled(CommandSender viewer) {
|
||||
return !(viewer instanceof Player) || isEnabled((Player) viewer);
|
||||
}
|
||||
|
||||
public boolean isVisible(CommandSender viewer) {
|
||||
return viewer.hasPermission(getListeningPermission()) &&
|
||||
isEnabled(viewer);
|
||||
}
|
||||
|
||||
public Stream<CommandSender> viewers() {
|
||||
return Stream.<CommandSender>concat(Stream.of(console),
|
||||
players.all().stream())
|
||||
.filter(this::isVisible);
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package tc.oc.commons.bukkit.channels;
|
||||
|
||||
import tc.oc.commons.bukkit.settings.SettingBinder;
|
||||
import tc.oc.commons.core.inject.HybridManifest;
|
||||
import tc.oc.commons.core.plugin.PluginFacetBinder;
|
||||
|
||||
public class AdminChatManifest extends HybridManifest {
|
||||
@Override
|
||||
protected void configure() {
|
||||
new SettingBinder(publicBinder())
|
||||
.addBinding().toInstance(AdminChannel.SETTING);
|
||||
|
||||
new PluginFacetBinder(binder())
|
||||
.register(AdminChannel.class);
|
||||
|
||||
expose(AdminChannel.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package tc.oc.commons.bukkit.channels;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import tc.oc.api.docs.Chat;
|
||||
import tc.oc.api.docs.PlayerId;
|
||||
import tc.oc.api.docs.virtual.ChatDoc;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* An {@link Audience} that sends {@link Chat} messages to the API.
|
||||
*/
|
||||
public interface Channel extends Audience {
|
||||
|
||||
ChatDoc.Type type();
|
||||
|
||||
void chat(CommandSender sender, String message);
|
||||
|
||||
void chat(@Nullable PlayerId playerId, String message);
|
||||
|
||||
void show(Chat message);
|
||||
|
||||
boolean sendable(CommandSender sender);
|
||||
|
||||
boolean viewable(CommandSender sender);
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package tc.oc.commons.bukkit.channels;
|
||||
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import tc.oc.api.docs.PlayerId;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Called when a command sender chats in a local {@link Channel}.
|
||||
* If cancelled, the message will not be seen by users or reported to the API.
|
||||
*/
|
||||
public class ChannelChatEvent extends Event implements Cancellable {
|
||||
private final static HandlerList handlers = new HandlerList();
|
||||
|
||||
private final Channel channel;
|
||||
private final PlayerId sender;
|
||||
private final String message;
|
||||
private boolean cancelled;
|
||||
|
||||
public ChannelChatEvent(Channel channel, PlayerId sender, String message) {
|
||||
this.channel = channel;
|
||||
this.sender = sender;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public Channel channel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public @Nullable
|
||||
PlayerId sender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
public String message() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package tc.oc.commons.bukkit.channels;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
|
||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
import tc.oc.api.docs.virtual.ChatDoc;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.commands.CommandUtils;
|
||||
import tc.oc.commons.bukkit.util.SyncPlayerExecutorFactory;
|
||||
import tc.oc.commons.core.commands.Commands;
|
||||
import tc.oc.commons.core.commands.TranslatableCommandException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class ChannelCommands implements Commands, Listener {
|
||||
|
||||
private final SyncPlayerExecutorFactory syncPlayerExecutorFactory;
|
||||
private final ChannelRouter channelRouter;
|
||||
private final Audiences audiences;
|
||||
|
||||
@Inject ChannelCommands(SyncPlayerExecutorFactory syncPlayerExecutorFactory, ChannelRouter channelRouter, Audiences audiences) {
|
||||
this.syncPlayerExecutorFactory = syncPlayerExecutorFactory;
|
||||
this.channelRouter = channelRouter;
|
||||
this.audiences = audiences;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = "a",
|
||||
desc = "Send a message to the staff channel.",
|
||||
usage = "[message...]"
|
||||
)
|
||||
public void admin(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
onChatCommand(ChatDoc.Type.ADMIN, args, sender);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = "g",
|
||||
desc = "Send a message to everyone on the local server.",
|
||||
usage = "[message...]"
|
||||
)
|
||||
public void server(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
onChatCommand(ChatDoc.Type.SERVER, args, sender);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = "t",
|
||||
desc = "Send a message to your teammates.",
|
||||
usage = "[message...]"
|
||||
)
|
||||
public void chat(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
onChatCommand(ChatDoc.Type.TEAM, args, sender);
|
||||
}
|
||||
|
||||
public void onChatCommand(ChatDoc.Type type, CommandContext args, CommandSender sender) throws CommandException {
|
||||
final String typeName = type.name().toLowerCase();
|
||||
final Channel channel = channelRouter.getChannel(sender, type)
|
||||
.orElseThrow(() -> new TranslatableCommandException("channels.unavailable", typeName));
|
||||
if(channel.sendable(sender)) {
|
||||
if(args.argsLength() == 0) {
|
||||
final Player player = CommandUtils.senderToPlayer(sender);
|
||||
if(channel.equals(channelRouter.getDefaultChannel(player))) {
|
||||
throw new TranslatableCommandException("channels.default.alreadySet", typeName);
|
||||
} else {
|
||||
channelRouter.setDefaultChannel(player, channel.type());
|
||||
audiences.get(player).sendMessage(new TranslatableComponent("channels.default.set", typeName));
|
||||
}
|
||||
} else {
|
||||
channel.chat(sender, args.getRemainingString(0));
|
||||
}
|
||||
} else {
|
||||
throw new CommandPermissionsException();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onChat(AsyncPlayerChatEvent event) {
|
||||
event.setCancelled(true);
|
||||
syncPlayerExecutorFactory.queued(event.getPlayer()).execute(player -> {
|
||||
Channel channel = channelRouter.getDefaultChannel(player);
|
||||
if(!channel.sendable(player)) {
|
||||
// If player cannot chat in their preferred channel,
|
||||
// assume they can send to the default channel.
|
||||
channel = channelRouter.getDefaultChannel();
|
||||
}
|
||||
channel.chat(player, event.getMessage());
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package tc.oc.commons.bukkit.channels;
|
||||
|
||||
import tc.oc.commons.bukkit.channels.admin.AdminChannel;
|
||||
import tc.oc.commons.bukkit.channels.server.ServerChannel;
|
||||
import tc.oc.commons.bukkit.settings.SettingBinder;
|
||||
import tc.oc.commons.core.inject.HybridManifest;
|
||||
import tc.oc.commons.core.plugin.PluginFacetBinder;
|
||||
|
||||
public class ChannelManifest extends HybridManifest {
|
||||
@Override
|
||||
protected void configure() {
|
||||
|
||||
bindAndExpose(ChannelRouter.class);
|
||||
expose(ChannelCommands.class);
|
||||
expose(AdminChannel.class);
|
||||
expose(ServerChannel.class);
|
||||
|
||||
final PluginFacetBinder facets = new PluginFacetBinder(binder());
|
||||
facets.register(ChannelCommands.class);
|
||||
facets.register(AdminChannel.class);
|
||||
facets.register(ServerChannel.class);
|
||||
|
||||
final SettingBinder settings = new SettingBinder(publicBinder());
|
||||
settings.addBinding().toInstance(AdminChannel.SETTING);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package tc.oc.commons.bukkit.channels;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import tc.oc.api.bukkit.users.BukkitUserStore;
|
||||
import tc.oc.api.docs.Chat;
|
||||
import tc.oc.api.docs.User;
|
||||
import tc.oc.api.docs.virtual.ChatDoc;
|
||||
import tc.oc.api.docs.virtual.UserDoc;
|
||||
import tc.oc.api.users.UserService;
|
||||
import tc.oc.commons.bukkit.channels.admin.AdminChannel;
|
||||
import tc.oc.commons.bukkit.channels.server.ServerChannel;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Get the {@link Channel} based on the {@link ChatDoc.Type}.
|
||||
*/
|
||||
@Singleton
|
||||
public class ChannelRouter {
|
||||
|
||||
private final BukkitUserStore userStore;
|
||||
private final UserService userService;
|
||||
private final ServerChannel serverChannel;
|
||||
private final AdminChannel adminChannel;
|
||||
private Function<Player, Channel> teamChannelFunction;
|
||||
|
||||
@Inject ChannelRouter(BukkitUserStore userStore, UserService userService, ServerChannel serverChannel, AdminChannel adminChannel) {
|
||||
this.userStore = userStore;
|
||||
this.userService = userService;
|
||||
this.serverChannel = serverChannel;
|
||||
this.adminChannel = adminChannel;
|
||||
setTeamChannelFunction(null);
|
||||
}
|
||||
|
||||
public Optional<Channel> getChannel(ChatDoc.Type type) {
|
||||
return getChannel(null, type);
|
||||
}
|
||||
|
||||
public Optional<Channel> getChannel(Chat chat) {
|
||||
return getChannel(userStore.find(chat.sender()), chat.type());
|
||||
}
|
||||
|
||||
public Optional<Channel> getChannel(@Nullable CommandSender sender, ChatDoc.Type type) {
|
||||
Channel channel = null;
|
||||
if(type == ChatDoc.Type.SERVER) {
|
||||
channel = serverChannel;
|
||||
} else if(type == ChatDoc.Type.ADMIN) {
|
||||
channel = adminChannel;
|
||||
} else if(sender != null && sender instanceof Player && type == ChatDoc.Type.TEAM) {
|
||||
channel = teamChannelFunction.apply((Player) sender);
|
||||
}
|
||||
return Optional.ofNullable(channel);
|
||||
}
|
||||
|
||||
public Channel getDefaultChannel() {
|
||||
return serverChannel;
|
||||
}
|
||||
|
||||
public Channel getDefaultChannel(Player player) {
|
||||
return getChannel(player, userStore.getUser(player).chat_channel()).orElse(getDefaultChannel());
|
||||
}
|
||||
|
||||
public ListenableFuture<User> setDefaultChannel(Player player, ChatDoc.Type type) {
|
||||
return userService.update(userStore.playerId(player), new UserDoc.Channel() {
|
||||
@Override
|
||||
public ChatDoc.Type chat_channel() {
|
||||
return type;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setTeamChannelFunction(@Nullable Function<Player, Channel> function) {
|
||||
teamChannelFunction = function != null ? function : sender -> serverChannel;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package tc.oc.commons.bukkit.channels;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
|
||||
/**
|
||||
* An {@link Audience} with membership access based off of a {@link Permission} node.
|
||||
*/
|
||||
public interface PermissibleChannel extends Channel {
|
||||
|
||||
Permission permission();
|
||||
|
||||
@Override
|
||||
default boolean sendable(CommandSender sender) {
|
||||
return sender.hasPermission(permission());
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean viewable(CommandSender sender) {
|
||||
return sender.hasPermission(permission());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package tc.oc.commons.bukkit.channels;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventBus;
|
||||
import tc.oc.api.bukkit.users.BukkitUserStore;
|
||||
import tc.oc.api.docs.Chat;
|
||||
import tc.oc.api.docs.PlayerId;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.chat.ChatCreator;
|
||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||
import tc.oc.commons.bukkit.nick.IdentityProvider;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
import tc.oc.commons.core.chat.Component;
|
||||
import tc.oc.commons.core.chat.MultiAudience;
|
||||
import tc.oc.commons.core.plugin.PluginFacet;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public abstract class SimpleChannel implements MultiAudience, Channel, PluginFacet {
|
||||
|
||||
@Inject protected Audiences audiences;
|
||||
@Inject protected EventBus eventBus;
|
||||
@Inject protected BukkitUserStore userStore;
|
||||
@Inject protected ChatCreator chatCreator;
|
||||
@Inject protected IdentityProvider identityProvider;
|
||||
|
||||
// Chat messages are sent to the local server before API verification.
|
||||
// This prevents downtime or lockup from stopping all local server chat.
|
||||
protected Cache<String, Boolean> chatCache = CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(10, TimeUnit.MINUTES)
|
||||
.build();
|
||||
|
||||
public abstract BaseComponent prefix();
|
||||
|
||||
public abstract BaseComponent format(PlayerComponent player, String message);
|
||||
|
||||
@Override
|
||||
public void sendMessage(BaseComponent message) {
|
||||
MultiAudience.super.sendMessage(new Component(prefix()).extra(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<? extends Audience> audiences() {
|
||||
return Stream.of(audiences.filter(this::viewable));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chat(@Nullable PlayerId playerId, String message) {
|
||||
final ChannelChatEvent event = new ChannelChatEvent(this, playerId, message);
|
||||
eventBus.callEvent(event);
|
||||
if(!event.isCancelled()) {
|
||||
chatCreator.chat(playerId, event.message(), type(), this::show);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(Chat chat) {
|
||||
if(chatCache.getIfPresent(chat._id()) == null) {
|
||||
chatCache.put(chat._id(), true);
|
||||
sendMessage(format(
|
||||
new PlayerComponent(identityProvider.currentOrConsoleIdentity(chat.sender())),
|
||||
chat.message()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chat(CommandSender sender, String message) {
|
||||
chat(sender instanceof Player ? userStore.tryUser((Player) sender) : null, message);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package tc.oc.commons.bukkit.channels.admin;
|
||||
|
||||
import me.anxuiz.settings.Setting;
|
||||
import me.anxuiz.settings.SettingBuilder;
|
||||
import me.anxuiz.settings.types.BooleanType;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import tc.oc.api.docs.virtual.ChatDoc;
|
||||
import tc.oc.commons.bukkit.channels.PermissibleChannel;
|
||||
import tc.oc.commons.bukkit.channels.SimpleChannel;
|
||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||
import tc.oc.commons.bukkit.permissions.PermissionRegistry;
|
||||
import tc.oc.commons.bukkit.settings.SettingManagerProvider;
|
||||
import tc.oc.commons.core.chat.Component;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class AdminChannel extends SimpleChannel implements PermissibleChannel {
|
||||
|
||||
public final static Permission PERMISSION = new Permission("ocn.chat.admin", PermissionDefault.OP);
|
||||
public final static Setting SETTING = new SettingBuilder()
|
||||
.name("AdminChat")
|
||||
.alias("ac")
|
||||
.summary("Show confidential staff chat")
|
||||
.type(new BooleanType())
|
||||
.defaultValue(true)
|
||||
.get();
|
||||
|
||||
private final SettingManagerProvider settings;
|
||||
private final PermissionRegistry permissions;
|
||||
|
||||
@Inject AdminChannel(PermissionRegistry permissions, SettingManagerProvider settings) {
|
||||
this.settings = settings;
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
permissions.register(PERMISSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Permission permission() {
|
||||
return PERMISSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean viewable(CommandSender sender) {
|
||||
return !(sender instanceof Player) ||
|
||||
(PermissibleChannel.super.viewable(sender) &&
|
||||
settings.getManager((Player) sender).getValue(SETTING, Boolean.class, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseComponent prefix() {
|
||||
return new Component().extra("[").extra(new Component("A", ChatColor.GOLD)).extra("] ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseComponent format(PlayerComponent player, String message) {
|
||||
return new Component(player).extra(": ").extra(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatDoc.Type type() {
|
||||
return ChatDoc.Type.ADMIN;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package tc.oc.commons.bukkit.channels.server;
|
||||
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import tc.oc.api.docs.virtual.ChatDoc;
|
||||
import tc.oc.commons.bukkit.channels.SimpleChannel;
|
||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||
import tc.oc.commons.core.chat.Component;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class ServerChannel extends SimpleChannel {
|
||||
|
||||
@Inject ServerChannel() {}
|
||||
|
||||
@Override
|
||||
public BaseComponent prefix() {
|
||||
return new Component();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseComponent format(PlayerComponent player, String message) {
|
||||
return new Component().extra("<").extra(player).extra(">: ").extra(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatDoc.Type type() {
|
||||
return ChatDoc.Type.SERVER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendable(CommandSender sender) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean viewable(CommandSender sender) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package tc.oc.commons.bukkit.chat;
|
||||
|
||||
import tc.oc.api.docs.Chat;
|
||||
import tc.oc.api.docs.Server;
|
||||
import tc.oc.api.docs.virtual.ChatDoc;
|
||||
import tc.oc.api.message.MessageListener;
|
||||
import tc.oc.api.message.types.ModelUpdate;
|
||||
import tc.oc.api.queue.PrimaryQueue;
|
||||
import tc.oc.api.servers.ServerStore;
|
||||
import tc.oc.commons.bukkit.broadcast.BroadcastSender;
|
||||
import tc.oc.commons.bukkit.channels.Channel;
|
||||
import tc.oc.commons.bukkit.channels.ChannelRouter;
|
||||
import tc.oc.commons.core.plugin.PluginFacet;
|
||||
import tc.oc.minecraft.scheduler.MainThreadExecutor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Optional;
|
||||
|
||||
@Singleton
|
||||
public class ChatAnnouncer implements PluginFacet, MessageListener {
|
||||
|
||||
private final Server server;
|
||||
private final ServerStore serverStore;
|
||||
private final PrimaryQueue primaryQueue;
|
||||
private final MainThreadExecutor executor;
|
||||
private final ChannelRouter channelRouter;
|
||||
private final BroadcastSender broadcaster;
|
||||
|
||||
@Inject ChatAnnouncer(Server server, ServerStore serverStore, PrimaryQueue primaryQueue, MainThreadExecutor executor, ChannelRouter channelRouter, BroadcastSender broadcaster) {
|
||||
this.server = server;
|
||||
this.primaryQueue = primaryQueue;
|
||||
this.executor = executor;
|
||||
this.channelRouter = channelRouter;
|
||||
this.broadcaster = broadcaster;
|
||||
this.serverStore = serverStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
primaryQueue.bind(ModelUpdate.class);
|
||||
primaryQueue.subscribe(this, executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
primaryQueue.unsubscribe(this);
|
||||
}
|
||||
|
||||
@MessageListener.HandleMessage
|
||||
public void onChat(ModelUpdate<Chat> message) {
|
||||
final Chat chat = message.document();
|
||||
if(shouldAnnounce(chat)) {
|
||||
final ChatDoc.Type type = chat.type();
|
||||
final Optional<Channel> channel = channelRouter.getChannel(chat);
|
||||
if(channel.isPresent()) {
|
||||
channel.get().show(chat);
|
||||
} else if(type == ChatDoc.Type.BROADCAST) {
|
||||
broadcaster.show(chat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean shouldAnnounce(Chat chat) {
|
||||
final Server origin = serverStore.byId(chat.server_id());
|
||||
final boolean local = server.equals(origin);
|
||||
final boolean remote = serverStore.canCommunicate(server._id(), origin._id());
|
||||
switch(chat.type()) {
|
||||
case SERVER:
|
||||
case TEAM:
|
||||
return local;
|
||||
case ADMIN:
|
||||
return local || remote;
|
||||
case BROADCAST:
|
||||
return shouldAnnounce(chat.broadcast());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldAnnounce(ChatDoc.Broadcast broadcast) {
|
||||
final String destination = broadcast.id();
|
||||
switch(broadcast.destination()) {
|
||||
case SERVER:
|
||||
return server._id().equalsIgnoreCase(destination);
|
||||
case FAMILY:
|
||||
return server.family().equalsIgnoreCase(destination);
|
||||
case GAME:
|
||||
final String game = server.game_id();
|
||||
return game == null || game.equalsIgnoreCase(destination);
|
||||
case NETWORK:
|
||||
return server.network().name().equalsIgnoreCase(destination);
|
||||
case GLOBAL:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package tc.oc.commons.bukkit.chat;
|
||||
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import tc.oc.api.docs.Chat;
|
||||
import tc.oc.api.docs.PlayerId;
|
||||
import tc.oc.api.docs.Server;
|
||||
import tc.oc.api.docs.virtual.ChatDoc;
|
||||
import tc.oc.api.docs.virtual.MatchDoc;
|
||||
import tc.oc.api.model.BatchUpdater;
|
||||
import tc.oc.api.model.BatchUpdaterFactory;
|
||||
import tc.oc.api.model.IdFactory;
|
||||
import tc.oc.api.model.ModelService;
|
||||
import tc.oc.commons.core.plugin.PluginFacet;
|
||||
import tc.oc.minecraft.api.event.Listener;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
@Singleton
|
||||
public class ChatCreator implements PluginFacet, Listener {
|
||||
|
||||
private final IdFactory idFactory;
|
||||
private final ModelService<Chat, ChatDoc.Partial> chatService;
|
||||
private final BatchUpdater<ChatDoc.Partial> chatBatchUpdater;
|
||||
private final Server server;
|
||||
|
||||
@Inject ChatCreator(IdFactory idFactory, ModelService<Chat, ChatDoc.Partial> chatService, BatchUpdaterFactory<ChatDoc.Partial> chatBatchUpdaterFactory, Server server) {
|
||||
this.idFactory = idFactory;
|
||||
this.chatService = chatService;
|
||||
this.chatBatchUpdater = chatBatchUpdaterFactory.createBatchUpdater(Duration.ofMinutes(1));
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public ListenableFuture<Chat> chat(@Nullable PlayerId sender, String message, ChatDoc.Type type, Consumer<Chat> callback) {
|
||||
return send(sender, message, type, null, callback);
|
||||
}
|
||||
|
||||
public ListenableFuture<Chat> broadcast(@Nullable PlayerId sender, String message, ChatDoc.Destination destination, String destination_id) {
|
||||
return send(sender, message, ChatDoc.Type.BROADCAST,
|
||||
new ChatDoc.Broadcast() {
|
||||
public ChatDoc.Destination destination() { return destination; }
|
||||
public String id() { return destination_id; }
|
||||
}, null
|
||||
);
|
||||
}
|
||||
|
||||
protected ListenableFuture<Chat> send(@Nullable PlayerId sender, String message, ChatDoc.Type type, @Nullable ChatDoc.Broadcast broadcast, @Nullable Consumer<Chat> callback) {
|
||||
final Instant time = Instant.now();
|
||||
final String id = idFactory.newId();
|
||||
ChatDoc.Creation chat = new ChatDoc.Creation() {
|
||||
public String _id() { return id; }
|
||||
public String sender_id() { return sender != null ? sender._id() : null; }
|
||||
public String message() { return message; }
|
||||
public String server_id() { return server._id(); }
|
||||
public String match_id() { return ofNullable(server.current_match()).map(MatchDoc::_id).orElse(null); }
|
||||
public ChatDoc.Type type() { return type; }
|
||||
public Instant sent_at() { return time; }
|
||||
public ChatDoc.Broadcast broadcast() { return broadcast; }
|
||||
};
|
||||
// Some chats are only consumed by the local server,
|
||||
// so those messages can have delayed reporting to the API.
|
||||
if(type.batchUpdate) {
|
||||
if(callback != null) callback.accept(mock(sender, chat));
|
||||
chatBatchUpdater.update(chat);
|
||||
return Futures.immediateFuture(null);
|
||||
} else {
|
||||
return chatService.update(chat);
|
||||
}
|
||||
}
|
||||
|
||||
private Chat mock(@Nullable PlayerId sender, ChatDoc.Creation chat) {
|
||||
return new Chat() {
|
||||
public PlayerId sender() { return sender; }
|
||||
public String _id() { return chat._id(); }
|
||||
public String message() { return chat.message(); }
|
||||
public String server_id() { return chat.server_id(); }
|
||||
public String match_id() { return chat.match_id(); }
|
||||
public ChatDoc.Type type() { return chat.type(); }
|
||||
public Instant sent_at() { return chat.sent_at(); }
|
||||
public ChatDoc.Broadcast broadcast() { return chat.broadcast(); }
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package tc.oc.commons.bukkit.chat;
|
||||
|
||||
import tc.oc.commons.bukkit.broadcast.BroadcastSender;
|
||||
import tc.oc.commons.core.inject.HybridManifest;
|
||||
import tc.oc.commons.core.plugin.PluginFacetBinder;
|
||||
|
||||
public class ChatManifest extends HybridManifest {
|
||||
@Override
|
||||
protected void configure() {
|
||||
|
||||
expose(ChatCreator.class);
|
||||
expose(ChatAnnouncer.class);
|
||||
expose(BroadcastSender.class);
|
||||
|
||||
final PluginFacetBinder facets = new PluginFacetBinder(binder());
|
||||
facets.register(ChatCreator.class);
|
||||
facets.register(ChatAnnouncer.class);
|
||||
facets.register(BroadcastSender.class);
|
||||
}
|
||||
}
|
|
@ -52,7 +52,7 @@ public class Paginator<T> {
|
|||
}
|
||||
|
||||
public void display(CommandSender sender, Collection<? extends T> results, int page) {
|
||||
display(BukkitAudiences.getAudience(sender), results, page);
|
||||
display(Audiences.Deprecated.get(sender), results, page);
|
||||
}
|
||||
|
||||
public void display(Audience audience, Collection<? extends T> results, int page) {
|
||||
|
|
|
@ -2,14 +2,20 @@ package tc.oc.commons.bukkit.commands;
|
|||
|
||||
import java.time.Duration;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
|
@ -20,9 +26,11 @@ import org.bukkit.permissions.Permission;
|
|||
import tc.oc.api.docs.PlayerId;
|
||||
import tc.oc.api.docs.Server;
|
||||
import tc.oc.commons.bukkit.chat.ComponentRenderers;
|
||||
import tc.oc.commons.bukkit.chat.ListComponent;
|
||||
import tc.oc.commons.bukkit.localization.Translations;
|
||||
import tc.oc.commons.core.chat.Component;
|
||||
import tc.oc.commons.core.commands.TranslatableCommandException;
|
||||
import tc.oc.commons.core.formatting.StringUtils;
|
||||
import tc.oc.commons.core.util.TimeUtils;
|
||||
|
||||
public abstract class CommandUtils {
|
||||
|
@ -218,4 +226,35 @@ public abstract class CommandUtils {
|
|||
public static void notEnoughArguments(CommandSender sender) throws CommandException {
|
||||
throw new CommandException(Translations.get().t("command.error.notEnoughArguments", sender));
|
||||
}
|
||||
|
||||
public static <E extends Enum> Map<String, E> enumChoices(Class<E> enumClass) {
|
||||
return Stream.of(enumClass.getEnumConstants())
|
||||
.collect(Collectors.toMap(e -> e.name().toLowerCase().replaceAll("_", "-"), Function.identity()));
|
||||
}
|
||||
|
||||
public static <E extends Enum> List<String> enumChoicesList(Class<E> enumClass) {
|
||||
return new ArrayList<>(enumChoices(enumClass).keySet());
|
||||
}
|
||||
|
||||
public static @Nullable <E extends Enum> E tryEnum(String text, Class<E> enumClass) {
|
||||
return StringUtils.bestFuzzyMatch(text, enumChoices(enumClass), 0.8);
|
||||
}
|
||||
|
||||
public static <E extends Enum> E tryEnum(String text, Class<E> enumClass, E def) {
|
||||
final E option = tryEnum(text, enumClass);
|
||||
return option == null ? def : option;
|
||||
}
|
||||
|
||||
public static <E extends Enum> E getEnum(String text, Class<E> enumClass) throws CommandException {
|
||||
final E option = tryEnum(text, enumClass);
|
||||
if(option != null) {
|
||||
return option;
|
||||
} else {
|
||||
throw new TranslatableCommandException("command.error.invalidOption", text, new ListComponent(enumChoicesList(enumClass), TextComponent::new));
|
||||
}
|
||||
}
|
||||
|
||||
public static <E extends Enum> List<String> completeEnum(String prefix, Class<E> enumClass) {
|
||||
return StringUtils.complete(prefix, enumChoicesList(enumClass));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,13 @@ import tc.oc.api.docs.User;
|
|||
import tc.oc.api.friendships.FriendshipRequest;
|
||||
import tc.oc.api.friendships.FriendshipService;
|
||||
import tc.oc.api.minecraft.MinecraftService;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.chat.Links;
|
||||
import tc.oc.commons.bukkit.chat.NameStyle;
|
||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||
import tc.oc.commons.core.util.Lazy;
|
||||
import tc.oc.minecraft.scheduler.SyncExecutor;
|
||||
import tc.oc.api.sessions.SessionService;
|
||||
import tc.oc.commons.bukkit.chat.BukkitAudiences;
|
||||
import tc.oc.commons.bukkit.chat.ComponentPaginator;
|
||||
import tc.oc.commons.bukkit.chat.ComponentRenderers;
|
||||
import tc.oc.commons.bukkit.chat.HeaderComponent;
|
||||
|
@ -47,8 +47,9 @@ public class UserCommands implements Commands {
|
|||
private final UserFinder userFinder;
|
||||
private final IdentityProvider identityProvider;
|
||||
private final UserFormatter userFormatter;
|
||||
private final Audiences audiences;
|
||||
|
||||
@Inject UserCommands(MinecraftService minecraftService, SyncExecutor syncExecutor, SessionService sessionService, FriendshipService friendshipService, UserFinder userFinder, IdentityProvider identityProvider, UserFormatter userFormatter) {
|
||||
@Inject UserCommands(MinecraftService minecraftService, SyncExecutor syncExecutor, SessionService sessionService, FriendshipService friendshipService, UserFinder userFinder, IdentityProvider identityProvider, UserFormatter userFormatter, Audiences audiences) {
|
||||
this.minecraftService = minecraftService;
|
||||
this.syncExecutor = syncExecutor;
|
||||
this.sessionService = sessionService;
|
||||
|
@ -56,6 +57,7 @@ public class UserCommands implements Commands {
|
|||
this.userFinder = userFinder;
|
||||
this.identityProvider = identityProvider;
|
||||
this.userFormatter = userFormatter;
|
||||
this.audiences = audiences;
|
||||
}
|
||||
|
||||
@Command(
|
||||
|
@ -113,7 +115,7 @@ public class UserCommands implements Commands {
|
|||
@CommandPermissions("ocn.friend.request")
|
||||
public void friend(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
User friender = userFinder.getLocalUser(CommandUtils.senderToPlayer(sender));
|
||||
Audience audience = BukkitAudiences.getAudience(sender);
|
||||
Audience audience = audiences.get(sender);
|
||||
syncExecutor.callback(
|
||||
userFinder.findUser(sender, args, 0),
|
||||
response -> {
|
||||
|
@ -163,7 +165,7 @@ public class UserCommands implements Commands {
|
|||
@CommandPermissions("ocn.friend.request")
|
||||
public void unfriend(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
User friender = userFinder.getLocalUser(CommandUtils.senderToPlayer(sender));
|
||||
Audience audience = BukkitAudiences.getAudience(sender);
|
||||
Audience audience = audiences.get(sender);
|
||||
syncExecutor.callback(
|
||||
userFinder.findUser(sender, args, 0),
|
||||
response -> {
|
||||
|
@ -204,7 +206,7 @@ public class UserCommands implements Commands {
|
|||
syncExecutor.callback(
|
||||
sessionService.staff(minecraftService.getLocalServer().network(), identityProvider.revealAll(sender)),
|
||||
CommandFutureCallback.onSuccess(sender, args, result -> {
|
||||
final Audience audience = BukkitAudiences.getAudience(sender);
|
||||
final Audience audience = audiences.get(sender);
|
||||
if(result.documents().isEmpty()) {
|
||||
audience.sendMessage(new TranslatableComponent("command.staff.noStaffOnline"));
|
||||
return;
|
||||
|
|
|
@ -8,6 +8,7 @@ import javax.inject.Inject;
|
|||
import javax.inject.Singleton;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import tc.oc.api.bukkit.users.BukkitUserStore;
|
||||
import tc.oc.api.docs.virtual.UserDoc;
|
||||
|
@ -37,6 +38,7 @@ public class FlairRenderer implements PartialNameRenderer {
|
|||
@Override
|
||||
public String getLegacyName(Identity identity, NameType type) {
|
||||
if(!(type.style.contains(NameFlag.FLAIR) && type.reveal)) return "";
|
||||
if(identity.isConsole()) return ChatColor.GOLD + "❖";
|
||||
return getFlairs(identity).reduce("", String::concat);
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,11 @@ public class ConsoleIdentity implements Identity {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConsole() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(CommandSender viewer) {
|
||||
return NAME;
|
||||
|
|
|
@ -60,6 +60,11 @@ public interface Identity {
|
|||
*/
|
||||
boolean isCurrent();
|
||||
|
||||
/**
|
||||
* Does the identity belong to a console?
|
||||
*/
|
||||
boolean isConsole();
|
||||
|
||||
// Viewer-relative properties
|
||||
|
||||
/**
|
||||
|
|
|
@ -71,6 +71,11 @@ public class IdentityImpl implements Identity {
|
|||
return player != null && equals(identityProvider.currentIdentity(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConsole() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDead(CommandSender viewer) {
|
||||
if(!isOnline(viewer)) return false;
|
||||
|
|
|
@ -84,7 +84,7 @@ public class UsernameRenderer implements PartialNameRenderer {
|
|||
rendered.setColor(getColor(identity, type));
|
||||
}
|
||||
|
||||
if(type.style.contains(NameFlag.TELEPORT)) {
|
||||
if(!identity.isConsole() && type.style.contains(NameFlag.TELEPORT)) {
|
||||
Component dupe = rendered.duplicate();
|
||||
rendered.clickEvent(makeRemoteTeleportClickEvent(identity, identity.getNickname() != null && !type.reveal));
|
||||
rendered.hoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("tip.teleportTo", dupe));
|
||||
|
|
|
@ -14,25 +14,22 @@ import tc.oc.api.docs.virtual.MatchDoc;
|
|||
import tc.oc.api.docs.virtual.PunishmentDoc;
|
||||
import tc.oc.api.model.IdFactory;
|
||||
import tc.oc.api.model.ModelService;
|
||||
import tc.oc.commons.bukkit.report.ReportConfiguration;
|
||||
|
||||
@Singleton
|
||||
public class PunishmentCreator {
|
||||
|
||||
private final ReportConfiguration config;
|
||||
private final ModelService<Punishment, PunishmentDoc.Partial> punishmentService;
|
||||
private final IdFactory idFactory;
|
||||
private final Server localServer;
|
||||
|
||||
@Inject PunishmentCreator(ReportConfiguration config, ModelService<Punishment, PunishmentDoc.Partial> punishmentService, IdFactory idFactory, Server localServer) {
|
||||
this.config = config;
|
||||
@Inject PunishmentCreator(ModelService<Punishment, PunishmentDoc.Partial> punishmentService, IdFactory idFactory, Server localServer) {
|
||||
this.punishmentService = punishmentService;
|
||||
this.idFactory = idFactory;
|
||||
this.localServer = localServer;
|
||||
}
|
||||
|
||||
public boolean offRecord() {
|
||||
return !config.crossServer();
|
||||
return localServer.cross_server_profile() == null;
|
||||
}
|
||||
|
||||
public ListenableFuture<Punishment> create(@Nullable PlayerId punisher, PlayerId punished, String reason, @Nullable PunishmentDoc.Type type, @Nullable Duration duration, boolean silent, boolean auto, boolean offrecord) {
|
||||
|
|
|
@ -1,25 +1,22 @@
|
|||
package tc.oc.commons.bukkit.report;
|
||||
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import me.anxuiz.settings.Setting;
|
||||
import me.anxuiz.settings.SettingBuilder;
|
||||
import me.anxuiz.settings.types.BooleanType;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import tc.oc.api.docs.Report;
|
||||
import tc.oc.api.docs.Server;
|
||||
import tc.oc.api.message.MessageListener;
|
||||
import tc.oc.api.message.MessageQueue;
|
||||
import tc.oc.api.message.types.ModelUpdate;
|
||||
import tc.oc.commons.bukkit.channels.AdminChannel;
|
||||
import tc.oc.api.servers.ServerStore;
|
||||
import tc.oc.commons.bukkit.channels.admin.AdminChannel;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.chat.BukkitSound;
|
||||
import tc.oc.commons.bukkit.settings.SettingManagerProvider;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
import tc.oc.commons.core.plugin.PluginFacet;
|
||||
import tc.oc.minecraft.scheduler.MainThreadExecutor;
|
||||
|
||||
|
@ -39,24 +36,17 @@ public class ReportAnnouncer implements PluginFacet, MessageListener {
|
|||
private final MessageQueue primaryQueue;
|
||||
private final MainThreadExecutor executor;
|
||||
private final Server localServer;
|
||||
private final AdminChannel adminChannel;
|
||||
private final ServerStore serverStore;
|
||||
private final Audiences audiences;
|
||||
private final SettingManagerProvider settings;
|
||||
|
||||
@Inject ReportAnnouncer(ReportConfiguration config, ReportFormatter reportFormatter, MessageQueue primaryQueue, MainThreadExecutor executor, Server localServer, AdminChannel adminChannel, Audiences audiences, SettingManagerProvider settings) {
|
||||
@Inject ReportAnnouncer(ReportConfiguration config, ReportFormatter reportFormatter, MessageQueue primaryQueue, MainThreadExecutor executor, Server localServer, ServerStore serverStore, Audiences audiences) {
|
||||
this.config = config;
|
||||
this.reportFormatter = reportFormatter;
|
||||
this.primaryQueue = primaryQueue;
|
||||
this.executor = executor;
|
||||
this.localServer = localServer;
|
||||
this.adminChannel = adminChannel;
|
||||
this.serverStore = serverStore;
|
||||
this.audiences = audiences;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return config.crossServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,19 +62,9 @@ public class ReportAnnouncer implements PluginFacet, MessageListener {
|
|||
|
||||
@HandleMessage
|
||||
public void broadcast(ModelUpdate<Report> message) {
|
||||
if(localServer._id().equals(message.document().server_id()) ||
|
||||
(config.crossServer() && config.families().contains(message.document().family()))) {
|
||||
|
||||
final List<? extends BaseComponent> formatted = reportFormatter.format(message.document(), true, false);
|
||||
adminChannel.viewers()
|
||||
.filter(viewer -> viewer.hasPermission(ReportPermissions.RECEIVE))
|
||||
.forEach(viewer -> {
|
||||
Audience audience = audiences.get(viewer);
|
||||
audience.sendMessages(formatted);
|
||||
if (viewer instanceof Player && (boolean)settings.getManager((Player)viewer).getValue(SOUND_SETTING)) {
|
||||
audience.playSound(REPORT_SOUND);
|
||||
}
|
||||
});
|
||||
if(serverStore.canCommunicate(localServer._id(), message.document().server_id())) {
|
||||
audiences.permission(ReportPermissions.RECEIVE)
|
||||
.sendMessages(reportFormatter.format(message.document(), true, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,11 +161,8 @@ public class ReportCommands implements Commands, Listener {
|
|||
final boolean crossServer = args.hasFlag('a');
|
||||
|
||||
ReportSearchRequest request = ReportSearchRequest.create(page, PER_PAGE);
|
||||
request = crossServer ? request.forFamilies(reportConfiguration.families())
|
||||
: request.forServer(localServer);
|
||||
if(userResult != null) {
|
||||
request = request.forPlayer(userResult.user);
|
||||
}
|
||||
request = userResult != null ? request.forPlayer(userResult.user)
|
||||
: request.forServer(localServer, crossServer);
|
||||
|
||||
syncExecutor.callback(
|
||||
reportService.find(request),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package tc.oc.commons.bukkit.report;
|
||||
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.bukkit.configuration.Configuration;
|
||||
|
@ -22,12 +21,4 @@ public class ReportConfiguration {
|
|||
public Duration cooldown() {
|
||||
return ConfigUtils.getDuration(config, "reports.cooldown", Duration.ZERO);
|
||||
}
|
||||
|
||||
public List<String> families() {
|
||||
return config.getStringList("reports.families");
|
||||
}
|
||||
|
||||
public boolean crossServer() {
|
||||
return config.getBoolean("reports.cross-server", false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ public class TeleportListener implements MessageListener, Listener, PluginFacet,
|
|||
|
||||
@Override
|
||||
public void enable() {
|
||||
permissionRegistry.addPermission(Teleporter.PERMISSION);
|
||||
permissionRegistry.register(Teleporter.PERMISSION);
|
||||
primaryQueue.subscribe(this, syncExecutor);
|
||||
primaryQueue.bind(PlayerTeleportRequest.class);
|
||||
}
|
||||
|
|
|
@ -11,11 +11,9 @@ import org.bukkit.command.CommandSender;
|
|||
import org.bukkit.entity.Player;
|
||||
import tc.oc.api.docs.Server;
|
||||
import tc.oc.api.docs.Whisper;
|
||||
import tc.oc.api.docs.virtual.ServerDoc;
|
||||
import tc.oc.api.servers.ServerStore;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.chat.BukkitSound;
|
||||
import tc.oc.commons.bukkit.chat.ConsoleAudience;
|
||||
import tc.oc.commons.bukkit.chat.NameStyle;
|
||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||
import tc.oc.commons.bukkit.chat.UserTextComponent;
|
||||
|
@ -42,16 +40,14 @@ public class WhisperFormatter {
|
|||
private final Server localServer;
|
||||
private final SettingManagerProvider playerSettings;
|
||||
private final Audiences audiences;
|
||||
private final ConsoleAudience consoleAudience;
|
||||
|
||||
@Inject WhisperFormatter(IdentityProvider identities, MiscFormatter miscFormatter, ServerStore serverStore, Server localServer, SettingManagerProvider playerSettings, Audiences audiences, ConsoleAudience consoleAudience) {
|
||||
@Inject WhisperFormatter(IdentityProvider identities, MiscFormatter miscFormatter, ServerStore serverStore, Server localServer, SettingManagerProvider playerSettings, Audiences audiences) {
|
||||
this.identities = identities;
|
||||
this.miscFormatter = miscFormatter;
|
||||
this.serverStore = serverStore;
|
||||
this.localServer = localServer;
|
||||
this.playerSettings = playerSettings;
|
||||
this.audiences = audiences;
|
||||
this.consoleAudience = consoleAudience;
|
||||
this.serverFormatter = ServerFormatter.dark;
|
||||
}
|
||||
|
||||
|
@ -81,7 +77,7 @@ public class WhisperFormatter {
|
|||
.extra(new Component(new UserTextComponent(sender, whisper.content()), ChatColor.WHITE));
|
||||
|
||||
audience.sendMessage(display);
|
||||
consoleAudience.sendMessage(display);
|
||||
audiences.console().sendMessage(display);
|
||||
}
|
||||
|
||||
public void receive(Player viewer, Whisper whisper) {
|
||||
|
@ -135,7 +131,7 @@ public class WhisperFormatter {
|
|||
|
||||
audience.sendMessage(display);
|
||||
if(!local) {
|
||||
consoleAudience.sendMessage(display);
|
||||
audiences.console().sendMessage(display);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,6 @@ join-messages:
|
|||
reports:
|
||||
enabled: true
|
||||
cooldown: 0s
|
||||
families: []
|
||||
cross-server: true
|
||||
|
||||
datadog:
|
||||
enabled: false
|
||||
|
|
|
@ -6,7 +6,7 @@ website: ${url}
|
|||
main: ${plugin.mainClass}
|
||||
prefix: ${plugin.prefix}
|
||||
isolate: true
|
||||
depend: [API, BukkitSettings, Channels]
|
||||
depend: [API, BukkitSettings]
|
||||
|
||||
permissions:
|
||||
sudo:
|
||||
|
|
|
@ -14,6 +14,8 @@ command.error.invalidEnum = Invalid enum option '{0}'
|
|||
command.error.invalidNumber = Invalid number '{0}'
|
||||
command.error.invalidPage = There is no page {0}. Pages run from 1 to {1}.
|
||||
command.error.emptyResult = Empty result
|
||||
command.error.invalidOption = There is no option named '{0}'. Here are the possible options: \
|
||||
{1}
|
||||
command.onlyPlayers = You must be a player to use this command.
|
||||
command.error.internal = Sorry, there was an internal error while processing your command.
|
||||
|
||||
|
@ -130,6 +132,10 @@ game.description.party = Special events
|
|||
tip.teleportTo = Teleport to {0}
|
||||
tip.connectTo = Connect to {0}
|
||||
|
||||
tip.sentBy = Sent by {0}
|
||||
|
||||
broadcast.prefix = Broadcast
|
||||
|
||||
# {0} = Sender
|
||||
# {1} = Recipient
|
||||
# {2} = Relative time
|
||||
|
@ -174,6 +180,11 @@ appealNotification.count = You have - {0} - unread {1}
|
|||
misc.appeals.singular = appeal
|
||||
misc.appeals.plural = appeals
|
||||
|
||||
# {0} = chat channel type
|
||||
channels.default.alreadySet = Your default channel is already {0} chat
|
||||
channels.default.set = Your default channel is now {0} chat
|
||||
channels.unavailable = {0} chat is currently unavailable.
|
||||
|
||||
misc.enabled = enabled
|
||||
misc.disabled = disabled
|
||||
|
||||
|
|
|
@ -151,6 +151,7 @@ start.needMorePlayers.ffa.plural = Waiting for {0} more players to join
|
|||
start.needMorePlayers.team.singular = Waiting for {0} more player to join {1}
|
||||
start.needMorePlayers.team.plural = Waiting for {0} more players to join {1}
|
||||
|
||||
defuse.broadcast = {0} defused {1}'s TNT
|
||||
defuse.world = You defused world TNT.
|
||||
# {0} = the player(s)
|
||||
defuse.player = You defused {0}'s TNT.
|
||||
|
|
|
@ -41,6 +41,9 @@ command.nick.setOther.queued = {1} will be disguised as {0} the next time they c
|
|||
command.freeze.frozen = You have frozen {0}
|
||||
command.freeze.unfrozen = You have unfrozen {0}
|
||||
|
||||
freeze.frozen.broadcast = {0} has been frozen by {1}
|
||||
freeze.unfrozen.broadcast = {0} has been unfrozen by {1}
|
||||
|
||||
# {0} = the server name
|
||||
command.server.teleporting = Teleporting you to {0}
|
||||
command.server.currentServer = You are currently on {0}
|
||||
|
|
|
@ -19,7 +19,6 @@ import tc.oc.commons.core.commands.CommandRegistry;
|
|||
import tc.oc.inject.ProtectedBinder;
|
||||
import tc.oc.minecraft.logging.BetterRaven;
|
||||
import tc.oc.pgm.antigrief.CraftingProtect;
|
||||
import tc.oc.pgm.channels.ChannelCommands;
|
||||
import tc.oc.pgm.commands.MapCommands;
|
||||
import tc.oc.pgm.commands.PollCommands;
|
||||
import tc.oc.pgm.commands.RotationControlCommands;
|
||||
|
@ -195,7 +194,6 @@ public final class PGM extends JavaPlugin {
|
|||
|
||||
private void setupCommands() {
|
||||
commands.register(MapCommands.class);
|
||||
commands.register(ChannelCommands.class);
|
||||
commands.register(PollCommands.class);
|
||||
commands.register(RotationEditCommands.RotationEditParent.class);
|
||||
commands.register(RotationControlCommands.RotationControlParent.class);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package tc.oc.pgm;
|
||||
|
||||
import tc.oc.pgm.channels.ChannelManifest;
|
||||
import tc.oc.commons.core.inject.HybridManifest;
|
||||
import tc.oc.pgm.animation.AnimationManifest;
|
||||
import tc.oc.pgm.broadcast.BroadcastManifest;
|
||||
|
@ -70,6 +71,7 @@ public class PGMModulesManifest extends HybridManifest {
|
|||
install(new LaneManifest());
|
||||
install(new BroadcastManifest());
|
||||
install(new StatsManifest());
|
||||
install(new ChannelManifest());
|
||||
install(new RaindropManifest());
|
||||
install(new TokenManifest());
|
||||
install(new ObjectiveModeManifest());
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.bukkit.Location;
|
|||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
|
@ -25,14 +26,18 @@ import org.bukkit.event.player.PlayerInteractEvent;
|
|||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import tc.oc.commons.bukkit.channels.AdminChannel;
|
||||
import tc.oc.commons.bukkit.channels.admin.AdminChannel;
|
||||
import tc.oc.commons.bukkit.chat.ComponentRenderers;
|
||||
import tc.oc.commons.bukkit.chat.ListComponent;
|
||||
import tc.oc.commons.bukkit.chat.NameStyle;
|
||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||
import tc.oc.commons.bukkit.event.ObserverKitApplyEvent;
|
||||
import tc.oc.commons.bukkit.nick.IdentityProvider;
|
||||
import tc.oc.commons.core.inject.Proxied;
|
||||
import tc.oc.commons.core.plugin.PluginFacet;
|
||||
import tc.oc.pgm.PGMTranslations;
|
||||
import tc.oc.pgm.match.Match;
|
||||
import tc.oc.pgm.match.MatchFinder;
|
||||
import tc.oc.pgm.match.MatchManager;
|
||||
import tc.oc.pgm.match.MatchPlayer;
|
||||
import tc.oc.pgm.match.ParticipantState;
|
||||
|
@ -43,9 +48,10 @@ public class DefuseListener implements PluginFacet, Listener {
|
|||
public static final Material DEFUSE_ITEM = Material.SHEARS;
|
||||
public static final int DEFUSE_SLOT = 4;
|
||||
|
||||
private final MatchManager mm;
|
||||
private final EntityResolver entityResolver;
|
||||
private final AdminChannel adminChannel;
|
||||
@Inject MatchFinder mm;
|
||||
@Inject AdminChannel adminChannel;
|
||||
@Inject IdentityProvider identityProvider;
|
||||
@Inject @Proxied EntityResolver entityResolver;
|
||||
|
||||
@Inject DefuseListener(MatchManager mm, @Proxied EntityResolver entityResolver, AdminChannel adminChannel) {
|
||||
this.mm = mm;
|
||||
|
@ -72,10 +78,12 @@ public class DefuseListener implements PluginFacet, Listener {
|
|||
// check tnt
|
||||
if(!(entity instanceof TNTPrimed)) return;
|
||||
|
||||
TNTMatchModule tntmm = mm.getMatch(player.getWorld()).getMatchModule(TNTMatchModule.class);
|
||||
final Match match = mm.needMatch((CommandSender) player);
|
||||
|
||||
TNTMatchModule tntmm = match.getMatchModule(TNTMatchModule.class);
|
||||
if(tntmm != null && !tntmm.getProperties().friendlyDefuse) return;
|
||||
|
||||
MatchPlayer clicker = this.mm.getPlayer(player);
|
||||
MatchPlayer clicker = match.getPlayer(player);
|
||||
if(clicker == null || !clicker.canInteract()) return;
|
||||
|
||||
// check water
|
||||
|
@ -86,17 +94,19 @@ public class DefuseListener implements PluginFacet, Listener {
|
|||
}
|
||||
|
||||
// check owner
|
||||
MatchPlayer owner = this.mm.getPlayer(entityResolver.getOwner(entity));
|
||||
MatchPlayer owner = match.getPlayer(entityResolver.getOwner(entity));
|
||||
if(owner == null || (owner != clicker && owner.getParty() == clicker.getParty())) { // cannot defuse own TNT
|
||||
// defuse TNT
|
||||
entity.remove();
|
||||
if(owner != null) {
|
||||
this.notifyDefuse(clicker, entity, ChatColor.RED + PGMTranslations.t("defuse.player", clicker, owner.getDisplayName(clicker) + ChatColor.RED));
|
||||
adminChannel.broadcast(clicker.getDisplayName() +
|
||||
ChatColor.WHITE + " defused " +
|
||||
owner.getDisplayName()
|
||||
+ ChatColor.WHITE + "'s " +
|
||||
ChatColor.DARK_RED + "TNT");
|
||||
adminChannel.sendMessage(
|
||||
new TranslatableComponent(
|
||||
"defuse.broadcast",
|
||||
new PlayerComponent(identityProvider.currentIdentity(clicker.getPlayerId()), NameStyle.VERBOSE),
|
||||
new PlayerComponent(identityProvider.currentIdentity(owner.getPlayerId()), NameStyle.VERBOSE)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
this.notifyDefuse(clicker, entity, ChatColor.RED + PGMTranslations.t("defuse.world", clicker));
|
||||
}
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
package tc.oc.pgm.channels;
|
||||
|
||||
import com.github.rmsy.channels.Channel;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
|
||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import tc.oc.pgm.match.MatchPlayer;
|
||||
import tc.oc.pgm.PGMTranslations;
|
||||
import tc.oc.pgm.commands.CommandUtils;
|
||||
|
||||
public class ChannelCommands {
|
||||
@Command(
|
||||
aliases = "t",
|
||||
desc = "Sends a message to the team channel (or sets the team channel to your default channel).",
|
||||
usage = "[message...]",
|
||||
min = 0,
|
||||
max = -1,
|
||||
anyFlags = true
|
||||
)
|
||||
public static void teamChat(CommandContext args, CommandSender sender) throws CommandException {
|
||||
MatchPlayer player = CommandUtils.senderToMatchPlayer(sender);
|
||||
|
||||
if (player.getBukkit().hasPermission(ChannelMatchModule.TEAM_SEND_PERMISSION)) {
|
||||
ChannelMatchModule cmm = player.getMatch().needMatchModule(ChannelMatchModule.class);
|
||||
|
||||
if (args.argsLength() == 0) {
|
||||
cmm.setTeamChat(player, true);
|
||||
player.sendMessage(new TranslatableComponent("command.chat.team.switchSuccess"));
|
||||
} else {
|
||||
Channel channel = cmm.getChannel(player.getParty());
|
||||
channel.sendMessage(args.getJoinedStrings(0), player.getBukkit());
|
||||
if (!player.getBukkit().hasPermission(channel.getListeningPermission())) {
|
||||
sender.sendMessage(ChatColor.YELLOW + PGMTranslations.t("command.chat.team.success", player));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new CommandPermissionsException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package tc.oc.pgm.channels;
|
||||
|
||||
import tc.oc.commons.core.inject.HybridManifest;
|
||||
import tc.oc.pgm.match.inject.MatchModuleFixtureManifest;
|
||||
|
||||
public class ChannelManifest extends HybridManifest {
|
||||
@Override
|
||||
protected void configure() {
|
||||
installFactory(PartyChannel.Factory.class);
|
||||
install(new MatchModuleFixtureManifest<ChannelMatchModule>(){});
|
||||
}
|
||||
}
|
|
@ -1,206 +1,74 @@
|
|||
package tc.oc.pgm.channels;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.github.rmsy.channels.Channel;
|
||||
import com.github.rmsy.channels.ChannelsPlugin;
|
||||
import com.github.rmsy.channels.PlayerManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import tc.oc.chatmoderator.ChatModeratorPlugin;
|
||||
import tc.oc.commons.bukkit.chat.ComponentRenderers;
|
||||
import tc.oc.commons.bukkit.util.NullCommandSender;
|
||||
import tc.oc.commons.bukkit.util.OnlinePlayerMapAdapter;
|
||||
import tc.oc.commons.core.util.DefaultMapAdapter;
|
||||
import tc.oc.commons.bukkit.channels.Channel;
|
||||
import tc.oc.commons.bukkit.channels.ChannelRouter;
|
||||
import tc.oc.pgm.events.CompetitorAddEvent;
|
||||
import tc.oc.pgm.events.CompetitorRemoveEvent;
|
||||
import tc.oc.pgm.events.ListenerScope;
|
||||
import tc.oc.pgm.events.PartyAddEvent;
|
||||
import tc.oc.pgm.events.PartyRemoveEvent;
|
||||
import tc.oc.pgm.events.PlayerJoinPartyEvent;
|
||||
import tc.oc.pgm.events.PlayerLeavePartyEvent;
|
||||
import tc.oc.pgm.match.Match;
|
||||
import tc.oc.pgm.match.MatchModule;
|
||||
import tc.oc.pgm.match.MatchPlayer;
|
||||
import tc.oc.pgm.match.MatchScope;
|
||||
import tc.oc.pgm.match.MultiPlayerParty;
|
||||
import tc.oc.pgm.match.Party;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ListenerScope(MatchScope.LOADED)
|
||||
public class ChannelMatchModule extends MatchModule implements Listener {
|
||||
|
||||
public static final String RECEIVE_ALL_PERMISSION = "pgm.chat.all.receive";
|
||||
public static final String TEAM_RECEIVE_PERMISSION = "pgm.chat.team.receive";
|
||||
public static final String TEAM_SEND_PERMISSION = "pgm.chat.team.send";
|
||||
private final Map<Party, Channel> channels = new HashMap<>();
|
||||
|
||||
// This dynamic permission has all party channel listening permissions as children.
|
||||
// A player with this permission receives all channels simultaneously. It is granted
|
||||
// automatically to observers that have the RECEIVE_ALL_PERMISSION.
|
||||
private final Permission matchListeningPermission;
|
||||
@Inject
|
||||
ChannelRouter channelRouter;
|
||||
@Inject PartyChannel.Factory channelFactory;
|
||||
|
||||
private final ChannelsPlugin channelsPlugin = ChannelsPlugin.get();
|
||||
private final Map<MultiPlayerParty, PartyChannel> partyChannels = new HashMap<>();
|
||||
|
||||
// This is used to keep track of players' global/team chat preference. We can't just
|
||||
// check their channel through the Channels plugin because FFA players always use the
|
||||
// global channel. All players are set to team chat when they join a match, and the /t
|
||||
// command sets them to team chat. They can switch to global chat with /g, but we don't
|
||||
// know when this happens, so we check for it whenever they switch parties.
|
||||
private final Map<Player, Boolean> teamChatters;
|
||||
|
||||
@Inject ChannelMatchModule(Match match, Plugin plugin) {
|
||||
this.matchListeningPermission = new Permission("pgm.chat.all." + match.getId() + ".receive", PermissionDefault.FALSE);
|
||||
|
||||
final OnlinePlayerMapAdapter<Boolean> map = new OnlinePlayerMapAdapter<>(plugin);
|
||||
map.enable();
|
||||
this.teamChatters = new DefaultMapAdapter<>(map, true, false);
|
||||
}
|
||||
|
||||
protected void updatePlayerChannel(MatchPlayer player) {
|
||||
if(teamChatters.get(player.getBukkit())) {
|
||||
channelsPlugin.getPlayerManager().setMembershipChannel(player.getBukkit(), getChannel(player.getParty()));
|
||||
} else {
|
||||
channelsPlugin.getPlayerManager().setMembershipChannel(player.getBukkit(), channelsPlugin.getGlobalChannel());
|
||||
public void create(Party party) {
|
||||
if(!channels.containsKey(party) && party instanceof MultiPlayerParty) {
|
||||
channels.put(party, channelFactory.create(party));
|
||||
}
|
||||
}
|
||||
|
||||
public void setTeamChat(MatchPlayer player, boolean teamChat) {
|
||||
teamChatters.put(player.getBukkit(), teamChat);
|
||||
updatePlayerChannel(player);
|
||||
}
|
||||
|
||||
public Channel getChannel(Party party) {
|
||||
if(party instanceof MultiPlayerParty) {
|
||||
return partyChannels.get(party);
|
||||
} else {
|
||||
return channelsPlugin.getGlobalChannel();
|
||||
}
|
||||
}
|
||||
|
||||
protected Permission createChannelPermission(Party party) {
|
||||
Permission permission = new Permission("pgm.chat.team." + this.match.getId() + '-' + party.hashCode() + ".receive", PermissionDefault.FALSE);
|
||||
getMatch().getPluginManager().addPermission(permission);
|
||||
permission.addParent(matchListeningPermission, true);
|
||||
return permission;
|
||||
}
|
||||
|
||||
protected void removeChannelPermission(Channel channel) {
|
||||
matchListeningPermission.getChildren().remove(channel.getListeningPermission().getName());
|
||||
matchListeningPermission.recalculatePermissibles();
|
||||
getMatch().getPluginManager().removePermission(channel.getListeningPermission());
|
||||
}
|
||||
|
||||
protected void createChannel(Party party) {
|
||||
if(party instanceof MultiPlayerParty) {
|
||||
logger.fine("Creating channel for " + party);
|
||||
|
||||
String format = ComponentRenderers.toLegacyText(party.getChatPrefix(), NullCommandSender.INSTANCE) + "{1}§f: {3}";
|
||||
|
||||
PartyChannel channel;
|
||||
if (getMatch().getPluginManager().getPlugin("ChatModerator") == null) {
|
||||
channel = new UnfilteredPartyChannel(format,
|
||||
createChannelPermission(party),
|
||||
party);
|
||||
} else {
|
||||
channel = new FilteredPartyChannel(format,
|
||||
createChannelPermission(party),
|
||||
party,
|
||||
ChatModeratorPlugin.MINIMUM_SCORE_NO_SEND,
|
||||
ChatModeratorPlugin.PARTIALLY_OFFENSIVE_RATIO);
|
||||
}
|
||||
|
||||
if(partyChannels.put((MultiPlayerParty) party, channel) != null) {
|
||||
throw new IllegalStateException("Party added multiple times");
|
||||
}
|
||||
}
|
||||
public void remove(Party party) {
|
||||
channels.remove(party);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
super.load();
|
||||
|
||||
// Let the console receive all channels
|
||||
match.getPluginManager().addPermission(matchListeningPermission);
|
||||
getMatch().getServer().getConsoleSender().addAttachment(getMatch().getPlugin()).setPermission(matchListeningPermission, true);
|
||||
|
||||
// Parties may be created before the module loads
|
||||
for(Party party : getMatch().getParties()) {
|
||||
createChannel(party);
|
||||
}
|
||||
match.getParties().forEach(this::create);
|
||||
channelRouter.setTeamChannelFunction(player -> channels.get(match.player(player).map(MatchPlayer::getParty).orElse(null)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload() {
|
||||
getMatch().getServer().getConsoleSender().removeAttachments(matchListeningPermission);
|
||||
getMatch().getPluginManager().removePermission(matchListeningPermission);
|
||||
|
||||
super.unload();
|
||||
channelRouter.setTeamChannelFunction(null);
|
||||
match.getParties().forEach(this::remove);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void partyAdd(final PartyAddEvent event) {
|
||||
createChannel(event.getParty());
|
||||
public void onPartyAdd(PartyAddEvent event) {
|
||||
create(event.getParty());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void partyRemove(final PartyRemoveEvent event) {
|
||||
if(event.getParty() instanceof MultiPlayerParty) {
|
||||
PartyChannel channel = partyChannels.remove(event.getParty());
|
||||
if(channel != null) {
|
||||
removeChannelPermission(channel);
|
||||
}
|
||||
}
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPartyRemove(PartyRemoveEvent event) {
|
||||
remove(event.getParty());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void partyJoin(PlayerJoinPartyEvent event) {
|
||||
if(event.getNewParty() instanceof MultiPlayerParty) {
|
||||
PlayerManager playerManager = channelsPlugin.getPlayerManager();
|
||||
Player bukkitPlayer = event.getPlayer().getBukkit();
|
||||
PartyChannel channel = partyChannels.get(event.getNewParty());
|
||||
|
||||
if(channel != null) {
|
||||
if(event.getNewParty().isObservingType() && bukkitPlayer.hasPermission(RECEIVE_ALL_PERMISSION)) {
|
||||
// If the player is joining observers and they have the receive-all perm, let them listen to all channels
|
||||
bukkitPlayer.addAttachment(getMatch().getPlugin()).setPermission(matchListeningPermission, true);
|
||||
} else if(bukkitPlayer.hasPermission(TEAM_RECEIVE_PERMISSION)) {
|
||||
// Give the player listening permission for the team's channel
|
||||
bukkitPlayer.addAttachment(getMatch().getPlugin()).setPermission(channel.getListeningPermission(), true);
|
||||
}
|
||||
|
||||
// If their sending channel was previously set to a team channel, switch it to the new team's channel
|
||||
if(playerManager.getMembershipChannel(bukkitPlayer) instanceof PartyChannel) {
|
||||
playerManager.setMembershipChannel(bukkitPlayer, channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updatePlayerChannel(event.getPlayer());
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onCompetitorAdd(CompetitorAddEvent event) {
|
||||
create(event.getParty());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void partyLeave(PlayerLeavePartyEvent event) {
|
||||
if(event.getOldParty() instanceof MultiPlayerParty) {
|
||||
PlayerManager playerManager = channelsPlugin.getPlayerManager();
|
||||
Player bukkitPlayer = event.getPlayer().getBukkit();
|
||||
PartyChannel channel = partyChannels.get(event.getOldParty());
|
||||
|
||||
if(channel != null) {
|
||||
bukkitPlayer.removeAttachments(channel.getListeningPermission());
|
||||
bukkitPlayer.removeAttachments(matchListeningPermission);
|
||||
|
||||
// Whenever the player leaves a party with its own channel, check if that is the player's current channel,
|
||||
// and if it's not, then set their team chat setting to false. This is the only way to find out when they
|
||||
// switch to global chat, because the Channels plugin doesn't provide any notifcation.
|
||||
if(playerManager.getMembershipChannel(bukkitPlayer) != channel) {
|
||||
teamChatters.put(bukkitPlayer, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onCompetitorRemove(CompetitorRemoveEvent event) {
|
||||
remove(event.getParty());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
package tc.oc.pgm.channels;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import tc.oc.chatmoderator.channels.SimpleFilteredChannel;
|
||||
import tc.oc.pgm.match.Party;
|
||||
|
||||
public class FilteredPartyChannel extends SimpleFilteredChannel implements PartyChannel {
|
||||
|
||||
private final Party party;
|
||||
|
||||
public FilteredPartyChannel(String format, final Permission permission, final Party party, int minimumScoreNoSend, float partial) {
|
||||
super(format, permission, minimumScoreNoSend, partial);
|
||||
this.party = Preconditions.checkNotNull(party, "party");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Party getParty() {
|
||||
return this.party;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,69 @@
|
|||
package tc.oc.pgm.channels;
|
||||
|
||||
import com.github.rmsy.channels.Channel;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import tc.oc.api.docs.virtual.ChatDoc;
|
||||
import tc.oc.commons.bukkit.channels.SimpleChannel;
|
||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
import tc.oc.commons.core.chat.Component;
|
||||
import tc.oc.commons.core.chat.MultiAudience;
|
||||
import tc.oc.pgm.match.MatchPlayer;
|
||||
import tc.oc.pgm.match.Party;
|
||||
|
||||
public interface PartyChannel extends Channel {
|
||||
Party getParty();
|
||||
import javax.inject.Inject;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class PartyChannel extends SimpleChannel implements MultiAudience {
|
||||
|
||||
public static final String RECEIVE_ALL_PERMISSION = "pgm.chat.receive.all";
|
||||
|
||||
public interface Factory {
|
||||
PartyChannel create(Party party);
|
||||
}
|
||||
|
||||
private final Party party;
|
||||
|
||||
@Inject PartyChannel(@Assisted Party party) {
|
||||
this.party = party;
|
||||
}
|
||||
|
||||
public Party party() {
|
||||
return party;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseComponent prefix() {
|
||||
return party.getChatPrefix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseComponent format(PlayerComponent player, String message) {
|
||||
return new Component(player).extra(": ").extra(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatDoc.Type type() {
|
||||
return ChatDoc.Type.TEAM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendable(CommandSender sender) {
|
||||
return party.getPlayers().contains(party.getMatch().getPlayer(sender));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean viewable(CommandSender sender) {
|
||||
final MatchPlayer player = party.getMatch().getPlayer(sender);
|
||||
return sendable(sender) ||
|
||||
player == null ||
|
||||
(sender.hasPermission(RECEIVE_ALL_PERMISSION) && player.isObserving());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<? extends Audience> audiences() {
|
||||
return party.players();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
package tc.oc.pgm.channels;
|
||||
|
||||
import com.github.rmsy.channels.impl.SimpleChannel;
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import tc.oc.pgm.match.Party;
|
||||
|
||||
public class UnfilteredPartyChannel extends SimpleChannel implements PartyChannel {
|
||||
|
||||
private Party party;
|
||||
|
||||
public UnfilteredPartyChannel(String format, final Permission permission, Party party) {
|
||||
super(format, permission);
|
||||
this.party = Preconditions.checkNotNull(party, "party");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Party getParty() {
|
||||
return this.party;
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@ import org.bukkit.command.CommandSender;
|
|||
import tc.oc.api.docs.User;
|
||||
import tc.oc.api.docs.virtual.MapDoc;
|
||||
import tc.oc.api.util.Permissions;
|
||||
import tc.oc.commons.bukkit.chat.BukkitAudiences;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.chat.ComponentRenderContext;
|
||||
import tc.oc.commons.bukkit.chat.NameStyle;
|
||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||
|
@ -166,7 +166,7 @@ public class MapCommands implements Commands {
|
|||
if(args.getSuggestionContext() != null) {
|
||||
return CommandUtils.completeMapName(args.getJoinedStrings(0));
|
||||
}
|
||||
final Audience audience = BukkitAudiences.getAudience(sender);
|
||||
final Audience audience = Audiences.Deprecated.get(sender);
|
||||
final PGMMap map;
|
||||
if(args.argsLength() > 0) {
|
||||
map = CommandUtils.getMap(args.getJoinedStrings(0), sender);
|
||||
|
|
|
@ -2,6 +2,7 @@ package tc.oc.pgm.ffa;
|
|||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
@ -223,8 +224,8 @@ public class Tribute implements Competitor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Audience audience() {
|
||||
return player != null ? player : NullAudience.INSTANCE;
|
||||
public Stream<? extends Audience> audiences() {
|
||||
return player != null ? Stream.of(player) : Stream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -14,15 +14,13 @@ import org.bukkit.command.CommandSender;
|
|||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import tc.oc.commons.bukkit.channels.AdminChannel;
|
||||
import tc.oc.commons.bukkit.channels.admin.AdminChannel;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.chat.BukkitSound;
|
||||
import tc.oc.commons.bukkit.chat.NameStyle;
|
||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||
import tc.oc.commons.bukkit.commands.CommandUtils;
|
||||
import tc.oc.commons.bukkit.freeze.FrozenPlayer;
|
||||
import tc.oc.commons.bukkit.freeze.PlayerFreezer;
|
||||
import tc.oc.commons.bukkit.nick.Identity;
|
||||
import tc.oc.commons.bukkit.nick.IdentityProvider;
|
||||
import tc.oc.commons.bukkit.util.OnlinePlayerMapAdapter;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
|
@ -81,20 +79,15 @@ public class Freeze implements PluginFacet {
|
|||
));
|
||||
}
|
||||
|
||||
final Identity freezerIdentity = identityProvider.createIdentity(freezer);
|
||||
final PlayerComponent freezerComponent = new PlayerComponent(identityProvider.createIdentity(freezer), NameStyle.VERBOSE);
|
||||
final PlayerComponent freezeeComponent = new PlayerComponent(identityProvider.createIdentity(freezee), NameStyle.VERBOSE);
|
||||
final Audience freezeeAudience = audiences.get(freezee);
|
||||
|
||||
final FrozenPlayer frozenPlayer = frozenPlayers.get(freezee);
|
||||
if(frozen && frozenPlayer == null) {
|
||||
frozenPlayers.put(freezee, playerFreezer.freeze(freezee));
|
||||
|
||||
final BaseComponent freezeeMessage = new Component(
|
||||
new TranslatableComponent(
|
||||
"freeze.frozen",
|
||||
new PlayerComponent(freezerIdentity, NameStyle.FANCY)
|
||||
),
|
||||
ChatColor.RED
|
||||
);
|
||||
final BaseComponent freezeeMessage = new Component(new TranslatableComponent("freeze.frozen", freezerComponent), ChatColor.RED);
|
||||
|
||||
freezeeAudience.playSound(FREEZE_SOUND);
|
||||
freezeeAudience.sendWarning(freezeeMessage, false);
|
||||
|
@ -106,26 +99,15 @@ public class Freeze implements PluginFacet {
|
|||
removeEntities(((Player) freezer).getLocation(), config.tntSenderRadius());
|
||||
}
|
||||
|
||||
adminChannel.broadcast(CommandUtils.getDisplayName(freezer) +
|
||||
ChatColor.RED + " froze " +
|
||||
CommandUtils.getDisplayName(freezee));
|
||||
adminChannel.sendMessage(new TranslatableComponent("freeze.frozen.broadcast", freezeeComponent, freezerComponent));
|
||||
} else if(!frozen && frozenPlayer != null) {
|
||||
frozenPlayer.thaw();
|
||||
frozenPlayers.remove(freezee);
|
||||
|
||||
freezeeAudience.hideTitle();
|
||||
freezeeAudience.playSound(THAW_SOUND);
|
||||
freezeeAudience.sendMessage(new Component(
|
||||
new TranslatableComponent(
|
||||
"freeze.unfrozen",
|
||||
new PlayerComponent(freezerIdentity, NameStyle.FANCY)
|
||||
),
|
||||
ChatColor.GREEN
|
||||
));
|
||||
|
||||
adminChannel.broadcast(CommandUtils.getDisplayName(freezer) +
|
||||
ChatColor.RED + " unfroze " +
|
||||
CommandUtils.getDisplayName(freezee));
|
||||
freezeeAudience.sendMessage(new Component(new TranslatableComponent("freeze.unfrozen", freezerComponent), ChatColor.GREEN));
|
||||
adminChannel.sendMessage(new TranslatableComponent("freeze.unfrozen.broadcast", freezeeComponent, freezerComponent));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -197,11 +197,11 @@ public abstract class TouchableGoal<T extends ProximityGoalDefinition> extends P
|
|||
|
||||
if(toucher != null) {
|
||||
if(includeToucher) {
|
||||
toucher.getAudience().sendMessage(getTouchMessage(toucher, true));
|
||||
toucher.sendMessage(getTouchMessage(toucher, true));
|
||||
}
|
||||
|
||||
if(getDeferTouches()) {
|
||||
toucher.getAudience().sendMessage(new TranslatableComponent("match.touch.destroyable.deferredNotice"));
|
||||
toucher.sendMessage(new TranslatableComponent("match.touch.destroyable.deferredNotice"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -478,7 +478,7 @@ public class BlockTransformListener implements PluginFacet, Listener {
|
|||
event.getCancelMessage() != null &&
|
||||
event.isManual()) {
|
||||
|
||||
((PlayerBlockTransformEvent) event).getPlayerState().getAudience().sendWarning(event.getCancelMessage(), false);
|
||||
((PlayerBlockTransformEvent) event).getPlayerState().sendWarning(event.getCancelMessage(), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -246,7 +246,7 @@ public class MapRatingsMatchModule extends MatchModule implements Listener {
|
|||
}
|
||||
|
||||
if(oldScore != null && score == oldScore) {
|
||||
player.sendWarning(PGMTranslations.t("rating.sameRating", player, score), true);
|
||||
player.sendWarning(PGMTranslations.t("rating.sameRating", player, score), false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ import java.time.Duration;
|
|||
import java.time.Instant;
|
||||
import tc.oc.api.docs.PlayerId;
|
||||
import tc.oc.api.docs.UserId;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
import tc.oc.commons.core.chat.MultiAudience;
|
||||
import tc.oc.commons.core.inject.InjectionScopable;
|
||||
import tc.oc.commons.core.random.Entropy;
|
||||
import tc.oc.commons.core.util.ArrayUtils;
|
||||
|
@ -47,7 +47,7 @@ import tc.oc.pgm.module.ModuleLoadException;
|
|||
import tc.oc.pgm.time.TickClock;
|
||||
import tc.oc.pgm.time.TickTime;
|
||||
|
||||
public interface Match extends Audience, IMatchQuery, Filterable<IMatchQuery>, MatchPlayerFinder, InjectionScopable<MatchScoped> {
|
||||
public interface Match extends MultiAudience, IMatchQuery, Filterable<IMatchQuery>, MatchPlayerFinder, InjectionScopable<MatchScoped> {
|
||||
|
||||
/**
|
||||
* Unique ID for this match
|
||||
|
|
|
@ -1,50 +1,46 @@
|
|||
package tc.oc.pgm.match;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import tc.oc.commons.bukkit.chat.ConsoleAudience;
|
||||
import tc.oc.commons.core.chat.AbstractMultiAudience;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
import tc.oc.commons.core.chat.MultiAudience;
|
||||
import tc.oc.minecraft.api.entity.Player;
|
||||
import tc.oc.pgm.filters.Filter;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Provides various aggregate {@link Audience}s within a match
|
||||
*/
|
||||
@Singleton
|
||||
public class MatchAudiences {
|
||||
|
||||
private final Match match;
|
||||
private final Audience participants;
|
||||
private final Audience observers;
|
||||
private final ImmutableSet<ConsoleAudience> console;
|
||||
private final Audiences audiences;
|
||||
|
||||
@Inject MatchAudiences(Match match, ConsoleAudience console) {
|
||||
@Inject
|
||||
MatchAudiences(Match match, Audiences audiences) {
|
||||
this.match = match;
|
||||
this.console = ImmutableSet.of(console);
|
||||
this.participants = new MultiAudience(Iterables.concat(this.console, match.getParticipatingPlayers()));
|
||||
this.observers = new MultiAudience(Iterables.concat(this.console, match.getObservingPlayers()));
|
||||
this.audiences = audiences;
|
||||
}
|
||||
|
||||
public Audience all() {
|
||||
return match;
|
||||
public MultiAudience all() {
|
||||
return () -> Stream.of(audiences.console(), audiences.playerFilter(player -> match.player(player).isPresent()));
|
||||
}
|
||||
|
||||
public Audience participants() {
|
||||
return participants;
|
||||
public MultiAudience participants() {
|
||||
return () -> Stream.of(audiences.console(), audiences.playerFilter(player -> match.participant(player).isPresent()));
|
||||
}
|
||||
|
||||
public Audience observers() {
|
||||
return observers;
|
||||
public MultiAudience observers() {
|
||||
return () -> Stream.of(audiences.console(), audiences.playerFilter(player -> match.getObservingPlayers().contains(match.player(player).orElse(null))));
|
||||
}
|
||||
|
||||
public Audience filter(Filter filter) {
|
||||
return new AbstractMultiAudience() {
|
||||
@Override
|
||||
protected Iterable<? extends Audience> getAudiences() {
|
||||
return Iterables.concat(console, Iterables.filter(match.getPlayers(), player -> !filter.denies(player)));
|
||||
}
|
||||
};
|
||||
public MultiAudience filter(Filter filter) {
|
||||
final Set<Player> allowed = match.players().filter(player -> !filter.denies(player)).map(MatchPlayer::getBukkit).collect(Collectors.toSet());
|
||||
return () -> Stream.of(audiences.console(), audiences.playerFilter(allowed::contains));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,13 +24,10 @@ import com.google.common.collect.BiMap;
|
|||
import com.google.common.collect.BoundType;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import com.google.common.collect.Range;
|
||||
import com.google.common.collect.SetMultimap;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -45,10 +42,8 @@ import tc.oc.api.docs.PlayerId;
|
|||
import tc.oc.api.docs.User;
|
||||
import tc.oc.api.docs.UserId;
|
||||
import tc.oc.api.model.IdFactory;
|
||||
import tc.oc.commons.bukkit.chat.ConsoleAudience;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
import tc.oc.commons.core.chat.ForwardingAudience;
|
||||
import tc.oc.commons.core.chat.MultiAudience;
|
||||
import tc.oc.commons.core.exception.ExceptionHandler;
|
||||
import tc.oc.commons.core.inject.ChildInjectorFactory;
|
||||
import tc.oc.commons.core.inject.FacetContext;
|
||||
|
@ -99,7 +94,7 @@ import tc.oc.pgm.utils.WorldTickRandom;
|
|||
|
||||
import static com.google.common.base.Preconditions.*;
|
||||
|
||||
public class MatchImpl implements Match, ForwardingAudience {
|
||||
public class MatchImpl implements Match {
|
||||
|
||||
private Logger logger;
|
||||
|
||||
|
@ -121,8 +116,7 @@ public class MatchImpl implements Match, ForwardingAudience {
|
|||
@Inject private FeatureDefinitionContext featureDefinitions;
|
||||
@Inject private World world;
|
||||
|
||||
@Inject private ConsoleAudience consoleAudience;
|
||||
private Audience audience;
|
||||
@Inject private Audiences audiences;
|
||||
|
||||
// State management
|
||||
private final AtomicBoolean unloaded = new AtomicBoolean(true); // true before loading starts and after unloading finishes
|
||||
|
@ -194,7 +188,6 @@ public class MatchImpl implements Match, ForwardingAudience {
|
|||
id = idFactory.newId();
|
||||
url = new URL("http", "localhost:3000", "/matches/" + id);
|
||||
loadTime = clock.now();
|
||||
audience = new MultiAudience(Iterables.concat(ImmutableSet.of(consoleAudience), getPlayers()));
|
||||
setState(MatchState.Idle);
|
||||
}
|
||||
|
||||
|
@ -265,8 +258,8 @@ public class MatchImpl implements Match, ForwardingAudience {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Audience audience() {
|
||||
return audience;
|
||||
public Stream<Audience> audiences() {
|
||||
return Stream.of(audiences.console(), audiences.filter(sender -> player(sender).isPresent()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -927,21 +920,4 @@ public class MatchImpl implements Match, ForwardingAudience {
|
|||
partyChanges.remove(player);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --------------
|
||||
// ---- Chat ----
|
||||
// --------------
|
||||
|
||||
@Override
|
||||
public void sendMessageExcept(BaseComponent message, MatchPlayer... except) {
|
||||
consoleAudience.sendMessage(message);
|
||||
Match.super.sendMessageExcept(message, except);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessageExcept(BaseComponent message, MatchPlayerState... except) {
|
||||
consoleAudience.sendMessage(message);
|
||||
Match.super.sendMessageExcept(message, except);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import tc.oc.api.docs.PlayerId;
|
|||
import tc.oc.api.docs.Server;
|
||||
import tc.oc.api.docs.User;
|
||||
import tc.oc.commons.bukkit.attribute.AttributeUtils;
|
||||
import tc.oc.commons.bukkit.chat.BukkitAudiences;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.chat.BukkitSound;
|
||||
import tc.oc.commons.bukkit.chat.NameStyle;
|
||||
import tc.oc.commons.bukkit.chat.Named;
|
||||
|
@ -77,6 +77,7 @@ public class MatchPlayer extends MatchFacetContext<MatchPlayerFacet> implements
|
|||
@Inject private Server localServer;
|
||||
@Inject private OnlineFriends friendMap;
|
||||
@Inject private PlayerStates playerStates;
|
||||
@Inject private Audiences audiences;
|
||||
|
||||
@Inject MatchUserContext userContext;
|
||||
|
||||
|
@ -90,7 +91,7 @@ public class MatchPlayer extends MatchFacetContext<MatchPlayerFacet> implements
|
|||
private Logger logger;
|
||||
private SettingManager settings;
|
||||
private Audience audience;
|
||||
@Inject private void init(Loggers loggers, SettingManagerProvider settingManagerProvider, BukkitAudiences audiences, Player player) {
|
||||
@Inject private void init(Loggers loggers, SettingManagerProvider settingManagerProvider, Audiences audiences, Player player) {
|
||||
this.logger = loggers.get(match.getLogger(), getClass(), getName());
|
||||
this.settings = settingManagerProvider.getManager(player);
|
||||
this.audience = audiences.get(player);
|
||||
|
@ -519,19 +520,19 @@ public class MatchPlayer extends MatchFacetContext<MatchPlayerFacet> implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public Audience audience() {
|
||||
return audience;
|
||||
public Optional<Audience> audience() {
|
||||
return Optional.ofNullable(audiences.get(bukkit));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendWarning(String message, boolean audible) {
|
||||
audience().sendWarning(message, audible);
|
||||
audience().get().sendWarning(message, audible);
|
||||
if(audible) playWarningSound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendWarning(BaseComponent message, boolean audible) {
|
||||
audience().sendWarning(message, audible);
|
||||
audience().get().sendWarning(message, audible);
|
||||
if(audible) playWarningSound();
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,10 @@ public interface MatchPlayerFinder {
|
|||
return state == null ? null : getPlayer(state.getUniqueId());
|
||||
}
|
||||
|
||||
default Optional<MatchPlayer> player(@Nullable tc.oc.minecraft.api.entity.Player api) {
|
||||
return Optional.ofNullable(getPlayer((Player) api));
|
||||
}
|
||||
|
||||
default Optional<MatchPlayer> player(@Nullable Player bukkit) {
|
||||
return Optional.ofNullable(getPlayer(bukkit));
|
||||
}
|
||||
|
@ -54,6 +58,10 @@ public interface MatchPlayerFinder {
|
|||
return Optional.ofNullable(getPlayer(userId));
|
||||
}
|
||||
|
||||
default Optional<MatchPlayer> participant(@Nullable tc.oc.minecraft.api.entity.Player api) {
|
||||
return player(api).filter(MatchPlayer::isParticipating);
|
||||
}
|
||||
|
||||
default Optional<MatchPlayer> participant(@Nullable Entity entity) {
|
||||
return player(entity).filter(MatchPlayer::isParticipating);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import tc.oc.commons.bukkit.chat.NameStyle;
|
|||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||
import tc.oc.commons.bukkit.nick.Identity;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
import tc.oc.commons.core.chat.ForwardingAudience;
|
||||
import tc.oc.commons.core.chat.NullAudience;
|
||||
import tc.oc.commons.core.util.Utils;
|
||||
import tc.oc.pgm.filters.query.IPlayerQuery;
|
||||
|
@ -21,7 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
/**
|
||||
* Represents a "snapshot" view of a {@link MatchPlayer}.
|
||||
*/
|
||||
public class MatchPlayerState extends MatchEntityState implements IPlayerQuery {
|
||||
public class MatchPlayerState extends MatchEntityState implements IPlayerQuery, ForwardingAudience {
|
||||
protected final Identity identity;
|
||||
protected final Party party;
|
||||
|
||||
|
@ -88,9 +89,9 @@ public class MatchPlayerState extends MatchEntityState implements IPlayerQuery {
|
|||
return getParty().isParticipating();
|
||||
}
|
||||
|
||||
public Audience getAudience() {
|
||||
MatchPlayer matchPlayer = getMatchPlayer();
|
||||
return matchPlayer == null ? NullAudience.INSTANCE : matchPlayer;
|
||||
@Override
|
||||
public Optional<Audience> audience() {
|
||||
return Optional.ofNullable(getMatchPlayer());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,12 +2,12 @@ package tc.oc.pgm.match;
|
|||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import tc.oc.api.bukkit.users.Users;
|
||||
import tc.oc.api.docs.PlayerId;
|
||||
import tc.oc.commons.core.chat.AbstractMultiAudience;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
|
||||
public abstract class MultiPlayerParty implements Party {
|
||||
|
@ -15,13 +15,6 @@ public abstract class MultiPlayerParty implements Party {
|
|||
protected final Match match;
|
||||
private final Set<MatchPlayer> players = new HashSet<>();
|
||||
|
||||
private final Audience audience = new AbstractMultiAudience() {
|
||||
@Override
|
||||
protected Iterable<? extends Audience> getAudiences() {
|
||||
return getPlayers();
|
||||
}
|
||||
};
|
||||
|
||||
public MultiPlayerParty(Match match) {
|
||||
this.match = match;
|
||||
}
|
||||
|
@ -64,7 +57,7 @@ public abstract class MultiPlayerParty implements Party {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Audience audience() {
|
||||
return audience;
|
||||
public Stream<? extends Audience> audiences() {
|
||||
return players();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import tc.oc.commons.core.chat.Audience;
|
|||
import tc.oc.commons.bukkit.chat.Named;
|
||||
import tc.oc.commons.core.chat.Component;
|
||||
import tc.oc.commons.core.chat.Components;
|
||||
import tc.oc.commons.core.chat.MultiAudience;
|
||||
import tc.oc.pgm.filters.Filterable;
|
||||
import tc.oc.pgm.filters.query.IPartyQuery;
|
||||
|
||||
|
@ -19,7 +20,7 @@ import java.util.Optional;
|
|||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface Party extends Named, IPartyQuery, Filterable<IPartyQuery> {
|
||||
public interface Party extends Named, IPartyQuery, Filterable<IPartyQuery>, MultiAudience {
|
||||
|
||||
enum Type { Participating, Observing }
|
||||
|
||||
|
@ -156,8 +157,6 @@ public interface Party extends Named, IPartyQuery, Filterable<IPartyQuery> {
|
|||
return isObservingType() || !getMatch().isRunning();
|
||||
}
|
||||
|
||||
Audience audience();
|
||||
|
||||
@Override
|
||||
default Optional<? extends Filterable<? super IPartyQuery>> filterableParent() {
|
||||
return Optional.of(getMatch());
|
||||
|
|
|
@ -5,7 +5,6 @@ import tc.oc.pgm.api.EngagementMatchModule;
|
|||
import tc.oc.pgm.api.MatchPublishingMatchModule;
|
||||
import tc.oc.pgm.api.ParticipationPublishingMatchModule;
|
||||
import tc.oc.pgm.bossbar.BossBarMatchModule;
|
||||
import tc.oc.pgm.channels.ChannelMatchModule;
|
||||
import tc.oc.pgm.cycle.CycleMatchModule;
|
||||
import tc.oc.pgm.damage.HitboxMatchModule;
|
||||
import tc.oc.pgm.death.DeathMessageMatchModule;
|
||||
|
@ -52,7 +51,6 @@ public class MatchModulesManifest extends HybridManifest {
|
|||
install(new MatchModuleFixtureManifest<SkillRequirementMatchModule>(){});
|
||||
install(new MatchModuleFixtureManifest<StartMatchModule>(){});
|
||||
install(new MatchModuleFixtureManifest<ArrowRemovalMatchModule>(){});
|
||||
install(new MatchModuleFixtureManifest<ChannelMatchModule>(){});
|
||||
install(new MatchModuleFixtureManifest<DoubleJumpMatchModule>(){});
|
||||
install(new MatchModuleFixtureManifest<GoalMatchModule>(){});
|
||||
install(new MatchModuleFixtureManifest<ProjectileMatchModule>(){});
|
||||
|
|
|
@ -167,7 +167,7 @@ public class MutationCommands implements NestedCommands {
|
|||
}
|
||||
}
|
||||
Audience origin = audiences.get(sender);
|
||||
Audience all = audiences.localServer();
|
||||
Audience all = audiences.all();
|
||||
String message = message(!queued, value, mutations.size() == 1);
|
||||
ListComponent changed = new ListComponent(Collections2.transform(mutations, Mutation.toComponent(ChatColor.AQUA)));
|
||||
if(queued) {
|
||||
|
|
|
@ -195,7 +195,7 @@ public class EntityMutation<E extends Entity> extends KitMutation {
|
|||
|
||||
@EventHandler(ignoreCancelled = false, priority = EventPriority.HIGHEST)
|
||||
public void onPlayerSpawnEntity(PlayerSpawnEntityEvent event) {
|
||||
match().participant(event.getPlayer())
|
||||
match().participant((Entity) event.getPlayer())
|
||||
.ifPresent(player -> cast(event.getEntity(), type)
|
||||
.ifPresent(entity -> {
|
||||
register(entity, player);
|
||||
|
|
|
@ -66,7 +66,7 @@ public class DynamicRotationListener implements PluginFacet, Listener {
|
|||
rotationManager.setCurrentRotationName(rotation.name);
|
||||
|
||||
logger.info("Changing to \"" + rotation.name + "\" rotation...");
|
||||
sendRotationChangeMessage(audiences.localServer(), oldRotation, rotation.name);
|
||||
sendRotationChangeMessage(audiences.all(), oldRotation, rotation.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ import org.bukkit.entity.Player;
|
|||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import tc.oc.api.docs.virtual.ChatDoc;
|
||||
import tc.oc.commons.bukkit.channels.ChannelChatEvent;
|
||||
import tc.oc.commons.core.chat.Component;
|
||||
import tc.oc.commons.core.formatting.PeriodFormats;
|
||||
import tc.oc.commons.core.util.Comparables;
|
||||
|
@ -59,7 +61,7 @@ public class HuddleCountdown extends PreMatchCountdown implements Listener {
|
|||
|
||||
if(Comparables.greaterThan(total, Duration.ZERO)) {
|
||||
getMatch().getCompetitors().stream().filter(competitor -> competitor instanceof Team).forEach(competitor -> {
|
||||
competitor.audience().sendMessage(new Component(
|
||||
competitor.sendMessage(new Component(
|
||||
new TranslatableComponent("huddle.instructions",
|
||||
PeriodFormats.briefNaturalPrecise(total)),
|
||||
ChatColor.YELLOW
|
||||
|
@ -69,12 +71,12 @@ public class HuddleCountdown extends PreMatchCountdown implements Listener {
|
|||
}
|
||||
|
||||
@EventHandler
|
||||
public void onChat(ChannelMessageEvent event) {
|
||||
if(event.getChannel() == ChannelsPlugin.get().getGlobalChannel()) {
|
||||
public void onChat(ChannelChatEvent event) {
|
||||
if(event.channel().type().equals(ChatDoc.Type.SERVER)) {
|
||||
event.setCancelled(true);
|
||||
MatchPlayer player = getMatch().getPlayer(event.getSender());
|
||||
MatchPlayer player = getMatch().getPlayer(event.sender());
|
||||
if(player != null) {
|
||||
player.sendWarning(new TranslatableComponent("huddle.globalChatDisabled"));
|
||||
player.sendWarning(new TranslatableComponent("huddle.globalChatDisabled"), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -477,7 +477,7 @@ public class TeamMatchModule extends MatchModule implements Listener, JoinHandle
|
|||
MatchPlayer player = shortList.get(i);
|
||||
if(even && areTeamsEven() && shortList.size() - i < getTeams().size()) {
|
||||
// Prevent join if even teams are required, and there aren't enough remaining players to go around
|
||||
player.sendWarning(new TranslatableComponent("command.gameplay.join.uneven"));
|
||||
player.sendWarning(new TranslatableComponent("command.gameplay.join.uneven"), false);
|
||||
} else {
|
||||
join(player, request, queryJoin(player, request, true));
|
||||
}
|
||||
|
|
|
@ -168,9 +168,9 @@ public class WoolMatchModule extends MatchModule implements Listener {
|
|||
if(player != null) { // wool can only be placed by a player
|
||||
BaseComponent woolName = BukkitUtils.woolName(wool.getDyeColor());
|
||||
if(!isValidWool(wool.getDyeColor(), event.getNewState())) {
|
||||
player.getAudience().sendWarning(new TranslatableComponent("match.wool.placeWrong", woolName), true);
|
||||
player.sendWarning(new TranslatableComponent("match.wool.placeWrong", woolName), true);
|
||||
} else if(wool.getOwner() != player.getParty()) {
|
||||
player.getAudience().sendWarning(new TranslatableComponent("match.wool.placeOther", wool.getOwner().getComponentName(), woolName), true);
|
||||
player.sendWarning(new TranslatableComponent("match.wool.placeOther", wool.getOwner().getComponentName(), woolName), true);
|
||||
} else {
|
||||
event.setCancelled(false);
|
||||
wool.markPlaced();
|
||||
|
|
|
@ -6,9 +6,6 @@ depend:
|
|||
- Commons
|
||||
- API
|
||||
- BukkitSettings
|
||||
- Channels
|
||||
softdepend:
|
||||
- ChatModerator
|
||||
authors:
|
||||
- Overcast Network
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public class Tourney extends JavaPlugin {
|
|||
);
|
||||
|
||||
audiences.get(Bukkit.getConsoleSender()).sendMessage(message);
|
||||
audiences.withPermission(TourneyPermissions.REFEREE).sendMessage(message);
|
||||
audiences.permission(TourneyPermissions.REFEREE).sendMessage(message);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -4,7 +4,6 @@ import javax.inject.Inject;
|
|||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import com.github.rmsy.channels.ChannelsPlugin;
|
||||
import net.anxuiz.tourney.MatchManager;
|
||||
import net.anxuiz.tourney.TeamManager;
|
||||
import net.anxuiz.tourney.Tourney;
|
||||
|
@ -137,10 +136,6 @@ public class TeamListener implements Listener {
|
|||
Team team = teamManagerProvider.get().getTeam(player);
|
||||
if(team != null) {
|
||||
event.getMatch().setPlayerParty(event.getPlayer(), team, false);
|
||||
ChannelsPlugin.get().getPlayerManager().setMembershipChannel(
|
||||
player,
|
||||
event.getMatch().needMatchModule(ChannelMatchModule.class).getChannel(team)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ public class VoteContext {
|
|||
// broadcast to team
|
||||
if (classificationSelected) {
|
||||
for (Entrant participation : vote.getParticipatingTeams()) {
|
||||
final Audience team = teamManager.entrantToTeam(participation).audience();
|
||||
final Audience team = teamManager.entrantToTeam(participation);
|
||||
team.sendMessage(StringUtils.dashedChatMessage(ChatColor.GRAY + " Veto Information", "-", ChatColor.RED + "" + ChatColor.STRIKETHROUGH));
|
||||
team.sendMessage(ChatColor.GRAY + "Your team may now veto another map.");
|
||||
team.sendMessage(ChatColor.GRAY + "Note that any team member may veto. Please consult with your teammates and choose wisely.");
|
||||
|
@ -149,7 +149,7 @@ public class VoteContext {
|
|||
}
|
||||
} else {
|
||||
for (Entrant participation : vote.getParticipatingTeams()) {
|
||||
final Audience team = teamManager.entrantToTeam(participation).audience();
|
||||
final Audience team = teamManager.entrantToTeam(participation);
|
||||
team.sendMessage(StringUtils.dashedChatMessage(ChatColor.GRAY + " Veto Information", "-", ChatColor.RED + "" + ChatColor.STRIKETHROUGH));
|
||||
team.sendMessage(ChatColor.GRAY + "Your team may now veto another classification.");
|
||||
team.sendMessage(ChatColor.GRAY + "Note that any team member may veto. Please consult with your teammates and choose wisely.");
|
||||
|
|
|
@ -1,6 +1,187 @@
|
|||
package tc.oc.commons.bukkit.chat;
|
||||
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import tc.oc.commons.core.chat.AbstractAudiences;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
import tc.oc.commons.core.chat.Component;
|
||||
import tc.oc.commons.core.chat.Components;
|
||||
import tc.oc.commons.core.chat.ConsoleAudience;
|
||||
import tc.oc.commons.core.chat.NullAudience;
|
||||
import tc.oc.commons.core.chat.Sound;
|
||||
import tc.oc.commons.core.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static tc.oc.minecraft.protocol.MinecraftVersion.lessThan;
|
||||
import static tc.oc.minecraft.protocol.MinecraftVersion.MINECRAFT_1_8;
|
||||
|
||||
@Singleton
|
||||
public class Audiences extends AbstractAudiences<CommandSender> {
|
||||
|
||||
@Inject
|
||||
ComponentRenderContext renderContext;
|
||||
|
||||
@Override
|
||||
public Audience get(@Nullable CommandSender sender) {
|
||||
if(sender == null) {
|
||||
return NullAudience.INSTANCE;
|
||||
} if(sender instanceof org.bukkit.entity.Player) {
|
||||
org.bukkit.entity.Player player = (org.bukkit.entity.Player) sender;
|
||||
if(lessThan(MINECRAFT_1_8, player.getProtocolVersion())) {
|
||||
return new LegacyPlayer((org.bukkit.entity.Player) sender);
|
||||
} else {
|
||||
return new Player((org.bukkit.entity.Player) sender);
|
||||
}
|
||||
} else if(sender instanceof ConsoleCommandSender) {
|
||||
return new Console(sender.getServer().getConsoleSender());
|
||||
} else {
|
||||
return new Sender(sender);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Base<T extends CommandSender> implements Audience {
|
||||
|
||||
private final T sender;
|
||||
|
||||
protected Base(T sender) {
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
protected T sender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(BaseComponent message) {
|
||||
sender().sendMessage(render(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendWarning(BaseComponent message, boolean audible) {
|
||||
sendMessage(new WarningComponent(message));
|
||||
}
|
||||
|
||||
protected BaseComponent render(@Nullable BaseComponent component) {
|
||||
return component == null ? new Component() : renderContext.render(component, sender());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Sender extends Base<CommandSender> {
|
||||
|
||||
public Sender(CommandSender sender) {
|
||||
super(sender);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(Sound sound) {}
|
||||
|
||||
@Override
|
||||
public void stopSound(Sound sound) {}
|
||||
|
||||
@Override
|
||||
public void sendHotbarMessage(BaseComponent message) {
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTitle(@Nullable BaseComponent title, @Nullable BaseComponent subtitle, int inTicks, int stayTicks, int outTicks) {
|
||||
Optional.ofNullable(title).ifPresent(this::sendMessage);
|
||||
Optional.ofNullable(subtitle).ifPresent(this::sendMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideTitle() {}
|
||||
|
||||
}
|
||||
|
||||
class Player extends Base<org.bukkit.entity.Player> {
|
||||
|
||||
public Player(org.bukkit.entity.Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendHotbarMessage(BaseComponent message) {
|
||||
sender().sendMessage(ChatMessageType.ACTION_BAR, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideTitle() {
|
||||
sender().hideTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTitle(@Nullable BaseComponent title, @Nullable BaseComponent subtitle, int inTicks, int stayTicks, int outTicks) {
|
||||
sender().showTitle(render(title), render(subtitle), inTicks, stayTicks, outTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(Sound sound) {
|
||||
sender().playSound(sender().getLocation(), sound.name(), sound.volume(), sound.pitch());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopSound(Sound sound) {
|
||||
sender().stopSound(sound.name());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class LegacyPlayer extends Player {
|
||||
|
||||
private BaseComponent recentHotbarMessage;
|
||||
|
||||
public LegacyPlayer(org.bukkit.entity.Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
protected void emphasize(BaseComponent message) {
|
||||
sendMessage(Components.blank());
|
||||
sendMessage(message);
|
||||
sendMessage(Components.blank());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendHotbarMessage(BaseComponent message) {
|
||||
// Do not spam hot bar messages, as the protocol converts
|
||||
// them to regular chat messages.
|
||||
if(!Components.equals(message, recentHotbarMessage)) {
|
||||
emphasize(message);
|
||||
recentHotbarMessage = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTitle(@Nullable BaseComponent title, @Nullable BaseComponent subtitle, int inTicks, int stayTicks, int outTicks) {
|
||||
emphasize(Components.join(Components.space(), Stream.of(title, subtitle).filter(msg -> msg != null).collect(Collectors.toImmutableList())));
|
||||
}
|
||||
}
|
||||
|
||||
class Console extends Base<ConsoleCommandSender> implements ConsoleAudience {
|
||||
|
||||
public Console(ConsoleCommandSender sender) {
|
||||
super(sender);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Deprecated {
|
||||
|
||||
@Inject static Audiences audiences;
|
||||
|
||||
@java.lang.Deprecated
|
||||
public static Audience get(@Nullable CommandSender sender) {
|
||||
return audiences.get(sender);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public interface Audiences extends tc.oc.commons.core.chat.Audiences<CommandSender> {
|
||||
}
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
package tc.oc.commons.bukkit.chat;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
import tc.oc.commons.core.chat.MinecraftAudiences;
|
||||
import tc.oc.commons.core.chat.NullAudience;
|
||||
|
||||
import static tc.oc.minecraft.protocol.MinecraftVersion.lessThan;
|
||||
import static tc.oc.minecraft.protocol.MinecraftVersion.MINECRAFT_1_8;
|
||||
|
||||
@Singleton
|
||||
public class BukkitAudiences extends MinecraftAudiences<CommandSender> implements Audiences {
|
||||
|
||||
@Deprecated
|
||||
public static Audience getAudience(CommandSender sender) {
|
||||
if(sender == null) {
|
||||
return NullAudience.INSTANCE;
|
||||
} if(sender instanceof Player) {
|
||||
Player player = (Player) sender;
|
||||
if(lessThan(MINECRAFT_1_8, player.getProtocolVersion())) {
|
||||
return new LegacyPlayerAudience(player);
|
||||
} else {
|
||||
return new PlayerAudience(player);
|
||||
}
|
||||
} else if(sender instanceof ConsoleCommandSender) {
|
||||
return new ConsoleAudience(sender.getServer());
|
||||
} else {
|
||||
return new CommandSenderAudience(sender);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Audience get(CommandSender viewer) {
|
||||
return getAudience(viewer);
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package tc.oc.commons.bukkit.chat;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import tc.oc.commons.core.chat.AbstractAudience;
|
||||
import tc.oc.commons.core.chat.Sound;
|
||||
|
||||
public class CommandSenderAudience extends AbstractAudience {
|
||||
|
||||
protected final CommandSender sender;
|
||||
|
||||
public CommandSenderAudience(CommandSender sender) {
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
protected CommandSender getCommandSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
getCommandSender().sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(BaseComponent message) {
|
||||
ComponentRenderers.send(getCommandSender(), message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendHotbarMessage(BaseComponent message) {
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTitle(@Nullable BaseComponent title, @Nullable BaseComponent subtitle, int inTicks, int stayTicks, int outTicks) {
|
||||
if(title != null) sendMessage(title);
|
||||
if(subtitle != null) sendMessage(subtitle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideTitle() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(Sound sound) {
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package tc.oc.commons.bukkit.chat;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.bukkit.Server;
|
||||
import tc.oc.commons.core.chat.AbstractConsoleAudience;
|
||||
|
||||
public class ConsoleAudience extends AbstractConsoleAudience {
|
||||
|
||||
private final Server server;
|
||||
|
||||
@Inject public ConsoleAudience(Server server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(BaseComponent message) {
|
||||
ComponentRenderers.send(server.getConsoleSender(), message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
server.getConsoleSender().sendMessage(message);
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package tc.oc.commons.bukkit.chat;
|
||||
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.bukkit.entity.Player;
|
||||
import tc.oc.commons.core.chat.Components;
|
||||
import tc.oc.commons.core.stream.Collectors;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class LegacyPlayerAudience extends PlayerAudience {
|
||||
|
||||
private BaseComponent recentHotbarMessage;
|
||||
|
||||
public LegacyPlayerAudience(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendHotbarMessage(BaseComponent message) {
|
||||
// Do not spam hot bar messages, as the protocol converts
|
||||
// them to regular chat messages.
|
||||
if(!Components.equals(message, recentHotbarMessage)) {
|
||||
emphasize(message);
|
||||
recentHotbarMessage = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTitle(BaseComponent title, BaseComponent subtitle, int inTicks, int stayTicks, int outTicks) {
|
||||
emphasize(Components.join(Components.space(), Stream.of(title, subtitle).filter(msg -> msg != null).collect(Collectors.toImmutableList())));
|
||||
}
|
||||
|
||||
protected void emphasize(BaseComponent message) {
|
||||
sendMessage(Components.blank());
|
||||
sendMessage(message);
|
||||
sendMessage(Components.blank());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package tc.oc.commons.bukkit.chat;
|
||||
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import org.bukkit.entity.Player;
|
||||
import tc.oc.commons.core.chat.Component;
|
||||
import tc.oc.commons.core.chat.Sound;
|
||||
|
||||
public class PlayerAudience extends CommandSenderAudience {
|
||||
|
||||
public PlayerAudience(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
protected Player getPlayer() {
|
||||
return (Player) getCommandSender();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendHotbarMessage(BaseComponent message) {
|
||||
getPlayer().sendMessage(ChatMessageType.ACTION_BAR, ComponentRenderers.render(message, getPlayer()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTitle(BaseComponent title, BaseComponent subtitle, int inTicks, int stayTicks, int outTicks) {
|
||||
title = title == null ? new Component("") : ComponentRenderers.render(title, getPlayer());
|
||||
subtitle = subtitle == null ? new Component("") : ComponentRenderers.render(subtitle, getPlayer());
|
||||
getPlayer().showTitle(title, subtitle, inTicks, stayTicks, outTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideTitle() {
|
||||
getPlayer().hideTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(Sound sound) {
|
||||
getPlayer().playSound(getPlayer().getLocation(), sound.name(), sound.volume(), sound.pitch());
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@ import com.google.inject.assistedinject.FactoryModuleBuilder;
|
|||
import org.bukkit.plugin.Plugin;
|
||||
import tc.oc.commons.bukkit.bossbar.BossBarFactory;
|
||||
import tc.oc.commons.bukkit.bossbar.BossBarFactoryImpl;
|
||||
import tc.oc.commons.bukkit.chat.BukkitAudiences;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.item.RenderedItemBuilder;
|
||||
import tc.oc.commons.bukkit.logging.BukkitLoggerFactory;
|
||||
import tc.oc.commons.bukkit.permissions.BukkitPermissionRegistry;
|
||||
|
@ -31,8 +31,8 @@ public class BukkitServerManifest extends SingletonManifest {
|
|||
|
||||
bind(new TypeLiteral<PluginResolver<Plugin>>(){}).to(BukkitPluginResolver.class);
|
||||
bind(Loggers.class).to(BukkitLoggerFactory.class);
|
||||
bind(tc.oc.commons.core.chat.Audiences.class).to(tc.oc.commons.bukkit.chat.Audiences.class);
|
||||
bind(tc.oc.commons.bukkit.chat.Audiences.class).to(BukkitAudiences.class);
|
||||
bind(tc.oc.commons.core.chat.Audiences.class).to(Audiences.class);
|
||||
requestStaticInjection(Audiences.Deprecated.class);
|
||||
bind(PermissionRegistry.class).to(BukkitPermissionRegistry.class);
|
||||
bind(BossBarFactory.class).to(BossBarFactoryImpl.class);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import org.bukkit.event.player.PlayerTeleportEvent;
|
|||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
import org.bukkit.util.RayBlockIntersection;
|
||||
import org.bukkit.util.Vector;
|
||||
import tc.oc.commons.bukkit.chat.BukkitAudiences;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.event.BlockPunchEvent;
|
||||
import tc.oc.commons.bukkit.event.BlockTrampleEvent;
|
||||
import tc.oc.commons.bukkit.event.CoarsePlayerMoveEvent;
|
||||
|
@ -42,6 +42,7 @@ import tc.oc.commons.core.plugin.PluginFacet;
|
|||
public class PlayerMovementListener implements PluginFacet, Listener {
|
||||
|
||||
protected final EventBus eventBus;
|
||||
protected final Audiences audiences;
|
||||
|
||||
// The last location of a player that has been used to generate
|
||||
// coarse movement events. If a player is not in this list, then
|
||||
|
@ -49,8 +50,9 @@ public class PlayerMovementListener implements PluginFacet, Listener {
|
|||
// on its own.
|
||||
private final Map<Player, EntityLocation> lastToLocation = new WeakHashMap<>();
|
||||
|
||||
@Inject PlayerMovementListener(EventBus eventBus) {
|
||||
@Inject PlayerMovementListener(EventBus eventBus, Audiences audiences) {
|
||||
this.eventBus = eventBus;
|
||||
this.audiences = audiences;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -257,7 +259,7 @@ public class PlayerMovementListener implements PluginFacet, Listener {
|
|||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void processCancelMessage(final CoarsePlayerMoveEvent event) {
|
||||
if(event.isCancelled() && event.getCancelMessage() != null) {
|
||||
BukkitAudiences.getAudience(event.getPlayer()).sendWarning(event.getCancelMessage(), false);
|
||||
audiences.get(event.getPlayer()).sendWarning(event.getCancelMessage(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,12 +14,12 @@ public class BukkitPermissionRegistry implements PermissionRegistry {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addPermission(Permission permission) {
|
||||
public void register(Permission permission) {
|
||||
pluginManager.addPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePermission(Permission permission) {
|
||||
public void unregister(Permission permission) {
|
||||
pluginManager.removePermission(permission);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,36 @@
|
|||
package tc.oc.commons.bukkit.permissions;
|
||||
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
|
||||
/**
|
||||
* Abstraction layer for Bukkit permission API
|
||||
*/
|
||||
public interface PermissionRegistry {
|
||||
void addPermission(Permission perm);
|
||||
void removePermission(Permission perm);
|
||||
|
||||
void register(Permission perm);
|
||||
|
||||
void unregister(Permission perm);
|
||||
|
||||
default Permission create(String name, PermissionDefault def) {
|
||||
Permission permission = new Permission(name, def);
|
||||
register(permission);
|
||||
return permission;
|
||||
}
|
||||
|
||||
default Permission create(String name) {
|
||||
return create(name, Permission.DEFAULT_PERMISSION);
|
||||
}
|
||||
|
||||
default Permission createWithDefaultOp(String name) {
|
||||
return create(name, PermissionDefault.OP);
|
||||
}
|
||||
|
||||
default Permission createWithDefaultFalse(String name) {
|
||||
return create(name, PermissionDefault.FALSE);
|
||||
}
|
||||
|
||||
default Permission createWithDefaultTrue(String name) {
|
||||
return create(name, PermissionDefault.TRUE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,90 @@
|
|||
package tc.oc.commons.bungee.chat;
|
||||
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import tc.oc.commons.core.chat.AbstractAudiences;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
import tc.oc.commons.core.chat.ConsoleAudience;
|
||||
import tc.oc.commons.core.chat.Sound;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class Audiences extends AbstractAudiences<CommandSender> {
|
||||
|
||||
@Override
|
||||
public Audience get(CommandSender sender) {
|
||||
if(sender instanceof ProxiedPlayer) {
|
||||
return new Player((ProxiedPlayer) sender);
|
||||
} else {
|
||||
return new Console();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Base<T extends CommandSender> implements Audience {
|
||||
|
||||
private final T sender;
|
||||
|
||||
protected Base(T sender) {
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
protected T sender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(BaseComponent message) {
|
||||
sender().sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendWarning(BaseComponent message, boolean audible) {
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Player extends Base<ProxiedPlayer> {
|
||||
|
||||
public Player(ProxiedPlayer proxiedPlayer) {
|
||||
super(proxiedPlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(Sound sound) {}
|
||||
|
||||
@Override
|
||||
public void stopSound(Sound sound) {}
|
||||
|
||||
@Override
|
||||
public void sendHotbarMessage(BaseComponent message) {
|
||||
sender().sendMessage(ChatMessageType.ACTION_BAR, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTitle(@Nullable BaseComponent title, @Nullable BaseComponent subtitle, int inTicks, int stayTicks, int outTicks) {
|
||||
sender().sendTitle(ProxyServer.getInstance().createTitle().title(title).subTitle(subtitle).fadeIn(inTicks).stay(stayTicks).fadeOut(outTicks));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideTitle() {
|
||||
sender().sendTitle(ProxyServer.getInstance().createTitle().clear());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Console implements ConsoleAudience {
|
||||
|
||||
@Override
|
||||
public void sendMessage(BaseComponent message) {
|
||||
ProxyServer.getInstance().getConsoleSender().sendMessage(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public interface Audiences extends tc.oc.commons.core.chat.Audiences<CommandSender> {
|
||||
}
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
package tc.oc.commons.bungee.chat;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import tc.oc.commons.core.chat.Audience;
|
||||
import tc.oc.commons.core.chat.MinecraftAudiences;
|
||||
|
||||
@Singleton
|
||||
public class BungeeAudiences extends MinecraftAudiences<CommandSender> implements Audiences {
|
||||
@Override
|
||||
public Audience get(CommandSender sender) {
|
||||
if(sender instanceof ProxiedPlayer) {
|
||||
return new PlayerAudience((ProxiedPlayer) sender);
|
||||
} else {
|
||||
return new ConsoleAudience();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package tc.oc.commons.bungee.chat;
|
||||
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import tc.oc.commons.core.chat.AbstractConsoleAudience;
|
||||
|
||||
public class ConsoleAudience extends AbstractConsoleAudience {
|
||||
|
||||
@Override
|
||||
public void sendMessage(BaseComponent message) {
|
||||
ProxyServer.getInstance().getConsole().sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
ProxyServer.getInstance().getConsole().sendMessage(message);
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
package tc.oc.commons.bungee.chat;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import tc.oc.commons.core.chat.AbstractAudience;
|
||||
import tc.oc.commons.core.chat.Sound;
|
||||
|
||||
public class PlayerAudience extends AbstractAudience {
|
||||
|
||||
private final ProxiedPlayer player;
|
||||
|
||||
public PlayerAudience(ProxiedPlayer player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(BaseComponent message) {
|
||||
player.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(Sound sound) {
|
||||
// Possible, but not worth the trouble
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendHotbarMessage(BaseComponent message) {
|
||||
player.sendMessage(ChatMessageType.ACTION_BAR, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTitle(@Nullable BaseComponent title, @Nullable BaseComponent subtitle, int inTicks, int stayTicks, int outTicks) {
|
||||
player.sendTitle(ProxyServer.getInstance().createTitle().title(title).subTitle(subtitle).fadeIn(inTicks).stay(stayTicks).fadeOut(outTicks));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideTitle() {
|
||||
player.sendTitle(ProxyServer.getInstance().createTitle().clear());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
player.sendMessage(message);
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package tc.oc.commons.bungee.inject;
|
|||
|
||||
import com.google.inject.TypeLiteral;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import tc.oc.commons.bungee.chat.BungeeAudiences;
|
||||
import tc.oc.commons.bungee.chat.Audiences;
|
||||
import tc.oc.commons.bungee.logging.BungeeLoggerFactory;
|
||||
import tc.oc.commons.bungee.plugin.BungeePluginResolver;
|
||||
import tc.oc.commons.core.inject.SingletonManifest;
|
||||
|
@ -17,7 +17,6 @@ public class BungeeServerManifest extends SingletonManifest {
|
|||
|
||||
bind(new TypeLiteral<PluginResolver<Plugin>>(){}).to(BungeePluginResolver.class);
|
||||
bind(Loggers.class).to(BungeeLoggerFactory.class);
|
||||
bind(tc.oc.commons.core.chat.Audiences.class).to(tc.oc.commons.bungee.chat.Audiences.class);
|
||||
bind(tc.oc.commons.bungee.chat.Audiences.class).to(BungeeAudiences.class);
|
||||
bind(tc.oc.commons.core.chat.Audiences.class).to(Audiences.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
package tc.oc.commons.core.chat;
|
||||
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
|
||||
public abstract class AbstractAudience implements Audience {
|
||||
|
||||
@Override
|
||||
public void sendWarning(BaseComponent message, boolean audible) {
|
||||
sendMessage(new Component(ChatColor.RED).extra(new Component(" \u26a0 ", ChatColor.YELLOW), message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendWarning(String message, boolean audible) {
|
||||
sendMessage(ChatColor.YELLOW + " \u26a0 " + ChatColor.RED + message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package tc.oc.commons.core.chat;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import tc.oc.minecraft.api.command.CommandSender;
|
||||
import tc.oc.minecraft.api.server.LocalServer;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public abstract class AbstractAudiences<C extends CommandSender> implements Audiences<C> {
|
||||
|
||||
@Inject
|
||||
LocalServer localServer;
|
||||
|
||||
@Override
|
||||
public MultiAudience all() {
|
||||
return () -> senders().map(sender -> get((C) sender));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiAudience filter(Predicate<C> condition) {
|
||||
return () -> senders().filter(sender -> condition.test((C) sender)).map(sender -> get((C) sender));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Audience console() {
|
||||
return get((C) localServer.getConsoleSender());
|
||||
}
|
||||
|
||||
private Stream<CommandSender> senders() {
|
||||
return ImmutableList.<CommandSender>builder().add(localServer.getConsoleSender()).addAll(localServer.getOnlinePlayers()).build().stream();
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue