Skip to content

Commit cee374e

Browse files
committed
Initial commit, adds all plugin files
0 parents  commit cee374e

10 files changed

Lines changed: 487 additions & 0 deletions

File tree

pom.xml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>de.kcodeyt</groupId>
8+
<artifactId>HeadsDatabase</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
11+
<build>
12+
<plugins>
13+
<plugin>
14+
<groupId>org.apache.maven.plugins</groupId>
15+
<artifactId>maven-compiler-plugin</artifactId>
16+
<configuration>
17+
<source>8</source>
18+
<target>8</target>
19+
</configuration>
20+
</plugin>
21+
</plugins>
22+
</build>
23+
24+
<dependencies>
25+
<dependency>
26+
<groupId>de.kcodeyt</groupId>
27+
<artifactId>Heads</artifactId>
28+
<version>1.0-SNAPSHOT</version>
29+
</dependency>
30+
<dependency>
31+
<groupId>org.powernukkit</groupId>
32+
<artifactId>powernukkit</artifactId>
33+
<version>1.4.0.0-CODE-PN-SNAPSHOT</version>
34+
</dependency>
35+
<dependency>
36+
<groupId>org.projectlombok</groupId>
37+
<artifactId>lombok</artifactId>
38+
<version>1.18.0</version>
39+
</dependency>
40+
</dependencies>
41+
42+
</project>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package de.kcodeyt.headsdb;
2+
3+
import cn.nukkit.plugin.PluginBase;
4+
import de.kcodeyt.headsdb.command.HeadDBCommand;
5+
import de.kcodeyt.headsdb.database.Database;
6+
import lombok.Getter;
7+
8+
@Getter
9+
public class HeadsDB extends PluginBase {
10+
11+
private final Database database = new Database();
12+
13+
@Override
14+
public void onEnable() {
15+
this.getServer().getCommandMap().register("headsdb", new HeadDBCommand(this));
16+
if(!this.database.load()) {
17+
this.getLogger().error("Could not load heads database!");
18+
this.getServer().getPluginManager().disablePlugin(this);
19+
}
20+
}
21+
22+
@Override
23+
public void onDisable() {
24+
25+
}
26+
27+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package de.kcodeyt.headsdb.command;
2+
3+
import cn.nukkit.Player;
4+
import cn.nukkit.command.Command;
5+
import cn.nukkit.command.CommandSender;
6+
import cn.nukkit.form.element.ElementSlider;
7+
import cn.nukkit.form.window.FormWindowCustom;
8+
import de.kcodeyt.headsdb.HeadsDB;
9+
import de.kcodeyt.headsdb.database.DBSkin;
10+
import de.kcodeyt.headsdb.util.FormAPI;
11+
12+
import java.util.List;
13+
import java.util.Random;
14+
import java.util.concurrent.ThreadLocalRandom;
15+
16+
public class HeadDBCommand extends Command {
17+
18+
private final HeadsDB headsDB;
19+
20+
public HeadDBCommand(HeadsDB headsDB) {
21+
super("hdb");
22+
this.setAliases(new String[]{"headsdb"});
23+
this.headsDB = headsDB;
24+
}
25+
26+
@Override
27+
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
28+
if(args.length > 0) {
29+
final String subCommand = args[0].toLowerCase();
30+
switch(subCommand) {
31+
case "reload":
32+
if(sender.isOp()) {
33+
if(this.headsDB.getDatabase().reload())
34+
sender.sendMessage("§aReload the heads database successfully!");
35+
else
36+
sender.sendMessage("§cCould not reload the database!");
37+
return true;
38+
}
39+
break;
40+
case "random":
41+
if(sender.isOp()) {
42+
if(this.isConsole(sender))
43+
return false;
44+
45+
int amount;
46+
try {
47+
amount = Integer.parseInt(args.length > 1 ? args[1] : "1");
48+
if(amount > 32)
49+
amount = 32;
50+
if(amount < 1)
51+
amount = 1;
52+
} catch(NumberFormatException e) {
53+
amount = 1;
54+
}
55+
56+
final List<DBSkin> dbSkins = this.headsDB.getDatabase().getDbSkins();
57+
final Random random = ThreadLocalRandom.current();
58+
for(int i = 0; i < amount; i++)
59+
this.headsDB.getDatabase().giveItem((Player) sender, dbSkins.get(random.nextInt(dbSkins.size())));
60+
return true;
61+
}
62+
break;
63+
case "config":
64+
if(this.isConsole(sender))
65+
return false;
66+
67+
final Player player = (Player) sender;
68+
final FormWindowCustom configForm = new FormWindowCustom("Configure");
69+
configForm.addElement(new ElementSlider("Page length", 20, 120, 5, 40));
70+
FormAPI.create(player, configForm, () -> {
71+
if(configForm.wasClosed())
72+
return;
73+
final int pageLength = (int) configForm.getResponse().getSliderResponse(0);
74+
this.headsDB.getDatabase().getPageCount().put(player.getName(), pageLength);
75+
player.sendMessage("§aSet your page length to " + pageLength + "!");
76+
});
77+
return true;
78+
}
79+
}
80+
81+
if(this.isConsole(sender))
82+
return false;
83+
84+
this.headsDB.getDatabase().showForm((Player) sender);
85+
return true;
86+
}
87+
88+
private boolean isConsole(CommandSender sender) {
89+
if(sender instanceof Player)
90+
return false;
91+
sender.sendMessage("You must be logged in, to be able to use this command!");
92+
return true;
93+
}
94+
95+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package de.kcodeyt.headsdb.database;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
6+
@Getter
7+
@AllArgsConstructor
8+
public enum Categories {
9+
10+
ALPHABET("Alphabet", "alphabet"),
11+
ANIMALS("Animals", "animals"),
12+
BLOCKS("Blocks", "blocks"),
13+
DECORATION("Decoration", "decoration"),
14+
FOOD_DRINKS("Food & Drinks", "food-drinks"),
15+
HUMANS("Humans", "humans"),
16+
HUMANOID("Humanoid", "humanoid"),
17+
MISCELLANEOUS("Miscellaneous", "miscellaneous"),
18+
MONSTERS("Monsters", "monsters"),
19+
PLANTS("Plants", "plants");
20+
21+
private final String displayName;
22+
private final String identifier;
23+
24+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package de.kcodeyt.headsdb.database;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
6+
import java.util.List;
7+
8+
@Getter
9+
@AllArgsConstructor
10+
class Category {
11+
12+
private final Categories categories;
13+
private final String displayName;
14+
private final String displaySkin;
15+
private final List<DBSkin> skins;
16+
17+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package de.kcodeyt.headsdb.database;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
6+
@Getter
7+
@AllArgsConstructor
8+
public class DBSkin {
9+
10+
private final String name;
11+
private final String id;
12+
private final String texture;
13+
14+
}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package de.kcodeyt.headsdb.database;
2+
3+
import cn.nukkit.Player;
4+
import cn.nukkit.Server;
5+
import cn.nukkit.form.element.ElementButton;
6+
import cn.nukkit.form.element.ElementButtonImageData;
7+
import cn.nukkit.form.window.FormWindowSimple;
8+
import cn.nukkit.item.Item;
9+
import com.google.common.collect.Iterables;
10+
import com.google.gson.Gson;
11+
import de.kcodeyt.heads.Heads;
12+
import de.kcodeyt.heads.util.HeadInput;
13+
import de.kcodeyt.headsdb.util.FormAPI;
14+
import de.kcodeyt.headsdb.util.HeadRender;
15+
import lombok.Getter;
16+
17+
import java.io.IOException;
18+
import java.io.InputStream;
19+
import java.net.HttpURLConnection;
20+
import java.net.URL;
21+
import java.nio.charset.StandardCharsets;
22+
import java.util.*;
23+
import java.util.stream.Collectors;
24+
25+
@Getter
26+
public class Database {
27+
28+
private static final String API_URL = "https://minecraft-heads.com/scripts/api.php";
29+
private static final Gson GSON = new Gson();
30+
31+
private final Map<String, Integer> pageCount;
32+
private final List<Category> categories;
33+
private final List<DBSkin> dbSkins;
34+
35+
public Database() {
36+
this.pageCount = new HashMap<>();
37+
this.categories = new ArrayList<>();
38+
this.dbSkins = new ArrayList<>();
39+
}
40+
41+
public boolean reload() {
42+
this.categories.clear();
43+
this.dbSkins.clear();
44+
return this.load();
45+
}
46+
47+
public boolean load() {
48+
try {
49+
for(final Categories value : Categories.values()) {
50+
final List<Map<String, String>> values = GSON.<List<Map<String, String>>>fromJson(this.httpRequest(API_URL + "?cat=" + value.getIdentifier()), List.class);
51+
final List<DBSkin> dbSkins = values.stream().map(map -> new DBSkin(map.get("name"), map.get("uuid"), map.get("value"))).collect(Collectors.toList());
52+
this.dbSkins.addAll(dbSkins);
53+
this.categories.add(new Category(value, value.getDisplayName(), Iterables.getLast(dbSkins).getTexture(), Collections.unmodifiableList(dbSkins)));
54+
}
55+
56+
return true;
57+
} catch(IOException e) {
58+
Server.getInstance().getLogger().error("Error whilst loading heads from database api!", e);
59+
e.printStackTrace();
60+
return false;
61+
}
62+
}
63+
64+
private String httpRequest(String urlSpec) throws IOException {
65+
final HttpURLConnection connection = (HttpURLConnection) new URL(urlSpec).openConnection();
66+
connection.setRequestProperty("User-Agent", "Chrome");
67+
68+
String content = "{}";
69+
if(connection.getResponseCode() == 200) {
70+
try(final InputStream inputStream = connection.getInputStream()) {
71+
final StringBuilder builder = new StringBuilder();
72+
final byte[] bytes = new byte[1024 * 1024];
73+
for(int read; (read = inputStream.read(bytes)) > 0; )
74+
builder.append(new String(Arrays.copyOf(bytes, read), StandardCharsets.UTF_8));
75+
content = builder.toString();
76+
}
77+
}
78+
79+
connection.disconnect();
80+
return content;
81+
}
82+
83+
private List<List<DBSkin>> toPages(Category category, int count) {
84+
final List<DBSkin> dbSkins = category.getSkins();
85+
final int dbSize = dbSkins.size();
86+
if(dbSize <= 0)
87+
return Collections.emptyList();
88+
final List<List<DBSkin>> pages = new ArrayList<>();
89+
final int chunks = (dbSize - 1) / count;
90+
for(int i = 0; i <= chunks; i++)
91+
pages.add(dbSkins.subList(i * count, i == chunks ? dbSize : (i + 1) * count));
92+
return Collections.unmodifiableList(pages);
93+
}
94+
95+
public void showForm(Player player) {
96+
final FormWindowSimple categoriesForm = new FormWindowSimple("Select a category", "");
97+
final List<Category> categories = Collections.unmodifiableList(new ArrayList<>(this.categories));
98+
for(final Category category : categories)
99+
categoriesForm.addButton(new ElementButton(category.getDisplayName(), new ElementButtonImageData(ElementButtonImageData.IMAGE_DATA_TYPE_URL, HeadRender.createUrl(category.getDisplaySkin()))));
100+
FormAPI.create(player, categoriesForm, () -> {
101+
if(categoriesForm.wasClosed())
102+
return;
103+
final Category category = categories.get(categoriesForm.getResponse().getClickedButtonId());
104+
if(category == null)
105+
return;
106+
final FormWindowSimple pagesForm = new FormWindowSimple("Select a page", "");
107+
final List<List<DBSkin>> pages = this.toPages(category, this.pageCount.getOrDefault(player.getName(), 40));
108+
for(int i = 0; i < pages.size(); i++)
109+
pagesForm.addButton(new ElementButton("Page " + (i + 1), new ElementButtonImageData(ElementButtonImageData.IMAGE_DATA_TYPE_URL, HeadRender.createUrl(Iterables.getLast(pages.get(i)).getTexture()))));
110+
FormAPI.create(player, pagesForm, () -> {
111+
if(pagesForm.wasClosed()) {
112+
this.showForm(player);
113+
return;
114+
}
115+
116+
final List<DBSkin> dbSkins = pages.get(pagesForm.getResponse().getClickedButtonId());
117+
if(dbSkins == null)
118+
return;
119+
final FormWindowSimple subForm = new FormWindowSimple(category.getDisplayName(), "");
120+
for(final DBSkin dbSkin : dbSkins)
121+
subForm.addButton(new ElementButton(dbSkin.getName(), new ElementButtonImageData(ElementButtonImageData.IMAGE_DATA_TYPE_URL, HeadRender.createUrl(dbSkin.getTexture()))));
122+
FormAPI.create(player, subForm, () -> {
123+
if(subForm.wasClosed())
124+
return;
125+
final DBSkin dbSkin = dbSkins.get(subForm.getResponse().getClickedButtonId());
126+
if(dbSkin == null)
127+
return;
128+
this.giveItem(player, dbSkin);
129+
});
130+
});
131+
});
132+
}
133+
134+
public void giveItem(Player player, DBSkin dbSkin) {
135+
Heads.createItem(HeadInput.ofTexture(dbSkin.getTexture(), dbSkin.getId())).whenComplete((result, throwable) -> {
136+
if(throwable != null) {
137+
player.sendMessage("§cCould not create the requested skull item!");
138+
return;
139+
}
140+
141+
final Item item = result.getItem();
142+
item.setCustomName("§r§7" + dbSkin.getName());
143+
final Item[] drops = player.getInventory().addItem(item);
144+
if(drops.length > 0) {
145+
for(final Item drop : drops)
146+
player.getLevel().dropItem(player, drop);
147+
}
148+
149+
player.sendMessage("§aGave you the head " + dbSkin.getName() + "§r§a!");
150+
});
151+
}
152+
153+
}

0 commit comments

Comments
 (0)