From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: montlikadani <montlikada@gmail.com>
Date: Fri, 13 Nov 2020 17:52:40 +0100
Subject: [PATCH] Add adjustable breeding cooldown to config


diff --git a/src/main/java/net/minecraft/world/entity/animal/Animal.java b/src/main/java/net/minecraft/world/entity/animal/Animal.java
index 43841b5c77beb73169e2ff1645afe1234d8f74c7..d5d9f8e9c7119ae159a085aa414fc7f303be72a5 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Animal.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Animal.java
@@ -145,7 +145,7 @@ public abstract class Animal extends AgeableMob {
         if (this.isFood(itemstack)) {
             int i = this.getAge();
 
-            if (!this.level.isClientSide && i == 0 && this.canFallInLove()) {
+            if (!this.level.isClientSide && i == 0 && this.canFallInLove() && (this.level.purpurConfig.animalBreedingCooldownSeconds <= 0 || !this.level.hasBreedingCooldown(player.getUUID(), this.getClass()))) { // Purpur
                 this.usePlayerItem(player, hand, itemstack);
                 this.setInLove(player);
                 this.gameEvent(GameEvent.MOB_INTERACT, this.eyeBlockPosition());
@@ -239,6 +239,14 @@ public abstract class Animal extends AgeableMob {
             if (entityplayer == null && other.getLoveCause() != null) {
                 entityplayer = other.getLoveCause();
             }
+            // Purpur start
+            if (entityplayer != null && world.purpurConfig.animalBreedingCooldownSeconds > 0) {
+                if (world.hasBreedingCooldown(entityplayer.getUUID(), this.getClass())) {
+                    return;
+                }
+                world.addBreedingCooldown(entityplayer.getUUID(), this.getClass());
+            }
+            // Purpur end
             // CraftBukkit start - call EntityBreedEvent
             entityageable.setBaby(true);
             entityageable.moveTo(this.getX(), this.getY(), this.getZ(), 0.0F, 0.0F);
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 514e4ff64275a45ddd9aa4e0c8245aaa5483306c..27674fb28825b48eee86b93d6bbd1e7af94c0fe0 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -188,6 +188,49 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
     }
     // Paper end - fix and optimise world upgrading
 
+    // Purpur start
+    private com.google.common.cache.Cache<BreedingCooldownPair, Object> playerBreedingCooldowns;
+
+    private com.google.common.cache.Cache<BreedingCooldownPair, Object> getNewBreedingCooldownCache() {
+        return com.google.common.cache.CacheBuilder.newBuilder().expireAfterWrite(this.purpurConfig.animalBreedingCooldownSeconds, java.util.concurrent.TimeUnit.SECONDS).build();
+    }
+
+    public void resetBreedingCooldowns() {
+        this.playerBreedingCooldowns = this.getNewBreedingCooldownCache();
+    }
+
+    public boolean hasBreedingCooldown(java.util.UUID player, Class<? extends net.minecraft.world.entity.animal.Animal> animalType) { // Purpur
+        return this.playerBreedingCooldowns.getIfPresent(new BreedingCooldownPair(player, animalType)) != null;
+    }
+
+    public void addBreedingCooldown(java.util.UUID player, Class<? extends net.minecraft.world.entity.animal.Animal> animalType) {
+        this.playerBreedingCooldowns.put(new BreedingCooldownPair(player, animalType), new Object());
+    }
+
+    private static final class BreedingCooldownPair {
+        private final java.util.UUID playerUUID;
+        private final Class<? extends net.minecraft.world.entity.animal.Animal> animalType;
+
+        public BreedingCooldownPair(java.util.UUID playerUUID, Class<? extends net.minecraft.world.entity.animal.Animal> animalType) {
+            this.playerUUID = playerUUID;
+            this.animalType = animalType;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            BreedingCooldownPair that = (BreedingCooldownPair) o;
+            return playerUUID.equals(that.playerUUID) && animalType.equals(that.animalType);
+        }
+
+        @Override
+        public int hashCode() {
+            return java.util.Objects.hash(playerUUID, animalType);
+        }
+    }
+    // Purpur end
+
     public CraftWorld getWorld() {
         return this.world;
     }
@@ -319,6 +362,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
         this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper
         this.tuinityConfig = new com.tuinity.tuinity.config.TuinityConfig.WorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData)worlddatamutable).getLevelName()); // Tuinity - Server Config
         this.purpurConfig = new net.pl3x.purpur.PurpurWorldConfig((ServerLevel) this, ((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), env); // Purpur
+        this.playerBreedingCooldowns = this.getNewBreedingCooldownCache(); // Purpur
         this.generator = gen;
         this.world = new CraftWorld((ServerLevel) this, gen, env);
         this.ticksPerAnimalSpawns = this.getCraftServer().getTicksPerAnimalSpawns(); // CraftBukkit
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
index 74544421716246a73876f4a39711ee25438a8f2c..db50fe00f2e725d0ab44f8704443cf6107e39d4e 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -354,6 +354,7 @@ public class PurpurWorldConfig {
     public double voidDamageHeight = -64.0D;
     public double voidDamageDealt = 4.0D;
     public int raidCooldownSeconds = 0;
+    public int animalBreedingCooldownSeconds = 0;
     private void miscGameplayMechanicsSettings() {
         useBetterMending = getBoolean("gameplay-mechanics.use-better-mending", useBetterMending);
         boatEjectPlayersOnLand = getBoolean("gameplay-mechanics.boat.eject-players-on-land", boatEjectPlayersOnLand);
@@ -365,6 +366,7 @@ public class PurpurWorldConfig {
         voidDamageHeight = getDouble("gameplay-mechanics.void-damage-height", voidDamageHeight);
         voidDamageDealt = getDouble("gameplay-mechanics.void-damage-dealt", voidDamageDealt);
         raidCooldownSeconds = getInt("gameplay-mechanics.raid-cooldown-seconds", raidCooldownSeconds);
+        animalBreedingCooldownSeconds = getInt("gameplay-mechanics.animal-breeding-cooldown-seconds", animalBreedingCooldownSeconds);
     }
 
     public Set<Block> noRandomTickBlocks = new HashSet<>();
diff --git a/src/main/java/net/pl3x/purpur/command/PurpurCommand.java b/src/main/java/net/pl3x/purpur/command/PurpurCommand.java
index 6e7f56fe2b78d7a09d5d130f2c88338fb8ae628e..cd63e9e556fa4931ab33c63931cf916757c51a62 100644
--- a/src/main/java/net/pl3x/purpur/command/PurpurCommand.java
+++ b/src/main/java/net/pl3x/purpur/command/PurpurCommand.java
@@ -49,6 +49,7 @@ public class PurpurCommand extends Command {
             PurpurConfig.init((File) console.options.valueOf("purpur-settings"));
             for (ServerLevel level : console.getAllLevels()) {
                 level.purpurConfig.init();
+                level.resetBreedingCooldowns();
             }
             console.server.reloadCount++;
 
