1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-19 19:25:48 +00:00

Fixed Armor Stands getting damaged/pushed by Explosive Bow

This commit is contained in:
TheBusyBiscuit 2020-11-20 13:39:25 +01:00
parent c5f6b53412
commit 5bf3e38bae
18 changed files with 178 additions and 38 deletions

View File

@ -72,6 +72,8 @@
* Fixed #2558
* Fixed a duplication bug with the Block Placer
* Fixed Slimefun Guide Settings showing "last activity" as a negative number
* Fixed Armor Stands getting damaged/pushed by Explosive Bow
* Fixed Sword of Beheading dropping Zombie/Skeleton Skulls from Zombie/Skeleton subvariants
## Release Candidate 17 (17 Oct 2020)

View File

@ -46,7 +46,7 @@ final class ContributorsMenu {
});
List<Contributor> contributors = new ArrayList<>(SlimefunPlugin.getGitHubService().getContributors().values());
contributors.sort(Comparator.comparingInt(Contributor::index));
contributors.sort(Comparator.comparingInt(Contributor::getPosition));
for (int i = page * 36; i < contributors.size() && i < (page + 1) * 36; i++) {
Contributor contributor = contributors.get(i);

View File

@ -169,8 +169,11 @@ public class NetworkManager {
public void updateAllNetworks(@Nonnull Location l) {
Validate.notNull(l, "The Location cannot be null");
for (Network network : getNetworksFromLocation(l, Network.class)) {
network.markDirty(l);
// No need to create a sublist and loop through it if there are no Networks
if (!networks.isEmpty()) {
for (Network network : getNetworksFromLocation(l, Network.class)) {
network.markDirty(l);
}
}
}

View File

@ -38,7 +38,7 @@ public class Contributor {
private final ComputedOptional<String> headTexture = ComputedOptional.createNew();
private Optional<UUID> uuid = Optional.empty();
private boolean locked = false;
private boolean immutable = false;
/**
* This creates a new {@link Contributor} with the given ingame name and GitHub profile.
@ -84,7 +84,7 @@ public class Contributor {
Validate.notNull(role, "The role cannot be null!");
Validate.isTrue(commits >= 0, "Contributions cannot be negative");
if (!locked || role.startsWith("translator,")) {
if (!immutable || role.startsWith("translator,")) {
contributions.put(role, commits);
}
}
@ -120,6 +120,13 @@ public class Contributor {
return profileLink;
}
/**
* This returns a {@link List} of contributions for this {@link Contributor}.
* Each {@link Entry} consists of a {@link String} (for the role) and an {@link Integer}
* (for the amount of commits).
*
* @return A {@link List} of contributions for this {@link Contributor}
*/
@Nonnull
public List<Map.Entry<String, Integer>> getContributions() {
List<Map.Entry<String, Integer>> list = new ArrayList<>(contributions.entrySet());
@ -214,16 +221,35 @@ public class Contributor {
return contributions.values().stream().mapToInt(Integer::intValue).sum();
}
public int index() {
return -getTotalContributions();
}
/**
* This returns the final display name for this {@link Contributor}.
* The display name is basically the GitHub username but if the Minecraft username differs,
* it will be appended in brackets behind the GitHub username.
*
* @return The final display name of this {@link Contributor}.
*/
@Nonnull
public String getDisplayName() {
return ChatColor.GRAY + githubUsername + (!githubUsername.equals(minecraftUsername) ? ChatColor.DARK_GRAY + " (MC: " + minecraftUsername + ")" : "");
}
public void lock() {
locked = true;
/**
* This returns the position on where to order this {@link Contributor}.
* This is just a convenience method for a {@link Comparator}, it is equivalent to
* {@link #getTotalContributions()} multiplied by minus one.
*
* @return The position of this {@link Contributor} in terms for positioning and ordering.
*/
public int getPosition() {
return -getTotalContributions();
}
/**
* This marks this {@link Contributor} as immutable.
* Immutable {@link Contributor Contributors} will no longer be assigned any contributions.
* This is useful when you want to prevent some commits from counting twice.
*/
public void setImmutable() {
immutable = true;
}
}

View File

@ -8,6 +8,7 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -37,6 +38,7 @@ public class GitHubService {
private boolean logging = false;
private LocalDateTime lastUpdate = LocalDateTime.now();
private int openIssues = 0;
private int pendingPullRequests = 0;
private int publicForks = 0;
@ -56,9 +58,18 @@ public class GitHubService {
loadConnectors(false);
}
/**
* This will start the {@link GitHubService} and run the asynchronous {@link GitHubTask}
* every so often to update its data.
*
* @param plugin
* Our instance of {@link SlimefunPlugin}
*/
public void start(@Nonnull SlimefunPlugin plugin) {
long period = TimeUnit.HOURS.toMillis(1);
GitHubTask task = new GitHubTask(this);
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, task, 80L, 60 * 60 * 20L);
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, task, 80L, period);
}
/**
@ -215,8 +226,16 @@ public class GitHubService {
texturesCache.save();
}
/**
* This returns the cached skin texture for a given username.
*
* @param username
* The minecraft username
*
* @return The cached skin texture for that user (or null)
*/
@Nullable
protected String getCachedTexture(@Nonnull String name) {
return texturesCache.getString(name);
protected String getCachedTexture(@Nonnull String username) {
return texturesCache.getString(username);
}
}

View File

@ -183,7 +183,7 @@ public class Translators {
Contributor contributor = github.addContributor(minecraftName, "https://github.com/" + username, "translator," + lang.getLanguageId(), 0);
if (lock) {
contributor.lock();
contributor.setImmutable();
}
}

View File

@ -79,6 +79,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.IronGolemList
import io.github.thebusybiscuit.slimefun4.implementation.listeners.ItemPickupListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.MobDropListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.MultiBlockListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.NetworkListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.PiglinListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.PlayerProfileListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SeismicAxeListener;
@ -117,7 +118,6 @@ import me.mrCookieSlime.Slimefun.api.inventory.UniversalBlockMenu;
/**
* This is the main class of Slimefun.
* This is where all the magic starts, take a look around.
* Feel like home.
*
* @author TheBusyBiscuit
*/
@ -509,6 +509,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
new CauldronListener(this);
new GrindstoneListener(this);
new CartographyTableListener(this);
new NetworkListener(this, networkManager);
if (minecraftVersion.isAtLeast(MinecraftVersion.MINECRAFT_1_15)) {
new BeeListener(this);

View File

@ -2,9 +2,13 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.weapons;
import java.util.Collection;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
@ -33,6 +37,7 @@ public class ExplosiveBow extends SlimefunBow {
private final ItemSetting<Integer> range = new IntRangeSetting("explosion-range", 1, 3, Integer.MAX_VALUE);
@ParametersAreNonnullByDefault
public ExplosiveBow(Category category, SlimefunItemStack item, ItemStack[] recipe) {
super(category, item, recipe);
@ -44,8 +49,9 @@ public class ExplosiveBow extends SlimefunBow {
return (e, target) -> {
target.getWorld().spawnParticle(Particle.EXPLOSION_LARGE, target.getLocation(), 1);
target.getWorld().playSound(target.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 1, 1);
int radius = range.getValue();
Collection<Entity> entites = target.getWorld().getNearbyEntities(target.getLocation(), range.getValue(), range.getValue(), range.getValue(), entity -> entity instanceof LivingEntity && entity.isValid());
Collection<Entity> entites = target.getWorld().getNearbyEntities(target.getLocation(), radius, radius, radius, this::canDamage);
for (Entity nearby : entites) {
LivingEntity entity = (LivingEntity) nearby;
@ -71,6 +77,10 @@ public class ExplosiveBow extends SlimefunBow {
};
}
private boolean canDamage(@Nonnull Entity n) {
return n instanceof LivingEntity && !(n instanceof ArmorStand) && n.isValid();
}
private double calculateDamage(double distanceSquared, double originalDamage) {
if (distanceSquared <= 0.05) {
return originalDamage;

View File

@ -2,6 +2,9 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.weapons;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.Location;
@ -42,6 +45,7 @@ public class SeismicAxe extends SimpleSlimefunItem<ItemUseHandler> implements No
private static final float DAMAGE = 6;
private static final int RANGE = 10;
@ParametersAreNonnullByDefault
public SeismicAxe(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
}
@ -96,7 +100,8 @@ public class SeismicAxe extends SimpleSlimefunItem<ItemUseHandler> implements No
}
}
private Block findGround(Block b) {
@Nonnull
private Block findGround(@Nonnull Block b) {
if (b.getType() == Material.AIR) {
for (int y = 0; y < b.getY(); y++) {
Block block = b.getRelative(0, -y, 0);

View File

@ -3,8 +3,11 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.weapons;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Material;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Player;
import org.bukkit.entity.Skeleton;
import org.bukkit.entity.WitherSkeleton;
@ -21,6 +24,17 @@ import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
* The {@link SwordOfBeheading} is a special kind of sword which allows you to obtain
* {@link Zombie}, {@link Skeleton} and {@link Creeper} skulls when killing the respective {@link Monster}.
* Additionally, you can also obtain the head of a {@link Player} by killing them too.
* This sword also allows you to have a higher chance of getting the skull of a {@link WitherSkeleton} too.
*
* All chances are managed by an {@link ItemSetting} and can be configured.
*
* @author TheBusyBiscuit
*
*/
public class SwordOfBeheading extends SimpleSlimefunItem<EntityKillHandler> {
private final ItemSetting<Integer> chanceZombie = new IntRangeSetting("chance.ZOMBIE", 0, 40, 100);
@ -29,6 +43,7 @@ public class SwordOfBeheading extends SimpleSlimefunItem<EntityKillHandler> {
private final ItemSetting<Integer> chanceCreeper = new IntRangeSetting("chance.CREEPER", 0, 40, 100);
private final ItemSetting<Integer> chancePlayer = new IntRangeSetting("chance.PLAYER", 0, 70, 100);
@ParametersAreNonnullByDefault
public SwordOfBeheading(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
@ -40,29 +55,40 @@ public class SwordOfBeheading extends SimpleSlimefunItem<EntityKillHandler> {
return (e, entity, killer, item) -> {
Random random = ThreadLocalRandom.current();
if (e.getEntity() instanceof Zombie) {
switch (e.getEntityType()) {
case ZOMBIE:
if (random.nextInt(100) < chanceZombie.getValue()) {
e.getDrops().add(new ItemStack(Material.ZOMBIE_HEAD));
}
} else if (e.getEntity() instanceof WitherSkeleton) {
if (random.nextInt(100) < chanceWitherSkeleton.getValue()) {
e.getDrops().add(new ItemStack(Material.WITHER_SKELETON_SKULL));
}
} else if (e.getEntity() instanceof Skeleton) {
break;
case SKELETON:
if (random.nextInt(100) < chanceSkeleton.getValue()) {
e.getDrops().add(new ItemStack(Material.SKELETON_SKULL));
}
} else if (e.getEntity() instanceof Creeper) {
break;
case CREEPER:
if (random.nextInt(100) < chanceCreeper.getValue()) {
e.getDrops().add(new ItemStack(Material.CREEPER_HEAD));
}
} else if (e.getEntity() instanceof Player && random.nextInt(100) < chancePlayer.getValue()) {
ItemStack skull = new ItemStack(Material.PLAYER_HEAD);
ItemMeta meta = skull.getItemMeta();
((SkullMeta) meta).setOwningPlayer((Player) e.getEntity());
skull.setItemMeta(meta);
break;
case WITHER_SKELETON:
if (random.nextInt(100) < chanceWitherSkeleton.getValue()) {
e.getDrops().add(new ItemStack(Material.WITHER_SKELETON_SKULL));
}
break;
case PLAYER:
if (random.nextInt(100) < chancePlayer.getValue()) {
ItemStack skull = new ItemStack(Material.PLAYER_HEAD);
e.getDrops().add(skull);
ItemMeta meta = skull.getItemMeta();
((SkullMeta) meta).setOwningPlayer((Player) e.getEntity());
skull.setItemMeta(meta);
e.getDrops().add(skull);
}
break;
default:
break;
}
};
}

View File

@ -1,5 +1,8 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.weapons;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Sound;
import org.bukkit.attribute.Attribute;
import org.bukkit.entity.LivingEntity;
@ -28,6 +31,7 @@ public class VampireBlade extends SlimefunItem {
private static final double HEALING_AMOUNT = 4.0;
private final ItemSetting<Integer> chance = new IntRangeSetting("chance", 0, 45, 100);
@ParametersAreNonnullByDefault
public VampireBlade(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
@ -43,7 +47,7 @@ public class VampireBlade extends SlimefunItem {
return chance.getValue();
}
public void heal(Player p) {
public void heal(@Nonnull Player p) {
p.playSound(p.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 0.7F, 0.7F);
double health = p.getHealth() + HEALING_AMOUNT;
double maxHealth = p.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();

View File

@ -21,9 +21,27 @@ import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
*/
public class CapacitorTextureUpdateTask implements Runnable {
/**
* The {@link Location} of the {@link Capacitor}.
*/
private final Location l;
/**
* The level of how "full" this {@link Capacitor} is.
* From 0.0 to 1.0.
*/
private final double filledPercentage;
/**
* This creates a new {@link CapacitorTextureUpdateTask} with the given parameters.
*
* @param l
* The {@link Location} of the {@link Capacitor}
* @param charge
* The amount of charge in this {@link Capacitor}
* @param capacity
* The capacity of this {@link Capacitor}
*/
public CapacitorTextureUpdateTask(@Nonnull Location l, double charge, double capacity) {
Validate.notNull(l, "The Location cannot be null");
@ -36,6 +54,7 @@ public class CapacitorTextureUpdateTask implements Runnable {
Block b = l.getBlock();
Material type = b.getType();
// Ensure that this Block is still a Player Head
if (type == Material.PLAYER_HEAD || type == Material.PLAYER_WALL_HEAD) {
if (filledPercentage <= 0.25) {
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_25.getTexture());

View File

@ -9,7 +9,6 @@ import org.bukkit.World;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.ButcherAndroidListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.NetworkListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.TeleporterListener;
import io.github.thebusybiscuit.slimefun4.implementation.setup.PostSetup;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -69,10 +68,6 @@ public class SlimefunStartupTask implements Runnable {
if (isEnabled("PROGRAMMABLE_ANDROID_BUTCHER", "PROGRAMMABLE_ANDROID_2_BUTCHER", "PROGRAMMABLE_ANDROID_3_BUTCHER")) {
new ButcherAndroidListener(plugin);
}
if (isEnabled("ENERGY_REGULATOR", "CARGO_MANAGER")) {
new NetworkListener(plugin, SlimefunPlugin.getNetworkManager());
}
}
private boolean isEnabled(String... itemIds) {

View File

@ -65,6 +65,7 @@ public final class ChatUtils {
*
* @return A human-friendly version of the given {@link String}
*/
@Nonnull
public static String humanize(@Nonnull String string) {
StringBuilder builder = new StringBuilder();
String[] segments = PatternUtils.UNDERSCORE.split(string.toLowerCase(Locale.ROOT));

View File

@ -159,6 +159,9 @@ public enum ColoredMaterial {
// @formatter:on
/**
* This is our {@link List} of {@link Material Materials}, the backbone of this enum.
*/
private final List<Material> list;
/**
@ -175,11 +178,25 @@ public enum ColoredMaterial {
list = Collections.unmodifiableList(Arrays.asList(materials));
}
/**
* This returns an ordered {@link List} of {@link Material Materials}
* that are part o this {@link ColoredMaterial}.
*
* @return An ordered {@link List} of {@link Material Materials}
*/
@Nonnull
public List<Material> asList() {
return list;
}
/**
* This returns the {@link Material} at the given index.
*
* @param index
* The index
*
* @return The {@link Material} at that index
*/
@Nonnull
public Material get(int index) {
Validate.isTrue(index >= 0 && index < 16, "The index must be between 0 and 15 (inclusive).");
@ -187,6 +204,15 @@ public enum ColoredMaterial {
return list.get(index);
}
/**
* This returns the {@link Material} with the given {@link DyeColor}.
*
* @param color
* The {@link DyeColor}
*
* @return The {@link Material} with that {@link DyeColor}
*/
@Nonnull
public Material get(@Nonnull DyeColor color) {
Validate.notNull(color, "Color cannot be null!");

View File

@ -252,6 +252,8 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock,
* identify all instances of the same {@link AContainer}.
* This way we can add the recipes to all instances of the same machine.
*
* <strong>This method will be deprecated and replaced in the future</strong>
*
* @return The identifier of this machine
*/
@Nonnull

View File

@ -63,7 +63,7 @@ public abstract class AGenerator extends AbstractEnergyProvider {
@Override
public boolean canOpen(Block b, Player p) {
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.ACCESS_INVENTORIES);
return p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.INTERACT_BLOCK);
}
@Override

View File

@ -47,6 +47,7 @@ public interface ItemHandler {
*
* @param item
* The {@link SlimefunItem} to validate
*
* @return An {@link Optional} describing the result, it will contain an {@link IncompatibleItemHandlerException}
* should there be an issue
*/