Food bait for animals
Requires: FakePlayer & ProtocolLib
Requires: FakePlayer & ProtocolLib
const ProtocolLib = Services.get("ProtocolLib");
var activeBaits = [];
var fakeIds = [];
var soundCoordinates = [];
const Bukkit = org.bukkit.Bukkit;
const dispatch = Bukkit.dispatchCommand;
const ItemStack = org.bukkit.inventory.ItemStack
const NamespacedKey = org.bukkit.NamespacedKey
const PersistentDataType = org.bukkit.persistence.PersistentDataType
const console = Bukkit.getConsoleSender();
const server = Bukkit.getServer();
const baitIndicator = "isBait";
const ArmorStand = org.bukkit.entity.ArmorStand;
const FileName = "BaitData"
const BaitsKey = "Baits";
const pickUpDistance = 3; // Blocks
const IdLenght = 16;
const respawnLenght = 32;
DiskApi.loadFile(FileName, false, false);
function RunCommand(command) {
task.main(function() {
dispatch(console, command);
});
}
function getEntityById(id) {
for (const world of server.getWorlds()) {
for (const entity of world.getEntities()) {
if (entity.getEntityId() === id) return entity;
}
}
return null;
}
function ArrayContains(Array, Value) {
for (let i in Array) {
if (Array[i] == Value) {
return true
}
}
return false
}
function GetStoredBaits() {
let raw = DiskApi.getVar(FileName, "baitsData", "");
return raw ? raw.split("|") : [];
}
function calculateDistance(loc1, loc2) {
return loc1.distance(loc2);
}
function StoreBait(itemID) {
let raw = DiskApi.getVar(FileName, "baitsData", "");
const parts = raw ? raw.split("|") : [];
if (!ArrayContains(parts, itemID)) {
parts.push(itemID);
}
DiskApi.setVar(FileName, "baitsData", parts.join("|"));
}
function UnstoreBait(itemID) {
let raw = DiskApi.getVar(FileName, "baitsData", "");
const parts = raw ? raw.split("|") : [];
const filtered = parts.filter(p => p !== itemID);
DiskApi.setVar(FileName, "baitsData", filtered.join("|"));
}
function isFakePlayer(entity) {
if (!entity) return false;
return fakeIds[entity.getName()];
}
function getEntityID(entity) {
var type = entity.getType().name().toLowerCase();
var customName = entity.getCustomName();
if (customName) {
return customName.replace(type+"_", "");
}
}
function getEntityByCustomName(customName) {
for (const world of server.getWorlds()) {
for (const entity of world.getEntities()) {
const name = getEntityID(entity);
if (name && name.equals(customName)) {
return entity;
}
}
}
return null;
}
function getItemByUniqueID(uniqueID) {
for (const world of server.getWorlds()) {
for (const entity of world.getEntitiesByClass(Packages.org.bukkit.entity.Item.class)) {
if (entity.getUniqueId().toString() === uniqueID) {
return entity;
}
}
}
return null;
}
function setEntityID(entity, baitID) {
var type = entity.getType().name().toLowerCase();
entity.setCustomName(type + "_" + baitID);
}
function isFakeEntity(entity) {
if (!entity) return false;
var ID = getEntityID(entity);
if (!ID) return false;
return fakeIds[ID];
}
function markItemAsBait(item) {
const meta = item.getItemMeta();
meta.getPersistentDataContainer().set(
NamespacedKey.minecraft("baititem"),
PersistentDataType.STRING,
"true"
);
item.setItemMeta(meta);
}
function isBaitItem(item) {
if (!item || !item.hasItemMeta()) return false;
const meta = item.getItemMeta();
return meta.getPersistentDataContainer().has(
NamespacedKey.minecraft("baititem"),
PersistentDataType.STRING
);
}
function isInventoryFull(player, stackableItem) {
const inv = player.getInventory();
const maxStack = stackableItem.getMaxStackSize();
const type = stackableItem.getType();
const meta = stackableItem.hasItemMeta() ? stackableItem.getItemMeta() : null;
for (let i = 0; i < inv.getSize(); i++) {
const item = inv.getItem(i);
if (!item) return false;
if (
item.getType() === type &&
item.getAmount() < maxStack &&
(meta == null || (item.hasItemMeta() && item.getItemMeta().equals(meta)))
) {
return false;
}
}
return true;
}
function givePlayerBaitItem(player, material) {
const item = new ItemStack(material, 1);
var materialName = material.name();
var constructedMatName = (materialName[0] + String(materialName).slice(1).toLowerCase()).replace("_", " ");
var itemMeta = item.getItemMeta();
itemMeta.setDisplayName("§6" + constructedMatName + "§7 §eBait§7");
item.setItemMeta(itemMeta);
markItemAsBait(item);
if ( player.getInventory().addItem(item).isEmpty() ) {
player.sendMessage("§6" + constructedMatName + "§7 §eBait§7 has been added to your inventory!")
return true
} else {
return false
}
}
function createPickupArmorStand(item, BaitID) {
const loc = item.getLocation().clone();
loc.setY(loc.getY() - 0.3);
const stand = item.getWorld().spawn(loc, ArmorStand.class);
setEntityID(stand, BaitID);
stand.setInvisible(true);
stand.setSmall(true);
stand.setGravity(false);
stand.setInvulnerable(true);
stand.setCollidable(false);
stand.setSilent(true);
return stand;
}
ProtocolLib.registerListener("NORMAL", {
onSend(event) {
const packet = event.getPacket();
const type = event.getPacketType().name();
const entityId = packet.getIntegers().read(0);
const entity = getEntityById(entityId);
if (entity && isFakePlayer(entity)) {
event.setCancelled(true);
}
}
}, ["Play.Server.SPAWN_ENTITY"]);
ProtocolLib.registerListener("NORMAL", {
onSend(event) {
const packet = event.getPacket();
const entries = packet.getPlayerInfoDataLists().read(1);
if (!entries || entries.isEmpty()) return;
entries.removeIf(entry =>
entry == null || fakeIds[entry.getProfile().getName()]
);
packet.getPlayerInfoDataLists().write(1, entries);
}
}, ["Play.Server.PLAYER_INFO"]);
ProtocolLib.registerListener("NORMAL", {
onSend(event) {
const packet = event.getPacket();
const soundData = packet.getIntegers();
const x = soundData.read(0) / 8.0;
const y = soundData.read(1) / 8.0;
const z = soundData.read(2) / 8.0;
for (const loc of soundCoordinates) {
if ((Math.abs(loc.getX() - x) + Math.abs(loc.getY() - y) + Math.abs(loc.getZ() - z)) <= 0.4) {
event.setCancelled(true);
return;
}
}
}
}, ["Play.Server.NAMED_SOUND_EFFECT"]);
function getBaitID(item) {
return item.getUniqueId().toString().replace(/-/g, "").substring(0, IdLenght);
}
function UniqueToBaitID(uniqueId) {
return uniqueId.toString().replace(/-/g, "").substring(0, IdLenght);
}
function spawnFakePlayer(Name, location, waitForPlayer) {
const world = location.getWorld().getKey().toString();
const x = location.getX();
const y = location.getY();
const z = location.getZ();
RunCommand(`fp spawn ${Name} ${world} ${x} ${y} ${z}`);
soundCoordinates.push(location)
task.delay(0.5, function () {
const index = soundCoordinates.indexOf(location);
if (index !== -1) soundCoordinates.splice(index, 1);
});
if (waitForPlayer) {
var fakeplayer = Bukkit.getPlayer(Name);
if (!fakeplayer) {
while (!fakeplayer) {
task.wait(0.01);
fakeplayer = Bukkit.getPlayer(Name);
}
}
task.main(function() {
fakeplayer.teleport(location)
})
return fakeplayer
}
}
function updateFakePlayer(fakeplayer, material) {
return task.main(function () {
fakeplayer.setCollidable(false);
fakeplayer.setSilent(true);
fakeplayer.setGameMode(org.bukkit.GameMode.CREATIVE);
fakeplayer.setWalkSpeed(0);
fakeplayer.setFlySpeed(0);
fakeplayer.setFlying(true);
const inv = fakeplayer.getInventory();
inv.setItemInMainHand(new ItemStack(material));
})
}
function dropBait(item, player) {
var BaitID = getBaitID(item);
var armorStand = createPickupArmorStand(item, BaitID);
var material = item.getItemStack().getType();
var materialName = material.name();
var constructedMatName = (materialName[0] + String(materialName).slice(1).toLowerCase()).replace("_", " ");
var baitData = {};
baitData["id"] = BaitID;
baitData["storeID"] = StoreBait(item.getUniqueId().toString());
baitData["item"] = item;
baitData["armorStand"] = armorStand;
baitData["tasks"] = [];
fakeIds[BaitID] = true; // anything spawned with this ID is a bait
item.setPickupDelay(9999999);
item.setCustomName("§6" + constructedMatName + "§7 §eBait§7");
item.setCustomNameVisible(true);
item.setUnlimitedLifetime(true);
task.spawn(function () {
baitData["SpawnLocation"] = item.getLocation()
var fakeplayer = spawnFakePlayer(BaitID, baitData.SpawnLocation, true);
baitData["fakeplayer"] = fakeplayer;
baitData.tasks.push(updateFakePlayer(fakeplayer, material))
baitData.tasks.push(task.spawn(function() {
while (true) {
task.wait(0.1)
if (baitData && baitData.SpawnLocation) {
task.main(function () {
armorStand.teleport(item.getLocation().clone().add(0, -0.7, 0));
if (calculateDistance(baitData.SpawnLocation, fakeplayer.getLocation()) >= respawnLenght ) {
fakeplayer.setHealth(0);
task.spawn(function() {
let itemLocation = item.getLocation()
baitData.SpawnLocation = itemLocation
fakeplayer = spawnFakePlayer(BaitID, itemLocation, true)
baitData.fakeplayer = fakeplayer;
updateFakePlayer(fakeplayer, material)
})
} else {
fakeplayer.teleport(item.getLocation().clone().add(0, -1, 0));
}
})
}
}
}));
activeBaits[BaitID] = baitData;
})
}
function removebait(baitID) {
var baitData = activeBaits[baitID];
if (!baitData) return;
for (let i = 0; i < baitData.tasks.length; i++) {
task.cancel(baitData.tasks[i]);
}
UnstoreBait(baitData.storeID);
baitData.item.remove();
baitData.armorStand.remove();
baitData.fakeplayer.setHealth(0);
task.delay(0.5, function() {
fakeIds[baitID] = null;
})
activeBaits[baitID] = null;
}
addCommand("bait", {
onCommand: function(sender, args) {
if (!sender.getLocation) {
sender.sendMessage("§cOnly for players!.");
return;
}
if (args.length < 1) {
sender.sendMessage("§eUsage: /bait <item>");
return;
}
const matName = args[0].toUpperCase();
const material = org.bukkit.Material.matchMaterial(matName);
if (!material || !material.isItem()) {
sender.sendMessage("§cUnknown Item: " + matName);
return;
}
const loc = sender.getLocation().clone().add(0, 1, 0);
const world = sender.getWorld();
var itemStack = new org.bukkit.inventory.ItemStack(material, 1);
var item = world.dropItemNaturally(loc, itemStack);
dropBait(item, sender);
sender.sendMessage("§aDropped a bait with " + material.name());
},
onTabComplete: function(sender, args) {
if (args.length === 1) {
const prefix = args[0].toLowerCase();
const matches = [];
for (const mat of org.bukkit.Material.values()) {
if (mat.isItem() && mat.name().toLowerCase().startsWith(prefix)) {
matches.push(mat.name().toLowerCase());
}
}
return toJavaList(matches.slice(0, 40));
}
return toJavaList([]);
}
});
registerEvent("org.bukkit.event.entity.EntityDamageEvent", function(event) {
const entity = event.getEntity();
if (isFakeEntity(entity)) {
event.setCancelled(true);
}
});
registerEvent("org.bukkit.event.player.PlayerInteractAtEntityEvent", function(event) {
const entity = event.getRightClicked();
if (isFakeEntity(entity)) {
event.setCancelled(true);
const player = event.getPlayer();
const plrLoc = player.getLocation();
const curLoc = entity.getLocation();
if ( calculateDistance(curLoc, plrLoc) <= pickUpDistance ) {
var baitID = getEntityID(entity)
var baitData = activeBaits[baitID]
var collectedItem = givePlayerBaitItem(player, baitData.item.getItemStack().getType())
if (collectedItem) {
removebait(baitID);
} else {
player.sendMessage("§cYour inventory is full");
}
}
}
})
registerEvent("org.bukkit.event.player.PlayerDropItemEvent", (event) => {
const rawItem = event.getItemDrop();
const item = rawItem.getItemStack();
if (isBaitItem(item)) {
dropBait(rawItem)
}
});
registerEvent("org.bukkit.event.entity.ItemDespawnEvent", (event) => {
const rawItem = event.getEntity()
const item = rawItem.getItemStack();
if (isBaitItem(item)) {
removebait(UniqueToBaitID(rawItem.getUniqueId().toString()))
}
});
registerEvent("org.bukkit.event.player.PlayerJoinEvent", function (event) {
const name = event.getPlayer().getName();
if (fakeIds[name]) event.setJoinMessage(null);
});
registerEvent("org.bukkit.event.player.PlayerQuitEvent", function (event) {
const name = event.getPlayer().getName();
if (fakeIds[name]) event.setQuitMessage(null);
});
registerEvent("org.bukkit.event.entity.PlayerDeathEvent", function (event) {
const name = event.getEntity().getName();
if (fakeIds[name]) event.setDeathMessage(null);
});
registerEvent("org.bukkit.event.server.ServerCommandEvent", function (event) {
const msg = event.getCommand();
if (shouldSuppressMessage(msg)) event.setCancelled(true);
});
registerEvent("org.bukkit.event.server.BroadcastMessageEvent", function (event) {
const msg = event.getMessage();
if (shouldSuppressMessage(msg)) event.setMessage(null);
});
function shouldSuppressMessage(msg) {
const words = msg.split(" ");
for (let word of words) {
if (word.length === IdLenght && fakeIds[word]) {
return true;
}
}
return false;
}
task.delay(1, function() {
task.main(function() {
var baits = GetStoredBaits();
for (let i in baits) {
var ItemID = baits[i];
var item = getItemByUniqueID(ItemID);
var baitID = UniqueToBaitID(ItemID);
var armorStand = getEntityByCustomName(baitID);
var fakePlayer = Bukkit.getPlayer(baitID);
if (armorStand) {
armorStand.remove();
}
if (fakePlayer) {
fakePlayer.setHealth(0);
}
if (item) {
dropBait(item)
} else {
log.info("Removed arbitary bait!")
UnstoreBait(ItemID)
}
}
})
})Requires: ProtocolLib
Last updated
Was this helpful?