More fixes

This is now for sure going to fix hoppers entirely, except speeds which we should see in other patch.
Apparently caching the inventory doesn't work for composters as they're constantly updating their block state.
The code now makes it so that we only cache if the block is NOT a composter.

This is also fixing a bug with offline mode servers and proxies for vanilla commands. Read the new patch's patch notes to see what I'm talking about.
This commit is contained in:
Ivan Pekov 2020-08-17 21:39:05 +03:00 committed by GitHub
parent f19c7640c9
commit b352b7e83a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 255 additions and 140 deletions

View File

@ -101,6 +101,7 @@ # Patches
| server | Tulips change fox type | William Blake Galbreath | |
| server | Tweak Explosions | Aikar | |
| server | Use block distance in portal search radius | Patrick Hemmer | |
| server | Use offline uuids if we need to | Ivan Pekov | |
| server | Villagers follow emerald blocks | William Blake Galbreath | |
| api | Yatopia API Bundle | Bud Gidiere | |
| server | Yatopia-Server-Fixes | Bud Gidiere | |

View File

@ -60,137 +60,137 @@ index cb344a424bf4c657bb1bbca286a1136c9b21b489..82fc63dbfc0d48267e0c1972a312b714
\ No newline at end of file
diff --git a/src/main/java/dev/tr7zw/yatopia/EntityFilter.java b/src/main/java/dev/tr7zw/yatopia/EntityFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..e20dfbdfc07e5bc68e66940ef12d7e847ebd35d9
index 0000000000000000000000000000000000000000..1c50d30d74e06b78d96660dd2b9d7230ec609e89
--- /dev/null
+++ b/src/main/java/dev/tr7zw/yatopia/EntityFilter.java
@@ -0,0 +1,127 @@
+package dev.tr7zw.yatopia;
+
+import com.google.common.base.Predicates;
+import de.minebench.origami.OrigamiConfig;
+import java.util.function.Predicate;
+import net.minecraft.server.Entity;
+import net.minecraft.server.EntityTypes;
+import net.minecraft.server.EnumCreatureType;
+import net.minecraft.server.IEntitySelector;
+import net.minecraft.server.ScoreboardTeamBase;
+
+public class EntityFilter {
+
+ public static Predicate<Entity> getFilter(Entity entity) {
+ OrigamiConfig.WorldConfig config = entity.world.origamiConfig;
+ if (config.allCollisionsEnabled) {
+ return IEntitySelector.a(entity);
+ }
+
+ 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 Predicates.alwaysFalse();
+ }
+
+ Predicate<Entity> ret = (tested) -> {
+ if (!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) -> {
+ // no need to continue if we already got false from this check
+ if (!tested.canCollideWith(entity) || !entity.canCollideWith(tested)) {
+ return false;
+ }
+
+ Predicate<Entity> entitySpecific = (es) -> {
+ if (config.playerCollisions) {
+ return es.getEntityType() == EntityTypes.PLAYER;
+ }
+ return false;
+ };
+
+ if (config.animalCollisions) {
+ entitySpecific = entitySpecific.or((es) -> es.getEntityType().getEnumCreatureType() == EnumCreatureType.CREATURE);
+ }
+
+ if (config.ambientCollisions) {
+ entitySpecific = entitySpecific.or((es) -> es.getEntityType().getEnumCreatureType() == EnumCreatureType.AMBIENT);
+ }
+
+ if (config.monsterCollisions) {
+ entitySpecific = entitySpecific.or((es) -> es.getEntityType().getEnumCreatureType() == EnumCreatureType.MONSTER
+ && (config.pillagerCollisions || es.getEntityType() != EntityTypes.PILLAGER));
+ }
+
+ if (config.miscCollisions) {
+ entitySpecific = entitySpecific.or((es) -> {
+ if (es.getEntityType().getEnumCreatureType() == EnumCreatureType.MISC) {
+ return miscVPI(es, config, true);
+ }
+ return false;
+ });
+ } else {
+ entitySpecific = entitySpecific.or((es) -> miscVPI(es, config, false));
+ }
+
+ if (config.waterCreatureCollisions) {
+ entitySpecific = entitySpecific.or((es) -> es.getEntityType().getEnumCreatureType() == EnumCreatureType.WATER_CREATURE);
+ }
+
+ if (config.waterAmbientCollisions) {
+ entitySpecific = entitySpecific.or((es) -> es.getEntityType().getEnumCreatureType() == EnumCreatureType.WATER_AMBIENT);
+ }
+
+ return entitySpecific.test(tested);
+ });
+
+ return ret;
+ }
+
+ private static boolean miscVPI(Entity es, OrigamiConfig.WorldConfig config, boolean isMisc) {
+ Predicate<Entity> ret = (p) -> {
+ if (config.villagerCollisions) {
+ return p.getEntityType() == EntityTypes.VILLAGER;
+ }
+ return isMisc;
+ };
+ if (config.ironGolemCollisions) {
+ ret = ret.or((p) -> p.getEntityType() == EntityTypes.IRON_GOLEM);
+ }
+ if (config.itemCollisions) {
+ ret = ret.or((p) -> p.getEntityType() == EntityTypes.ITEM);
+ }
+ return ret.test(es);
+ }
+}
+package dev.tr7zw.yatopia;
+
+import com.google.common.base.Predicates;
+import de.minebench.origami.OrigamiConfig;
+import java.util.function.Predicate;
+import net.minecraft.server.Entity;
+import net.minecraft.server.EntityTypes;
+import net.minecraft.server.EnumCreatureType;
+import net.minecraft.server.IEntitySelector;
+import net.minecraft.server.ScoreboardTeamBase;
+
+public class EntityFilter {
+
+ public static Predicate<Entity> getFilter(Entity entity) {
+ OrigamiConfig.WorldConfig config = entity.world.origamiConfig;
+ if (config.allCollisionsEnabled) {
+ return IEntitySelector.a(entity);
+ }
+
+ 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 Predicates.alwaysFalse();
+ }
+
+ Predicate<Entity> ret = (tested) -> {
+ if (!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) -> {
+ // no need to continue if we already got false from this check
+ if (!tested.canCollideWith(entity) || !entity.canCollideWith(tested)) {
+ return false;
+ }
+
+ Predicate<Entity> entitySpecific = (es) -> {
+ if (config.playerCollisions) {
+ return es.getEntityType() == EntityTypes.PLAYER;
+ }
+ return false;
+ };
+
+ if (config.animalCollisions) {
+ entitySpecific = entitySpecific.or((es) -> es.getEntityType().getEnumCreatureType() == EnumCreatureType.CREATURE);
+ }
+
+ if (config.ambientCollisions) {
+ entitySpecific = entitySpecific.or((es) -> es.getEntityType().getEnumCreatureType() == EnumCreatureType.AMBIENT);
+ }
+
+ if (config.monsterCollisions) {
+ entitySpecific = entitySpecific.or((es) -> es.getEntityType().getEnumCreatureType() == EnumCreatureType.MONSTER
+ && (config.pillagerCollisions || es.getEntityType() != EntityTypes.PILLAGER));
+ }
+
+ if (config.miscCollisions) {
+ entitySpecific = entitySpecific.or((es) -> {
+ if (es.getEntityType().getEnumCreatureType() == EnumCreatureType.MISC) {
+ return miscVPI(es, config, true);
+ }
+ return false;
+ });
+ } else {
+ entitySpecific = entitySpecific.or((es) -> miscVPI(es, config, false));
+ }
+
+ if (config.waterCreatureCollisions) {
+ entitySpecific = entitySpecific.or((es) -> es.getEntityType().getEnumCreatureType() == EnumCreatureType.WATER_CREATURE);
+ }
+
+ if (config.waterAmbientCollisions) {
+ entitySpecific = entitySpecific.or((es) -> es.getEntityType().getEnumCreatureType() == EnumCreatureType.WATER_AMBIENT);
+ }
+
+ return entitySpecific.test(tested);
+ });
+
+ return ret;
+ }
+
+ private static boolean miscVPI(Entity es, OrigamiConfig.WorldConfig config, boolean isMisc) {
+ Predicate<Entity> ret = (p) -> {
+ if (config.villagerCollisions) {
+ return p.getEntityType() == EntityTypes.VILLAGER;
+ }
+ return isMisc;
+ };
+ if (config.ironGolemCollisions) {
+ ret = ret.or((p) -> p.getEntityType() == EntityTypes.IRON_GOLEM);
+ }
+ if (config.itemCollisions) {
+ ret = ret.or((p) -> p.getEntityType() == EntityTypes.ITEM);
+ }
+ return ret.test(es);
+ }
+}
diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
index 88f4c30a03e9139b0284ff1a545ad80941dbd46c..dca7a86dba22bca9bfd830a353a2c9561d1cf0ec 100644
--- a/src/main/java/net/minecraft/server/EntityLiving.java

