Merge 8b51c184ab
into b883ef5799
This commit is contained in:
commit
3e93a87f40
|
@ -5,7 +5,7 @@
|
|||
<groupId>tc.oc</groupId>
|
||||
<artifactId>api-parent</artifactId>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
<version>1.11-SNAPSHOT</version>
|
||||
<version>1.12-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>api</artifactId>
|
||||
|
|
|
@ -2,6 +2,7 @@ package tc.oc.api;
|
|||
|
||||
import tc.oc.api.document.DocumentsManifest;
|
||||
import tc.oc.api.engagement.EngagementModelManifest;
|
||||
import tc.oc.api.friendships.FriendshipModelManifest;
|
||||
import tc.oc.api.games.GameModelManifest;
|
||||
import tc.oc.api.http.HttpManifest;
|
||||
import tc.oc.api.maps.MapModelManifest;
|
||||
|
@ -44,5 +45,6 @@ public final class ApiManifest extends HybridManifest {
|
|||
install(new WhisperModelManifest());
|
||||
install(new TrophyModelManifest());
|
||||
install(new TournamentModelManifest());
|
||||
install(new FriendshipModelManifest());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package tc.oc.api.docs;
|
||||
|
||||
import tc.oc.api.docs.virtual.FriendshipDoc;
|
||||
|
||||
public interface Friendship extends FriendshipDoc.Complete {}
|
|
@ -0,0 +1,23 @@
|
|||
package tc.oc.api.docs.virtual;
|
||||
|
||||
import tc.oc.api.annotations.Serialize;
|
||||
import tc.oc.api.docs.PlayerId;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.Instant;
|
||||
|
||||
public interface FriendshipDoc {
|
||||
|
||||
interface Partial extends PartialModel {}
|
||||
|
||||
@Serialize
|
||||
interface Complete extends Model, Partial {
|
||||
Instant sent_date();
|
||||
@Nullable Instant decision_date();
|
||||
PlayerId friender();
|
||||
PlayerId friended();
|
||||
boolean undecided();
|
||||
boolean accepted();
|
||||
boolean rejected();
|
||||
}
|
||||
}
|
|
@ -30,11 +30,7 @@ public interface MatchDoc extends Model {
|
|||
Collection<String> winning_team_ids();
|
||||
Collection<String> winning_user_ids();
|
||||
|
||||
enum Mutation {
|
||||
BLITZ, UHC, EXPLOSIVES, NO_FALL, MOBS, STRENGTH, DOUBLE_JUMP, INVISIBILITY, LIGHTNING, RAGE, ELYTRA;
|
||||
}
|
||||
|
||||
Set<Mutation> mutations();
|
||||
Set<String> mutations();
|
||||
|
||||
@Serialize
|
||||
interface Team extends MapDoc.Team, CompetitorDoc {
|
||||
|
|
|
@ -22,6 +22,7 @@ public interface PunishmentDoc {
|
|||
boolean silent();
|
||||
boolean automatic();
|
||||
boolean active();
|
||||
boolean off_record();
|
||||
}
|
||||
|
||||
@Serialize
|
||||
|
@ -29,7 +30,6 @@ public interface PunishmentDoc {
|
|||
@Nullable String punisher_id();
|
||||
@Nullable String punished_id();
|
||||
@Nullable Type type();
|
||||
boolean off_record();
|
||||
}
|
||||
|
||||
@Serialize
|
||||
|
|
|
@ -50,7 +50,8 @@ public interface ServerDoc {
|
|||
}
|
||||
|
||||
@Serialize
|
||||
interface CurrentPort extends Partial {
|
||||
interface Ip extends Partial {
|
||||
String ip();
|
||||
Integer current_port();
|
||||
}
|
||||
|
||||
|
@ -95,7 +96,7 @@ public interface ServerDoc {
|
|||
* Startup info sent to the API
|
||||
*/
|
||||
@Serialize
|
||||
interface Startup extends Online, CurrentPort {
|
||||
interface Startup extends Online, Ip {
|
||||
@Nullable DeployInfo deploy_info();
|
||||
Map<String, String> plugin_versions();
|
||||
Set<Integer> protocol_versions();
|
||||
|
@ -105,7 +106,7 @@ public interface ServerDoc {
|
|||
* Startup info received from the API
|
||||
*/
|
||||
@Serialize
|
||||
interface Configuration extends Partial {
|
||||
interface Configuration extends Rotations {
|
||||
String settings_profile();
|
||||
Map<UUID, String> operators();
|
||||
@Nullable Team team();
|
||||
|
@ -116,7 +117,6 @@ public interface ServerDoc {
|
|||
Visibility startup_visibility();
|
||||
boolean whitelist_enabled();
|
||||
boolean waiting_room();
|
||||
|
||||
@Nullable String resource_pack_url();
|
||||
@Nullable String resource_pack_sha1();
|
||||
boolean resource_pack_fast_update();
|
||||
|
@ -138,7 +138,18 @@ public interface ServerDoc {
|
|||
|
||||
@Serialize
|
||||
interface Mutation extends Partial {
|
||||
Set<MatchDoc.Mutation> queued_mutations();
|
||||
Set<String> queued_mutations();
|
||||
}
|
||||
|
||||
@Serialize
|
||||
interface Rotations extends Partial {
|
||||
List<Rotation> rotations();
|
||||
}
|
||||
|
||||
@Serialize
|
||||
interface Rotation extends Document {
|
||||
String name();
|
||||
String next_map_id();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,6 +14,7 @@ public interface SessionDoc {
|
|||
interface Complete extends Model, Partial {
|
||||
String family_id();
|
||||
String server_id();
|
||||
@Nullable String version();
|
||||
PlayerId user();
|
||||
@Nullable String nickname();
|
||||
@Nullable String nickname_lower();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package tc.oc.api.docs.virtual;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -80,10 +79,14 @@ public interface UserDoc {
|
|||
* Stuff we get from the API on login, and keep around for plugins to use
|
||||
*/
|
||||
@Serialize
|
||||
interface Login extends Identity, Locale, Trophies, License.Complete {
|
||||
interface Login extends Identity, Locale, Trophies, DefaultServer, FriendTokens, DeathScreen, License.Complete {
|
||||
int raindrops();
|
||||
int maptokens();
|
||||
int mutationtokens();
|
||||
String mc_last_sign_in_ip();
|
||||
@Nullable Date trial_expires_at();
|
||||
@Nullable Instant nickname_updated_at();
|
||||
Map<String, Map<String, Map<String, Object>>> stats_value();
|
||||
Map<String, Map<String, Boolean>> mc_permissions_by_realm();
|
||||
Map<String, Map<String, String>> mc_settings_by_profile();
|
||||
Map<String, String> classes();
|
||||
|
@ -110,4 +113,20 @@ public interface UserDoc {
|
|||
interface ResourcePackResponse extends Partial {
|
||||
UserDoc.ResourcePackStatus resource_pack_status();
|
||||
}
|
||||
|
||||
@Serialize
|
||||
interface DefaultServer extends Partial {
|
||||
@Nullable String default_server_id();
|
||||
}
|
||||
|
||||
@Serialize
|
||||
interface DeathScreen extends Partial {
|
||||
String death_screen();
|
||||
}
|
||||
|
||||
@Serialize
|
||||
interface FriendTokens extends Partial {
|
||||
int friend_tokens_limit();
|
||||
int friend_tokens_concurrent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package tc.oc.api.friendships;
|
||||
|
||||
import com.google.inject.multibindings.OptionalBinder;
|
||||
import tc.oc.api.docs.Friendship;
|
||||
import tc.oc.api.docs.virtual.FriendshipDoc;
|
||||
import tc.oc.api.model.ModelBinders;
|
||||
import tc.oc.commons.core.inject.HybridManifest;
|
||||
|
||||
public class FriendshipModelManifest extends HybridManifest implements ModelBinders {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bindModel(Friendship.class, FriendshipDoc.Partial.class, model -> {
|
||||
model.bindService().to(FriendshipService.class);
|
||||
});
|
||||
|
||||
OptionalBinder.newOptionalBinder(publicBinder(), FriendshipService.class)
|
||||
.setDefault().to(NullFriendshipService.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package tc.oc.api.friendships;
|
||||
|
||||
import tc.oc.api.annotations.Serialize;
|
||||
import tc.oc.api.docs.virtual.Document;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Serialize
|
||||
public interface FriendshipRequest extends Document {
|
||||
String friender_id();
|
||||
@Nullable String friended_id();
|
||||
|
||||
static FriendshipRequest create(String friender_id, @Nullable String friended_id) {
|
||||
return new FriendshipRequest() {
|
||||
public String friender_id() { return friender_id; }
|
||||
public String friended_id() { return friended_id; }
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package tc.oc.api.friendships;
|
||||
|
||||
import tc.oc.api.annotations.Serialize;
|
||||
import tc.oc.api.docs.Friendship;
|
||||
import tc.oc.api.docs.virtual.Document;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
@Serialize
|
||||
public interface FriendshipResponse extends Document {
|
||||
boolean success();
|
||||
@Nullable String error();
|
||||
@Nullable List<Friendship> friendships();
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package tc.oc.api.friendships;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import tc.oc.api.docs.Friendship;
|
||||
import tc.oc.api.docs.virtual.FriendshipDoc;
|
||||
import tc.oc.api.model.ModelService;
|
||||
|
||||
public interface FriendshipService extends ModelService<Friendship, FriendshipDoc.Partial> {
|
||||
|
||||
ListenableFuture<FriendshipResponse> create(FriendshipRequest request);
|
||||
|
||||
ListenableFuture<FriendshipResponse> destroy(FriendshipRequest request);
|
||||
|
||||
ListenableFuture<FriendshipResponse> list(FriendshipRequest request);
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package tc.oc.api.friendships;
|
||||
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import tc.oc.api.docs.Friendship;
|
||||
import tc.oc.api.docs.virtual.FriendshipDoc;
|
||||
import tc.oc.api.exceptions.NotFound;
|
||||
import tc.oc.api.model.NullModelService;
|
||||
|
||||
public class NullFriendshipService extends NullModelService<Friendship, FriendshipDoc.Partial> implements FriendshipService {
|
||||
|
||||
@Override
|
||||
public ListenableFuture<FriendshipResponse> create(FriendshipRequest request) {
|
||||
return Futures.immediateFailedFuture(new NotFound());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<FriendshipResponse> destroy(FriendshipRequest request) {
|
||||
return Futures.immediateFailedFuture(new NotFound());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<FriendshipResponse> list(FriendshipRequest request) {
|
||||
return Futures.immediateFailedFuture(new NotFound());
|
||||
}
|
||||
}
|
|
@ -33,7 +33,5 @@ public class TypeAdaptersManifest extends Manifest {
|
|||
|
||||
gson.bindAdapter(new TypeLiteral<Set<MapDoc.Gamemode>>(){})
|
||||
.to(new TypeLiteral<LenientEnumSetTypeAdapter<MapDoc.Gamemode>>(){});
|
||||
gson.bindAdapter(new TypeLiteral<Set<MatchDoc.Mutation>>(){})
|
||||
.to(new TypeLiteral<LenientEnumSetTypeAdapter<MatchDoc.Mutation>>(){});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,6 @@ import tc.oc.api.message.types.Reply;
|
|||
|
||||
@Serialize
|
||||
public interface BadNickname extends Reply {
|
||||
enum Problem { TAKEN, INVALID }
|
||||
enum Problem { TAKEN, INVALID, THROTTLE }
|
||||
Problem problem();
|
||||
}
|
||||
|
|
|
@ -15,5 +15,7 @@ public interface SessionStartRequest extends Document {
|
|||
|
||||
InetAddress ip();
|
||||
|
||||
String version();
|
||||
|
||||
@Nullable String previous_session_id();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package tc.oc.api.users;
|
||||
|
||||
import tc.oc.api.annotations.Serialize;
|
||||
import tc.oc.api.docs.virtual.Document;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.Instant;
|
||||
|
||||
@Serialize
|
||||
public interface ChangeGroupRequest extends Document {
|
||||
String group();
|
||||
String type();
|
||||
@Nullable Instant end();
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package tc.oc.api.users;
|
||||
|
||||
import tc.oc.api.annotations.Serialize;
|
||||
import tc.oc.api.docs.virtual.Document;
|
||||
|
||||
@Serialize
|
||||
public interface CreditTokensRequest extends Document {
|
||||
String type();
|
||||
int amount();
|
||||
|
||||
static CreditTokensRequest raindrops(int amount) {
|
||||
return new CreditTokensRequest() {
|
||||
public String type() { return "raindrops"; }
|
||||
public int amount() { return amount; }
|
||||
};
|
||||
}
|
||||
|
||||
static CreditTokensRequest maps(int amount) {
|
||||
return new CreditTokensRequest() {
|
||||
public String type() { return "maptokens"; }
|
||||
public int amount() { return amount; }
|
||||
};
|
||||
}
|
||||
|
||||
static CreditTokensRequest mutations(int amount) {
|
||||
return new CreditTokensRequest() {
|
||||
public String type() { return "mutationtokens"; }
|
||||
public int amount() { return amount; }
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package tc.oc.api.users;
|
||||
|
||||
import tc.oc.api.annotations.Serialize;
|
||||
import tc.oc.api.docs.virtual.Document;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.Instant;
|
||||
|
||||
@Serialize
|
||||
public interface FriendJoinRequest extends Document {
|
||||
int amount();
|
||||
}
|
|
@ -4,6 +4,7 @@ import tc.oc.api.annotations.Serialize;
|
|||
import tc.oc.api.docs.virtual.Document;
|
||||
|
||||
@Serialize
|
||||
public interface CreditRaindropsRequest extends Document {
|
||||
int raindrops();
|
||||
public interface FriendJoinResponse extends Document {
|
||||
boolean authorized();
|
||||
String message();
|
||||
}
|
|
@ -31,10 +31,20 @@ public class NullUserService extends NullModelService<User, UserDoc.Partial> imp
|
|||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<UserUpdateResponse> creditRaindrops(UserId userId, CreditRaindropsRequest request) {
|
||||
public ListenableFuture<UserUpdateResponse> creditTokens(UserId userId, CreditTokensRequest request) {
|
||||
return Futures.immediateFuture(UserUpdateResponse.FAILURE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<User> changeGroup(UserId userId, ChangeGroupRequest request) {
|
||||
return Futures.immediateFailedFuture(new NotFound());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<FriendJoinResponse> joinFriend(UserId userId, FriendJoinRequest request) {
|
||||
return Futures.immediateFailedFuture(new NotFound());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<User> purchaseGizmo(UserId userId, PurchaseGizmoRequest request) {
|
||||
return Futures.immediateFailedFuture(new NotFound());
|
||||
|
|
|
@ -19,11 +19,11 @@ public interface UserService extends ModelService<User, UserDoc.Partial> {
|
|||
|
||||
ListenableFuture<?> logout(LogoutRequest request);
|
||||
|
||||
default ListenableFuture<UserUpdateResponse> creditRaindrops(UserId userId, int raindrops) {
|
||||
return creditRaindrops(userId, () -> raindrops);
|
||||
}
|
||||
ListenableFuture<UserUpdateResponse> creditTokens(UserId userId, CreditTokensRequest request);
|
||||
|
||||
ListenableFuture<UserUpdateResponse> creditRaindrops(UserId userId, CreditRaindropsRequest request);
|
||||
ListenableFuture<User> changeGroup(UserId userId, ChangeGroupRequest request);
|
||||
|
||||
ListenableFuture<FriendJoinResponse> joinFriend(UserId userId, FriendJoinRequest request);
|
||||
|
||||
ListenableFuture<User> purchaseGizmo(UserId userId, PurchaseGizmoRequest request);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<groupId>tc.oc</groupId>
|
||||
<artifactId>api-parent</artifactId>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
<version>1.11-SNAPSHOT</version>
|
||||
<version>1.12-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>api-bukkit</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<groupId>tc.oc</groupId>
|
||||
<artifactId>api-parent</artifactId>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
<version>1.11-SNAPSHOT</version>
|
||||
<version>1.12-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>api-bungee</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<groupId>tc.oc</groupId>
|
||||
<artifactId>api-parent</artifactId>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
<version>1.11-SNAPSHOT</version>
|
||||
<version>1.12-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>api-minecraft</artifactId>
|
||||
|
|
|
@ -12,4 +12,6 @@ public interface MinecraftApiConfiguration extends ApiConfiguration {
|
|||
String box();
|
||||
|
||||
ServerDoc.Role role();
|
||||
|
||||
boolean publishIp();
|
||||
}
|
||||
|
|
|
@ -37,6 +37,11 @@ public class MinecraftApiConfigurationImpl implements MinecraftApiConfiguration
|
|||
return ServerDoc.Role.valueOf(config.getString("server.role").toUpperCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean publishIp() {
|
||||
return config.getBoolean("server.publishIp", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String primaryQueueName() {
|
||||
return "server." + serverId();
|
||||
|
|
|
@ -23,7 +23,7 @@ import tc.oc.commons.core.commands.NestedCommands;
|
|||
import tc.oc.commons.core.formatting.StringUtils;
|
||||
import tc.oc.minecraft.api.command.CommandSender;
|
||||
|
||||
class ModelCommands implements NestedCommands {
|
||||
public class ModelCommands implements NestedCommands {
|
||||
|
||||
public static class Parent implements Commands {
|
||||
@Command(
|
||||
|
|
|
@ -279,7 +279,12 @@ public class LocalServerDocument extends StartupServerDocument implements Server
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<MatchDoc.Mutation> queued_mutations() {
|
||||
public Set<String> queued_mutations() {
|
||||
return mutations != null ? mutations.queued_mutations() : Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServerDoc.Rotation> rotations() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
package tc.oc.api.minecraft.servers;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
@ -15,6 +20,7 @@ import com.google.common.io.Files;
|
|||
import com.google.gson.Gson;
|
||||
import tc.oc.api.docs.virtual.DeployInfo;
|
||||
import tc.oc.api.docs.virtual.ServerDoc;
|
||||
import tc.oc.api.minecraft.config.MinecraftApiConfiguration;
|
||||
import tc.oc.commons.core.logging.Loggers;
|
||||
import tc.oc.commons.core.util.Lazy;
|
||||
import tc.oc.minecraft.api.plugin.PluginFinder;
|
||||
|
@ -26,6 +32,7 @@ public class StartupServerDocument implements ServerDoc.Startup {
|
|||
@Inject private Gson gson;
|
||||
@Inject private LocalServer minecraftServer;
|
||||
@Inject private PluginFinder pluginFinder;
|
||||
@Inject private MinecraftApiConfiguration configuration;
|
||||
|
||||
private Logger logger;
|
||||
@Inject void init(Loggers loggers) {
|
||||
|
@ -51,10 +58,25 @@ public class StartupServerDocument implements ServerDoc.Startup {
|
|||
}
|
||||
});
|
||||
|
||||
private final Lazy<String> ip = Lazy.from(() -> {
|
||||
try {
|
||||
URL url = new URL("http://checkip.amazonaws.com");
|
||||
return new BufferedReader(new InputStreamReader(url.openStream())).readLine();
|
||||
} catch(IOException e) {
|
||||
logger.log(Level.SEVERE, "Unable to find external ip", e);
|
||||
return minecraftServer.getAddress().getHostName();
|
||||
}
|
||||
});
|
||||
|
||||
@Override public boolean online() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String ip() {
|
||||
return configuration.publishIp() ? ip.get() : null;
|
||||
}
|
||||
|
||||
@Override public Integer current_port() {
|
||||
return minecraftServer.getAddress().getPort();
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import tc.oc.api.docs.Session;
|
|||
import tc.oc.api.docs.UserId;
|
||||
import tc.oc.api.minecraft.users.UserStore;
|
||||
import tc.oc.minecraft.api.entity.Player;
|
||||
import tc.oc.minecraft.protocol.MinecraftVersion;
|
||||
|
||||
@Singleton
|
||||
public class LocalSessionFactory {
|
||||
|
@ -41,6 +42,13 @@ public class LocalSessionFactory {
|
|||
return localServer._id();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String version() {
|
||||
return userStore.byUserId(userId)
|
||||
.map(player -> MinecraftVersion.describeProtocol(player.getProtocolVersion()))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerId user() {
|
||||
return playerId;
|
||||
|
|
|
@ -40,6 +40,11 @@ public class LocalUserDocument extends SimplePlayerId implements User {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant nickname_updated_at() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String mc_locale() {
|
||||
return null;
|
||||
|
@ -80,6 +85,16 @@ public class LocalUserDocument extends SimplePlayerId implements User {
|
|||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int maptokens() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int mutationtokens() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mc_last_sign_in_ip() {
|
||||
return ip;
|
||||
|
@ -90,6 +105,11 @@ public class LocalUserDocument extends SimplePlayerId implements User {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Map<String, Map<String, Object>>> stats_value() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Map<String, Boolean>> mc_permissions_by_realm() {
|
||||
return ImmutableMap.of(
|
||||
|
@ -121,4 +141,24 @@ public class LocalUserDocument extends SimplePlayerId implements User {
|
|||
public int enemy_kills() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String default_server_id() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int friend_tokens_limit() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int friend_tokens_concurrent() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String death_screen() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,17 +18,7 @@ import tc.oc.api.docs.virtual.UserDoc;
|
|||
import tc.oc.api.exceptions.NotFound;
|
||||
import tc.oc.api.minecraft.sessions.LocalSessionFactory;
|
||||
import tc.oc.api.model.NullModelService;
|
||||
import tc.oc.api.users.ChangeClassRequest;
|
||||
import tc.oc.api.users.ChangeSettingRequest;
|
||||
import tc.oc.api.users.CreditRaindropsRequest;
|
||||
import tc.oc.api.users.LoginRequest;
|
||||
import tc.oc.api.users.LoginResponse;
|
||||
import tc.oc.api.users.LogoutRequest;
|
||||
import tc.oc.api.users.PurchaseGizmoRequest;
|
||||
import tc.oc.api.users.UserSearchRequest;
|
||||
import tc.oc.api.users.UserSearchResponse;
|
||||
import tc.oc.api.users.UserService;
|
||||
import tc.oc.api.users.UserUpdateResponse;
|
||||
import tc.oc.api.users.*;
|
||||
import tc.oc.commons.core.concurrent.FutureUtils;
|
||||
import tc.oc.minecraft.api.user.UserFinder;
|
||||
|
||||
|
@ -118,8 +108,7 @@ class LocalUserService extends NullModelService<User, UserDoc.Partial> implement
|
|||
return Futures.immediateFuture(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<UserUpdateResponse> creditRaindrops(UserId userId, CreditRaindropsRequest request) {
|
||||
private ListenableFuture<UserUpdateResponse> update(UserId userId) {
|
||||
return FutureUtils.mapSync(find(userId), user -> new UserUpdateResponse() {
|
||||
@Override
|
||||
public boolean success() {
|
||||
|
@ -133,6 +122,31 @@ class LocalUserService extends NullModelService<User, UserDoc.Partial> implement
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<UserUpdateResponse> creditTokens(UserId userId, CreditTokensRequest request) {
|
||||
return update(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<User> changeGroup(UserId userId, ChangeGroupRequest request) {
|
||||
return find(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<FriendJoinResponse> joinFriend(UserId userId, FriendJoinRequest request) {
|
||||
return Futures.immediateFuture(new FriendJoinResponse() {
|
||||
@Override
|
||||
public boolean authorized() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String message() {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<User> purchaseGizmo(UserId userId, PurchaseGizmoRequest request) {
|
||||
return find(userId);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<groupId>tc.oc</groupId>
|
||||
<artifactId>api-parent</artifactId>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
<version>1.11-SNAPSHOT</version>
|
||||
<version>1.12-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>api-ocn</artifactId>
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package tc.oc.api.ocn;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import tc.oc.api.docs.Friendship;
|
||||
import tc.oc.api.docs.virtual.FriendshipDoc;
|
||||
import tc.oc.api.friendships.FriendshipRequest;
|
||||
import tc.oc.api.friendships.FriendshipResponse;
|
||||
import tc.oc.api.friendships.FriendshipService;
|
||||
import tc.oc.api.http.HttpOption;
|
||||
import tc.oc.api.model.HttpModelService;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
class OCNFriendshipService extends HttpModelService<Friendship, FriendshipDoc.Partial> implements FriendshipService {
|
||||
|
||||
@Override
|
||||
public ListenableFuture<FriendshipResponse> create(FriendshipRequest request) {
|
||||
return this.client().post(collectionUri("create"), request, FriendshipResponse.class, HttpOption.INFINITE_RETRY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<FriendshipResponse> destroy(FriendshipRequest request) {
|
||||
return this.client().post(collectionUri("destroy"), request, FriendshipResponse.class, HttpOption.INFINITE_RETRY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<FriendshipResponse> list(FriendshipRequest request) {
|
||||
return this.client().post(collectionUri("list"), request, FriendshipResponse.class, HttpOption.INFINITE_RETRY);
|
||||
}
|
||||
|
||||
}
|
|
@ -13,6 +13,7 @@ import tc.oc.api.docs.virtual.MatchDoc;
|
|||
import tc.oc.api.docs.virtual.PunishmentDoc;
|
||||
import tc.oc.api.docs.virtual.ReportDoc;
|
||||
import tc.oc.api.engagement.EngagementService;
|
||||
import tc.oc.api.friendships.FriendshipService;
|
||||
import tc.oc.api.games.TicketService;
|
||||
import tc.oc.api.maps.MapService;
|
||||
import tc.oc.api.model.ModelBinders;
|
||||
|
@ -58,7 +59,6 @@ public class OCNModelsManifest extends HybridManifest implements ModelBinders {
|
|||
bindModel(Objective.class, model -> {
|
||||
model.bindService().to(model.httpService());
|
||||
});
|
||||
|
||||
publicBinder().install(new Manifest() {
|
||||
@Override protected void configure() {
|
||||
// Specialized AMQP services
|
||||
|
@ -72,6 +72,7 @@ public class OCNModelsManifest extends HybridManifest implements ModelBinders {
|
|||
forOptional(TournamentService.class).setBinding().to(OCNTournamentService.class);
|
||||
forOptional(UserService.class).setBinding().to(OCNUserService.class);
|
||||
forOptional(WhisperService.class).setBinding().to(OCNWhisperService.class);
|
||||
forOptional(FriendshipService.class).setBinding().to(OCNFriendshipService.class);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -15,17 +15,7 @@ import tc.oc.api.message.types.PlayerTeleportRequest;
|
|||
import tc.oc.api.minecraft.users.UserStore;
|
||||
import tc.oc.api.model.HttpModelService;
|
||||
import tc.oc.api.queue.Exchange;
|
||||
import tc.oc.api.users.ChangeClassRequest;
|
||||
import tc.oc.api.users.ChangeSettingRequest;
|
||||
import tc.oc.api.users.CreditRaindropsRequest;
|
||||
import tc.oc.api.users.LoginRequest;
|
||||
import tc.oc.api.users.LoginResponse;
|
||||
import tc.oc.api.users.LogoutRequest;
|
||||
import tc.oc.api.users.PurchaseGizmoRequest;
|
||||
import tc.oc.api.users.UserSearchRequest;
|
||||
import tc.oc.api.users.UserSearchResponse;
|
||||
import tc.oc.api.users.UserService;
|
||||
import tc.oc.api.users.UserUpdateResponse;
|
||||
import tc.oc.api.users.*;
|
||||
import tc.oc.commons.core.concurrent.FutureUtils;
|
||||
import tc.oc.minecraft.api.entity.Player;
|
||||
|
||||
|
@ -82,13 +72,23 @@ class OCNUserService extends HttpModelService<User, UserDoc.Partial> implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<UserUpdateResponse> creditRaindrops(UserId userId, CreditRaindropsRequest request) {
|
||||
return handleUserUpdate(client().post(memberUri(userId, "credit_raindrops"), request, UserUpdateResponse.class, HttpOption.INFINITE_RETRY));
|
||||
public ListenableFuture<User> purchaseGizmo(UserId userId, PurchaseGizmoRequest request) {
|
||||
return handleUpdate(client().post(memberUri(userId, "purchase_gizmo"), request, User.class, HttpOption.INFINITE_RETRY));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<User> purchaseGizmo(UserId userId, PurchaseGizmoRequest request) {
|
||||
return handleUpdate(client().post(memberUri(userId, "purchase_gizmo"), request, User.class, HttpOption.INFINITE_RETRY));
|
||||
public ListenableFuture<UserUpdateResponse> creditTokens(UserId userId, CreditTokensRequest request) {
|
||||
return handleUserUpdate(client().post(memberUri(userId, "credit_tokens"), request, UserUpdateResponse.class, HttpOption.INFINITE_RETRY));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<User> changeGroup(UserId userId, ChangeGroupRequest request) {
|
||||
return handleUpdate(client().post(memberUri(userId, "change_group"), request, User.class, HttpOption.INFINITE_RETRY));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<FriendJoinResponse> joinFriend(UserId userId, FriendJoinRequest request) {
|
||||
return client().post(memberUri(userId, "join_friend"), request, FriendJoinResponse.class, HttpOption.INFINITE_RETRY);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<groupId>tc.oc</groupId>
|
||||
<artifactId>ProjectAres</artifactId>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
<version>1.11-SNAPSHOT</version>
|
||||
<version>1.12-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>api-parent</artifactId>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<artifactId>commons</artifactId>
|
||||
<groupId>tc.oc</groupId>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
<version>1.11-SNAPSHOT</version>
|
||||
<version>1.12-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>commons-bukkit</artifactId>
|
||||
|
|
|
@ -24,15 +24,10 @@ import tc.oc.commons.bukkit.chat.TextComponentRenderer;
|
|||
import tc.oc.commons.bukkit.chat.TranslatableComponentRenderer;
|
||||
import tc.oc.commons.bukkit.chat.UserTextComponent;
|
||||
import tc.oc.commons.bukkit.chat.UserTextComponentRenderer;
|
||||
import tc.oc.commons.bukkit.commands.PermissionCommands;
|
||||
import tc.oc.commons.bukkit.commands.ServerCommands;
|
||||
import tc.oc.commons.bukkit.commands.ServerVisibilityCommands;
|
||||
import tc.oc.commons.bukkit.commands.SkinCommands;
|
||||
import tc.oc.commons.bukkit.commands.TraceCommands;
|
||||
import tc.oc.commons.bukkit.commands.UserCommands;
|
||||
import tc.oc.commons.bukkit.commands.UserFinder;
|
||||
import tc.oc.commons.bukkit.commands.*;
|
||||
import tc.oc.commons.bukkit.debug.LeakListener;
|
||||
import tc.oc.commons.bukkit.event.targeted.TargetedEventManifest;
|
||||
import tc.oc.commons.bukkit.flairs.FlairConfiguration;
|
||||
import tc.oc.commons.bukkit.format.ServerFormatter;
|
||||
import tc.oc.commons.bukkit.freeze.PlayerFreezer;
|
||||
import tc.oc.commons.bukkit.inject.BukkitPluginManifest;
|
||||
|
@ -68,9 +63,13 @@ import tc.oc.commons.bukkit.respack.ResourcePackManager;
|
|||
import tc.oc.commons.bukkit.restart.RestartCommands;
|
||||
import tc.oc.commons.bukkit.sessions.SessionListener;
|
||||
import tc.oc.commons.bukkit.settings.SettingManifest;
|
||||
import tc.oc.commons.bukkit.stats.StatsCommands;
|
||||
import tc.oc.commons.bukkit.stats.StatsManifest;
|
||||
import tc.oc.commons.bukkit.suspend.SuspendListener;
|
||||
import tc.oc.commons.bukkit.tablist.PlayerTabEntry;
|
||||
import tc.oc.commons.bukkit.tablist.TabRender;
|
||||
import tc.oc.commons.bukkit.teleport.Navigator;
|
||||
import tc.oc.commons.bukkit.teleport.NavigatorInterface;
|
||||
import tc.oc.commons.bukkit.teleport.NavigatorManifest;
|
||||
import tc.oc.commons.bukkit.teleport.PlayerServerChanger;
|
||||
import tc.oc.commons.bukkit.teleport.TeleportCommands;
|
||||
|
@ -80,6 +79,7 @@ import tc.oc.commons.bukkit.ticket.TicketBooth;
|
|||
import tc.oc.commons.bukkit.ticket.TicketCommands;
|
||||
import tc.oc.commons.bukkit.ticket.TicketDisplay;
|
||||
import tc.oc.commons.bukkit.ticket.TicketListener;
|
||||
import tc.oc.commons.bukkit.tokens.TokenManifest;
|
||||
import tc.oc.commons.bukkit.trophies.TrophyCase;
|
||||
import tc.oc.commons.bukkit.trophies.TrophyCommands;
|
||||
import tc.oc.commons.bukkit.users.JoinMessageManifest;
|
||||
|
@ -110,6 +110,8 @@ public final class CommonsBukkitManifest extends HybridManifest {
|
|||
install(new LocalizationManifest());
|
||||
install(new NavigatorManifest());
|
||||
install(new RaindropManifest());
|
||||
install(new TokenManifest());
|
||||
install(new StatsManifest());
|
||||
install(new PunishmentManifest());
|
||||
|
||||
// These are already bound as facets, so they only need to be exposed
|
||||
|
@ -119,6 +121,7 @@ public final class CommonsBukkitManifest extends HybridManifest {
|
|||
expose(TicketDisplay.class);
|
||||
expose(TicketListener.class);
|
||||
|
||||
bindAndExpose(FlairConfiguration.class);
|
||||
bindAndExpose(PlayerAppearanceChanger.class);
|
||||
bindAndExpose(UserFinder.class);
|
||||
bindAndExpose(Teleporter.class);
|
||||
|
@ -155,6 +158,9 @@ public final class CommonsBukkitManifest extends HybridManifest {
|
|||
facets.register(LeakListener.class);
|
||||
facets.register(LocaleListener.class);
|
||||
facets.register(LoginListener.class);
|
||||
facets.register(MiscCommands.class);
|
||||
facets.register(Navigator.class);
|
||||
facets.register(NavigatorInterface.class);
|
||||
facets.register(NicknameCommands.class);
|
||||
facets.register(PermissionCommands.class);
|
||||
facets.register(PermissionCommands.Parent.class);
|
||||
|
@ -189,6 +195,7 @@ public final class CommonsBukkitManifest extends HybridManifest {
|
|||
facets.register(WindowManager.class);
|
||||
facets.register(AppealAlertListener.class);
|
||||
facets.register(SuspendListener.class);
|
||||
facets.register(GroupCommands.Parent.class);
|
||||
|
||||
// DataDog
|
||||
facets.register(TickReporter.class);
|
||||
|
|
|
@ -5,10 +5,12 @@ import javax.inject.Inject;
|
|||
import me.anxuiz.settings.Setting;
|
||||
import me.anxuiz.settings.SettingBuilder;
|
||||
import me.anxuiz.settings.types.BooleanType;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import tc.oc.commons.bukkit.broadcast.model.BroadcastPrefix;
|
||||
import tc.oc.commons.bukkit.settings.SettingManagerProvider;
|
||||
import tc.oc.commons.bukkit.util.ItemCreator;
|
||||
|
||||
public class BroadcastSettings {
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ 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;
|
||||
|
@ -27,6 +28,7 @@ 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
|
||||
|
|
|
@ -3,6 +3,7 @@ package tc.oc.commons.bukkit.chat;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import tc.oc.commons.bukkit.flairs.FlairRenderer;
|
||||
import tc.oc.commons.bukkit.nick.Identity;
|
||||
import tc.oc.commons.bukkit.nick.UsernameRenderer;
|
||||
import tc.oc.commons.core.chat.Component;
|
||||
|
|
|
@ -13,12 +13,17 @@ import tc.oc.commons.core.util.ExceptionUtils;
|
|||
public class Links {
|
||||
private Links() {}
|
||||
|
||||
public static final String HOST = "localhost"; // TODO: configurable
|
||||
public static final String HOST = "stratus.network";
|
||||
public static final String SHOP_HOST = "stratusnetwork.buycraft.net";
|
||||
|
||||
public static URI homeUri(String path) throws URISyntaxException {
|
||||
return new URI("http", HOST, path, null);
|
||||
}
|
||||
|
||||
public static URI shopUri() throws URISyntaxException {
|
||||
return new URI("http", SHOP_HOST, null, null);
|
||||
}
|
||||
|
||||
public static URI homeUriSafe(String path) {
|
||||
return ExceptionUtils.propagate(() -> homeUri(path));
|
||||
}
|
||||
|
@ -39,8 +44,12 @@ public class Links {
|
|||
return homeLinkSafe("/");
|
||||
}
|
||||
|
||||
public static BaseComponent shopLink(boolean compact) throws URISyntaxException {
|
||||
return new LinkComponent(shopUri(), compact);
|
||||
}
|
||||
|
||||
public static BaseComponent shopLink() {
|
||||
return homeLinkSafe("/shop");
|
||||
return ExceptionUtils.propagate(() -> shopLink(true));
|
||||
}
|
||||
|
||||
public static BaseComponent appealLink() {
|
||||
|
|
|
@ -124,14 +124,14 @@ public abstract class CommandUtils {
|
|||
}
|
||||
|
||||
public static Duration getDuration(CommandContext args, int index, Duration def) throws CommandException {
|
||||
return args.argsLength() > index ? getDuration(args.getString(index), null) : def;
|
||||
return getDuration(args.getString(index, null), def);
|
||||
}
|
||||
|
||||
public static @Nullable Duration getDuration(@Nullable String text) throws CommandException {
|
||||
public static @Nullable Duration getDuration(String text) throws CommandException {
|
||||
return getDuration(text, null);
|
||||
}
|
||||
|
||||
public static Duration getDuration(@Nullable String text, Duration def) throws CommandException {
|
||||
public static Duration getDuration(String text, Duration def) throws CommandException {
|
||||
if(text == null) {
|
||||
return def;
|
||||
} else {
|
||||
|
@ -143,6 +143,26 @@ public abstract class CommandUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static @Nullable <E extends Enum<E>> E getEnum(CommandContext args, CommandSender sender, int index, Class<E> type) throws CommandException {
|
||||
return getEnum(args, sender, index, type, null);
|
||||
}
|
||||
|
||||
public static <E extends Enum<E>> E getEnum(CommandContext args, CommandSender sender, int index, Class<E> type, E def) throws CommandException {
|
||||
return getEnum(args.getString(index, null), sender, type, def);
|
||||
}
|
||||
|
||||
public static <E extends Enum<E>> E getEnum(String text, CommandSender sender, Class<E> type, E def) throws CommandException {
|
||||
if(text == null) {
|
||||
return def;
|
||||
} else {
|
||||
try {
|
||||
return Enum.valueOf(type, text.toUpperCase().replace(' ', '_'));
|
||||
} catch(IllegalArgumentException e) {
|
||||
throw newCommandException(sender, new TranslatableComponent("command.error.invalidEnum", text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String getDisplayName(CommandSender target) {
|
||||
return getDisplayName(target, null);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
package tc.oc.commons.bukkit.commands;
|
||||
|
||||
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.NestedCommand;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import tc.oc.api.bukkit.users.BukkitUserStore;
|
||||
import tc.oc.api.docs.User;
|
||||
import tc.oc.api.users.ChangeGroupRequest;
|
||||
import tc.oc.api.users.UserService;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.core.commands.Commands;
|
||||
import tc.oc.commons.core.commands.NestedCommands;
|
||||
import tc.oc.commons.core.concurrent.Flexecutor;
|
||||
import tc.oc.commons.core.util.ThrowingBiConsumer;
|
||||
import tc.oc.minecraft.scheduler.Sync;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.time.Instant;
|
||||
|
||||
public class GroupCommands implements NestedCommands {
|
||||
|
||||
public static class Parent implements Commands {
|
||||
@Command(
|
||||
aliases = { "group" },
|
||||
desc = "Commands to edit group membership",
|
||||
min = 1,
|
||||
max = -1
|
||||
)
|
||||
@NestedCommand(value = {GroupCommands.class})
|
||||
public void commands() throws CommandPermissionsException {}
|
||||
}
|
||||
|
||||
private final Flexecutor flexecutor;
|
||||
private final BukkitUserStore userStore;
|
||||
private final UserService userService;
|
||||
private final UserFinder userFinder;
|
||||
private final Audiences audiences;
|
||||
|
||||
@Inject GroupCommands(@Sync Flexecutor flexecutor, BukkitUserStore userStore, UserService userService, UserFinder userFinder, Audiences audiences) {
|
||||
this.flexecutor = flexecutor;
|
||||
this.userStore = userStore;
|
||||
this.userService = userService;
|
||||
this.userFinder = userFinder;
|
||||
this.audiences = audiences;
|
||||
}
|
||||
|
||||
public void edit(final CommandContext args, final CommandSender sender, boolean add, boolean expire, ThrowingBiConsumer<User, String, Exception> consumer) throws CommandException {
|
||||
if(!(sender instanceof ConsoleCommandSender)) throw new CommandPermissionsException();
|
||||
flexecutor.callback(
|
||||
userFinder.findUser(sender, args, 0),
|
||||
response -> {
|
||||
String group = args.getString(1);
|
||||
flexecutor.callback(
|
||||
userService.changeGroup(response.user, new ChangeGroupRequest() {
|
||||
public String group() {
|
||||
return group;
|
||||
}
|
||||
public String type() {
|
||||
return add ? "join" : (expire ? "expire" : "leave");
|
||||
}
|
||||
public Instant end() {
|
||||
try {
|
||||
return add ? Instant.now().plus(CommandUtils.getDuration(args, 2, null)) : null;
|
||||
} catch(CommandException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}),
|
||||
user -> consumer.acceptThrows(user, group)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "join" },
|
||||
desc = "Add a player to a group",
|
||||
usage = "<player> <group> [duration]",
|
||||
min = 2,
|
||||
max = 3
|
||||
)
|
||||
public void join(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
edit(args, sender, true, false, (User user, String group) -> {
|
||||
sender.sendMessage("Added " + user.username() + " to the " + group + " group");
|
||||
});
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "leave" },
|
||||
desc = "Remove a player to a group",
|
||||
usage = "<player> <group>",
|
||||
min = 2,
|
||||
max = 2
|
||||
)
|
||||
public void leave(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
edit(args, sender, false, false, (User user, String group) -> {
|
||||
sender.sendMessage("Removed " + user.username() + " from the " + group + " group");
|
||||
});
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "expire" },
|
||||
desc = "Expire a player's membership to a group",
|
||||
usage = "<player> <group>",
|
||||
min = 2,
|
||||
max = 2
|
||||
)
|
||||
public void expire(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
edit(args, sender, false, true, (User user, String group) -> {
|
||||
sender.sendMessage("Expired " + user.username() + "'s membership from the " + group + " group");
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
package tc.oc.commons.bukkit.commands;
|
||||
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
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 net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import tc.oc.api.bukkit.users.BukkitUserStore;
|
||||
import tc.oc.api.docs.User;
|
||||
import tc.oc.api.docs.virtual.UserDoc;
|
||||
import tc.oc.api.users.UserService;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.chat.HeaderComponent;
|
||||
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.commands.Commands;
|
||||
import tc.oc.commons.core.concurrent.Flexecutor;
|
||||
import tc.oc.commons.core.stream.Collectors;
|
||||
import tc.oc.commons.core.util.Streams;
|
||||
import tc.oc.minecraft.protocol.MinecraftVersion;
|
||||
import tc.oc.minecraft.scheduler.Sync;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Commands for miscellaneous purposes.
|
||||
*/
|
||||
public class MiscCommands implements Commands {
|
||||
|
||||
private final Flexecutor flexecutor;
|
||||
private final UserService userService;
|
||||
private final BukkitUserStore userStore;
|
||||
private final UserFinder userFinder;
|
||||
private final IdentityProvider identityProvider;
|
||||
private final Audiences audiences;
|
||||
|
||||
@Inject MiscCommands(@Sync Flexecutor flexecutor, UserService userService, BukkitUserStore userStore, UserFinder userFinder, IdentityProvider identityProvider, Audiences audiences) {
|
||||
this.flexecutor = flexecutor;
|
||||
this.userService = userService;
|
||||
this.userStore = userStore;
|
||||
this.userFinder = userFinder;
|
||||
this.identityProvider = identityProvider;
|
||||
this.audiences = audiences;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "playerversion", "pv" },
|
||||
desc = "Shows statics on what version players online are using",
|
||||
flags = "ad",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("ocn.developer")
|
||||
public void listPlayerVersions(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
Audience audience = audiences.get(sender);
|
||||
if (args.hasFlag('a')) {
|
||||
Map<String, Integer> playerCountVersionMap = new HashMap<>();
|
||||
userStore.stream().forEach(player -> {
|
||||
String version = MinecraftVersion.describeProtocol(player.getProtocolVersion(), !args.hasFlag('d'));
|
||||
playerCountVersionMap.put(version, playerCountVersionMap.getOrDefault(version, 0) + 1);
|
||||
});
|
||||
|
||||
audience.sendMessage(new HeaderComponent(new Component(ChatColor.AQUA).translate("list.player.versions.title")));
|
||||
for (Map.Entry<String, Integer> entry : playerCountVersionMap.entrySet()) {
|
||||
audience.sendMessage(new TranslatableComponent("list.player.versions.message." + (entry.getValue() == 1 ? "singular" : "plural"),
|
||||
ChatColor.AQUA + entry.getValue().toString(),
|
||||
ChatColor.AQUA + entry.getKey(),
|
||||
String.format("%.1f", 100 * entry.getValue() / (double) userStore.count()) + "%"));
|
||||
}
|
||||
} else {
|
||||
Player player = CommandUtils.getPlayerOrSelf(args, sender, 0);
|
||||
audience.sendMessage(new TranslatableComponent("list.player.version.singular.message", new PlayerComponent(identityProvider.createIdentity(player)), ChatColor.AQUA + MinecraftVersion.describeProtocol(player.getProtocolVersion(), false)));
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "coinflip" },
|
||||
desc = "Flip a Coin",
|
||||
flags = "b",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("coinflip")
|
||||
public void coinFlip(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
if (args.hasFlag('b')) {
|
||||
Bukkit.broadcastMessage(ChatColor.AQUA + (Math.random() < 0.5 ? "Heads" : "Tails"));
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.AQUA + (Math.random() < 0.5 ? "Heads" : "Tails"));
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "togglegravity" },
|
||||
usage = "<player>",
|
||||
desc = "Toggle a player's gravity.",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("togglegravity")
|
||||
public void noGravity(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
Player player = CommandUtils.getPlayerOrSelf(args, sender, 0);
|
||||
player.setGravity(!player.hasGravity());
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "join-friend-tokens" },
|
||||
usage = "<player> <concurrent> <limit>",
|
||||
desc = "Change the join friend tokens limit for a premium player",
|
||||
min = 3
|
||||
)
|
||||
public void joinFriend(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
if(!(sender instanceof ConsoleCommandSender)) throw new CommandPermissionsException();
|
||||
int concurrent = args.getInteger(1, 1);
|
||||
int limit = args.getInteger(2, 3);
|
||||
flexecutor.callback(
|
||||
userFinder.findLocalPlayer(sender, args, 0),
|
||||
response -> {
|
||||
userService.update(response.user, new UserDoc.FriendTokens() {
|
||||
@Override
|
||||
public int friend_tokens_limit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int friend_tokens_concurrent() {
|
||||
return concurrent;
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "sudo" },
|
||||
usage = "<player> [command... (rand|mode|near|color|*)=value]",
|
||||
desc = "Run a command as console or another player",
|
||||
flags = "cd",
|
||||
anyFlags = true,
|
||||
min = 1,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions("sudo")
|
||||
public void sudo(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
Server server = sender.getServer();
|
||||
int index = 1;
|
||||
CommandSender other = userStore.find(args.getString(0, ""));
|
||||
if(other == null) {
|
||||
other = args.hasFlag('c') ? server.getConsoleSender() : sender;
|
||||
index = 0;
|
||||
}
|
||||
if(!sender.equals(other) && !sender.hasPermission("sudo.others")) {
|
||||
throw new CommandPermissionsException();
|
||||
}
|
||||
String command = args.getRemainingString(index);
|
||||
List<String> commands = getPermutations(sender, command);
|
||||
String explanation;
|
||||
if(commands.size() == 1) {
|
||||
explanation = "/" + commands.get(0);
|
||||
} else {
|
||||
explanation = commands.size() + ChatColor.WHITE.toString() + " commands";
|
||||
}
|
||||
sender.sendMessage("Executing " + ChatColor.AQUA + explanation + ChatColor.WHITE + " as " + identityProvider.currentIdentity(other).getName(sender));
|
||||
for(String cmd : commands) {
|
||||
if(commands.size() > 1 && args.hasFlag('d')) {
|
||||
sender.sendMessage(" > " + cmd);
|
||||
}
|
||||
server.dispatchCommand(other, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getPermutations(CommandSender sender, String command) throws CommandException {
|
||||
List<String> permutations = new ArrayList<>();
|
||||
getPermutations(sender, command, permutations);
|
||||
return permutations;
|
||||
}
|
||||
|
||||
public void getPermutations(CommandSender sender, String command, List<String> commands) throws CommandException {
|
||||
Matcher matcher = Pattern.compile("\\*|[A-Za-z]{1,}=[A-Za-z0-9_-]{1,}").matcher(command);
|
||||
if(matcher.find()) {
|
||||
String keyValue = matcher.group();
|
||||
for(String name : getPlayers(sender, keyValue).map(player -> player.getName(sender)).collect(Collectors.toImmutableList())) {
|
||||
getPermutations(sender, matcher.replaceFirst(name), commands);
|
||||
}
|
||||
} else {
|
||||
commands.add(command);
|
||||
}
|
||||
}
|
||||
|
||||
public Stream<Player> getPlayers(CommandSender sender, String keyValue) throws CommandException {
|
||||
Stream<Player> players = userStore.stream();
|
||||
int seperator = keyValue.indexOf("=");
|
||||
String key = seperator != -1 ? keyValue.substring(0, seperator) : keyValue;
|
||||
String value = seperator != -1 ? keyValue.substring(seperator + 1, keyValue.length()) : "";
|
||||
int parsed;
|
||||
try {
|
||||
parsed = Integer.parseInt(value);
|
||||
} catch(NumberFormatException nfe) {
|
||||
parsed = -1;
|
||||
}
|
||||
int valueInt = parsed;
|
||||
switch(key) {
|
||||
case "rand":
|
||||
return players.collect(Collectors.toRandomSubList(valueInt)).stream();
|
||||
case "mode":
|
||||
return players.filter(p -> p.getGameMode().getValue() == valueInt);
|
||||
case "near":
|
||||
Location location = CommandUtils.senderToPlayer(sender).getLocation();
|
||||
return players.filter(p -> p.getLocation().distance(location) <= valueInt);
|
||||
case "color":
|
||||
ChatColor color = CommandUtils.getEnum(value, sender, ChatColor.class, ChatColor.WHITE);
|
||||
return players.filter(p -> getFuzzyColor(p).equals(color));
|
||||
case "*":
|
||||
return Streams.shuffle(players);
|
||||
default:
|
||||
throw new CommandException("Unrecognized player filter '" + key + "'");
|
||||
}
|
||||
}
|
||||
|
||||
public ChatColor getFuzzyColor(CommandSender sender) {
|
||||
if(sender instanceof Player) {
|
||||
Player player = (Player) sender;
|
||||
Matcher matcher = ChatColor.STRIP_COLOR_PATTERN.matcher(player.getDisplayName(sender));
|
||||
String color = null;
|
||||
while(matcher.find()) {
|
||||
color = matcher.group();
|
||||
}
|
||||
if(color != null) {
|
||||
return ChatColor.getByChar(color.charAt(1));
|
||||
}
|
||||
}
|
||||
return ChatColor.WHITE;
|
||||
}
|
||||
|
||||
}
|
|
@ -5,19 +5,26 @@ import java.util.Collections;
|
|||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import javax.inject.Inject;
|
||||
|
||||
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 net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import tc.oc.api.bukkit.users.BukkitUserStore;
|
||||
import tc.oc.api.docs.Server;
|
||||
import tc.oc.api.docs.User;
|
||||
import tc.oc.api.docs.virtual.ServerDoc;
|
||||
import tc.oc.api.docs.virtual.UserDoc;
|
||||
import tc.oc.api.servers.ServerStore;
|
||||
import tc.oc.api.users.UserService;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.chat.Paginator;
|
||||
import tc.oc.commons.bukkit.chat.WarningComponent;
|
||||
|
@ -27,22 +34,31 @@ 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.commands.TranslatableCommandException;
|
||||
import tc.oc.commons.core.concurrent.Flexecutor;
|
||||
import tc.oc.commons.core.formatting.StringUtils;
|
||||
import tc.oc.commons.core.util.Pair;
|
||||
import tc.oc.minecraft.scheduler.Sync;
|
||||
|
||||
public class ServerCommands implements Commands {
|
||||
|
||||
private final Flexecutor flexecutor;
|
||||
private final Server localServer;
|
||||
private final ServerStore serverStore;
|
||||
private final ServerFormatter formatter = ServerFormatter.light;
|
||||
private final Teleporter teleporter;
|
||||
private final BukkitUserStore userStore;
|
||||
private final UserService userService;
|
||||
private final Audiences audiences;
|
||||
|
||||
private static final Comparator<Server> FULLNESS = Comparator.comparing(Server::num_online).reversed();
|
||||
|
||||
@Inject ServerCommands(Server localServer, ServerStore serverStore, Teleporter teleporter, Audiences audiences) {
|
||||
@Inject ServerCommands(@Sync Flexecutor flexecutor, Server localServer, ServerStore serverStore, Teleporter teleporter, BukkitUserStore userStore, UserService userService, Audiences audiences) {
|
||||
this.flexecutor = flexecutor;
|
||||
this.localServer = localServer;
|
||||
this.serverStore = serverStore;
|
||||
this.teleporter = teleporter;
|
||||
this.userStore = userStore;
|
||||
this.userService = userService;
|
||||
this.audiences = audiences;
|
||||
}
|
||||
|
||||
|
@ -90,16 +106,86 @@ public class ServerCommands implements Commands {
|
|||
flags = "bd:"
|
||||
)
|
||||
public List<String> server(CommandContext args, final CommandSender sender) throws CommandException {
|
||||
Pair<Server, List<String>> response = find(args, sender, user -> teleporter.showCurrentServer(sender));
|
||||
if(response != null) {
|
||||
Server route = response.first;
|
||||
List<String> suggestions = response.second;
|
||||
if(suggestions != null) {
|
||||
return suggestions;
|
||||
} else if(route != null) {
|
||||
if(route.equals(localServer)) {
|
||||
teleporter.showCurrentServer(sender);
|
||||
} else {
|
||||
teleporter.remoteTeleport(CommandUtils.senderToPlayer(sender), route);
|
||||
}
|
||||
} else {
|
||||
teleporter.sendToLobby(CommandUtils.senderToPlayer(sender), false);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "default-server", "def-srv" },
|
||||
desc = "Set your default server when connecting to the network",
|
||||
usage = "[-d datacenter] [name]",
|
||||
flags = "bd:"
|
||||
)
|
||||
@CommandPermissions("ocn.default-server")
|
||||
public List<String> defaultServer(final CommandContext args, CommandSender sender) throws CommandException {
|
||||
Pair<Server, List<String>> response = find(args, sender, user -> {
|
||||
audiences.get(sender).sendMessage(
|
||||
new Component(
|
||||
new TranslatableComponent(
|
||||
"command.server.defaultServer.get",
|
||||
serverStore.tryId(user.default_server_id())
|
||||
.map(server -> new Component(formatter.nameWithDatacenter(server)))
|
||||
.orElse(new Component("Automatic", ChatColor.GREEN))
|
||||
), ChatColor.DARK_PURPLE
|
||||
)
|
||||
);
|
||||
});
|
||||
if(response != null) {
|
||||
Server route = response.first;
|
||||
List<String> suggestions = response.second;
|
||||
if(suggestions != null) {
|
||||
return suggestions;
|
||||
} else if(route != null) {
|
||||
flexecutor.callback(
|
||||
userService.update(
|
||||
userStore.playerId(CommandUtils.senderToPlayer(sender)),
|
||||
(UserDoc.DefaultServer) route::_id
|
||||
), user -> {
|
||||
audiences.get(sender).sendMessage(
|
||||
new Component(
|
||||
new TranslatableComponent(
|
||||
"command.server.defaultServer.set",
|
||||
new Component(formatter.nameWithDatacenter(route))
|
||||
), ChatColor.DARK_PURPLE
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
teleporter.showCurrentServer(sender);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Pair<Server, List<String>> find(CommandContext args, CommandSender sender, Consumer<User> show) throws CommandException {
|
||||
if(args.getSuggestionContext() != null) {
|
||||
return StringUtils.complete(args.getJoinedStrings(0),
|
||||
return Pair.create(null, StringUtils.complete(args.getJoinedStrings(0),
|
||||
serverStore.all()
|
||||
.filter(teleporter::isConnectable)
|
||||
.map(Server::name));
|
||||
.map(Server::name)));
|
||||
}
|
||||
|
||||
// Show current server
|
||||
// Return current server
|
||||
if(args.argsLength() == 0) {
|
||||
teleporter.showCurrentServer(sender);
|
||||
if(sender instanceof Player) {
|
||||
show.accept(userStore.getUser((Player) sender));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -111,8 +197,7 @@ public class ServerCommands implements Commands {
|
|||
if(byBungee == null) {
|
||||
throw new TranslatableCommandException("command.serverNotFound");
|
||||
}
|
||||
teleporter.remoteTeleport(player, byBungee);
|
||||
return null;
|
||||
return Pair.create(byBungee, null);
|
||||
}
|
||||
|
||||
// Search by name/datacenter
|
||||
|
@ -129,16 +214,14 @@ public class ServerCommands implements Commands {
|
|||
|
||||
// Special aliases for the lobby
|
||||
if(name.equals("lobby") || name.equals("hub")) {
|
||||
teleporter.remoteTeleport(player, datacenter, null, null);
|
||||
return null;
|
||||
return Pair.create(null, null);
|
||||
}
|
||||
|
||||
final Set<Server> connectable = serverStore.subset(teleporter::isConnectable);
|
||||
final List<Server> partial = new ArrayList<>();
|
||||
for(Server server : connectable) {
|
||||
if(server.name().equalsIgnoreCase(name)) {
|
||||
teleporter.remoteTeleport(player, server);
|
||||
return null;
|
||||
return Pair.create(server, null);
|
||||
}
|
||||
if(StringUtils.startsWithIgnoreCase(server.name(), name)) {
|
||||
partial.add(server);
|
||||
|
|
|
@ -11,8 +11,15 @@ import net.md_5.bungee.api.chat.BaseComponent;
|
|||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import tc.oc.api.bukkit.users.Users;
|
||||
import tc.oc.api.docs.Friendship;
|
||||
import tc.oc.api.docs.PlayerId;
|
||||
import tc.oc.api.docs.User;
|
||||
import tc.oc.api.friendships.FriendshipRequest;
|
||||
import tc.oc.api.friendships.FriendshipService;
|
||||
import tc.oc.api.minecraft.MinecraftService;
|
||||
import tc.oc.commons.bukkit.chat.Links;
|
||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||
import tc.oc.commons.core.util.Lazy;
|
||||
import tc.oc.minecraft.scheduler.SyncExecutor;
|
||||
import tc.oc.api.sessions.SessionService;
|
||||
import tc.oc.commons.bukkit.chat.BukkitAudiences;
|
||||
|
@ -35,14 +42,16 @@ public class UserCommands implements Commands {
|
|||
private final MinecraftService minecraftService;
|
||||
private final SyncExecutor syncExecutor;
|
||||
private final SessionService sessionService;
|
||||
private final FriendshipService friendshipService;
|
||||
private final UserFinder userFinder;
|
||||
private final IdentityProvider identityProvider;
|
||||
private final UserFormatter userFormatter;
|
||||
|
||||
@Inject UserCommands(MinecraftService minecraftService, SyncExecutor syncExecutor, SessionService sessionService, UserFinder userFinder, IdentityProvider identityProvider, UserFormatter userFormatter) {
|
||||
@Inject UserCommands(MinecraftService minecraftService, SyncExecutor syncExecutor, SessionService sessionService, FriendshipService friendshipService, UserFinder userFinder, IdentityProvider identityProvider, UserFormatter userFormatter) {
|
||||
this.minecraftService = minecraftService;
|
||||
this.syncExecutor = syncExecutor;
|
||||
this.sessionService = sessionService;
|
||||
this.friendshipService = friendshipService;
|
||||
this.userFinder = userFinder;
|
||||
this.identityProvider = identityProvider;
|
||||
this.userFormatter = userFormatter;
|
||||
|
@ -66,13 +75,13 @@ public class UserCommands implements Commands {
|
|||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "friends", "fr", "fs" },
|
||||
aliases = { "friends", "frs" },
|
||||
usage = "[page #]",
|
||||
desc = "Shows what servers your friends are on",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("projectares.friends.view")
|
||||
@CommandPermissions("ocn.friend.list")
|
||||
public void friends(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
final PlayerId playerId = Users.playerId(CommandUtils.senderToPlayer(sender));
|
||||
final int page = args.getInteger(0, 1);
|
||||
|
@ -93,6 +102,95 @@ public class UserCommands implements Commands {
|
|||
);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "friend", "fr" },
|
||||
usage = "<player>",
|
||||
desc = "Send a friend request to a player",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("ocn.friend.request")
|
||||
public void friend(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
User friender = userFinder.getLocalUser(CommandUtils.senderToPlayer(sender));
|
||||
Audience audience = BukkitAudiences.getAudience(sender);
|
||||
syncExecutor.callback(
|
||||
userFinder.findUser(sender, args, 0),
|
||||
response -> {
|
||||
Lazy<PlayerComponent> friended = Lazy.from(
|
||||
() -> new PlayerComponent(identityProvider.currentIdentity(response.user))
|
||||
);
|
||||
if(response.disguised) {
|
||||
// If player is disguised pretend they do not accept friends
|
||||
audience.sendWarning(new TranslatableComponent(
|
||||
"friend.request.not_accepting",
|
||||
friended.get()
|
||||
), false);
|
||||
} else {
|
||||
syncExecutor.callback(
|
||||
friendshipService.create(FriendshipRequest.create(
|
||||
friender.player_id(),
|
||||
response.user.player_id()
|
||||
)),
|
||||
response1 -> {
|
||||
if(response1.success()) {
|
||||
Friendship friendship = response1.friendships().get(0);
|
||||
audience.sendMessage(new TranslatableComponent(
|
||||
"friend.request." + (friendship.accepted() ? "accepted" : "sent"),
|
||||
friended.get()
|
||||
));
|
||||
} else {
|
||||
audience.sendWarning(new TranslatableComponent(
|
||||
"friend.request." + response1.error(),
|
||||
friended.get(),
|
||||
Links.shopLink(true)
|
||||
), false);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "unfriend", "unfr" },
|
||||
usage = "<player>",
|
||||
desc = "Withdraw a friend request or unfriend a current friend",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("ocn.friend.request")
|
||||
public void unfriend(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
User friender = userFinder.getLocalUser(CommandUtils.senderToPlayer(sender));
|
||||
Audience audience = BukkitAudiences.getAudience(sender);
|
||||
syncExecutor.callback(
|
||||
userFinder.findUser(sender, args, 0),
|
||||
response -> {
|
||||
boolean were = friender.friends().contains(response.user);
|
||||
syncExecutor.callback(
|
||||
friendshipService.destroy(FriendshipRequest.create(
|
||||
friender.player_id(),
|
||||
response.user.player_id()
|
||||
)),
|
||||
response1 -> {
|
||||
PlayerComponent friended = new PlayerComponent(identityProvider.currentIdentity(response.user));
|
||||
if(response1.success()) {
|
||||
audience.sendMessage(new TranslatableComponent(
|
||||
"friend.unrequest." + (were ? "success" : "withdraw"),
|
||||
friended
|
||||
));
|
||||
} else {
|
||||
audience.sendWarning(new TranslatableComponent(
|
||||
"friend.unrequest." + response1.error(),
|
||||
friended
|
||||
), false);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "staff", "mods" },
|
||||
desc = "List staff members who are on the network right now",
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package tc.oc.commons.bukkit.event;
|
||||
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import tc.oc.commons.bukkit.gui.Interface;
|
||||
|
||||
public class InterfaceOpenEvent extends Event {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final Interface gui;
|
||||
private final Player player;
|
||||
|
||||
public InterfaceOpenEvent(Interface gui, Player player) {
|
||||
this.gui = gui;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public Interface getInterface() {
|
||||
return this.gui;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package tc.oc.commons.bukkit.flairs;
|
||||
|
||||
import org.bukkit.configuration.Configuration;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class FlairConfiguration {
|
||||
|
||||
private final ConfigurationSection config;
|
||||
|
||||
@Inject
|
||||
FlairConfiguration(Configuration config) {
|
||||
this.config = checkNotNull(config.getConfigurationSection("flairs"));
|
||||
}
|
||||
|
||||
public boolean overheadFlair() {
|
||||
return config.getBoolean("overhead", false);
|
||||
}
|
||||
|
||||
public int maxFlairs() {
|
||||
return config.getInt("limit", -1);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
package tc.oc.commons.bukkit.chat;
|
||||
package tc.oc.commons.bukkit.flairs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
|
@ -9,6 +12,9 @@ import net.md_5.bungee.api.chat.BaseComponent;
|
|||
import tc.oc.api.bukkit.users.BukkitUserStore;
|
||||
import tc.oc.api.docs.virtual.UserDoc;
|
||||
import tc.oc.api.minecraft.MinecraftService;
|
||||
import tc.oc.commons.bukkit.chat.NameFlag;
|
||||
import tc.oc.commons.bukkit.chat.NameType;
|
||||
import tc.oc.commons.bukkit.chat.PartialNameRenderer;
|
||||
import tc.oc.commons.bukkit.nick.Identity;
|
||||
import tc.oc.commons.core.chat.Components;
|
||||
|
||||
|
@ -20,16 +26,26 @@ public class FlairRenderer implements PartialNameRenderer {
|
|||
|
||||
private final MinecraftService minecraftService;
|
||||
private final BukkitUserStore userStore;
|
||||
private final FlairConfiguration flairConfiguration;
|
||||
|
||||
@Inject protected FlairRenderer(MinecraftService minecraftService, BukkitUserStore userStore) {
|
||||
@Inject protected FlairRenderer(MinecraftService minecraftService, BukkitUserStore userStore, FlairConfiguration flairConfiguration) {
|
||||
this.minecraftService = minecraftService;
|
||||
this.userStore = userStore;
|
||||
this.flairConfiguration = flairConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLegacyName(Identity identity, NameType type) {
|
||||
if(!(type.style.contains(NameFlag.FLAIR) && type.reveal)) return "";
|
||||
return getFlairs(identity).reduce("", String::concat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseComponent getComponentName(Identity identity, NameType type) {
|
||||
return Components.fromLegacyText(getLegacyName(identity, type));
|
||||
}
|
||||
|
||||
public Stream<String> getFlairs(Identity identity) {
|
||||
final UserDoc.Identity user;
|
||||
if(identity.getPlayerId() instanceof UserDoc.Identity) {
|
||||
// Flair may already be stashed inside the Identity
|
||||
|
@ -37,19 +53,21 @@ public class FlairRenderer implements PartialNameRenderer {
|
|||
} else {
|
||||
user = userStore.tryUser(identity.getPlayerId());
|
||||
}
|
||||
if(user == null) return "";
|
||||
if(user == null) return Stream.empty();
|
||||
|
||||
final Set<String> realms = ImmutableSet.copyOf(minecraftService.getLocalServer().realms());
|
||||
|
||||
return user.minecraft_flair()
|
||||
.stream()
|
||||
.filter(flair -> realms.contains(flair.realm))
|
||||
.map(flair -> flair.text)
|
||||
.reduce("", String::concat);
|
||||
.stream()
|
||||
.filter(flair -> realms.contains(flair.realm))
|
||||
.sorted((flair1, flair2) -> flair1.priority - flair2.priority)
|
||||
.limit(flairConfiguration.maxFlairs() < 0 ? Long.MAX_VALUE : flairConfiguration.maxFlairs())
|
||||
.sorted((flair1, flair2) -> flair2.priority - flair1.priority)
|
||||
.map(flair -> flair.text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseComponent getComponentName(Identity identity, NameType type) {
|
||||
return Components.fromLegacyText(getLegacyName(identity, type));
|
||||
public int getNumberOfFlairs(Identity identity) {
|
||||
return (int) getFlairs(identity).count();
|
||||
}
|
||||
|
||||
}
|
|
@ -2,6 +2,7 @@ package tc.oc.commons.bukkit.freeze;
|
|||
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
@ -15,10 +16,16 @@ import org.bukkit.event.EventPriority;
|
|||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
import tc.oc.commons.bukkit.event.CoarsePlayerMoveEvent;
|
||||
import tc.oc.commons.bukkit.util.NMSHacks;
|
||||
import tc.oc.commons.core.collection.WeakHashSet;
|
||||
import tc.oc.commons.core.plugin.PluginFacet;
|
||||
import tc.oc.commons.core.util.Pair;
|
||||
import tc.oc.minecraft.api.scheduler.Tickable;
|
||||
|
||||
import static tc.oc.minecraft.protocol.MinecraftVersion.lessThan;
|
||||
import static tc.oc.minecraft.protocol.MinecraftVersion.MINECRAFT_1_8;
|
||||
|
||||
/**
|
||||
* Freezes players by mounting them on an invisible minecart.
|
||||
*/
|
||||
|
@ -27,6 +34,7 @@ public class PlayerFreezer implements PluginFacet, Listener, Tickable {
|
|||
|
||||
private final Map<World, NMSHacks.FakeArmorStand> armorStands = new WeakHashMap<>();
|
||||
private final SetMultimap<Player, FrozenPlayer> frozenPlayers = HashMultimap.create();
|
||||
private final Map<Player, Pair<Boolean, Boolean>> legacyFrozenPlayers = new WeakHashMap<>();
|
||||
|
||||
@Inject PlayerFreezer() {}
|
||||
|
||||
|
@ -53,6 +61,14 @@ public class PlayerFreezer implements PluginFacet, Listener, Tickable {
|
|||
player.leaveVehicle(); // TODO: Put them back in the vehicle when thawed?
|
||||
armorStand(player).spawn(player, player.getLocation());
|
||||
sendAttach(player);
|
||||
if(lessThan(MINECRAFT_1_8, player.getProtocolVersion())) {
|
||||
boolean canFly = player.getAllowFlight(), isFlying = player.isFlying();
|
||||
legacyFrozenPlayers.put(player, Pair.create(canFly, isFlying));
|
||||
if(!player.isOnGround()) {
|
||||
player.setAllowFlight(true);
|
||||
player.setFlying(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return frozenPlayer;
|
||||
|
@ -70,9 +86,17 @@ public class PlayerFreezer implements PluginFacet, Listener, Tickable {
|
|||
armorStand(player).ride(player, player);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onMove(CoarsePlayerMoveEvent event) {
|
||||
if(isFrozen(event.getPlayer()) && legacyFrozenPlayers.containsKey(event.getPlayer())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
frozenPlayers.removeAll(event.getPlayer());
|
||||
legacyFrozenPlayers.remove(event.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
|
@ -96,6 +120,11 @@ public class PlayerFreezer implements PluginFacet, Listener, Tickable {
|
|||
if(frozenPlayers.remove(player, this) && !isFrozen(player) && player.isOnline()) {
|
||||
armorStand(player).destroy(player);
|
||||
player.setPaused(false);
|
||||
Pair<Boolean, Boolean> fly = legacyFrozenPlayers.remove(player);
|
||||
if(fly != null) {
|
||||
player.setFlying(fly.second);
|
||||
player.setAllowFlight(fly.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
package tc.oc.commons.bukkit.gui;
|
||||
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import tc.oc.commons.bukkit.gui.buttons.Button;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class Interface {
|
||||
|
||||
protected Player player;
|
||||
private List<Button> buttons = new ArrayList<>();
|
||||
private List<Object> data = new ArrayList<>();
|
||||
|
||||
public Interface(Player viewer, List<Button> buttons, Object... data) {
|
||||
setData(data);
|
||||
setPlayer(viewer);
|
||||
setButtons(buttons);
|
||||
InterfaceManager.cleanUp(this);
|
||||
}
|
||||
|
||||
public void setData(Object... data) {
|
||||
this.data.clear();
|
||||
Collections.addAll(this.data, data);
|
||||
}
|
||||
|
||||
public List<Object> getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public void setPlayer(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
public void setButtons(List<Button> buttons) {
|
||||
this.buttons = buttons;
|
||||
}
|
||||
|
||||
public List<Button> getButtons() {
|
||||
return this.buttons;
|
||||
}
|
||||
|
||||
public void updateButtons() {
|
||||
updateInventory();
|
||||
}
|
||||
|
||||
public void updateInventory() {
|
||||
try {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
for (Button button : getButtons()) {
|
||||
getInventory().setItem(button.getSlot(), button.getIcon().create());
|
||||
}
|
||||
for (HumanEntity player : getInventory().getViewers()) {
|
||||
player.getOpenInventory().getTopInventory().clear();
|
||||
for (Button button : getButtons()) {
|
||||
player.getOpenInventory().setItem(button.getSlot(), button.getIcon().create());
|
||||
}
|
||||
// player.openInventory(getInventory().getInventory());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public Inventory getInventory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void cleanUp() {
|
||||
player = null;
|
||||
buttons = null;
|
||||
data = null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package tc.oc.commons.bukkit.gui;
|
||||
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
|
||||
public interface InterfaceHolder extends InventoryHolder {
|
||||
|
||||
Inventory getInventory();
|
||||
|
||||
Interface getInterface();
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package tc.oc.commons.bukkit.gui;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import tc.oc.commons.bukkit.gui.buttons.Button;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class InterfaceManager {
|
||||
|
||||
private static List<Interface> inventories = new ArrayList<>();
|
||||
|
||||
public static void registerInventory(Interface gui) {
|
||||
inventories.add(gui);
|
||||
}
|
||||
|
||||
public static void unregisterInventories() {
|
||||
inventories.clear();
|
||||
}
|
||||
|
||||
public static Interface getInterface(InventoryView inventory) {
|
||||
if (inventory.getTopInventory().getHolder() instanceof SimpleInterfaceHolder) {
|
||||
SimpleInterfaceHolder holder = (SimpleInterfaceHolder)inventory.getTopInventory().getHolder();
|
||||
return holder.getInterface();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Interface getInterface(InventoryHolder holder) {
|
||||
if (holder instanceof SimpleInterfaceHolder) {
|
||||
SimpleInterfaceHolder interfaceHolder = (SimpleInterfaceHolder)holder;
|
||||
return interfaceHolder.getInterface();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Interface getInterface(Inventory inventory) {
|
||||
for (Interface gui : inventories) {
|
||||
if (gui.getInventory().equals(inventory)) {
|
||||
return gui;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<Button> getButtons(Interface gui, int slot) {
|
||||
List<Button> buttons = new ArrayList<>();
|
||||
for (Button button : gui.getButtons()) {
|
||||
if (button.getSlot() == slot) {
|
||||
buttons.add(button);
|
||||
}
|
||||
}
|
||||
return buttons;
|
||||
}
|
||||
|
||||
public static Button getButton(Interface gui, ItemStack itemStack) {
|
||||
for (Button button : gui.getButtons()) {
|
||||
if (button.getIcon().create().equals(itemStack)) {
|
||||
return button;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void cleanUp(Interface inventory) {
|
||||
for (Interface inv: inventories) {
|
||||
if (inv != inventory && inv.getPlayer() == inventory.getPlayer()) {
|
||||
inv.cleanUp();
|
||||
inventories.remove(inv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void cleanUp(Player player) {
|
||||
for (Interface inventory: inventories) {
|
||||
if (inventory.getPlayer() == player) {
|
||||
inventory.cleanUp();
|
||||
inventories.remove(inventory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package tc.oc.commons.bukkit.gui;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
|
||||
public class SimpleInterfaceHolder implements InterfaceHolder {
|
||||
|
||||
private Inventory inventory;
|
||||
private Interface gui;
|
||||
private World world;
|
||||
|
||||
public SimpleInterfaceHolder(Inventory inventory, Interface gui, World world) {
|
||||
this.inventory = inventory;
|
||||
this.gui = gui;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inventory getInventory() {
|
||||
return this.inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Interface getInterface() {
|
||||
return this.gui;
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package tc.oc.commons.bukkit.gui.buttons;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import tc.oc.commons.bukkit.util.ItemCreator;
|
||||
|
||||
/**
|
||||
* Button's are used as a way to allow players to interact with inventories. Interfaces contain buttons. When a button
|
||||
* is clicked, the function() method is fired, which can customized in special buttons to perform functions which the
|
||||
* button defines.
|
||||
*/
|
||||
|
||||
public class Button {
|
||||
|
||||
private ItemCreator icon;
|
||||
private Integer slot = 0;
|
||||
|
||||
public Button(ItemCreator icon) {
|
||||
setIcon(icon);
|
||||
}
|
||||
|
||||
public Button(int slot) {
|
||||
setSlot(slot);
|
||||
}
|
||||
|
||||
public Button(ItemCreator icon, int slot) {
|
||||
setIcon(icon);
|
||||
setSlot(slot);
|
||||
}
|
||||
|
||||
public void setIcon(ItemCreator icon) {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is what the button looks like in an interface.
|
||||
* @return the item
|
||||
*/
|
||||
public ItemCreator getIcon() {
|
||||
return this.icon;
|
||||
}
|
||||
|
||||
public void setSlot(int slot) {
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the page is looking for a specific slot for the item, this is where it will go.
|
||||
* @return the slot
|
||||
*/
|
||||
public Integer getSlot() {
|
||||
return this.slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an action that the button performs. Typically overrided with a new function to be used to carry out
|
||||
* various actions.
|
||||
*/
|
||||
public void function(Player player) {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package tc.oc.commons.bukkit.gui.buttons.empty;
|
||||
|
||||
import tc.oc.commons.bukkit.gui.buttons.Button;
|
||||
import tc.oc.commons.bukkit.util.ItemCreator;
|
||||
import org.bukkit.Material;
|
||||
|
||||
public class EmptyButton extends Button {
|
||||
|
||||
public EmptyButton(int slot) {
|
||||
super(new ItemCreator(Material.AIR), slot);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package tc.oc.commons.bukkit.gui.buttons.nextPage;
|
||||
|
||||
import tc.oc.commons.bukkit.gui.Interface;
|
||||
import tc.oc.commons.bukkit.gui.InterfaceManager;
|
||||
import tc.oc.commons.bukkit.gui.buttons.Button;
|
||||
import tc.oc.commons.bukkit.gui.interfaces.ChestOptionsPageInterface;
|
||||
import tc.oc.commons.bukkit.gui.interfaces.SinglePageInterface;
|
||||
import tc.oc.commons.bukkit.util.Constants;
|
||||
import tc.oc.commons.bukkit.util.ItemCreator;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class NextPageButton extends Button {
|
||||
|
||||
private SinglePageInterface page;
|
||||
|
||||
public NextPageButton(int slot) {
|
||||
super(null, slot);
|
||||
}
|
||||
|
||||
public NextPageButton(SinglePageInterface gui, int slot) {
|
||||
super(null, slot);
|
||||
this.page = gui;
|
||||
}
|
||||
|
||||
public SinglePageInterface getNextPage(SinglePageInterface chestInterface) {
|
||||
try {
|
||||
if (chestInterface instanceof ChestOptionsPageInterface) {
|
||||
ChestOptionsPageInterface nextPage = new ChestOptionsPageInterface(this.page.rawButtons, this.page.getSize(), this.page.rawTitle, this.page, this.page.page + 1);
|
||||
nextPage.update();
|
||||
return nextPage != null ? nextPage : chestInterface;
|
||||
}
|
||||
SinglePageInterface nextPage = new SinglePageInterface(this.page.getPlayer(), this.page.rawButtons, this.page.getSize(), this.page.rawTitle, this.page.page + 1);
|
||||
nextPage.update();
|
||||
return nextPage != null ? nextPage : chestInterface;
|
||||
} catch (Exception e) {
|
||||
return chestInterface;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemCreator getIcon() {
|
||||
return new ItemCreator(Material.ARROW)
|
||||
.setName(Constants.PREFIX + "Next");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void function(Player player) {
|
||||
Interface currentInterface = InterfaceManager.getInterface(player.getOpenInventory());
|
||||
//Interface nextPage = getNextPage((SinglePageInterface) currentInterface);
|
||||
((SinglePageInterface)currentInterface).openNextPage();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package tc.oc.commons.bukkit.gui.buttons.toggle;
|
||||
|
||||
import tc.oc.commons.bukkit.gui.buttons.Button;
|
||||
import tc.oc.commons.bukkit.util.ItemCreator;
|
||||
|
||||
/**
|
||||
* Created by ShinyDialga45 on 4/10/2015.
|
||||
*/
|
||||
public class ToggleButton extends Button {
|
||||
|
||||
private boolean state = false;
|
||||
|
||||
public ToggleButton(ItemCreator itemCreator, boolean state) {
|
||||
super(itemCreator);
|
||||
setState(state);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(boolean state) {
|
||||
this.state = state;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package tc.oc.commons.bukkit.gui.buttons.toggle.type;
|
||||
|
||||
public class BooleanToggleType {
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package tc.oc.commons.bukkit.gui.buttons.toggle.type;
|
||||
|
||||
public class EnumToggleType extends ToggleType {
|
||||
|
||||
private int value;
|
||||
|
||||
public EnumToggleType() {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package tc.oc.commons.bukkit.gui.buttons.toggle.type;
|
||||
|
||||
public class ToggleType {
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package tc.oc.commons.bukkit.gui.interfaces;
|
||||
|
||||
import tc.oc.commons.bukkit.gui.Interface;
|
||||
import tc.oc.commons.bukkit.gui.SimpleInterfaceHolder;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import tc.oc.commons.bukkit.gui.buttons.Button;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ChestInterface extends Interface {
|
||||
|
||||
private int size;
|
||||
private Inventory inventory;
|
||||
private String title;
|
||||
|
||||
public ChestInterface(Player player, List<Button> buttons, int size, String title) {
|
||||
super(player, buttons);
|
||||
setSize(size);
|
||||
setTitle(title);
|
||||
this.inventory = Bukkit.createInventory(new SimpleInterfaceHolder(inventory, this, player.getWorld()), getSize(), getTitle());
|
||||
//setInventory(new InterfaceInventory(this, inventory));
|
||||
}
|
||||
|
||||
public void setSize(int size) {
|
||||
//If the size isn't a multiple of 9, round it to the nearest multiple of 9.
|
||||
if (size % 9 != 0) {
|
||||
setSize(9*(Math.round(size / 9)));
|
||||
} else {
|
||||
this.size = size;
|
||||
}
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
int titleSize = 32;
|
||||
this.title = title.length() > titleSize ? title.substring(0, titleSize - 1) : title;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inventory getInventory() {
|
||||
return this.inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
super.cleanUp();
|
||||
inventory = null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
package tc.oc.commons.bukkit.gui.interfaces;
|
||||
|
||||
import tc.oc.commons.bukkit.gui.Interface;
|
||||
import tc.oc.commons.bukkit.gui.buttons.Button;
|
||||
import tc.oc.commons.bukkit.gui.buttons.empty.EmptyButton;
|
||||
import tc.oc.commons.bukkit.gui.buttons.toggle.ToggleButton;
|
||||
import tc.oc.commons.bukkit.util.Constants;
|
||||
import tc.oc.commons.bukkit.util.ItemCreator;
|
||||
import tc.oc.commons.bukkit.util.ObjectUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MultiPageInterfaces are a special group of interfaces. They aren't a single interface, but a collection of
|
||||
* SinglePageInterfaces. Given a set of buttons, it will add them to a page with default items in order. This can be
|
||||
* used as a way to provide a list of non-hardcoded items without having to define their slots.
|
||||
*/
|
||||
|
||||
public class ChestOptionsPageInterface extends SinglePageInterface {
|
||||
|
||||
public ChestOptionsPageInterface(List<Button> buttons, int size, String title, Interface parent) {
|
||||
this(null, buttons, size, title, parent, 1);
|
||||
}
|
||||
|
||||
public ChestOptionsPageInterface(List<Button> buttons, int size, String title, Interface parent, int i) {
|
||||
this(null, buttons, size, title, parent, i);
|
||||
}
|
||||
|
||||
public ChestOptionsPageInterface(Player player, List<Button> buttons, int size, String title, Interface parent) {
|
||||
this(player, buttons, size, title, parent, 1);
|
||||
}
|
||||
|
||||
public ChestOptionsPageInterface(Player player, List<Button> buttons, int size, String title, Interface parent, int i, Object... data) {
|
||||
super(player, buttons, size, title + (i > 1 ? " - " + i : ""), 1, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateButtons() {
|
||||
if (getButtons().size() == 0) {
|
||||
List<Button> buttons = new ArrayList<>();
|
||||
for (Button button : getDefaultButtons()) {
|
||||
button.setSlot(getNextSlot(button.getSlot(), buttons));
|
||||
if (button.getSlot() < getSize()) {
|
||||
buttons.add(button);
|
||||
}
|
||||
}
|
||||
Button empty = new Button(
|
||||
new ItemCreator(Material.DEAD_BUSH)
|
||||
.setName(Constants.PREFIX + "Nothing here..."));
|
||||
empty.setSlot(getNextSlot(empty.getSlot(), buttons));
|
||||
if (empty.getSlot() < getSize()) {
|
||||
buttons.add(empty);
|
||||
}
|
||||
buttons.remove(this.nextPageButton);
|
||||
setButtons(buttons);
|
||||
updateInventory();
|
||||
return;
|
||||
}
|
||||
int allButtons = getDefaultButtons().size() + getButtons().size()*2;
|
||||
//This tells the plugin how many pages are needed to store all of the items.
|
||||
int allPages = (int)((double) ((allButtons) / (getSize() - getDefaultButtons().size())));
|
||||
if (((getButtons().size() + 1) % (getSize() - getDefaultButtons().size()) == 0) && allPages > 1) {
|
||||
allPages = allPages - 1;
|
||||
}
|
||||
if (allButtons < getSize()) {
|
||||
allPages = 1;
|
||||
}
|
||||
if (allPages >= 3) {
|
||||
//allPages = allPages - 1;
|
||||
}
|
||||
//This gets the items for the page it is currently on.
|
||||
List<Button> buttons = ObjectUtils.paginate(getButtons(), page, (getSize() - getDefaultButtons().size())/2);
|
||||
try {
|
||||
if (buttons.size() != 0) {
|
||||
ArrayList<Button> currentButtons = new ArrayList<>();
|
||||
for (Button button : getDefaultButtons()) {
|
||||
if (button.equals(this.nextPageButton)) {
|
||||
button.setIcon(button.getIcon().setSize(page + 1));
|
||||
}
|
||||
button.setSlot(button.getSlot());
|
||||
if (button.getSlot() > getSize()) {
|
||||
break;
|
||||
}
|
||||
currentButtons.add(button);
|
||||
}
|
||||
int currentButton = 0;
|
||||
for (Button button : buttons) {
|
||||
if (buttons.indexOf(button) > 0 && buttons.get(buttons.size() - 1).equals(button) && page == (allPages)) {
|
||||
// break;
|
||||
}
|
||||
final ToggleButton toggleButton = (ToggleButton) button;
|
||||
toggleButton.setSlot(getNextSlot(currentButton, currentButtons));
|
||||
ItemCreator dye = new ItemCreator(Material.INK_SACK)
|
||||
.setData(toggleButton.getState() == true ? 10 : 8)
|
||||
.setName((toggleButton.getState() == true ? ChatColor.GREEN : ChatColor.RED) + ChatColor.BOLD.toString() + (toggleButton.getState() == true ? "Enabled" : "Disabled"));
|
||||
Button toggleDye = new Button(dye) {
|
||||
@Override
|
||||
public void function(Player player) {
|
||||
toggleButton.function(player);
|
||||
}
|
||||
};
|
||||
toggleDye.setSlot(toggleButton.getSlot() + 9);
|
||||
if (button.getSlot() > getSize()) {
|
||||
break;
|
||||
}
|
||||
currentButtons.add(toggleButton);
|
||||
currentButtons.add(toggleDye);
|
||||
currentButton = toggleButton.getSlot();
|
||||
}
|
||||
if (allPages == page) {
|
||||
currentButtons.remove(this.nextPageButton);
|
||||
}
|
||||
setButtons(currentButtons);
|
||||
updateInventory();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
if (page > 0) {
|
||||
page = page - 1;
|
||||
updateButtons();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultButtons() {
|
||||
defaultButtons.clear();
|
||||
for (Integer integer : new Integer[]{1, 2, 3, 4, 5, 6, 7, 9, 17, 18, 26, 27, 35, 36, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 11, 20, 29, 38, 13, 22, 31, 40, 15, 24, 33, 42}) {
|
||||
if (integer > getSize()) {
|
||||
break;
|
||||
}
|
||||
EmptyButton button = new EmptyButton(integer);
|
||||
defaultButtons.add(button);
|
||||
}
|
||||
defaultButtons.add(this.nextPageButton);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
package tc.oc.commons.bukkit.gui.interfaces;
|
||||
|
||||
import tc.oc.commons.bukkit.gui.Interface;
|
||||
import tc.oc.commons.bukkit.gui.buttons.Button;
|
||||
import tc.oc.commons.bukkit.gui.buttons.empty.EmptyButton;
|
||||
import tc.oc.commons.bukkit.util.Constants;
|
||||
import tc.oc.commons.bukkit.util.ItemCreator;
|
||||
import tc.oc.commons.bukkit.util.ObjectUtils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MultiPageInterfaces are a special group of interfaces. They aren't a single interface, but a collection of
|
||||
* SinglePageInterfaces. Given a set of buttons, it will add them to a page with default items in order. This can be
|
||||
* used as a way to provide a list of non-hardcoded items without having to define their slots.
|
||||
*/
|
||||
|
||||
@Deprecated
|
||||
public class ChestPageInterface extends ChestInterface {
|
||||
|
||||
private List<ChestInterface> pages = new ArrayList<>();
|
||||
|
||||
// public final LastPageButton lastPageButton = new LastPageButton(this, 0); TODO
|
||||
//public final NextPageButton nextPageButton = new NextPageButton(this, 8);
|
||||
|
||||
public ChestPageInterface(List<Button> buttons, int size, String title, Interface parent) {
|
||||
this(null, buttons, size, title, parent);
|
||||
}
|
||||
|
||||
public ChestPageInterface(Player player, List<Button> buttons, int size, String title, Object... data) {
|
||||
super(player, buttons, size, title);
|
||||
/*
|
||||
MultiPageInterfaces must be contain necessary default items, if it cannot contain the next page item
|
||||
(currently has the highest slot value of a necessary default item), it won't allow proper navagation.
|
||||
*/
|
||||
setData(data);
|
||||
//setSize((size >= this.nextPageButton.getSlot() + 1 ? size : this.nextPageButton.getSlot() + 1));
|
||||
}
|
||||
|
||||
public void setupInventory() {
|
||||
pages.clear();
|
||||
if (getButtons().size() == 0) {
|
||||
List<Button> buttons = new ArrayList<>();
|
||||
for (Button button : getDefaultButtons()) {
|
||||
button.setSlot(getNextSlot(button.getSlot(), buttons));
|
||||
if (button.getSlot() < getSize()) {
|
||||
buttons.add(button);
|
||||
}
|
||||
}
|
||||
Button empty = new Button(
|
||||
new ItemCreator(Material.DEAD_BUSH)
|
||||
.setName(Constants.PREFIX + "Nothing here..."));
|
||||
empty.setSlot(getNextSlot(empty.getSlot(), buttons));
|
||||
if (empty.getSlot() < getSize()) {
|
||||
buttons.add(empty);
|
||||
}
|
||||
pages.add(new ChestInterface(null, buttons, getSize(), getTitle()));
|
||||
return;
|
||||
}
|
||||
int allButtons = getDefaultButtons().size() + getButtons().size();
|
||||
//This tells the plugin how many pages are needed to store all of the items.
|
||||
int allPages = (int) Math.round((double) (allButtons) / (getSize() - getDefaultButtons().size()));
|
||||
if (((getButtons().size() + 1) % (getSize() - getDefaultButtons().size()) == 0) && allPages > 1) {
|
||||
allPages = allPages - 1;
|
||||
}
|
||||
if (allPages >= 3) {
|
||||
allPages = allPages - 1;
|
||||
}
|
||||
for (int i = 1; i <= allPages; i++) {
|
||||
//This gets the items for the page it is currently on.
|
||||
List<Button> buttons = ObjectUtils.paginate(getButtons(), i, getSize() - getDefaultButtons().size());
|
||||
if (allButtons < getSize()) {
|
||||
allPages = 1;
|
||||
}
|
||||
if (buttons.size() != 0) {
|
||||
ArrayList<Button> currentButtons = new ArrayList<>();
|
||||
for (Button button : getDefaultButtons()) {
|
||||
button.setSlot(button.getSlot());
|
||||
if (button.getSlot() > getSize()) {
|
||||
break;
|
||||
}
|
||||
currentButtons.add(button);
|
||||
}
|
||||
int currentButton = 0;
|
||||
for (Button button : buttons) {
|
||||
button.setSlot(getNextSlot(currentButton, currentButtons));
|
||||
if (button.getSlot() > getSize()) {
|
||||
break;
|
||||
}
|
||||
currentButtons.add(button);
|
||||
currentButton++;
|
||||
}
|
||||
if (allPages == i) {
|
||||
// currentButtons.remove(this.nextPageButton);
|
||||
}
|
||||
String suffix = i > 1 ? " - " + i : "";
|
||||
ChestInterface gui = new ChestInterface(null, currentButtons, getSize(), getTitle() + suffix);
|
||||
gui.updateInventory();
|
||||
pages.add(gui);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPages(List<ChestInterface> pages) {
|
||||
this.pages = pages;
|
||||
}
|
||||
|
||||
public List<ChestInterface> getPages() {
|
||||
return this.pages;
|
||||
}
|
||||
|
||||
public int getNextSlot(int slot, List<Button> buttons) {
|
||||
for (Button button : buttons) {
|
||||
if (button.getSlot() == slot) {
|
||||
return getNextSlot(slot + 1, buttons);
|
||||
}
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Inventory guide.
|
||||
00 01 02 03 04 05 06 07 08
|
||||
09 10 11 12 13 14 15 16 17
|
||||
18 19 20 21 22 23 24 25 26
|
||||
27 28 29 30 31 32 33 34 35
|
||||
36 37 38 39 40 41 42 43 44
|
||||
45 46 47 48 49 50 51 52 53
|
||||
|
||||
Key:
|
||||
p = Page arrow
|
||||
x = Empty space
|
||||
o = Paginated item
|
||||
|
||||
Current inventory layout
|
||||
p x x x x x x x p
|
||||
x o o o o o o o x
|
||||
x o o o o o o o x
|
||||
x o o o o o o o x
|
||||
x o o o o o o o x
|
||||
x x x x x x x x x
|
||||
|
||||
Everything is easily customizable. The methods take currently taken slots into consideration.
|
||||
|
||||
*/
|
||||
public List<Button> getDefaultButtons() {
|
||||
List<Button> buttons = new ArrayList<>();
|
||||
for (Integer integer : new Integer[]{1, 2, 3, 4, 5, 6, 7, 9, 17, 18, 26, 27, 35, 36, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53}) {
|
||||
if (integer > getSize()) {
|
||||
break;
|
||||
}
|
||||
EmptyButton button = new EmptyButton(integer);
|
||||
buttons.add(button);
|
||||
}
|
||||
//buttons.add(this.lastPageButton); TODO
|
||||
// buttons.add(this.nextPageButton);
|
||||
//if (this.nextPageButton.getSlot() < getSize()) {
|
||||
//}
|
||||
return buttons;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inventory getInventory() {
|
||||
return getPages().get(0).getInventory();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package tc.oc.commons.bukkit.gui.interfaces;
|
||||
|
||||
import tc.oc.commons.bukkit.gui.Interface;
|
||||
import tc.oc.commons.bukkit.gui.SimpleInterfaceHolder;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import tc.oc.commons.bukkit.gui.buttons.Button;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HopperInterface extends Interface {
|
||||
|
||||
private int size;
|
||||
private Inventory inventory;
|
||||
private String title;
|
||||
|
||||
public HopperInterface(Player player, List<Button> buttons, String title, Interface parent) {
|
||||
super(player, buttons);
|
||||
setTitle(title);
|
||||
this.inventory = Bukkit.createInventory(new SimpleInterfaceHolder(inventory, this, player.getWorld()), InventoryType.HOPPER, getTitle());
|
||||
/*//this.inventory = player.getInventory();
|
||||
//inventory = Bukkit.createInventory(new SimpleInterfaceHolder(inventory, this), InventoryType.valueOf(args), getTitle());
|
||||
//setInventory(new InterfaceInventory(this, inventory));
|
||||
updateButtons();
|
||||
updateInventory();*/
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
int titleSize = 32;
|
||||
this.title = title.length() > titleSize ? title.substring(0, titleSize - 1) : title;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inventory getInventory() {
|
||||
return this.inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
super.cleanUp();
|
||||
inventory = null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
package tc.oc.commons.bukkit.gui.interfaces;
|
||||
|
||||
import tc.oc.commons.bukkit.gui.Interface;
|
||||
import tc.oc.commons.bukkit.gui.buttons.Button;
|
||||
import tc.oc.commons.bukkit.gui.buttons.empty.EmptyButton;
|
||||
import tc.oc.commons.bukkit.gui.buttons.nextPage.NextPageButton;
|
||||
import tc.oc.commons.bukkit.util.Constants;
|
||||
import tc.oc.commons.bukkit.util.ItemCreator;
|
||||
import tc.oc.commons.bukkit.util.ObjectUtils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MultiPageInterfaces are a special group of interfaces. They aren't a single interface, but a collection of
|
||||
* SinglePageInterfaces. Given a set of buttons, it will add them to a page with default items in order. This can be
|
||||
* used as a way to provide a list of non-hardcoded items without having to define their slots.
|
||||
*/
|
||||
|
||||
public class SinglePageInterface extends ChestInterface {
|
||||
|
||||
public List<Button> defaultButtons = new ArrayList<>();
|
||||
|
||||
public int page;
|
||||
public String rawTitle;
|
||||
public List<Button> rawButtons = new ArrayList<>();
|
||||
|
||||
public final NextPageButton nextPageButton = new NextPageButton(this, 8);
|
||||
|
||||
public SinglePageInterface(Player player, List<Button> buttons, int size, String title) {
|
||||
this(player, buttons, size, title, 1);
|
||||
}
|
||||
|
||||
public SinglePageInterface(Player player, List<Button> buttons, int size, String title, int page, Object... data) {
|
||||
super(player, buttons, size, title + (page > 1 ? " - " + page : ""));
|
||||
this.rawTitle = title;
|
||||
this.rawButtons = buttons;
|
||||
/*
|
||||
MultiPageInterfaces must be contain necessary default items, if it cannot contain the next page item
|
||||
(currently has the highest slot value of a necessary default item), it won't allow proper navagation.
|
||||
*/
|
||||
setData(data);
|
||||
this.page = page;
|
||||
setSize((size >= this.nextPageButton.getSlot() + 1 ? size : this.nextPageButton.getSlot() + 1));
|
||||
}
|
||||
|
||||
public void openLastPage(Player player) {
|
||||
page = page - 1;
|
||||
if (page > 0) {
|
||||
update();
|
||||
} else {
|
||||
player.openInventory(getInventory());
|
||||
//getParent().updateButtons();
|
||||
}
|
||||
}
|
||||
|
||||
public void openNextPage() {
|
||||
page = page + 1;
|
||||
update();
|
||||
}
|
||||
|
||||
public void update() {
|
||||
setButtons();
|
||||
rawButtons = getButtons();
|
||||
setDefaultButtons();
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
public void setButtons() {
|
||||
setButtons(getButtons());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateButtons() {
|
||||
if (getButtons().size() == 0) {
|
||||
List<Button> buttons = new ArrayList<>();
|
||||
for (Button button : getDefaultButtons()) {
|
||||
button.setSlot(getNextSlot(button.getSlot(), buttons));
|
||||
if (button.getSlot() < getSize()) {
|
||||
buttons.add(button);
|
||||
}
|
||||
}
|
||||
Button empty = new Button(
|
||||
new ItemCreator(Material.DEAD_BUSH)
|
||||
.setName(Constants.PREFIX + "Nothing here..."));
|
||||
empty.setSlot(getNextSlot(empty.getSlot(), buttons));
|
||||
if (empty.getSlot() < getSize()) {
|
||||
buttons.add(empty);
|
||||
}
|
||||
buttons.remove(this.nextPageButton);
|
||||
setButtons(buttons);
|
||||
updateInventory();
|
||||
return;
|
||||
}
|
||||
int allButtons = getDefaultButtons().size() + getButtons().size();
|
||||
//This tells the plugin how many pages are needed to store all of the items.
|
||||
int allPages = (int) Math.round((double) (allButtons) / (getSize() - getDefaultButtons().size()));
|
||||
if (((getButtons().size() + 1) % (getSize() - getDefaultButtons().size()) == 0) && allPages > 1) {
|
||||
allPages = allPages - 1;
|
||||
}
|
||||
if (allPages >= 3) {
|
||||
// allPages = allPages - 1;
|
||||
}
|
||||
//This gets the items for the page it is currently on.
|
||||
List<Button> buttons = ObjectUtils.paginate(getButtons(), page, getSize() - getDefaultButtons().size());
|
||||
if (allButtons < getSize()) {
|
||||
allPages = 1;
|
||||
}
|
||||
try {
|
||||
if (buttons.size() != 0) {
|
||||
ArrayList<Button> currentButtons = new ArrayList<>();
|
||||
for (Button button : getDefaultButtons()) {
|
||||
button.setSlot(button.getSlot());
|
||||
if (button.getSlot() > getSize()) {
|
||||
break;
|
||||
}
|
||||
currentButtons.add(button);
|
||||
}
|
||||
int currentButton = 0;
|
||||
for (Button button : buttons) {
|
||||
button.setSlot(getNextSlot(currentButton, currentButtons));
|
||||
if (button.getSlot() > getSize()) {
|
||||
break;
|
||||
}
|
||||
currentButtons.add(button);
|
||||
currentButton++;
|
||||
}
|
||||
if (allPages == page) {
|
||||
currentButtons.remove(this.nextPageButton);
|
||||
}
|
||||
setButtons(currentButtons);
|
||||
updateInventory();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (page > 0) {
|
||||
page = page - 1;
|
||||
updateButtons();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getNextSlot(int slot, List<Button> buttons) {
|
||||
for (Button button : buttons) {
|
||||
if (button.getSlot() == slot) {
|
||||
return getNextSlot(slot + 1, buttons);
|
||||
}
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
public void setDefaultButtons() {
|
||||
defaultButtons.clear();
|
||||
defaultButtons.add(this.nextPageButton);
|
||||
for (Integer integer : new Integer[]{1, 2, 3, 4, 5, 6, 7, 9, 17, 18, 26, 27, 35, 36, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53}) {
|
||||
if (integer > getSize()) {
|
||||
break;
|
||||
}
|
||||
EmptyButton button = new EmptyButton(integer);
|
||||
defaultButtons.add(button);
|
||||
}
|
||||
//if (this.nextPageButton.getSlot() < getSize()) {
|
||||
//}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Inventory guide.
|
||||
00 01 02 03 04 05 06 07 08
|
||||
09 10 11 12 13 14 15 16 17
|
||||
18 19 20 21 22 23 24 25 26
|
||||
27 28 29 30 31 32 33 34 35
|
||||
36 37 38 39 40 41 42 43 44
|
||||
45 46 47 48 49 50 51 52 53
|
||||
|
||||
Key:
|
||||
p = Page arrow
|
||||
x = Empty space
|
||||
o = Paginated item
|
||||
|
||||
Current inventory layout
|
||||
p x x x x x x x p
|
||||
x o o o o o o o x
|
||||
x o o o o o o o x
|
||||
x o o o o o o o x
|
||||
x o o o o o o o x
|
||||
x x x x x x x x x
|
||||
|
||||
Everything is easily customizable. The methods take currently taken slots into consideration.
|
||||
|
||||
*/
|
||||
public List<Button> getDefaultButtons() {
|
||||
return this.defaultButtons;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
super.cleanUp();
|
||||
defaultButtons = null;
|
||||
rawButtons = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package tc.oc.commons.bukkit.gui.interfaces.render;
|
||||
|
||||
import tc.oc.commons.bukkit.gui.Interface;
|
||||
import tc.oc.commons.bukkit.gui.buttons.Button;
|
||||
import tc.oc.commons.bukkit.gui.interfaces.ChestInterface;
|
||||
import tc.oc.commons.bukkit.util.ItemCreator;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ChestRenderInterface extends ChestInterface {
|
||||
|
||||
private Coordinate origin;
|
||||
|
||||
public ChestRenderInterface(Player player, List<Button> buttons, int size, String title) {
|
||||
super(player, buttons, size, title);
|
||||
this.origin = new Coordinate(0, 0);
|
||||
}
|
||||
|
||||
public int getRenderSlot(Coordinate index) {
|
||||
double currentX = getOrigin().getX();
|
||||
double currentY = getOrigin().getY();
|
||||
for (int i = 0; i < getSize(); i++) {
|
||||
Coordinate coordinate = new Coordinate(currentX, currentY);
|
||||
//Bukkit.broadcastMessage(index.getX() + " " + coordinate.getX() + " " + getOrigin().getX());
|
||||
//Bukkit.broadcastMessage(index.getY() + " " + coordinate.getY() + " " + getOrigin().getY());
|
||||
if (index.getX() == coordinate.getX() && index.getY() == coordinate.getY()) {
|
||||
return i;
|
||||
}
|
||||
if (((i + 1) % 9) == 0) {
|
||||
currentX = getOrigin().getX();
|
||||
currentY--;
|
||||
} else {
|
||||
currentX++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Coordinate getOrigin() {
|
||||
return this.origin != null ? this.origin : new Coordinate(0, 0);
|
||||
}
|
||||
|
||||
public void setOrigin(Coordinate origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateButtons() {
|
||||
List<Button> buttons = new ArrayList<>();
|
||||
List<Coordinate> coordinates = new ArrayList<>();
|
||||
for (final Coordinate coordinate : coordinates) {
|
||||
int renderSlot = getRenderSlot(coordinate);
|
||||
if (renderSlot >= 0) {
|
||||
Button button = new Button(new ItemCreator(Material.DIRT).setName(coordinate.getX() + " " + coordinate.getY()), renderSlot) {
|
||||
@Override
|
||||
public void function(Player player) {
|
||||
Bukkit.broadcastMessage(coordinate.getX() + " " + coordinate.getY());
|
||||
}
|
||||
};
|
||||
buttons.add(button);
|
||||
}
|
||||
}
|
||||
Button up = new Button(new ItemCreator(Material.ARROW)
|
||||
.setName(ChatColor.GREEN + "Move Up"), 7) {
|
||||
@Override
|
||||
public void function(Player player) {
|
||||
setOrigin(new Coordinate(getOrigin().getX(), getOrigin().getY() + 1));
|
||||
updateButtons();
|
||||
}
|
||||
};
|
||||
buttons.add(up);
|
||||
Button down = new Button(new ItemCreator(Material.ARROW)
|
||||
.setName(ChatColor.GREEN + "Move Down"), 25) {
|
||||
@Override
|
||||
public void function(Player player) {
|
||||
setOrigin(new Coordinate(getOrigin().getX(), getOrigin().getY() - 1));
|
||||
updateButtons();
|
||||
}
|
||||
};
|
||||
buttons.add(down);
|
||||
Button left = new Button(new ItemCreator(Material.ARROW)
|
||||
.setName(ChatColor.GREEN + "Move Left"), 15) {
|
||||
@Override
|
||||
public void function(Player player) {
|
||||
setOrigin(new Coordinate(getOrigin().getX() - 1, getOrigin().getY()));
|
||||
updateButtons();
|
||||
}
|
||||
};
|
||||
buttons.add(left);
|
||||
Button right = new Button(new ItemCreator(Material.ARROW)
|
||||
.setName(ChatColor.GREEN + "Move Right"), 17) {
|
||||
@Override
|
||||
public void function(Player player) {
|
||||
setOrigin(new Coordinate(getOrigin().getX() + 1, getOrigin().getY()));
|
||||
updateButtons();
|
||||
}
|
||||
};
|
||||
buttons.add(right);
|
||||
Button compass = new Button(new ItemCreator(Material.COMPASS)
|
||||
.setName(ChatColor.GREEN + "Use these to move!"), 16);
|
||||
buttons.add(compass);
|
||||
setButtons(buttons);
|
||||
updateInventory();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package tc.oc.commons.bukkit.gui.interfaces.render;
|
||||
|
||||
public class Coordinate {
|
||||
|
||||
private double x = 0;
|
||||
private double y = 0;
|
||||
|
||||
public Coordinate(double x, double y) {
|
||||
setX(x);
|
||||
setY(y);
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
public void setX(double x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return this.y;
|
||||
}
|
||||
|
||||
public void setY(double y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,431 @@
|
|||
package tc.oc.commons.bukkit.gui.interfaces.render.text;
|
||||
|
||||
import tc.oc.commons.bukkit.gui.Interface;
|
||||
import tc.oc.commons.bukkit.gui.buttons.Button;
|
||||
import tc.oc.commons.bukkit.gui.interfaces.render.ChestRenderInterface;
|
||||
import tc.oc.commons.bukkit.gui.interfaces.render.Coordinate;
|
||||
import tc.oc.commons.bukkit.util.ItemCreator;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class GridTextRenderInterface extends ChestRenderInterface {
|
||||
|
||||
private String text;
|
||||
|
||||
public GridTextRenderInterface(Player player, List<Button> buttons, int size, String title, String text) {
|
||||
super(player, buttons, size, title);
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateButtons() {
|
||||
List<Button> buttons = new ArrayList<>();
|
||||
List<Letter> letters = new ArrayList<>();
|
||||
for (char c : getText().toCharArray()) {
|
||||
letters.add(Letter.getLetter(c));
|
||||
}
|
||||
double totalX = 0;
|
||||
for (Letter letter : letters) {
|
||||
for (final Coordinate coordinate : letter.getCoordinates().keySet()) {
|
||||
Coordinate newCoordinate = new Coordinate(coordinate.getX(), coordinate.getY());
|
||||
newCoordinate.setX(coordinate.getX() + totalX);
|
||||
int renderSlot = getRenderSlot(newCoordinate);
|
||||
if (renderSlot >= 0) {
|
||||
ItemCreator itemCreator = letter.getCoordinates().get(coordinate) != null ? letter.getCoordinates().get(coordinate) : new ItemCreator(Material.WOOL).setData(6);
|
||||
Button button = new Button(itemCreator.setName(newCoordinate.getX() + " " + newCoordinate.getY()), renderSlot);
|
||||
buttons.add(button);
|
||||
}
|
||||
}
|
||||
totalX = totalX + letter.getLength() + 1;
|
||||
}
|
||||
|
||||
Button up = new Button(new ItemCreator(Material.ARROW)
|
||||
.setName(ChatColor.GREEN + "Move Up"), 7) {
|
||||
@Override
|
||||
public void function(Player player) {
|
||||
setOrigin(new Coordinate(getOrigin().getX(), getOrigin().getY() + 1));
|
||||
updateButtons();
|
||||
}
|
||||
};
|
||||
buttons.add(up);
|
||||
Button down = new Button(new ItemCreator(Material.ARROW)
|
||||
.setName(ChatColor.GREEN + "Move Down"), 25) {
|
||||
@Override
|
||||
public void function(Player player) {
|
||||
setOrigin(new Coordinate(getOrigin().getX(), getOrigin().getY() - 1));
|
||||
updateButtons();
|
||||
}
|
||||
};
|
||||
buttons.add(down);
|
||||
Button left = new Button(new ItemCreator(Material.ARROW)
|
||||
.setName(ChatColor.GREEN + "Move Left"), 15) {
|
||||
@Override
|
||||
public void function(Player player) {
|
||||
setOrigin(new Coordinate(getOrigin().getX() - 1, getOrigin().getY()));
|
||||
updateButtons();
|
||||
}
|
||||
};
|
||||
buttons.add(left);
|
||||
Button right = new Button(new ItemCreator(Material.ARROW)
|
||||
.setName(ChatColor.GREEN + "Move Right"), 17) {
|
||||
@Override
|
||||
public void function(Player player) {
|
||||
setOrigin(new Coordinate(getOrigin().getX() + 1, getOrigin().getY()));
|
||||
updateButtons();
|
||||
}
|
||||
};
|
||||
buttons.add(right);
|
||||
Button compass = new Button(new ItemCreator(Material.COMPASS)
|
||||
.setName(ChatColor.GREEN + "Use these to move!"), 16);
|
||||
buttons.add(compass);
|
||||
setButtons(buttons);
|
||||
updateInventory();
|
||||
}
|
||||
|
||||
public enum Letter {
|
||||
|
||||
A(
|
||||
'A',
|
||||
Arrays.asList(
|
||||
"_X_",
|
||||
"X_X",
|
||||
"X_X",
|
||||
"XXX",
|
||||
"X_X")),
|
||||
B(
|
||||
'B',
|
||||
Arrays.asList(
|
||||
"XX_",
|
||||
"X_X",
|
||||
"XX_",
|
||||
"X_X",
|
||||
"XX_")),
|
||||
C(
|
||||
'C',
|
||||
Arrays.asList(
|
||||
"_XX",
|
||||
"X__",
|
||||
"X__",
|
||||
"X__",
|
||||
"_XX")),
|
||||
D(
|
||||
'D',
|
||||
Arrays.asList(
|
||||
"XX_",
|
||||
"X_X",
|
||||
"X_X",
|
||||
"X_X",
|
||||
"XX_")),
|
||||
E(
|
||||
'E',
|
||||
Arrays.asList(
|
||||
"XXX",
|
||||
"X__",
|
||||
"XX_",
|
||||
"X__",
|
||||
"XXX")),
|
||||
F(
|
||||
'F',
|
||||
Arrays.asList(
|
||||
"XXX",
|
||||
"X__",
|
||||
"XX_",
|
||||
"X__",
|
||||
"X__")),
|
||||
G(
|
||||
'G',
|
||||
Arrays.asList(
|
||||
"XXX",
|
||||
"X__",
|
||||
"X__",
|
||||
"X_X",
|
||||
"XXX")),
|
||||
H(
|
||||
'H',
|
||||
Arrays.asList(
|
||||
"X_X",
|
||||
"X_X",
|
||||
"XXX",
|
||||
"X_X",
|
||||
"X_X")),
|
||||
I(
|
||||
'I',
|
||||
Arrays.asList(
|
||||
"XXX",
|
||||
"_X_",
|
||||
"_X_",
|
||||
"_X_",
|
||||
"XXX")),
|
||||
J(
|
||||
'J',
|
||||
Arrays.asList(
|
||||
"__X",
|
||||
"__X",
|
||||
"__X",
|
||||
"X_X",
|
||||
"XXX")),
|
||||
K(
|
||||
'K',
|
||||
Arrays.asList(
|
||||
"X_X",
|
||||
"X_X",
|
||||
"XX_",
|
||||
"X_X",
|
||||
"X_X")),
|
||||
L(
|
||||
'L',
|
||||
Arrays.asList(
|
||||
"X__",
|
||||
"X__",
|
||||
"X__",
|
||||
"X__",
|
||||
"XXX")),
|
||||
M(
|
||||
'M',
|
||||
Arrays.asList(
|
||||
"X_X",
|
||||
"XXX",
|
||||
"X_X",
|
||||
"X_X",
|
||||
"X_X")),
|
||||
N(
|
||||
'N',
|
||||
Arrays.asList(
|
||||
"X__X",
|
||||
"XX_X",
|
||||
"X_XX",
|
||||
"X__X",
|
||||
"X__X")),
|
||||
O(
|
||||
'O',
|
||||
Arrays.asList(
|
||||
"XXX",
|
||||
"X_X",
|
||||
"X_X",
|
||||
"X_X",
|
||||
"XXX")),
|
||||
P(
|
||||
'P',
|
||||
Arrays.asList(
|
||||
"XXX",
|
||||
"X_X",
|
||||
"XXX",
|
||||
"X__",
|
||||
"X__")),
|
||||
Q(
|
||||
'Q',
|
||||
Arrays.asList(
|
||||
"XXX",
|
||||
"X_X",
|
||||
"X_X",
|
||||
"XX_",
|
||||
"__X")),
|
||||
R(
|
||||
'R',
|
||||
Arrays.asList(
|
||||
"XXX",
|
||||
"X_X",
|
||||
"XX_",
|
||||
"X_X",
|
||||
"X_X")),
|
||||
S(
|
||||
'S',
|
||||
Arrays.asList(
|
||||
"XXX",
|
||||
"X__",
|
||||
"XXX",
|
||||
"__X",
|
||||
"XXX")),
|
||||
T(
|
||||
'T',
|
||||
Arrays.asList(
|
||||
"XXX",
|
||||
"_X_",
|
||||
"_X_",
|
||||
"_X_",
|
||||
"_X_")),
|
||||
U(
|
||||
'U',
|
||||
Arrays.asList(
|
||||
"X_X",
|
||||
"X_X",
|
||||
"X_X",
|
||||
"X_X",
|
||||
"XXX")),
|
||||
V(
|
||||
'V',
|
||||
Arrays.asList(
|
||||
"X_X",
|
||||
"X_X",
|
||||
"X_X",
|
||||
"X_X",
|
||||
"_X_")),
|
||||
W(
|
||||
'W',
|
||||
Arrays.asList(
|
||||
"X_X",
|
||||
"X_X",
|
||||
"XXX",
|
||||
"XXX",
|
||||
"X_X")),
|
||||
X(
|
||||
'X',
|
||||
Arrays.asList(
|
||||
"X_X",
|
||||
"X_X",
|
||||
"_X_",
|
||||
"X_X",
|
||||
"X_X")),
|
||||
Y(
|
||||
'Y',
|
||||
Arrays.asList(
|
||||
"X_X",
|
||||
"X_X",
|
||||
"_X_",
|
||||
"_X_",
|
||||
"_X_")),
|
||||
Z(
|
||||
'Z',
|
||||
Arrays.asList(
|
||||
"XXX",
|
||||
"__X",
|
||||
"_X_",
|
||||
"X__",
|
||||
"XXX")),
|
||||
SPACE(
|
||||
' ',
|
||||
Arrays.asList(
|
||||
"_",
|
||||
"_",
|
||||
"_",
|
||||
"_",
|
||||
"_")),
|
||||
COLON(
|
||||
':',
|
||||
Arrays.asList(
|
||||
"_",
|
||||
"X",
|
||||
"_",
|
||||
"X",
|
||||
"_")),
|
||||
RIGHT_PARENTHESIS(
|
||||
')',
|
||||
Arrays.asList(
|
||||
"X_",
|
||||
"_X",
|
||||
"_X",
|
||||
"_X",
|
||||
"X_"));
|
||||
|
||||
private char letter;
|
||||
private List<String> lines = new ArrayList<>();
|
||||
private HashMap<Coordinate, ItemCreator> coordinates = new HashMap<>();
|
||||
private ItemCreator itemCreator;
|
||||
|
||||
Letter(char letter, List<String> lines) {
|
||||
this.letter = letter;
|
||||
this.lines = lines;
|
||||
this.coordinates = draw();
|
||||
}
|
||||
|
||||
Letter(char letter, List<String> lines, ItemCreator itemCreator) {
|
||||
this.letter = letter;
|
||||
this.lines = lines;
|
||||
this.itemCreator = itemCreator;
|
||||
this.coordinates = draw();
|
||||
}
|
||||
|
||||
public static Letter getLetter(char c) {
|
||||
for (Letter letter : values()) {
|
||||
if (letter.getLetter() == c) {
|
||||
return letter;
|
||||
}
|
||||
}
|
||||
return A;
|
||||
}
|
||||
|
||||
public static double getLength(String text) {
|
||||
double length = 0;
|
||||
for (char c : text.toCharArray()) {
|
||||
length = length + Letter.getLetter(c).getLength();
|
||||
if (c != ' ') {
|
||||
length = length + 1;
|
||||
} else {
|
||||
length = length + 2;
|
||||
}
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
public HashMap<Coordinate, ItemCreator> draw() {
|
||||
HashMap<Coordinate, ItemCreator> map = new HashMap<>();
|
||||
int currentX = 0;
|
||||
int currentY = 0;
|
||||
for (String line : getLines()) {
|
||||
for (char c : line.toCharArray()) {
|
||||
Coordinate coordinate = new Coordinate(currentX, currentY);
|
||||
ItemCreator itemCreator = c == '_' ? new ItemCreator(Material.AIR) : getItemCreator();
|
||||
map.put(coordinate, itemCreator);
|
||||
currentX++;
|
||||
}
|
||||
currentX = 0;
|
||||
currentY--;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public HashMap<Coordinate, ItemCreator> getCoordinates() {
|
||||
return this.coordinates;
|
||||
}
|
||||
|
||||
public char getLetter() {
|
||||
return this.letter;
|
||||
}
|
||||
|
||||
public List<String> getLines() {
|
||||
return this.lines;
|
||||
}
|
||||
|
||||
public ItemCreator getItemCreator() {
|
||||
return this.itemCreator;
|
||||
}
|
||||
|
||||
public double getHeight() {
|
||||
return getLines().size();
|
||||
/*double lowestPoint = 0;
|
||||
double highestPoint = 0;
|
||||
for (Coordinate coordinate : getCoordinates().keySet()) {
|
||||
if (coordinate.getY() < lowestPoint) {
|
||||
lowestPoint = coordinate.getY();
|
||||
} else if (coordinate.getY() > highestPoint) {
|
||||
highestPoint = coordinate.getY();
|
||||
}
|
||||
}
|
||||
return Math.abs(highestPoint - lowestPoint) + 1;*/
|
||||
}
|
||||
|
||||
public double getLength() {
|
||||
return getLines().get(0).length();
|
||||
/*double leftmostPoint = 0;
|
||||
double rightmostPoint = 0;
|
||||
for (Coordinate coordinate : getCoordinates().keySet()) {
|
||||
if (coordinate.getX() <= leftmostPoint) {
|
||||
leftmostPoint = coordinate.getX();
|
||||
} else if (coordinate.getX() >= rightmostPoint) {
|
||||
rightmostPoint = coordinate.getX();
|
||||
}
|
||||
}
|
||||
return Math.abs(leftmostPoint - rightmostPoint) + 1;*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -144,6 +144,8 @@ public class LoginListener implements Listener, PluginFacet {
|
|||
final Player player = event.getPlayer();
|
||||
final UUID uuid = player.getUniqueId();
|
||||
|
||||
player.setGravity(true);
|
||||
|
||||
this.logins.cleanUp();
|
||||
final LoginResponse response = this.logins.getIfPresent(uuid);
|
||||
this.logins.invalidate(uuid);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package tc.oc.commons.bukkit.nick;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -27,11 +29,14 @@ import org.bukkit.permissions.PermissionAttachment;
|
|||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import tc.oc.api.bukkit.users.BukkitUserStore;
|
||||
import tc.oc.api.bukkit.users.OnlinePlayers;
|
||||
import tc.oc.api.docs.PlayerId;
|
||||
import tc.oc.api.docs.User;
|
||||
import tc.oc.api.docs.virtual.UserDoc;
|
||||
import tc.oc.api.exceptions.UnprocessableEntity;
|
||||
import tc.oc.commons.core.commands.TranslatableCommandException;
|
||||
import tc.oc.commons.core.formatting.PeriodFormats;
|
||||
import tc.oc.minecraft.scheduler.SyncExecutor;
|
||||
import tc.oc.api.users.UserService;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
|
@ -58,9 +63,11 @@ public class NicknameCommands implements Listener, Commands {
|
|||
public static final String PERMISSION_ANY = PERMISSION + ".any";
|
||||
public static final String PERMISSION_ANY_SET = PERMISSION_ANY + ".set";
|
||||
public static final String PERMISSION_ANY_GET = PERMISSION_ANY + ".get";
|
||||
public static final String PERMISSION_UNLIMITED = PERMISSION + ".unlimited";
|
||||
|
||||
private final NicknameConfiguration config;
|
||||
private final SyncExecutor syncExecutor;
|
||||
private final BukkitUserStore userStore;
|
||||
private final UserService userService;
|
||||
private final Audiences audiences;
|
||||
private final IdentityProvider identities;
|
||||
|
@ -71,6 +78,7 @@ public class NicknameCommands implements Listener, Commands {
|
|||
|
||||
@Inject NicknameCommands(NicknameConfiguration config,
|
||||
SyncExecutor syncExecutor,
|
||||
BukkitUserStore userStore,
|
||||
UserService userService,
|
||||
Audiences audiences,
|
||||
IdentityProvider identities,
|
||||
|
@ -80,6 +88,7 @@ public class NicknameCommands implements Listener, Commands {
|
|||
Plugin plugin) {
|
||||
this.config = config;
|
||||
this.syncExecutor = syncExecutor;
|
||||
this.userStore = userStore;
|
||||
this.userService = userService;
|
||||
this.audiences = audiences;
|
||||
this.identities = identities;
|
||||
|
@ -99,7 +108,8 @@ public class NicknameCommands implements Listener, Commands {
|
|||
PERMISSION_ANY,
|
||||
PERMISSION_ANY_GET,
|
||||
PERMISSION_ANY_SET,
|
||||
PERMISSION_IMMEDIATE
|
||||
PERMISSION_IMMEDIATE,
|
||||
PERMISSION_UNLIMITED
|
||||
).forEach(name -> {
|
||||
final Permission permission = new Permission(name, PermissionDefault.FALSE);
|
||||
pluginManager.addPermission(permission);
|
||||
|
@ -121,6 +131,17 @@ public class NicknameCommands implements Listener, Commands {
|
|||
if(immediate) {
|
||||
CommandUtils.assertPermission(sender, PERMISSION_IMMEDIATE);
|
||||
}
|
||||
|
||||
if(sender instanceof Player) {
|
||||
Instant updatedAt = userStore.getUser((Player) sender).nickname_updated_at();
|
||||
Instant nextAt = updatedAt == null ? Instant.now() : updatedAt.plus(Duration.ofDays(1));
|
||||
if(!sender.hasPermission(PERMISSION_UNLIMITED) && nextAt.isAfter(Instant.now())) {
|
||||
throw new TranslatableCommandException(
|
||||
"command.nick.mustWait",
|
||||
PeriodFormats.relativeFutureApproximate(nextAt)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
|
|
|
@ -4,16 +4,23 @@ import javax.annotation.Nullable;
|
|||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import org.bukkit.Skin;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
import org.bukkit.scoreboard.Team;
|
||||
import tc.oc.commons.bukkit.chat.FlairRenderer;
|
||||
import tc.oc.commons.bukkit.flairs.FlairConfiguration;
|
||||
import tc.oc.commons.bukkit.flairs.FlairRenderer;
|
||||
import tc.oc.commons.bukkit.chat.FullNameRenderer;
|
||||
import tc.oc.commons.bukkit.chat.NameStyle;
|
||||
import tc.oc.commons.bukkit.chat.NameType;
|
||||
import tc.oc.commons.core.scheduler.Scheduler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Manages the Bukkit aspects of a player's name and appearance
|
||||
*/
|
||||
|
@ -24,20 +31,27 @@ public class PlayerAppearanceChanger {
|
|||
private static final NameType NICKNAME_TYPE = new NameType(NameStyle.VERBOSE, true, false, false, false, false);
|
||||
|
||||
private final IdentityProvider identityProvider;
|
||||
private final NicknameConfiguration config;
|
||||
private final FlairConfiguration flairConfig;
|
||||
private final Scheduler scheduler;
|
||||
private final FullNameRenderer nameRenderer;
|
||||
private final UsernameRenderer usernameRenderer;
|
||||
private final FlairRenderer flairRenderer;
|
||||
private final Map<String, Skin> skinAssigned;
|
||||
private final Cache<Skin, Integer> skinPool;
|
||||
|
||||
@Inject
|
||||
PlayerAppearanceChanger(IdentityProvider identityProvider, NicknameConfiguration config, Scheduler scheduler, FullNameRenderer nameRenderer, UsernameRenderer usernameRenderer, FlairRenderer flairRenderer) {
|
||||
PlayerAppearanceChanger(IdentityProvider identityProvider, FlairConfiguration flairConfig, Scheduler scheduler, FullNameRenderer nameRenderer, UsernameRenderer usernameRenderer, FlairRenderer flairRenderer) {
|
||||
this.identityProvider = identityProvider;
|
||||
this.config = config;
|
||||
this.flairConfig = flairConfig;
|
||||
this.scheduler = scheduler;
|
||||
this.nameRenderer = nameRenderer;
|
||||
this.usernameRenderer = usernameRenderer;
|
||||
this.flairRenderer = flairRenderer;
|
||||
this.skinAssigned = new HashMap<>();
|
||||
this.skinPool = CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(1, TimeUnit.HOURS)
|
||||
.maximumSize(30)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,7 +74,7 @@ public class PlayerAppearanceChanger {
|
|||
refreshFakeNameAndSkin(player, identity, legacyNickname, viewer);
|
||||
}
|
||||
|
||||
if(config.overheadFlair()) {
|
||||
if(flairConfig.overheadFlair()) {
|
||||
String prefix = usernameRenderer.getColor(identity, REAL_NAME_TYPE).toString();
|
||||
if(identity.getNickname() == null) {
|
||||
prefix = flairRenderer.getLegacyName(identity, REAL_NAME_TYPE) + prefix;
|
||||
|
@ -83,7 +97,9 @@ public class PlayerAppearanceChanger {
|
|||
* Release any resources being used to maintain the given player's appearance
|
||||
*/
|
||||
public void cleanupAfterPlayer(Player player) {
|
||||
if(config.overheadFlair()) {
|
||||
skinPool.put(player.getRealSkin(), flairRenderer.getNumberOfFlairs(identityProvider.createIdentity(player)));
|
||||
|
||||
if(flairConfig.overheadFlair()) {
|
||||
// Remove players from their "overhead flair team" on quit
|
||||
final Team team = player.getServer().getScoreboardManager().getMainScoreboard().getPlayerTeam(player);
|
||||
if(team != null) {
|
||||
|
@ -100,7 +116,7 @@ public class PlayerAppearanceChanger {
|
|||
player.setFakeNameAndSkin(viewer, null, null);
|
||||
player.setFakeDisplayName(viewer, null);
|
||||
} else {
|
||||
player.setFakeNameAndSkin(viewer, identity.getNickname(), Skin.EMPTY);
|
||||
player.setFakeNameAndSkin(viewer, identity.getNickname(), getRandomSkin(fakeDisplayName));
|
||||
player.setFakeDisplayName(viewer, fakeDisplayName);
|
||||
}
|
||||
}
|
||||
|
@ -125,4 +141,34 @@ public class PlayerAppearanceChanger {
|
|||
private @Nullable String renderLegacyNickname(Identity identity) {
|
||||
return identity.getNickname() == null ? null : nameRenderer.getLegacyName(identity, NICKNAME_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random skin from users that have recently disconnected.
|
||||
* Prioritize skins that come from players with fewer flairs.
|
||||
*/
|
||||
private Skin getRandomSkin(@Nullable String nickname) {
|
||||
Skin skin;
|
||||
if(skinAssigned.containsKey(nickname)) {
|
||||
skin = skinAssigned.get(nickname);
|
||||
} else {
|
||||
skin = skinPool.asMap()
|
||||
.entrySet()
|
||||
.stream()
|
||||
.sorted(Map.Entry.<Skin, Integer>comparingByValue()
|
||||
.reversed()
|
||||
.thenComparing(entry -> entry.getKey().hashCode()))
|
||||
.map(Map.Entry::getKey)
|
||||
.findAny()
|
||||
.orElse(null);
|
||||
if(skin != null) {
|
||||
skinPool.invalidate(skin);
|
||||
} else {
|
||||
skin = Skin.EMPTY;
|
||||
}
|
||||
if(nickname != null) {
|
||||
skinAssigned.put(nickname, skin);
|
||||
}
|
||||
}
|
||||
return skin;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import static tc.oc.api.docs.virtual.PunishmentDoc.Type;
|
|||
import static tc.oc.api.docs.virtual.PunishmentDoc.Type.*;
|
||||
import static tc.oc.commons.bukkit.commands.UserFinder.Default.NULL;
|
||||
import static tc.oc.commons.bukkit.commands.UserFinder.Default.SENDER;
|
||||
import static tc.oc.commons.bukkit.commands.UserFinder.Scope;
|
||||
import static tc.oc.commons.bukkit.punishment.PunishmentPermissions.fromFlag;
|
||||
import static tc.oc.commons.bukkit.punishment.PunishmentPermissions.fromType;
|
||||
|
||||
|
@ -90,9 +91,10 @@ public class PunishmentCommands implements Commands {
|
|||
final boolean auto = flag('a', args, sender);
|
||||
final boolean silent = flag('s', args, sender);
|
||||
final boolean offrecord = flag('o', args, sender);
|
||||
final Scope scope = punishmentCreator.offRecord() ? Scope.LOCAL : Scope.ALL;
|
||||
if(permission(sender, type)) {
|
||||
syncExecutor.callback(
|
||||
userFinder.findUser(sender, args, 0),
|
||||
userFinder.findUser(sender, args, 0, scope),
|
||||
response -> {
|
||||
punishmentCreator.create(
|
||||
punisher,
|
||||
|
|
|
@ -105,7 +105,9 @@ public class PunishmentEnforcer implements Enableable, MessageListener {
|
|||
break;
|
||||
}
|
||||
|
||||
punishmentService.update(punishment._id(), (PunishmentDoc.Enforce) () -> true);
|
||||
if(!punishment.off_record()) {
|
||||
punishmentService.update(punishment._id(), (PunishmentDoc.Enforce) () -> true);
|
||||
}
|
||||
}
|
||||
|
||||
private void announce(Punishment punishment) {
|
||||
|
@ -121,7 +123,7 @@ public class PunishmentEnforcer implements Enableable, MessageListener {
|
|||
public boolean viewable(CommandSender sender, Punishment punishment, boolean announced) {
|
||||
if(viewByIdentity(sender, punishment)) {
|
||||
if(announced) {
|
||||
return viewByType(sender, punishment) && viewBySetting(sender, punishment) && viewByIdentity(sender, punishment);
|
||||
return viewByType(sender, punishment) && viewBySetting(sender, punishment) && viewByIdentity(sender, punishment) && viewByRecord(sender, punishment);
|
||||
} else {
|
||||
return viewByLookup(sender, punishment);
|
||||
}
|
||||
|
@ -144,6 +146,13 @@ public class PunishmentEnforcer implements Enableable, MessageListener {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean viewByRecord(CommandSender sender, Punishment punishment) {
|
||||
if(punishment.off_record()) {
|
||||
return localServer._id().equals(punishment.server_id());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean viewByType(CommandSender sender, Punishment punishment) {
|
||||
switch(punishment.type()) {
|
||||
|
|
|
@ -65,7 +65,7 @@ public class PunishmentFormatter {
|
|||
|
||||
return ImmutableList.of(
|
||||
Components.join(Components.space(), parts),
|
||||
new Component(" > ").extra(new Component(punishment.reason(), ChatColor.YELLOW))
|
||||
new Component(" > ").extra(new Component(punishment.reason(), punishment.stale() ? ChatColor.GRAY : ChatColor.YELLOW))
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import me.anxuiz.settings.Setting;
|
|||
import me.anxuiz.settings.SettingBuilder;
|
||||
import me.anxuiz.settings.types.EnumType;
|
||||
import me.anxuiz.settings.types.Name;
|
||||
import org.bukkit.Material;
|
||||
import tc.oc.commons.bukkit.util.ItemCreator;
|
||||
|
||||
public class PunishmentMessageSetting {
|
||||
|
||||
|
|
|
@ -36,9 +36,9 @@ public class RaindropCommands implements Commands {
|
|||
}
|
||||
|
||||
@Command(
|
||||
aliases = {"raindrops", "rds"},
|
||||
aliases = {"droplets", "drp"},
|
||||
usage = "[player]",
|
||||
desc = "Shows the amount of raindrops that you have",
|
||||
desc = "Shows the amount of droplets that you have",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.bukkit.plugin.Plugin;
|
|||
import java.time.Duration;
|
||||
import tc.oc.api.bukkit.users.BukkitUserStore;
|
||||
import tc.oc.api.docs.PlayerId;
|
||||
import tc.oc.api.users.CreditTokensRequest;
|
||||
import tc.oc.api.users.UserService;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.util.NMSHacks;
|
||||
|
@ -103,7 +104,7 @@ public class RaindropUtil {
|
|||
if(save) {
|
||||
final int finalDelta = delta;
|
||||
playerExecutorFactory.queued(playerId).callback(
|
||||
userService.creditRaindrops(playerId, finalDelta),
|
||||
userService.creditTokens(playerId, CreditTokensRequest.raindrops(finalDelta)),
|
||||
(player, update) -> {
|
||||
if(update.success()) {
|
||||
showRaindrops(player, finalDelta, multiplier, reason, show);
|
||||
|
@ -156,7 +157,7 @@ public class RaindropUtil {
|
|||
private static BaseComponent raindropsMessage(int count, int multiplier, @Nullable BaseComponent reason) {
|
||||
Component message = new Component(ChatColor.GRAY);
|
||||
message.extra(new Component((count > 0 ? "+" : "") + count, ChatColor.GREEN, ChatColor.BOLD),
|
||||
new Component(" Raindrop" + (count == 1 || count == -1 ? "" : "s"), ChatColor.AQUA));
|
||||
new Component(" Droplet" + (count == 1 || count == -1 ? "" : "s"), ChatColor.AQUA));
|
||||
if(multiplier != 100) {
|
||||
message.extra(new Component(" | ", ChatColor.DARK_PURPLE),
|
||||
new Component((multiplier / 100f) + "x", ChatColor.GOLD, ChatColor.ITALIC));
|
||||
|
|
|
@ -17,6 +17,7 @@ import tc.oc.api.bukkit.users.BukkitUserStore;
|
|||
import tc.oc.api.bukkit.users.OnlinePlayers;
|
||||
import tc.oc.api.docs.Server;
|
||||
import tc.oc.api.docs.Session;
|
||||
import tc.oc.minecraft.protocol.MinecraftVersion;
|
||||
import tc.oc.minecraft.scheduler.SyncExecutor;
|
||||
import tc.oc.api.sessions.SessionService;
|
||||
import tc.oc.api.sessions.SessionStartRequest;
|
||||
|
@ -70,6 +71,11 @@ public class SessionListener implements Listener, PluginFacet {
|
|||
return player.getAddress().getAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String version() {
|
||||
return MinecraftVersion.describeProtocol(player.getProtocolVersion());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String previous_session_id() {
|
||||
return userStore.session(player)
|
||||
|
|
|
@ -3,6 +3,8 @@ package tc.oc.commons.bukkit.settings;
|
|||
import me.anxuiz.settings.Setting;
|
||||
import me.anxuiz.settings.SettingBuilder;
|
||||
import me.anxuiz.settings.types.BooleanType;
|
||||
import org.bukkit.Material;
|
||||
import tc.oc.commons.bukkit.util.ItemCreator;
|
||||
|
||||
/**
|
||||
* TODO: Not implemented yet
|
||||
|
@ -10,7 +12,7 @@ import me.anxuiz.settings.types.BooleanType;
|
|||
public class RemoteTeleport {
|
||||
private static final Setting inst = new SettingBuilder()
|
||||
.name("RemoteTeleport").alias("rtp")
|
||||
.summary("Allow /tp to teleport you across servers, just like /rtp")
|
||||
.summary("Allow /tp to move you across servers like /rtp")
|
||||
.type(new BooleanType())
|
||||
.defaultValue(true).get();
|
||||
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
package tc.oc.commons.bukkit.stats;
|
||||
|
||||
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 net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.chat.HeaderComponent;
|
||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||
import tc.oc.commons.bukkit.commands.UserFinder;
|
||||
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.CommandFutureCallback;
|
||||
import tc.oc.commons.core.commands.Commands;
|
||||
import tc.oc.minecraft.scheduler.SyncExecutor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class StatsCommands implements Commands {
|
||||
|
||||
private final SyncExecutor syncExecutor;
|
||||
private final UserFinder userFinder;
|
||||
private final Audiences audiences;
|
||||
private final IdentityProvider identityProvider;
|
||||
|
||||
@Inject
|
||||
StatsCommands(UserFinder userFinder, SyncExecutor executor, Audiences audiences, IdentityProvider identityProvider) {
|
||||
this.userFinder = userFinder;
|
||||
this.syncExecutor = executor;
|
||||
this.audiences = audiences;
|
||||
this.identityProvider = identityProvider;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "stats"},
|
||||
usage = "[player]",
|
||||
desc = "Shows a player's stats",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("projectares.stats")
|
||||
public void listStats(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
syncExecutor.callback(
|
||||
userFinder.findUser(sender, args, 0, UserFinder.Default.SENDER),
|
||||
CommandFutureCallback.onSuccess(sender, args, result -> {
|
||||
HashMap<String, Double> stats = StatsUtil.getStats(result.user);
|
||||
|
||||
Audience audience = audiences.get(sender);
|
||||
|
||||
audience.sendMessage(new HeaderComponent(new Component(ChatColor.AQUA)
|
||||
.translate("stats.list", new PlayerComponent(identityProvider.createIdentity(result)))));
|
||||
audience.sendMessage(new Component(ChatColor.AQUA)
|
||||
.translate("stats.kills", new Component(String.format("%,d", (int)(double)stats.get("kills")), ChatColor.BLUE)));
|
||||
audience.sendMessage(new Component(ChatColor.AQUA)
|
||||
.translate("stats.deaths", new Component(String.format("%,d", (int)(double)stats.get("deaths")), ChatColor.BLUE)));
|
||||
audience.sendMessage(new Component(ChatColor.AQUA)
|
||||
.translate("stats.kd", new Component(String.format("%.2f", stats.get("kd")), ChatColor.BLUE)));
|
||||
audience.sendMessage(new Component(ChatColor.AQUA)
|
||||
.translate("stats.wools", new Component(String.format("%,d", (int)(double)stats.get("wool_placed")), ChatColor.BLUE)));
|
||||
audience.sendMessage(new Component(ChatColor.AQUA)
|
||||
.translate("stats.cores", new Component(String.format("%,d", (int)(double)stats.get("cores_leaked")), ChatColor.BLUE)));
|
||||
audience.sendMessage(new Component(ChatColor.AQUA)
|
||||
.translate("stats.monuments", new Component(String.format("%,d", (int)(double)stats.get("destroyables_destroyed")), ChatColor.BLUE)));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package tc.oc.commons.bukkit.stats;
|
||||
|
||||
import tc.oc.commons.core.inject.HybridManifest;
|
||||
import tc.oc.commons.core.plugin.PluginFacetBinder;
|
||||
|
||||
public class StatsManifest extends HybridManifest {
|
||||
@Override
|
||||
protected void configure() {
|
||||
requestStaticInjection(StatsUtil.class);
|
||||
|
||||
new PluginFacetBinder(binder())
|
||||
.register(StatsCommands.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package tc.oc.commons.bukkit.stats;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import tc.oc.api.bukkit.users.BukkitUserStore;
|
||||
import tc.oc.api.docs.User;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class StatsUtil {
|
||||
|
||||
@Inject
|
||||
private static BukkitUserStore userStore;
|
||||
|
||||
public static HashMap<String, Double> getStats(Player player) {
|
||||
return getStats(userStore.getUser(player));
|
||||
}
|
||||
|
||||
public static HashMap<String, Double> getStats(User user) {
|
||||
HashMap<String, Double> map = new HashMap<>();
|
||||
|
||||
if (user.stats_value() != null) {
|
||||
Map<String, Map<String, Object>> statsCheck = user.stats_value().get("eternity");
|
||||
if (statsCheck != null) {
|
||||
Map<String, Object> stats = statsCheck.get("global");
|
||||
if (stats != null) {
|
||||
map.put("kills", getDoubleValue(stats.get("kills")));
|
||||
map.put("deaths", getDoubleValue(stats.get("deaths")));
|
||||
map.put("kd", getDoubleValue(stats.get("kd")));
|
||||
map.put("kk", getDoubleValue(stats.get("kk")));
|
||||
map.put("wool_placed", getDoubleValue(stats.get("wool_placed")));
|
||||
map.put("cores_leaked", getDoubleValue(stats.get("cores_leaked")));
|
||||
map.put("destroyables_destroyed", getDoubleValue(stats.get("destroyables_destroyed")));
|
||||
map.put("tkrate", getDoubleValue(stats.get("tkrate")));
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
||||
map.put("kills", 0.0);
|
||||
map.put("deaths", 0.0);
|
||||
map.put("kd", 0.0);
|
||||
map.put("kk", 0.0);
|
||||
map.put("wool_placed", 0.0);
|
||||
map.put("cores_leaked", 0.0);
|
||||
map.put("destroyables_destroyed", 0.0);
|
||||
map.put("tkrate", 0.0);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
private static Double getDoubleValue(Object value) {
|
||||
if (value == null) {
|
||||
return 0.0;
|
||||
}
|
||||
return (Double)value;
|
||||
}
|
||||
|
||||
}
|
|
@ -76,7 +76,7 @@ public class PlayerTabEntry extends DynamicTabEntry {
|
|||
@Override
|
||||
public @Nullable Skin getSkin(TabView view) {
|
||||
final Identity identity = identityProvider.currentIdentity(player);
|
||||
return identity.isDisguised(view.getViewer()) ? null : player.getSkin();
|
||||
return identity.isDisguised(view.getViewer()) ? player.getFakeSkin(view.getViewer()) : player.getSkin();
|
||||
}
|
||||
|
||||
// Dispatched by TabManager
|
||||
|
|
|
@ -14,6 +14,9 @@ import org.bukkit.entity.Player;
|
|||
import tc.oc.commons.bukkit.chat.ComponentRenderContext;
|
||||
import tc.oc.commons.bukkit.util.NMSHacks;
|
||||
|
||||
import static tc.oc.minecraft.protocol.MinecraftVersion.atLeast;
|
||||
import static tc.oc.minecraft.protocol.MinecraftVersion.MINECRAFT_1_8;
|
||||
|
||||
public class TabRender {
|
||||
|
||||
@Inject private static ComponentRenderContext componentRenderContext;
|
||||
|
@ -38,7 +41,10 @@ public class TabRender {
|
|||
}
|
||||
|
||||
private void send(Packet packet) {
|
||||
NMSHacks.sendPacket(this.view.getViewer(), packet);
|
||||
// Legacy players will be unable to see custom tab rendering code
|
||||
if(atLeast(MINECRAFT_1_8, this.view.getViewer().getProtocolVersion())) {
|
||||
NMSHacks.sendPacket(this.view.getViewer(), packet);
|
||||
}
|
||||
}
|
||||
|
||||
private PacketPlayOutPlayerInfo createPlayerInfoPacket(PacketPlayOutPlayerInfo.EnumPlayerInfoAction action) {
|
||||
|
|
|
@ -3,6 +3,7 @@ package tc.oc.commons.bukkit.teleport;
|
|||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
@ -13,8 +14,13 @@ import javax.inject.Inject;
|
|||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.inject.Singleton;
|
||||
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 net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import tc.oc.api.docs.Arena;
|
||||
import tc.oc.api.docs.Game;
|
||||
|
@ -27,12 +33,13 @@ import tc.oc.api.model.ModelListener;
|
|||
import tc.oc.api.servers.ServerStore;
|
||||
import tc.oc.commons.bukkit.format.GameFormatter;
|
||||
import tc.oc.commons.bukkit.ticket.TicketBooth;
|
||||
import tc.oc.commons.core.commands.Commands;
|
||||
import tc.oc.commons.core.plugin.PluginFacet;
|
||||
import tc.oc.commons.core.util.CacheUtils;
|
||||
import tc.oc.commons.core.util.Utils;
|
||||
|
||||
@Singleton
|
||||
public class Navigator implements PluginFacet, ModelListener {
|
||||
public class Navigator implements PluginFacet, ModelListener, Commands {
|
||||
|
||||
private static final char SERVER_SIGIL = '@';
|
||||
private static final char FAMILY_SIGIL = '.';
|
||||
|
@ -62,6 +69,31 @@ public class Navigator implements PluginFacet, ModelListener {
|
|||
modelDispatcher.subscribe(this);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "showcachedconnectors" },
|
||||
desc = "Print a list of cached connectors",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("ocn.developer")
|
||||
public void servers(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
sender.sendMessage("Cached Connectors:");
|
||||
final Map<String, SingleServerConnector> servers = serverConnectors.asMap();
|
||||
for (Map.Entry<String, SingleServerConnector> value : servers.entrySet()) {
|
||||
sender.sendMessage(value.getKey() + " : " + value.getValue().toString());
|
||||
}
|
||||
|
||||
final Map<String, FeaturedServerConnector> families = familyConnectors.asMap();
|
||||
for (Map.Entry<String, FeaturedServerConnector> value :families.entrySet()) {
|
||||
sender.sendMessage(value.getKey() + " : " + value.getValue().toString());
|
||||
}
|
||||
|
||||
final Map<String, GameConnector> games = gameConnectors.asMap();
|
||||
for (Map.Entry<String, GameConnector> value : games.entrySet()) {
|
||||
sender.sendMessage(value.getKey() + " : " + value.getValue().toString());
|
||||
}
|
||||
}
|
||||
|
||||
private String localDatacenter() {
|
||||
return featuredServerTracker.localDatacenter();
|
||||
}
|
||||
|
@ -212,7 +244,7 @@ public class Navigator implements PluginFacet, ModelListener {
|
|||
return server != null &&
|
||||
server.datacenter().equals(localDatacenter()) &&
|
||||
server.visibility() == ServerDoc.Visibility.PUBLIC &&
|
||||
server.running();
|
||||
server.online();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -13,11 +13,16 @@ import javax.inject.Singleton;
|
|||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
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 net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -51,6 +56,7 @@ import tc.oc.commons.bukkit.listeners.WindowManager;
|
|||
import tc.oc.commons.bukkit.ticket.TicketBooth;
|
||||
import tc.oc.commons.core.chat.Component;
|
||||
import tc.oc.commons.core.chat.Components;
|
||||
import tc.oc.commons.core.commands.Commands;
|
||||
import tc.oc.commons.core.inject.InnerFactory;
|
||||
import tc.oc.commons.core.plugin.PluginFacet;
|
||||
import tc.oc.minecraft.api.configuration.InvalidConfigurationException;
|
||||
|
@ -58,7 +64,7 @@ import tc.oc.minecraft.api.configuration.InvalidConfigurationException;
|
|||
import static tc.oc.commons.core.exception.LambdaExceptionUtils.rethrowFunction;
|
||||
|
||||
@Singleton
|
||||
public class NavigatorInterface implements PluginFacet, Listener {
|
||||
public class NavigatorInterface implements PluginFacet, Listener, Commands {
|
||||
|
||||
private final GameStore games;
|
||||
private final ServerFormatter serverFormatter = ServerFormatter.light;
|
||||
|
@ -103,6 +109,21 @@ public class NavigatorInterface implements PluginFacet, Listener {
|
|||
configFactory.create(this);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "shownavigatorbuttons" },
|
||||
desc = "Print a list of the buttons in the navigator",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("ocn.developer")
|
||||
public void servers(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
sender.sendMessage("Buttons:");
|
||||
for (Button button: buttons.values()) {
|
||||
sender.sendMessage(button.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setOpenButtonSlot(Slot.Player openButtonSlot) {
|
||||
this.openButtonSlot = openButtonSlot;
|
||||
}
|
||||
|
@ -248,6 +269,36 @@ public class NavigatorInterface implements PluginFacet, Listener {
|
|||
final Consumer<Navigator.Connector> observer = c ->
|
||||
openWindows.forEach(window -> updateWindow((Player) window.getPlayer(), window.getTopInventory()));
|
||||
|
||||
public String toString() {
|
||||
String string = "{";
|
||||
string += "slot: {" + slot.getColumn() + ", " + slot.getRow() + "}, ";
|
||||
string += "icon: " + icon.getType() + ", ";
|
||||
string += "connector: " + "{isConnectable: " + connector.isConnectable() + ", ";
|
||||
string += "isVisible: " + connector.isVisible() + ", ";
|
||||
if (connector instanceof Navigator.ServerConnector) {
|
||||
Server server = ((Navigator.ServerConnector)connector).server;
|
||||
string += "server: {";
|
||||
string += "bungee_name: " + server.bungee_name() + ", ";
|
||||
string += "box: " + server.box() + ", ";
|
||||
string += "datacenter: " + server.datacenter() + ", ";
|
||||
string += "family: " + server.family() + ", ";
|
||||
string += "description: " + server.description() + ", ";
|
||||
string += "ip: " + server.ip() + ", ";
|
||||
string += "name: " + server.name() + ", ";
|
||||
string += "max_players: " + server.max_players() + ", ";
|
||||
string += "num_online: " + server.num_online() + ", ";
|
||||
string += "_id: " + server._id() + ", ";
|
||||
string += "slug: " + server.slug() + ", ";
|
||||
string += "priority: " + server.priority() + ", ";
|
||||
string += "visibility: " + server.visibility() + ", ";
|
||||
string += "online: " + server.online() + ", ";
|
||||
string += "running: " + server.running();
|
||||
string += "}";
|
||||
}
|
||||
string += "}";
|
||||
return string;
|
||||
}
|
||||
|
||||
Button(ConfigurationSection config, ItemConfigurationParser itemParser) throws InvalidConfigurationException {
|
||||
this.slot = itemParser.needSlotByPosition(config, null, null, Slot.Container.class);
|
||||
this.icon = config.isString("skull") ? itemParser.needSkull(config, "skull")
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
package tc.oc.commons.bukkit.tokens;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.*;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.TranslatableComponent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||
import tc.oc.commons.bukkit.commands.UserFinder;
|
||||
import tc.oc.commons.bukkit.nick.IdentityProvider;
|
||||
import tc.oc.commons.bukkit.raindrops.RaindropUtil;
|
||||
import tc.oc.commons.core.chat.Component;
|
||||
import tc.oc.commons.core.commands.CommandFutureCallback;
|
||||
import tc.oc.commons.core.commands.Commands;
|
||||
import tc.oc.minecraft.scheduler.SyncExecutor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class TokenCommands implements Commands {
|
||||
private final UserFinder userFinder;
|
||||
private final SyncExecutor executor;
|
||||
private final Audiences audiences;
|
||||
private final IdentityProvider identityProvider;
|
||||
|
||||
@Inject
|
||||
TokenCommands(UserFinder userFinder, SyncExecutor executor, Audiences audiences, IdentityProvider identityProvider) {
|
||||
this.userFinder = userFinder;
|
||||
this.executor = executor;
|
||||
this.audiences = audiences;
|
||||
this.identityProvider = identityProvider;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = {"tokens"},
|
||||
usage = "[player]",
|
||||
desc = "Shows the amount of tokens that you have",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
public void tokens(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
executor.callback(
|
||||
userFinder.findUser(sender, args, 0, UserFinder.Default.SENDER),
|
||||
CommandFutureCallback.onSuccess(sender, args, result -> {
|
||||
final boolean self = sender instanceof Player && ((Player) sender).getUniqueId().equals(result.user.uuid());
|
||||
final int mapTokens = result.user.maptokens();
|
||||
audiences.get(sender).sendMessage(
|
||||
new Component(ChatColor.WHITE)
|
||||
.translate(self ? "maptokens.balance.self" : "maptokens.balance.other",
|
||||
new PlayerComponent(identityProvider.createIdentity(result)),
|
||||
new Component(String.format("%,d", mapTokens), ChatColor.AQUA),
|
||||
new TranslatableComponent(Math.abs(mapTokens) == 1 ? "maptokens.singular" : "maptokens.plural"))
|
||||
);
|
||||
final int mutationTokens = result.user.mutationtokens();
|
||||
audiences.get(sender).sendMessage(
|
||||
new Component(ChatColor.WHITE)
|
||||
.translate(self ? "mutationtokens.balance.self" : "mutationtokens.balance.other",
|
||||
new PlayerComponent(identityProvider.createIdentity(result)),
|
||||
new Component(String.format("%,d", mutationTokens), ChatColor.AQUA),
|
||||
new TranslatableComponent(Math.abs(mutationTokens) == 1 ? "mutationtokens.singular" : "mutationtokens.plural"))
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Command(
|
||||
aliases = {"givetokens"},
|
||||
usage = "[player] [setnext|mutation] [count]",
|
||||
desc = "gives a player tokens",
|
||||
min = 3,
|
||||
max = 3
|
||||
)
|
||||
@CommandPermissions("tokens.give")
|
||||
public void givetokens(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
int numberOfTokens = args.getInteger(2);
|
||||
executor.callback(
|
||||
userFinder.findUser(sender, args, 0, UserFinder.Default.SENDER),
|
||||
CommandFutureCallback.onSuccess(sender, args, result -> {
|
||||
result.user.player_id();
|
||||
String type = args.getString(1).toLowerCase();
|
||||
if (type.equals("setnext") || type.equals("map")) {
|
||||
TokenUtil.giveMapTokens(result.user, numberOfTokens);
|
||||
} else if (type.equals("mutation") || type.equals("mt")) {
|
||||
TokenUtil.giveMutationTokens(result.user, numberOfTokens);
|
||||
} else if (type.equals("droplets") || type.equals("raindrops") || type.equals("rds")) {
|
||||
RaindropUtil.giveRaindrops(result.user, numberOfTokens, null);
|
||||
} else {
|
||||
throw new CommandUsageException(ChatColor.RED + "/givetokens [player] [setnext|mutation] [count]");
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package tc.oc.commons.bukkit.tokens;
|
||||
|
||||
import tc.oc.commons.core.inject.HybridManifest;
|
||||
import tc.oc.commons.core.plugin.PluginFacetBinder;
|
||||
|
||||
public class TokenManifest extends HybridManifest {
|
||||
@Override
|
||||
protected void configure() {
|
||||
requestStaticInjection(TokenUtil.class);
|
||||
|
||||
new PluginFacetBinder(binder())
|
||||
.register(TokenCommands.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package tc.oc.commons.bukkit.tokens;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import tc.oc.api.bukkit.users.BukkitUserStore;
|
||||
import tc.oc.api.docs.PlayerId;
|
||||
import tc.oc.api.users.CreditTokensRequest;
|
||||
import tc.oc.api.users.UserService;
|
||||
import tc.oc.commons.bukkit.util.SyncPlayerExecutorFactory;
|
||||
import tc.oc.api.docs.User;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class TokenUtil {
|
||||
|
||||
@Inject
|
||||
private static BukkitUserStore userStore;
|
||||
@Inject
|
||||
private static UserService userService;
|
||||
@Inject
|
||||
private static SyncPlayerExecutorFactory playerExecutorFactory;
|
||||
|
||||
public static User getUser(Player player) {
|
||||
return userStore.getUser(player);
|
||||
}
|
||||
|
||||
public static void giveMapTokens(PlayerId playerId, int count) {
|
||||
playerExecutorFactory.queued(playerId).callback(
|
||||
userService.creditTokens(playerId, CreditTokensRequest.maps(count)),
|
||||
(player, update) -> {}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public static void giveMutationTokens(PlayerId playerId, int count) {
|
||||
playerExecutorFactory.queued(playerId).callback(
|
||||
userService.creditTokens(playerId, CreditTokensRequest.mutations(count)),
|
||||
(player, update) -> {}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -36,6 +36,7 @@ import tc.oc.api.sessions.SessionChange;
|
|||
import tc.oc.commons.bukkit.chat.Audiences;
|
||||
import tc.oc.commons.bukkit.chat.NameStyle;
|
||||
import tc.oc.commons.bukkit.chat.PlayerComponent;
|
||||
import tc.oc.commons.bukkit.event.UserLoginEvent;
|
||||
import tc.oc.commons.bukkit.format.ServerFormatter;
|
||||
import tc.oc.commons.bukkit.nick.Identity;
|
||||
import tc.oc.commons.bukkit.nick.IdentityProvider;
|
||||
|
@ -152,8 +153,12 @@ public class JoinMessageAnnouncer implements MessageListener, Listener, PluginFa
|
|||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onJoin(PlayerJoinEvent event) {
|
||||
public void preJoin(PlayerJoinEvent event) {
|
||||
event.setJoinMessage(null);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onJoin(UserLoginEvent event) {
|
||||
final User user = userStore.getUser(event.getPlayer());
|
||||
final SessionChange change = pendingJoins.getIfPresent(user);
|
||||
if(change != null) {
|
||||
|
|
|
@ -4,7 +4,9 @@ import me.anxuiz.settings.Setting;
|
|||
import me.anxuiz.settings.SettingBuilder;
|
||||
import me.anxuiz.settings.types.EnumType;
|
||||
import me.anxuiz.settings.types.Name;
|
||||
import org.bukkit.Material;
|
||||
import tc.oc.commons.bukkit.nick.Familiarity;
|
||||
import tc.oc.commons.bukkit.util.ItemCreator;
|
||||
|
||||
public class JoinMessageSetting {
|
||||
private static final Setting inst = new SettingBuilder()
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package tc.oc.commons.bukkit.util;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
public enum Constants {
|
||||
|
||||
PREFIX(ChatColor.GOLD.toString() + ChatColor.BOLD),
|
||||
SUBTEXT(ChatColor.AQUA.toString()),
|
||||
CLICK(ChatColor.RED.toString() + ChatColor.BOLD),
|
||||
ERROR(ChatColor.RED.toString());
|
||||
|
||||
private final String location;
|
||||
|
||||
Constants(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return location;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,220 @@
|
|||
package tc.oc.commons.bukkit.util;
|
||||
|
||||
import net.minecraft.server.NBTTagCompound;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ItemCreator {
|
||||
|
||||
private Material material;
|
||||
private String name;
|
||||
private int size = 1;
|
||||
private int data = 0;
|
||||
private List<String> lore = new ArrayList<>();
|
||||
private Map<Enchantment, Integer> enchantments = new HashMap<>();
|
||||
private Color armorColor;
|
||||
private String skullOwner;
|
||||
private PotionEffect potionEffect;
|
||||
private List<HideFlag> hideFlags;
|
||||
private boolean unbreakable;
|
||||
|
||||
public ItemCreator(Material material) {
|
||||
setMaterial(material);
|
||||
setName(material.toString());
|
||||
}
|
||||
|
||||
public Material getMaterial() {
|
||||
return material;
|
||||
}
|
||||
|
||||
public ItemCreator setMaterial(Material material) {
|
||||
this.material = material;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ItemCreator setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public ItemCreator setSize(int size) {
|
||||
this.size = size;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public ItemCreator setData(int data) {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<String> getLore() {
|
||||
return lore;
|
||||
}
|
||||
|
||||
public ItemCreator setLore(String... lore) {
|
||||
this.lore.clear();
|
||||
this.lore.addAll(Arrays.asList(lore));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemCreator addLore(String... lore) {
|
||||
this.lore.addAll(Arrays.asList(lore));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemCreator clearLore() {
|
||||
this.lore.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Map<Enchantment, Integer> getEnchantments() {
|
||||
return enchantments;
|
||||
}
|
||||
|
||||
public ItemCreator addEnchantment(Enchantment enchantment, int level) {
|
||||
this.enchantments.put(enchantment, level);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemCreator removeEnchantments() {
|
||||
this.enchantments.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Color getArmorColor() {
|
||||
return armorColor;
|
||||
}
|
||||
|
||||
public ItemCreator setArmorColor(Color armorColor) {
|
||||
this.armorColor = armorColor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getSkullOwner() {
|
||||
return skullOwner;
|
||||
}
|
||||
|
||||
public ItemCreator setSkullOwner(String owner) {
|
||||
this.skullOwner = owner;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PotionEffect getPotionEffect() {
|
||||
return potionEffect;
|
||||
}
|
||||
|
||||
public ItemCreator setPotionEffect(PotionEffect potionEffect) {
|
||||
this.potionEffect = potionEffect;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean getUnbreakable() {
|
||||
return unbreakable;
|
||||
}
|
||||
|
||||
public ItemCreator setUnbreakable(boolean unbreakable) {
|
||||
this.unbreakable = unbreakable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public enum HideFlag {
|
||||
ENCHANTMENTS(1),
|
||||
ATTRIBUTES(2),
|
||||
UNBREAKABLE(4),
|
||||
CAN_DESTROY(8),
|
||||
CAN_PLACE_ON(16),
|
||||
OTHERS(32),
|
||||
ALL(ENCHANTMENTS.getValue() +
|
||||
ATTRIBUTES.getValue() +
|
||||
UNBREAKABLE.getValue() +
|
||||
CAN_DESTROY.getValue() +
|
||||
CAN_PLACE_ON.getValue() +
|
||||
OTHERS.getValue()
|
||||
);
|
||||
|
||||
private int value;
|
||||
|
||||
HideFlag(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public List<HideFlag> getHideFlags() {
|
||||
return hideFlags;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public ItemCreator setHideFlags(boolean all) {
|
||||
this.hideFlags = all ? Collections.singletonList(HideFlag.ALL) : Collections.emptyList();
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemCreator setHideFlags(HideFlag... hideFlags) {
|
||||
this.hideFlags = Arrays.asList(hideFlags);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStack create() {
|
||||
ItemStack item = new ItemStack(material, size, (short)data);
|
||||
if (!item.getType().equals(Material.AIR)) {
|
||||
net.minecraft.server.ItemStack nmsStack = CraftItemStack.asNMSCopy(item);
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
if (hideFlags != null && hideFlags.size() > 0) {
|
||||
int hideFlagValue = 0;
|
||||
for (HideFlag flag : getHideFlags()) {
|
||||
hideFlagValue += flag.getValue();
|
||||
}
|
||||
hideFlagValue = Math.max(1, Math.min(63, hideFlagValue));
|
||||
tag.setInt("HideFlags", hideFlagValue);
|
||||
}
|
||||
if (skullOwner != null) {
|
||||
tag.setString("SkullOwner", skullOwner);
|
||||
}
|
||||
nmsStack.setTag(tag);
|
||||
item = CraftItemStack.asBukkitCopy(nmsStack);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName(name);
|
||||
meta.setLore(lore);
|
||||
item.setItemMeta(meta);
|
||||
item.addUnsafeEnchantments(enchantments);
|
||||
if (armorColor != null) {
|
||||
LeatherArmorMeta armorMeta = (LeatherArmorMeta) item.getItemMeta();
|
||||
armorMeta.setColor(armorColor);
|
||||
item.setItemMeta(armorMeta);
|
||||
}
|
||||
if (potionEffect != null) {
|
||||
PotionMeta potionMeta = (PotionMeta) item.getItemMeta();
|
||||
potionMeta.setMainEffect(potionEffect.getType());
|
||||
potionMeta.addCustomEffect(potionEffect, false);
|
||||
item.setItemMeta(potionMeta);
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package tc.oc.commons.bukkit.util;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ObjectUtils {
|
||||
|
||||
public static <T> List<T> paginate(List<T> objects, int page, int pageLength) {
|
||||
if (objects.size() <= ((page - 1) * pageLength)) {
|
||||
return null;
|
||||
}
|
||||
int firstItem = ((page * pageLength) - pageLength);
|
||||
int lastItem = (firstItem + pageLength);
|
||||
int max = objects.size() <= lastItem ? objects.size() : lastItem;
|
||||
if (max < firstItem) {
|
||||
firstItem = max - 1;
|
||||
}
|
||||
return objects.subList(firstItem, max);
|
||||
}
|
||||
|
||||
}
|
|
@ -4,9 +4,11 @@ import me.anxuiz.settings.Setting;
|
|||
import me.anxuiz.settings.SettingBuilder;
|
||||
import me.anxuiz.settings.types.EnumType;
|
||||
import me.anxuiz.settings.types.Name;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import tc.oc.commons.bukkit.nick.Familiarity;
|
||||
import tc.oc.commons.bukkit.nick.Identity;
|
||||
import tc.oc.commons.bukkit.util.ItemCreator;
|
||||
|
||||
public class WhisperSettings {
|
||||
|
||||
|
@ -25,7 +27,8 @@ public class WhisperSettings {
|
|||
.name("PrivateMessages")
|
||||
.alias("msg").alias("message").alias("messages").alias("pm").alias("pmr")
|
||||
.description(description).type(enumType).defaultValue(defaultValue)
|
||||
.summary("Who can send you private messages").get();
|
||||
.summary("Who can send you private messages")
|
||||
.get();
|
||||
|
||||
public static Setting receive() {
|
||||
return recieve;
|
||||
|
@ -41,7 +44,7 @@ public class WhisperSettings {
|
|||
.name("PrivateMessageSounds")
|
||||
.alias("sounds").alias("pmsound").alias("pms")
|
||||
.description(description).type(enumType).defaultValue(defaultValue)
|
||||
.summary("Whether you hear a sound when you receive a private message").get();
|
||||
.summary("Hear a sound when you get a message").get();
|
||||
|
||||
public static Setting sound() {
|
||||
return sound;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue