From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: MrIvanPlays Date: Thu, 13 Aug 2020 15:14:36 +0300 Subject: [PATCH] Per entity (type) collision settings Base patch was the only player collisions patch, the original author of was tr7zw but pretty much the whole implementation changed. This patch implements per entity (type) collision settings with 100% compatibility with bukkit api and vanilla. The whole code is based around 1 class, the EntityFilter class. Whole filtering logic is there. Co-authored-by: tr7zw diff --git a/src/main/java/de/minebench/origami/OrigamiConfig.java b/src/main/java/de/minebench/origami/OrigamiConfig.java index 9a008acd3e6dd5522d163dfbe09c611f6f717d4e..a088b8f84f01ce3863ae949f4cd3d7ae9589c27c 100644 --- a/src/main/java/de/minebench/origami/OrigamiConfig.java +++ b/src/main/java/de/minebench/origami/OrigamiConfig.java @@ -121,6 +121,39 @@ public final class OrigamiConfig { private void pigmenDontTargetUnlessHit() { pigmenDontTargetUnlessHit = getBoolean("pigmen.dont-target-unless-hit", pigmenDontTargetUnlessHit); } + + // Yatopia start + public boolean playerCollisions = true; + public boolean animalCollisions = true; + public boolean ambientCollisions = true; + public boolean monsterCollisions = true; + public boolean villagerCollisions = true; + public boolean pillagerCollisions = true; + public boolean ironGolemCollisions = true; + public boolean miscCollisions = true; + public boolean itemCollisions = true; + public boolean waterCreatureCollisions = true; + public boolean waterAmbientCollisions = true; + public boolean allCollisionsEnabled = false; + private void specificCollisionSettings() { + playerCollisions = getBoolean("collisions.players", playerCollisions); + animalCollisions = getBoolean("collisions.animals", animalCollisions); + ambientCollisions = getBoolean("collisions.ambient", ambientCollisions); + monsterCollisions = getBoolean("collisions.monsters", monsterCollisions); + villagerCollisions = getBoolean("collisions.villagers", villagerCollisions); + pillagerCollisions = getBoolean("collisions.pillagers", pillagerCollisions); + ironGolemCollisions = getBoolean("collisions.iron-golems", ironGolemCollisions); + miscCollisions = getBoolean("collisions.misc", miscCollisions); + itemCollisions = getBoolean("collisions.items", itemCollisions); + waterCreatureCollisions = getBoolean("collisions.water-creature", waterCreatureCollisions); + waterAmbientCollisions = getBoolean("collisions.water-ambient", waterAmbientCollisions); + + allCollisionsEnabled = + playerCollisions && animalCollisions && ambientCollisions && monsterCollisions && villagerCollisions + && pillagerCollisions && ironGolemCollisions && miscCollisions && itemCollisions + && waterCreatureCollisions && waterAmbientCollisions; + } + // Yatopia end } } \ No newline at end of file diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java index cfd2846c70db349aaf5377217ede422560964e29..3541a869e85b45d9d5a0c2547357a6200836ee1e 100644 --- a/src/main/java/net/minecraft/world/entity/EntityLiving.java +++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java @@ -3001,7 +3001,7 @@ public abstract class EntityLiving extends Entity { // Paper - end don't run getEntities if we're not going to use its result // Tuinity start - reduce memory allocation from collideNearby List list = com.tuinity.tuinity.util.CachedLists.getTempGetEntitiesList(); - this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.pushable(this, world.paperConfig.fixClimbingBypassingCrammingRule), list); // Paper - fix climbing bypassing cramming rule + this.world.getEntities(this, this.getBoundingBox(), org.yatopiamc.yatopia.server.EntityFilter.getFilter(this, world.paperConfig.fixClimbingBypassingCrammingRule), list); // Paper - fix climbing bypassing cramming rule // Yatopia try { // Tuinity end - reduce memory allocation from collideNearby diff --git a/src/main/java/org/yatopiamc/yatopia/server/EntityFilter.java b/src/main/java/org/yatopiamc/yatopia/server/EntityFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..77df98d9b622e66ce47d1640819a5d20e5651fdc --- /dev/null +++ b/src/main/java/org/yatopiamc/yatopia/server/EntityFilter.java @@ -0,0 +1,145 @@ +package org.yatopiamc.yatopia.server; + +import de.minebench.origami.OrigamiConfig; +import java.util.function.Predicate; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityTypes; +import net.minecraft.world.entity.EnumCreatureType; +import net.minecraft.world.entity.IEntitySelector; +import net.minecraft.world.scores.ScoreboardTeamBase; + +public class EntityFilter { + + public static Predicate getFilter(Entity entity, boolean ignoreClimbing) { + OrigamiConfig.WorldConfig config = entity.world.origamiConfig; + if (config.allCollisionsEnabled) { + return IEntitySelector.pushable(entity, ignoreClimbing); + } + + ScoreboardTeamBase entityTeam = entity.getScoreboardTeam(); + ScoreboardTeamBase.EnumTeamPush entityTeamPush = + entityTeam == null ? + ScoreboardTeamBase.EnumTeamPush.ALWAYS : + entityTeam.getCollisionRule(); + + if (entityTeamPush == ScoreboardTeamBase.EnumTeamPush.NEVER || entity.world.isClientSide + || entity.isSpectator()) { + return tested -> false; + } + + Predicate ret = (tested) -> { + if (!tested.isCollidable(ignoreClimbing) || !tested.canCollideWith(entity) || !entity.canCollideWith(tested)) { + return false; + } + ScoreboardTeamBase testedTeam = tested.getScoreboardTeam(); + ScoreboardTeamBase.EnumTeamPush testedPush = + testedTeam == null ? + ScoreboardTeamBase.EnumTeamPush.ALWAYS : + testedTeam.getCollisionRule(); + + if (testedPush == ScoreboardTeamBase.EnumTeamPush.NEVER) { + return false; + } + if (testedTeam != null && entityTeam != null) { + // see IEntitySelector#a(Entity) + // copied from there, although for me this logic doesn't seem quite right + boolean ally = entityTeam.isAlly(testedTeam); + + if ((entityTeamPush == ScoreboardTeamBase.EnumTeamPush.PUSH_OWN_TEAM || + testedPush == ScoreboardTeamBase.EnumTeamPush.PUSH_OWN_TEAM) && ally) { + return false; + } + return (entityTeamPush != ScoreboardTeamBase.EnumTeamPush.PUSH_OTHER_TEAMS + && testedPush != ScoreboardTeamBase.EnumTeamPush.PUSH_OTHER_TEAMS) || ally; + } else { + return testedPush == ScoreboardTeamBase.EnumTeamPush.ALWAYS && + entityTeamPush == ScoreboardTeamBase.EnumTeamPush.ALWAYS; + } + }; + + ret = ret.and((tested) -> { + if (tested.getEntityType() == EntityTypes.PLAYER && config.playerCollisions) { + return true; + } + if (tested.getEntityType().getEnumCreatureType() == EnumCreatureType.CREATURE && config.animalCollisions) { + return true; + } + if (tested.getEntityType().getEnumCreatureType() == EnumCreatureType.AMBIENT && config.ambientCollisions) { + return true; + } + if (tested.getEntityType().getEnumCreatureType() == EnumCreatureType.MONSTER) { + if (config.monsterCollisions) { + if (config.pillagerCollisions) { + return true; + } else { + return tested.getEntityType() != EntityTypes.PILLAGER; + } + } else { + if (config.pillagerCollisions) { + return tested.getEntityType() == EntityTypes.PILLAGER; + } else { + return false; + } + } + } + if (tested.getEntityType().getEnumCreatureType() == EnumCreatureType.MISC) { + if (config.miscCollisions) { + if (config.villagerCollisions && config.ironGolemCollisions && config.itemCollisions) { + return true; + } + if (!config.villagerCollisions) { + if (tested.getEntityType() == EntityTypes.VILLAGER) { + return false; + } + } + if (!config.ironGolemCollisions) { + if (tested.getEntityType() == EntityTypes.IRON_GOLEM) { + return false; + } + } + if (!config.itemCollisions) { + if (tested.getEntityType() == EntityTypes.ITEM) { + return false; + } + } + return true; + } else { + if (config.villagerCollisions && config.ironGolemCollisions && config.itemCollisions) { + if (tested.getEntityType() == EntityTypes.VILLAGER) { + return true; + } + if (tested.getEntityType() == EntityTypes.IRON_GOLEM) { + return true; + } + if (tested.getEntityType() == EntityTypes.ITEM) { + return true; + } + } + if (config.villagerCollisions && config.ironGolemCollisions) { + if (tested.getEntityType() == EntityTypes.VILLAGER) { + return true; + } + if (tested.getEntityType() == EntityTypes.IRON_GOLEM) { + return true; + } + } + if (config.villagerCollisions) { + if (tested.getEntityType() == EntityTypes.VILLAGER) { + return true; + } + } + return false; + } + } + if (tested.getEntityType().getEnumCreatureType() == EnumCreatureType.WATER_CREATURE && config.waterCreatureCollisions) { + return true; + } + if (tested.getEntityType().getEnumCreatureType() == EnumCreatureType.WATER_AMBIENT && config.waterAmbientCollisions) { + return true; + } + return false; + }); + + return ret; + } +}