Allow cross-server chat messages
This commit is contained in:
parent
ac0c821a90
commit
44481e4b63
|
@ -1,5 +1,6 @@
|
||||||
package tc.oc.api;
|
package tc.oc.api;
|
||||||
|
|
||||||
|
import tc.oc.api.chat.ChatModelManifest;
|
||||||
import tc.oc.api.document.DocumentsManifest;
|
import tc.oc.api.document.DocumentsManifest;
|
||||||
import tc.oc.api.engagement.EngagementModelManifest;
|
import tc.oc.api.engagement.EngagementModelManifest;
|
||||||
import tc.oc.api.friendships.FriendshipModelManifest;
|
import tc.oc.api.friendships.FriendshipModelManifest;
|
||||||
|
@ -46,5 +47,6 @@ public final class ApiManifest extends HybridManifest {
|
||||||
install(new TrophyModelManifest());
|
install(new TrophyModelManifest());
|
||||||
install(new TournamentModelManifest());
|
install(new TournamentModelManifest());
|
||||||
install(new FriendshipModelManifest());
|
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_url();
|
||||||
@Nullable String resource_pack_sha1();
|
@Nullable String resource_pack_sha1();
|
||||||
boolean resource_pack_fast_update();
|
boolean resource_pack_fast_update();
|
||||||
|
@Nullable String cross_server_profile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serialize
|
@Serialize
|
||||||
|
|
|
@ -43,6 +43,11 @@ public interface UserDoc {
|
||||||
List<String> trophy_ids();
|
List<String> trophy_ids();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serialize
|
||||||
|
interface Channel extends Partial {
|
||||||
|
@Nonnull ChatDoc.Type chat_channel();
|
||||||
|
}
|
||||||
|
|
||||||
interface License {
|
interface License {
|
||||||
|
|
||||||
@Serialize
|
@Serialize
|
||||||
|
@ -79,7 +84,7 @@ public interface UserDoc {
|
||||||
* Stuff we get from the API on login, and keep around for plugins to use
|
* Stuff we get from the API on login, and keep around for plugins to use
|
||||||
*/
|
*/
|
||||||
@Serialize
|
@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 raindrops();
|
||||||
int maptokens();
|
int maptokens();
|
||||||
int mutationtokens();
|
int mutationtokens();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package tc.oc.api.reports;
|
package tc.oc.api.reports;
|
||||||
|
|
||||||
import java.util.Collection;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import tc.oc.api.annotations.Serialize;
|
import tc.oc.api.annotations.Serialize;
|
||||||
|
@ -15,39 +15,33 @@ import static com.google.common.base.Preconditions.checkState;
|
||||||
public class ReportSearchRequest extends FindRequest<Report> {
|
public class ReportSearchRequest extends FindRequest<Report> {
|
||||||
|
|
||||||
@Serialize private final @Nullable String server_id;
|
@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 @Nullable String user_id;
|
||||||
|
@Serialize private final boolean cross_server;
|
||||||
|
|
||||||
private final int page, perPage;
|
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(page > 0);
|
||||||
checkArgument(perPage > 0);
|
checkArgument(perPage > 0);
|
||||||
|
|
||||||
this.server_id = server_id;
|
this.server_id = server_id;
|
||||||
this.family_ids = family_ids;
|
|
||||||
this.user_id = user_id;
|
this.user_id = user_id;
|
||||||
|
this.cross_server = cross_server;
|
||||||
this.page = page;
|
this.page = page;
|
||||||
this.perPage = perPage;
|
this.perPage = perPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ReportSearchRequest create(int page, int 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) {
|
public ReportSearchRequest forServer(ServerDoc.Identity server, boolean cross_server) {
|
||||||
checkState(server_id == null);
|
return new ReportSearchRequest(server._id(), null, cross_server, page, perPage);
|
||||||
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 forPlayer(PlayerId playerId) {
|
public ReportSearchRequest forPlayer(PlayerId playerId) {
|
||||||
checkState(user_id == null);
|
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
|
@Override
|
||||||
|
|
|
@ -23,8 +23,11 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||||
@Singleton
|
@Singleton
|
||||||
public class ServerStore extends ModelStore<Server> {
|
public class ServerStore extends ModelStore<Server> {
|
||||||
|
|
||||||
|
private final SetMultimap<String, Server> byName = HashMultimap.create();
|
||||||
private final Map<String, Server> byBungeeName = new HashMap<>();
|
private final Map<String, Server> byBungeeName = new HashMap<>();
|
||||||
private final SetMultimap<ServerDoc.Role, Server> byRole = HashMultimap.create();
|
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();
|
private final SetMultimap<String, Server> byArenaId = HashMultimap.create();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -32,6 +35,18 @@ public class ServerStore extends ModelStore<Server> {
|
||||||
return new ServerSearchRequest();
|
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) {
|
public @Nullable Server tryBungeeName(String name) {
|
||||||
checkArgument(!"default".equals(name), "Cannot lookup lobbies by bungee_name");
|
checkArgument(!"default".equals(name), "Cannot lookup lobbies by bungee_name");
|
||||||
return byBungeeName.get(name);
|
return byBungeeName.get(name);
|
||||||
|
@ -59,10 +74,20 @@ public class ServerStore extends ModelStore<Server> {
|
||||||
return playerCount;
|
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
|
@Override
|
||||||
protected void unindex(Server doc) {
|
protected void unindex(Server doc) {
|
||||||
super.unindex(doc);
|
super.unindex(doc);
|
||||||
|
byName.remove(doc.name(), doc);
|
||||||
byRole.remove(doc.role(), 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.arena_id() != null) byArenaId.remove(doc.arena_id(), doc);
|
||||||
if(doc.bungee_name() != null) byBungeeName.remove(doc.bungee_name());
|
if(doc.bungee_name() != null) byBungeeName.remove(doc.bungee_name());
|
||||||
}
|
}
|
||||||
|
@ -70,7 +95,10 @@ public class ServerStore extends ModelStore<Server> {
|
||||||
@Override
|
@Override
|
||||||
protected void reindex(Server doc) {
|
protected void reindex(Server doc) {
|
||||||
super.reindex(doc);
|
super.reindex(doc);
|
||||||
|
byName.put(doc.name(), doc);
|
||||||
byRole.put(doc.role(), 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.arena_id() != null) byArenaId.put(doc.arena_id(), doc);
|
||||||
if(doc.bungee_name() != null) byBungeeName.put(doc.bungee_name(), doc);
|
if(doc.bungee_name() != null) byBungeeName.put(doc.bungee_name(), doc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,25 @@
|
||||||
package tc.oc.api.util;
|
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.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
public final class Permissions {
|
public interface Permissions {
|
||||||
|
|
||||||
private Permissions() {}
|
String CONSOLE = "ocn.console";
|
||||||
|
String LOGIN = "ocn.login";
|
||||||
public static final String CONSOLE = "ocn.console";
|
String STAFF = "projectares.staff";
|
||||||
public static final String LOGIN = "ocn.login";
|
String OBSERVER = "ocn.observer";
|
||||||
public static final String STAFF = "projectares.staff";
|
String PARTICIPANT = "ocn.participant";
|
||||||
public static final String OBSERVER = "ocn.observer";
|
String MAPMAKER = "ocn.mapmaker";
|
||||||
public static final String PARTICIPANT = "ocn.participant";
|
String DEVELOPER = "ocn.developer";
|
||||||
public static final String MAPMAKER = "ocn.mapmaker";
|
String MAPDEV = "pgm.mapdev";
|
||||||
public static final String DEVELOPER = "ocn.developer";
|
String MAPERRORS = "pgm.maperrors";
|
||||||
public static final String MAPDEV = "pgm.mapdev";
|
|
||||||
public static final String MAPERRORS = "pgm.maperrors";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merge the given by-realm permissions into a single set of permissions using the given (ordered) realms
|
* 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
|
* @param permsByRealm Permissions, grouped by realm
|
||||||
* @return Effective permissions
|
* @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<>();
|
Map<String, Boolean> effectivePerms = new HashMap<>();
|
||||||
for(String realm : realms) {
|
for(String realm : realms) {
|
||||||
Map<String, Boolean> perms = permsByRealm.get(realm);
|
Map<String, Boolean> perms = permsByRealm.get(realm);
|
||||||
|
@ -34,4 +37,42 @@ public final class Permissions {
|
||||||
}
|
}
|
||||||
return effectivePerms;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String cross_server_profile() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<UUID, String> fake_usernames() {
|
public Map<UUID, String> fake_usernames() {
|
||||||
return Collections.emptyMap();
|
return Collections.emptyMap();
|
||||||
|
|
|
@ -7,12 +7,14 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import tc.oc.api.docs.PlayerId;
|
import tc.oc.api.docs.PlayerId;
|
||||||
import tc.oc.api.docs.SimplePlayerId;
|
import tc.oc.api.docs.SimplePlayerId;
|
||||||
import tc.oc.api.docs.User;
|
import tc.oc.api.docs.User;
|
||||||
|
import tc.oc.api.docs.virtual.ChatDoc;
|
||||||
import tc.oc.api.docs.virtual.UserDoc;
|
import tc.oc.api.docs.virtual.UserDoc;
|
||||||
import tc.oc.api.minecraft.servers.DefaultPermissions;
|
import tc.oc.api.minecraft.servers.DefaultPermissions;
|
||||||
|
|
||||||
|
@ -161,4 +163,9 @@ public class LocalUserDocument extends SimplePlayerId implements User {
|
||||||
public String death_screen() {
|
public String death_screen() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChatDoc.Type chat_channel() {
|
||||||
|
return ChatDoc.Type.TEAM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package tc.oc.api.ocn;
|
package tc.oc.api.ocn;
|
||||||
|
|
||||||
import tc.oc.api.docs.Arena;
|
import tc.oc.api.docs.Arena;
|
||||||
|
import tc.oc.api.docs.Chat;
|
||||||
import tc.oc.api.docs.Death;
|
import tc.oc.api.docs.Death;
|
||||||
import tc.oc.api.docs.Game;
|
import tc.oc.api.docs.Game;
|
||||||
import tc.oc.api.docs.Objective;
|
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.Punishment;
|
||||||
import tc.oc.api.docs.Report;
|
import tc.oc.api.docs.Report;
|
||||||
import tc.oc.api.docs.Trophy;
|
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.DeathDoc;
|
||||||
import tc.oc.api.docs.virtual.MatchDoc;
|
import tc.oc.api.docs.virtual.MatchDoc;
|
||||||
import tc.oc.api.docs.virtual.PunishmentDoc;
|
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 -> {
|
bindModel(Punishment.class, PunishmentDoc.Partial.class, model -> {
|
||||||
model.bindService().to(model.httpService());
|
model.bindService().to(model.httpService());
|
||||||
});
|
});
|
||||||
|
bindModel(Chat.class, ChatDoc.Partial.class, model -> {
|
||||||
|
model.bindService().to(model.httpService());
|
||||||
|
});
|
||||||
bindModel(MatchDoc.class, model -> {
|
bindModel(MatchDoc.class, model -> {
|
||||||
model.bindService().to(model.httpService());
|
model.bindService().to(model.httpService());
|
||||||
});
|
});
|
||||||
|
|
|
@ -41,18 +41,6 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</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>
|
<dependency>
|
||||||
<groupId>me.anxuiz</groupId>
|
<groupId>me.anxuiz</groupId>
|
||||||
<artifactId>bukkit-settings</artifactId>
|
<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.LatencyReporter;
|
||||||
import tc.oc.bukkit.analytics.TickReporter;
|
import tc.oc.bukkit.analytics.TickReporter;
|
||||||
import tc.oc.commons.bukkit.broadcast.BroadcastManifest;
|
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.ComponentRenderContext;
|
||||||
import tc.oc.commons.bukkit.chat.ComponentRendererRegistry;
|
import tc.oc.commons.bukkit.chat.ComponentRendererRegistry;
|
||||||
import tc.oc.commons.bukkit.chat.ComponentRenderers;
|
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.restart.RestartCommands;
|
||||||
import tc.oc.commons.bukkit.sessions.SessionListener;
|
import tc.oc.commons.bukkit.sessions.SessionListener;
|
||||||
import tc.oc.commons.bukkit.settings.SettingManifest;
|
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.stats.StatsManifest;
|
||||||
import tc.oc.commons.bukkit.suspend.SuspendListener;
|
import tc.oc.commons.bukkit.suspend.SuspendListener;
|
||||||
import tc.oc.commons.bukkit.tablist.PlayerTabEntry;
|
import tc.oc.commons.bukkit.tablist.PlayerTabEntry;
|
||||||
|
@ -104,7 +104,8 @@ public final class CommonsBukkitManifest extends HybridManifest {
|
||||||
install(new SettingManifest());
|
install(new SettingManifest());
|
||||||
install(new WhisperManifest());
|
install(new WhisperManifest());
|
||||||
install(new JoinMessageManifest());
|
install(new JoinMessageManifest());
|
||||||
install(new AdminChatManifest());
|
install(new ChatManifest());
|
||||||
|
install(new ChannelManifest());
|
||||||
install(new BroadcastManifest());
|
install(new BroadcastManifest());
|
||||||
install(new LocalizationManifest());
|
install(new LocalizationManifest());
|
||||||
install(new NavigatorManifest());
|
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;
|
break;
|
||||||
|
|
||||||
case NEWS:
|
case NEWS:
|
||||||
case ALERT:
|
|
||||||
setting = NEWS;
|
setting = NEWS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -72,6 +71,7 @@ public class BroadcastSettings {
|
||||||
setting = RANDOM;
|
setting = RANDOM;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ALERT:
|
||||||
default:
|
default:
|
||||||
return true;
|
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) {
|
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) {
|
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.Duration;
|
||||||
import java.time.format.DateTimeParseException;
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
import com.sk89q.minecraft.util.commands.CommandException;
|
import com.sk89q.minecraft.util.commands.CommandException;
|
||||||
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
|
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
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 net.md_5.bungee.api.chat.TranslatableComponent;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
|
@ -20,9 +26,11 @@ import org.bukkit.permissions.Permission;
|
||||||
import tc.oc.api.docs.PlayerId;
|
import tc.oc.api.docs.PlayerId;
|
||||||
import tc.oc.api.docs.Server;
|
import tc.oc.api.docs.Server;
|
||||||
import tc.oc.commons.bukkit.chat.ComponentRenderers;
|
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.bukkit.localization.Translations;
|
||||||
import tc.oc.commons.core.chat.Component;
|
import tc.oc.commons.core.chat.Component;
|
||||||
import tc.oc.commons.core.commands.TranslatableCommandException;
|
import tc.oc.commons.core.commands.TranslatableCommandException;
|
||||||
|
import tc.oc.commons.core.formatting.StringUtils;
|
||||||
import tc.oc.commons.core.util.TimeUtils;
|
import tc.oc.commons.core.util.TimeUtils;
|
||||||
|
|
||||||
public abstract class CommandUtils {
|
public abstract class CommandUtils {
|
||||||
|
@ -218,4 +226,35 @@ public abstract class CommandUtils {
|
||||||
public static void notEnoughArguments(CommandSender sender) throws CommandException {
|
public static void notEnoughArguments(CommandSender sender) throws CommandException {
|
||||||
throw new CommandException(Translations.get().t("command.error.notEnoughArguments", sender));
|
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.FriendshipRequest;
|
||||||
import tc.oc.api.friendships.FriendshipService;
|
import tc.oc.api.friendships.FriendshipService;
|
||||||
import tc.oc.api.minecraft.MinecraftService;
|
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.Links;
|
||||||
import tc.oc.commons.bukkit.chat.NameStyle;
|
import tc.oc.commons.bukkit.chat.NameStyle;
|
||||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||||
import tc.oc.commons.core.util.Lazy;
|
import tc.oc.commons.core.util.Lazy;
|
||||||
import tc.oc.minecraft.scheduler.SyncExecutor;
|
import tc.oc.minecraft.scheduler.SyncExecutor;
|
||||||
import tc.oc.api.sessions.SessionService;
|
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.ComponentPaginator;
|
||||||
import tc.oc.commons.bukkit.chat.ComponentRenderers;
|
import tc.oc.commons.bukkit.chat.ComponentRenderers;
|
||||||
import tc.oc.commons.bukkit.chat.HeaderComponent;
|
import tc.oc.commons.bukkit.chat.HeaderComponent;
|
||||||
|
@ -47,8 +47,9 @@ public class UserCommands implements Commands {
|
||||||
private final UserFinder userFinder;
|
private final UserFinder userFinder;
|
||||||
private final IdentityProvider identityProvider;
|
private final IdentityProvider identityProvider;
|
||||||
private final UserFormatter userFormatter;
|
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.minecraftService = minecraftService;
|
||||||
this.syncExecutor = syncExecutor;
|
this.syncExecutor = syncExecutor;
|
||||||
this.sessionService = sessionService;
|
this.sessionService = sessionService;
|
||||||
|
@ -56,6 +57,7 @@ public class UserCommands implements Commands {
|
||||||
this.userFinder = userFinder;
|
this.userFinder = userFinder;
|
||||||
this.identityProvider = identityProvider;
|
this.identityProvider = identityProvider;
|
||||||
this.userFormatter = userFormatter;
|
this.userFormatter = userFormatter;
|
||||||
|
this.audiences = audiences;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
|
@ -113,7 +115,7 @@ public class UserCommands implements Commands {
|
||||||
@CommandPermissions("ocn.friend.request")
|
@CommandPermissions("ocn.friend.request")
|
||||||
public void friend(final CommandContext args, final CommandSender sender) throws CommandException {
|
public void friend(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||||
User friender = userFinder.getLocalUser(CommandUtils.senderToPlayer(sender));
|
User friender = userFinder.getLocalUser(CommandUtils.senderToPlayer(sender));
|
||||||
Audience audience = BukkitAudiences.getAudience(sender);
|
Audience audience = audiences.get(sender);
|
||||||
syncExecutor.callback(
|
syncExecutor.callback(
|
||||||
userFinder.findUser(sender, args, 0),
|
userFinder.findUser(sender, args, 0),
|
||||||
response -> {
|
response -> {
|
||||||
|
@ -163,7 +165,7 @@ public class UserCommands implements Commands {
|
||||||
@CommandPermissions("ocn.friend.request")
|
@CommandPermissions("ocn.friend.request")
|
||||||
public void unfriend(final CommandContext args, final CommandSender sender) throws CommandException {
|
public void unfriend(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||||
User friender = userFinder.getLocalUser(CommandUtils.senderToPlayer(sender));
|
User friender = userFinder.getLocalUser(CommandUtils.senderToPlayer(sender));
|
||||||
Audience audience = BukkitAudiences.getAudience(sender);
|
Audience audience = audiences.get(sender);
|
||||||
syncExecutor.callback(
|
syncExecutor.callback(
|
||||||
userFinder.findUser(sender, args, 0),
|
userFinder.findUser(sender, args, 0),
|
||||||
response -> {
|
response -> {
|
||||||
|
@ -204,7 +206,7 @@ public class UserCommands implements Commands {
|
||||||
syncExecutor.callback(
|
syncExecutor.callback(
|
||||||
sessionService.staff(minecraftService.getLocalServer().network(), identityProvider.revealAll(sender)),
|
sessionService.staff(minecraftService.getLocalServer().network(), identityProvider.revealAll(sender)),
|
||||||
CommandFutureCallback.onSuccess(sender, args, result -> {
|
CommandFutureCallback.onSuccess(sender, args, result -> {
|
||||||
final Audience audience = BukkitAudiences.getAudience(sender);
|
final Audience audience = audiences.get(sender);
|
||||||
if(result.documents().isEmpty()) {
|
if(result.documents().isEmpty()) {
|
||||||
audience.sendMessage(new TranslatableComponent("command.staff.noStaffOnline"));
|
audience.sendMessage(new TranslatableComponent("command.staff.noStaffOnline"));
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -8,6 +8,7 @@ import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import net.md_5.bungee.api.ChatColor;
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
import tc.oc.api.bukkit.users.BukkitUserStore;
|
import tc.oc.api.bukkit.users.BukkitUserStore;
|
||||||
import tc.oc.api.docs.virtual.UserDoc;
|
import tc.oc.api.docs.virtual.UserDoc;
|
||||||
|
@ -37,6 +38,7 @@ public class FlairRenderer implements PartialNameRenderer {
|
||||||
@Override
|
@Override
|
||||||
public String getLegacyName(Identity identity, NameType type) {
|
public String getLegacyName(Identity identity, NameType type) {
|
||||||
if(!(type.style.contains(NameFlag.FLAIR) && type.reveal)) return "";
|
if(!(type.style.contains(NameFlag.FLAIR) && type.reveal)) return "";
|
||||||
|
if(identity.isConsole()) return ChatColor.GOLD + "❖";
|
||||||
return getFlairs(identity).reduce("", String::concat);
|
return getFlairs(identity).reduce("", String::concat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,11 @@ public class ConsoleIdentity implements Identity {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isConsole() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName(CommandSender viewer) {
|
public String getName(CommandSender viewer) {
|
||||||
return NAME;
|
return NAME;
|
||||||
|
|
|
@ -60,6 +60,11 @@ public interface Identity {
|
||||||
*/
|
*/
|
||||||
boolean isCurrent();
|
boolean isCurrent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the identity belong to a console?
|
||||||
|
*/
|
||||||
|
boolean isConsole();
|
||||||
|
|
||||||
// Viewer-relative properties
|
// Viewer-relative properties
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -71,6 +71,11 @@ public class IdentityImpl implements Identity {
|
||||||
return player != null && equals(identityProvider.currentIdentity(player));
|
return player != null && equals(identityProvider.currentIdentity(player));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isConsole() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDead(CommandSender viewer) {
|
public boolean isDead(CommandSender viewer) {
|
||||||
if(!isOnline(viewer)) return false;
|
if(!isOnline(viewer)) return false;
|
||||||
|
|
|
@ -84,7 +84,7 @@ public class UsernameRenderer implements PartialNameRenderer {
|
||||||
rendered.setColor(getColor(identity, type));
|
rendered.setColor(getColor(identity, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type.style.contains(NameFlag.TELEPORT)) {
|
if(!identity.isConsole() && type.style.contains(NameFlag.TELEPORT)) {
|
||||||
Component dupe = rendered.duplicate();
|
Component dupe = rendered.duplicate();
|
||||||
rendered.clickEvent(makeRemoteTeleportClickEvent(identity, identity.getNickname() != null && !type.reveal));
|
rendered.clickEvent(makeRemoteTeleportClickEvent(identity, identity.getNickname() != null && !type.reveal));
|
||||||
rendered.hoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslatableComponent("tip.teleportTo", dupe));
|
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.docs.virtual.PunishmentDoc;
|
||||||
import tc.oc.api.model.IdFactory;
|
import tc.oc.api.model.IdFactory;
|
||||||
import tc.oc.api.model.ModelService;
|
import tc.oc.api.model.ModelService;
|
||||||
import tc.oc.commons.bukkit.report.ReportConfiguration;
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class PunishmentCreator {
|
public class PunishmentCreator {
|
||||||
|
|
||||||
private final ReportConfiguration config;
|
|
||||||
private final ModelService<Punishment, PunishmentDoc.Partial> punishmentService;
|
private final ModelService<Punishment, PunishmentDoc.Partial> punishmentService;
|
||||||
private final IdFactory idFactory;
|
private final IdFactory idFactory;
|
||||||
private final Server localServer;
|
private final Server localServer;
|
||||||
|
|
||||||
@Inject PunishmentCreator(ReportConfiguration config, ModelService<Punishment, PunishmentDoc.Partial> punishmentService, IdFactory idFactory, Server localServer) {
|
@Inject PunishmentCreator(ModelService<Punishment, PunishmentDoc.Partial> punishmentService, IdFactory idFactory, Server localServer) {
|
||||||
this.config = config;
|
|
||||||
this.punishmentService = punishmentService;
|
this.punishmentService = punishmentService;
|
||||||
this.idFactory = idFactory;
|
this.idFactory = idFactory;
|
||||||
this.localServer = localServer;
|
this.localServer = localServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean offRecord() {
|
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) {
|
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;
|
package tc.oc.commons.bukkit.report;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import me.anxuiz.settings.Setting;
|
import me.anxuiz.settings.Setting;
|
||||||
import me.anxuiz.settings.SettingBuilder;
|
import me.anxuiz.settings.SettingBuilder;
|
||||||
import me.anxuiz.settings.types.BooleanType;
|
import me.anxuiz.settings.types.BooleanType;
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
import org.bukkit.Sound;
|
import org.bukkit.Sound;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import tc.oc.api.docs.Report;
|
import tc.oc.api.docs.Report;
|
||||||
import tc.oc.api.docs.Server;
|
import tc.oc.api.docs.Server;
|
||||||
import tc.oc.api.message.MessageListener;
|
import tc.oc.api.message.MessageListener;
|
||||||
import tc.oc.api.message.MessageQueue;
|
import tc.oc.api.message.MessageQueue;
|
||||||
import tc.oc.api.message.types.ModelUpdate;
|
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.Audiences;
|
||||||
import tc.oc.commons.bukkit.chat.BukkitSound;
|
import tc.oc.commons.bukkit.chat.BukkitSound;
|
||||||
import tc.oc.commons.bukkit.settings.SettingManagerProvider;
|
import tc.oc.commons.bukkit.settings.SettingManagerProvider;
|
||||||
import tc.oc.commons.core.chat.Audience;
|
|
||||||
import tc.oc.commons.core.plugin.PluginFacet;
|
import tc.oc.commons.core.plugin.PluginFacet;
|
||||||
import tc.oc.minecraft.scheduler.MainThreadExecutor;
|
import tc.oc.minecraft.scheduler.MainThreadExecutor;
|
||||||
|
|
||||||
|
@ -39,24 +36,17 @@ public class ReportAnnouncer implements PluginFacet, MessageListener {
|
||||||
private final MessageQueue primaryQueue;
|
private final MessageQueue primaryQueue;
|
||||||
private final MainThreadExecutor executor;
|
private final MainThreadExecutor executor;
|
||||||
private final Server localServer;
|
private final Server localServer;
|
||||||
private final AdminChannel adminChannel;
|
private final ServerStore serverStore;
|
||||||
private final Audiences audiences;
|
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.config = config;
|
||||||
this.reportFormatter = reportFormatter;
|
this.reportFormatter = reportFormatter;
|
||||||
this.primaryQueue = primaryQueue;
|
this.primaryQueue = primaryQueue;
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
this.localServer = localServer;
|
this.localServer = localServer;
|
||||||
this.adminChannel = adminChannel;
|
this.serverStore = serverStore;
|
||||||
this.audiences = audiences;
|
this.audiences = audiences;
|
||||||
this.settings = settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isActive() {
|
|
||||||
return config.crossServer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -72,19 +62,9 @@ public class ReportAnnouncer implements PluginFacet, MessageListener {
|
||||||
|
|
||||||
@HandleMessage
|
@HandleMessage
|
||||||
public void broadcast(ModelUpdate<Report> message) {
|
public void broadcast(ModelUpdate<Report> message) {
|
||||||
if(localServer._id().equals(message.document().server_id()) ||
|
if(serverStore.canCommunicate(localServer._id(), message.document().server_id())) {
|
||||||
(config.crossServer() && config.families().contains(message.document().family()))) {
|
audiences.permission(ReportPermissions.RECEIVE)
|
||||||
|
.sendMessages(reportFormatter.format(message.document(), true, false));
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,11 +161,8 @@ public class ReportCommands implements Commands, Listener {
|
||||||
final boolean crossServer = args.hasFlag('a');
|
final boolean crossServer = args.hasFlag('a');
|
||||||
|
|
||||||
ReportSearchRequest request = ReportSearchRequest.create(page, PER_PAGE);
|
ReportSearchRequest request = ReportSearchRequest.create(page, PER_PAGE);
|
||||||
request = crossServer ? request.forFamilies(reportConfiguration.families())
|
request = userResult != null ? request.forPlayer(userResult.user)
|
||||||
: request.forServer(localServer);
|
: request.forServer(localServer, crossServer);
|
||||||
if(userResult != null) {
|
|
||||||
request = request.forPlayer(userResult.user);
|
|
||||||
}
|
|
||||||
|
|
||||||
syncExecutor.callback(
|
syncExecutor.callback(
|
||||||
reportService.find(request),
|
reportService.find(request),
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package tc.oc.commons.bukkit.report;
|
package tc.oc.commons.bukkit.report;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import org.bukkit.configuration.Configuration;
|
import org.bukkit.configuration.Configuration;
|
||||||
|
@ -22,12 +21,4 @@ public class ReportConfiguration {
|
||||||
public Duration cooldown() {
|
public Duration cooldown() {
|
||||||
return ConfigUtils.getDuration(config, "reports.cooldown", Duration.ZERO);
|
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
|
@Override
|
||||||
public void enable() {
|
public void enable() {
|
||||||
permissionRegistry.addPermission(Teleporter.PERMISSION);
|
permissionRegistry.register(Teleporter.PERMISSION);
|
||||||
primaryQueue.subscribe(this, syncExecutor);
|
primaryQueue.subscribe(this, syncExecutor);
|
||||||
primaryQueue.bind(PlayerTeleportRequest.class);
|
primaryQueue.bind(PlayerTeleportRequest.class);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,9 @@ import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import tc.oc.api.docs.Server;
|
import tc.oc.api.docs.Server;
|
||||||
import tc.oc.api.docs.Whisper;
|
import tc.oc.api.docs.Whisper;
|
||||||
import tc.oc.api.docs.virtual.ServerDoc;
|
|
||||||
import tc.oc.api.servers.ServerStore;
|
import tc.oc.api.servers.ServerStore;
|
||||||
import tc.oc.commons.bukkit.chat.Audiences;
|
import tc.oc.commons.bukkit.chat.Audiences;
|
||||||
import tc.oc.commons.bukkit.chat.BukkitSound;
|
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.NameStyle;
|
||||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||||
import tc.oc.commons.bukkit.chat.UserTextComponent;
|
import tc.oc.commons.bukkit.chat.UserTextComponent;
|
||||||
|
@ -42,16 +40,14 @@ public class WhisperFormatter {
|
||||||
private final Server localServer;
|
private final Server localServer;
|
||||||
private final SettingManagerProvider playerSettings;
|
private final SettingManagerProvider playerSettings;
|
||||||
private final Audiences audiences;
|
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.identities = identities;
|
||||||
this.miscFormatter = miscFormatter;
|
this.miscFormatter = miscFormatter;
|
||||||
this.serverStore = serverStore;
|
this.serverStore = serverStore;
|
||||||
this.localServer = localServer;
|
this.localServer = localServer;
|
||||||
this.playerSettings = playerSettings;
|
this.playerSettings = playerSettings;
|
||||||
this.audiences = audiences;
|
this.audiences = audiences;
|
||||||
this.consoleAudience = consoleAudience;
|
|
||||||
this.serverFormatter = ServerFormatter.dark;
|
this.serverFormatter = ServerFormatter.dark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +77,7 @@ public class WhisperFormatter {
|
||||||
.extra(new Component(new UserTextComponent(sender, whisper.content()), ChatColor.WHITE));
|
.extra(new Component(new UserTextComponent(sender, whisper.content()), ChatColor.WHITE));
|
||||||
|
|
||||||
audience.sendMessage(display);
|
audience.sendMessage(display);
|
||||||
consoleAudience.sendMessage(display);
|
audiences.console().sendMessage(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void receive(Player viewer, Whisper whisper) {
|
public void receive(Player viewer, Whisper whisper) {
|
||||||
|
@ -135,7 +131,7 @@ public class WhisperFormatter {
|
||||||
|
|
||||||
audience.sendMessage(display);
|
audience.sendMessage(display);
|
||||||
if(!local) {
|
if(!local) {
|
||||||
consoleAudience.sendMessage(display);
|
audiences.console().sendMessage(display);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,6 @@ join-messages:
|
||||||
reports:
|
reports:
|
||||||
enabled: true
|
enabled: true
|
||||||
cooldown: 0s
|
cooldown: 0s
|
||||||
families: []
|
|
||||||
cross-server: true
|
|
||||||
|
|
||||||
datadog:
|
datadog:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
|
@ -6,7 +6,7 @@ website: ${url}
|
||||||
main: ${plugin.mainClass}
|
main: ${plugin.mainClass}
|
||||||
prefix: ${plugin.prefix}
|
prefix: ${plugin.prefix}
|
||||||
isolate: true
|
isolate: true
|
||||||
depend: [API, BukkitSettings, Channels]
|
depend: [API, BukkitSettings]
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
sudo:
|
sudo:
|
||||||
|
|
|
@ -14,6 +14,8 @@ command.error.invalidEnum = Invalid enum option '{0}'
|
||||||
command.error.invalidNumber = Invalid number '{0}'
|
command.error.invalidNumber = Invalid number '{0}'
|
||||||
command.error.invalidPage = There is no page {0}. Pages run from 1 to {1}.
|
command.error.invalidPage = There is no page {0}. Pages run from 1 to {1}.
|
||||||
command.error.emptyResult = Empty result
|
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.onlyPlayers = You must be a player to use this command.
|
||||||
command.error.internal = Sorry, there was an internal error while processing your 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.teleportTo = Teleport to {0}
|
||||||
tip.connectTo = Connect to {0}
|
tip.connectTo = Connect to {0}
|
||||||
|
|
||||||
|
tip.sentBy = Sent by {0}
|
||||||
|
|
||||||
|
broadcast.prefix = Broadcast
|
||||||
|
|
||||||
# {0} = Sender
|
# {0} = Sender
|
||||||
# {1} = Recipient
|
# {1} = Recipient
|
||||||
# {2} = Relative time
|
# {2} = Relative time
|
||||||
|
@ -174,6 +180,11 @@ appealNotification.count = You have - {0} - unread {1}
|
||||||
misc.appeals.singular = appeal
|
misc.appeals.singular = appeal
|
||||||
misc.appeals.plural = appeals
|
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.enabled = enabled
|
||||||
misc.disabled = disabled
|
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.singular = Waiting for {0} more player to join {1}
|
||||||
start.needMorePlayers.team.plural = Waiting for {0} more players 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.
|
defuse.world = You defused world TNT.
|
||||||
# {0} = the player(s)
|
# {0} = the player(s)
|
||||||
defuse.player = You defused {0}'s TNT.
|
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.frozen = You have frozen {0}
|
||||||
command.freeze.unfrozen = You have unfrozen {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
|
# {0} = the server name
|
||||||
command.server.teleporting = Teleporting you to {0}
|
command.server.teleporting = Teleporting you to {0}
|
||||||
command.server.currentServer = You are currently on {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.inject.ProtectedBinder;
|
||||||
import tc.oc.minecraft.logging.BetterRaven;
|
import tc.oc.minecraft.logging.BetterRaven;
|
||||||
import tc.oc.pgm.antigrief.CraftingProtect;
|
import tc.oc.pgm.antigrief.CraftingProtect;
|
||||||
import tc.oc.pgm.channels.ChannelCommands;
|
|
||||||
import tc.oc.pgm.commands.MapCommands;
|
import tc.oc.pgm.commands.MapCommands;
|
||||||
import tc.oc.pgm.commands.PollCommands;
|
import tc.oc.pgm.commands.PollCommands;
|
||||||
import tc.oc.pgm.commands.RotationControlCommands;
|
import tc.oc.pgm.commands.RotationControlCommands;
|
||||||
|
@ -195,7 +194,6 @@ public final class PGM extends JavaPlugin {
|
||||||
|
|
||||||
private void setupCommands() {
|
private void setupCommands() {
|
||||||
commands.register(MapCommands.class);
|
commands.register(MapCommands.class);
|
||||||
commands.register(ChannelCommands.class);
|
|
||||||
commands.register(PollCommands.class);
|
commands.register(PollCommands.class);
|
||||||
commands.register(RotationEditCommands.RotationEditParent.class);
|
commands.register(RotationEditCommands.RotationEditParent.class);
|
||||||
commands.register(RotationControlCommands.RotationControlParent.class);
|
commands.register(RotationControlCommands.RotationControlParent.class);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package tc.oc.pgm;
|
package tc.oc.pgm;
|
||||||
|
|
||||||
|
import tc.oc.pgm.channels.ChannelManifest;
|
||||||
import tc.oc.commons.core.inject.HybridManifest;
|
import tc.oc.commons.core.inject.HybridManifest;
|
||||||
import tc.oc.pgm.animation.AnimationManifest;
|
import tc.oc.pgm.animation.AnimationManifest;
|
||||||
import tc.oc.pgm.broadcast.BroadcastManifest;
|
import tc.oc.pgm.broadcast.BroadcastManifest;
|
||||||
|
@ -70,6 +71,7 @@ public class PGMModulesManifest extends HybridManifest {
|
||||||
install(new LaneManifest());
|
install(new LaneManifest());
|
||||||
install(new BroadcastManifest());
|
install(new BroadcastManifest());
|
||||||
install(new StatsManifest());
|
install(new StatsManifest());
|
||||||
|
install(new ChannelManifest());
|
||||||
install(new RaindropManifest());
|
install(new RaindropManifest());
|
||||||
install(new TokenManifest());
|
install(new TokenManifest());
|
||||||
install(new ObjectiveModeManifest());
|
install(new ObjectiveModeManifest());
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.Sound;
|
import org.bukkit.Sound;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.entity.TNTPrimed;
|
import org.bukkit.entity.TNTPrimed;
|
||||||
|
@ -25,14 +26,18 @@ import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
import org.bukkit.inventory.ItemFlag;
|
import org.bukkit.inventory.ItemFlag;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
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.ComponentRenderers;
|
||||||
import tc.oc.commons.bukkit.chat.ListComponent;
|
import tc.oc.commons.bukkit.chat.ListComponent;
|
||||||
import tc.oc.commons.bukkit.chat.NameStyle;
|
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.event.ObserverKitApplyEvent;
|
||||||
|
import tc.oc.commons.bukkit.nick.IdentityProvider;
|
||||||
import tc.oc.commons.core.inject.Proxied;
|
import tc.oc.commons.core.inject.Proxied;
|
||||||
import tc.oc.commons.core.plugin.PluginFacet;
|
import tc.oc.commons.core.plugin.PluginFacet;
|
||||||
import tc.oc.pgm.PGMTranslations;
|
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.MatchManager;
|
||||||
import tc.oc.pgm.match.MatchPlayer;
|
import tc.oc.pgm.match.MatchPlayer;
|
||||||
import tc.oc.pgm.match.ParticipantState;
|
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 Material DEFUSE_ITEM = Material.SHEARS;
|
||||||
public static final int DEFUSE_SLOT = 4;
|
public static final int DEFUSE_SLOT = 4;
|
||||||
|
|
||||||
private final MatchManager mm;
|
@Inject MatchFinder mm;
|
||||||
private final EntityResolver entityResolver;
|
@Inject AdminChannel adminChannel;
|
||||||
private final AdminChannel adminChannel;
|
@Inject IdentityProvider identityProvider;
|
||||||
|
@Inject @Proxied EntityResolver entityResolver;
|
||||||
|
|
||||||
@Inject DefuseListener(MatchManager mm, @Proxied EntityResolver entityResolver, AdminChannel adminChannel) {
|
@Inject DefuseListener(MatchManager mm, @Proxied EntityResolver entityResolver, AdminChannel adminChannel) {
|
||||||
this.mm = mm;
|
this.mm = mm;
|
||||||
|
@ -72,10 +78,12 @@ public class DefuseListener implements PluginFacet, Listener {
|
||||||
// check tnt
|
// check tnt
|
||||||
if(!(entity instanceof TNTPrimed)) return;
|
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;
|
if(tntmm != null && !tntmm.getProperties().friendlyDefuse) return;
|
||||||
|
|
||||||
MatchPlayer clicker = this.mm.getPlayer(player);
|
MatchPlayer clicker = match.getPlayer(player);
|
||||||
if(clicker == null || !clicker.canInteract()) return;
|
if(clicker == null || !clicker.canInteract()) return;
|
||||||
|
|
||||||
// check water
|
// check water
|
||||||
|
@ -86,17 +94,19 @@ public class DefuseListener implements PluginFacet, Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check owner
|
// 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
|
if(owner == null || (owner != clicker && owner.getParty() == clicker.getParty())) { // cannot defuse own TNT
|
||||||
// defuse TNT
|
// defuse TNT
|
||||||
entity.remove();
|
entity.remove();
|
||||||
if(owner != null) {
|
if(owner != null) {
|
||||||
this.notifyDefuse(clicker, entity, ChatColor.RED + PGMTranslations.t("defuse.player", clicker, owner.getDisplayName(clicker) + ChatColor.RED));
|
this.notifyDefuse(clicker, entity, ChatColor.RED + PGMTranslations.t("defuse.player", clicker, owner.getDisplayName(clicker) + ChatColor.RED));
|
||||||
adminChannel.broadcast(clicker.getDisplayName() +
|
adminChannel.sendMessage(
|
||||||
ChatColor.WHITE + " defused " +
|
new TranslatableComponent(
|
||||||
owner.getDisplayName()
|
"defuse.broadcast",
|
||||||
+ ChatColor.WHITE + "'s " +
|
new PlayerComponent(identityProvider.currentIdentity(clicker.getPlayerId()), NameStyle.VERBOSE),
|
||||||
ChatColor.DARK_RED + "TNT");
|
new PlayerComponent(identityProvider.currentIdentity(owner.getPlayerId()), NameStyle.VERBOSE)
|
||||||
|
)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.notifyDefuse(clicker, entity, ChatColor.RED + PGMTranslations.t("defuse.world", clicker));
|
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;
|
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.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.permissions.Permission;
|
import tc.oc.commons.bukkit.channels.Channel;
|
||||||
import org.bukkit.permissions.PermissionDefault;
|
import tc.oc.commons.bukkit.channels.ChannelRouter;
|
||||||
import org.bukkit.plugin.Plugin;
|
import tc.oc.pgm.events.CompetitorAddEvent;
|
||||||
import tc.oc.chatmoderator.ChatModeratorPlugin;
|
import tc.oc.pgm.events.CompetitorRemoveEvent;
|
||||||
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.pgm.events.ListenerScope;
|
import tc.oc.pgm.events.ListenerScope;
|
||||||
import tc.oc.pgm.events.PartyAddEvent;
|
import tc.oc.pgm.events.PartyAddEvent;
|
||||||
import tc.oc.pgm.events.PartyRemoveEvent;
|
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.MatchModule;
|
||||||
import tc.oc.pgm.match.MatchPlayer;
|
import tc.oc.pgm.match.MatchPlayer;
|
||||||
import tc.oc.pgm.match.MatchScope;
|
import tc.oc.pgm.match.MatchScope;
|
||||||
import tc.oc.pgm.match.MultiPlayerParty;
|
import tc.oc.pgm.match.MultiPlayerParty;
|
||||||
import tc.oc.pgm.match.Party;
|
import tc.oc.pgm.match.Party;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@ListenerScope(MatchScope.LOADED)
|
@ListenerScope(MatchScope.LOADED)
|
||||||
public class ChannelMatchModule extends MatchModule implements Listener {
|
public class ChannelMatchModule extends MatchModule implements Listener {
|
||||||
|
|
||||||
public static final String RECEIVE_ALL_PERMISSION = "pgm.chat.all.receive";
|
private final Map<Party, Channel> channels = new HashMap<>();
|
||||||
public static final String TEAM_RECEIVE_PERMISSION = "pgm.chat.team.receive";
|
|
||||||
public static final String TEAM_SEND_PERMISSION = "pgm.chat.team.send";
|
|
||||||
|
|
||||||
// This dynamic permission has all party channel listening permissions as children.
|
@Inject
|
||||||
// A player with this permission receives all channels simultaneously. It is granted
|
ChannelRouter channelRouter;
|
||||||
// automatically to observers that have the RECEIVE_ALL_PERMISSION.
|
@Inject PartyChannel.Factory channelFactory;
|
||||||
private final Permission matchListeningPermission;
|
|
||||||
|
|
||||||
private final ChannelsPlugin channelsPlugin = ChannelsPlugin.get();
|
public void create(Party party) {
|
||||||
private final Map<MultiPlayerParty, PartyChannel> partyChannels = new HashMap<>();
|
if(!channels.containsKey(party) && party instanceof MultiPlayerParty) {
|
||||||
|
channels.put(party, channelFactory.create(party));
|
||||||
// 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 setTeamChat(MatchPlayer player, boolean teamChat) {
|
public void remove(Party party) {
|
||||||
teamChatters.put(player.getBukkit(), teamChat);
|
channels.remove(party);
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load() {
|
||||||
super.load();
|
match.getParties().forEach(this::create);
|
||||||
|
channelRouter.setTeamChannelFunction(player -> channels.get(match.player(player).map(MatchPlayer::getParty).orElse(null)));
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unload() {
|
public void unload() {
|
||||||
getMatch().getServer().getConsoleSender().removeAttachments(matchListeningPermission);
|
channelRouter.setTeamChannelFunction(null);
|
||||||
getMatch().getPluginManager().removePermission(matchListeningPermission);
|
match.getParties().forEach(this::remove);
|
||||||
|
|
||||||
super.unload();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
public void partyAdd(final PartyAddEvent event) {
|
public void onPartyAdd(PartyAddEvent event) {
|
||||||
createChannel(event.getParty());
|
create(event.getParty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR)
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
public void partyRemove(final PartyRemoveEvent event) {
|
public void onPartyRemove(PartyRemoveEvent event) {
|
||||||
if(event.getParty() instanceof MultiPlayerParty) {
|
remove(event.getParty());
|
||||||
PartyChannel channel = partyChannels.remove(event.getParty());
|
|
||||||
if(channel != null) {
|
|
||||||
removeChannelPermission(channel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
public void partyJoin(PlayerJoinPartyEvent event) {
|
public void onCompetitorAdd(CompetitorAddEvent event) {
|
||||||
if(event.getNewParty() instanceof MultiPlayerParty) {
|
create(event.getParty());
|
||||||
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.MONITOR, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
public void partyLeave(PlayerLeavePartyEvent event) {
|
public void onCompetitorRemove(CompetitorRemoveEvent event) {
|
||||||
if(event.getOldParty() instanceof MultiPlayerParty) {
|
remove(event.getParty());
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
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;
|
import tc.oc.pgm.match.Party;
|
||||||
|
|
||||||
public interface PartyChannel extends Channel {
|
import javax.inject.Inject;
|
||||||
Party getParty();
|
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.User;
|
||||||
import tc.oc.api.docs.virtual.MapDoc;
|
import tc.oc.api.docs.virtual.MapDoc;
|
||||||
import tc.oc.api.util.Permissions;
|
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.ComponentRenderContext;
|
||||||
import tc.oc.commons.bukkit.chat.NameStyle;
|
import tc.oc.commons.bukkit.chat.NameStyle;
|
||||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||||
|
@ -166,7 +166,7 @@ public class MapCommands implements Commands {
|
||||||
if(args.getSuggestionContext() != null) {
|
if(args.getSuggestionContext() != null) {
|
||||||
return CommandUtils.completeMapName(args.getJoinedStrings(0));
|
return CommandUtils.completeMapName(args.getJoinedStrings(0));
|
||||||
}
|
}
|
||||||
final Audience audience = BukkitAudiences.getAudience(sender);
|
final Audience audience = Audiences.Deprecated.get(sender);
|
||||||
final PGMMap map;
|
final PGMMap map;
|
||||||
if(args.argsLength() > 0) {
|
if(args.argsLength() > 0) {
|
||||||
map = CommandUtils.getMap(args.getJoinedStrings(0), sender);
|
map = CommandUtils.getMap(args.getJoinedStrings(0), sender);
|
||||||
|
|
|
@ -2,6 +2,7 @@ package tc.oc.pgm.ffa;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
@ -223,8 +224,8 @@ public class Tribute implements Competitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Audience audience() {
|
public Stream<? extends Audience> audiences() {
|
||||||
return player != null ? player : NullAudience.INSTANCE;
|
return player != null ? Stream.of(player) : Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -14,15 +14,13 @@ import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.entity.TNTPrimed;
|
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.Audiences;
|
||||||
import tc.oc.commons.bukkit.chat.BukkitSound;
|
import tc.oc.commons.bukkit.chat.BukkitSound;
|
||||||
import tc.oc.commons.bukkit.chat.NameStyle;
|
import tc.oc.commons.bukkit.chat.NameStyle;
|
||||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
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.FrozenPlayer;
|
||||||
import tc.oc.commons.bukkit.freeze.PlayerFreezer;
|
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.nick.IdentityProvider;
|
||||||
import tc.oc.commons.bukkit.util.OnlinePlayerMapAdapter;
|
import tc.oc.commons.bukkit.util.OnlinePlayerMapAdapter;
|
||||||
import tc.oc.commons.core.chat.Audience;
|
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 Audience freezeeAudience = audiences.get(freezee);
|
||||||
|
|
||||||
final FrozenPlayer frozenPlayer = frozenPlayers.get(freezee);
|
final FrozenPlayer frozenPlayer = frozenPlayers.get(freezee);
|
||||||
if(frozen && frozenPlayer == null) {
|
if(frozen && frozenPlayer == null) {
|
||||||
frozenPlayers.put(freezee, playerFreezer.freeze(freezee));
|
frozenPlayers.put(freezee, playerFreezer.freeze(freezee));
|
||||||
|
|
||||||
final BaseComponent freezeeMessage = new Component(
|
final BaseComponent freezeeMessage = new Component(new TranslatableComponent("freeze.frozen", freezerComponent), ChatColor.RED);
|
||||||
new TranslatableComponent(
|
|
||||||
"freeze.frozen",
|
|
||||||
new PlayerComponent(freezerIdentity, NameStyle.FANCY)
|
|
||||||
),
|
|
||||||
ChatColor.RED
|
|
||||||
);
|
|
||||||
|
|
||||||
freezeeAudience.playSound(FREEZE_SOUND);
|
freezeeAudience.playSound(FREEZE_SOUND);
|
||||||
freezeeAudience.sendWarning(freezeeMessage, false);
|
freezeeAudience.sendWarning(freezeeMessage, false);
|
||||||
|
@ -106,26 +99,15 @@ public class Freeze implements PluginFacet {
|
||||||
removeEntities(((Player) freezer).getLocation(), config.tntSenderRadius());
|
removeEntities(((Player) freezer).getLocation(), config.tntSenderRadius());
|
||||||
}
|
}
|
||||||
|
|
||||||
adminChannel.broadcast(CommandUtils.getDisplayName(freezer) +
|
adminChannel.sendMessage(new TranslatableComponent("freeze.frozen.broadcast", freezeeComponent, freezerComponent));
|
||||||
ChatColor.RED + " froze " +
|
|
||||||
CommandUtils.getDisplayName(freezee));
|
|
||||||
} else if(!frozen && frozenPlayer != null) {
|
} else if(!frozen && frozenPlayer != null) {
|
||||||
frozenPlayer.thaw();
|
frozenPlayer.thaw();
|
||||||
frozenPlayers.remove(freezee);
|
frozenPlayers.remove(freezee);
|
||||||
|
|
||||||
freezeeAudience.hideTitle();
|
freezeeAudience.hideTitle();
|
||||||
freezeeAudience.playSound(THAW_SOUND);
|
freezeeAudience.playSound(THAW_SOUND);
|
||||||
freezeeAudience.sendMessage(new Component(
|
freezeeAudience.sendMessage(new Component(new TranslatableComponent("freeze.unfrozen", freezerComponent), ChatColor.GREEN));
|
||||||
new TranslatableComponent(
|
adminChannel.sendMessage(new TranslatableComponent("freeze.unfrozen.broadcast", freezeeComponent, freezerComponent));
|
||||||
"freeze.unfrozen",
|
|
||||||
new PlayerComponent(freezerIdentity, NameStyle.FANCY)
|
|
||||||
),
|
|
||||||
ChatColor.GREEN
|
|
||||||
));
|
|
||||||
|
|
||||||
adminChannel.broadcast(CommandUtils.getDisplayName(freezer) +
|
|
||||||
ChatColor.RED + " unfroze " +
|
|
||||||
CommandUtils.getDisplayName(freezee));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -197,11 +197,11 @@ public abstract class TouchableGoal<T extends ProximityGoalDefinition> extends P
|
||||||
|
|
||||||
if(toucher != null) {
|
if(toucher != null) {
|
||||||
if(includeToucher) {
|
if(includeToucher) {
|
||||||
toucher.getAudience().sendMessage(getTouchMessage(toucher, true));
|
toucher.sendMessage(getTouchMessage(toucher, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getDeferTouches()) {
|
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.getCancelMessage() != null &&
|
||||||
event.isManual()) {
|
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) {
|
if(oldScore != null && score == oldScore) {
|
||||||
player.sendWarning(PGMTranslations.t("rating.sameRating", player, score), true);
|
player.sendWarning(PGMTranslations.t("rating.sameRating", player, score), false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import tc.oc.api.docs.PlayerId;
|
import tc.oc.api.docs.PlayerId;
|
||||||
import tc.oc.api.docs.UserId;
|
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.inject.InjectionScopable;
|
||||||
import tc.oc.commons.core.random.Entropy;
|
import tc.oc.commons.core.random.Entropy;
|
||||||
import tc.oc.commons.core.util.ArrayUtils;
|
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.TickClock;
|
||||||
import tc.oc.pgm.time.TickTime;
|
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
|
* Unique ID for this match
|
||||||
|
|
|
@ -1,50 +1,46 @@
|
||||||
package tc.oc.pgm.match;
|
package tc.oc.pgm.match;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import tc.oc.commons.bukkit.chat.Audiences;
|
||||||
|
|
||||||
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.core.chat.Audience;
|
import tc.oc.commons.core.chat.Audience;
|
||||||
import tc.oc.commons.core.chat.MultiAudience;
|
import tc.oc.commons.core.chat.MultiAudience;
|
||||||
|
import tc.oc.minecraft.api.entity.Player;
|
||||||
import tc.oc.pgm.filters.Filter;
|
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
|
* Provides various aggregate {@link Audience}s within a match
|
||||||
*/
|
*/
|
||||||
|
@Singleton
|
||||||
public class MatchAudiences {
|
public class MatchAudiences {
|
||||||
|
|
||||||
private final Match match;
|
private final Match match;
|
||||||
private final Audience participants;
|
private final Audiences audiences;
|
||||||
private final Audience observers;
|
|
||||||
private final ImmutableSet<ConsoleAudience> console;
|
|
||||||
|
|
||||||
@Inject MatchAudiences(Match match, ConsoleAudience console) {
|
@Inject
|
||||||
|
MatchAudiences(Match match, Audiences audiences) {
|
||||||
this.match = match;
|
this.match = match;
|
||||||
this.console = ImmutableSet.of(console);
|
this.audiences = audiences;
|
||||||
this.participants = new MultiAudience(Iterables.concat(this.console, match.getParticipatingPlayers()));
|
|
||||||
this.observers = new MultiAudience(Iterables.concat(this.console, match.getObservingPlayers()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Audience all() {
|
public MultiAudience all() {
|
||||||
return match;
|
return () -> Stream.of(audiences.console(), audiences.playerFilter(player -> match.player(player).isPresent()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Audience participants() {
|
public MultiAudience participants() {
|
||||||
return participants;
|
return () -> Stream.of(audiences.console(), audiences.playerFilter(player -> match.participant(player).isPresent()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Audience observers() {
|
public MultiAudience observers() {
|
||||||
return observers;
|
return () -> Stream.of(audiences.console(), audiences.playerFilter(player -> match.getObservingPlayers().contains(match.player(player).orElse(null))));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Audience filter(Filter filter) {
|
public MultiAudience filter(Filter filter) {
|
||||||
return new AbstractMultiAudience() {
|
final Set<Player> allowed = match.players().filter(player -> !filter.denies(player)).map(MatchPlayer::getBukkit).collect(Collectors.toSet());
|
||||||
@Override
|
return () -> Stream.of(audiences.console(), audiences.playerFilter(allowed::contains));
|
||||||
protected Iterable<? extends Audience> getAudiences() {
|
|
||||||
return Iterables.concat(console, Iterables.filter(match.getPlayers(), player -> !filter.denies(player)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,13 +24,10 @@ import com.google.common.collect.BiMap;
|
||||||
import com.google.common.collect.BoundType;
|
import com.google.common.collect.BoundType;
|
||||||
import com.google.common.collect.HashBiMap;
|
import com.google.common.collect.HashBiMap;
|
||||||
import com.google.common.collect.HashMultimap;
|
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.Maps;
|
||||||
import com.google.common.collect.Multimaps;
|
import com.google.common.collect.Multimaps;
|
||||||
import com.google.common.collect.Range;
|
import com.google.common.collect.Range;
|
||||||
import com.google.common.collect.SetMultimap;
|
import com.google.common.collect.SetMultimap;
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
import org.bukkit.Server;
|
import org.bukkit.Server;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Player;
|
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.User;
|
||||||
import tc.oc.api.docs.UserId;
|
import tc.oc.api.docs.UserId;
|
||||||
import tc.oc.api.model.IdFactory;
|
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.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.exception.ExceptionHandler;
|
||||||
import tc.oc.commons.core.inject.ChildInjectorFactory;
|
import tc.oc.commons.core.inject.ChildInjectorFactory;
|
||||||
import tc.oc.commons.core.inject.FacetContext;
|
import tc.oc.commons.core.inject.FacetContext;
|
||||||
|
@ -99,7 +94,7 @@ import tc.oc.pgm.utils.WorldTickRandom;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.*;
|
import static com.google.common.base.Preconditions.*;
|
||||||
|
|
||||||
public class MatchImpl implements Match, ForwardingAudience {
|
public class MatchImpl implements Match {
|
||||||
|
|
||||||
private Logger logger;
|
private Logger logger;
|
||||||
|
|
||||||
|
@ -121,8 +116,7 @@ public class MatchImpl implements Match, ForwardingAudience {
|
||||||
@Inject private FeatureDefinitionContext featureDefinitions;
|
@Inject private FeatureDefinitionContext featureDefinitions;
|
||||||
@Inject private World world;
|
@Inject private World world;
|
||||||
|
|
||||||
@Inject private ConsoleAudience consoleAudience;
|
@Inject private Audiences audiences;
|
||||||
private Audience audience;
|
|
||||||
|
|
||||||
// State management
|
// State management
|
||||||
private final AtomicBoolean unloaded = new AtomicBoolean(true); // true before loading starts and after unloading finishes
|
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();
|
id = idFactory.newId();
|
||||||
url = new URL("http", "localhost:3000", "/matches/" + id);
|
url = new URL("http", "localhost:3000", "/matches/" + id);
|
||||||
loadTime = clock.now();
|
loadTime = clock.now();
|
||||||
audience = new MultiAudience(Iterables.concat(ImmutableSet.of(consoleAudience), getPlayers()));
|
|
||||||
setState(MatchState.Idle);
|
setState(MatchState.Idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,8 +258,8 @@ public class MatchImpl implements Match, ForwardingAudience {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Audience audience() {
|
public Stream<Audience> audiences() {
|
||||||
return audience;
|
return Stream.of(audiences.console(), audiences.filter(sender -> player(sender).isPresent()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -927,21 +920,4 @@ public class MatchImpl implements Match, ForwardingAudience {
|
||||||
partyChanges.remove(player);
|
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.Server;
|
||||||
import tc.oc.api.docs.User;
|
import tc.oc.api.docs.User;
|
||||||
import tc.oc.commons.bukkit.attribute.AttributeUtils;
|
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.BukkitSound;
|
||||||
import tc.oc.commons.bukkit.chat.NameStyle;
|
import tc.oc.commons.bukkit.chat.NameStyle;
|
||||||
import tc.oc.commons.bukkit.chat.Named;
|
import tc.oc.commons.bukkit.chat.Named;
|
||||||
|
@ -77,6 +77,7 @@ public class MatchPlayer extends MatchFacetContext<MatchPlayerFacet> implements
|
||||||
@Inject private Server localServer;
|
@Inject private Server localServer;
|
||||||
@Inject private OnlineFriends friendMap;
|
@Inject private OnlineFriends friendMap;
|
||||||
@Inject private PlayerStates playerStates;
|
@Inject private PlayerStates playerStates;
|
||||||
|
@Inject private Audiences audiences;
|
||||||
|
|
||||||
@Inject MatchUserContext userContext;
|
@Inject MatchUserContext userContext;
|
||||||
|
|
||||||
|
@ -90,7 +91,7 @@ public class MatchPlayer extends MatchFacetContext<MatchPlayerFacet> implements
|
||||||
private Logger logger;
|
private Logger logger;
|
||||||
private SettingManager settings;
|
private SettingManager settings;
|
||||||
private Audience audience;
|
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.logger = loggers.get(match.getLogger(), getClass(), getName());
|
||||||
this.settings = settingManagerProvider.getManager(player);
|
this.settings = settingManagerProvider.getManager(player);
|
||||||
this.audience = audiences.get(player);
|
this.audience = audiences.get(player);
|
||||||
|
@ -519,19 +520,19 @@ public class MatchPlayer extends MatchFacetContext<MatchPlayerFacet> implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Audience audience() {
|
public Optional<Audience> audience() {
|
||||||
return audience;
|
return Optional.ofNullable(audiences.get(bukkit));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendWarning(String message, boolean audible) {
|
public void sendWarning(String message, boolean audible) {
|
||||||
audience().sendWarning(message, audible);
|
audience().get().sendWarning(message, audible);
|
||||||
if(audible) playWarningSound();
|
if(audible) playWarningSound();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendWarning(BaseComponent message, boolean audible) {
|
public void sendWarning(BaseComponent message, boolean audible) {
|
||||||
audience().sendWarning(message, audible);
|
audience().get().sendWarning(message, audible);
|
||||||
if(audible) playWarningSound();
|
if(audible) playWarningSound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,10 @@ public interface MatchPlayerFinder {
|
||||||
return state == null ? null : getPlayer(state.getUniqueId());
|
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) {
|
default Optional<MatchPlayer> player(@Nullable Player bukkit) {
|
||||||
return Optional.ofNullable(getPlayer(bukkit));
|
return Optional.ofNullable(getPlayer(bukkit));
|
||||||
}
|
}
|
||||||
|
@ -54,6 +58,10 @@ public interface MatchPlayerFinder {
|
||||||
return Optional.ofNullable(getPlayer(userId));
|
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) {
|
default Optional<MatchPlayer> participant(@Nullable Entity entity) {
|
||||||
return player(entity).filter(MatchPlayer::isParticipating);
|
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.chat.PlayerComponent;
|
||||||
import tc.oc.commons.bukkit.nick.Identity;
|
import tc.oc.commons.bukkit.nick.Identity;
|
||||||
import tc.oc.commons.core.chat.Audience;
|
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.chat.NullAudience;
|
||||||
import tc.oc.commons.core.util.Utils;
|
import tc.oc.commons.core.util.Utils;
|
||||||
import tc.oc.pgm.filters.query.IPlayerQuery;
|
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}.
|
* 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 Identity identity;
|
||||||
protected final Party party;
|
protected final Party party;
|
||||||
|
|
||||||
|
@ -88,9 +89,9 @@ public class MatchPlayerState extends MatchEntityState implements IPlayerQuery {
|
||||||
return getParty().isParticipating();
|
return getParty().isParticipating();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Audience getAudience() {
|
@Override
|
||||||
MatchPlayer matchPlayer = getMatchPlayer();
|
public Optional<Audience> audience() {
|
||||||
return matchPlayer == null ? NullAudience.INSTANCE : matchPlayer;
|
return Optional.ofNullable(getMatchPlayer());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -2,12 +2,12 @@ package tc.oc.pgm.match;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import tc.oc.api.bukkit.users.Users;
|
import tc.oc.api.bukkit.users.Users;
|
||||||
import tc.oc.api.docs.PlayerId;
|
import tc.oc.api.docs.PlayerId;
|
||||||
import tc.oc.commons.core.chat.AbstractMultiAudience;
|
|
||||||
import tc.oc.commons.core.chat.Audience;
|
import tc.oc.commons.core.chat.Audience;
|
||||||
|
|
||||||
public abstract class MultiPlayerParty implements Party {
|
public abstract class MultiPlayerParty implements Party {
|
||||||
|
@ -15,13 +15,6 @@ public abstract class MultiPlayerParty implements Party {
|
||||||
protected final Match match;
|
protected final Match match;
|
||||||
private final Set<MatchPlayer> players = new HashSet<>();
|
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) {
|
public MultiPlayerParty(Match match) {
|
||||||
this.match = match;
|
this.match = match;
|
||||||
}
|
}
|
||||||
|
@ -64,7 +57,7 @@ public abstract class MultiPlayerParty implements Party {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Audience audience() {
|
public Stream<? extends Audience> audiences() {
|
||||||
return audience;
|
return players();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import tc.oc.commons.core.chat.Audience;
|
||||||
import tc.oc.commons.bukkit.chat.Named;
|
import tc.oc.commons.bukkit.chat.Named;
|
||||||
import tc.oc.commons.core.chat.Component;
|
import tc.oc.commons.core.chat.Component;
|
||||||
import tc.oc.commons.core.chat.Components;
|
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.Filterable;
|
||||||
import tc.oc.pgm.filters.query.IPartyQuery;
|
import tc.oc.pgm.filters.query.IPartyQuery;
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Stream;
|
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 }
|
enum Type { Participating, Observing }
|
||||||
|
|
||||||
|
@ -156,8 +157,6 @@ public interface Party extends Named, IPartyQuery, Filterable<IPartyQuery> {
|
||||||
return isObservingType() || !getMatch().isRunning();
|
return isObservingType() || !getMatch().isRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
Audience audience();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default Optional<? extends Filterable<? super IPartyQuery>> filterableParent() {
|
default Optional<? extends Filterable<? super IPartyQuery>> filterableParent() {
|
||||||
return Optional.of(getMatch());
|
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.MatchPublishingMatchModule;
|
||||||
import tc.oc.pgm.api.ParticipationPublishingMatchModule;
|
import tc.oc.pgm.api.ParticipationPublishingMatchModule;
|
||||||
import tc.oc.pgm.bossbar.BossBarMatchModule;
|
import tc.oc.pgm.bossbar.BossBarMatchModule;
|
||||||
import tc.oc.pgm.channels.ChannelMatchModule;
|
|
||||||
import tc.oc.pgm.cycle.CycleMatchModule;
|
import tc.oc.pgm.cycle.CycleMatchModule;
|
||||||
import tc.oc.pgm.damage.HitboxMatchModule;
|
import tc.oc.pgm.damage.HitboxMatchModule;
|
||||||
import tc.oc.pgm.death.DeathMessageMatchModule;
|
import tc.oc.pgm.death.DeathMessageMatchModule;
|
||||||
|
@ -52,7 +51,6 @@ public class MatchModulesManifest extends HybridManifest {
|
||||||
install(new MatchModuleFixtureManifest<SkillRequirementMatchModule>(){});
|
install(new MatchModuleFixtureManifest<SkillRequirementMatchModule>(){});
|
||||||
install(new MatchModuleFixtureManifest<StartMatchModule>(){});
|
install(new MatchModuleFixtureManifest<StartMatchModule>(){});
|
||||||
install(new MatchModuleFixtureManifest<ArrowRemovalMatchModule>(){});
|
install(new MatchModuleFixtureManifest<ArrowRemovalMatchModule>(){});
|
||||||
install(new MatchModuleFixtureManifest<ChannelMatchModule>(){});
|
|
||||||
install(new MatchModuleFixtureManifest<DoubleJumpMatchModule>(){});
|
install(new MatchModuleFixtureManifest<DoubleJumpMatchModule>(){});
|
||||||
install(new MatchModuleFixtureManifest<GoalMatchModule>(){});
|
install(new MatchModuleFixtureManifest<GoalMatchModule>(){});
|
||||||
install(new MatchModuleFixtureManifest<ProjectileMatchModule>(){});
|
install(new MatchModuleFixtureManifest<ProjectileMatchModule>(){});
|
||||||
|
|
|
@ -167,7 +167,7 @@ public class MutationCommands implements NestedCommands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Audience origin = audiences.get(sender);
|
Audience origin = audiences.get(sender);
|
||||||
Audience all = audiences.localServer();
|
Audience all = audiences.all();
|
||||||
String message = message(!queued, value, mutations.size() == 1);
|
String message = message(!queued, value, mutations.size() == 1);
|
||||||
ListComponent changed = new ListComponent(Collections2.transform(mutations, Mutation.toComponent(ChatColor.AQUA)));
|
ListComponent changed = new ListComponent(Collections2.transform(mutations, Mutation.toComponent(ChatColor.AQUA)));
|
||||||
if(queued) {
|
if(queued) {
|
||||||
|
|
|
@ -195,7 +195,7 @@ public class EntityMutation<E extends Entity> extends KitMutation {
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = false, priority = EventPriority.HIGHEST)
|
@EventHandler(ignoreCancelled = false, priority = EventPriority.HIGHEST)
|
||||||
public void onPlayerSpawnEntity(PlayerSpawnEntityEvent event) {
|
public void onPlayerSpawnEntity(PlayerSpawnEntityEvent event) {
|
||||||
match().participant(event.getPlayer())
|
match().participant((Entity) event.getPlayer())
|
||||||
.ifPresent(player -> cast(event.getEntity(), type)
|
.ifPresent(player -> cast(event.getEntity(), type)
|
||||||
.ifPresent(entity -> {
|
.ifPresent(entity -> {
|
||||||
register(entity, player);
|
register(entity, player);
|
||||||
|
|
|
@ -66,7 +66,7 @@ public class DynamicRotationListener implements PluginFacet, Listener {
|
||||||
rotationManager.setCurrentRotationName(rotation.name);
|
rotationManager.setCurrentRotationName(rotation.name);
|
||||||
|
|
||||||
logger.info("Changing to \"" + rotation.name + "\" rotation...");
|
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.EventHandler;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.bukkit.event.Listener;
|
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.chat.Component;
|
||||||
import tc.oc.commons.core.formatting.PeriodFormats;
|
import tc.oc.commons.core.formatting.PeriodFormats;
|
||||||
import tc.oc.commons.core.util.Comparables;
|
import tc.oc.commons.core.util.Comparables;
|
||||||
|
@ -59,7 +61,7 @@ public class HuddleCountdown extends PreMatchCountdown implements Listener {
|
||||||
|
|
||||||
if(Comparables.greaterThan(total, Duration.ZERO)) {
|
if(Comparables.greaterThan(total, Duration.ZERO)) {
|
||||||
getMatch().getCompetitors().stream().filter(competitor -> competitor instanceof Team).forEach(competitor -> {
|
getMatch().getCompetitors().stream().filter(competitor -> competitor instanceof Team).forEach(competitor -> {
|
||||||
competitor.audience().sendMessage(new Component(
|
competitor.sendMessage(new Component(
|
||||||
new TranslatableComponent("huddle.instructions",
|
new TranslatableComponent("huddle.instructions",
|
||||||
PeriodFormats.briefNaturalPrecise(total)),
|
PeriodFormats.briefNaturalPrecise(total)),
|
||||||
ChatColor.YELLOW
|
ChatColor.YELLOW
|
||||||
|
@ -69,12 +71,12 @@ public class HuddleCountdown extends PreMatchCountdown implements Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onChat(ChannelMessageEvent event) {
|
public void onChat(ChannelChatEvent event) {
|
||||||
if(event.getChannel() == ChannelsPlugin.get().getGlobalChannel()) {
|
if(event.channel().type().equals(ChatDoc.Type.SERVER)) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
MatchPlayer player = getMatch().getPlayer(event.getSender());
|
MatchPlayer player = getMatch().getPlayer(event.sender());
|
||||||
if(player != null) {
|
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);
|
MatchPlayer player = shortList.get(i);
|
||||||
if(even && areTeamsEven() && shortList.size() - i < getTeams().size()) {
|
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
|
// 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 {
|
} else {
|
||||||
join(player, request, queryJoin(player, request, true));
|
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
|
if(player != null) { // wool can only be placed by a player
|
||||||
BaseComponent woolName = BukkitUtils.woolName(wool.getDyeColor());
|
BaseComponent woolName = BukkitUtils.woolName(wool.getDyeColor());
|
||||||
if(!isValidWool(wool.getDyeColor(), event.getNewState())) {
|
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()) {
|
} 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 {
|
} else {
|
||||||
event.setCancelled(false);
|
event.setCancelled(false);
|
||||||
wool.markPlaced();
|
wool.markPlaced();
|
||||||
|
|
|
@ -6,9 +6,6 @@ depend:
|
||||||
- Commons
|
- Commons
|
||||||
- API
|
- API
|
||||||
- BukkitSettings
|
- BukkitSettings
|
||||||
- Channels
|
|
||||||
softdepend:
|
|
||||||
- ChatModerator
|
|
||||||
authors:
|
authors:
|
||||||
- Overcast Network
|
- Overcast Network
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ public class Tourney extends JavaPlugin {
|
||||||
);
|
);
|
||||||
|
|
||||||
audiences.get(Bukkit.getConsoleSender()).sendMessage(message);
|
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.Provider;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import com.github.rmsy.channels.ChannelsPlugin;
|
|
||||||
import net.anxuiz.tourney.MatchManager;
|
import net.anxuiz.tourney.MatchManager;
|
||||||
import net.anxuiz.tourney.TeamManager;
|
import net.anxuiz.tourney.TeamManager;
|
||||||
import net.anxuiz.tourney.Tourney;
|
import net.anxuiz.tourney.Tourney;
|
||||||
|
@ -137,10 +136,6 @@ public class TeamListener implements Listener {
|
||||||
Team team = teamManagerProvider.get().getTeam(player);
|
Team team = teamManagerProvider.get().getTeam(player);
|
||||||
if(team != null) {
|
if(team != null) {
|
||||||
event.getMatch().setPlayerParty(event.getPlayer(), team, false);
|
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
|
// broadcast to team
|
||||||
if (classificationSelected) {
|
if (classificationSelected) {
|
||||||
for (Entrant participation : vote.getParticipatingTeams()) {
|
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(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 + "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.");
|
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 {
|
} else {
|
||||||
for (Entrant participation : vote.getParticipatingTeams()) {
|
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(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 + "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.");
|
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;
|
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.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 org.bukkit.plugin.Plugin;
|
||||||
import tc.oc.commons.bukkit.bossbar.BossBarFactory;
|
import tc.oc.commons.bukkit.bossbar.BossBarFactory;
|
||||||
import tc.oc.commons.bukkit.bossbar.BossBarFactoryImpl;
|
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.item.RenderedItemBuilder;
|
||||||
import tc.oc.commons.bukkit.logging.BukkitLoggerFactory;
|
import tc.oc.commons.bukkit.logging.BukkitLoggerFactory;
|
||||||
import tc.oc.commons.bukkit.permissions.BukkitPermissionRegistry;
|
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(new TypeLiteral<PluginResolver<Plugin>>(){}).to(BukkitPluginResolver.class);
|
||||||
bind(Loggers.class).to(BukkitLoggerFactory.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.core.chat.Audiences.class).to(Audiences.class);
|
||||||
bind(tc.oc.commons.bukkit.chat.Audiences.class).to(BukkitAudiences.class);
|
requestStaticInjection(Audiences.Deprecated.class);
|
||||||
bind(PermissionRegistry.class).to(BukkitPermissionRegistry.class);
|
bind(PermissionRegistry.class).to(BukkitPermissionRegistry.class);
|
||||||
bind(BossBarFactory.class).to(BossBarFactoryImpl.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.event.player.PlayerTeleportEvent.TeleportCause;
|
||||||
import org.bukkit.util.RayBlockIntersection;
|
import org.bukkit.util.RayBlockIntersection;
|
||||||
import org.bukkit.util.Vector;
|
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.BlockPunchEvent;
|
||||||
import tc.oc.commons.bukkit.event.BlockTrampleEvent;
|
import tc.oc.commons.bukkit.event.BlockTrampleEvent;
|
||||||
import tc.oc.commons.bukkit.event.CoarsePlayerMoveEvent;
|
import tc.oc.commons.bukkit.event.CoarsePlayerMoveEvent;
|
||||||
|
@ -42,6 +42,7 @@ import tc.oc.commons.core.plugin.PluginFacet;
|
||||||
public class PlayerMovementListener implements PluginFacet, Listener {
|
public class PlayerMovementListener implements PluginFacet, Listener {
|
||||||
|
|
||||||
protected final EventBus eventBus;
|
protected final EventBus eventBus;
|
||||||
|
protected final Audiences audiences;
|
||||||
|
|
||||||
// The last location of a player that has been used to generate
|
// The last location of a player that has been used to generate
|
||||||
// coarse movement events. If a player is not in this list, then
|
// 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.
|
// on its own.
|
||||||
private final Map<Player, EntityLocation> lastToLocation = new WeakHashMap<>();
|
private final Map<Player, EntityLocation> lastToLocation = new WeakHashMap<>();
|
||||||
|
|
||||||
@Inject PlayerMovementListener(EventBus eventBus) {
|
@Inject PlayerMovementListener(EventBus eventBus, Audiences audiences) {
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
|
this.audiences = audiences;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -257,7 +259,7 @@ public class PlayerMovementListener implements PluginFacet, Listener {
|
||||||
@EventHandler(priority = EventPriority.MONITOR)
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
public void processCancelMessage(final CoarsePlayerMoveEvent event) {
|
public void processCancelMessage(final CoarsePlayerMoveEvent event) {
|
||||||
if(event.isCancelled() && event.getCancelMessage() != null) {
|
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
|
@Override
|
||||||
public void addPermission(Permission permission) {
|
public void register(Permission permission) {
|
||||||
pluginManager.addPermission(permission);
|
pluginManager.addPermission(permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removePermission(Permission permission) {
|
public void unregister(Permission permission) {
|
||||||
pluginManager.removePermission(permission);
|
pluginManager.removePermission(permission);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,36 @@
|
||||||
package tc.oc.commons.bukkit.permissions;
|
package tc.oc.commons.bukkit.permissions;
|
||||||
|
|
||||||
import org.bukkit.permissions.Permission;
|
import org.bukkit.permissions.Permission;
|
||||||
|
import org.bukkit.permissions.PermissionDefault;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstraction layer for Bukkit permission API
|
* Abstraction layer for Bukkit permission API
|
||||||
*/
|
*/
|
||||||
public interface PermissionRegistry {
|
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;
|
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.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 com.google.inject.TypeLiteral;
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
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.logging.BungeeLoggerFactory;
|
||||||
import tc.oc.commons.bungee.plugin.BungeePluginResolver;
|
import tc.oc.commons.bungee.plugin.BungeePluginResolver;
|
||||||
import tc.oc.commons.core.inject.SingletonManifest;
|
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(new TypeLiteral<PluginResolver<Plugin>>(){}).to(BungeePluginResolver.class);
|
||||||
bind(Loggers.class).to(BungeeLoggerFactory.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.core.chat.Audiences.class).to(Audiences.class);
|
||||||
bind(tc.oc.commons.bungee.chat.Audiences.class).to(BungeeAudiences.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