Skip to content

Commit a822f5d

Browse files
committed
Finish implementing sponge support (Fixes #18)
1 parent 79e884e commit a822f5d

10 files changed

Lines changed: 401 additions & 16 deletions

File tree

bukkit/src/main/java/com/github/games647/changeskin/bukkit/commands/SetSkinCommand.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ private void setSkinUUID(CommandSender sender, Player receiverPayer, String targ
8383
}
8484

8585
plugin.sendMessage(sender, "skin-change-queue");
86-
8786
SkinDownloader skinDownloader = new SkinDownloader(plugin, sender, receiverPayer, uuid);
8887
Bukkit.getScheduler().runTaskAsynchronously(plugin, skinDownloader);
8988
} catch (IllegalArgumentException illegalArgumentException) {

bukkit/src/main/java/com/github/games647/changeskin/bukkit/tasks/NameResolver.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ public void run() {
4141
SkinData targetSkin = plugin.getStorage().getSkin(targetName);
4242
if (targetSkin != null) {
4343
onNameResolveDatabase(targetSkin);
44-
4544
return;
4645
}
4746

sponge/src/main/java/com/github/games647/changeskin/sponge/ChangeSkinSponge.java

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
import com.github.games647.changeskin.core.ChangeSkinCore;
44
import com.github.games647.changeskin.core.SkinStorage;
5+
import com.github.games647.changeskin.sponge.commands.SetSkinCommand;
6+
import com.github.games647.changeskin.sponge.commands.SkinInvalidateCommand;
7+
import com.google.common.cache.Cache;
8+
import com.google.common.cache.CacheBuilder;
59
import com.google.common.collect.Lists;
610
import com.google.common.io.Resources;
711
import com.google.inject.Inject;
@@ -10,32 +14,41 @@
1014
import java.io.FileOutputStream;
1115
import java.io.IOException;
1216
import java.util.List;
17+
import java.util.UUID;
18+
import java.util.concurrent.TimeUnit;
1319

1420
import ninja.leaping.configurate.ConfigurationNode;
1521
import ninja.leaping.configurate.yaml.YAMLConfigurationLoader;
1622

1723
import org.slf4j.Logger;
1824
import org.spongepowered.api.Game;
1925
import org.spongepowered.api.command.CommandManager;
26+
import org.spongepowered.api.command.CommandSource;
27+
import org.spongepowered.api.command.args.GenericArguments;
28+
import org.spongepowered.api.command.spec.CommandSpec;
2029
import org.spongepowered.api.config.DefaultConfig;
30+
import org.spongepowered.api.entity.living.player.Player;
2131
import org.spongepowered.api.event.Listener;
2232
import org.spongepowered.api.event.game.state.GameInitializationEvent;
2333
import org.spongepowered.api.event.game.state.GamePreInitializationEvent;
2434
import org.spongepowered.api.plugin.Plugin;
35+
import org.spongepowered.api.text.Text;
36+
import org.spongepowered.api.text.serializer.TextSerializers;
2537

2638
@Plugin(id = "changeskin", name = "ChangeSkin", version = "1.7"
2739
, url = "https://github.com/games647/ChangeSkin"
2840
, description = "Sponge plugin to change your skin server side")
2941
public class ChangeSkinSponge {
3042

3143
@Inject
32-
@DefaultConfig(sharedRoot = true)
44+
@DefaultConfig(sharedRoot = false)
3345
//We will place more than one config there (i.e. H2/SQLite database)
3446
private File defaultConfigFile;
3547

3648
private final Logger logger;
3749
private final Game game;
3850

51+
private Cache<UUID, Object> cooldowns;
3952
private ChangeSkinCore core;
4053
private ConfigurationNode rootNode;
4154

@@ -92,11 +105,15 @@ public void onPreInit(GamePreInitializationEvent preInitEvent) {
92105
}
93106

94107
List<String> defaultSkins = Lists.newArrayList();
95-
rootNode.getNode("default-skins").getChildrenList().stream()
96-
.forEach((configurationNode) -> defaultSkins.add(configurationNode.getString()));
108+
for (ConfigurationNode node : rootNode.getNode("default-skins").getChildrenMap().values()) {
109+
defaultSkins.add(node.getString());
110+
}
97111

98112
core.loadDefaultSkins(defaultSkins);
99113
loadLocale();
114+
115+
int cooldown = rootNode.getNode("cooldown").getInt();
116+
cooldowns = CacheBuilder.newBuilder().expireAfterWrite(cooldown, TimeUnit.SECONDS).build();
100117
} catch (IOException ioEx) {
101118
logger.error("Failed to load config", ioEx);
102119
}
@@ -105,21 +122,52 @@ public void onPreInit(GamePreInitializationEvent preInitEvent) {
105122
@Listener //command and event register
106123
public void onInit(GameInitializationEvent initEvent) {
107124
CommandManager commandManager = game.getCommandManager();
108-
// commandManager.register(this, CommandSpec.builder()
109-
// .executor(new SetSkinCommand(this))
110-
// .arguments(GenericArguments.string(Text.of("skin"))
111-
// , GenericArguments.optional(GenericArguments.string(Text.of("target"))))
112-
// .build(), "changeskin");
125+
commandManager.register(this, CommandSpec.builder()
126+
.executor(new SetSkinCommand(this))
127+
.arguments(GenericArguments.string(Text.of("skin")))
128+
.build(), "changeskin", "setskin");
113129

114-
// commandManager.register(this, CommandSpec.builder()
115-
// .executor(new SkinInvalidateCommand(this))
116-
// .build(), "skininvalidate");
130+
commandManager.register(this, CommandSpec.builder()
131+
.executor(new SkinInvalidateCommand(this))
132+
.build(), "skininvalidate");
117133

118134
game.getEventManager().registerListeners(this, new LoginListener(this));
119135
}
120136

121137
private void loadLocale() {
122-
//todo
138+
File messageFile = new File(defaultConfigFile.getParentFile(), "messages.yml");
139+
140+
if (!messageFile.exists()) {
141+
FileOutputStream fileOutputStream = null;
142+
try {
143+
fileOutputStream = new FileOutputStream(messageFile);
144+
Resources.copy(getClass().getResource("/messages.yml"), fileOutputStream);
145+
} catch (IOException ioEx) {
146+
logger.error("Error deploying default message", ioEx);
147+
} finally {
148+
if (fileOutputStream != null) {
149+
try {
150+
fileOutputStream.close();
151+
} catch (IOException ex) {
152+
//ignore
153+
}
154+
}
155+
}
156+
}
157+
158+
YAMLConfigurationLoader messageLoader = YAMLConfigurationLoader.builder().setFile(messageFile).build();
159+
try {
160+
ConfigurationNode messageNode = messageLoader.load();
161+
for (ConfigurationNode node : messageNode.getChildrenMap().values()) {
162+
core.addMessage((String) node.getKey(), node.getString());
163+
}
164+
165+
for (ConfigurationNode configurationNode : messageNode.getChildrenList()) {
166+
167+
}
168+
} catch (IOException ioEx) {
169+
logger.error("Failed to load locale", ioEx);
170+
}
123171
}
124172

125173
public ChangeSkinCore getCore() {
@@ -130,6 +178,27 @@ public ConfigurationNode getRootNode() {
130178
return rootNode;
131179
}
132180

181+
public boolean isCooldown(CommandSource sender) {
182+
if (sender instanceof Player) {
183+
return cooldowns.asMap().containsKey(((Player) sender).getUniqueId());
184+
}
185+
186+
return false;
187+
}
188+
189+
public void sendMessage(CommandSource sender, String key) {
190+
String message = core.getMessage(key);
191+
if (message != null && sender != null) {
192+
sender.sendMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(message.replace('&', '§')));
193+
}
194+
}
195+
196+
public void addCooldown(CommandSource sender) {
197+
if (sender instanceof Player) {
198+
cooldowns.put(((Player) sender).getUniqueId(), new Object());
199+
}
200+
}
201+
133202
public Game getGame() {
134203
return game;
135204
}

sponge/src/main/java/com/github/games647/changeskin/sponge/LoginListener.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public void onPlayerPreLogin(ClientConnectionEvent.Auth preLoginEvent) {
3636
if (preferences.getTargetSkin() == null
3737
&& (!plugin.getRootNode().getNode("restoreSkins").getBoolean() || !refetch(preferences, profile))) {
3838
setDefaultSkin(preferences, profile);
39+
} else {
40+
applySkin(preferences.getTargetSkin(), profile);
3941
}
4042
}
4143

sponge/src/main/java/com/github/games647/changeskin/sponge/commands/SetSkinCommand.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
package com.github.games647.changeskin.sponge.commands;
22

33
import com.github.games647.changeskin.sponge.ChangeSkinSponge;
4+
import com.github.games647.changeskin.sponge.tasks.NameResolver;
5+
import com.github.games647.changeskin.sponge.tasks.SkinDownloader;
6+
7+
import java.util.UUID;
48

59
import org.spongepowered.api.command.CommandException;
610
import org.spongepowered.api.command.CommandResult;
711
import org.spongepowered.api.command.CommandSource;
812
import org.spongepowered.api.command.args.CommandContext;
913
import org.spongepowered.api.command.spec.CommandExecutor;
14+
import org.spongepowered.api.entity.living.player.Player;
1015

1116
public class SetSkinCommand implements CommandExecutor {
1217

@@ -18,6 +23,36 @@ public SetSkinCommand(ChangeSkinSponge plugin) {
1823

1924
@Override
2025
public CommandResult execute(CommandSource src, CommandContext args) throws CommandException {
21-
throw new UnsupportedOperationException("Not supported yet.");
26+
if (!(src instanceof Player)) {
27+
plugin.sendMessage(src, "no-console");
28+
return CommandResult.empty();
29+
}
30+
31+
if (plugin.isCooldown(src)) {
32+
plugin.sendMessage(src, "cooldown");
33+
return CommandResult.empty();
34+
}
35+
36+
Player receiver = (Player) src;
37+
String targetSkin = args.<String>getOne("skin").get();
38+
if (targetSkin.equals("reset")) {
39+
targetSkin = receiver.getUniqueId().toString();
40+
}
41+
42+
if (targetSkin.length() > 16) {
43+
UUID targetUUID = UUID.fromString(targetSkin);
44+
45+
plugin.sendMessage(src, "skin-change-queue");
46+
plugin.getGame().getScheduler().createTaskBuilder()
47+
.execute(new SkinDownloader(plugin, src, receiver, targetUUID))
48+
.submit(plugin);
49+
return CommandResult.success();
50+
}
51+
52+
plugin.sendMessage(src, "queue-name-resolve");
53+
plugin.getGame().getScheduler().createTaskBuilder()
54+
.execute(new NameResolver(plugin, src, targetSkin, receiver))
55+
.submit(plugin);
56+
return CommandResult.success();
2257
}
2358
}

sponge/src/main/java/com/github/games647/changeskin/sponge/commands/SkinInvalidateCommand.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package com.github.games647.changeskin.sponge.commands;
22

33
import com.github.games647.changeskin.sponge.ChangeSkinSponge;
4+
import com.github.games647.changeskin.sponge.tasks.SkinInvalidater;
45

56
import org.spongepowered.api.command.CommandException;
67
import org.spongepowered.api.command.CommandResult;
78
import org.spongepowered.api.command.CommandSource;
89
import org.spongepowered.api.command.args.CommandContext;
910
import org.spongepowered.api.command.spec.CommandExecutor;
11+
import org.spongepowered.api.entity.living.player.Player;
1012

1113
public class SkinInvalidateCommand implements CommandExecutor {
1214

@@ -18,6 +20,14 @@ public SkinInvalidateCommand(ChangeSkinSponge plugin) {
1820

1921
@Override
2022
public CommandResult execute(CommandSource src, CommandContext args) throws CommandException {
21-
throw new UnsupportedOperationException("Not supported yet.");
23+
if (!(src instanceof Player)) {
24+
plugin.sendMessage(src, "no-console");
25+
return CommandResult.empty();
26+
}
27+
28+
Player receiver = (Player) src;
29+
plugin.getGame().getScheduler().createTaskBuilder().async()
30+
.execute(new SkinInvalidater(plugin, receiver)).submit(plugin);
31+
return CommandResult.success();
2232
}
2333
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package com.github.games647.changeskin.sponge.tasks;
2+
3+
import com.github.games647.changeskin.core.NotPremiumException;
4+
import com.github.games647.changeskin.core.RateLimitException;
5+
import com.github.games647.changeskin.core.SkinData;
6+
import com.github.games647.changeskin.sponge.ChangeSkinSponge;
7+
8+
import java.util.UUID;
9+
10+
import org.spongepowered.api.command.CommandSource;
11+
import org.spongepowered.api.entity.living.player.Player;
12+
13+
public class NameResolver implements Runnable {
14+
15+
private final ChangeSkinSponge plugin;
16+
private final CommandSource invoker;
17+
private final String targetName;
18+
private final Player receiver;
19+
20+
public NameResolver(ChangeSkinSponge plugin, CommandSource invoker, String targetName, Player receiver) {
21+
this.plugin = plugin;
22+
this.invoker = invoker;
23+
this.targetName = targetName;
24+
this.receiver = receiver;
25+
}
26+
27+
@Override
28+
public void run() {
29+
UUID uuid = plugin.getCore().getUuidCache().get(targetName);
30+
if (uuid == null) {
31+
if (plugin.getCore().getCrackedNames().containsKey(targetName)) {
32+
if (invoker != null) {
33+
plugin.sendMessage(invoker, "not-premium");
34+
}
35+
36+
return;
37+
}
38+
39+
SkinData targetSkin = plugin.getCore().getStorage().getSkin(targetName);
40+
if (targetSkin != null) {
41+
onNameResolveDatabase(targetSkin);
42+
return;
43+
}
44+
45+
try {
46+
uuid = plugin.getCore().getUUID(targetName);
47+
if (uuid == null) {
48+
if (invoker != null) {
49+
plugin.sendMessage(invoker, "no-resolve");
50+
}
51+
} else {
52+
plugin.getCore().getUuidCache().put(targetName, uuid);
53+
onNameResolve(uuid);
54+
}
55+
} catch (NotPremiumException notPremiumEx) {
56+
plugin.getLogger().debug("Requested not premium", notPremiumEx);
57+
plugin.getCore().getCrackedNames().put(targetName, new Object());
58+
59+
if (invoker != null) {
60+
plugin.sendMessage(invoker, "not-premium");
61+
}
62+
} catch (RateLimitException rateLimitEx) {
63+
plugin.getLogger().error("UUID Rate Limit reached", rateLimitEx);
64+
if (invoker != null) {
65+
plugin.sendMessage(invoker, "rate-limit");
66+
}
67+
}
68+
} else {
69+
onNameResolve(uuid);
70+
}
71+
}
72+
73+
private void onNameResolveDatabase(SkinData targetSkin) {
74+
if (invoker != null) {
75+
plugin.sendMessage(invoker, "uuid-resolved");
76+
plugin.sendMessage(invoker, "skin-downloading");
77+
}
78+
79+
SkinUpdater skinUpdater = new SkinUpdater(plugin, invoker, receiver, targetSkin);
80+
plugin.getGame().getScheduler().createTaskBuilder().execute(skinUpdater).submit(plugin);
81+
}
82+
83+
private void onNameResolve(UUID uuid) {
84+
if (invoker != null) {
85+
plugin.sendMessage(invoker, "uuid-resolved");
86+
plugin.sendMessage(invoker, "skin-downloading");
87+
}
88+
89+
//run this is the same thread
90+
new SkinDownloader(plugin, invoker, receiver, uuid).run();
91+
}
92+
}

0 commit comments

Comments
 (0)