Skip to content

Commit a7a35e0

Browse files
authored
2.1.6-PRE
This update contains mainly bugfixes and some improvements. ### Improved: * Work of pet cooldowns * Performance when pets follow you ### Fixed: * Many possible NPEs (such as #124) * Error on EntityDamageByEntityEvent (#130) * Pet duplication after teleportaton (#110) * Copy the horse's brand bug (#120)
2 parents c0a62cf + c13d909 commit a7a35e0

File tree

12 files changed

+274
-79
lines changed

12 files changed

+274
-79
lines changed

src/main/java/ru/endlesscode/rpginventory/api/PetAPI.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,25 @@
3535
@SuppressWarnings({"unused", "WeakerAccess"})
3636
public class PetAPI {
3737
/**
38-
* Get pet spawn item from RPGInventory of specific player
38+
* Get pet spawn item from RPGInventory of specific player.
3939
*
4040
* @param player - not null player
4141
* @return ItemStack if player have pet spawn item, null - otherwise
4242
*/
4343
@Nullable
4444
public static ItemStack getPetItem(Player player) {
45+
if (!InventoryManager.playerIsLoaded(player) || !PetManager.isEnabled()) {
46+
return null;
47+
}
48+
4549
PlayerWrapper playerWrapper = InventoryManager.get(player);
46-
ItemStack petItem = PetManager.isEnabled() && playerWrapper != null ? playerWrapper.getInventory().getItem(PetManager.getPetSlotId()) : null;
50+
ItemStack petItem = playerWrapper.getInventory().getItem(PetManager.getPetSlotId());
4751

4852
return ItemUtils.isEmpty(petItem) ? null : petItem;
4953
}
5054

5155
/**
52-
* Get Pet of specific player
56+
* Get Pet of specific player.
5357
*
5458
* @param player - not null player
5559
* @return Pet if player have pet, null - otherwise

src/main/java/ru/endlesscode/rpginventory/event/listener/CraftListener.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public void onPacketSending(@NotNull PacketEvent event) {
6060
Player player = event.getPlayer();
6161
//noinspection ConstantConditions
6262
if (event.isCancelled() || !InventoryManager.playerIsLoaded(player)
63-
|| isNotNeededHere(player)) {
63+
|| isExtensionsNotNeededHere(player)) {
6464
return;
6565
}
6666

@@ -84,7 +84,7 @@ public void onInventoryOpen(@NotNull InventoryOpenEvent event) {
8484
final Player player = (Player) event.getPlayer();
8585
if (!InventoryManager.playerIsLoaded(player)
8686
|| event.getInventory().getType() != InventoryType.WORKBENCH
87-
|| isNotNeededHere(player)) {
87+
|| isExtensionsNotNeededHere(player)) {
8888
return;
8989
}
9090

@@ -98,7 +98,7 @@ public void onInventoryClick(@NotNull InventoryClickEvent event) {
9898
//noinspection ConstantConditions
9999
if (!InventoryManager.playerIsLoaded(player)
100100
|| event.getInventory().getType() != InventoryType.WORKBENCH
101-
|| isNotNeededHere(player)) {
101+
|| isExtensionsNotNeededHere(player)) {
102102
return;
103103
}
104104

@@ -114,7 +114,13 @@ public void onInventoryClick(@NotNull InventoryClickEvent event) {
114114
}
115115
}
116116

117-
private boolean isNotNeededHere(Player player) {
117+
/**
118+
* Checks that inventory extensions not needed there.
119+
* It always should be used after `InventoryManager.playerIsLoaded(player)` check.
120+
*
121+
* @param player Player to check
122+
*/
123+
private boolean isExtensionsNotNeededHere(Player player) {
118124
return !InventoryManager.get(player).isPocketCraft()
119125
&& !Config.getConfig().getBoolean("craft.workbench", true);
120126
}

src/main/java/ru/endlesscode/rpginventory/event/listener/InventoryListener.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -262,13 +262,15 @@ public void onInventoryClick(@NotNull final InventoryClickEvent event) {
262262

263263
// Crafting area
264264
if (inventory.getType() == InventoryType.CRAFTING) {
265-
if (InventoryManager.get(player).isOpened()) {
265+
PlayerWrapper playerWrapper = InventoryManager.get(player);
266+
267+
if (playerWrapper.isOpened()) {
266268
return;
267269
}
268270

269271
switch (event.getSlotType()) {
270272
case CRAFTING:
271-
InventoryManager.get(player).openInventory(true);
273+
playerWrapper.openInventory(true);
272274
case QUICKBAR:
273275
// Shield slot is QUICKBAR and has rawId - 45 o.O
274276
if (rawSlot != 45) {
@@ -491,10 +493,8 @@ public void onWorldChanged(@NotNull PlayerChangedWorldEvent event) {
491493

492494
if (!InventoryManager.isAllowedWorld(player.getWorld())) {
493495
InventoryManager.unloadPlayerInventory(player);
494-
} else {
495-
if (InventoryManager.get(player).hasPet()) {
496-
PetManager.respawnPet(player);
497-
}
496+
} else if (InventoryManager.get(player).hasPet()) {
497+
PetManager.respawnPet(player);
498498
}
499499
}
500500
}

src/main/java/ru/endlesscode/rpginventory/event/listener/PetListener.java

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,21 @@
1818

1919
package ru.endlesscode.rpginventory.event.listener;
2020

21-
import org.bukkit.GameMode;
22-
import org.bukkit.Location;
23-
import org.bukkit.Material;
24-
import org.bukkit.OfflinePlayer;
25-
import org.bukkit.Sound;
21+
import org.bukkit.*;
2622
import org.bukkit.entity.*;
2723
import org.bukkit.event.EventHandler;
2824
import org.bukkit.event.EventPriority;
2925
import org.bukkit.event.Listener;
3026
import org.bukkit.event.block.Action;
31-
import org.bukkit.event.entity.EntityDamageByEntityEvent;
32-
import org.bukkit.event.entity.EntityDeathEvent;
33-
import org.bukkit.event.entity.EntityPortalEnterEvent;
34-
import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
35-
import org.bukkit.event.entity.PlayerDeathEvent;
27+
import org.bukkit.event.entity.*;
3628
import org.bukkit.event.inventory.InventoryOpenEvent;
37-
import org.bukkit.event.player.PlayerInteractEntityEvent;
38-
import org.bukkit.event.player.PlayerInteractEvent;
39-
import org.bukkit.event.player.PlayerMoveEvent;
40-
import org.bukkit.event.player.PlayerRespawnEvent;
29+
import org.bukkit.event.player.*;
4130
import org.bukkit.event.vehicle.VehicleEnterEvent;
4231
import org.bukkit.inventory.HorseInventory;
4332
import org.bukkit.inventory.Inventory;
4433
import org.bukkit.inventory.ItemStack;
4534
import org.bukkit.scheduler.BukkitRunnable;
46-
import org.jetbrains.annotations.*;
35+
import org.jetbrains.annotations.NotNull;
4736
import ru.endlesscode.rpginventory.RPGInventory;
4837
import ru.endlesscode.rpginventory.inventory.InventoryManager;
4938
import ru.endlesscode.rpginventory.inventory.PlayerWrapper;
@@ -119,6 +108,39 @@ public void onPlayerRespawn(@NotNull PlayerRespawnEvent event) {
119108
}
120109
}
121110

111+
//Possible fix #110
112+
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
113+
public void onPlayerTeleport(@NotNull PlayerTeleportEvent event) {
114+
Player player = event.getPlayer();
115+
116+
if (!InventoryManager.playerIsLoaded(player) || !PetManager.isEnabled()) {
117+
return;
118+
}
119+
120+
if (!InventoryManager.get(player).hasPet()) {
121+
return;
122+
}
123+
124+
//Ugly trick to avoid infinite pet spawning when player teleports from non-solid/non-cuboid block
125+
final Location from = event.getFrom();
126+
final Location to = event.getTo();
127+
if (from.getBlockX() != to.getBlockX() || from.getBlockZ() != to.getBlockZ()) {
128+
return;
129+
}
130+
if (from.distance(to) < 0.775D) {
131+
return;
132+
}
133+
134+
final double maxDistance = (event.getPlayer().getServer().getViewDistance() / 2.0D) * 15.75D;
135+
final ItemStack item = InventoryManager.get(player).getInventory().getItem(PetManager.getPetSlotId());
136+
if (from.distance(to) > maxDistance && item != null) {
137+
PetManager.spawnPet(player, item);
138+
} else {
139+
PetManager.teleportPet(player, to);
140+
}
141+
142+
}
143+
122144
@EventHandler
123145
public void onPetFeed(@NotNull PlayerInteractEntityEvent event) {
124146
Player player = event.getPlayer();

src/main/java/ru/endlesscode/rpginventory/inventory/InventoryManager.java

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
package ru.endlesscode.rpginventory.inventory;
2020

21+
import com.comphenix.protocol.*;
2122
import org.bukkit.Material;
2223
import org.bukkit.OfflinePlayer;
2324
import org.bukkit.World;
@@ -52,10 +53,7 @@
5253
import java.io.IOException;
5354
import java.nio.file.Files;
5455
import java.nio.file.Path;
55-
import java.util.HashMap;
56-
import java.util.List;
57-
import java.util.Map;
58-
import java.util.UUID;
56+
import java.util.*;
5957

6058
@SuppressWarnings("ResultOfMethodCallIgnored")
6159
public class InventoryManager {
@@ -549,14 +547,13 @@ public static void savePlayerInventory(@NotNull Player player) {
549547
}
550548
}
551549

552-
public static PlayerWrapper get(@Nullable OfflinePlayer player) {
553-
if (player == null) {
554-
throw new IllegalArgumentException("OfflinePlayer can not be null!");
555-
}
550+
@NotNull
551+
public static PlayerWrapper get(@NotNull OfflinePlayer player) {
556552
PlayerWrapper playerWrapper = InventoryManager.INVENTORIES.get(player.getUniqueId());
557553
if (playerWrapper == null) {
558-
throw new IllegalArgumentException(player.getName() + "'s inventory is not loaded!");
554+
throw new IllegalStateException("" + player.getName() + "'s inventory should be initialized!");
559555
}
556+
560557
return playerWrapper;
561558
}
562559

src/main/java/ru/endlesscode/rpginventory/inventory/slot/SlotManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.util.ArrayList;
3333
import java.util.List;
3434
import java.util.Objects;
35+
import java.util.logging.Level;
3536

3637
/**
3738
* Created by OsipXD on 05.09.2015
@@ -79,7 +80,7 @@ public static boolean init() {
7980
try {
8081
SlotManager.slotManager = new SlotManager();
8182
} catch (Exception e) {
82-
e.printStackTrace();
83+
RPGInventory.getPluginLogger().log(Level.WARNING, "Failed to initialize SlotManager", e);
8384
return false;
8485
}
8586

src/main/java/ru/endlesscode/rpginventory/pet/CooldownTimer.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@
3535
* It is part of the RpgInventory.
3636
* All rights reserved 2014 - 2016 © «EndlessCode Group»
3737
*/
38+
@Deprecated
3839
class CooldownTimer extends BukkitRunnable {
3940
private final Player player;
4041
private final ItemStack petItem;
4142

43+
@Deprecated
4244
public CooldownTimer(Player player, ItemStack petItem) {
4345
this.player = player;
4446
this.petItem = petItem;
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package ru.endlesscode.rpginventory.pet;
2+
3+
import org.bukkit.Material;
4+
import org.bukkit.entity.Player;
5+
import org.bukkit.inventory.Inventory;
6+
import org.bukkit.inventory.ItemStack;
7+
import org.bukkit.inventory.meta.ItemMeta;
8+
import org.bukkit.scheduler.BukkitRunnable;
9+
import ru.endlesscode.rpginventory.RPGInventory;
10+
import ru.endlesscode.rpginventory.inventory.InventoryManager;
11+
import ru.endlesscode.rpginventory.inventory.slot.Slot;
12+
import ru.endlesscode.rpginventory.inventory.slot.SlotManager;
13+
import ru.endlesscode.rpginventory.utils.ItemUtils;
14+
15+
import java.util.*;
16+
import java.util.concurrent.atomic.AtomicInteger;
17+
18+
/**
19+
* Created by Dereku on 17.04.2018
20+
* It is part of the RpgInventory.
21+
* All rights reserved 2014 - 2018 © «EndlessCode Group»
22+
*/
23+
public class CooldownsTimer extends BukkitRunnable {
24+
25+
public final static int TICK_PERIOD = 5;
26+
private final static int TICK_RATE = 20 / CooldownsTimer.TICK_PERIOD;
27+
//temporaryMap for avoid CME.
28+
private final HashMap<UUID, ValuePair> petItemsByPlayer = new HashMap<>(), temporaryMap = new HashMap<>();
29+
private final RPGInventory plugin;
30+
private final Slot petSlot;
31+
32+
@SuppressWarnings("WeakerAccess")
33+
public CooldownsTimer(RPGInventory pluginInstance) {
34+
this.plugin = pluginInstance;
35+
this.petSlot = Objects.requireNonNull(SlotManager.instance().getPetSlot(), "Pet slot can't be null!");
36+
}
37+
38+
public void addPetCooldown(Player player, ItemStack itemStack) {
39+
if (player == null || itemStack == null || itemStack.getType() == Material.AIR) {
40+
//throw new IllegalArgumentException?
41+
return;
42+
}
43+
44+
if (PetManager.getPetFromItem(itemStack) == null) {
45+
//throw new IllegalArgumentException?
46+
return;
47+
}
48+
49+
this.temporaryMap.put(player.getUniqueId(), new ValuePair(itemStack, new AtomicInteger(0)));
50+
51+
}
52+
53+
@Override
54+
public void run() {
55+
//Because there is no safe way to iterate map.
56+
if (!this.temporaryMap.isEmpty()) {
57+
this.petItemsByPlayer.putAll(this.temporaryMap);
58+
this.temporaryMap.clear();
59+
}
60+
61+
final Iterator<Map.Entry<UUID, ValuePair>> iterator = this.petItemsByPlayer.entrySet().iterator();
62+
while (iterator.hasNext()) {
63+
final Map.Entry<UUID, ValuePair> next = iterator.next();
64+
int ticks = next.getValue().getTimer().incrementAndGet();
65+
66+
if (ticks % CooldownsTimer.TICK_RATE != 0) {
67+
continue;
68+
}
69+
70+
final Player player = this.plugin.getServer().getPlayer(next.getKey());
71+
if (player == null || !InventoryManager.playerIsLoaded(player)) {
72+
iterator.remove();
73+
continue;
74+
}
75+
76+
final Inventory inventory = InventoryManager.get(player).getInventory();
77+
if (inventory == null || inventory.getItem(PetManager.getPetSlotId()) == null) {
78+
iterator.remove();
79+
continue;
80+
}
81+
82+
//Future bug fix of multiple pets cooldown
83+
//TODO: Improve that. If we need it, ofc.
84+
/*if (!inventory.getItem(PetManager.getPetSlotId()).isSimilar(next.getValue().getItemStack())) {
85+
iterator.remove();
86+
continue;
87+
}*/
88+
89+
int cooldown = PetManager.getCooldown(next.getValue().getItemStack());
90+
if (1 > cooldown) {
91+
PetManager.saveDeathTime(next.getValue().getItemStack(), 0);
92+
PetManager.spawnPet(player, next.getValue().getItemStack());
93+
inventory.setItem(PetManager.getPetSlotId(), next.getValue().getItemStack());
94+
iterator.remove();
95+
} else if (60 >= cooldown) {
96+
final ItemStack item = next.getValue().getItemStack().clone();
97+
final ItemMeta itemMeta = item.getItemMeta();
98+
itemMeta.setDisplayName(
99+
itemMeta.getDisplayName() + RPGInventory.getLanguage().getMessage("pet.cooldown", cooldown)
100+
);
101+
item.setItemMeta(itemMeta);
102+
PetManager.addGlow(item);
103+
104+
String itemTag = ItemUtils.getTag(item, ItemUtils.PET_TAG);
105+
if (itemTag != null) {
106+
ItemUtils.setTag(item, ItemUtils.PET_TAG, itemTag);
107+
inventory.setItem(PetManager.getPetSlotId(), item);
108+
} else {
109+
inventory.setItem(PetManager.getPetSlotId(), this.petSlot.getCup());
110+
iterator.remove();
111+
}
112+
}
113+
}
114+
}
115+
116+
private class ValuePair {
117+
private final ItemStack itemStack;
118+
private final AtomicInteger timer;
119+
120+
private ValuePair(ItemStack itemStack, AtomicInteger timer) {
121+
this.itemStack = itemStack;
122+
this.timer = timer;
123+
}
124+
125+
private ItemStack getItemStack() {
126+
return itemStack;
127+
}
128+
129+
private AtomicInteger getTimer() {
130+
return timer;
131+
}
132+
}
133+
}

0 commit comments

Comments
 (0)