first commit

This commit is contained in:
yourfriendoss 2023-04-16 00:16:16 +03:00
commit aecaab67ac
19 changed files with 1265 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
target/

4
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,4 @@
{
"java.configuration.updateBuildConfiguration": "automatic",
"java.compile.nullAnalysis.mode": "disabled"
}

132
pom.xml Normal file
View file

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>lv.pi.animalrp</groupId>
<artifactId>animalrp</artifactId>
<version>1.0.0</version>
<name>animalrp</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<repository>
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>codemc-releases</id>
<url>https://repo.codemc.org/repository/maven-releases/</url>
</repository>
<repository>
<id>sonatype-oss-snapshots1</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.19.4-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.13.0</version>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-legacy</artifactId>
<version>4.13.0</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>animalrp</shadedClassifierName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>net.md-5</groupId>
<artifactId>specialsource-maven-plugin</artifactId>
<version>1.2.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>remap</goal>
</goals>
<id>remap-obf</id>
<configuration>
<srgIn>org.spigotmc:minecraft-server:1.19.4-R0.1-SNAPSHOT:txt:maps-mojang</srgIn>
<reverse>true</reverse>
<remappedDependencies>org.spigotmc:spigot:1.19.4-R0.1-SNAPSHOT:jar:remapped-mojang</remappedDependencies>
<remappedArtifactAttached>true</remappedArtifactAttached>
<remappedClassifierName>remapped-obf</remappedClassifierName>
</configuration>
</execution>
<execution>
<phase>package</phase>
<goals>
<goal>remap</goal>
</goals>
<id>remap-spigot</id>
<configuration>
<inputFile>${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar</inputFile>
<srgIn>org.spigotmc:minecraft-server:1.19.4-R0.1-SNAPSHOT:csrg:maps-spigot</srgIn>
<remappedDependencies>org.spigotmc:spigot:1.19.4-R0.1-SNAPSHOT:jar:remapped-obf</remappedDependencies>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

58
readme.md Normal file
View file

@ -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)

View file

@ -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<UUID, Animal> users = new HashMap<UUID, Animal>();
public static HashMap<UUID, Cooldown> cooldowns = new HashMap<UUID, Cooldown>();
public static HashMap<String, Animal> animals = new HashMap<String, Animal>();
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<String, String> usersReformatted = new HashMap<String, String>();
for (Entry<UUID,Animal> 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<String,JsonElement> 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<String,JsonElement> 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
}
}

View file

@ -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<Mood, Sound> moodSounds = new HashMap<Mood, Sound>();
public ArrayList<Material> superfoods = new ArrayList<Material>();
@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);
}

View file

@ -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<UUID> sneakers = new ArrayList<UUID>();
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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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("<red>You have <green>" + String.join(", ", Emote.emotes.keySet().stream().map(Emote.Emotes::name).map(String::toLowerCase).collect(Collectors.toSet())) + "</green> 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("<gray>I'm sorry console. :(</gray>"));
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("<red>Stopped emoting."));
AnimalRP.emotes.stopEmote(player.getUniqueId());
} else {
arg0.sendMessage(AnimalRP.mm.deserialize("<red>Emoting!"));
AnimalRP.emotes.playEmote(player.getUniqueId(), emote);
}
return true;
}
}

View file

@ -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("<gray>I'm sorry console. :(</gray>"));
return true;
}
Player player = (Player)sender;
Animal aplayer = AnimalRP.users.get(player.getUniqueId());
if(aplayer == null) {
player.sendMessage(AnimalRP.mm.deserialize("<gray>Only animals can interact with other animals :("));
return true;
}
if(args.length == 0) {
player.sendMessage(AnimalRP.mm.deserialize("<gray>Include a user!"));
return true;
}
Player splayer = Bukkit.getPlayer(args[0]);
if(splayer == null) {
player.sendMessage(AnimalRP.mm.deserialize("<gray>I can't find this player :("));
return true;
}
if(splayer.getName() == player.getName()) {
player.sendMessage(AnimalRP.mm.deserialize("<gray>You can't "+command+" yourself."));
return true;
}
Animal asplayer = AnimalRP.users.get(splayer.getUniqueId());
if(asplayer == null) {
player.sendMessage(AnimalRP.mm.deserialize("<gray>"+splayer.getName() + " is not an animal! :("));
return true;
}
splayer.sendMessage(AnimalRP.mm.deserialize(String.format(this.toThem, "<light_purple>"+player.getName()+"</light_purple>", "<italic><gray>"+aplayer.catchphrase+"</italic>")));
player.sendMessage(AnimalRP.mm.deserialize(String.format(this.toYou, "<light_purple>"+splayer.getName()+"</light_purple>", "<italic><gray>"+asplayer.catchphrase+"</italic>")));
player.getWorld().playSound(splayer.getLocation(), asplayer.moodSounds.get(this.mood), 1F, 1);
return true;
}
}