View File

@ -35,15 +35,15 @@ index a29294fbc7cd6fcfff0df9eadd11de3bd7f1405e..2f66740de68667e5c0054a0bc7990256
private void a(World world, BlockPosition blockposition, IBlockData iblockdata) {
diff --git a/src/main/java/net/minecraft/server/TileEntityHopper.java b/src/main/java/net/minecraft/server/TileEntityHopper.java
index 95bede605c6401af10f18b641cd12c9d8ec2f207..20070cd7633798472458a29498d64da1ccb856a0 100644
index 95bede605c6401af10f18b641cd12c9d8ec2f207..1e74b550e4f1ffc7800db24605f9b3f5f5736aae 100644
--- a/src/main/java/net/minecraft/server/TileEntityHopper.java
+++ b/src/main/java/net/minecraft/server/TileEntityHopper.java
@@ -661,14 +661,47 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
@@ -661,14 +661,62 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
@Nullable
private IInventory l() {
+ // Yatopia start
+ if (cachedPush != null) {
+ if (!blockUnderWasComposter && cachedPush != null) {
+ return cachedPush;
+ }
+ // Yatopia end
@ -52,12 +52,27 @@ index 95bede605c6401af10f18b641cd12c9d8ec2f207..20070cd7633798472458a29498d64da1
- return b(this.getWorld(), this.position.shift(enumdirection));
+ // Yatopia start - replace logic
+ //return b(this.getWorld(), this.position.shift(enumdirection));
+ IInventory tmp = b(this.getWorld(), this.position.shift(enumdirection), cachedPushAir);
+ if (tmp != null) {
+ this.cachedPush = tmp;
+ } else {
+ cachedPushAir = true;
+ return null;
+ // basically reimplement TileEntityHopper#b but in a better way in order to
+ // not make them composters bork
+ BlockPosition shifted = this.position.shift(enumdirection);
+ BlockPosition checkedPosition = new BlockPosition(shifted.getX() + 0.5D, shifted.getY() + 0.5D, shifted.getZ() + 0.5D);
+ if (blockUnderWasComposter || !cachedPushAir) {
+ if (!world.isLoaded(checkedPosition)) return null;
+ IBlockData blockData = world.getType(checkedPosition);
+ Block block = blockData.getBlock();
+ if (block instanceof IInventoryHolder) {
+ this.cachedPush = ((IInventoryHolder) block).a(blockData, world, checkedPosition);
+ blockUnderWasComposter = true;
+ } else if (block.isTileEntity()) {
+ TileEntity tileEntity = world.getTileEntity(checkedPosition);
+ if (tileEntity instanceof IInventory) {
+ IInventory inv = (IInventory) tileEntity;
+ if (inv instanceof TileEntityChest && block instanceof BlockChest) {
+ inv = BlockChest.getInventory((BlockChest) block, blockData, world, checkedPosition, true);
+ }
+ this.cachedPush = inv;
+ }
+ }
+ }
+ if (this.cachedPush == null) {
+ this.cachedPushAir = true;
@ -87,7 +102,7 @@ index 95bede605c6401af10f18b641cd12c9d8ec2f207..20070cd7633798472458a29498d64da1
}
public static List<EntityItem> c(IHopper ihopper) {
@@ -683,14 +716,16 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
@@ -683,14 +731,16 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
}
@Nullable
@ -108,7 +123,7 @@ index 95bede605c6401af10f18b641cd12c9d8ec2f207..20070cd7633798472458a29498d64da1
BlockPosition blockposition = new BlockPosition(d0, d1, d2);
if ( !world.isLoaded( blockposition ) ) return null; // Spigot
IBlockData iblockdata = world.getType(blockposition);
@@ -708,8 +743,9 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
@@ -708,8 +758,9 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
}
}
}
@ -119,7 +134,7 @@ index 95bede605c6401af10f18b641cd12c9d8ec2f207..20070cd7633798472458a29498d64da1
List<Entity> list = world.getEntities((Entity) null, new AxisAlignedBB(d0 - 0.5D, d1 - 0.5D, d2 - 0.5D, d0 + 0.5D, d1 + 0.5D, d2 + 0.5D), IEntitySelector.d);
if (!list.isEmpty()) {
@@ -779,4 +815,16 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
@@ -779,4 +830,18 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
protected Container createContainer(int i, PlayerInventory playerinventory) {
return new ContainerHopper(i, playerinventory, this);
}
@ -129,10 +144,12 @@ index 95bede605c6401af10f18b641cd12c9d8ec2f207..20070cd7633798472458a29498d64da1
+ private IInventory cachedPush = null;
+ private boolean cachedPushAir = false;
+ private boolean cachedPullAir = false;
+ private boolean blockUnderWasComposter = false;
+ public void flushCaches() {
+ cachedAbove = null;
+ cachedPush = null;
+ cachedPushAir = false;
+ cachedPullAir = false;
+ blockUnderWasComposter = false;
+ }
}

View File

@ -0,0 +1,97 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Pekov <ivan@mrivanplays.com>
Date: Mon, 17 Aug 2020 19:16:39 +0300
Subject: [PATCH] Use offline uuids if we need to
By default, the user cache falls back to requests to mojang if it wasn't able to find a player.
This is completely fine if we're running an online mode server, however proxies require the
server to run in offline mode, which makes mojang's default commands to not work properly
( say if we want to ban a player which has never joined the server, he wouldn't get banned )
What our change does is make use of already existing options in paper.yml and spigot.yml to check
if the server is running behind a proxy and if the proxy is running online mode. If admins fail to
configure it properly, their mistake!
Furthermore, my research on the issue shows that this behavior also can be seen if we're not running
behind a proxy at all! I try to whitelist any of my staff, and they get whitelisted with online mode
UUIDs, while they should get whitelisted with offline mode ones.
Thanks to Gabriele C <sgdc3.mail@gmail.com> for pointing this issue to us, as he said paper doesn't
have any interest fixing this.
diff --git a/src/main/java/dev/tr7zw/yatopia/YatopiaConfig.java b/src/main/java/dev/tr7zw/yatopia/YatopiaConfig.java
index 0543de8ea80322028729723fd2b500ee7921ffd5..74bff3264d50d5352398d94526239c3c7507a5e4 100644
--- a/src/main/java/dev/tr7zw/yatopia/YatopiaConfig.java
+++ b/src/main/java/dev/tr7zw/yatopia/YatopiaConfig.java
@@ -233,4 +233,26 @@ public class YatopiaConfig {
private static void fixFallDistance() {
fixFallDistance = getBoolean("settings.fixFallDistance", false);
}
+
+ public static boolean shouldUseOfflineUUID() {
+ if (org.spigotmc.SpigotConfig.bungee && com.destroystokyo.paper.PaperConfig.bungeeOnlineMode) {
+ return false;
+ }
+ if (org.spigotmc.SpigotConfig.bungee) {
+ return true;
+ }
+ if (com.destroystokyo.paper.PaperConfig.velocitySupport &&
+ com.destroystokyo.paper.PaperConfig.velocityOnlineMode) {
+ return false;
+ }
+ if (com.destroystokyo.paper.PaperConfig.velocitySupport) {
+ return true;
+ }
+
+ return !MinecraftServer.getServer().getOnlineMode();
+ }
+
+ public static boolean isProxy() {
+ return org.spigotmc.SpigotConfig.bungee || com.destroystokyo.paper.PaperConfig.velocitySupport;
+ }
}
diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java
index a52c0391b171c8a57de75f87c534ce1e0e78c44a..bc46685716865927cec193c67a14f3edcf5ffc2e 100644
--- a/src/main/java/net/minecraft/server/EntityHuman.java
+++ b/src/main/java/net/minecraft/server/EntityHuman.java
@@ -1923,7 +1923,7 @@ public abstract class EntityHuman extends EntityLiving {
public static UUID a(GameProfile gameprofile) {
UUID uuid = gameprofile.getId();
- if (uuid == null) {
+ if (dev.tr7zw.yatopia.YatopiaConfig.shouldUseOfflineUUID() || uuid == null) { // Yatopia
uuid = getOfflineUUID(gameprofile.getName());
}
diff --git a/src/main/java/net/minecraft/server/UserCache.java b/src/main/java/net/minecraft/server/UserCache.java
index 1496c43fc9487caf6ddb3782a9d1c79ef6ca1e94..ca15524a0687197905ea940190ac4c547b609542 100644
--- a/src/main/java/net/minecraft/server/UserCache.java
+++ b/src/main/java/net/minecraft/server/UserCache.java
@@ -82,6 +82,11 @@ public class UserCache {
@Nullable
private static GameProfile a(GameProfileRepository gameprofilerepository, String s) {
+ // Yatopia start
+ if (dev.tr7zw.yatopia.YatopiaConfig.shouldUseOfflineUUID() && dev.tr7zw.yatopia.YatopiaConfig.isProxy()) {
+ return new GameProfile(EntityHuman.getOfflineUUID(s), s);
+ }
+ // Yatopia end
final AtomicReference<GameProfile> atomicreference = new AtomicReference();
ProfileLookupCallback profilelookupcallback = new ProfileLookupCallback() {
public void onProfileLookupSucceeded(GameProfile gameprofile) {
@@ -102,6 +107,15 @@ public class UserCache {
gameprofile = new GameProfile(uuid, s);
}
+ // Yatopia start
+ if (dev.tr7zw.yatopia.YatopiaConfig.shouldUseOfflineUUID() && !dev.tr7zw.yatopia.YatopiaConfig.isProxy()) {
+ GameProfile newProfile = new GameProfile(EntityHuman.getOfflineUUID(s), s);
+ if (gameprofile == null || gameprofile.getProperties().isEmpty()) return newProfile;
+ newProfile.getProperties().putAll(gameprofile.getProperties());
+ return newProfile;
+ }
+ // Yatopia end
+
return gameprofile;
}