From aecaab67ac6d4b0825e8e3ff8bac899789e598cb Mon Sep 17 00:00:00 2001
From: yourfriendoss <81387799+yourfriendoss@users.noreply.github.com>
Date: Sun, 16 Apr 2023 00:16:16 +0300
Subject: [PATCH] first commit
---
.gitignore | 1 +
.vscode/settings.json | 4 +
pom.xml | 132 ++++++++++++++
readme.md | 58 ++++++
src/main/java/lv/pi/animalrp/AnimalRP.java | 168 ++++++++++++++++++
.../java/lv/pi/animalrp/animals/Animal.java | 57 ++++++
src/main/java/lv/pi/animalrp/animals/Bee.java | 102 +++++++++++
src/main/java/lv/pi/animalrp/animals/Cat.java | 68 +++++++
src/main/java/lv/pi/animalrp/animals/Fox.java | 72 ++++++++
.../lv/pi/animalrp/commands/EmoteCommand.java | 59 ++++++
.../animalrp/commands/InteractionCommand.java | 70 ++++++++
.../lv/pi/animalrp/commands/TfCommand.java | 92 ++++++++++
.../lv/pi/animalrp/listeners/AntiElytra.java | 86 +++++++++
.../lv/pi/animalrp/listeners/PlayerChat.java | 56 ++++++
.../java/lv/pi/animalrp/util/Cooldown.java | 35 ++++
src/main/java/lv/pi/animalrp/util/Emote.java | 131 ++++++++++++++
src/main/java/lv/pi/animalrp/util/Mood.java | 5 +
.../lv/pi/animalrp/util/TextDestroyer.java | 43 +++++
src/main/resources/plugin.yml | 26 +++
19 files changed, 1265 insertions(+)
create mode 100644 .gitignore
create mode 100644 .vscode/settings.json
create mode 100644 pom.xml
create mode 100644 readme.md
create mode 100644 src/main/java/lv/pi/animalrp/AnimalRP.java
create mode 100644 src/main/java/lv/pi/animalrp/animals/Animal.java
create mode 100644 src/main/java/lv/pi/animalrp/animals/Bee.java
create mode 100644 src/main/java/lv/pi/animalrp/animals/Cat.java
create mode 100644 src/main/java/lv/pi/animalrp/animals/Fox.java
create mode 100644 src/main/java/lv/pi/animalrp/commands/EmoteCommand.java
create mode 100644 src/main/java/lv/pi/animalrp/commands/InteractionCommand.java
create mode 100644 src/main/java/lv/pi/animalrp/commands/TfCommand.java
create mode 100644 src/main/java/lv/pi/animalrp/listeners/AntiElytra.java
create mode 100644 src/main/java/lv/pi/animalrp/listeners/PlayerChat.java
create mode 100644 src/main/java/lv/pi/animalrp/util/Cooldown.java
create mode 100644 src/main/java/lv/pi/animalrp/util/Emote.java
create mode 100644 src/main/java/lv/pi/animalrp/util/Mood.java
create mode 100644 src/main/java/lv/pi/animalrp/util/TextDestroyer.java
create mode 100644 src/main/resources/plugin.yml
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2f7896d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+target/
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..c6fe658
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,4 @@
+{
+ "java.configuration.updateBuildConfiguration": "automatic",
+ "java.compile.nullAnalysis.mode": "disabled"
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..6770ada
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,132 @@
+
+
+
+ 4.0.0
+
+ lv.pi.animalrp
+ animalrp
+ 1.0.0
+
+ animalrp
+
+
+ UTF-8
+ 17
+ 17
+
+
+
+
+ jitpack.io
+ https://jitpack.io
+
+
+ papermc
+ https://repo.papermc.io/repository/maven-public/
+
+
+ codemc-releases
+ https://repo.codemc.org/repository/maven-releases/
+
+
+ sonatype-oss-snapshots1
+ https://s01.oss.sonatype.org/content/repositories/snapshots/
+
+
+
+
+
+ io.papermc.paper
+ paper-api
+ 1.19.4-R0.1-SNAPSHOT
+ provided
+
+
+ net.kyori
+ adventure-text-minimessage
+ 4.13.0
+
+
+ net.kyori
+ adventure-text-serializer-legacy
+ 4.13.0
+
+
+
+
+
+
+
+ src/main/resources
+ true
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 17
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.2.1
+
+
+
+ package
+
+ shade
+
+
+
+ true
+ animalrp
+
+
+
+
+
+
+
+ net.md-5
+ specialsource-maven-plugin
+ 1.2.2
+
+
+ package
+
+ remap
+
+ remap-obf
+
+ org.spigotmc:minecraft-server:1.19.4-R0.1-SNAPSHOT:txt:maps-mojang
+ true
+ org.spigotmc:spigot:1.19.4-R0.1-SNAPSHOT:jar:remapped-mojang
+ true
+ remapped-obf
+
+
+
+ package
+
+ remap
+
+ remap-spigot
+
+ ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar
+ org.spigotmc:minecraft-server:1.19.4-R0.1-SNAPSHOT:csrg:maps-spigot
+ org.spigotmc:spigot:1.19.4-R0.1-SNAPSHOT:jar:remapped-obf
+
+
+
+
+
+
+
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..3267ab1
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,58 @@
+# **AnimalRPs plugin**
+
+## **Animal listing**
+1. Bee
+Doubleclicking shift you will float (levitation 5 for 1 second), allowing for better movement up hills as example. **Your superfood is the honeybottle.**
+2. Cat
+You take significantly less damage when falling (5 hearts). You can still die, don't count on your cat-powers catching you every time. **Your superfood is all types of eatable fish.**
+3. Fox
+You do more damage to mobs (25%). **Your superfood is all types of berry.**
+
+## **Chat**
+Chat while you are a animal is very different. When you speak, your words will become furry-ified and every time you talk you'll have animal sounds come out of you.
+
+## **Superfoods**
+Superfoods are items that when eaten, give you stackable **Speed II** and insane amounts of saturation (9.4 points) and hunger (4 points).
+
+## **Cooldowns & animals**
+Cooldowns are stored in game. Animal/cooldowns are stored in a json database.
+
+## **How to add a new animal?**
+
+1. Create a new class in animals/MyCoolAnimal.java
+2. Use this template
+```
+public class MyCoolAnimal extends Animal {
+ TextDestroyer destroyer = new TextDestroyer(new String[]{
+ "I'm Cool!"
+ }, new String[][]{
+ {"g", "z"}
+ });
+
+ public MyCoolAnimal() {
+ super("coolanimal", "awsome!", "#00ff00");
+ this.moodSounds.put(Mood.HAPPY, Sound.ENTITY_FOX_EAT);
+ this.moodSounds.put(Mood.CUTE, Sound.ENTITY_FOX_SLEEP);
+ this.moodSounds.put(Mood.SAD, Sound.ENTITY_FOX_SNIFF);
+ this.moodSounds.put(Mood.STRESSED, Sound.ENTITY_FOX_AGGRO);
+ this.moodSounds.put(Mood.ANGRY, Sound.ENTITY_FOX_BITE);
+
+ this.superfoods.add(Material.POTATO);
+ }
+
+ @Override
+ public String chatTransformations(String message) {
+ return this.destroyer.destroy(message);
+ }
+
+ @Override
+ public Location movementTransformations(Location location) {
+ return location;
+ }
+
+}
+```
+3. Change the info in the TextDestroyer initialization
+4. Change the info in the super() call, it is written as "name", "catchphrase", "color".
+5. Change the moodSounds and implement all sounds for the moods.
+6. Add superfoods (foods that the animal likes)
\ No newline at end of file
diff --git a/src/main/java/lv/pi/animalrp/AnimalRP.java b/src/main/java/lv/pi/animalrp/AnimalRP.java
new file mode 100644
index 0000000..f8f3364
--- /dev/null
+++ b/src/main/java/lv/pi/animalrp/AnimalRP.java
@@ -0,0 +1,168 @@
+/*
+⠀⠀⠀⠀⠀⠀⠀⠙⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⢺⣿⣿⡆⠀⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡇⠀⠀⠀⠀⠀⠀⣾⢡⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣿⣷⡦⠀⠀⠀⠀⢰⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠃⣠⣾⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣆⠀⠀⠀⣾⣿⣿⣿⣷⠄⠀⠰⠤⣀⠀⠀⣴⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠃⢺⣿⣿⣿⣿⡄⠀⠀⣿⣿⢿⣿⣿⣦⣦⣦⣶⣼⣭⣼⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⣿⣿⣷⡆⠂⣿⣿⣞⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢙⣿⣿⣿⣿⣷⠸⣿⣿⣿⣿⣿⣿⠟⠻⣿⣿⣿⣿⡿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⢿⣿⣿⣿⣿⡄⣿⣿⣿⣿⣿⣿⡀⢀⣿⣿⣿⣿⠀⢸⣿⣿⠅⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⣇⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⢐⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⢀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⡀⣠⣾⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡔⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⢁⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠠⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⣀⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⣻⣿⣿⣿⣿⣿⡟⠋⠙⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠙⢿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⣿⣿⣿⣿⣿⡿⠋⠀⠀⠀⢿⣿⣿⣿⣿⣿⣿⠿⢿⡿⠛⠋⠁⠀⠀⠈⠻⣿⣿⣿⣿⣿⣿⣅⠀⠀⠀⠀⠀
+⠀⠀⠀⣿⣿⣿⣿⡟⠃⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢻⣿⣿⣿⣿⣿⣤⡀⠀⠀⠀
+⠀⠜⢠⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣿⣿⣗⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣿⣦⠄⣠⠀
+⠠⢸⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣿
+⠀⠛⣿⣿⣿⡿⠏⠀⠀⠀⠀⠀⠀⢳⣾⣿⣿⣿⣿⣿⣿⡶⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿
+⠀⢨⠀⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠙⣿⣿⡿⡿⠿⠛⠙⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⠏⠉⠻⠿⠟⠁
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+*/
+
+package lv.pi.animalrp;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map.Entry;
+import java.util.UUID;
+
+import org.bukkit.plugin.PluginManager;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSyntaxException;
+
+import lv.pi.animalrp.animals.Animal;
+import lv.pi.animalrp.animals.Bee;
+import lv.pi.animalrp.animals.Cat;
+import lv.pi.animalrp.animals.Fox;
+import lv.pi.animalrp.commands.EmoteCommand;
+import lv.pi.animalrp.commands.InteractionCommand;
+import lv.pi.animalrp.commands.TfCommand;
+import lv.pi.animalrp.listeners.AntiElytra;
+import lv.pi.animalrp.listeners.PlayerChat;
+import lv.pi.animalrp.util.Cooldown;
+import lv.pi.animalrp.util.Emote;
+import lv.pi.animalrp.util.Mood;
+import net.kyori.adventure.text.minimessage.MiniMessage;
+
+public class AnimalRP extends JavaPlugin {
+ public static HashMap users = new HashMap();
+ public static HashMap cooldowns = new HashMap();
+ public static HashMap animals = new HashMap();
+ public static Emote emotes;
+
+ public static Boolean configEnabled = true;
+ private Gson gson;
+ public static MiniMessage mm = MiniMessage.miniMessage();
+
+ @Override
+ public void onDisable() {
+ File folder = getDataFolder();
+ HashMap usersReformatted = new HashMap();
+
+ for (Entry ee : users.entrySet()) {
+ usersReformatted.put(ee.getKey().toString(), ee.getValue().name);
+ }
+
+ try {
+ Path filePath = folder.toPath().resolve("database.json");
+
+ if(!Files.exists(filePath)) Files.createFile(filePath);
+
+ Files.write(filePath, gson.toJson(usersReformatted).getBytes());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ try {
+ Path filePath = folder.toPath().resolve("cooldowns.json");
+
+ if(!Files.exists(filePath)) Files.createFile(filePath);
+ JsonObject jsobj = new JsonObject();
+ AnimalRP.cooldowns.forEach((a, b) -> {
+ jsobj.add(a.toString(), b.toJson());
+ });
+ Files.write(filePath, gson.toJson(jsobj).getBytes());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onEnable() {
+ PluginManager pm = getServer().getPluginManager();
+ AnimalRP.emotes = new Emote();
+
+ this.gson = new Gson();
+
+ animals.put("cat", new Cat());
+ animals.put("fox", new Fox());
+ animals.put("bee", new Bee());
+
+ animals.forEach((z,b) -> {
+ pm.registerEvents(b, this);
+ });
+
+ Path folder = getDataFolder().toPath();
+
+ if(!Files.exists(folder)) {
+ try {
+ Files.createDirectory(folder);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ if(folder.resolve("database.json").toFile().exists()) {
+ try {
+ JsonObject z = JsonParser.parseString(Files.readString(folder.resolve("database.json"))).getAsJsonObject();
+
+ for (Entry entry : z.entrySet()) {
+ AnimalRP.users.put(UUID.fromString(entry.getKey()), AnimalRP.animals.get(entry.getValue().getAsString()));
+ }
+ } catch (JsonSyntaxException | IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ if(folder.resolve("cooldowns.json").toFile().exists()) {
+ try {
+ JsonObject z = JsonParser.parseString(Files.readString(folder.resolve("cooldowns.json"))).getAsJsonObject();
+
+ for (Entry entry : z.entrySet()) {
+ AnimalRP.cooldowns.put(UUID.fromString(entry.getKey()), Cooldown.fromJson(entry.getValue().getAsJsonObject()));
+ }
+ } catch (JsonSyntaxException | IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ pm.registerEvents(new PlayerChat(), this);
+ pm.registerEvents(new AntiElytra(), this);
+
+ getCommand("tf").setExecutor(new TfCommand());
+ getCommand("emote").setExecutor(new EmoteCommand());
+
+ getCommand("headpats").setExecutor(new InteractionCommand(Mood.HAPPY, "%s petted you! %s", "You petted %s! %s"));
+ getCommand("kiss").setExecutor(new InteractionCommand(Mood.CUTE, "%s kissed you.. 0////0 %s", "You kissed %s.. 0////0 %s"));
+ getCommand("bite").setExecutor(new InteractionCommand(Mood.ANGRY, "%s bit you!! Σ(っ゚Д゚)っ %s", "You bit %s! (○`д´)ノシ %s"));
+ getCommand("purr").setExecutor(new InteractionCommand(Mood.CUTE, "You hear the soft sound of %s purring on you... %s", "You jump on %s, and start purring. %s"));
+ getCommand("scratch").setExecutor(new InteractionCommand(Mood.ANGRY, "%s SCRATCHES YOU! Ow! %s", "You channel your inner evil, and scratch %s! %s"));
+ getCommand("hug").setExecutor(new InteractionCommand(Mood.HAPPY, "%s hugs you! How heartwarming. %s", "You hug %s! How heartwarming. %s")); // Simo__28 SUCKS
+ getCommand("cuddle").setExecutor(new InteractionCommand(Mood.CUTE, "%s cuddles with you. %s", "You and %s start cuddling. How cute! %s")); // Simo__28 SUCKS
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/lv/pi/animalrp/animals/Animal.java b/src/main/java/lv/pi/animalrp/animals/Animal.java
new file mode 100644
index 0000000..e4e7b74
--- /dev/null
+++ b/src/main/java/lv/pi/animalrp/animals/Animal.java
@@ -0,0 +1,57 @@
+package lv.pi.animalrp.animals;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerItemConsumeEvent;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+
+import lv.pi.animalrp.AnimalRP;
+import lv.pi.animalrp.util.Mood;
+
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+
+public abstract class Animal implements Listener {
+ public String name;
+ public String catchphrase;
+ public String color;
+ public HashMap moodSounds = new HashMap();
+ public ArrayList superfoods = new ArrayList();
+
+ @EventHandler
+ public void onEat(PlayerItemConsumeEvent event) {
+ Player player = event.getPlayer();
+
+ Animal animal = AnimalRP.users.get(player.getUniqueId());
+ if(animal == null) return;
+ if(animal.name != this.name) return;
+
+ if(event.getItem() != null) {
+ if(this.superfoods.contains(event.getItem().getType())) {
+ player.setFoodLevel(player.getFoodLevel() + 4);
+ player.setSaturation(player.getSaturation() + 9.4f);
+ PotionEffect eff = player.getPotionEffect(PotionEffectType.SPEED);
+ Integer duration = 20*4;
+
+ if(eff != null) { // This stacks!
+ duration += eff.getDuration();
+ }
+
+ player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, duration, 1, true));
+ }
+ }
+ }
+
+ Animal(String name, String catchphrase, String color) {
+ this.name = name; this.catchphrase = catchphrase; this.color = color;
+ }
+
+ public abstract String chatTransformations(String message);
+ public abstract Location movementTransformations(Location location);
+}
diff --git a/src/main/java/lv/pi/animalrp/animals/Bee.java b/src/main/java/lv/pi/animalrp/animals/Bee.java
new file mode 100644
index 0000000..3fc577c
--- /dev/null
+++ b/src/main/java/lv/pi/animalrp/animals/Bee.java
@@ -0,0 +1,102 @@
+package lv.pi.animalrp.animals;
+
+import java.util.ArrayList;
+import java.util.UUID;
+
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.Sound;
+import org.bukkit.block.BlockFace;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.player.PlayerToggleSneakEvent;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import lv.pi.animalrp.AnimalRP;
+import lv.pi.animalrp.util.Mood;
+import lv.pi.animalrp.util.TextDestroyer;
+
+class Cooldown {
+ Integer duration;
+ Long executionTime;
+ public Cooldown(Integer duration, Long executionTime) {
+ this.duration = duration;
+ this.executionTime = executionTime;
+ }
+
+ public boolean isExpired() {
+ return this.executionTime-(System.currentTimeMillis()-this.duration) <= 0;
+ }
+}
+
+public class Bee extends Animal {
+ TextDestroyer destroyer = new TextDestroyer(new String[]{
+ ">_<", "*buzz*",
+ ";3", ":3", "εწз", " ≧◠◡◠≦ ", "*stings you*", "*humms*",
+ "*i'm a bee*"
+ }, new String[][]{
+ {"e", "ee"},
+ {"b", "bzz"},
+ {"h", "hh"},
+ {"ie", "ee"},
+ {"be", "bee"},
+ {"E", "EE"},
+ {"B", "BZZ"},
+ {"H", "HH"},
+ {"IE", "EE"},
+ {"BE", "BEE"}
+ });
+
+ ArrayList sneakers = new ArrayList();
+
+ public Bee() {
+ super("bee", "Buzz...", "#FFFF00");
+ this.moodSounds.put(Mood.HAPPY, Sound.ENTITY_BEE_LOOP);
+ this.moodSounds.put(Mood.CUTE, Sound.ENTITY_BEE_LOOP);
+ this.moodSounds.put(Mood.SAD, Sound.ENTITY_BEE_HURT);
+ this.moodSounds.put(Mood.STRESSED, Sound.ENTITY_BEE_STING);
+ this.moodSounds.put(Mood.ANGRY, Sound.ENTITY_BEE_LOOP_AGGRESSIVE);
+
+ this.superfoods.add(Material.HONEY_BOTTLE);
+ this.superfoods.add(Material.CHORUS_FLOWER);
+ }
+
+ @EventHandler
+ public void onSneak(PlayerToggleSneakEvent event) {
+ Animal animal = AnimalRP.users.get(event.getPlayer().getUniqueId());
+ if(animal == null) return;
+ if(animal.name != this.name) return;
+
+ if (event.isSneaking() && event.getPlayer().getLocation().getBlock().getRelative(BlockFace.DOWN).getType() != Material.AIR) {
+ Player player = event.getPlayer();
+
+ if (!sneakers.contains(player.getUniqueId())) {
+ sneakers.add(player.getUniqueId());
+
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ if(sneakers.contains(player.getUniqueId())) sneakers.remove(player.getUniqueId());
+ }
+ }.runTaskLater(AnimalRP.getProvidingPlugin(Animal.class), 20);
+ } else {
+ sneakers.remove(player.getUniqueId());
+ player.addPotionEffect(new PotionEffect(PotionEffectType.LEVITATION, 20*1, 5, true));
+ player.getWorld().playSound(player.getLocation(), this.moodSounds.get(Mood.HAPPY), 1F, 1);
+ }
+ }
+ }
+
+ @Override
+ public String chatTransformations(String message) {
+ return destroyer.destroy(message);
+ }
+
+ @Override
+ public Location movementTransformations(Location location) {
+ return location;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/lv/pi/animalrp/animals/Cat.java b/src/main/java/lv/pi/animalrp/animals/Cat.java
new file mode 100644
index 0000000..90f60a0
--- /dev/null
+++ b/src/main/java/lv/pi/animalrp/animals/Cat.java
@@ -0,0 +1,68 @@
+package lv.pi.animalrp.animals;
+
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
+
+import lv.pi.animalrp.AnimalRP;
+import lv.pi.animalrp.util.Mood;
+import lv.pi.animalrp.util.TextDestroyer;
+
+public class Cat extends Animal {
+ TextDestroyer destroyer = new TextDestroyer(new String[]{
+ ">_<", ":3", "ʕʘ‿ʘʔ", ":D", "._.",
+ ";3", "xD", "ㅇㅅㅇ",
+ ">_>", "ÙωÙ", "UwU", "OwO", ":P",
+ "(◠‿◠✿)", "^_^", ";_;",
+ "x3", "(• o •)", "<_<"
+ }, new String[][]{
+ {"l", "w"},
+ {"r", "w"},
+ {"th", "d"},
+ {"L", "W"},
+ {"R", "W"},
+ {"TH", "D"}
+ });
+
+ public Cat() {
+ super("cat", "Nya~", "#F2BDCD");
+ this.moodSounds.put(Mood.HAPPY, Sound.ENTITY_CAT_PURR);
+ this.moodSounds.put(Mood.CUTE, Sound.ENTITY_CAT_PURREOW);
+ this.moodSounds.put(Mood.SAD, Sound.ENTITY_CAT_AMBIENT);
+ this.moodSounds.put(Mood.STRESSED, Sound.ENTITY_CAT_STRAY_AMBIENT);
+ this.moodSounds.put(Mood.ANGRY, Sound.ENTITY_CAT_HISS);
+
+ this.superfoods.add(Material.COOKED_COD);
+ this.superfoods.add(Material.COD);
+ this.superfoods.add(Material.COOKED_SALMON);
+ this.superfoods.add(Material.SALMON);
+ }
+
+ @EventHandler
+ public void onDamage(EntityDamageEvent event) {
+ if(!(event.getEntity() instanceof Player)) return;
+
+ Player player = (Player)event.getEntity();
+ Animal animal = AnimalRP.users.get(player.getUniqueId());
+ if(animal == null) return;
+ if(animal.name != this.name) return;
+ if(event.getCause() == DamageCause.FALL) {
+ event.setDamage(event.getDamage() - 5);
+ }
+ }
+
+ @Override
+ public String chatTransformations(String message) {
+ return destroyer.destroy(message);
+ }
+
+ @Override
+ public Location movementTransformations(Location location) {
+ return location;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/lv/pi/animalrp/animals/Fox.java b/src/main/java/lv/pi/animalrp/animals/Fox.java
new file mode 100644
index 0000000..7c2de2c
--- /dev/null
+++ b/src/main/java/lv/pi/animalrp/animals/Fox.java
@@ -0,0 +1,72 @@
+package lv.pi.animalrp.animals;
+
+import java.util.Random;
+
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.Sound;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
+
+import lv.pi.animalrp.AnimalRP;
+import lv.pi.animalrp.util.Mood;
+import lv.pi.animalrp.util.TextDestroyer;
+
+public class Fox extends Animal {
+ TextDestroyer destroyer = new TextDestroyer(new String[]{
+ "yap",
+ "*yap yap*",
+ "*beeps*",
+ "*barks*",
+ "*screeches*",
+ ":3"
+ }, new String[][]{
+ {"you", "u"},
+ {"o", "yo"},
+ {"i", "yi"},
+ {"!", " !"},
+ {"?", " ?"}
+ });
+ Random rand = new Random();
+
+ public Fox() {
+ super("fox", "Yap!", "#FF8000");
+ this.moodSounds.put(Mood.HAPPY, Sound.ENTITY_FOX_SNIFF);
+ this.moodSounds.put(Mood.CUTE, Sound.ENTITY_FOX_SLEEP);
+ this.moodSounds.put(Mood.SAD, Sound.ENTITY_FOX_SNIFF);
+ this.moodSounds.put(Mood.STRESSED, Sound.ENTITY_FOX_AGGRO);
+ this.moodSounds.put(Mood.ANGRY, Sound.ENTITY_FOX_BITE);
+
+ this.superfoods.add(Material.SWEET_BERRIES);
+ this.superfoods.add(Material.GLOW_BERRIES);
+ }
+
+ @EventHandler
+ public void onDamage(EntityDamageByEntityEvent event) {
+ if(event.getDamager() instanceof Player) {
+ Player player = (Player)event.getDamager();
+ Animal animal = AnimalRP.users.get(player.getUniqueId());
+
+ if(animal == null) return;
+ if(animal.name != this.name) return;
+
+ if(event.getCause() == DamageCause.ENTITY_ATTACK && event.getEntity().getType() != EntityType.PLAYER) {
+ event.setDamage(event.getDamage()*1.25);
+ }
+ }
+ }
+
+ @Override
+ public String chatTransformations(String message) {
+ return this.destroyer.destroy(message);
+ }
+
+ @Override
+ public Location movementTransformations(Location location) {
+ return location;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/lv/pi/animalrp/commands/EmoteCommand.java b/src/main/java/lv/pi/animalrp/commands/EmoteCommand.java
new file mode 100644
index 0000000..aeb756c
--- /dev/null
+++ b/src/main/java/lv/pi/animalrp/commands/EmoteCommand.java
@@ -0,0 +1,59 @@
+package lv.pi.animalrp.commands;
+
+import java.util.stream.Collectors;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+import lv.pi.animalrp.AnimalRP;
+import lv.pi.animalrp.util.Emote;
+import lv.pi.animalrp.util.Emote.Emotes;
+
+public class EmoteCommand implements CommandExecutor {
+ private void options(Player player) {
+ player.sendMessage(AnimalRP.mm.deserialize("You have " + String.join(", ", Emote.emotes.keySet().stream().map(Emote.Emotes::name).map(String::toLowerCase).collect(Collectors.toSet())) + " as options."));
+ }
+
+ @Override
+ public boolean onCommand(@NotNull CommandSender arg0, @NotNull Command arg1, @NotNull String arg2, @NotNull String[] arg3) {
+ if(!(arg0 instanceof Player)) {
+ arg0.sendMessage(AnimalRP.mm.deserialize("I'm sorry console. :("));
+ return true;
+ }
+
+ Player player = (Player)arg0;
+
+ if(arg3.length == 0) {
+ options(player);
+ return true;
+ }
+
+ String emoteString = arg3[0];
+ Emote.Emotes emote;
+
+ try {
+ emote = Emotes.valueOf(emoteString.toUpperCase());
+ } catch(Exception e) {
+ emote = null;
+ }
+
+ if(emote == null) {
+ options(player);
+ return true;
+ }
+
+ if(AnimalRP.emotes.isPlayerEmoting(player.getUniqueId())) {
+ arg0.sendMessage(AnimalRP.mm.deserialize("Stopped emoting."));
+ AnimalRP.emotes.stopEmote(player.getUniqueId());
+ } else {
+ arg0.sendMessage(AnimalRP.mm.deserialize("Emoting!"));
+ AnimalRP.emotes.playEmote(player.getUniqueId(), emote);
+ }
+
+ return true;
+ }
+
+}
diff --git a/src/main/java/lv/pi/animalrp/commands/InteractionCommand.java b/src/main/java/lv/pi/animalrp/commands/InteractionCommand.java
new file mode 100644
index 0000000..a94a18d
--- /dev/null
+++ b/src/main/java/lv/pi/animalrp/commands/InteractionCommand.java
@@ -0,0 +1,70 @@
+package lv.pi.animalrp.commands;
+
+import org.bukkit.command.CommandExecutor;
+
+import org.bukkit.Bukkit;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import lv.pi.animalrp.AnimalRP;
+import lv.pi.animalrp.animals.Animal;
+import lv.pi.animalrp.util.Mood;
+
+public class InteractionCommand implements CommandExecutor {
+ String toThem;
+ String toYou;
+ Mood mood;
+
+ public InteractionCommand(Mood mood, String toThem, String toYou) {
+ this.toThem = toThem;
+ this.toYou = toYou;
+ this.mood = mood;
+ }
+
+ @Override
+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if(!(sender instanceof Player)) {
+ sender.sendMessage(AnimalRP.mm.deserialize("I'm sorry console. :("));
+ return true;
+ }
+
+ Player player = (Player)sender;
+
+ Animal aplayer = AnimalRP.users.get(player.getUniqueId());
+
+ if(aplayer == null) {
+ player.sendMessage(AnimalRP.mm.deserialize("Only animals can interact with other animals :("));
+ return true;
+ }
+
+ if(args.length == 0) {
+ player.sendMessage(AnimalRP.mm.deserialize("Include a user!"));
+ return true;
+ }
+
+ Player splayer = Bukkit.getPlayer(args[0]);
+
+ if(splayer == null) {
+ player.sendMessage(AnimalRP.mm.deserialize("I can't find this player :("));
+ return true;
+ }
+
+ if(splayer.getName() == player.getName()) {
+ player.sendMessage(AnimalRP.mm.deserialize("You can't "+command+" yourself."));
+ return true;
+ }
+ Animal asplayer = AnimalRP.users.get(splayer.getUniqueId());
+
+ if(asplayer == null) {
+ player.sendMessage(AnimalRP.mm.deserialize(""+splayer.getName() + " is not an animal! :("));
+ return true;
+ }
+
+ splayer.sendMessage(AnimalRP.mm.deserialize(String.format(this.toThem, ""+player.getName()+"", ""+aplayer.catchphrase+"")));
+ player.sendMessage(AnimalRP.mm.deserialize(String.format(this.toYou, ""+splayer.getName()+"", ""+asplayer.catchphrase+"")));
+ player.getWorld().playSound(splayer.getLocation(), asplayer.moodSounds.get(this.mood), 1F, 1);
+ return true;
+ }
+}
diff --git a/src/main/java/lv/pi/animalrp/commands/TfCommand.java b/src/main/java/lv/pi/animalrp/commands/TfCommand.java
new file mode 100644
index 0000000..c4bf424
--- /dev/null
+++ b/src/main/java/lv/pi/animalrp/commands/TfCommand.java
@@ -0,0 +1,92 @@
+package lv.pi.animalrp.commands;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Map.Entry;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import lv.pi.animalrp.AnimalRP;
+import lv.pi.animalrp.animals.Animal;
+import lv.pi.animalrp.util.Cooldown;
+
+public class TfCommand implements CommandExecutor {
+ public void options(Player player) {
+ ArrayList parts = new ArrayList();
+
+ for (Entry entry : AnimalRP.animals.entrySet()) {
+ parts.add("<"+entry.getValue().color+">"+entry.getKey()+""+entry.getValue().color+">");
+ }
+
+ player.sendMessage(AnimalRP.mm.deserialize("Looking around you, you have \"" + String.join(", ", parts) + "\" as options."));
+ }
+
+ @Override
+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if(!(sender instanceof Player)) {
+ sender.sendMessage(AnimalRP.mm.deserialize("I'm sorry, but you have to be a player to become an animal. :("));
+ return true;
+ }
+
+ Player player = (Player)sender;
+
+ if(args.length == 0) {
+ if(AnimalRP.users.get(player.getUniqueId()) != null) {
+ Animal previous = AnimalRP.users.get(player.getUniqueId());
+ player.sendMessage(AnimalRP.mm.deserialize("You start splitting apart, dropping your " + previous.name+"-like appearence.."));
+ AnimalRP.users.remove(player.getUniqueId());
+ return true;
+ } else {
+ options(player); return true;
+
+ }
+ }
+
+ String tf = args[0];
+
+ Animal animal = AnimalRP.animals.get(tf);
+
+ if(animal == null) {
+ options(player); return true;
+ }
+
+ Cooldown cldn = AnimalRP.cooldowns.get(player.getUniqueId());
+
+ if(cldn != null) {
+ if(cldn.isExpired()) {
+ cldn = null;
+ } else {
+ SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
+ player.sendMessage(AnimalRP.mm.deserialize("You are still on cooldown. Time left: " + sdf.format(new Date(cldn.getTime()))));
+ return true;
+ }
+ }
+
+ if(AnimalRP.users.get(player.getUniqueId()) != null) {
+ Animal previous = AnimalRP.users.get(player.getUniqueId());
+ if(previous.name == animal.name) {
+ player.sendMessage(AnimalRP.mm.deserialize("You're " + previous.name + " already! " + animal.catchphrase));
+ return true;
+ }
+ player.sendMessage(AnimalRP.mm.deserialize("You slowly transform, from " + previous.name + " to.. " + animal.name + ". "+ animal.catchphrase));
+ } else {
+ player.sendMessage(AnimalRP.mm.deserialize("You slowly transform, to.. " + animal.name + ". "+ animal.catchphrase));
+ }
+
+ if(cldn == null) {
+ cldn = new Cooldown();
+ cldn.length = 21600000;
+ cldn.timeCreated = System.currentTimeMillis();
+ cldn.type = "tf-command";
+ AnimalRP.cooldowns.put(player.getUniqueId(), cldn);
+ }
+
+ AnimalRP.users.put(player.getUniqueId(), animal);
+ return true;
+ }
+
+}
diff --git a/src/main/java/lv/pi/animalrp/listeners/AntiElytra.java b/src/main/java/lv/pi/animalrp/listeners/AntiElytra.java
new file mode 100644
index 0000000..33e4934
--- /dev/null
+++ b/src/main/java/lv/pi/animalrp/listeners/AntiElytra.java
@@ -0,0 +1,86 @@
+package lv.pi.animalrp.listeners;
+
+import org.bukkit.GameMode;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.entity.EntityToggleGlideEvent;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.PlayerInventory;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import lv.pi.animalrp.AnimalRP;
+
+public class AntiElytra implements Listener {
+
+ public AntiElytra() {
+ JavaPlugin plugin = AnimalRP.getProvidingPlugin(AnimalRP.class);
+
+ new BukkitRunnable(){
+ public void run(){
+ for(Player p : plugin.getServer().getOnlinePlayers())
+ dequipElytra(p);
+ }
+ }.runTaskTimer(plugin, 20 * 5, 20 * 5);
+ }
+
+ private void message(Player player) {
+ player.sendMessage(AnimalRP.mm.deserialize("Elytras are not allowed to be worn. You can still trade with them as they might have a use in the future."));
+ }
+ @EventHandler
+ public void onGlide(EntityToggleGlideEvent event) {
+ if (event.getEntity().getType().equals(EntityType.PLAYER))
+ dequipElytra((Player) event.getEntity());
+ }
+
+ private int firstEmptyFromBack(PlayerInventory inv) {
+ int z = -1;
+
+ for(int i = 35; i >= 9; i--) {
+ if(inv.getItem(i) == null) {
+ z = i;
+ break;
+ }
+ }
+
+ return z;
+ }
+
+ private void dequipElytra(Player player) {
+ PlayerInventory i = player.getInventory();
+ if (!( (i.getChestplate() != null) && i.getChestplate().getType().equals(Material.ELYTRA))) return;
+ if(player.getGameMode() == GameMode.CREATIVE) return;
+
+ ItemStack elytra = i.getChestplate();
+ i.setChestplate(null);
+ message(player);
+
+ // inventory full?
+ if (firstEmptyFromBack(i) != -1) {
+ i.setItem(firstEmptyFromBack(i), elytra);
+ player.updateInventory();
+ } else {
+ Location l = i.getLocation();
+ l.getWorld().dropItemNaturally(l, elytra);
+ player.updateInventory();
+ }
+ }
+
+ @EventHandler
+ public void onInteract(PlayerInteractEvent event) {
+ Action a = event.getAction();
+ if(a == Action.PHYSICAL || a == Action.LEFT_CLICK_AIR || a == Action.LEFT_CLICK_BLOCK) return;
+
+ if(event.getItem() == null) return;
+ if(event.getItem().getType() != Material.ELYTRA) return;
+ if(event.getPlayer().getGameMode() == GameMode.CREATIVE) return;
+ message(event.getPlayer());
+ dequipElytra(event.getPlayer());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/lv/pi/animalrp/listeners/PlayerChat.java b/src/main/java/lv/pi/animalrp/listeners/PlayerChat.java
new file mode 100644
index 0000000..ff68e3b
--- /dev/null
+++ b/src/main/java/lv/pi/animalrp/listeners/PlayerChat.java
@@ -0,0 +1,56 @@
+package lv.pi.animalrp.listeners;
+
+import java.util.Random;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.jetbrains.annotations.NotNull;
+
+import io.papermc.paper.chat.ChatRenderer;
+import io.papermc.paper.event.player.AsyncChatEvent;
+import lv.pi.animalrp.animals.Animal;
+import lv.pi.animalrp.util.Mood;
+import net.kyori.adventure.audience.Audience;
+import net.kyori.adventure.text.Component;
+
+import net.kyori.adventure.text.format.TextColor;
+import lv.pi.animalrp.AnimalRP;
+
+class CustomChatRenderer implements ChatRenderer {
+ Animal animal;
+
+ public CustomChatRenderer(Animal animal) {
+ this.animal = animal;
+ }
+
+ @Override
+ public @NotNull Component render(@NotNull Player source, @NotNull Component sourceDisplayName, @NotNull Component message,
+ @NotNull Audience viewer) {
+ return Component
+ .text("<")
+ .append(sourceDisplayName.color(TextColor.fromHexString(animal.color)))
+ .append(Component.text(">"))
+ .appendSpace()
+ .append(AnimalRP.mm.deserialize(animal.chatTransformations(AnimalRP.mm.serialize(message))));
+ }
+};
+
+public class PlayerChat implements Listener {
+ Random random = new Random();
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onPlayerChat(final AsyncChatEvent event) {
+ Animal animal = AnimalRP.users.get(event.getPlayer().getUniqueId());
+
+ if(animal != null) {
+ if(random.nextDouble() < 0.08) {
+ event.getPlayer().getWorld().playSound(event.getPlayer().getLocation(), animal.moodSounds.get(Mood.HAPPY), 10F, 1);
+ }
+
+ event.renderer(new CustomChatRenderer(animal));
+ }
+ }
+}
+
diff --git a/src/main/java/lv/pi/animalrp/util/Cooldown.java b/src/main/java/lv/pi/animalrp/util/Cooldown.java
new file mode 100644
index 0000000..b39280d
--- /dev/null
+++ b/src/main/java/lv/pi/animalrp/util/Cooldown.java
@@ -0,0 +1,35 @@
+package lv.pi.animalrp.util;
+
+import com.google.gson.JsonObject;
+
+public class Cooldown {
+ public long timeCreated;
+ public Integer length;
+ public String type;
+
+ public long getTime() {
+ return this.timeCreated - (System.currentTimeMillis() - this.length);
+ }
+
+ public boolean isExpired() {
+ return this.getTime() <= 0;
+ }
+
+ public JsonObject toJson() {
+ JsonObject obj = new JsonObject();
+ obj.addProperty("timeCreated", this.timeCreated);
+ obj.addProperty("length", this.length);
+ obj.addProperty("type", this.type);
+
+ return obj;
+ }
+
+ public static Cooldown fromJson(JsonObject obj) {
+ Cooldown cldn = new Cooldown();
+ cldn.timeCreated = obj.get("timeCreated").getAsLong();
+ cldn.length = obj.get("length").getAsInt();
+ cldn.type = obj.get("type").getAsString();
+
+ return cldn;
+ }
+}
diff --git a/src/main/java/lv/pi/animalrp/util/Emote.java b/src/main/java/lv/pi/animalrp/util/Emote.java
new file mode 100644
index 0000000..1af2eef
--- /dev/null
+++ b/src/main/java/lv/pi/animalrp/util/Emote.java
@@ -0,0 +1,131 @@
+package lv.pi.animalrp.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import java.util.Map.Entry;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Color;
+import org.bukkit.Location;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+
+import lv.pi.animalrp.AnimalRP;
+
+
+public class Emote {
+ public enum Emotes {
+ HAPPY, UWU, RAWR
+ }
+
+ public static HashMap emotes = new HashMap();
+ private HashMap players = new HashMap();
+
+ static {
+ emotes.put(Emotes.HAPPY, new String[]{
+ "0010000000100",
+ "0101000001010",
+ "0000000000000",
+ "0000011100000"
+ });
+ emotes.put(Emotes.UWU, new String[]{
+ "0101000001010",
+ "0010000000100",
+ "0000000000000",
+ "0000011100000"
+ });
+
+ emotes.put(Emotes.RAWR, new String[]{
+ "0101000001010",
+ "0010000000100",
+ "0000000000000",
+ "0000011100000"
+ });
+ }
+
+ public Emote() {
+ Bukkit.getScheduler().scheduleSyncRepeatingTask(AnimalRP.getProvidingPlugin(AnimalRP.class), new Runnable() {
+ @Override
+ public void run() {
+ Set> playerset = players.entrySet();
+
+ for (Iterator> iterator = playerset.iterator(); iterator.hasNext(); ) {
+ Entry value = iterator.next();
+ Player plr = Bukkit.getPlayer(value.getKey());
+ if(plr == null) {
+ iterator.remove();
+ } else {
+ drawEmote(plr, value.getValue());
+ }
+ }
+ }
+ }, 5, 5);
+ }
+
+ public void drawEmote(Player player, Emotes emote) {
+ List locs = getEmoteLocs(player.getLocation(), emotes.get(emote), player.getLocation());
+ for (Location loc : locs) {
+ Particle.DustOptions dustOptions = new Particle.DustOptions(Color.WHITE, 0.5f);
+ player.spawnParticle(Particle.REDSTONE, loc, 15, 0, 0, 0, dustOptions);
+ }
+ }
+
+ public static List getEmoteLocs(Location loc, String[] ttEmote, Location rotationLoc) {
+ List> locations = new ArrayList<>();
+ int y = 0;
+ int distance = 10;
+ for (String s : ttEmote) {
+ List emoteTextLine = textToEmote(s);
+ List addLocs = new ArrayList<>();
+ for (int x = 0; x < emoteTextLine.size(); x++) {
+ float y2 = (float)y/((float)distance/2);
+ float side = (((float)emoteTextLine.get(x)/distance)-((float)ttEmote[0].length())/2/distance);
+ Vector rotation = rotationLoc.getDirection().normalize().setY(0);
+ Vector rot = rotation.crossProduct(new Vector(0, side, 0));
+ Location addLoc = loc.clone().add(rot);
+ addLoc.setY(loc.getY()+((float)ttEmote.length/distance-y2+2.25));
+ addLocs.add(addLoc);
+ }
+ locations.add(addLocs);
+ y++;
+ }
+
+ List locs = new ArrayList<>();
+
+ for (List listLocs : locations) {
+ locs.addAll(listLocs);
+ }
+
+
+ return locs;
+ }
+
+ private static List textToEmote(String textToEmote) {
+ List locs = new ArrayList<>();
+ for (int i=0; i out = new ArrayList<>();
+
+ Random y = new Random();
+
+ for (String word : words) {
+ if(y.nextBoolean()){
+ out.add(word);
+ continue;
+ };
+ if(word.startsWith("[") && word.endsWith("]")) {
+ out.add(word);
+ continue;
+ }
+
+ for(String[] replacing: this.replaces) {
+ word = word.replace(replacing[0], replacing[1]);
+ }
+
+ out.add(word);
+
+ if(y.nextDouble() < 0.12) out.add(this.expressions[y.nextInt(this.expressions.length)]);
+ }
+
+ return String.join(" ", out);
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
new file mode 100644
index 0000000..4f3c1d3
--- /dev/null
+++ b/src/main/resources/plugin.yml
@@ -0,0 +1,26 @@
+name: animalrp
+main: lv.pi.animalrp.AnimalRP
+version: 1.0.0
+api-version: 1.19
+commands:
+ tf:
+ usage: Become the animal of your dreams!
+ headpats:
+ aliases: [pats, pet]
+ usage: Pet someone! :3
+ kiss:
+ usage: Kiss someone! :3
+ bite:
+ aliases: lovebite
+ usage: Bite someone! (cutely)
+ purr:
+ aliases: [mrrow, meow]
+ usage: Purr to someone! :3
+ scratch:
+ usage: Scratch someone! Ow!
+ hug:
+ usage: Hug a person.
+ cuddle:
+ usage: Cuddle a person.
+ emote:
+ usage: Emote!
\ No newline at end of file