View file

@ -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<String> parts = new ArrayList<String>();
for (Entry<String,Animal> entry : AnimalRP.animals.entrySet()) {
parts.add("<"+entry.getValue().color+">"+entry.getKey()+"</"+entry.getValue().color+">");
}
player.sendMessage(AnimalRP.mm.deserialize("<green>Looking around you, you have <dark_green>\"" + String.join(", ", parts) + "\"<green> as options."));
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if(!(sender instanceof Player)) {
sender.sendMessage(AnimalRP.mm.deserialize("<gray>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("<green>You start splitting apart, dropping your <blue>" + previous.name+"-like<green> 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("<red>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("<gray>You're <blue>" + previous.name + "</blue> already! " + animal.catchphrase));
return true;
}
player.sendMessage(AnimalRP.mm.deserialize("<green>You slowly transform, from <blue>" + previous.name + "<green> to.. <blue>" + animal.name + ". "+ animal.catchphrase));
} else {
player.sendMessage(AnimalRP.mm.deserialize("<green>You slowly transform, to.. <blue>" + animal.name + "<green>. "+ 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;
}
}

View file

@ -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("<red>Elytras are not allowed to be worn. You <green>can still trade with them <red>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());
}
}

View file

@ -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));
}
}
}

View file

@ -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;
}
}

View file

@ -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, String[]> emotes = new HashMap<Emotes, String[]>();
private HashMap<UUID, Emotes> players = new HashMap<UUID, Emotes>();
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<Entry<UUID, Emotes>> playerset = players.entrySet();
for (Iterator<Entry<UUID, Emotes>> iterator = playerset.iterator(); iterator.hasNext(); ) {
Entry<UUID, Emotes> 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<Location> 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<Location> getEmoteLocs(Location loc, String[] ttEmote, Location rotationLoc) {
List<List<Location>> locations = new ArrayList<>();
int y = 0;
int distance = 10;
for (String s : ttEmote) {
List<Integer> emoteTextLine = textToEmote(s);
List<Location> 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<Location> locs = new ArrayList<>();
for (List<Location> listLocs : locations) {
locs.addAll(listLocs);
}
return locs;
}
private static List<Integer> textToEmote(String textToEmote) {
List<Integer> locs = new ArrayList<>();
for (int i=0; i<textToEmote.length(); i++) {
char l = textToEmote.charAt(i);
String letter = String.valueOf(l);
if (letter.equals("1")) {
locs.add(i);
}
}
return locs;
}
public void playEmote(UUID uuid, Emotes emote) {
this.players.put(uuid, emote);
}
public void stopEmote(UUID uuid) {
this.players.remove(uuid);
}
public boolean isPlayerEmoting(UUID uuid) {
return this.players.containsKey(uuid);
}
}

View file

@ -0,0 +1,5 @@
package lv.pi.animalrp.util;
public enum Mood {
HAPPY,SAD,STRESSED,ANGRY,CUTE
}

View file

@ -0,0 +1,43 @@
package lv.pi.animalrp.util;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class TextDestroyer {
String[] expressions;
String[][] replaces;
public TextDestroyer(String[] expressions, String[][] replaces) {
this.expressions = expressions;
this.replaces = replaces;
}
public String destroy(String message) {
final String[] words = message.split(" ");
final List<String> 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);
}
}

View file

@ -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!