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 + 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()+""); + } + + 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