diff --git a/build.gradle.kts b/build.gradle.kts index 2092ddcf..d1db36e9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { java id("com.github.johnrengelman.shadow") version "7.0.0" apply false - id("io.papermc.paperweight.patcher") version "1.0.4" + id("io.papermc.paperweight.patcher") version "1.0.2" } repositories { diff --git a/gradle.properties b/gradle.properties index 08760c3e..05927111 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,5 +12,4 @@ org.gradle.jvmargs=-Xms1G -Xmx3G org.gradle.parallel=true kotlin.parallel.tasks.in.project=true org.gradle.caching=true -org.gradle.configureondemand=true -org.gradle.vfs.watch=false # causes too much issues \ No newline at end of file +org.gradle.configureondemand=true \ No newline at end of file diff --git a/patches/api/remap in progress/0001-Modify-POM.patch b/patches/api/remap in progress/0001-Modify-POM.patch new file mode 100644 index 00000000..eace81d3 --- /dev/null +++ b/patches/api/remap in progress/0001-Modify-POM.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: YatopiaMC +Date: Sat, 1 Aug 2020 15:51:49 -0500 +Subject: [PATCH] Modify POM + + +diff --git a/pom.xml b/pom.xml +index 6fd6066b16d4dbf8695be16ec8b2d135d4d04901..57f8d001e6a83ea6ada0fb820a4e5b25866c0edb 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -3,18 +3,18 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + +- com.tuinity +- tuinity-parent ++ org.yatopiamc ++ yatopia-parent + dev-SNAPSHOT + ../pom.xml + + +- tuinity-api ++ yatopia-api + 1.16.5-R0.1-SNAPSHOT + jar + +- Tuinity-API +- https://github.com/Spottedleaf/Tuinity ++ Yatopia-API ++ https://github.com/YatopiaMC/Yatopia + An enhanced plugin API for Minecraft servers. + + +@@ -25,6 +25,19 @@ + 4.7.0 + + ++ ++ ++ ++ codemc-releases ++ https://repo.codemc.io/repository/maven-releases/ ++ ++ ++ codemc-snapshots ++ https://repo.codemc.io/repository/maven-snapshots/ ++ ++ ++ ++ + + + sonatype +@@ -68,7 +81,7 @@ + + it.unimi.dsi + fastutil +- 8.2.2 ++ 8.5.4 + provided + + +@@ -115,7 +128,7 @@ + + org.yaml + snakeyaml +- 1.27 ++ 1.28 + compile + + +@@ -148,7 +161,7 @@ + + org.slf4j + slf4j-api +- 1.7.25 ++ 1.7.30 + compile + + +@@ -174,12 +187,12 @@ + + org.ow2.asm + asm +- 9.0 ++ 9.1 + + + org.ow2.asm + asm-commons +- 9.0 ++ 9.1 + + + diff --git a/patches/api/remap in progress/0002-Yatopia-Config-Redirect-Config.patch b/patches/api/remap in progress/0002-Yatopia-Config-Redirect-Config.patch new file mode 100644 index 00000000..b61363fc --- /dev/null +++ b/patches/api/remap in progress/0002-Yatopia-Config-Redirect-Config.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: YatopiaMC +Date: Sun, 17 Jan 2021 15:37:52 -0600 +Subject: [PATCH] Yatopia Config & Redirect Config + + +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 0f66655541dbb0dbb05a13a3612bb46cfb2b538a..a69bf7aae1e9d6b658b079431d23ca0f28c871d1 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1618,6 +1618,22 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + } + // Purpur end + ++ // Origami start - add config to timings report ++ @NotNull ++ public org.bukkit.configuration.file.YamlConfiguration getOrigamiConfig() ++ { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ // Origami end ++ ++ // Yatopia start - add config to timings report ++ @NotNull ++ public org.bukkit.configuration.file.YamlConfiguration getYatopiaConfig() ++ { ++ throw new UnsupportedOperationException("Not supported yet."); ++ } ++ // Yatopia end ++ + /** + * Sends the component to the player + * diff --git a/patches/api/remap in progress/0003-Add-GameProfileLookupEvent.patch b/patches/api/remap in progress/0003-Add-GameProfileLookupEvent.patch new file mode 100644 index 00000000..7c123cd1 --- /dev/null +++ b/patches/api/remap in progress/0003-Add-GameProfileLookupEvent.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: tr7zw +Date: Sat, 1 Aug 2020 15:52:50 -0500 +Subject: [PATCH] Add GameProfileLookupEvent + + +diff --git a/pom.xml b/pom.xml +index 57f8d001e6a83ea6ada0fb820a4e5b25866c0edb..f0ef93cb0c1d369265b2a6fc56c80f79d61d4ebc 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -43,6 +43,10 @@ + sonatype + https://oss.sonatype.org/content/groups/public/ + ++ ++ mojang ++ https://libraries.minecraft.net/ ++ + + + +@@ -60,6 +64,13 @@ + + + ++ ++ ++ com.mojang ++ authlib ++ 1.5.25 ++ provided ++ + + + net.kyori +diff --git a/src/main/java/dev/tr7zw/yatopia/events/GameProfileLookupEvent.java b/src/main/java/dev/tr7zw/yatopia/events/GameProfileLookupEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..313fe42442a93db76f91eaab50a345340f314fa8 +--- /dev/null ++++ b/src/main/java/dev/tr7zw/yatopia/events/GameProfileLookupEvent.java +@@ -0,0 +1,51 @@ ++package dev.tr7zw.yatopia.events; ++ ++import com.mojang.authlib.GameProfile; ++import java.util.UUID; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++public class GameProfileLookupEvent extends Event { ++ private static final HandlerList handlers = new HandlerList(); ++ private GameProfile gameProfile = null; ++ private final UUID uuid; ++ private final String name; ++ ++ public GameProfileLookupEvent(boolean async, @NotNull UUID uuid, @NotNull String name) { ++ super(async); ++ this.uuid = uuid; ++ this.name = name; ++ } ++ ++ @Nullable ++ public GameProfile getGameProfile() { ++ return gameProfile; ++ } ++ ++ public void setGameProfile(@Nullable GameProfile gameProfile) { ++ this.gameProfile = gameProfile; ++ } ++ ++ @NotNull ++ public UUID getUuid() { ++ return uuid; ++ } ++ ++ @NotNull ++ public String getName() { ++ return name; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/api/remap in progress/0004-Add-last-tick-time-API.patch b/patches/api/remap in progress/0004-Add-last-tick-time-API.patch new file mode 100644 index 00000000..94c196a4 --- /dev/null +++ b/patches/api/remap in progress/0004-Add-last-tick-time-API.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Sun, 27 Sep 2020 18:01:50 +0300 +Subject: [PATCH] Add last tick time API + +Original patch by: +Co-authored-by: tr7zw + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 8036c66af0bc6b11ffd0f716138901bcfea007e1..5c11d5203491d120356098c14c0069874b2eaadf 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -1971,4 +1971,14 @@ public final class Bukkit { + return server.isLagging(); + } + // Purpur end ++ ++ // Yatopia start ++ @Deprecated ++ public static long getLastTickMs() { ++ return server.getLastTickMs(); ++ } ++ @NotNull public static java.time.Duration getLastTickTime() { ++ return server.getLastTickTime(); ++ } ++ // Yatopia end + } +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index a69bf7aae1e9d6b658b079431d23ca0f28c871d1..423e94f44cd62eaa270ac44b1e3f49acc5fcce9d 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -1760,4 +1760,24 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + */ + boolean isLagging(); + // Purpur end ++ ++ // Yatopia start ++ /** ++ * Returns the time the last tick took in milliseconds. ++ * ++ * @return long time value ++ * @deprecated newer method with java's Duration and a possibility to convert it from millis to something else ++ */ ++ @Deprecated ++ default long getLastTickMs() { ++ return getLastTickTime().toMillis(); ++ } ++ /** ++ * Returns the time in {@link java.time.Duration} the last tick took. ++ * ++ * @return duration ++ */ ++ @NotNull ++ java.time.Duration getLastTickTime(); ++ // Yatopia end + } diff --git a/patches/api/remap in progress/0005-Add-NBT-API-as-a-first-class-lib.patch b/patches/api/remap in progress/0005-Add-NBT-API-as-a-first-class-lib.patch new file mode 100644 index 00000000..3fff9bed --- /dev/null +++ b/patches/api/remap in progress/0005-Add-NBT-API-as-a-first-class-lib.patch @@ -0,0 +1,177 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: tr7zw +Date: Sat, 1 Aug 2020 15:55:15 -0500 +Subject: [PATCH] Add NBT API as a first-class lib + + +diff --git a/pom.xml b/pom.xml +index f0ef93cb0c1d369265b2a6fc56c80f79d61d4ebc..a6a2fd50e685f64afecac5da6aaaad6227a3731e 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -47,6 +47,11 @@ + mojang + https://libraries.minecraft.net/ + ++ ++ ++ codemc-repo ++ https://repo.codemc.io/repository/maven-public/ ++ + + + +@@ -205,6 +210,11 @@ + asm-commons + 9.1 + ++ ++ de.tr7zw ++ item-nbt-api ++ 2.7.1 ++ + + + +@@ -279,6 +289,12 @@ + ${project.build.directory}/dependency-reduced-pom.xml + + true ++ ++ ++ de.tr7zw.changeme.nbtapi ++ de.tr7zw.nbtapi ++ ++ + + + +diff --git a/src/main/java/org/bukkit/Chunk.java b/src/main/java/org/bukkit/Chunk.java +index 98263d896f316983609432c45b85401a2692432d..afaa459d2c351f99b598ec9054a6838ffb0098e8 100644 +--- a/src/main/java/org/bukkit/Chunk.java ++++ b/src/main/java/org/bukkit/Chunk.java +@@ -275,4 +275,16 @@ public interface Chunk extends PersistentDataHolder { + * @return if the block is contained within + */ + boolean contains(@NotNull BlockData block); ++ ++ // Yatopia start ++ /** ++ * Returns a custom tag container of this chunk. ++ * ++ * @return custom NBT tags container ++ */ ++ @NotNull ++ default de.tr7zw.changeme.nbtapi.NBTCompound getNBTC() { ++ return new de.tr7zw.changeme.nbtapi.NBTChunk(this).getPersistentDataContainer(); ++ } ++ // Yatopia end + } +diff --git a/src/main/java/org/bukkit/block/TileState.java b/src/main/java/org/bukkit/block/TileState.java +index 3b10fcc13893403b29f0260b8605144679e89b82..1e9a96d8b08cc396acf73dc42083009354e89d8a 100644 +--- a/src/main/java/org/bukkit/block/TileState.java ++++ b/src/main/java/org/bukkit/block/TileState.java +@@ -36,4 +36,26 @@ public interface TileState extends BlockState, PersistentDataHolder { + @NotNull + @Override + PersistentDataContainer getPersistentDataContainer(); ++ ++ // Yatopia start ++ /** ++ * Returns NBT representation of this tile entity. ++ * ++ * @return vanilla NBT tags container ++ */ ++ @NotNull ++ default de.tr7zw.changeme.nbtapi.NBTTileEntity getNBT() { ++ return new de.tr7zw.changeme.nbtapi.NBTTileEntity(this); ++ } ++ ++ /** ++ * Returns a custom tag container of this tile entity. ++ * ++ * @return custom NBT tags container ++ */ ++ @NotNull ++ default de.tr7zw.changeme.nbtapi.NBTCompound getNBTC() { ++ return getNBT().getPersistentDataContainer(); ++ } ++ // Yatopia end + } +diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java +index 62d8d7dbd4d602ca8cb00ff0cf1331583b398323..7cb395466babc84dd4ce1c91cbab7d130a5437b3 100644 +--- a/src/main/java/org/bukkit/entity/Entity.java ++++ b/src/main/java/org/bukkit/entity/Entity.java +@@ -778,4 +778,26 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent + */ + boolean isInDaylight(); + // Purpur end ++ ++ // Yatopia start ++ /** ++ * Returns NBT representation of this entity. ++ * ++ * @return vanilla NBT tags container ++ */ ++ @NotNull ++ default de.tr7zw.changeme.nbtapi.NBTEntity getNBT() { ++ return new de.tr7zw.changeme.nbtapi.NBTEntity(this); ++ } ++ ++ /** ++ * Returns a custom tag container of this entity. ++ * ++ * @return custom NBT tags container ++ */ ++ @NotNull ++ default de.tr7zw.changeme.nbtapi.NBTCompound getNBTC() { ++ return getNBT().getPersistentDataContainer(); ++ } ++ // Yatopia end + } +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index fceba6780a15c274c4689eccbeb6dfb2eee25ed9..1ba63c21245c4d4b9326b89ac83add9481fec243 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -1548,4 +1548,42 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor + return random.nextInt(unbreaking + 1) > 0; + } + // Purpur end ++ ++ // Yatopia start ++ /** ++ * Returns NBT representation of this item. The ItemStack will be cloned! ++ * ++ * @return item's NBT tags container ++ */ ++ @NotNull ++ public de.tr7zw.changeme.nbtapi.NBTItem getNBT() { ++ return getNBT(false); ++ } ++ ++ /** ++ * Returns NBT representation of this item. If directApply is true, ++ * all changes will be mapped to the original item. Changes to the NBTItem will ++ * overwrite changes done to the original item in that case. ++ * ++ * @param directApply if true, changes to NBTItem will affect this ItemStack ++ * @return item's NBT tags container ++ */ ++ @NotNull ++ public de.tr7zw.changeme.nbtapi.NBTItem getNBT(boolean directApply) { ++ return new de.tr7zw.changeme.nbtapi.NBTItem(this, directApply); ++ } ++ ++ /** ++ * Applies NBT data from the provided NBT item. ++ * ++ * @param nbt ItemStack's NBT container ++ */ ++ public void setNBT(@NotNull de.tr7zw.changeme.nbtapi.NBTItem nbt) { ++ ItemStack nbtItem = nbt.getItem(); ++ setType(nbtItem.getType()); ++ setAmount(nbtItem.getAmount()); ++ setData(nbtItem.getData()); ++ setItemMeta(nbtItem.getItemMeta()); ++ } ++ // Yatopia end + } diff --git a/patches/api/remap in progress/0006-PlayerAttackEntityEvent.patch b/patches/api/remap in progress/0006-PlayerAttackEntityEvent.patch new file mode 100644 index 00000000..93d75bfb --- /dev/null +++ b/patches/api/remap in progress/0006-PlayerAttackEntityEvent.patch @@ -0,0 +1,136 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Tue, 22 Sep 2020 12:52:57 +0300 +Subject: [PATCH] PlayerAttackEntityEvent + +Added per request + +diff --git a/src/main/java/net/yatopia/api/event/PlayerAttackEntityEvent.java b/src/main/java/net/yatopia/api/event/PlayerAttackEntityEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7a4bd2d6518409972651373c3e6ea0fd17f8fcf7 +--- /dev/null ++++ b/src/main/java/net/yatopia/api/event/PlayerAttackEntityEvent.java +@@ -0,0 +1,123 @@ ++package net.yatopia.api.event; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.HumanEntity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when the {@link Player} attacks a {@link Entity}. ++ *

++ * This event is fired earlier than {@link org.bukkit.event.entity.EntityDamageByEntityEvent} . ++ */ ++public class PlayerAttackEntityEvent extends Event implements Cancellable { ++ ++ private boolean cancelled = false; ++ private final HumanEntity attacker; ++ private final Entity attacked; ++ private final ItemStack attackItem; ++ ++ private boolean criticalHit; ++ private float damage; ++ ++ public PlayerAttackEntityEvent(@NotNull HumanEntity attacker, @NotNull Entity attacked, @NotNull ItemStack attackItem, boolean criticalHit, float damage) { ++ this.attacker = attacker; ++ this.attacked = attacked; ++ this.attackItem = attackItem; ++ this.criticalHit = criticalHit; ++ this.damage = damage; ++ } ++ ++ /** ++ * Returns the attacker. ++ * ++ * @return attacker ++ */ ++ @NotNull ++ public HumanEntity getAttacker() { ++ return attacker; ++ } ++ ++ /** ++ * Returns the entity attacked. ++ * ++ * @return attacked entity ++ */ ++ @NotNull ++ public Entity getAttackedEntity() { ++ return attacked; ++ } ++ ++ /** ++ * Returns the attack item used to damage the {@link #getAttackedEntity()} ++ *

++ * If there wasn't any item, it would return ItemStack(Material.AIR) ++ * ++ * @return attack item ++ */ ++ @NotNull ++ public ItemStack getAttackItem() { ++ return attackItem; ++ } ++ ++ /** ++ * Returns whether or not the hit is a critical hit. ++ *

++ * Minecraft multiplies the damage by 1.5 if the hit is critical. ++ * ++ * @return value ++ */ ++ public boolean isCritical() { ++ return criticalHit; ++ } ++ ++ /** ++ * Sets if the hit is critical. The value may be ignored if the server has disabled criticals. ++ * ++ * @param critical whether or not you want the hit to be critical. ++ */ ++ public void setCritical(boolean critical) { ++ this.criticalHit = critical; ++ } ++ ++ /** ++ * Returns the damage which is going to be dealt. ++ *

++ * WARNING: Critical hit is not included. ++ * ++ * @return damage ++ */ ++ public float getDamage() { ++ return damage; ++ } ++ ++ /** ++ * Sets the damage the {@link #getAttackedEntity()} will receive. If the hit is a {@link #isCritical()}, then the set damage ++ * will be multiplied by 1.5 ++ * ++ * @param damage damage ++ */ ++ public void setDamage(float damage) { ++ this.damage = damage; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ // ++ private static final HandlerList handlers = new HandlerList(); ++ @NotNull @Override public HandlerList getHandlers() { return handlers; } ++ @NotNull public static HandlerList getHandlerList() { return handlers; } ++ // ++} diff --git a/patches/api/remap in progress/0007-Disable-reload-command.patch b/patches/api/remap in progress/0007-Disable-reload-command.patch new file mode 100644 index 00000000..d241bc68 --- /dev/null +++ b/patches/api/remap in progress/0007-Disable-reload-command.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Mon, 19 Oct 2020 15:48:06 +0300 +Subject: [PATCH] Disable reload command + + +diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +index 0c7ba0718de2b93d013968ca0fec34ffd423990f..3a726fd145e5bbb1513b74eaae7d768ae6ab4a9f 100644 +--- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +@@ -21,6 +21,19 @@ public class ReloadCommand extends BukkitCommand { + @Override + public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { // Paper + if (!testPermission(sender)) return true; ++ // Yatopia start - fix lag ++ if (Boolean.parseBoolean(System.getProperty("Yatopia.DisableReloadCommand", "true"))) { ++ sender.sendMessage(ChatColor.RED + "Operation denied."); ++ sender.sendMessage(ChatColor.RED + "Reload command SHOULD NEVER EVER EVER be used in whatever circumstances."); ++ sender.sendMessage(ChatColor.RED + "YatopiaMC team has intentionally disabled it in order to stop you using it, instead of restarting your server."); ++ sender.sendMessage(ChatColor.RED + "---------------------------------------------"); ++ sender.sendMessage(ChatColor.RED + "RESTART YOUR SERVER AND NEVER USE /reload"); ++ sender.sendMessage(ChatColor.YELLOW + "For plugin developers: learn what a HOTSWAP AGENT is and stop using /reload"); ++ sender.sendMessage(ChatColor.RED + "---------------------------------------------"); ++ sender.sendMessage(ChatColor.YELLOW + "For more information, join our discord server."); ++ return true; ++ } ++ // Yatopia end + + // Paper start - Reload permissions.yml & require confirm + boolean confirmed = System.getProperty("LetMeReload") != null; diff --git a/patches/api/remap in progress/0008-Suspected-plugins-report.patch b/patches/api/remap in progress/0008-Suspected-plugins-report.patch new file mode 100644 index 00000000..668e29d7 --- /dev/null +++ b/patches/api/remap in progress/0008-Suspected-plugins-report.patch @@ -0,0 +1,258 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ishland +Date: Fri, 29 Jan 2021 09:57:47 +0800 +Subject: [PATCH] Suspected plugins report + +Added "Suspected Plugins" to Watchdog, crash reports and exception messages + +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index d1c35e4cf778070f8d18bbe0af8d423334c6dfbf..d87c8e97a4a73f8df1f5badc7bdfea18a54e406b 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -577,7 +577,11 @@ public final class SimplePluginManager implements PluginManager { + + // Paper start + private void handlePluginException(String msg, Throwable ex, Plugin plugin) { +- server.getLogger().log(Level.SEVERE, msg, ex); ++ // Yatopia start - detailed report ++ server.getLogger().log(Level.SEVERE, msg); ++ org.yatopiamc.yatopia.api.internal.StackTraceUtils.print(ex, _msg -> server.getLogger().log(Level.SEVERE, _msg)); ++ server.getLogger().log(Level.SEVERE, org.yatopiamc.yatopia.api.internal.StackTraceUtils.EXCEPTION_DETAILS_BELOW, ex); ++ // Yatopia end + callEvent(new ServerExceptionEvent(new ServerPluginEnableDisableException(msg, ex, plugin))); + } + // Paper end +@@ -638,7 +642,11 @@ public final class SimplePluginManager implements PluginManager { + } catch (Throwable ex) { + // Paper start - error reporting + String msg = "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName(); +- server.getLogger().log(Level.SEVERE, msg, ex); ++ // Yatopia start - detailed report ++ server.getLogger().log(Level.SEVERE, msg); ++ org.yatopiamc.yatopia.api.internal.StackTraceUtils.print(ex, _msg -> server.getLogger().log(Level.SEVERE, _msg)); ++ server.getLogger().log(Level.SEVERE, org.yatopiamc.yatopia.api.internal.StackTraceUtils.EXCEPTION_DETAILS_BELOW, ex); ++ // Yatopia end + if (!(event instanceof ServerExceptionEvent)) { // We don't want to cause an endless event loop + callEvent(new ServerExceptionEvent(new ServerEventException(msg, ex, registration.getPlugin(), registration.getListener(), event))); + } +@@ -922,4 +930,10 @@ public final class SimplePluginManager implements PluginManager { + } + // Paper end + ++ // Yatopia start - Accessor ++ @NotNull ++ public Collection getPluginLoaders() { ++ return new HashSet<>(fileAssociations.values()); ++ } ++ // Yatopia end + } +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +index 04fa3991f6ce4e9dad804f28fc6c947695857089..cb11eab6e13ed1c395b8f7db033c9a2817f4089c 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +@@ -111,7 +111,7 @@ public abstract class JavaPlugin extends PluginBase { + * @return File containing this plugin + */ + @NotNull +- protected File getFile() { ++ public File getFile() { // Yatopia + return file; + } + +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index b622cedeeee017f042bcf92485d81832030a8030..f1d3042e7f224059547ac840524cae5dd80ecd8b 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -369,7 +369,11 @@ public final class JavaPluginLoader implements PluginLoader { + try { + jPlugin.setEnabled(true); + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ // Yatopia start - detailed report ++ server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)"); ++ org.yatopiamc.yatopia.api.internal.StackTraceUtils.print(ex, _msg -> server.getLogger().log(Level.SEVERE, _msg)); ++ server.getLogger().log(Level.SEVERE, org.yatopiamc.yatopia.api.internal.StackTraceUtils.EXCEPTION_DETAILS_BELOW, ex); ++ // Yatopia end + // Paper start - Disable plugins that fail to load + server.getPluginManager().disablePlugin(jPlugin, true); // Paper - close Classloader on disable - She's dead jim + return; +@@ -404,7 +408,11 @@ public final class JavaPluginLoader implements PluginLoader { + try { + jPlugin.setEnabled(false); + } catch (Throwable ex) { +- server.getLogger().log(Level.SEVERE, "Error occurred while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); ++ // Yatopia start - detailed report ++ server.getLogger().log(Level.SEVERE, "Error occurred while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)"); ++ org.yatopiamc.yatopia.api.internal.StackTraceUtils.print(ex, _msg -> server.getLogger().log(Level.SEVERE, _msg)); ++ server.getLogger().log(Level.SEVERE, org.yatopiamc.yatopia.api.internal.StackTraceUtils.EXCEPTION_DETAILS_BELOW, ex); ++ // Yatopia end + } + + if (cloader instanceof PluginClassLoader) { +@@ -428,11 +436,20 @@ public final class JavaPluginLoader implements PluginLoader { + loader.close(); + } + } catch (IOException e) { ++ // Yatopia start - detailed report + server.getLogger().log(Level.WARNING, "Error closing the Plugin Class Loader for " + plugin.getDescription().getFullName()); ++ org.yatopiamc.yatopia.api.internal.StackTraceUtils.print(e, _msg -> server.getLogger().log(Level.WARNING, _msg)); ++ server.getLogger().log(Level.WARNING, org.yatopiamc.yatopia.api.internal.StackTraceUtils.EXCEPTION_DETAILS_BELOW, e); ++ // Yatopia end + e.printStackTrace(); + } + // Paper end + } + } + } ++ // Yatopia start - Accessor ++ public List getClassLoaders() { ++ return java.util.Collections.unmodifiableList(loaders); ++ } ++ // Yatopia end + } +diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +index 6ced06643cd9740e2c62bc8f10d150a2f9a92e31..161263242860fbae7b05766f006a7a83df82fc03 100644 +--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +@@ -250,4 +250,13 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + '}'; + } + // Paper end ++ ++ // Yatopia start - Accessor ++ public java.util.Collection> getLoadedClasses() { ++ return java.util.Collections.unmodifiableCollection( ++ new java.util.HashSet<>(classes.values()).stream() ++ .filter(clazz -> clazz.getClassLoader() == this).collect(java.util.stream.Collectors.toSet()) ++ ); ++ } ++ // Yatopia end + } +diff --git a/src/main/java/org/yatopiamc/yatopia/api/internal/StackTraceUtils.java b/src/main/java/org/yatopiamc/yatopia/api/internal/StackTraceUtils.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0aa9bc6ad0a85d469b29201b9da29165bafb874c +--- /dev/null ++++ b/src/main/java/org/yatopiamc/yatopia/api/internal/StackTraceUtils.java +@@ -0,0 +1,105 @@ ++package org.yatopiamc.yatopia.api.internal; ++ ++import com.google.common.base.Suppliers; ++import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; ++import org.bukkit.Bukkit; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.plugin.PluginLoader; ++import org.bukkit.plugin.SimplePluginManager; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.bukkit.plugin.java.JavaPluginLoader; ++import org.bukkit.plugin.java.PluginClassLoader; ++ ++import java.util.Arrays; ++import java.util.Collection; ++import java.util.Collections; ++import java.util.HashSet; ++import java.util.List; ++import java.util.Map; ++import java.util.Set; ++import java.util.concurrent.TimeUnit; ++import java.util.function.Consumer; ++import java.util.function.Supplier; ++import java.util.stream.Collectors; ++ ++public class StackTraceUtils { ++ ++ public static final String EXCEPTION_DETAILS_BELOW = "Exception details below: "; ++ ++ private static final Supplier>>> loadedClassesSupplier = Suppliers.memoizeWithExpiration(StackTraceUtils::scanForPluginClasses, 5, TimeUnit.SECONDS); ++ ++ public static void print(StackTraceElement[] stackTrace, Consumer out) { ++ Set suspectedPlugins = getSuspectedPluginsFromStackTrace(stackTrace); ++ ++ printSuspectedPlugins(out, suspectedPlugins); ++ } ++ ++ public static void print(Throwable t, Consumer out) { ++ Set suspectedPlugins = getSuspectedPluginsFromStackTrace(getStackTracesFromThrowable(t).toArray(new StackTraceElement[0])); ++ ++ printSuspectedPlugins(out, suspectedPlugins); ++ } ++ ++ private static Set getStackTracesFromThrowable(Throwable t) { ++ if(t == null) return Collections.emptySet(); ++ Set elements = new ObjectOpenHashSet<>(); ++ elements.addAll(getStackTracesFromThrowable(t.getCause())); ++ elements.addAll(Arrays.stream(t.getSuppressed()).flatMap(throwable -> getStackTracesFromThrowable(throwable).stream()).collect(Collectors.toSet())); ++ elements.addAll(Arrays.asList(t.getStackTrace())); ++ return elements; ++ } ++ ++ private static void printSuspectedPlugins(Consumer out, Set suspectedPlugins) { ++ if (!suspectedPlugins.isEmpty()) { ++ out.accept("Suspected Plugins: "); ++ for (Plugin plugin : suspectedPlugins) { ++ StringBuilder builder = new StringBuilder("\t"); ++ builder.append(plugin.getName()) ++ .append("{") ++ .append(plugin.isEnabled() ? "enabled" : "disabled") ++ .append(",").append("ver=").append(plugin.getDescription().getVersion()); ++ if (!plugin.isNaggable()) ++ builder.append(",").append("nag"); ++ if (plugin instanceof JavaPlugin) ++ builder.append(",").append("path=").append(((JavaPlugin) plugin).getFile()); ++ ++ builder.append("}"); ++ out.accept(builder.toString()); ++ } ++ } else { ++ out.accept("Suspected Plugins: None"); ++ } ++ } ++ ++ private static Set getSuspectedPluginsFromStackTrace(StackTraceElement[] stackTrace) { ++ Map>> loadedClasses = loadedClassesSupplier.get(); ++ Set suspectedPlugins = new HashSet<>(); ++ for (StackTraceElement stackTraceElement : stackTrace) { ++ for (Map.Entry>> pluginSetEntry : loadedClasses.entrySet()) { ++ if (pluginSetEntry.getValue().stream().anyMatch(clazz -> clazz.getName().equals(stackTraceElement.getClassName()))) ++ suspectedPlugins.add(pluginSetEntry.getKey()); ++ } ++ } ++ return suspectedPlugins; ++ } ++ ++ private static Map>> scanForPluginClasses() { ++ Map>> loadedClasses = new Object2ObjectOpenHashMap<>(); ++ if (Bukkit.getPluginManager() instanceof SimplePluginManager) { ++ final SimplePluginManager pluginManager = (SimplePluginManager) Bukkit.getPluginManager(); ++ final Collection pluginLoaders = pluginManager.getPluginLoaders(); ++ for (PluginLoader pluginLoader : pluginLoaders) { ++ if (pluginLoader instanceof JavaPluginLoader) { ++ JavaPluginLoader javaPluginLoader = (JavaPluginLoader) pluginLoader; ++ final List classLoaders = javaPluginLoader.getClassLoaders(); ++ for (PluginClassLoader classLoader : classLoaders) { ++ loadedClasses.put(classLoader.getPlugin(), new ObjectOpenHashSet<>(classLoader.getLoadedClasses())); ++ } ++ } ++ } ++ } ++ return loadedClasses; ++ } ++ ++} +diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java +index 82b2783497947f336b0dd95db61f31f8f77f446c..d0673f4cea94ce833a08bc3395fe3cc0abb614cb 100644 +--- a/src/test/java/org/bukkit/AnnotationTest.java ++++ b/src/test/java/org/bukkit/AnnotationTest.java +@@ -57,8 +57,11 @@ public class AnnotationTest { + "co/aikar/timings/TimingHistory$2$1$2", + "co/aikar/timings/TimingHistory$3", + "co/aikar/timings/TimingHistory$4", +- "co/aikar/timings/TimingHistoryEntry$1" ++ "co/aikar/timings/TimingHistoryEntry$1", + // Paper end ++ // Yatopia start ++ "org/yatopiamc/yatopia/api/internal/StackTraceUtils" ++ // Yatopia end + }; + + @Test diff --git a/patches/server/0001-Rebrand.patch b/patches/server/0001-Rebrand.patch deleted file mode 100644 index 1ace6cb9..00000000 --- a/patches/server/0001-Rebrand.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Toffikk -Date: Wed, 16 Jun 2021 15:04:11 +0100 -Subject: [PATCH] Rebrand - - -diff --git a/build.gradle.kts b/build.gradle.kts -index f111042223f0d7974785c37245bb60b75388163e..494297e5bed54f7cf41711032391fce991d5efa8 100644 ---- a/build.gradle.kts -+++ b/build.gradle.kts -@@ -19,8 +19,8 @@ repositories { - } - - dependencies { -- implementation(project(":Paper-API")) -- implementation(project(":Paper-MojangAPI")) -+ implementation(project(":Yatopia-API")) // Yatopia -+ implementation("com.destroystokyo.paper:paper-mojangapi:1.16.5-R0.1-SNAPSHOT") // Yatopia - // Paper start - implementation("org.jline:jline-terminal-jansi:3.12.1") - implementation("net.minecrell:terminalconsoleappender:1.2.0") -@@ -65,7 +65,7 @@ tasks.jar { - attributes(mapOf( - "Main-Class" to "org.bukkit.craftbukkit.Main", - "Implementation-Title" to "CraftBukkit", -- "Implementation-Version" to "git-Paper-\"$gitHash\"", -+ "Implementation-Version" to "git-Yatopia-\"$gitHash\"", // Yatopia - "Implementation-Vendor" to SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(Date()), // Paper - "Specification-Title" to "Bukkit", - "Specification-Version" to project.version, -@@ -119,7 +119,7 @@ tasks.test { - fun TaskContainer.registerRunTask( - name: String, block: JavaExec.() -> Unit - ): TaskProvider = register(name) { -- group = "paper" -+ group = "paperweight" // Yatopia - standardInput = System.`in` - workingDir = rootProject.layout.projectDirectory.dir( - providers.gradleProperty("runWorkDir").forUseAtConfigurationTime().orElse("run") -diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -index e0b1f0671d16ddddcb6725acd25a1d1d69e42701..d943a45200b89f541347d0bc7a3e8494022066db 100644 ---- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -+++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -@@ -17,7 +17,7 @@ public final class PaperConsole extends SimpleTerminalConsole { - @Override - protected LineReader buildReader(LineReaderBuilder builder) { - builder -- .appName("Paper") -+ .appName("Yatopia") // Yatopia - .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) - .completer(new ConsoleCommandCompleter(this.server)) - .option(LineReader.Option.COMPLETE_IN_WORD, true); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 1f29c92776aea8dbba52d4cb197addce5b3e4d5e..eab6410651fe41a2aa1db6871fc57ebca0c765c9 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1634,7 +1634,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop // Spigot - Spigot > // CraftBukkit - cb > vanilla! -+ return "Yatopia"; // Yatopia // Tuinity // Paper // Spigot // CraftBukkit - cb > vanilla! - } - - public SystemReport fillSystemReport(SystemReport systemreport) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 8a98bd1018afd934696fedbed24e271ab6b75f51..5c85cdb4ef4ffeebdadf01a4ad4a23801bd3fdca 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -230,7 +230,7 @@ import javax.annotation.Nullable; // Paper - import javax.annotation.Nonnull; // Paper - - public final class CraftServer implements Server { -- private final String serverName = "Paper"; // Paper -+ private final String serverName = "Yatopia"; // Paper // Yatopia - private final String serverVersion; - private final String bukkitVersion = Versioning.getBukkitVersion(); - private final Logger logger = Logger.getLogger("Minecraft"); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index a2a62bfb747994c43b8b0b607af90d3be2836873..b6b6d560d2294b3f9eb80dc167b140949c700e56 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -395,7 +395,7 @@ public final class CraftMagicNumbers implements UnsafeValues { - - @Override - public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { -- return new com.destroystokyo.paper.PaperVersionFetcher(); -+ return new org.yatopiamc.yatopia.server.YatopiaVersionFetcher(); // Yatopia - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -index 774556a62eb240da42e84db4502e2ed43495be17..359e64243b0b7adcc44138d192ea8fad7b10a542 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -@@ -11,7 +11,7 @@ public final class Versioning { - public static String getBukkitVersion() { - String result = "Unknown-Version"; - -- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/io.papermc.paper/paper-api/pom.properties"); -+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.yatopiamc.yatopia/yatopia-api/pom.properties"); // Yatopia - Properties properties = new Properties(); - - if (stream != null) { -diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaVersionFetcher.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaVersionFetcher.java -new file mode 100644 -index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/patches/server/remap in progress/0001-Modify-POM.patch b/patches/server/remap in progress/0001-Modify-POM.patch new file mode 100644 index 00000000..6e4814f0 --- /dev/null +++ b/patches/server/remap in progress/0001-Modify-POM.patch @@ -0,0 +1,144 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: YatopiaMC +Date: Wed, 26 Feb 2020 17:08:07 +0100 +Subject: [PATCH] Modify POM + + +diff --git a/pom.xml b/pom.xml +index 5136762f8e95cb1ea2564b6801703fb6f019fbe1..d39821039daafb19f0efc7346011fdfcc1063236 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -1,11 +1,11 @@ + + 4.0.0 +- tuinity ++ yatopia + jar + 1.16.5-R0.1-SNAPSHOT +- Tuinity-Server +- https://github.com/Spottedleaf/Tuinity ++ Yatopia-Server ++ https://github.com/YatopiaMC/Yatopia + + + +@@ -19,12 +19,21 @@ + + + +- com.tuinity +- tuinity-parent ++ org.yatopiamc ++ yatopia-parent + dev-SNAPSHOT + ../pom.xml + + ++ ++ ++ ++ codemc-snapshots ++ https://repo.codemc.io/repository/nms-local/ ++ ++ ++ ++ + + + +@@ -40,8 +49,8 @@ + + + +- net.pl3x.purpur +- purpur-api ++ org.yatopiamc ++ yatopia-api + + ${project.version} + compile +@@ -56,7 +65,7 @@ + + io.netty + netty-all +- 4.1.50.Final ++ 4.1.63.Final + + + +@@ -73,7 +82,7 @@ + + org.jline + jline-terminal-jansi +- 3.12.1 ++ 3.19.0 + runtime + + + + io.github.classgraph + classgraph +- 4.8.47 ++ 4.8.104 + test + + +@@ -209,6 +218,12 @@ + master-SNAPSHOT + compile + ++ ++ ++ org.apache.commons ++ commons-math3 ++ 3.6.1 ++ + + + +@@ -217,19 +232,32 @@ + purpur-snapshots + https://repo.pl3x.net/ + ++ ++ destroystokyo-repo ++ https://papermc.io/repo/repository/maven-public/ ++ ++ ++ aikar ++ https://repo.aikar.co/nexus/content/repositories/aikar/ ++ ++ ++ ++ velocity ++ https://nexus.velocitypowered.com/repository/maven-public/ ++ + + + + +- tuinity-${minecraft.version} +- install ++ yatopia-${minecraft.version} ++ clean install + + + com.lukegb.mojo + gitdescribe-maven-plugin + 1.3 + +- git-Tuinity- ++ git-Yatopia- + .. + + diff --git a/patches/server/remap in progress/0002-Brandings.patch b/patches/server/remap in progress/0002-Brandings.patch new file mode 100644 index 00000000..7c7f0be6 --- /dev/null +++ b/patches/server/remap in progress/0002-Brandings.patch @@ -0,0 +1,272 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: YatopiaMC +Date: Wed, 26 Feb 2020 18:37:34 +0100 +Subject: [PATCH] Brandings + + +diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java +index 4d8740678049aa749b42618470e9cc838555528d..159f72efe20f8fee940bd00ae7af00f026f51b1a 100644 +--- a/src/main/java/com/destroystokyo/paper/Metrics.java ++++ b/src/main/java/com/destroystokyo/paper/Metrics.java +@@ -593,7 +593,7 @@ public class Metrics { + boolean logFailedRequests = config.getBoolean("logFailedRequests", false); + // Only start Metrics, if it's enabled in the config + if (config.getBoolean("enabled", true)) { +- Metrics metrics = new Metrics("Purpur", serverUUID, logFailedRequests, Bukkit.getLogger()); // Purpur ++ Metrics metrics = new Metrics("Yatopia", serverUUID, logFailedRequests, Bukkit.getLogger()); // Purpur // Yatopia + + metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { + String minecraftVersion = Bukkit.getVersion(); +@@ -603,7 +603,7 @@ public class Metrics { + + metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size())); + metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() ? "online" : (PaperConfig.isProxyOnlineMode() ? "bungee" : "offline"))); // Purpur +- metrics.addCustomChart(new Metrics.SimplePie("purpur_version", () -> (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown")); // Purpur ++ metrics.addCustomChart(new Metrics.SimplePie("yatopia_version", () -> (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown")); // Purpur // Yatopia + + metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { + Map> map = new HashMap<>(); +diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +index e56ebeaaa12494817d31099eed54ef2c50b98b9e..eb0509386feb156ae9c8ca0eb25c0120c9332b19 100644 +--- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java ++++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java +@@ -19,7 +19,7 @@ public final class PaperConsole extends SimpleTerminalConsole { + @Override + protected LineReader buildReader(LineReaderBuilder builder) { + builder +- .appName("Purpur") // Purpur ++ .appName("Yatopia") // Yatopia + .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) + .completer(new ConsoleCommandCompleter(this.server)) + .option(LineReader.Option.COMPLETE_IN_WORD, true); +diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java +index a580b021c7d9727b82a67dedfc509c286feb8c7e..046b6a2f80b3a71437b088cada9dd23ccb231234 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurConfig.java ++++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java +@@ -187,7 +187,7 @@ public class PurpurConfig { + if (!TimingsManager.hiddenConfigs.contains("settings.seed.end-spike")) TimingsManager.hiddenConfigs.add("settings.seed.end-spike"); + } + +- public static String serverModName = "Purpur"; ++ public static String serverModName = "Yatopia"; + private static void serverModName() { + serverModName = getString("settings.server-mod-name", serverModName); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 560020bf1372f68186f78b53502e3d2c145ab098..3bf0e295f7e9a3593789f513863dabaf35f17281 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -230,7 +230,7 @@ import javax.annotation.Nullable; // Paper + import javax.annotation.Nonnull; // Paper + + public final class CraftServer implements Server { +- private final String serverName = "Purpur"; // Paper // Tuinity // Airplane // Purpur ++ private final String serverName = "Yatopia"; // Paper // Tuinity // Airplane // Purpur // Yatopia + private final String serverVersion; + private final String bukkitVersion = Versioning.getBukkitVersion(); + private final Logger logger = Logger.getLogger("Minecraft"); +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 8b344d69b9076e1bf2a5ba310ecf3f8ddd375fdc..05f6fe3db3fd6637e21066b174baef462557804a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -288,7 +288,7 @@ public class Main { + if (buildDate.before(deadline.getTime())) { + // Paper start - This is some stupid bullshit + System.err.println("*** Warning, you've not updated in a while! ***"); +- System.err.println("*** Please download a new build ***"); // Paper // Tuinity ++ System.err.println("*** Please download a new build as per instructions from https://yatopiamc.org/download ***"); // Paper // Tuinity // Yatopia + //System.err.println("*** Server will start in 20 seconds ***"); + //Thread.sleep(TimeUnit.SECONDS.toMillis(20)); + // Paper End +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index bfe4f7ed53620510b52d4f01c5ea2a3f726942d8..5e4f0a216919dc9e622ff2c4b9dd829cd2c71e46 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -397,7 +397,7 @@ public final class CraftMagicNumbers implements UnsafeValues { + + @Override + public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { +- return new net.pl3x.purpur.PurpurVersionFetcher(); ++ return new org.yatopiamc.yatopia.server.YatopiaVersionFetcher(); // Yatopia + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +index 191f5331f0c7871f80f0da9cc38345ce33353577..4776d0f496fb2ed492545ffb53ecf05e79ae2afb 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java +@@ -11,7 +11,7 @@ public final class Versioning { + public static String getBukkitVersion() { + String result = "Unknown-Version"; + +- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/net.pl3x.purpur/purpur-api/pom.properties"); // Tuinity // Airplane // Purpur ++ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.yatopiamc/yatopia-api/pom.properties"); // Tuinity // Airplane // Purpur // Yatopia + Properties properties = new Properties(); + + if (stream != null) { +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index b650f9b6901f15b7fec7a426cd77660039eecd66..b15db666281227d1dc486e4e57dae1831fbf78ec 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -26,7 +26,7 @@ public class WatchdogThread extends Thread + + private WatchdogThread(long timeoutTime, boolean restart) + { +- super( "Paper Watchdog Thread" ); ++ super( "Yatopia Watchdog Thread" ); // Yatopia + this.timeoutTime = timeoutTime; + this.restart = restart; + earlyWarningEvery = Math.min(PaperConfig.watchdogPrintEarlyWarningEvery, timeoutTime); // Paper +@@ -156,14 +156,14 @@ public class WatchdogThread extends Thread + if (isLongTimeout) { + // Paper end + log.log( Level.SEVERE, "------------------------------" ); +- log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper ++ log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Yatopia bug." ); // Paper // Yatopia + log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); + log.log( Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring" ); + log.log( Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once" ); + log.log( Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes" ); +- log.log( Level.SEVERE, "If you are unsure or still think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues" ); ++ log.log( Level.SEVERE, "If you are unsure or still think this is a Yatopia bug, please report this to https://github.com/YatopiaMC/Yatopia/issues" ); // Yatopia + log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" ); +- log.log( Level.SEVERE, "Paper version: " + Bukkit.getServer().getVersion() ); ++ log.log( Level.SEVERE, "Yatopia version: " + Bukkit.getServer().getVersion() ); // Yatopia + // + if ( net.minecraft.world.level.World.lastPhysicsProblem != null ) + { +@@ -186,12 +186,12 @@ public class WatchdogThread extends Thread + // Paper end + } else + { +- log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---"); ++ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO YATOPIA - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---"); // Yatopia + log.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump"); + } + // Paper end - Different message for short timeout + log.log( Level.SEVERE, "------------------------------" ); +- log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper ++ log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Yatopia!):" ); // Paper // Yatopia + ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper + this.dumpTickingInfo(); // Tuinity - log detailed tick information + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( server.serverThread.getId(), Integer.MAX_VALUE ), log ); +@@ -207,7 +207,7 @@ public class WatchdogThread extends Thread + dumpThread( thread, log ); + } + } else { +- log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---"); ++ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO YATOPIA - THIS IS NOT A BUG OR A CRASH ---"); // Yatopia + } + + +diff --git a/src/main/java/net/pl3x/purpur/PurpurVersionFetcher.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaVersionFetcher.java +similarity index 72% +rename from src/main/java/net/pl3x/purpur/PurpurVersionFetcher.java +rename to src/main/java/org/yatopiamc/yatopia/server/YatopiaVersionFetcher.java +index cabfcebf9f944f7a2a2a1cffc7401435803a8741..68212b9bdb9c7faf43f3783a84071da5303d78a9 100644 +--- a/src/main/java/net/pl3x/purpur/PurpurVersionFetcher.java ++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaVersionFetcher.java +@@ -1,7 +1,6 @@ +-package net.pl3x.purpur; ++package org.yatopiamc.yatopia.server; + + import com.destroystokyo.paper.VersionHistoryManager; +-import com.destroystokyo.paper.util.VersionFetcher; + import com.google.common.base.Charsets; + import com.google.common.io.Resources; + import com.google.gson.Gson; +@@ -12,41 +11,51 @@ import net.kyori.adventure.text.TextComponent; + import net.kyori.adventure.text.format.NamedTextColor; + import net.kyori.adventure.text.format.TextDecoration; + +-import javax.annotation.Nonnull; +-import javax.annotation.Nullable; + import java.io.BufferedReader; + import java.io.IOException; ++import java.io.InputStream; + import java.io.InputStreamReader; + import java.net.HttpURLConnection; + import java.net.URL; ++import java.net.URLEncoder; ++import java.util.Arrays; ++import java.util.Objects; ++import java.util.jar.Manifest; ++import javax.annotation.Nonnull; ++ ++import com.destroystokyo.paper.util.VersionFetcher; ++import javax.annotation.Nullable; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.format.NamedTextColor; ++import net.kyori.adventure.text.TextComponent; ++import net.kyori.adventure.text.format.TextDecoration; + +-public class PurpurVersionFetcher implements VersionFetcher { +- private static final String JENKINS_URL = "https://ci.pl3x.net/job/Purpur/lastSuccessfulBuild/buildNumber"; +- private static final String GITHUB_BRANCH_NAME = "master"; ++public class YatopiaVersionFetcher implements VersionFetcher { + + @Override + public long getCacheTime() { +- return 720000; ++ return 3600000; + } + + @Nonnull + @Override + public Component getVersionMessage(@Nonnull String serverVersion) { +- String[] parts = serverVersion.substring("git-Purpur-".length()).split("[-\\s]"); +- final Component updateMessage = getUpdateStatusMessage("pl3xgaming/Purpur", GITHUB_BRANCH_NAME, parts[0]); ++ if (serverVersion.equals("null")) return Component.text("Custom build"); ++ String[] parts = serverVersion.substring("git-Yatopia-".length()).split("[-\\s]"); ++ String branch = String.join("-", Arrays.copyOfRange(parts, 0, parts.length - 3)); ++ String version = parts[parts.length - 3]; ++ final Component updateMessage = getUpdateStatusMessage("YatopiaMC/Yatopia", branch, version); + final Component history = getHistory(); +- +- return history != null ? TextComponent.ofChildren(updateMessage, Component.newline(), history) : updateMessage; ++ return history != null ? TextComponent.ofChildren(history, Component.newline(), updateMessage) : updateMessage; + } + +- private static Component getUpdateStatusMessage(@Nonnull String repo, @Nonnull String branch, @Nonnull String versionInfo) { ++ private Component getUpdateStatusMessage(String repo, String branch, String versionInfo) { + int distance; + try { + int jenkinsBuild = Integer.parseInt(versionInfo); +- distance = fetchDistanceFromJenkins(jenkinsBuild); ++ distance = fetchDistanceFromJenkins(branch, jenkinsBuild); + } catch (NumberFormatException ignored) { +- versionInfo = versionInfo.replace("\"", ""); +- distance = fetchDistanceFromGitHub(repo, branch, versionInfo); ++ distance = fetchDistanceFromGitHub(repo, branch, versionInfo.replace("\"", "")); + } + + switch (distance) { +@@ -61,9 +70,10 @@ public class PurpurVersionFetcher implements VersionFetcher { + } + } + +- private static int fetchDistanceFromJenkins(int jenkinsBuild) { ++ // modified from PurpurVersionFetcher ++ private static int fetchDistanceFromJenkins(String branch, int jenkinsBuild) { + try { +- try (BufferedReader reader = Resources.asCharSource(new URL(JENKINS_URL), Charsets.UTF_8).openBufferedStream()) { ++ try (BufferedReader reader = Resources.asCharSource(new URL("https://ci.codemc.io/job/YatopiaMC/job/Yatopia/job/" + URLEncoder.encode(branch, Charsets.UTF_8.name()) + "/lastStableBuild/buildNumber"), Charsets.UTF_8).openBufferedStream()) { + return Integer.decode(reader.readLine()) - jenkinsBuild; + } catch (NumberFormatException ex) { + ex.printStackTrace(); +@@ -76,6 +86,7 @@ public class PurpurVersionFetcher implements VersionFetcher { + } + + // Contributed by Techcable in GH-65 ++ // from PaperVersionFetcher + private static int fetchDistanceFromGitHub(@Nonnull String repo, @Nonnull String branch, @Nonnull String hash) { + try { + HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + repo + "/compare/" + branch + "..." + hash).openConnection(); +@@ -102,6 +113,7 @@ public class PurpurVersionFetcher implements VersionFetcher { + } + } + ++ // from PaperVersionFetcher + @Nullable + private Component getHistory() { + final VersionHistoryManager.VersionData data = VersionHistoryManager.INSTANCE.getVersionData(); diff --git a/patches/server/remap in progress/0003-Utilities.patch b/patches/server/remap in progress/0003-Utilities.patch new file mode 100644 index 00000000..1594246c --- /dev/null +++ b/patches/server/remap in progress/0003-Utilities.patch @@ -0,0 +1,143 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: YatopiaMC +Date: Fri, 23 Oct 2020 09:20:01 -0700 +Subject: [PATCH] Utilities + +This patch includes all utilities required by the Yatopia project and its patches. + +Co-authored-by: Mykyta Komarnytskyy +Co-authored-by: Ivan Pekov + +diff --git a/pom.xml b/pom.xml +index d39821039daafb19f0efc7346011fdfcc1063236..9e078cfce61a4462cafdb69c1915b2555a4b4f27 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -224,6 +224,12 @@ + commons-math3 + 3.6.1 + ++ ++ ++ org.apache.commons ++ commons-rng-core ++ 1.3 ++ + + + +diff --git a/src/main/java/org/yatopiamc/yatopia/server/util/Constants.java b/src/main/java/org/yatopiamc/yatopia/server/util/Constants.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ac5235155eb1b5515165fc9648b7c9d7a0713b44 +--- /dev/null ++++ b/src/main/java/org/yatopiamc/yatopia/server/util/Constants.java +@@ -0,0 +1,7 @@ ++package org.yatopiamc.yatopia.server.util; ++ ++public class Constants { ++ ++ public static final int[] EMPTY_ARRAY = new int[0]; ++ public static final int[] ZERO_ARRAY = new int[]{0}; ++} +diff --git a/src/main/java/org/yatopiamc/yatopia/server/util/FastRandom.java b/src/main/java/org/yatopiamc/yatopia/server/util/FastRandom.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e41c1e3fa656d8f595733897ab05089c3b0976a7 +--- /dev/null ++++ b/src/main/java/org/yatopiamc/yatopia/server/util/FastRandom.java +@@ -0,0 +1,64 @@ ++package org.yatopiamc.yatopia.server.util; ++ ++import org.apache.commons.rng.core.source64.XoRoShiRo128PlusPlus; ++ ++import java.util.Random; ++import java.util.SplittableRandom; ++ ++public class FastRandom extends Random { ++ ++ private XoRoShiRo128PlusPlus random; ++ ++ public FastRandom() { ++ super(); ++ SplittableRandom randomseed = new SplittableRandom(); ++ this.random = new XoRoShiRo128PlusPlus(randomseed.nextLong(), randomseed.nextLong()); ++ } ++ ++ public FastRandom(long seed) { ++ super(seed); ++ SplittableRandom randomseed = new SplittableRandom(seed); ++ this.random = new XoRoShiRo128PlusPlus(randomseed.nextLong(), randomseed.nextLong()); ++ } ++ ++ @Override ++ public boolean nextBoolean() { ++ return random.nextBoolean(); ++ } ++ ++ @Override ++ public int nextInt() { ++ return random.nextInt(); ++ } ++ ++ @Override ++ public float nextFloat() { ++ return (float) random.nextDouble(); ++ } ++ ++ @Override ++ public double nextDouble() { ++ return random.nextDouble(); ++ } ++ ++ @Override ++ public synchronized void setSeed(long seed) { ++ SplittableRandom randomseed = new SplittableRandom(seed); ++ this.random = new XoRoShiRo128PlusPlus(randomseed.nextLong(), randomseed.nextLong()); ++ } ++ ++ @Override ++ public void nextBytes(byte[] bytes) { ++ random.nextBytes(bytes); ++ } ++ ++ @Override ++ public int nextInt(int bound) { ++ return random.nextInt(bound); ++ } ++ ++ @Override ++ public long nextLong() { ++ return random.nextLong(); ++ } ++} +diff --git a/src/main/java/org/yatopiamc/yatopia/server/util/TimeUtils.java b/src/main/java/org/yatopiamc/yatopia/server/util/TimeUtils.java +new file mode 100644 +index 0000000000000000000000000000000000000000..acdf3d60738791b767a3bafa2c9511342a8c18df +--- /dev/null ++++ b/src/main/java/org/yatopiamc/yatopia/server/util/TimeUtils.java +@@ -0,0 +1,27 @@ ++package org.yatopiamc.yatopia.server.util; ++ ++import java.util.concurrent.TimeUnit; ++ ++public class TimeUtils { ++ ++ public static String getFriendlyName(TimeUnit unit) { ++ switch (unit) { ++ case NANOSECONDS: ++ return "ns"; ++ case MILLISECONDS: ++ return "ms"; ++ case MICROSECONDS: ++ return "micros"; ++ case SECONDS: ++ return "s"; ++ case MINUTES: ++ return "m"; ++ case DAYS: ++ return "d"; ++ case HOURS: ++ return "h"; ++ default: ++ throw new AssertionError(); ++ } ++ } ++} diff --git a/patches/server/remap in progress/0004-Add-GameProfileLookupEvent.patch b/patches/server/remap in progress/0004-Add-GameProfileLookupEvent.patch new file mode 100644 index 00000000..0ec94218 --- /dev/null +++ b/patches/server/remap in progress/0004-Add-GameProfileLookupEvent.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: tr7zw +Date: Wed, 5 Aug 2020 14:25:50 -0500 +Subject: [PATCH] Add GameProfileLookupEvent + + +diff --git a/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java +index 3d9452892a4077e64f37424052a9e52d76dd7a6d..7e88d332b3f31e49935ce7d9f99d447c9427769e 100644 +--- a/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java ++++ b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java +@@ -187,13 +187,24 @@ public class CraftPlayerProfile implements PlayerProfile { + + boolean isCompleteFromCache = this.completeFromCache(true, onlineMode); + if (onlineMode && (!isCompleteFromCache || textures && !hasTextures())) { +- GameProfile result = server.getMinecraftSessionService().fillProfileProperties(profile, true); +- if (result != null) { +- copyProfileProperties(result, this.profile, true); +- } +- if (this.profile.isComplete()) { +- server.getUserCache().saveProfile(this.profile); ++ // Yatopia start ++ dev.tr7zw.yatopia.events.GameProfileLookupEvent event = new ++ dev.tr7zw.yatopia.events.GameProfileLookupEvent( ++ !org.bukkit.Bukkit.isPrimaryThread(), profile.getId(), profile.getName()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ GameProfile eventProfile = event.getGameProfile(); ++ if (eventProfile != null) { ++ this.profile = eventProfile; ++ } else { ++ GameProfile result = server.getMinecraftSessionService().fillProfileProperties(profile, true); ++ if (result != null) { ++ copyProfileProperties(result, this.profile, true); ++ } ++ if (this.profile.isComplete()) { ++ server.getUserCache().saveProfile(this.profile); ++ } + } ++ // Yatopia end + } + return profile.isComplete() && (!onlineMode || !textures || hasTextures()); + } +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java +index 4f7c014fa609a39cac651ccc6d3397d7edb77d8d..fe9238ecc0f3a4948f5867fcae4fe64c9142a98e 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java +@@ -87,7 +87,18 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa + + if ( property == null ) + { ++ // Yatopia start ++ dev.tr7zw.yatopia.events.GameProfileLookupEvent event = ++ new dev.tr7zw.yatopia.events.GameProfileLookupEvent( ++ !org.bukkit.Bukkit.isPrimaryThread(), profile.getId(), profile.getName()); ++ org.bukkit.Bukkit.getPluginManager().callEvent(event); ++ GameProfile eventProfile = event.getGameProfile(); ++ if (eventProfile != null) { ++ profile = eventProfile; ++ } else { + profile = TileEntitySkull.sessionService.fillProfileProperties( profile, true ); ++ } ++ // Yatopia end + } + } + diff --git a/patches/server/remap in progress/0005-Add-last-tick-time-API.patch b/patches/server/remap in progress/0005-Add-last-tick-time-API.patch new file mode 100644 index 00000000..eea18a41 --- /dev/null +++ b/patches/server/remap in progress/0005-Add-last-tick-time-API.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Sun, 27 Sep 2020 18:30:10 +0300 +Subject: [PATCH] Add last tick time API + +Original patch by: +Co-authored-by: tr7zw + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 3f33301c3349c1c04b869a001120d03697afae8d..08d4a2ef671ff750305df9d4c0cac0f2e9c89006 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1068,6 +1068,8 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) { + sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); + if (!hasShownMemoryWarning) { +@@ -50,4 +54,16 @@ public class TicksPerSecondCommand extends Command + return ( ( tps > 18.0 ) ? ChatColor.GREEN : ( tps > 16.0 ) ? ChatColor.YELLOW : ChatColor.RED ).toString() + + ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise + } ++ ++ // Yatopia start ++ public static String formatTo(java.time.Duration duration, java.util.concurrent.TimeUnit unit) ++ { ++ java.util.concurrent.TimeUnit nanosUnit = java.util.concurrent.TimeUnit.NANOSECONDS; ++ long nanos = duration.toNanos(); ++ long toAskedUnit = unit.convert( nanos, nanosUnit ); ++ long ms = nanosUnit.toMillis( nanos ); ++ ChatColor startingColor = ms < 40 ? ChatColor.GREEN : ( ms < 50 ) ? ChatColor.YELLOW : ChatColor.RED; ++ return startingColor.toString() + toAskedUnit + ChatColor.GOLD + org.yatopiamc.yatopia.server.util.TimeUtils.getFriendlyName( unit ); ++ } ++ // Yatopia end + } diff --git a/patches/server/remap in progress/0006-Yatopia-configuration.patch b/patches/server/remap in progress/0006-Yatopia-configuration.patch new file mode 100644 index 00000000..6e44ab36 --- /dev/null +++ b/patches/server/remap in progress/0006-Yatopia-configuration.patch @@ -0,0 +1,324 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: tr7zw +Date: Wed, 5 Aug 2020 08:05:10 -0500 +Subject: [PATCH] Yatopia configuration + +also some basic settings that dont deserve a patch + +diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java +index 4b171a2a60e24947e884f8988920f335bd99a471..5431ec9e8794397b3082a1eb49f82767f083a217 100644 +--- a/src/main/java/co/aikar/timings/TimingsExport.java ++++ b/src/main/java/co/aikar/timings/TimingsExport.java +@@ -234,6 +234,7 @@ public class TimingsExport extends Thread { + pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)), + pair("tuinity", mapAsJSON(Bukkit.spigot().getTuinityConfig(), null)), // Tuinity - add config to timings report + pair("purpur", mapAsJSON(Bukkit.spigot().getPurpurConfig(), null)) ++ , pair("yatopia", mapAsJSON(Bukkit.spigot().getYatopiaConfig(), null)) // Yatopia - add config to timings report + // Purpur end + )); + +@@ -324,7 +325,7 @@ public class TimingsExport extends Thread { + String response = null; + String timingsURL = null; + try { +- HttpURLConnection con = (HttpURLConnection) new URL(net.pl3x.purpur.PurpurConfig.timingsUrl + "/post").openConnection(); // Purpur ++ HttpURLConnection con = (HttpURLConnection) new URL("http://timings.aikar.co/post").openConnection(); // Purpur // Yatopia + con.setDoOutput(true); + String hostName = "BrokenHost"; + try { +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index a257a4ab22eeec2da0a53dccf89e8511be3f5d30..0b7e85f83d1e2494fc58a5563862db18ec8c1081 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -228,6 +228,15 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + gg.airplane.AirplaneConfig.load(); // Airplane - config + gg.airplane.commands.AirplaneCommands.init(); // Airplane - command + ++ // Yatopia start ++ try { ++ org.yatopiamc.yatopia.server.YatopiaConfig.init((java.io.File) options.valueOf("yatopia-settings")); ++ } catch (Exception e) { ++ DedicatedServer.LOGGER.error("Unable to load server configuration", e); ++ return false; ++ } ++ // Yatopia end ++ + this.setPVP(dedicatedserverproperties.pvp); + this.setAllowFlight(dedicatedserverproperties.allowFlight); + this.setResourcePack(dedicatedserverproperties.resourcePack, this.ba()); +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 1f6a84566e8bd2df866fd4c166a0e1874bb1e4bb..36d53df60dfad980119eefa4499f4cb7280f55b1 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -272,7 +272,7 @@ public abstract class PlayerList { + // Spigot - view distance + playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), entityplayer.playerInteractManager.c(), BiomeManager.a(worldserver1.getSeed()), worlddata.isHardcore(), this.server.F(), this.s, worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), this.getMaxPlayers(), worldserver1.getChunkProvider().playerChunkMap.playerChunkManager.getLoadDistance(), flag1, !flag, worldserver1.isDebugWorld(), worldserver1.isFlatWorld())); // Paper - no-tick view distance // Tuinity - replace old player chunk management + entityplayer.getBukkitEntity().sendSupportedChannels(); // CraftBukkit +- playerconnection.sendPacket(new PacketPlayOutCustomPayload(PacketPlayOutCustomPayload.a, (new PacketDataSerializer(Unpooled.buffer())).a(this.getServer().getServerModName()))); ++ playerconnection.sendPacket(new PacketPlayOutCustomPayload(PacketPlayOutCustomPayload.a, (new PacketDataSerializer(Unpooled.buffer())).a(org.yatopiamc.yatopia.server.YatopiaConfig.brandName))); // Yatopia + playerconnection.sendPacket(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); + playerconnection.sendPacket(new PacketPlayOutAbilities(entityplayer.abilities)); + playerconnection.sendPacket(new PacketPlayOutHeldItemSlot(entityplayer.inventory.itemInHandIndex)); +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 330ff6ff03c6be4d35d4f594e3202209ff584341..426936975c876d2aecfc30f9d086ececcc73a3a4 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -370,6 +370,7 @@ public abstract class EntityLiving extends Entity { + this.world.getMethodProfiler().enter("livingEntityBaseTick"); + boolean flag = this instanceof EntityHuman; + ++ if (!org.yatopiamc.yatopia.server.YatopiaConfig.disableEntityStuckChecks) { // Yatopia + if (this.isAlive()) { + if (this.inBlock()) { + this.damageEntity(DamageSource.STUCK, 1.0F); +@@ -386,6 +387,7 @@ public abstract class EntityLiving extends Entity { + } + } + } ++ } // Yatopia + + if (this.isFireProof() || this.world.isClientSide) { + this.extinguish(); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 1f7a592aa8e76d0ff4cb6391f1c0b8a8e85c427d..f4a5ed86dfbd9c11f070d05016fc6a3cc67d4ea1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -877,6 +877,7 @@ public final class CraftServer implements Server { + playerList.getProfileBans().load(); + } catch (IOException ex) { + logger.log(Level.WARNING, "Failed to load banned-players.json, " + ex.getMessage()); ++ org.yatopiamc.yatopia.server.YatopiaConfig.init((File) console.options.valueOf("yatopia-settings")); // Yatopia + } + + org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot +@@ -2408,6 +2409,13 @@ public final class CraftServer implements Server { + org.spigotmc.RestartCommand.restart(); + } + ++ // Yatopia start ++ @Override ++ public YamlConfiguration getYatopiaConfig() { ++ return org.yatopiamc.yatopia.server.YatopiaConfig.config; ++ } ++ // Yatopia end ++ + @Override + public void broadcast(BaseComponent component) { + for (Player player : getOnlinePlayers()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 05f6fe3db3fd6637e21066b174baef462557804a..8a08cd35c4645ef83aa26cbfde1c583b123e2c6a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -170,6 +170,14 @@ public class Main { + .describedAs("Yml file"); + // Origami end - Server Config + ++ // Yatopia start ++ acceptsAll(asList("yatopia", "yatopia-settings"), "File for yatopia settings") ++ .withRequiredArg() ++ .ofType(File.class) ++ .defaultsTo(new File("yatopia.yml")) ++ .describedAs("Yml file"); ++ // Yatopia end ++ + // Paper start + acceptsAll(asList("server-name"), "Name of the server") + .withRequiredArg() +diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f5a43e607f9c13e07a0f5e7e139eed93f159185b +--- /dev/null ++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +@@ -0,0 +1,192 @@ ++package org.yatopiamc.yatopia.server; ++ ++import com.google.common.base.Throwables; ++import java.io.File; ++import java.io.IOException; ++import java.lang.reflect.InvocationTargetException; ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import java.util.List; ++import java.util.concurrent.TimeUnit; ++import java.util.logging.Level; ++import java.util.regex.Pattern; ++import org.bukkit.Bukkit; ++import org.bukkit.configuration.InvalidConfigurationException; ++import org.bukkit.configuration.file.YamlConfiguration; ++ ++public class YatopiaConfig { ++ ++ public static File CONFIG_FILE; ++ private static final String HEADER = "This is the main configuration file for Yatopia.\n" ++ + "Yatopia contains many breaking changes and settings, so know what you are doing!\n" ++ + "You have been warned!\n"; ++ /*========================================================================*/ ++ public static YamlConfiguration config; ++ public static int version; // since we're remapping sidestreams' configs we need this public ++ public static boolean verbose; // since we're remapping sidestreams' configs we need this public ++ /*========================================================================*/ ++ ++ public static void init(File configFile) { ++ CONFIG_FILE = configFile; ++ config = new YamlConfiguration(); ++ try { ++ config.load(CONFIG_FILE); ++ } catch (IOException ex) { ++ } catch (InvalidConfigurationException ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not load yatopia.yml, please correct your syntax errors", ex); ++ throw Throwables.propagate(ex); ++ } ++ config.options().header(HEADER); ++ config.options().copyDefaults(true); ++ verbose = getBoolean("verbose", false); ++ ++ version = getInt("config-version", 1); ++ set("config-version", 1); ++ removeLeftovers(); ++ readConfig(YatopiaConfig.class, null); ++ } ++ ++ private static void removeLeftovers() { ++ // this method is only to remove non-used values in the config ++ ++ // leftover from rainforest ++ if (config.get("world-settings") != null) { ++ set("world-settings", null); ++ } ++ if (config.get("allow-player-item-duplication") != null) { ++ set("allow-player-item-duplication", null); ++ } ++ if (config.get("allow-ridable-chestable-duping") != null) { ++ set("allow-ridable-chestable-duping", null); ++ } ++ if (config.get("allow-sand-duping") != null) { ++ set("allow-sand-duping", null); ++ } ++ } ++ ++ protected static void logError(String s) { ++ Bukkit.getLogger().severe(s); ++ } ++ ++ protected static void log(String s) { ++ if (verbose) { ++ Bukkit.getLogger().info(s); ++ } ++ } ++ ++ static void readConfig(Class clazz, Object instance) { ++ for (Method method : clazz.getDeclaredMethods()) { ++ if (Modifier.isPrivate(method.getModifiers())) { ++ if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) { ++ try { ++ method.setAccessible(true); ++ method.invoke(instance); ++ } catch (InvocationTargetException ex) { ++ throw Throwables.propagate(ex.getCause()); ++ } catch (Exception ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Error invoking " + method, ex); ++ } ++ } ++ } ++ } ++ ++ try { ++ config.save(CONFIG_FILE); ++ } catch (IOException ex) { ++ Bukkit.getLogger().log(Level.SEVERE, "Could not save " + CONFIG_FILE, ex); ++ } ++ } ++ ++ private static final Pattern SPACE = Pattern.compile(" "); ++ private static final Pattern NOT_NUMERIC = Pattern.compile("[^-\\d.]"); ++ ++ public static int getSeconds(String str) { ++ str = SPACE.matcher(str).replaceAll(""); ++ final char unit = str.charAt(str.length() - 1); ++ str = NOT_NUMERIC.matcher(str).replaceAll(""); ++ double num; ++ try { ++ num = Double.parseDouble(str); ++ } catch (Exception e) { ++ num = 0D; ++ } ++ switch (unit) { ++ case 'd': ++ num *= (double) 60 * 60 * 24; ++ break; ++ case 'h': ++ num *= (double) 60 * 60; ++ break; ++ case 'm': ++ num *= 60; ++ break; ++ default: ++ case 's': ++ break; ++ } ++ return (int) num; ++ } ++ ++ protected static String timeSummary(int seconds) { ++ String time = ""; ++ ++ if (seconds > 60 * 60 * 24) { ++ time += TimeUnit.SECONDS.toDays(seconds) + "d"; ++ seconds %= 60 * 60 * 24; ++ } ++ ++ if (seconds > 60 * 60) { ++ time += TimeUnit.SECONDS.toHours(seconds) + "h"; ++ seconds %= 60 * 60; ++ } ++ ++ if (seconds > 0) { ++ time += TimeUnit.SECONDS.toMinutes(seconds) + "m"; ++ } ++ return time; ++ } ++ ++ private static void set(String path, Object val) { ++ config.set(path, val); ++ } ++ ++ private static boolean getBoolean(String path, boolean def) { ++ config.addDefault(path, def); ++ return config.getBoolean(path, config.getBoolean(path)); ++ } ++ ++ private static double getDouble(String path, double def) { ++ config.addDefault(path, def); ++ return config.getDouble(path, config.getDouble(path)); ++ } ++ ++ private static float getFloat(String path, float def) { ++ // TODO: Figure out why getFloat() always returns the default value. ++ return (float) getDouble(path, (double) def); ++ } ++ ++ private static int getInt(String path, int def) { ++ config.addDefault(path, def); ++ return config.getInt(path, config.getInt(path)); ++ } ++ ++ private static List getList(String path, List def) { ++ config.addDefault(path, def); ++ return (List) config.getList(path, config.getList(path)); ++ } ++ ++ private static String getString(String path, String def) { ++ config.addDefault(path, def); ++ return config.getString(path, config.getString(path)); ++ } ++ ++ public static boolean disableEntityStuckChecks = false; ++ private static void disableEntityStuckChecks() { ++ disableEntityStuckChecks = getBoolean("settings.disableEntityStuckChecks", false); ++ } ++ ++ public static String brandName = "Yatopia"; ++ private static void brandName() { ++ brandName = getString("brand-name", brandName); ++ } ++} diff --git a/patches/server/remap in progress/0007-Per-entity-type-collision-settings.patch b/patches/server/remap in progress/0007-Per-entity-type-collision-settings.patch new file mode 100644 index 00000000..a0d88461 --- /dev/null +++ b/patches/server/remap in progress/0007-Per-entity-type-collision-settings.patch @@ -0,0 +1,224 @@ +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 426936975c876d2aecfc30f9d086ececcc73a3a4..3158511eca5467b3891de08bca503f65d3f27154 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -3124,7 +3124,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; ++ } ++} diff --git a/patches/server/remap in progress/0008-Add-NBT-API-as-a-first-class-lib.patch b/patches/server/remap in progress/0008-Add-NBT-API-as-a-first-class-lib.patch new file mode 100644 index 00000000..391fb510 --- /dev/null +++ b/patches/server/remap in progress/0008-Add-NBT-API-as-a-first-class-lib.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: tr7zw +Date: Thu, 2 Apr 2020 18:49:38 +0200 +Subject: [PATCH] Add NBT API as a first-class lib + + +diff --git a/pom.xml b/pom.xml +index 9e078cfce61a4462cafdb69c1915b2555a4b4f27..3cfc312c3f4f5d30421e15977ef2dfeac0c3c841 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -427,6 +427,10 @@ + net/minecraft/server/v${minecraft_version}/$2 + true + ++ ++ de.tr7zw.changeme.nbtapi ++ de.tr7zw.nbtapi ++ + + + diff --git a/patches/server/remap in progress/0009-Modify-default-configs.patch b/patches/server/remap in progress/0009-Modify-default-configs.patch new file mode 100644 index 00000000..4953cbd5 --- /dev/null +++ b/patches/server/remap in progress/0009-Modify-default-configs.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: tr7zw +Date: Tue, 21 Apr 2020 16:14:10 +0200 +Subject: [PATCH] Modify default configs + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index a0ed8ed1d6b89a4f10dff645e09eaff303fb3f8a..3115c6b308c1371f065dcbb60d9443f439e24560 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -206,7 +206,7 @@ public class PaperConfig { + + public static String timingsServerName; + private static void timings() { +- boolean timings = getBoolean("timings.enabled", true); ++ boolean timings = getBoolean("timings.enabled", false); // Yatopia don't profile by default + boolean verboseTimings = getBoolean("timings.verbose", true); + TimingsManager.privacy = getBoolean("timings.server-name-privacy", false); + TimingsManager.hiddenConfigs = getList("timings.hidden-config-entries", Lists.newArrayList("database", "settings.bungeecord-addresses", "settings.velocity-support.secret")); +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 577ed19fa8875ab37433b1061f055521a4245434..c3b31fd44abb1a8731fecc8587d581f4a1efa2e3 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -633,7 +633,7 @@ public class PaperWorldConfig { + } + + public boolean cooldownHopperWhenFull = true; +- public boolean disableHopperMoveEvents = false; ++ public boolean disableHopperMoveEvents = true; // Yatopia disable by default + private void hopperOptimizations() { + cooldownHopperWhenFull = getBoolean("hopper.cooldown-when-full", cooldownHopperWhenFull); + log("Cooldown Hoppers when Full: " + (cooldownHopperWhenFull ? "enabled" : "disabled")); diff --git a/patches/server/remap in progress/0010-lithium-MixinDirection.patch b/patches/server/remap in progress/0010-lithium-MixinDirection.patch new file mode 100644 index 00000000..eb7d78e0 --- /dev/null +++ b/patches/server/remap in progress/0010-lithium-MixinDirection.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Mon, 11 May 2020 21:00:44 +0200 +Subject: [PATCH] lithium MixinDirection + +Original code by JellySquid, licensed under GNU Lesser General Public License v3.0 +you can find the original code on https://github.com/CaffeineMC/lithium-fabric/ (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/core/EnumDirection.java b/src/main/java/net/minecraft/core/EnumDirection.java +index 9f1ea11d0bc15b8b0069fcf46ea2f6751c5e3064..b8fe75b8c37ef1968519e69e078444b1a3c5c359 100644 +--- a/src/main/java/net/minecraft/core/EnumDirection.java ++++ b/src/main/java/net/minecraft/core/EnumDirection.java +@@ -24,13 +24,13 @@ public enum EnumDirection implements INamable { + DOWN(0, 1, -1, "down", EnumDirection.EnumAxisDirection.NEGATIVE, EnumDirection.EnumAxis.Y, new BaseBlockPosition(0, -1, 0)), UP(1, 0, -1, "up", EnumDirection.EnumAxisDirection.POSITIVE, EnumDirection.EnumAxis.Y, new BaseBlockPosition(0, 1, 0)), NORTH(2, 3, 2, "north", EnumDirection.EnumAxisDirection.NEGATIVE, EnumDirection.EnumAxis.Z, new BaseBlockPosition(0, 0, -1)), SOUTH(3, 2, 0, "south", EnumDirection.EnumAxisDirection.POSITIVE, EnumDirection.EnumAxis.Z, new BaseBlockPosition(0, 0, 1)), WEST(4, 5, 1, "west", EnumDirection.EnumAxisDirection.NEGATIVE, EnumDirection.EnumAxis.X, new BaseBlockPosition(-1, 0, 0)), EAST(5, 4, 3, "east", EnumDirection.EnumAxisDirection.POSITIVE, EnumDirection.EnumAxis.X, new BaseBlockPosition(1, 0, 0)); + + private final int g; +- private final int h; ++ private final int h; // Yatopia this is idOpposit(yarn) + private final int i; + private final String j; + private final EnumDirection.EnumAxis k; + private final EnumDirection.EnumAxisDirection l; + private final BaseBlockPosition m; +- private static final EnumDirection[] n = values(); ++ private static final EnumDirection[] n = values(); private static final EnumDirection[] ALL = n;// Yatopia OBF HELPER + private static final Map o = (Map) Arrays.stream(EnumDirection.n).collect(Collectors.toMap(EnumDirection::m, (enumdirection) -> { + return enumdirection; + })); +@@ -112,8 +112,12 @@ public enum EnumDirection implements INamable { + return this.l; + } + ++ /** ++ * @reason Avoid the modulo/abs operations ++ * @author JellySquid ++ */ + public EnumDirection opposite() { +- return fromType1(this.h); ++ return ALL[this.h]; + } + + public EnumDirection rotateCW() { return g(); } // Purpur - OBFHELPER +@@ -214,8 +218,12 @@ public enum EnumDirection implements INamable { + return (float) ((this.i & 3) * 90); + } + ++ /** ++ * @reason Do not allocate an excessive number of Direction arrays ++ * @author JellySquid ++ */ + public static EnumDirection a(Random random) { +- return (EnumDirection) SystemUtils.a((Object[]) EnumDirection.n, random); ++ return ALL[random.nextInt(ALL.length)]; + } + + public static EnumDirection a(double d0, double d1, double d2) { diff --git a/patches/server/remap in progress/0011-lithium-MixinBox.patch b/patches/server/remap in progress/0011-lithium-MixinBox.patch new file mode 100644 index 00000000..b84765fd --- /dev/null +++ b/patches/server/remap in progress/0011-lithium-MixinBox.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Mon, 11 May 2020 21:02:57 +0200 +Subject: [PATCH] lithium MixinBox + +Original code by JellySquid, licensed under GNU Lesser General Public License v3.0 +you can find the original code on https://github.com/CaffeineMC/lithium-fabric/ (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java +index 0248ff18bf3f2dede4d0dda90df5e0eea56b7708..7a3577f919a250eb61b2dfb8d65e668f7af45220 100644 +--- a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java ++++ b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java +@@ -197,12 +197,38 @@ public class AxisAlignedBB { + return new AxisAlignedBB(vec3d.x, vec3d.y, vec3d.z, vec3d.x + 1.0D, vec3d.y + 1.0D, vec3d.z + 1.0D); + } + ++ /** ++ * @reason Simplify the code to better help the JVM optimize it ++ * @author JellySquid ++ */ + public double a(EnumDirection.EnumAxis enumdirection_enumaxis) { +- return enumdirection_enumaxis.a(this.minX, this.minY, this.minZ); ++ switch (enumdirection_enumaxis) { ++ case X: ++ return this.minX; ++ case Y: ++ return this.minY; ++ case Z: ++ return this.minZ; ++ } ++ ++ throw new IllegalArgumentException(); + } + ++ /** ++ * @reason Simplify the code to better help the JVM optimize it ++ * @author JellySquid ++ */ + public double b(EnumDirection.EnumAxis enumdirection_enumaxis) { +- return enumdirection_enumaxis.a(this.maxX, this.maxY, this.maxZ); ++ switch (enumdirection_enumaxis) { ++ case X: ++ return this.maxX; ++ case Y: ++ return this.maxY; ++ case Z: ++ return this.maxZ; ++ } ++ ++ throw new IllegalArgumentException(); + } + + public boolean equals(Object object) { diff --git a/patches/server/remap in progress/0012-lithium-enum_values.patch b/patches/server/remap in progress/0012-lithium-enum_values.patch new file mode 100644 index 00000000..acb4b611 --- /dev/null +++ b/patches/server/remap in progress/0012-lithium-enum_values.patch @@ -0,0 +1,133 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Fri, 31 Jul 2020 21:44:22 -0500 +Subject: [PATCH] lithium enum_values + +Original code by JellySquid, licensed under GNU Lesser General Public License v3.0 +you can find the original code on https://github.com/CaffeineMC/lithium-fabric/ (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/core/EnumAxisCycle.java b/src/main/java/net/minecraft/core/EnumAxisCycle.java +index 8078e4f5b79eaada03508265ba6b81db636e822a..b2d26289a6f501b093ec229394f75864531c978a 100644 +--- a/src/main/java/net/minecraft/core/EnumAxisCycle.java ++++ b/src/main/java/net/minecraft/core/EnumAxisCycle.java +@@ -26,12 +26,24 @@ public enum EnumAxisCycle { + + @Override + public EnumDirection.EnumAxis a(EnumDirection.EnumAxis enumdirection_enumaxis) { +- return null.d[Math.floorMod(enumdirection_enumaxis.ordinal() + 1, 3)]; ++ // Yatopia start - replace logic ++ //return null.d[Math.floorMod(enumdirection_enumaxis.ordinal() + 1, 3)]; ++ switch (enumdirection_enumaxis) { ++ case X: ++ return EnumDirection.EnumAxis.Y; ++ case Y: ++ return EnumDirection.EnumAxis.Z; ++ case Z: ++ return EnumDirection.EnumAxis.X; ++ } ++ ++ throw new IllegalArgumentException(); ++ // Yatopia end + } + + @Override + public EnumAxisCycle a() { +- return null.BACKWARD; ++ return BACKWARD; // Yatopia + } + }, + BACKWARD { +@@ -42,12 +54,24 @@ public enum EnumAxisCycle { + + @Override + public EnumDirection.EnumAxis a(EnumDirection.EnumAxis enumdirection_enumaxis) { +- return null.d[Math.floorMod(enumdirection_enumaxis.ordinal() - 1, 3)]; ++ // Yatopia start - replaced logic ++ //return null.d[Math.floorMod(enumdirection_enumaxis.ordinal() - 1, 3)]; ++ switch (enumdirection_enumaxis) { ++ case X: ++ return EnumDirection.EnumAxis.Z; ++ case Y: ++ return EnumDirection.EnumAxis.X; ++ case Z: ++ return EnumDirection.EnumAxis.Y; ++ } ++ ++ throw new IllegalArgumentException(); ++ // Yatopia end + } + + @Override + public EnumAxisCycle a() { +- return null.FORWARD; ++ return FORWARD; // Yatopia + } + }; + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 3158511eca5467b3891de08bca503f65d3f27154..7b8a2332b0992c4e4b20eedacef4347dd5dc929e 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -2779,10 +2779,12 @@ public abstract class EntityLiving extends Entity { + + } + ++ private static final EnumItemSlot[] aenumitemslot = EnumItemSlot.values(); // Yatopia ++ + @Nullable + private Map q() { + Map map = null; +- EnumItemSlot[] aenumitemslot = EnumItemSlot.values(); ++ //EnumItemSlot[] aenumitemslot = EnumItemSlot.values(); // Yatopia + int i = aenumitemslot.length; + + for (int j = 0; j < i; ++j) { +diff --git a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java +index 8aa51fb207820a7629d50b80ea821ec6cccf8b54..96ec55a705cf372ba1943710362898b73a1464de 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java +@@ -156,9 +156,10 @@ public class BlockPiston extends BlockDirectional { + } + + } ++ private static final EnumDirection[] aenumdirection = EnumDirection.values(); // Yatopia + + private boolean a(World world, BlockPosition blockposition, EnumDirection enumdirection) { +- EnumDirection[] aenumdirection = EnumDirection.values(); ++ //EnumDirection[] aenumdirection = EnumDirection.values(); // Yatopia + int i = aenumdirection.length; + + int j; +@@ -175,12 +176,12 @@ public class BlockPiston extends BlockDirectional { + return true; + } else { + BlockPosition blockposition1 = blockposition.up(); +- EnumDirection[] aenumdirection1 = EnumDirection.values(); ++ //EnumDirection[] aenumdirection1 = EnumDirection.values(); // Yatopia + +- j = aenumdirection1.length; ++ j = aenumdirection.length; // Yatopia + + for (int k = 0; k < j; ++k) { +- EnumDirection enumdirection2 = aenumdirection1[k]; ++ EnumDirection enumdirection2 = aenumdirection[k]; // Yatopia + + if (enumdirection2 != EnumDirection.DOWN && world.isBlockFacePowered(blockposition1.shift(enumdirection2), enumdirection2)) { + return true; +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonExtendsChecker.java b/src/main/java/net/minecraft/world/level/block/piston/PistonExtendsChecker.java +index cbe34059659e0f80ff384508b01e516cd7c5e28a..5813075cd3f2abf53c8a8ed3fa45be89586f25ea 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonExtendsChecker.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonExtendsChecker.java +@@ -173,10 +173,11 @@ public class PistonExtendsChecker { + this.f.addAll(list1); + this.f.addAll(list2); + } ++ private static final EnumDirection[] aenumdirection = EnumDirection.values(); // Yatopia + + private boolean a(BlockPosition blockposition) { + IBlockData iblockdata = this.a.getType(blockposition); +- EnumDirection[] aenumdirection = EnumDirection.values(); ++ //EnumDirection[] aenumdirection = EnumDirection.values(); // Yatopia + int i = aenumdirection.length; + + for (int j = 0; j < i; ++j) { diff --git a/patches/server/remap in progress/0013-lithium-HashedList.patch b/patches/server/remap in progress/0013-lithium-HashedList.patch new file mode 100644 index 00000000..c0c4a5bd --- /dev/null +++ b/patches/server/remap in progress/0013-lithium-HashedList.patch @@ -0,0 +1,294 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Fri, 31 Jul 2020 21:46:32 -0500 +Subject: [PATCH] lithium HashedList + +Original code by JellySquid, licensed under GNU Lesser General Public License v3.0 +you can find the original code on https://github.com/CaffeineMC/lithium-fabric/ (Yarn mappings) + +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/collections/HashedList.java b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/HashedList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2d79932dbd1fc386a94b8d6ea3526934c54c2aad +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/HashedList.java +@@ -0,0 +1,280 @@ ++package me.jellysquid.mods.lithium.common.util.collections; ++ ++import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ReferenceArrayList; ++import java.util.Collection; ++import java.util.Iterator; ++import java.util.List; ++import java.util.ListIterator; ++import java.util.NoSuchElementException; ++ ++/** ++ * Wraps a {@link List} with a hash table which provides O(1) lookups for {@link Collection#contains(Object)}. The type ++ * contained by this list must use reference-equality semantics. ++ */ ++@SuppressWarnings("SuspiciousMethodCalls") ++public class HashedList implements List { ++ private final ReferenceArrayList list; ++ private final Reference2IntOpenHashMap counter; ++ ++ public HashedList(List list) { ++ this.list = new ReferenceArrayList<>(); ++ this.list.addAll(list); ++ ++ this.counter = new Reference2IntOpenHashMap<>(); ++ this.counter.defaultReturnValue(0); ++ ++ for (T obj : this.list) { ++ this.counter.addTo(obj, 1); ++ } ++ } ++ ++ @Override ++ public int size() { ++ return this.list.size(); ++ } ++ ++ @Override ++ public boolean isEmpty() { ++ return this.list.isEmpty(); ++ } ++ ++ @Override ++ public boolean contains(Object o) { ++ return this.counter.containsKey(o); ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return this.listIterator(); ++ } ++ ++ @Override ++ public Object[] toArray() { ++ return this.list.toArray(); ++ } ++ ++ @SuppressWarnings("SuspiciousToArrayCall") ++ @Override ++ public T1[] toArray(T1[] a) { ++ return this.list.toArray(a); ++ } ++ ++ @Override ++ public boolean add(T t) { ++ this.trackReferenceAdded(t); ++ ++ return this.list.add(t); ++ } ++ ++ @Override ++ public boolean remove(Object o) { ++ this.trackReferenceRemoved(o); ++ ++ return this.list.remove(o); ++ } ++ ++ @Override ++ public boolean containsAll(Collection c) { ++ for (Object obj : c) { ++ if (!this.counter.containsKey(obj)) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ ++ @Override ++ public boolean addAll(Collection c) { ++ for (T obj : c) { ++ this.trackReferenceAdded(obj); ++ } ++ ++ return this.list.addAll(c); ++ } ++ ++ @Override ++ public boolean addAll(int index, Collection c) { ++ for (T obj : c) { ++ this.trackReferenceAdded(obj); ++ } ++ ++ return this.list.addAll(index, c); ++ } ++ ++ @Override ++ public boolean removeAll(Collection c) { ++ for (Object obj : c) { ++ this.trackReferenceRemoved(obj); ++ } ++ ++ return this.list.removeAll(c); ++ } ++ ++ @Override ++ public boolean retainAll(Collection c) { ++ return this.list.retainAll(c); ++ } ++ ++ @Override ++ public void clear() { ++ this.counter.clear(); ++ this.list.clear(); ++ } ++ ++ @Override ++ public T get(int index) { ++ return this.list.get(index); ++ } ++ ++ @Override ++ public T set(int index, T element) { ++ T prev = this.list.set(index, element); ++ ++ if (prev != element) { ++ if (prev != null) { ++ this.trackReferenceRemoved(prev); ++ } ++ ++ this.trackReferenceAdded(element); ++ } ++ ++ return prev; ++ } ++ ++ @Override ++ public void add(int index, T element) { ++ this.trackReferenceAdded(element); ++ ++ this.list.add(index, element); ++ } ++ ++ @Override ++ public T remove(int index) { ++ T prev = this.list.remove(index); ++ ++ if (prev != null) { ++ this.trackReferenceRemoved(prev); ++ } ++ ++ return prev; ++ } ++ ++ @Override ++ public int indexOf(Object o) { ++ return this.list.indexOf(o); ++ } ++ ++ @Override ++ public int lastIndexOf(Object o) { ++ return this.list.lastIndexOf(o); ++ } ++ ++ @Override ++ public ListIterator listIterator() { ++ return this.listIterator(0); ++ } ++ ++ @Override ++ public ListIterator listIterator(int index) { ++ return new ListIterator() { ++ private final ListIterator inner = HashedList.this.list.listIterator(index); ++ ++ @Override ++ public boolean hasNext() { ++ return this.inner.hasNext(); ++ } ++ ++ @Override ++ public T next() { ++ return this.inner.next(); ++ } ++ ++ @Override ++ public boolean hasPrevious() { ++ return this.inner.hasPrevious(); ++ } ++ ++ @Override ++ public T previous() { ++ return this.inner.previous(); ++ } ++ ++ @Override ++ public int nextIndex() { ++ return this.inner.nextIndex(); ++ } ++ ++ @Override ++ public int previousIndex() { ++ return this.inner.previousIndex(); ++ } ++ ++ @Override ++ public void remove() { ++ int last = this.previousIndex(); ++ ++ if (last == -1) { ++ throw new NoSuchElementException(); ++ } ++ ++ T prev = HashedList.this.get(last); ++ ++ if (prev != null) { ++ HashedList.this.trackReferenceRemoved(prev); ++ } ++ ++ this.inner.remove(); ++ } ++ ++ @Override ++ public void set(T t) { ++ int last = this.previousIndex(); ++ ++ if (last == -1) { ++ throw new NoSuchElementException(); ++ } ++ ++ T prev = HashedList.this.get(last); ++ ++ if (prev != t) { ++ if (prev != null) { ++ HashedList.this.trackReferenceRemoved(prev); ++ } ++ ++ HashedList.this.trackReferenceAdded(t); ++ } ++ ++ this.inner.remove(); ++ } ++ ++ @Override ++ public void add(T t) { ++ HashedList.this.trackReferenceAdded(t); ++ ++ this.inner.add(t); ++ } ++ }; ++ } ++ ++ @Override ++ public List subList(int fromIndex, int toIndex) { ++ return this.list.subList(fromIndex, toIndex); ++ } ++ ++ private void trackReferenceAdded(T t) { ++ this.counter.addTo(t, 1); ++ } ++ ++ @SuppressWarnings("unchecked") ++ private void trackReferenceRemoved(Object o) { ++ if (this.counter.addTo((T) o, -1) <= 1) { ++ this.counter.removeInt(o); ++ } ++ } ++ ++ public static HashedList wrapper(List list) { ++ return new HashedList<>(list); ++ } ++} diff --git a/patches/server/remap in progress/0014-Item-stuck-sleep-config.patch b/patches/server/remap in progress/0014-Item-stuck-sleep-config.patch new file mode 100644 index 00000000..473b8a0d --- /dev/null +++ b/patches/server/remap in progress/0014-Item-stuck-sleep-config.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: tr7zw +Date: Fri, 31 Jul 2020 21:48:14 -0500 +Subject: [PATCH] Item stuck sleep config + + +diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +index dd4997e7ffac4773e01add88efec7c0dcd7b4df0..2cdb72093c9668d7e5ff4d6d0a91ffbf5889470d 100644 +--- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java ++++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java +@@ -115,7 +115,7 @@ public class EntityItem extends Entity { + + if (this.world.isClientSide) { + this.noclip = false; +- } else { ++ } else if (!this.onGround || this.noclip || this.ticksLived % org.yatopiamc.yatopia.server.YatopiaConfig.itemStuckSleepTicks == 0) { // Yatopia + this.noclip = !this.world.getCubes(this); + if (this.noclip) { + this.l(this.locX(), (this.getBoundingBox().minY + this.getBoundingBox().maxY) / 2.0D, this.locZ()); +diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +index f5a43e607f9c13e07a0f5e7e139eed93f159185b..4722a170519dfebc7b41ce886563a3b80c8e111b 100644 +--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java ++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +@@ -189,4 +189,9 @@ public class YatopiaConfig { + private static void brandName() { + brandName = getString("brand-name", brandName); + } ++ ++ public static int itemStuckSleepTicks = 1; ++ private static void itemStuckSleepTicks() { ++ itemStuckSleepTicks = getInt("settings.itemStuckSleepTicks", 1); ++ } + } diff --git a/patches/server/remap in progress/0015-Option-for-simpler-Villagers.patch b/patches/server/remap in progress/0015-Option-for-simpler-Villagers.patch new file mode 100644 index 00000000..adbae4b3 --- /dev/null +++ b/patches/server/remap in progress/0015-Option-for-simpler-Villagers.patch @@ -0,0 +1,170 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: tr7zw +Date: Fri, 31 Jul 2020 21:58:24 -0500 +Subject: [PATCH] Option for simpler Villagers + + +diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +index e042af3f78a25587ba14d5fd9e346805dd5f1e85..53916eb31f9b5699c56bbe466ba46834149a8f08 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java +@@ -103,6 +103,7 @@ import org.bukkit.event.entity.VillagerReplenishTradeEvent; + + public class EntityVillager extends EntityVillagerAbstract implements ReputationHandler, VillagerDataHolder { + ++ private boolean simplerVillagerBehavior = org.yatopiamc.yatopia.server.YatopiaConfig.simplerVillagerBehavior; // Yatopia - so we don't make them bork upon reload + private static final DataWatcherObject br = DataWatcher.a(EntityVillager.class, DataWatcherRegistry.q); + public static final Map bp = ImmutableMap.of(Items.BREAD, 4, Items.POTATO, 1, Items.CARROT, 1, Items.BEETROOT, 1); + private static final Set bs = ImmutableSet.of(Items.BREAD, Items.POTATO, Items.CARROT, Items.WHEAT, Items.WHEAT_SEEDS, Items.BEETROOT, new Item[]{Items.BEETROOT_SEEDS}); +@@ -139,8 +140,14 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + public EntityVillager(EntityTypes entitytypes, World world, VillagerType villagertype) { + super(entitytypes, world); + this.by = new Reputation(); ++ if (!simplerVillagerBehavior) { + ((Navigation) this.getNavigation()).a(true); + this.getNavigation().d(true); ++ // Yatopia start ++ } else { ++ initPathfinder(); ++ } ++ // Yatopia end + this.setCanPickupLoot(true); + this.setVillagerData(this.getVillagerData().withType(villagertype).withProfession(VillagerProfession.NONE)); + this.brainTickOffset = getRandom().nextInt(100); // Purpur +@@ -161,6 +168,38 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + protected void initPathfinder() { + this.goalSelector.a(0, new PathfinderGoalHasRider(this)); // Purpur + if (world.purpurConfig.villagerFollowEmeraldBlock) this.goalSelector.a(3, new PathfinderGoalTempt(this, 1.0D, false, TEMPT_ITEMS)); ++ // Yatopia Start ++ if (!simplerVillagerBehavior) { ++ // safety ++ return; ++ } ++ this.goalSelector.a(0, new net.minecraft.world.entity.ai.goal.PathfinderGoalFloat(this)); ++ if (org.yatopiamc.yatopia.server.YatopiaConfig.villagersHideAtNight) { ++ this.goalSelector.a(0, new net.minecraft.world.entity.ai.goal.PathfinderGoalUseItem<>(this, net.minecraft.world.item.alchemy.PotionUtil.a(new ItemStack(Items.POTION), net.minecraft.world.item.alchemy.Potions.INVISIBILITY), SoundEffects.ENTITY_WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { ++ return !this.world.isDay() && !entityvillagertrader.isInvisible(); ++ })); ++ this.goalSelector.a(0, new net.minecraft.world.entity.ai.goal.PathfinderGoalUseItem<>(this, new ItemStack(Items.MILK_BUCKET), SoundEffects.ENTITY_WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> { ++ return this.world.isDay() && entityvillagertrader.isInvisible(); ++ })); ++ } ++ this.goalSelector.a(1, new net.minecraft.world.entity.ai.goal.PathfinderGoalTradeWithPlayer(this)); ++ this.goalSelector.a(1, new net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget<>(this, net.minecraft.world.entity.monster.EntityZombie.class, 8.0F, 0.5D, 0.5D)); ++ this.goalSelector.a(1, new net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget<>(this, net.minecraft.world.entity.monster.EntityEvoker.class, 12.0F, 0.5D, 0.5D)); ++ this.goalSelector.a(1, new net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget<>(this, net.minecraft.world.entity.monster.EntityVindicator.class, 8.0F, 0.5D, 0.5D)); ++ this.goalSelector.a(1, new net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget<>(this, net.minecraft.world.entity.monster.EntityVex.class, 8.0F, 0.5D, 0.5D)); ++ this.goalSelector.a(1, new net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget<>(this, net.minecraft.world.entity.monster.EntityPillager.class, 15.0F, 0.5D, 0.5D)); ++ this.goalSelector.a(1, new net.minecraft.world.entity.ai.goal.PathfinderGoalAvoidTarget<>(this, net.minecraft.world.entity.monster.EntityIllagerIllusioner.class, 12.0F, 0.5D, 0.5D)); ++ this.goalSelector.a(1, new net.minecraft.world.entity.ai.goal.PathfinderGoalPanic(this, 0.5D)); ++ this.goalSelector.a(1, new net.minecraft.world.entity.ai.goal.PathfinderGoalLookAtTradingPlayer(this)); ++ this.goalSelector.a(2, new net.minecraft.world.entity.ai.goal.PathfinderGoalStrollVillageGolem(this, 0.6D)); ++ this.goalSelector.a(3, new net.minecraft.world.entity.ai.goal.PathfinderGoalMoveThroughVillage(this, 0.6D, false, 4, () -> { ++ return false; ++ })); ++ this.goalSelector.a(4, new net.minecraft.world.entity.ai.goal.PathfinderGoalMoveTowardsRestriction(this, 0.35D)); ++ this.goalSelector.a(8, new net.minecraft.world.entity.ai.goal.PathfinderGoalRandomStrollLand(this, 0.35D)); ++ this.goalSelector.a(9, new net.minecraft.world.entity.ai.goal.PathfinderGoalInteract(this, EntityHuman.class, 3.0F, 1.0F)); ++ this.goalSelector.a(10, new net.minecraft.world.entity.ai.goal.PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F)); ++ // Yatopia End + } + + @Override +@@ -186,6 +225,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + + @Override + protected BehaviorController a(Dynamic dynamic) { ++ if (simplerVillagerBehavior) return super.a(dynamic); // Yatopia + BehaviorController behaviorcontroller = this.cK().a(dynamic); + + this.a(behaviorcontroller); +@@ -265,6 +305,27 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + // Spigot End + + private int behaviorTick = 0; ++ // Yatopia start ++ private VillagerProfession getRandomProfession() { ++ int type = random.nextInt(13); ++ switch(type) { ++ case 0: return VillagerProfession.ARMORER; ++ case 1: return VillagerProfession.BUTCHER; ++ case 2: return VillagerProfession.CARTOGRAPHER; ++ case 3: return VillagerProfession.CLERIC; ++ case 4: return VillagerProfession.FARMER; ++ case 5: return VillagerProfession.FISHERMAN; ++ case 6: return VillagerProfession.FLETCHER; ++ case 7: return VillagerProfession.LEATHERWORKER; ++ case 8: return VillagerProfession.LIBRARIAN; ++ case 9: return VillagerProfession.MASON; ++ case 10: return VillagerProfession.SHEPHERD; ++ case 11: return VillagerProfession.TOOLSMITH; ++ case 12: return VillagerProfession.WEAPONSMITH; ++ default: return VillagerProfession.FARMER; ++ } ++ } ++ // Yatopia end + + // Purpur start + boolean lobotomized = false; +@@ -290,6 +351,13 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + protected void mobTick() { mobTick(false); } + protected void mobTick(boolean inactive) { + this.world.getMethodProfiler().enter("villagerBrain"); ++ // Yatopia start ++ if (simplerVillagerBehavior && this.getVillagerData().getProfession() == VillagerProfession.NONE) { ++ this.setVillagerData(this.getVillagerData().withProfession(getRandomProfession())); ++ } ++ if (simplerVillagerBehavior && canRefresh()) restUses(); ++ if (simplerVillagerBehavior) return; ++ // Yatopia end + // Purpur start + if (world.purpurConfig.villagerLobotomizeEnabled) inactive = inactive || isLobotomized(); + boolean tick = (world.getTime() + brainTickOffset) % world.purpurConfig.villagerBrainTicks == 0; +@@ -416,6 +484,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + this.fl(); + } + ++ public final boolean canRefresh() { return fc(); } // Yatopia - OBFHELPER + private void fl() { + Iterator iterator = this.getOffers().iterator(); + +@@ -490,6 +559,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + return this.fn() && this.fm(); + } + ++ public final void restUses() { fo(); } // Yatopia - OBFHELPER + private void fo() { + int i = 2 - this.bD; + +@@ -722,6 +792,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + } + + private void a(Entity entity) { ++ if (simplerVillagerBehavior) return; // Yatopia + if (this.world instanceof WorldServer) { + Optional> optional = this.bg.getMemory(MemoryModuleType.VISIBLE_MOBS); + +@@ -738,6 +809,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation + } + + public void a(MemoryModuleType memorymoduletype) { ++ if (simplerVillagerBehavior) return; + if (this.world instanceof WorldServer) { + MinecraftServer minecraftserver = ((WorldServer) this.world).getMinecraftServer(); + +diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +index 4722a170519dfebc7b41ce886563a3b80c8e111b..f318508a4c2a6376b00d55886f313fd4e007c14f 100644 +--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java ++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +@@ -194,4 +194,11 @@ public class YatopiaConfig { + private static void itemStuckSleepTicks() { + itemStuckSleepTicks = getInt("settings.itemStuckSleepTicks", 1); + } ++ ++ public static boolean simplerVillagerBehavior = false; ++ public static boolean villagersHideAtNight = false; ++ private static void villagerSettings() { ++ simplerVillagerBehavior = getBoolean("settings.villager.simplerVillagerBehavior", false); ++ villagersHideAtNight = getBoolean("settings.villager.villagersHideAtNight", false); ++ } + } diff --git a/patches/server/remap in progress/0016-Heavily-optimize-furnance-fuel-and-recipe-lookups.patch b/patches/server/remap in progress/0016-Heavily-optimize-furnance-fuel-and-recipe-lookups.patch new file mode 100644 index 00000000..9e9e041f --- /dev/null +++ b/patches/server/remap in progress/0016-Heavily-optimize-furnance-fuel-and-recipe-lookups.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: tr7zw +Date: Thu, 25 Jun 2020 23:40:12 +0200 +Subject: [PATCH] Heavily optimize furnance fuel and recipe lookups + +Co-authored-by: Mykyta Komarn + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +index ac42fd627009a87709448354f232d8b5ed7fa6b9..8ec9ed518a3b5f70c5a5d74605a1f17d0f47b300 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +@@ -331,7 +331,10 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + this.cookTime = MathHelper.clamp(this.cookTime - 2, 0, this.cookTimeTotal); + } + } else { +- IRecipe irecipe = this.world.getCraftingManager().craft((Recipes) this.c, this, this.world).orElse(null); // Eclipse fail ++ // Yatopia start - used cached recipe if possible, otherwise look up ++ IRecipe irecipe = getCurrentRecipe(); ++ if (irecipe == null) irecipe = this.world.getCraftingManager().craft((Recipes) this.c, this, this.world).orElse(null); // Eclipse fail ++ // Yatopia end + + if (!this.isBurning() && this.canBurn(irecipe)) { + // CraftBukkit start +@@ -663,4 +666,18 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + } + + } ++ ++ // Yatopia start - cache recipe ++ private IRecipe cachedRecipe = null; ++ ++ @Override ++ public IRecipe getCurrentRecipe() { ++ return cachedRecipe; ++ } ++ ++ @Override ++ public void setCurrentRecipe(IRecipe recipe) { ++ cachedRecipe = recipe; ++ } ++ // Yatopia end + } diff --git a/patches/server/remap in progress/0017-Optimize-TileEntity-load-unload.patch b/patches/server/remap in progress/0017-Optimize-TileEntity-load-unload.patch new file mode 100644 index 00000000..293e6e86 --- /dev/null +++ b/patches/server/remap in progress/0017-Optimize-TileEntity-load-unload.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: tr7zw +Date: Wed, 5 Aug 2020 08:08:44 -0500 +Subject: [PATCH] Optimize TileEntity load/unload + + +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index b38ae7942cb1c99ed3d0046a7b813da428d0867c..c3ae27ed4b1cc7ffb36560112459b0746095befd 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -106,8 +106,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public static final ResourceKey THE_END = ResourceKey.a(IRegistry.L, new MinecraftKey("the_end")); + private static final EnumDirection[] a = EnumDirection.values(); + //public final List tileEntityList = Lists.newArrayList(); // Paper - remove unused list +- public final List tileEntityListTick = Lists.newArrayList(); +- protected final List tileEntityListPending = Lists.newArrayList(); ++ public final List tileEntityListTick = me.jellysquid.mods.lithium.common.util.collections.HashedList.wrapper(Lists.newArrayList()); // Yatopia ++ protected final List tileEntityListPending = me.jellysquid.mods.lithium.common.util.collections.HashedList.wrapper(Lists.newArrayList()); // Yatopia + protected final java.util.Set tileEntityListUnload = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>()); // Airplane - use set with faster contains + public final Thread serverThread; + private final boolean debugWorld; diff --git a/patches/server/remap in progress/0018-Global-Eula-file.patch b/patches/server/remap in progress/0018-Global-Eula-file.patch new file mode 100644 index 00000000..daf1727c --- /dev/null +++ b/patches/server/remap in progress/0018-Global-Eula-file.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: tr7zw +Date: Sat, 25 Jul 2020 17:16:18 +0200 +Subject: [PATCH] Global Eula file + + +diff --git a/src/main/java/net/minecraft/server/EULA.java b/src/main/java/net/minecraft/server/EULA.java +index 87891161f5b06bb8be0e2016b490484e6daca9d7..b6d94005cb2d7f28fc4f0b78191ef1ba13190e56 100644 +--- a/src/main/java/net/minecraft/server/EULA.java ++++ b/src/main/java/net/minecraft/server/EULA.java +@@ -17,12 +17,25 @@ public class EULA { + + public EULA(Path path) { + this.b = path; +- this.c = SharedConstants.d || this.b(); ++ this.c = SharedConstants.d || globalEula() || this.b(this.b); // Yatopia + } + +- private boolean b() { ++ // Yatopia start ++ private boolean globalEula() { ++ java.io.File globalEula = new java.io.File(System.getProperty("user.home"), "eula.txt"); ++ ++ if (globalEula.exists()) { ++ return b(globalEula.toPath()); ++ } else { ++ System.out.println("No global eula found at " + globalEula.getAbsolutePath()); ++ } ++ return false; ++ } ++ // Yatopia end ++ ++ private boolean b(java.nio.file.Path path) { // Yatopia + try { +- InputStream inputstream = Files.newInputStream(this.b); ++ InputStream inputstream = Files.newInputStream(path); + Throwable throwable = null; + + boolean flag; diff --git a/patches/server/remap in progress/0019-Redirect-Configs.patch b/patches/server/remap in progress/0019-Redirect-Configs.patch new file mode 100644 index 00000000..cb51889a --- /dev/null +++ b/patches/server/remap in progress/0019-Redirect-Configs.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: tr7zw +Date: Wed, 5 Aug 2020 08:17:46 -0500 +Subject: [PATCH] Redirect Configs + + +diff --git a/src/main/java/de/minebench/origami/OrigamiConfig.java b/src/main/java/de/minebench/origami/OrigamiConfig.java +index a088b8f84f01ce3863ae949f4cd3d7ae9589c27c..4ff5d3d45c1055af148e34d6bfe645a6c3809b89 100644 +--- a/src/main/java/de/minebench/origami/OrigamiConfig.java ++++ b/src/main/java/de/minebench/origami/OrigamiConfig.java +@@ -20,6 +20,8 @@ public final class OrigamiConfig { + private static int configVersion; + + public static void init(final File file) { ++ // Yatopia start ++ /* + OrigamiConfig.configFile = file; + OrigamiConfig.config = new YamlConfiguration(); + config.options().header(CONFIG_HEADER); +@@ -39,13 +41,16 @@ public final class OrigamiConfig { + System.out.println("Failure to load origami config"); + throw new RuntimeException(ex); + } +- } +- +- OrigamiConfig.load(OrigamiConfig.class, null); ++ }*/ ++ config = org.yatopiamc.yatopia.server.YatopiaConfig.config; ++ configFile = org.yatopiamc.yatopia.server.YatopiaConfig.CONFIG_FILE; ++ configVersion = org.yatopiamc.yatopia.server.YatopiaConfig.version; ++ //OrigamiConfig.load(OrigamiConfig.class, null); // todo: uncomment when config options are ported ++ // Yatopia end + } + + public static void load(Class clazz, Object instance) { +- OrigamiConfig.configVersion = OrigamiConfig.getInt("config-version-please-do-not-modify-me", CURRENT_CONFIG_VERSION); ++ //OrigamiConfig.configVersion = OrigamiConfig.getInt("config-version-please-do-not-modify-me", CURRENT_CONFIG_VERSION); // Yatopia - NO + + for (final Method method : clazz.getDeclaredMethods()) { + if (method.getReturnType() != void.class || method.getParameterCount() != 0 || +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 0b7e85f83d1e2494fc58a5563862db18ec8c1081..2662202e60d80af9af33b3dc4af535cf3dd8b366 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -236,7 +236,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + return false; + } + // Yatopia end +- ++ de.minebench.origami.OrigamiConfig.init((java.io.File) options.valueOf("origami-settings")); + this.setPVP(dedicatedserverproperties.pvp); + this.setAllowFlight(dedicatedserverproperties.allowFlight); + this.setResourcePack(dedicatedserverproperties.resourcePack, this.ba()); +diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java +index 8a08cd35c4645ef83aa26cbfde1c583b123e2c6a..18a5c114bdcde9ab2e66d024d4f0365c2d480ab3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Main.java ++++ b/src/main/java/org/bukkit/craftbukkit/Main.java +@@ -316,7 +316,7 @@ public class Main { + } + // Paper end + System.setProperty( "library.jansi.version", "Paper" ); // Paper - set meaningless jansi version to prevent git builds from crashing on Windows +- de.minebench.origami.OrigamiConfig.init((java.io.File) options.valueOf("origami-settings")); // Origami - Server Config ++ //de.minebench.origami.OrigamiConfig.init((java.io.File) options.valueOf("origami-settings")); // Origami - Server Config // Yatopia - no load here for u + System.out.println("Loading libraries, please wait..."); + net.minecraft.server.Main.main(options); + } catch (Throwable t) { diff --git a/patches/server/remap in progress/0020-lithium-DataTrackerMixin.patch b/patches/server/remap in progress/0020-lithium-DataTrackerMixin.patch new file mode 100644 index 00000000..0c34583a --- /dev/null +++ b/patches/server/remap in progress/0020-lithium-DataTrackerMixin.patch @@ -0,0 +1,112 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Tue, 4 Aug 2020 21:46:05 +0200 +Subject: [PATCH] lithium DataTrackerMixin + +Original code by JellySquid, licensed under GNU Lesser General Public License v3.0 +you can find the original code on https://github.com/CaffeineMC/lithium-fabric/ (Yarn mappings) + +Co-authored-by: tr7zw + +diff --git a/src/main/java/net/minecraft/network/syncher/DataWatcher.java b/src/main/java/net/minecraft/network/syncher/DataWatcher.java +index bb09b7be91b488ebc336b2b6f5deafc0ccab27a4..c03f1293848192cada5e3a6238f7a5c11cd4ab10 100644 +--- a/src/main/java/net/minecraft/network/syncher/DataWatcher.java ++++ b/src/main/java/net/minecraft/network/syncher/DataWatcher.java +@@ -32,6 +32,77 @@ public class DataWatcher { + private boolean f = true; + private boolean g; + ++ // Yatopia lithium start ++ private static final int DEFAULT_ENTRY_COUNT = 10, GROW_FACTOR = 8; ++ /** Mirrors the vanilla backing entries map. Each DataWatcher.Item can be accessed in this array through its ID. **/ ++ private DataWatcher.Item[] entriesArray = new DataWatcher.Item[DEFAULT_ENTRY_COUNT]; ++ ++ /** ++ * We redirect the call to add a tracked data to the internal map so we can add it to our new storage structure. This ++ * should only ever occur during entity initialization. Type-erasure is a bit of a pain here since we must redirect ++ * a calls to the generic Map interface. ++ */ ++ private Object onAddTrackedDataInsertMap(Int2ObjectOpenHashMap> map, int keyRaw, DataWatcher.Item valueRaw) { ++ int k = keyRaw; ++ DataWatcher.Item v = (DataWatcher.Item) valueRaw; ++ ++ DataWatcher.Item[] storage = this.entriesArray; ++ ++ // Check if we need to grow the backing array to accommodate the new key range ++ if (storage.length <= k) { ++ // Grow the array to accommodate 8 entries after this one, but limit it to never be larger ++ // than 256 entries as per the vanilla limit ++ int newSize = Math.min(k + GROW_FACTOR, 256); ++ ++ this.entriesArray = storage = java.util.Arrays.copyOf(storage, newSize); ++ } ++ ++ // Update the storage ++ storage[k] = v; ++ ++ // Ensure that the vanilla backing storage is still updated appropriately ++ return this.entries.put(k, v); ++ } ++ ++ /** ++ * @reason Avoid integer boxing/unboxing and use our array-based storage ++ * @author JellySquid ++ */ ++ private DataWatcher.Item getEntry(DataWatcherObject data) { ++ try { ++ DataWatcher.Item[] array = this.entriesArray; ++ ++ int id = data.a(); ++ ++ // The vanilla implementation will simply return null if the tracker doesn't contain the specified entry. However, ++ // accessing an array with an invalid pointer will throw a OOB exception, where-as a HashMap would simply ++ // return null. We check this case (which should be free, even if so insignificant, as the subsequent bounds ++ // check will hopefully be eliminated) ++ if (id < 0 || id >= array.length) { ++ return null; ++ } ++ ++ // This cast can fail if trying to access a entry which doesn't belong to this tracker, as the ID could ++ // instead point to an entry of a different type. However, that is also vanilla behaviour. ++ // noinspection unchecked ++ return (DataWatcher.Item) array[id]; ++ } catch (Throwable cause) { ++ // Move to another method so this function can be in-lined better ++ throw onGetException(cause, data); ++ } ++ } ++ ++ private static ReportedException onGetException(Throwable cause, DataWatcherObject data) { ++ CrashReport report = CrashReport.a(cause, "Getting synced entity data"); ++ ++ CrashReportSystemDetails section = report.a("Synced entity data"); ++ section.a("Data ID", data); ++ ++ return new ReportedException(report); ++ } ++ ++ // Yatopia lithium end ++ + public DataWatcher(Entity entity) { + this.entity = entity; + } +@@ -96,7 +167,8 @@ public class DataWatcher { + DataWatcher.Item datawatcher_item = new DataWatcher.Item<>(datawatcherobject, t0); + + // this.lock.writeLock().lock(); // Spigot - not required +- this.entries.put(datawatcherobject.a(), datawatcher_item); ++ //this.entries.put(datawatcherobject.a(), datawatcher_item); ++ this.onAddTrackedDataInsertMap(this.entries, datawatcherobject.a(), datawatcher_item); // Yatopia lithium + this.f = false; + // this.lock.writeLock().unlock(); // Spigot - not required + } +@@ -127,7 +199,8 @@ public class DataWatcher { + } + + public T get(DataWatcherObject datawatcherobject) { +- return this.b(datawatcherobject).b(); ++ return getEntry(datawatcherobject).b(); // Yatopia ++ //return this.b(datawatcherobject).b(); + } + + public void set(DataWatcherObject datawatcherobject, T t0) { diff --git a/patches/server/remap in progress/0021-Fix-lead-fall-dmg-config.patch b/patches/server/remap in progress/0021-Fix-lead-fall-dmg-config.patch new file mode 100644 index 00000000..05dbc26f --- /dev/null +++ b/patches/server/remap in progress/0021-Fix-lead-fall-dmg-config.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: tr7zw +Date: Tue, 4 Aug 2020 22:08:09 +0200 +Subject: [PATCH] Fix lead fall dmg config + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index f3d1e0bf6b268fffa50181b1901f41539820fe05..286e14bb39509328844e1f57d8faa04b20014f83 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -1426,6 +1426,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + this.fallDistance = 0.0F; + } else if (d0 < 0.0D) { + this.fallDistance = (float) ((double) this.fallDistance - d0); ++ } else if (d0 > 0.0D && org.yatopiamc.yatopia.server.YatopiaConfig.fixFallDistance) { // Yatopia ++ this.fallDistance = 0.0F; // Yatopia + } + + } +diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +index f318508a4c2a6376b00d55886f313fd4e007c14f..50f232c956f68d3d9c3eaf645810e38d805f4531 100644 +--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java ++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +@@ -201,4 +201,9 @@ public class YatopiaConfig { + simplerVillagerBehavior = getBoolean("settings.villager.simplerVillagerBehavior", false); + villagersHideAtNight = getBoolean("settings.villager.villagersHideAtNight", false); + } ++ ++ public static boolean fixFallDistance = false; ++ private static void fixFallDistance() { ++ fixFallDistance = getBoolean("settings.fixFallDistance", false); ++ } + } diff --git a/patches/server/remap in progress/0022-Optimize-some-stuff-in-WorldServer-ticking.patch b/patches/server/remap in progress/0022-Optimize-some-stuff-in-WorldServer-ticking.patch new file mode 100644 index 00000000..8b2a2f31 --- /dev/null +++ b/patches/server/remap in progress/0022-Optimize-some-stuff-in-WorldServer-ticking.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrIvanPlays +Date: Sun, 9 Aug 2020 16:58:18 -0500 +Subject: [PATCH] Optimize some stuff in WorldServer ticking + +Replaced some streams and some array lists with glue lists + +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 7955f847dccf100488f348a1afad4e3ad6be9733..7d2d2790979ef6f31a75e9cf29cc402c4d50a3ef 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -1024,12 +1024,21 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.server.getPlayerList().sendAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.i, this.thunderLevel)); + } + // */ +- for (int idx = 0; idx < this.players.size(); ++idx) { +- if (((EntityPlayer) this.players.get(idx)).world == this) { +- ((EntityPlayer) this.players.get(idx)).tickWeather(); ++ // Yatopia start ++ boolean sleepyMatch = true; ++ for (EntityPlayer player : players) { ++ if (player.world == this) { ++ player.tickWeather(); ++ if (flag != this.isRaining()) player.setPlayerWeather((!flag ? WeatherType.DOWNFALL : WeatherType.CLEAR), false); ++ player.updateWeather(this.lastRainLevel, this.rainLevel, this.lastThunderLevel, this.thunderLevel); ++ } ++ if (sleepyMatch && !player.isSpectator() && !player.isDeeplySleeping() && !player.fauxSleeping) { ++ sleepyMatch = false; + } ++ // Yatopia end + } + ++ /* // Yatopia start - moved up + if (flag != this.isRaining()) { + // Only send weather packets to those affected + for (int idx = 0; idx < this.players.size(); ++idx) { +@@ -1044,11 +1053,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + } + // CraftBukkit end ++ */ // Yatopia end + +- if (this.purpurConfig.playersSkipNight && this.everyoneSleeping && this.players.stream().noneMatch((entityplayer) -> { // Purpur +- return !entityplayer.isSpectator() && !entityplayer.isDeeplySleeping() && !entityplayer.fauxSleeping && !(purpurConfig.idleTimeoutCountAsSleeping && entityplayer.isAfk()); // CraftBukkit // Purpur +- })) { +- // CraftBukkit start ++ if (this.purpurConfig.playersSkipNight && this.everyoneSleeping && sleepyMatch) { // Purpur // Yatopia + long l = this.worldData.getDayTime() + 24000L; + TimeSkipEvent event = new TimeSkipEvent(this.getWorld(), TimeSkipEvent.SkipReason.NIGHT_SKIP, (l - l % 24000L) - this.getDayTime()); + if (this.getGameRules().getBoolean(GameRules.DO_DAYLIGHT_CYCLE)) { +@@ -1253,9 +1260,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + + private void wakeupPlayers() { +- (this.players.stream().filter(EntityLiving::isSleeping).collect(Collectors.toList())).forEach((entityplayer) -> { // CraftBukkit - decompile error ++ for (EntityPlayer entityplayer : players) { if (entityplayer.isSleeping()) { // Yatopia + entityplayer.wakeup(false, false); +- }); ++ }} // Yatopia + } + + // Paper start - optimise random block ticking +@@ -2083,8 +2090,9 @@ public class WorldServer extends World implements GeneratorAccessSeed { + // Spigot start + if ( entity instanceof EntityHuman ) + { +- this.getMinecraftServer().worldServer.values().stream().map( WorldServer::getWorldPersistentData ).forEach( (worldData) -> ++ for ( WorldServer worldServer : getMinecraftServer().worldServer.values() ) // Yatopia + { ++ WorldPersistentData worldData = worldServer.getWorldPersistentData(); // Yatopia + for (Object o : worldData.data.values() ) + { + if ( o instanceof WorldMap ) +@@ -2101,7 +2109,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + } + } +- } ); ++ } // Yatopia + } + // Spigot end + // Spigot Start diff --git a/patches/server/remap in progress/0023-Optimize-BehaviorController.patch b/patches/server/remap in progress/0023-Optimize-BehaviorController.patch new file mode 100644 index 00000000..64b50f7b --- /dev/null +++ b/patches/server/remap in progress/0023-Optimize-BehaviorController.patch @@ -0,0 +1,109 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrIvanPlays +Date: Sun, 9 Aug 2020 22:27:52 +0300 +Subject: [PATCH] Optimize BehaviorController + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/BehaviorController.java b/src/main/java/net/minecraft/world/entity/ai/BehaviorController.java +index fc4216cafbd3a81cac319b11ee093bec38827742..e38cdf81e3f3ba1a2ee86c3a202e5643dd9c0fd1 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/BehaviorController.java ++++ b/src/main/java/net/minecraft/world/entity/ai/BehaviorController.java +@@ -65,13 +65,16 @@ public class BehaviorController { + + mutableobject.setValue((new MapCodec>() { + public Stream keys(DynamicOps dynamicops) { +- return collection.stream().flatMap((memorymoduletype) -> { +- return SystemUtils.a(memorymoduletype.getSerializer().map((codec) -> { +- return IRegistry.MEMORY_MODULE_TYPE.getKey(memorymoduletype); +- })); +- }).map((minecraftkey) -> { +- return dynamicops.createString(minecraftkey.toString()); +- }); ++ // Yatopia start ++ // about previous impl: WHY ? WHO DID THIS TO YOU? ++ Collection candidates = new java.util.ArrayList<>(); ++ for (MemoryModuleType moduleType : collection) { ++ moduleType.getSerializer() ++ .map(c -> IRegistry.MEMORY_MODULE_TYPE.getKey(moduleType)) ++ .ifPresent(key -> candidates.add(dynamicops.createString(key.toString()))); ++ } ++ return candidates.stream(); ++ // Yatopia end + } + + public DataResult> decode(DynamicOps dynamicops, MapLike maplike) { +@@ -83,23 +86,17 @@ public class BehaviorController { + return this.a(memorymoduletype, dynamicops, pair.getSecond()); + }); + +- mutableobject1.setValue(((DataResult) mutableobject1.getValue()).apply2(Builder::add, dataresult1)); ++ mutableobject1.setValue((mutableobject1.getValue()).apply2(Builder::add, dataresult1)); // Yatopia - decompile fix + }); +- DataResult dataresult = (DataResult) mutableobject1.getValue(); +- Logger logger = BehaviorController.LOGGER; ++ DataResult>> dataresult = mutableobject1.getValue(); // Yatopia - decompile fix + +- logger.getClass(); +- ImmutableList> immutablelist = (ImmutableList) dataresult.resultOrPartial(logger::error).map(Builder::build).orElseGet(ImmutableList::of); +- Collection collection2 = collection; +- Collection collection3 = collection1; +- MutableObject mutableobject2 = mutableobject; ++ ImmutableList> immutablelist = dataresult.resultOrPartial(BehaviorController.LOGGER::error).map(Builder::build).orElseGet(ImmutableList::of); // Yatopia - decompile fix + +- mutableobject.getClass(); +- return DataResult.success(new BehaviorController<>(collection2, collection3, immutablelist, mutableobject2::getValue)); ++ return DataResult.success(new BehaviorController<>(collection, collection1, immutablelist, mutableobject::getValue)); // Yatopia - decompile fix + } + + private DataResult> a(MemoryModuleType memorymoduletype, DynamicOps dynamicops, T t0) { +- return ((DataResult) memorymoduletype.getSerializer().map(DataResult::success).orElseGet(() -> { ++ return (memorymoduletype.getSerializer().map(DataResult::success).orElseGet(() -> { // Yatopia - decompile fix + return DataResult.error("No codec for memory: " + memorymoduletype); + })).flatMap((codec) -> { + return codec.parse(dynamicops, t0); +@@ -109,9 +106,9 @@ public class BehaviorController { + } + + public RecordBuilder encode(BehaviorController behaviorcontroller, DynamicOps dynamicops, RecordBuilder recordbuilder) { +- behaviorcontroller.j().forEach((behaviorcontroller_a) -> { ++ for (BehaviorController.a behaviorcontroller_a : behaviorcontroller.memoriesList()) { // Yatopia + behaviorcontroller_a.a(dynamicops, recordbuilder); +- }); ++ } // Yatopia + return recordbuilder; + } + }).fieldOf("memories").codec()); +@@ -170,6 +167,15 @@ public class BehaviorController { + return ((Codec) this.b.get()).encodeStart(dynamicops, this); + } + ++ // Yatopia start ++ private List> memoriesList() { ++ List> ret = new java.util.ArrayList<>(); ++ for (Map.Entry, Optional>> entry : memories.entrySet()) { ++ ret.add(BehaviorController.a.b(entry.getKey(), (Optional) entry.getValue())); ++ } ++ return ret; ++ } ++ // Yatopia end + private Stream> j() { + return this.memories.entrySet().stream().map((entry) -> { + return BehaviorController.a.b((MemoryModuleType) entry.getKey(), (Optional) entry.getValue()); +@@ -208,7 +214,7 @@ public class BehaviorController { + } + + public Optional getMemory(MemoryModuleType memorymoduletype) { +- return ((Optional) this.memories.get(memorymoduletype)).map(ExpirableMemory::c); ++ return (Optional) this.memories.get(memorymoduletype).map(ExpirableMemory::c); // Yatopia - Decompile fix + } + + public boolean b(MemoryModuleType memorymoduletype, U u0) { +@@ -547,7 +553,7 @@ public class BehaviorController { + private final MemoryModuleType a; + private final Optional> b; + +- private static BehaviorController.a b(MemoryModuleType memorymoduletype, Optional> optional) { ++ private static BehaviorController.a b(MemoryModuleType memorymoduletype, Optional> optional) { // Yatopia - decompile fix + return new BehaviorController.a<>(memorymoduletype, optional); + } + diff --git a/patches/server/remap in progress/0024-Add-timings-for-Pathfinder.patch b/patches/server/remap in progress/0024-Add-timings-for-Pathfinder.patch new file mode 100644 index 00000000..b91874da --- /dev/null +++ b/patches/server/remap in progress/0024-Add-timings-for-Pathfinder.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrIvanPlays +Date: Sun, 16 Aug 2020 13:45:32 +0300 +Subject: [PATCH] Add timings for Pathfinder + + +diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java +index 67980e1dc186c0b458eca9f00acfea7d2b26d575..e5df5045c7fb9faf692fed894e1a64fe6e1449af 100644 +--- a/src/main/java/co/aikar/timings/MinecraftTimings.java ++++ b/src/main/java/co/aikar/timings/MinecraftTimings.java +@@ -57,6 +57,8 @@ public final class MinecraftTimings { + return Timings.ofSafe(taskName); + } + ++ public static Timing getPathfinderTiming(String mobName) { return Timings.ofSafe("Pathfinder - " + mobName); } // Yatopia ++ + /** + * Gets a timer associated with a plugins tasks. + * @param bukkitTask +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +index ac7bad10697c6fde7d512753992d59710aa1e032..0c8f3e424a631aca98f83f570aff91c833aaf4b9 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java +@@ -51,6 +51,7 @@ public abstract class NavigationAbstract { + private float r; + private final Pathfinder s; public Pathfinder getPathfinder() { return this.s; } // Paper - OBFHELPER + private boolean t; ++ private co.aikar.timings.Timing timing; // Yatopia + + // Tuinity start + public boolean isViableForPathRecalculationChecking() { +@@ -69,6 +70,7 @@ public abstract class NavigationAbstract { + int i = MathHelper.floor(entityinsentient.b(GenericAttributes.FOLLOW_RANGE) * 16.0D); + + this.s = this.a(i); ++ timing = co.aikar.timings.MinecraftTimings.getPathfinderTiming(entityinsentient.getClass().getSimpleName()); // Yatopia + } + + public void g() { +@@ -253,6 +255,10 @@ public abstract class NavigationAbstract { + } + + public void c() { ++ // Yatopia start ++ timing.startTiming(); ++ try { ++ // Yatopia end + ++this.e; + if (this.m) { + this.j(); +@@ -280,6 +286,11 @@ public abstract class NavigationAbstract { + this.a.getControllerMove().a(vec3d.x, this.b.getType(blockposition.down()).isAir() ? vec3d.y : PathfinderNormal.a((IBlockAccess) this.b, blockposition), vec3d.z, this.d); + } + } ++ // Yatopia start ++ } finally { ++ timing.stopTiming(); ++ } ++ // Yatopia end + } + + protected void l() { diff --git a/patches/server/remap in progress/0025-Highly-optimize-VillagePlace-filtering.patch b/patches/server/remap in progress/0025-Highly-optimize-VillagePlace-filtering.patch new file mode 100644 index 00000000..4d7a533e --- /dev/null +++ b/patches/server/remap in progress/0025-Highly-optimize-VillagePlace-filtering.patch @@ -0,0 +1,479 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Thu, 27 Aug 2020 10:46:17 +0300 +Subject: [PATCH] Highly optimize VillagePlace filtering + +Replaced all streams I could. I expect this to be dropped in the next +major release and reimplemented again if mojang changes stuff with +villagers again. + +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/Producer.java b/src/main/java/me/jellysquid/mods/lithium/common/util/Producer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e647624f4c9afe8bc603792ad88c807ed9f01250 +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/util/Producer.java +@@ -0,0 +1,53 @@ ++package me.jellysquid.mods.lithium.common.util; ++ ++import java.util.List; ++import java.util.Spliterator; ++import java.util.Spliterators; ++import java.util.function.Consumer; ++import java.util.function.Function; ++import java.util.stream.Stream; ++import java.util.stream.StreamSupport; ++import org.yatopiamc.yatopia.server.util.HoldingConsumer; ++ ++public interface Producer { ++ /** ++ * Computes the next sequence of values in a collection. If a null value is passed for {@param consumer}, then ++ * the producer will only return whether or not elements existed. ++ * ++ * @param consumer The (nullable) consumer which will accept the computed values during this run. ++ * @return True if the producer produced any values, otherwise false ++ */ ++ boolean computeNext(Consumer consumer); ++ ++ default Producer map(Function mapper) { ++ return consumer -> { ++ Consumer con = (t) -> consumer.accept(mapper.apply(t)); ++ return Producer.this.computeNext(con); ++ }; ++ } ++ ++ static Stream asStream(Producer producer) { ++ return StreamSupport.stream(new Spliterators.AbstractSpliterator(Long.MAX_VALUE, Spliterator.ORDERED | Spliterator.NONNULL) { ++ @Override ++ public boolean tryAdvance(Consumer action) { ++ return producer.computeNext(action); ++ } ++ }, false); ++ } ++ ++ static void fillList(Producer producer, List list) { ++ HoldingConsumer consumer = new HoldingConsumer<>(); ++ while (producer.computeNext(consumer)) { ++ T value = consumer.getValue(); ++ if (value == null || list.contains(value)) { continue; } ++ list.add(value); ++ } ++ } ++ ++ Producer EMPTY_PRODUCER = consumer -> false; ++ ++ @SuppressWarnings("unchecked") ++ static Producer empty() { ++ return (Producer) EMPTY_PRODUCER; ++ } ++} +diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java +index 17d63cd4ca152adc66ffe9ffd3227a0770738a29..963c1c56732d8c44d9abc1a04cf9fd6f1cc1224d 100644 +--- a/src/main/java/net/minecraft/core/BlockPosition.java ++++ b/src/main/java/net/minecraft/core/BlockPosition.java +@@ -347,6 +347,16 @@ public class BlockPosition extends BaseBlockPosition { + return a(MathHelper.floor(axisalignedbb.minX), MathHelper.floor(axisalignedbb.minY), MathHelper.floor(axisalignedbb.minZ), MathHelper.floor(axisalignedbb.maxX), MathHelper.floor(axisalignedbb.maxY), MathHelper.floor(axisalignedbb.maxZ)); + } + ++ // Yatopia start ++ public static java.util.List getPositions(int i, int j, int k, int l, int i1, int j1) { ++ java.util.List ret = new java.util.ArrayList<>(); ++ Iterable iterable = b(i, j, k, l, i1, j1); ++ org.yatopiamc.yatopia.server.util.HoldingConsumer consumer = new org.yatopiamc.yatopia.server.util.HoldingConsumer<>(); ++ java.util.Spliterator spliterator = iterable.spliterator(); ++ while (spliterator.tryAdvance(consumer)) ret.add(consumer.getValue()); ++ return ret; ++ } ++ // Yatopia end + public static Stream a(int i, int j, int k, int l, int i1, int j1) { + return StreamSupport.stream(b(i, j, k, l, i1, j1).spliterator(), false); + } +diff --git a/src/main/java/net/minecraft/core/SectionPosition.java b/src/main/java/net/minecraft/core/SectionPosition.java +index 427413c668865e1660f1d81daf6a3385f08a0e38..a206a729b3afa01bf591fa4da1e5c14902da4778 100644 +--- a/src/main/java/net/minecraft/core/SectionPosition.java ++++ b/src/main/java/net/minecraft/core/SectionPosition.java +@@ -162,6 +162,7 @@ public class SectionPosition extends BaseBlockPosition { + return this.p().b(8, 8, 8); + } + ++ public final ChunkCoordIntPair asChunkPos() { return r(); } // Yatopia - OBFHELPER + public ChunkCoordIntPair r() { + return new ChunkCoordIntPair(this.a(), this.c()); + } +@@ -176,10 +177,12 @@ public class SectionPosition extends BaseBlockPosition { + return (((long) i & 4194303L) << 42) | (((long) j & 1048575L)) | (((long) k & 4194303L) << 20); // Paper - Simplify to reduce instruction count + } + ++ public final long asLong() { return s(); } // Yatopia - OBFHELPER + public long s() { + return (((long) getX() & 4194303L) << 42) | (((long) getY() & 1048575L)) | (((long) getZ() & 4194303L) << 20); // Paper - Simplify to reduce instruction count + } + ++ public java.util.List tList() { return BlockPosition.getPositions(d(), e(), f(), g(), h(), i()); } // Yatopia + public Stream t() { + return BlockPosition.a(this.d(), this.e(), this.f(), this.g(), this.h(), this.i()); + } +@@ -192,6 +195,18 @@ public class SectionPosition extends BaseBlockPosition { + return a(chunkcoordintpair.x - i, 0, chunkcoordintpair.z - i, chunkcoordintpair.x + i, 15, chunkcoordintpair.z + i); // Paper - simplify/inline + } + ++ // Yatopia start ++ public static java.util.List getPosList(SectionPosition pos, int i) { ++ return getPosList(pos.getX() - i, pos.getY() - i, pos.getZ() - i, pos.getX() + i, pos.getY() + i, pos.getZ() + i); ++ } ++ public static java.util.List getPosList(ChunkCoordIntPair chunkPos, int i) { ++ return getPosList(chunkPos.x - i, 0, chunkPos.z - i, chunkPos.x + i, 15, chunkPos.z + i); ++ } ++ public static java.util.List getPosList(int i, int j, int k, int l, int i1, int j1) { ++ return org.yatopiamc.yatopia.server.YatopiaChunkSectionPos.getChunkSectionPosList(i, j, k, l, i1, j1); ++ } ++ // Yatopia end ++ + public static Stream a(final int i, final int j, final int k, final int l, final int i1, final int j1) { + return StreamSupport.stream(new AbstractSpliterator((long) ((l - i + 1) * (i1 - j + 1) * (j1 - k + 1)), 64) { + final CursorPosition a = new CursorPosition(i, j, k, l, i1, j1); +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java +index 6082eed2d28f3be65daa7e7eb6f2c2a89bb28ff1..29cd71efe86eea2227f373c15c39dc530e9e8199 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java +@@ -193,7 +193,7 @@ public class VillagePlace extends RegionFileSection { + + public long count(Predicate predicate, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { return a(predicate, blockposition, i, villageplace_occupancy); } // Purpur - OBFHELPER + public long a(Predicate predicate, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { +- return this.c(predicate, blockposition, i, villageplace_occupancy).count(); ++ return this.cList(predicate, blockposition, i, villageplace_occupancy).size(); // Yatopia + } + + public boolean a(VillagePlaceType villageplacetype, BlockPosition blockposition) { +@@ -214,6 +214,39 @@ public class VillagePlace extends RegionFileSection { + }); + } + ++ // Yatopia start ++ public java.util.List bList(Predicate filter, BlockPosition pos, int i, VillagePlace.Occupancy occupancy) { ++ int j = org.apache.commons.math3.util.FastMath.floorDiv(i, 16) + 1; ++ ++ java.util.List list = ChunkCoordIntPair.streamList(new ChunkCoordIntPair(pos), j); ++ java.util.List ret = new java.util.ArrayList<>(); ++ for (ChunkCoordIntPair chunkPos : list) { ++ for (int k = 0; k < 16; k++) { // ITS THE LAW ++ this.d(SectionPosition.a(chunkPos, k).asLong()).ifPresent(section -> ret.addAll(section.aList(filter, occupancy))); ++ } ++ } ++ return ret; ++ } ++ public java.util.List cList(Predicate predicate, BlockPosition pos, int i, VillagePlace.Occupancy occupancy) { ++ int j = i * i; ++ java.util.List ret = new java.util.ArrayList<>(); ++ for (VillagePlaceRecord record : this.bList(predicate, pos, i, occupancy)) { ++ if (record.getPosition().distanceSquared(pos) <= j) { ret.add(record); } ++ } ++ return ret; ++ } ++ ++ public java.util.List cListPositions(Predicate predicate, Predicate recordFilter, BlockPosition pos, int i, VillagePlace.Occupancy occupancy) { ++ int j = i * i; ++ java.util.List ret = new java.util.ArrayList<>(); ++ for (VillagePlaceRecord record : this.bList(predicate, pos, i, occupancy)) { ++ BlockPosition recordPosition = record.getPosition(); ++ if (recordPosition.distanceSquared(pos) <= j && recordFilter.test(record)) { ret.add(recordPosition); } ++ } ++ return ret; ++ } ++ // Yatopia end ++ + public Stream c(Predicate predicate, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { + int j = i * i; + +@@ -230,10 +263,28 @@ public class VillagePlace extends RegionFileSection { + }); + } + ++ // Yatopia start ++ public java.util.List aList(Predicate predicate, Predicate posFilter, BlockPosition pos, int i, VillagePlace.Occupancy occupancy) { ++ java.util.List ret = new java.util.ArrayList<>(); ++ int j = i * i; ++ for (VillagePlaceRecord record : this.bList(predicate, pos, i, occupancy)) { ++ BlockPosition recordPosition = record.getPosition(); ++ if (recordPosition.distanceSquared(pos) <= j && posFilter.test(recordPosition)) { ret.add(recordPosition); } ++ } ++ return ret; ++ } ++ // Yatopia end + public Stream a(Predicate predicate, Predicate predicate1, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { + return this.c(predicate, blockposition, i, villageplace_occupancy).map(VillagePlaceRecord::f).filter(predicate1); + } + ++ // Yatopia start ++ public java.util.List bList(Predicate predicate, Predicate posFilter, BlockPosition pos, int i, VillagePlace.Occupancy occupancy) { ++ java.util.List ret = aList(predicate, posFilter, pos, i, occupancy); ++ ret.sort(Comparator.comparingDouble((pos1) -> pos1.distanceSquared(pos))); ++ return ret; ++ } ++ // Yatopia end + public Stream b(Predicate predicate, Predicate predicate1, BlockPosition blockposition, int i, VillagePlace.Occupancy villageplace_occupancy) { + return this.a(predicate, predicate1, blockposition, i, villageplace_occupancy).sorted(Comparator.comparingDouble((blockposition1) -> { + return blockposition1.j(blockposition); +@@ -381,7 +432,7 @@ public class VillagePlace extends RegionFileSection { + } + + private void a(ChunkSection chunksection, SectionPosition sectionposition, BiConsumer biconsumer) { +- sectionposition.t().forEach((blockposition) -> { ++ sectionposition.tList().forEach((blockposition) -> { // Yatopia + IBlockData iblockdata = chunksection.getType(SectionPosition.b(blockposition.getX()), SectionPosition.b(blockposition.getY()), SectionPosition.b(blockposition.getZ())); + + VillagePlaceType.b(iblockdata).ifPresent((villageplacetype) -> { +@@ -391,6 +442,16 @@ public class VillagePlace extends RegionFileSection { + } + + public void a(IWorldReader iworldreader, BlockPosition blockposition, int i) { ++ // Yatopia start - WHY? ++ java.util.List posList = SectionPosition.getPosList(new ChunkCoordIntPair(blockposition), org.apache.commons.math3.util.FastMath.floorDiv(i, 16)); ++ for (SectionPosition pos : posList) { ++ boolean shouldContinue = this.d(pos.asLong()).map(VillagePlaceSection::a).orElse(false); ++ if (shouldContinue) { ++ ChunkCoordIntPair chunkPos = pos.asChunkPos(); ++ if (b.add(chunkPos.pair())) { iworldreader.getChunkAt(chunkPos.x, chunkPos.z, ChunkStatus.EMPTY); } ++ } ++ } ++ /* + SectionPosition.b(new ChunkCoordIntPair(blockposition), Math.floorDiv(i, 16)).map((sectionposition) -> { + return Pair.of(sectionposition, this.d(sectionposition.s())); + }).filter((pair) -> { +@@ -402,6 +463,7 @@ public class VillagePlace extends RegionFileSection { + }).forEach((chunkcoordintpair) -> { + iworldreader.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.EMPTY); + }); ++ */ // Yatopia end + } + + final class a extends LightEngineGraphSection { +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceSection.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceSection.java +index 41ffad7cbb6c77713736f37b3728b201d315f6d4..866e9a434423702d2edaf9b52fa0e6219e13c2d7 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceSection.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceSection.java +@@ -5,6 +5,10 @@ import com.google.common.collect.Maps; + import com.google.common.collect.Sets; + import com.mojang.serialization.Codec; + import com.mojang.serialization.codecs.RecordCodecBuilder; ++// Yatopia start ++import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; ++import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; ++// Yatopia end + import it.unimi.dsi.fastutil.shorts.Short2ObjectMap; + import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap; + import java.util.List; +@@ -53,12 +57,23 @@ public class VillagePlaceSection { + + private VillagePlaceSection(Runnable runnable, boolean flag, List list) { + this.b = new Short2ObjectOpenHashMap(); +- this.c = Maps.newHashMap(); ++ this.c = new Reference2ReferenceOpenHashMap<>(); // Yatopia + this.d = runnable; + this.e = flag; + list.forEach(this::a); + } + ++ // Yatopia start ++ public java.util.List aList(Predicate predicate, VillagePlace.Occupancy occupancy) { ++ java.util.List ret = new java.util.ArrayList<>(); ++ for (Map.Entry> entry : c.entrySet()) { ++ if (predicate.test(entry.getKey())) { ++ for (VillagePlaceRecord record : entry.getValue()) { if (occupancy.a().test(record)) ret.add(record); } ++ } ++ } ++ return ret; ++ } ++ // Yatopia end + public Stream a(Predicate predicate, VillagePlace.Occupancy villageplace_occupancy) { + return this.c.entrySet().stream().filter((entry) -> { + return predicate.test(entry.getKey()); +@@ -101,7 +116,7 @@ public class VillagePlaceSection { + + this.b.put(short0, villageplacerecord); + ((Set) this.c.computeIfAbsent(villageplacetype, (villageplacetype1) -> { +- return Sets.newHashSet(); ++ return new ObjectOpenHashSet<>(); // Yatopia + })).add(villageplacerecord); + return true; + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java +index 4da4fadbd4a036b316d554de20c0d30d35cc206b..4fb72f73ef4a1131ad91b3edea78a79169202720 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java +@@ -856,15 +856,19 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB + private List j() { + BlockPosition blockposition = EntityBee.this.getChunkCoordinates(); + VillagePlace villageplace = ((WorldServer) EntityBee.this.world).y(); +- Stream stream = villageplace.c((villageplacetype) -> { ++ List stream = villageplace.cListPositions((villageplacetype) -> { // Yatopia + return villageplacetype == VillagePlaceType.t || villageplacetype == VillagePlaceType.u; +- }, blockposition, 20, VillagePlace.Occupancy.ANY); +- ++ }, (record) -> i(record.getPosition()), blockposition, 20, VillagePlace.Occupancy.ANY); // Yatopia ++ // Yatopia start ++ stream.sort(Comparator.comparingDouble((pos1) -> pos1.distanceSquared(blockposition))); ++ return stream; ++ /* + return (List) stream.map(VillagePlaceRecord::f).filter((blockposition1) -> { + return EntityBee.this.i(blockposition1); + }).sorted(Comparator.comparingDouble((blockposition1) -> { + return blockposition1.j(blockposition); + })).collect(Collectors.toList()); ++ */ // Yatopia end + } + } + +diff --git a/src/main/java/net/minecraft/world/entity/raid/PersistentRaid.java b/src/main/java/net/minecraft/world/entity/raid/PersistentRaid.java +index 11271762dcf5783c3179de1afc6a882c5330b4dd..a0321663a1cb410505e2b57397c6d0020433e6e1 100644 +--- a/src/main/java/net/minecraft/world/entity/raid/PersistentRaid.java ++++ b/src/main/java/net/minecraft/world/entity/raid/PersistentRaid.java +@@ -98,7 +98,7 @@ public class PersistentRaid extends PersistentBase { + return null; + } else { + BlockPosition blockposition = entityplayer.getChunkCoordinates(); +- List list = (List) this.b.y().c(VillagePlaceType.b, blockposition, 64, VillagePlace.Occupancy.IS_OCCUPIED).collect(Collectors.toList()); ++ List list = this.b.y().cList(VillagePlaceType.b, blockposition, 64, VillagePlace.Occupancy.IS_OCCUPIED); // Yatopia + int i = 0; + Vec3D vec3d = Vec3D.ORIGIN; + +diff --git a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java +index 53eb5b65683a2ab208edfc3f3bbf78ffee61bc85..ab169a113e69305f97c69541bcd4beabd05f9ed8 100644 +--- a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java ++++ b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java +@@ -119,6 +119,15 @@ public class ChunkCoordIntPair { + return a(new ChunkCoordIntPair(chunkcoordintpair.x - i, chunkcoordintpair.z - i), new ChunkCoordIntPair(chunkcoordintpair.x + i, chunkcoordintpair.z + i)); + } + ++ // Yatopia start ++ public static java.util.List streamList(ChunkCoordIntPair center, int radius) { ++ return streamList(new ChunkCoordIntPair(center.x - radius, center.z - radius), new ChunkCoordIntPair(center.x + radius, center.z + radius)); ++ } ++ public static java.util.List streamList(ChunkCoordIntPair pos1, ChunkCoordIntPair pos2) { ++ return org.yatopiamc.yatopia.server.YatopiaChunkPos.asList(pos1, pos2); ++ } ++ // Yatopia end ++ + public static Stream a(final ChunkCoordIntPair chunkcoordintpair, final ChunkCoordIntPair chunkcoordintpair1) { + int i = Math.abs(chunkcoordintpair.x - chunkcoordintpair1.x) + 1; + int j = Math.abs(chunkcoordintpair.z - chunkcoordintpair1.z) + 1; +diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaChunkPos.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaChunkPos.java +new file mode 100644 +index 0000000000000000000000000000000000000000..09700214355375b59697577253ac5df97608690b +--- /dev/null ++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaChunkPos.java +@@ -0,0 +1,54 @@ ++package org.yatopiamc.yatopia.server; ++ ++import java.util.ArrayList; ++import java.util.List; ++import java.util.function.Consumer; ++import me.jellysquid.mods.lithium.common.util.Producer; ++import net.minecraft.world.level.ChunkCoordIntPair; ++ ++public class YatopiaChunkPos { ++ ++ public static List asList(ChunkCoordIntPair pos1, ChunkCoordIntPair pos2) { ++ List list = new ArrayList<>(); ++ Producer.fillList(getStreamProducer(pos1, pos2), list); ++ return list; ++ } ++ ++ /** ++ * [VanillaCopy] but in a producer ++ * ++ * @param pos1 pos 1 ++ * @param pos2 pos 2 ++ * @return producer ++ */ ++ private static Producer getStreamProducer(ChunkCoordIntPair pos1, ChunkCoordIntPair pos2) { ++ final int k = pos1.x < pos2.x ? 1 : -1; ++ final int l = pos1.z < pos2.z ? 1 : -1; ++ ++ return new Producer() { ++ private ChunkCoordIntPair pair = null; ++ ++ @Override ++ public boolean computeNext(Consumer consumer) { ++ if (pair == null) { ++ pair = pos1; ++ } else { ++ int i1 = this.pair.x; ++ int j1 = this.pair.z; ++ ++ if (i1 == pos2.x) { ++ if (j1 == pos2.z) { ++ return false; ++ } ++ ++ this.pair = new ChunkCoordIntPair(pos1.x, j1 + l); ++ } else { ++ this.pair = new ChunkCoordIntPair(i1 + k, j1); ++ } ++ } ++ consumer.accept(pair); ++ return true; ++ } ++ }; ++ } ++} +diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaChunkSectionPos.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaChunkSectionPos.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7dc7ef3b652ad7a4cbb1c08f25d938a79a8b0030 +--- /dev/null ++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaChunkSectionPos.java +@@ -0,0 +1,32 @@ ++package org.yatopiamc.yatopia.server; ++ ++import java.util.ArrayList; ++import java.util.List; ++import java.util.function.Consumer; ++import me.jellysquid.mods.lithium.common.util.Producer; ++import net.minecraft.core.CursorPosition; ++import net.minecraft.core.SectionPosition; ++ ++public class YatopiaChunkSectionPos { ++ ++ public static List getChunkSectionPosList(int i, int j, int k, int l, int i1, int j1) { ++ List list = new ArrayList<>(); ++ Producer.fillList(getChunkSectionPosProducer(i, j, k, l, i1, j1), list); ++ return list; ++ } ++ ++ private static Producer getChunkSectionPosProducer(int i, int j, int k, int l, int i1, int j1) { ++ return new Producer() { ++ final CursorPosition cursorPos = new CursorPosition(i, j, k, l, i1, j1); ++ ++ @Override ++ public boolean computeNext(Consumer consumer) { ++ if (cursorPos.a()) { ++ consumer.accept(SectionPosition.a(cursorPos.b(), cursorPos.c(), cursorPos.d())); ++ return true; ++ } ++ return false; ++ } ++ }; ++ } ++} +diff --git a/src/main/java/org/yatopiamc/yatopia/server/util/HoldingConsumer.java b/src/main/java/org/yatopiamc/yatopia/server/util/HoldingConsumer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..adcbe5a009ef8156945b48c4d29d171ebffc4bec +--- /dev/null ++++ b/src/main/java/org/yatopiamc/yatopia/server/util/HoldingConsumer.java +@@ -0,0 +1,17 @@ ++package org.yatopiamc.yatopia.server.util; ++ ++import java.util.function.Consumer; ++ ++public class HoldingConsumer implements Consumer { ++ ++ private T value; ++ ++ @Override ++ public void accept(T t) { ++ this.value = t; ++ } ++ ++ public T getValue() { ++ return value; ++ } ++} diff --git a/patches/server/remap in progress/0026-Nuke-streams-off-BlockPosition.patch b/patches/server/remap in progress/0026-Nuke-streams-off-BlockPosition.patch new file mode 100644 index 00000000..0040413d --- /dev/null +++ b/patches/server/remap in progress/0026-Nuke-streams-off-BlockPosition.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Tue, 1 Sep 2020 19:11:50 +0300 +Subject: [PATCH] Nuke streams off BlockPosition + + +diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java +index 963c1c56732d8c44d9abc1a04cf9fd6f1cc1224d..092de56e31257c1817a04cc9fc2f9c300bbfa058 100644 +--- a/src/main/java/net/minecraft/core/BlockPosition.java ++++ b/src/main/java/net/minecraft/core/BlockPosition.java +@@ -324,7 +324,15 @@ public class BlockPosition extends BaseBlockPosition { + } + + public static Optional a(BlockPosition blockposition, int i, int j, Predicate predicate) { +- return b(blockposition, i, j, i).filter(predicate).findFirst(); ++ // Yatopia start - avoid using stream ++ // return b(blockposition, i, j, i).filter(predicate).findFirst(); ++ for (BlockPosition pos : a(blockposition, i, j, i)) { ++ if (predicate.test(pos)) { ++ return Optional.of(pos); ++ } ++ } ++ return Optional.empty(); ++ // Yatopia end + } + + public static Stream b(BlockPosition blockposition, int i, int j, int k) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +index d894e7f16d232596ec308f3de3ea5da410588cbe..81cf123cf445716ecaa8496b56b763cb4ae02d68 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java +@@ -735,6 +735,7 @@ public abstract class BlockBase { + return this.getBlock().getInventory(this.p(), world, blockposition); + } + ++ public final boolean hasTag(Tag tag) { return a(tag); } // Yatopia - OBFHELPER + public boolean a(Tag tag) { + return this.getBlock().a(tag); + } diff --git a/patches/server/remap in progress/0027-Nuke-streams-off-SectionPosition.patch b/patches/server/remap in progress/0027-Nuke-streams-off-SectionPosition.patch new file mode 100644 index 00000000..ecf37888 --- /dev/null +++ b/patches/server/remap in progress/0027-Nuke-streams-off-SectionPosition.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Tue, 1 Sep 2020 19:21:52 +0300 +Subject: [PATCH] Nuke streams off SectionPosition + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtil.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtil.java +index 30d14b559f49d8fcaaf519500a6eeeba3d2ce649..e1cfed99747f7220bc2eb306e0eab0106cfe1b0d 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtil.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtil.java +@@ -100,12 +100,25 @@ public class BehaviorUtil { + + public static SectionPosition a(WorldServer worldserver, SectionPosition sectionposition, int i) { + int j = worldserver.b(sectionposition); ++ // Yatopia start - replace stream ++ SectionPosition best = null; ++ for (SectionPosition pos : SectionPosition.getPosList(sectionposition, i)) { ++ if (worldserver.b(pos) < j) { ++ if (best == null || worldserver.b(pos) < worldserver.b(best)) { ++ best = pos; ++ } ++ } ++ } ++ if (best == null) best = sectionposition; ++ return best; ++ /* + Stream stream = SectionPosition.a(sectionposition, i).filter((sectionposition1) -> { // CraftBukkit - decompile error + return worldserver.b(sectionposition1) < j; + }); + + worldserver.getClass(); + return (SectionPosition) stream.min(Comparator.comparingInt(worldserver::b)).orElse(sectionposition); ++ */ // Yatopia end + } + + public static boolean a(EntityInsentient entityinsentient, EntityLiving entityliving, int i) { +diff --git a/src/main/java/net/minecraft/world/entity/raid/Raid.java b/src/main/java/net/minecraft/world/entity/raid/Raid.java +index 457cbdab3fa96fdf7fad1b0206bec9c0aa7847d8..f9d03b6d11ad5ffbfe5be072e8631f046bcd1646 100644 +--- a/src/main/java/net/minecraft/world/entity/raid/Raid.java ++++ b/src/main/java/net/minecraft/world/entity/raid/Raid.java +@@ -397,6 +397,18 @@ public class Raid { + } + + private void z() { ++ // Yatopia start - replace impl ++ BlockPosition best = null; ++ for (SectionPosition pos : SectionPosition.getPosList(SectionPosition.a(center), 2)) { ++ if (world.a(pos)) { ++ BlockPosition asBlockPos = pos.q(); ++ if (best == null || asBlockPos.distanceSquared(center) < best.distanceSquared(center)) { ++ best = asBlockPos; ++ } ++ } ++ } ++ if (best != null) this.c(best); ++ /* + Stream stream = SectionPosition.a(SectionPosition.a(this.center), 2); + WorldServer worldserver = this.world; + +@@ -404,6 +416,7 @@ public class Raid { + stream.filter(worldserver::a).map(SectionPosition::q).min(Comparator.comparingDouble((blockposition) -> { + return blockposition.j(this.center); + })).ifPresent(this::c); ++ */ // Yatopia end + } + + private Optional d(int i) { diff --git a/patches/server/remap in progress/0028-Stop-wasting-resources-on-JsonList-get.patch b/patches/server/remap in progress/0028-Stop-wasting-resources-on-JsonList-get.patch new file mode 100644 index 00000000..b9891d5a --- /dev/null +++ b/patches/server/remap in progress/0028-Stop-wasting-resources-on-JsonList-get.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Fri, 4 Sep 2020 10:07:42 +0300 +Subject: [PATCH] Stop wasting resources on JsonList#get + +Previously, when a banned player attempted to join the server was removing all the stale entries. +This caused a resource waste, which was unnoticeable to users that use ban plugins which doesn't +use the ban list. Akarin's changes for saving it async lowered the pressure, however it was +still pretty high. + +Our changes are the following: +1. Stop removing all stale entries when JsonList#get is called. +2. Only if a player joins and his ban has expired, remove his ban which triggers a save which then + triggers removing of all stale entries. + +diff --git a/src/main/java/net/minecraft/server/players/JsonList.java b/src/main/java/net/minecraft/server/players/JsonList.java +index c960852dc60d0598012c5eef0d139fe38bde63fb..96fbb1a3d216302aa937e07bf88fdb19c6ccc764 100644 +--- a/src/main/java/net/minecraft/server/players/JsonList.java ++++ b/src/main/java/net/minecraft/server/players/JsonList.java +@@ -71,9 +71,13 @@ public abstract class JsonList> { + // Paper start + // this.g(); + // return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error ++ // Yatopia start - only remove if it expires and has been requested ++ return this.getBackingMap().get(this.getMappingKey(k0)); ++ /* + return (V) this.getBackingMap().computeIfPresent(this.getMappingKey(k0), (k, v) -> { + return v.hasExpired() ? null : v; + }); ++ */ // Yatopia end + // Paper end + } + +@@ -151,12 +155,22 @@ public abstract class JsonList> { + this.removeStaleEntries(); // Paper - remove expired values before saving + JsonArray jsonarray = new JsonArray(); + ++ // Yatopia start - we're nuking streams wherever possible ++ /* + this.d.values().stream().map((jsonlistentry) -> { + JsonObject jsonobject = new JsonObject(); + + jsonlistentry.getClass(); + return (JsonObject) SystemUtils.a(jsonobject, jsonlistentry::a); // CraftBukkit - decompile error + }).forEach(jsonarray::add); ++ */ ++ for (V value : this.d.values()) { ++ JsonObject obj = new JsonObject(); ++ // todo: obfhelper for this? ++ value.a(obj); ++ jsonarray.add(obj); ++ } ++ // Yatopia end + BufferedWriter bufferedwriter = Files.newWriter(this.c, StandardCharsets.UTF_8); + Throwable throwable = null; + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 36d53df60dfad980119eefa4499f4cb7280f55b1..bc3adc076870cc7cfb61ac1fa9e4c939b714ef57 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -740,6 +740,7 @@ public abstract class PlayerList { + GameProfileBanEntry gameprofilebanentry; + if (getProfileBans().isBanned(gameprofile) && (gameprofilebanentry = getProfileBans().get(gameprofile)) != null) { + // Paper end ++ if (!gameprofilebanentry.hasExpired()) { // Yatopia + + chatmessage = new ChatMessage("multiplayer.disconnect.banned.reason", new Object[]{gameprofilebanentry.getReason()}); + if (gameprofilebanentry.getExpires() != null) { +@@ -747,7 +748,11 @@ public abstract class PlayerList { + } + + // return chatmessage; +- if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure ++ // Yatopia start ++ /* if (!gameprofilebanentry.hasExpired()) */ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure ++ } else { ++ getProfileBans().remove(gameprofile); ++ } // Yatopia end + } else if (!this.isWhitelisted(gameprofile, event)) { // Paper + //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper + //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted diff --git a/patches/server/remap in progress/0029-Fix-LightEngineThreaded-memory-leak.patch b/patches/server/remap in progress/0029-Fix-LightEngineThreaded-memory-leak.patch new file mode 100644 index 00000000..caacdfa5 --- /dev/null +++ b/patches/server/remap in progress/0029-Fix-LightEngineThreaded-memory-leak.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Thu, 10 Sep 2020 21:02:26 +0300 +Subject: [PATCH] Fix LightEngineThreaded memory leak + + +diff --git a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java +index 76ac408021c5124fd634682cba97dc63392642f5..b8f8fe2ed501efdccc0398fdf99231910a2e110b 100644 +--- a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java ++++ b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java +@@ -123,6 +123,8 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { + } + } + ++ public final void remove(long chunkId) { pendingTasks.removeIf(task -> task.chunkId == chunkId); queueUpdate(); } // Yatopia ++ + public final boolean isEmpty() { + return this.size == 0 && this.pendingTasks.isEmpty(); + } +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index 7d2d2790979ef6f31a75e9cf29cc402c4d50a3ef..aacf99c418b692fa9e29c00ad449b0c8c8c9ef71 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -2069,6 +2069,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { + } + // Paper end + ++ chunkProvider.getLightEngine().queue.remove(chunk.getPos().pair()); // Yatopia - unregister from light queue + } + + public void unregisterEntity(Entity entity) { diff --git a/patches/server/remap in progress/0030-Shutdown-Bootstrap-thread-pool.patch b/patches/server/remap in progress/0030-Shutdown-Bootstrap-thread-pool.patch new file mode 100644 index 00000000..60250a34 --- /dev/null +++ b/patches/server/remap in progress/0030-Shutdown-Bootstrap-thread-pool.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: foss-mc <69294560+foss-mc@users.noreply.github.com> +Date: Sat, 12 Sep 2020 11:12:23 +0800 +Subject: [PATCH] Shutdown Bootstrap thread pool + + +diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java +index 61b4c42e95994343772a91640b243b8e8224e09b..ce440ae5cc843fc6101dd11fd45d9089795411e4 100644 +--- a/src/main/java/net/minecraft/SystemUtils.java ++++ b/src/main/java/net/minecraft/SystemUtils.java +@@ -55,7 +55,7 @@ import org.apache.logging.log4j.Logger; + public class SystemUtils { + + private static final AtomicInteger c = new AtomicInteger(1); +- private static final ExecutorService d = a("Bootstrap", -2); // Paper - add -2 priority ++ public static final ExecutorService d = a("Bootstrap", -2); // Paper - add -2 priority // Yatopia - private -> public + private static final ExecutorService e = a("Main", -1); // Paper - add -1 priority + private static final ExecutorService f = n(); + public static LongSupplier a = System::nanoTime; +diff --git a/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java b/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java +index 28e36ee76da533f8aa0a09cfc4f1fc0f744af715..625dcfaeffb83a0b8b53778c32287cac8daae540 100644 +--- a/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java ++++ b/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java +@@ -199,14 +199,16 @@ public class DataConverterRegistry { + + private static final BiFunction a = Schema::new; + private static final BiFunction b = DataConverterSchemaNamed::new; +- private static final DataFixer c = b(); +- +- private static DataFixer b() { ++ // Yatopia start ++ private static final DataFixer c; ++ static { + DataFixerBuilder datafixerbuilder = new DataFixerBuilder(SharedConstants.getGameVersion().getWorldVersion()); + + a(datafixerbuilder); +- return datafixerbuilder.build(SystemUtils.e()); ++ c = datafixerbuilder.build(SystemUtils.d); ++ SystemUtils.d.shutdown(); + } ++ // Yatopia end + + public static DataFixer getDataFixer() { return a(); } // Paper - OBFHELPER + public static DataFixer a() { diff --git a/patches/server/remap in progress/0031-Optimize-Villagers.patch b/patches/server/remap in progress/0031-Optimize-Villagers.patch new file mode 100644 index 00000000..319d32cb --- /dev/null +++ b/patches/server/remap in progress/0031-Optimize-Villagers.patch @@ -0,0 +1,116 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Sat, 12 Sep 2020 19:17:05 +0300 +Subject: [PATCH] Optimize Villagers + +These changes aim to fix the following: +- Villagers trying to push farther POIs (Points Of Interest) +- Villagers ignoring doors most of the times +- Villagers pushing POIs (Points Of Interest) to unloaded chunks + +The following has been done to fix the mentioned problems: +- Replaced stream off BehaviorFindPosition +- Made sure that chunks are loaded for the POIs (Points Of Interest) that are gonna be tried. +- Added a profession cache, which followed by a stream removal. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java +index 09133c5822bc1386bc3d8a5f3c94196420bbfaea..5397a74e244e9cd6886068e0dfe283ec12ccd922 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorFindPosition.java +@@ -58,7 +58,7 @@ public class BehaviorFindPosition extends Behavior { + if (this.d && entitycreature.isBaby()) { + return false; + } else if (this.f == 0L) { +- this.f = entitycreature.world.getTime() + (long) worldserver.random.nextInt(20); ++ this.f = entitycreature.world.getTime() + (long) java.util.concurrent.ThreadLocalRandom.current().nextInt(20); // Yatopia + return false; + } else { + return worldserver.getTime() >= this.f; +@@ -66,7 +66,7 @@ public class BehaviorFindPosition extends Behavior { + } + + protected void a(WorldServer worldserver, EntityCreature entitycreature, long i) { +- this.f = i + 20L + (long) worldserver.getRandom().nextInt(20); ++ this.f = i + 20L + (long) java.util.concurrent.ThreadLocalRandom.current().nextInt(20); // Yatopia + if (entitycreature.getNavigation().isStuck()) this.f += 200L; // Airplane - wait an additional 10s to check again if they're stuck + VillagePlace villageplace = worldserver.y(); + +@@ -77,12 +77,20 @@ public class BehaviorFindPosition extends Behavior { + BehaviorFindPosition.a behaviorfindposition_a = (BehaviorFindPosition.a) this.g.get(blockposition.asLong()); + + if (behaviorfindposition_a == null) { +- return true; ++ return worldserver.getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; // Yatopia + } else if (!behaviorfindposition_a.c(i)) { + return false; + } else { +- behaviorfindposition_a.a(i); +- return true; ++ // Yatopia start - make sure chunks are loaded ++ int chunkX = blockposition.getX() >> 4; ++ int chunkZ = blockposition.getZ() >> 4; ++ if (worldserver.getChunkIfLoaded(chunkX, chunkZ) != null) { ++ behaviorfindposition_a.a(i); ++ return true; ++ } else { ++ return false; ++ } ++ // Yatopia end + } + }; + // Tuinity start - optimise POI access +@@ -113,7 +121,7 @@ public class BehaviorFindPosition extends Behavior { + BlockPosition blockposition1 = (BlockPosition) iterator.next(); + + this.g.computeIfAbsent(blockposition1.asLong(), (j) -> { +- return new BehaviorFindPosition.a(entitycreature.world.random, i); ++ return new BehaviorFindPosition.a(java.util.concurrent.ThreadLocalRandom.current(), i); // Yatopia + }); + } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceType.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceType.java +index 6a45ab049a4beeeaf7b3b5acf2946767f6e1198f..4af526ecbed506161cb021ea320b0f21112d7bf0 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceType.java ++++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlaceType.java +@@ -23,11 +23,20 @@ import net.minecraft.world.level.block.state.properties.BlockPropertyBedPart; + + public class VillagePlaceType { + ++ public static Set professionCache; // Yatopia + private static final Supplier> y = Suppliers.memoize(() -> { + return (Set) IRegistry.VILLAGER_PROFESSION.g().map(VillagerProfession::b).collect(Collectors.toSet()); + }); + public static final Predicate a = (villageplacetype) -> { +- return ((Set) VillagePlaceType.y.get()).contains(villageplacetype); ++ // Yatopia start ++ if (professionCache == null) { ++ professionCache = new java.util.HashSet<>(); ++ for (VillagerProfession profession : IRegistry.VILLAGER_PROFESSION) { ++ professionCache.add(profession.getPlaceType()); ++ } ++ } ++ return professionCache.contains(villageplacetype); ++ // Yatopia end + }; + public static final Predicate b = (villageplacetype) -> { + return true; +diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java b/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java +index dd9b678481620856fb7eaaa04c3b812c861e892a..d8fc1795b07945b41bd7368529db92fe5cdc4c19 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java ++++ b/src/main/java/net/minecraft/world/entity/npc/VillagerProfession.java +@@ -44,6 +44,7 @@ public class VillagerProfession { + this.t = soundeffect; + } + ++ public final VillagePlaceType getPlaceType() { return b(); } // Yatopia - OBFHELPER + public VillagePlaceType b() { + return this.q; + } +@@ -70,6 +71,7 @@ public class VillagerProfession { + } + + static VillagerProfession a(String s, VillagePlaceType villageplacetype, ImmutableSet immutableset, ImmutableSet immutableset1, @Nullable SoundEffect soundeffect) { ++ VillagePlaceType.professionCache = null; // Yatopia + return (VillagerProfession) IRegistry.a((IRegistry) IRegistry.VILLAGER_PROFESSION, new MinecraftKey(s), (Object) (new VillagerProfession(s, villageplacetype, immutableset, immutableset1, soundeffect))); + } + } diff --git a/patches/server/remap in progress/0032-Optimize-whitelist-command-for-multiple-additions-re.patch b/patches/server/remap in progress/0032-Optimize-whitelist-command-for-multiple-additions-re.patch new file mode 100644 index 00000000..47e2ae6f --- /dev/null +++ b/patches/server/remap in progress/0032-Optimize-whitelist-command-for-multiple-additions-re.patch @@ -0,0 +1,198 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Tue, 22 Sep 2020 10:09:08 +0300 +Subject: [PATCH] Optimize whitelist command for multiple additions / removals + +Previously the whitelist command was adding players 1 by 1. This caused massive overload +when you were adding multiple players due to the fact it saves every time a player was +added. + +These changes aim to reduce that load whenever you are using the /whitelist command. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 08d4a2ef671ff750305df9d4c0cac0f2e9c89006..c50e6c9199e6577a1a1a2b09f53b939e08589501 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -2121,6 +2121,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant commanddispatcher) { + commanddispatcher.register((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) ((LiteralArgumentBuilder) net.minecraft.commands.CommandDispatcher.a("whitelist").requires((commandlistenerwrapper) -> { +@@ -36,11 +36,25 @@ public class CommandWhitelist { + }))).then(net.minecraft.commands.CommandDispatcher.a("add").then(net.minecraft.commands.CommandDispatcher.a("targets", (ArgumentType) ArgumentProfile.a()).suggests((commandcontext, suggestionsbuilder) -> { + PlayerList playerlist = ((CommandListenerWrapper) commandcontext.getSource()).getServer().getPlayerList(); + ++ // Yatopia start - optimize this ++ /* + return ICompletionProvider.b(playerlist.getPlayers().stream().filter((entityplayer) -> { + return !playerlist.getWhitelist().isWhitelisted(entityplayer.getProfile()); + }).map((entityplayer) -> { + return entityplayer.getProfile().getName(); + }), suggestionsbuilder); ++ */ ++ for (net.minecraft.server.level.EntityPlayer player : playerlist.getPlayers()) { ++ if (!playerlist.getWhitelist().isWhitelisted(player.getProfile())) { ++ String remaining = suggestionsbuilder.getRemainingLowercase(); ++ String playerName = player.getName(); ++ if (ICompletionProvider.a(remaining, player.getNameLowercase())) { ++ suggestionsbuilder.suggest(playerName); ++ } ++ } ++ } ++ return suggestionsbuilder.buildFuture(); ++ // Yatopia end + }).executes((commandcontext) -> { + return a((CommandListenerWrapper) commandcontext.getSource(), ArgumentProfile.a(commandcontext, "targets")); + })))).then(net.minecraft.commands.CommandDispatcher.a("remove").then(net.minecraft.commands.CommandDispatcher.a("targets", (ArgumentType) ArgumentProfile.a()).suggests((commandcontext, suggestionsbuilder) -> { +@@ -61,6 +75,8 @@ public class CommandWhitelist { + + private static int a(CommandListenerWrapper commandlistenerwrapper, Collection collection) throws CommandSyntaxException { + WhiteList whitelist = commandlistenerwrapper.getServer().getPlayerList().getWhitelist(); ++ // Yatopia start - rewrite this ++ /* + int i = 0; + Iterator iterator = collection.iterator(); + +@@ -81,10 +97,27 @@ public class CommandWhitelist { + } else { + return i; + } ++ */ ++ java.util.List toAdd = new java.util.ArrayList<>(); ++ for (GameProfile profile : collection) { ++ if (!whitelist.isWhitelisted(profile)) { ++ toAdd.add(new WhiteListEntry(profile)); ++ commandlistenerwrapper.sendMessage(new ChatMessage("commands.whitelist.add.success", ChatComponentUtils.a(profile)), true); ++ } ++ } ++ if (toAdd.isEmpty()) { ++ throw CommandWhitelist.ADD_FAILED.create(); ++ } else { ++ whitelist.addAll(toAdd); ++ return toAdd.size(); ++ } ++ // Yatopia end + } + + private static int b(CommandListenerWrapper commandlistenerwrapper, Collection collection) throws CommandSyntaxException { + WhiteList whitelist = commandlistenerwrapper.getServer().getPlayerList().getWhitelist(); ++ // Yatopia start - rewrite this ++ /* + int i = 0; + Iterator iterator = collection.iterator(); + +@@ -106,6 +139,22 @@ public class CommandWhitelist { + commandlistenerwrapper.getServer().a(commandlistenerwrapper); + return i; + } ++ */ ++ java.util.List> toRemove = new java.util.ArrayList<>(); ++ for (GameProfile profile : collection) { ++ if (whitelist.isWhitelisted(profile)) { ++ toRemove.add(new WhiteListEntry(profile)); ++ commandlistenerwrapper.sendMessage(new ChatMessage("commands.whitelist.remove.success", ChatComponentUtils.a(profile)), true); ++ } ++ } ++ if (toRemove.isEmpty()) { ++ throw CommandWhitelist.REMOVE_FAILED.create(); ++ } else { ++ whitelist.removeAll(toRemove); ++ commandlistenerwrapper.getServer().kickNotWhitelisted(commandlistenerwrapper); ++ return toRemove.size(); ++ } ++ // Yatopia end + } + + private static int b(CommandListenerWrapper commandlistenerwrapper) throws CommandSyntaxException { +diff --git a/src/main/java/net/minecraft/server/players/JsonList.java b/src/main/java/net/minecraft/server/players/JsonList.java +index 96fbb1a3d216302aa937e07bf88fdb19c6ccc764..0521fa09488ef501cc5bcdf6c3134ac920a2e94a 100644 +--- a/src/main/java/net/minecraft/server/players/JsonList.java ++++ b/src/main/java/net/minecraft/server/players/JsonList.java +@@ -66,6 +66,20 @@ public abstract class JsonList> { + + } + ++ // Yatopia start ++ public void addAll(Iterable values) { ++ for (V value : values) { ++ d.put(getMappingKey(value.getKey()), value); ++ } ++ ++ try { ++ this.save(); ++ } catch (IOException io) { ++ JsonList.LOGGER.warn("Could not save the list after adding a user.", io); ++ } ++ } ++ // Yatopia end ++ + @Nullable + public V get(K k0) { + // Paper start +@@ -96,6 +110,20 @@ public abstract class JsonList> { + this.remove(jsonlistentry.getKey()); + } + ++ // Yatopia start ++ public void removeAll(Iterable> values) { ++ for (JsonListEntry entry : values) { ++ this.d.remove(getMappingKey(entry.getKey())); ++ } ++ ++ try { ++ this.save(); ++ } catch (IOException io) { ++ JsonList.LOGGER.warn("Could not save the list after removing a user.", io); ++ } ++ } ++ // Yatopia end ++ + public String[] getEntries() { + return (String[]) this.d.keySet().toArray(new String[this.d.size()]); + } +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 0443aaa9fc4058cc4ce61977a89cdf6ea6452b65..1406a4edfe3f95ff8be5d5e430b505ae845b9516 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -175,6 +175,7 @@ public abstract class EntityHuman extends EntityLiving { + // CraftBukkit start + public boolean fauxSleeping; + public int oldLevel = -1; ++ private String nameLowercase = null; // Yatopia + + @Override + public CraftHumanEntity getBukkitEntity() { +@@ -2085,6 +2086,15 @@ public abstract class EntityHuman extends EntityLiving { + return this.getProfile().getName(); + } + ++ // Yatopia start ++ public String getNameLowercase() { ++ if (nameLowercase == null) { ++ nameLowercase = getProfile().getName().toLowerCase(java.util.Locale.ROOT); ++ } ++ return nameLowercase; ++ } ++ // Yatopia end ++ + @Override + public float b(EntityPose entitypose, EntitySize entitysize) { + switch (entitypose) { diff --git a/patches/server/remap in progress/0033-PlayerAttackEntityEvent.patch b/patches/server/remap in progress/0033-PlayerAttackEntityEvent.patch new file mode 100644 index 00000000..a6d361cf --- /dev/null +++ b/patches/server/remap in progress/0033-PlayerAttackEntityEvent.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Tue, 22 Sep 2020 12:52:34 +0300 +Subject: [PATCH] PlayerAttackEntityEvent + +Added per request + +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 1406a4edfe3f95ff8be5d5e430b505ae845b9516..6c16db02cc405fb8a7d9ac2fa70882a6e6edbfec 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -1188,12 +1188,50 @@ public abstract class EntityHuman extends EntityLiving { + + flag2 = flag2 && !world.paperConfig.disablePlayerCrits; // Paper + flag2 = flag2 && !this.isSprinting(); +- if (flag2) { +- this.isCritical = true; // Purpur +- f *= this.world.purpurConfig.playerCriticalDamageMultiplier; // Purpur ++ // Yatopia start - PlayerAttackEntityEvent ++ /* ++ if (flag2) { ++ this.isCritical = true; // Purpur ++ f *= 1.5F; ++ } ++ ++ f += f1; ++ */ ++ net.yatopia.api.event.PlayerAttackEntityEvent playerAttackEntityEvent = ++ new net.yatopia.api.event.PlayerAttackEntityEvent( ++ getBukkitEntity(), ++ entity.getBukkitEntity(), ++ org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(getItemInMainHand()), ++ flag2, f + f1 ++ ); ++ float totalDamage = f + f1; ++ org.bukkit.Bukkit.getPluginManager().callEvent(playerAttackEntityEvent); ++ if (playerAttackEntityEvent.isCancelled()) { ++ return; ++ } ++ flag2 = playerAttackEntityEvent.isCritical() && !world.paperConfig.disablePlayerCrits; ++ if (playerAttackEntityEvent.getDamage() == totalDamage) { ++ if (flag2) { ++ this.isCritical = true; // Purpur ++ f *= 1.5F; ++ } ++ f += f1; ++ } else { ++ if (playerAttackEntityEvent.getDamage() < 0) { ++ return; ++ } ++ float damage = playerAttackEntityEvent.getDamage() - f1; ++ if (damage < 0) { ++ return; ++ } ++ if (flag2) { ++ this.isCritical = true; // Purpur ++ damage *= 1.5F; ++ } ++ damage += f1; ++ f = damage; + } +- +- f += f1; ++ // Yatopia end + boolean flag3 = false; + double d0 = (double) (this.A - this.z); + diff --git a/patches/server/remap in progress/0034-Ensure-pools-create-daemon-threads.patch b/patches/server/remap in progress/0034-Ensure-pools-create-daemon-threads.patch new file mode 100644 index 00000000..7c4200d9 --- /dev/null +++ b/patches/server/remap in progress/0034-Ensure-pools-create-daemon-threads.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Mon, 5 Oct 2020 17:09:00 +0300 +Subject: [PATCH] Ensure pools create daemon threads + +If only 1 non-daemon thread is left to run when the server is shutting down, the server won't shut down. +This patche ensures that executors make daemon threads. + +diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java +index b7399d17dd64ca8b1f1fab405cb0ac914dc53b98..add92c6ba9556b0a2695b007e0d83d7334412c2d 100644 +--- a/src/main/java/net/minecraft/server/MCUtil.java ++++ b/src/main/java/net/minecraft/server/MCUtil.java +@@ -59,12 +59,12 @@ public final class MCUtil { + public static final ThreadPoolExecutor asyncExecutor = new ThreadPoolExecutor( + 0, 2, 60L, TimeUnit.SECONDS, + new LinkedBlockingQueue(), +- new ThreadFactoryBuilder().setNameFormat("Paper Async Task Handler Thread - %1$d").build() ++ new ThreadFactoryBuilder().setDaemon(true).setNameFormat("Paper Async Task Handler Thread - %1$d").build() // Yatopia - daemon + ); + public static final ThreadPoolExecutor cleanerExecutor = new ThreadPoolExecutor( + 1, 1, 0L, TimeUnit.SECONDS, + new LinkedBlockingQueue(), +- new ThreadFactoryBuilder().setNameFormat("Paper Object Cleaner").build() ++ new ThreadFactoryBuilder().setDaemon(true).setNameFormat("Paper Object Cleaner").build() // Yatopia - daemon + ); + + public static final long INVALID_CHUNK_KEY = getCoordinateKey(Integer.MAX_VALUE, Integer.MAX_VALUE); +diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java +index f378d654a7fdd61ca31ca50ba45eff6acd93c3f1..46216e53f9917217ef50cae22dd387837974ef43 100644 +--- a/src/main/java/net/minecraft/server/network/LoginListener.java ++++ b/src/main/java/net/minecraft/server/network/LoginListener.java +@@ -129,7 +129,11 @@ public class LoginListener implements PacketLoginInListener { + // Paper start - Cache authenticator threads + private static final AtomicInteger threadId = new AtomicInteger(0); + private static final java.util.concurrent.ExecutorService authenticatorPool = java.util.concurrent.Executors.newCachedThreadPool( +- r -> new Thread(r, "User Authenticator #" + threadId.incrementAndGet()) ++ r -> { // Yatopia start - make sure produced threads are daemon ones ++ Thread thread = new Thread(r, "User Authenticator #" + threadId.incrementAndGet()); ++ thread.setDaemon(true); ++ return thread; ++ } // Yatopia end + ); + // Paper end + // Spigot start diff --git a/patches/server/remap in progress/0035-Add-IntelliJ-IDEA-runnable.patch b/patches/server/remap in progress/0035-Add-IntelliJ-IDEA-runnable.patch new file mode 100644 index 00000000..a79e3df7 --- /dev/null +++ b/patches/server/remap in progress/0035-Add-IntelliJ-IDEA-runnable.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zoe +Date: Sun, 27 Sep 2020 17:07:16 -0500 +Subject: [PATCH] Add IntelliJ IDEA runnable + + +diff --git a/.gitignore b/.gitignore +index 67fb370cad6924895a6b27052dbd5c1767e3f0c9..a111955550db7b00a6923a4fd715f3c524c7c438 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -37,3 +37,5 @@ dependency-reduced-pom.xml + + /src/main/resources/achievement + /src/main/resources/lang ++ ++/testserver/** +diff --git a/.run/Yatopia.run.xml b/.run/Yatopia.run.xml +new file mode 100644 +index 0000000000000000000000000000000000000000..ebba87ca805d8e57ce7aeb57d7f0b11abda0cc1c +--- /dev/null ++++ b/.run/Yatopia.run.xml +@@ -0,0 +1,23 @@ ++ ++ ++ ++ +\ No newline at end of file diff --git a/patches/server/remap in progress/0036-Fix-IndexOutOfBoundsException-when-sending-too-many-.patch b/patches/server/remap in progress/0036-Fix-IndexOutOfBoundsException-when-sending-too-many-.patch new file mode 100644 index 00000000..b5fa2cd1 --- /dev/null +++ b/patches/server/remap in progress/0036-Fix-IndexOutOfBoundsException-when-sending-too-many-.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Tue, 29 Sep 2020 19:25:49 +0300 +Subject: [PATCH] Fix IndexOutOfBoundsException when sending too many changes + + +diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMultiBlockChange.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMultiBlockChange.java +index e4bf350cb650d6deb0cea5f85fee66c6c92bc659..6d8727b116a88fd3d491102c1e3634890cdac05c 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMultiBlockChange.java ++++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMultiBlockChange.java +@@ -27,12 +27,16 @@ public class PacketPlayOutMultiBlockChange implements Packet +Date: Wed, 30 Sep 2020 18:05:45 +0300 +Subject: [PATCH] Add nspt command + + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 2662202e60d80af9af33b3dc4af535cf3dd8b366..117a289bf02a4269c6bcceec30885c17f2201cbb 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -235,6 +235,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + DedicatedServer.LOGGER.error("Unable to load server configuration", e); + return false; + } ++ org.yatopiamc.yatopia.server.YatopiaConfig.registerCommands(); + // Yatopia end + de.minebench.origami.OrigamiConfig.init((java.io.File) options.valueOf("origami-settings")); + this.setPVP(dedicatedserverproperties.pvp); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index f4a5ed86dfbd9c11f070d05016fc6a3cc67d4ea1..290dd284bff957ea455ff3a4e7a9a7ebf9e00fcc 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -941,6 +941,7 @@ public final class CraftServer implements Server { + org.spigotmc.SpigotConfig.registerCommands(); // Spigot + com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper + net.pl3x.purpur.PurpurConfig.registerCommands(); // Purpur ++ org.yatopiamc.yatopia.server.YatopiaConfig.registerCommands(); // Yatopia + overrideAllCommandBlockCommands = commandsConfiguration.getStringList("command-block-overrides").contains("*"); + ignoreVanillaPermissions = commandsConfiguration.getBoolean("ignore-vanilla-permissions"); + +diff --git a/src/main/java/org/yatopiamc/yatopia/server/NSPTCommand.java b/src/main/java/org/yatopiamc/yatopia/server/NSPTCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e6eaa07c57e04bbfba9e4aa8e0e939f85169d0c8 +--- /dev/null ++++ b/src/main/java/org/yatopiamc/yatopia/server/NSPTCommand.java +@@ -0,0 +1,59 @@ ++package org.yatopiamc.yatopia.server; ++ ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.List; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.ChatColor; ++import org.bukkit.Location; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++ ++public class NSPTCommand extends Command { ++ ++ public NSPTCommand(String name) { ++ super(name); ++ this.description = "View server tick times in nanoseconds"; ++ this.usageMessage = "/nspt"; ++ this.setPermission("bukkit.command.nspt"); ++ } ++ ++ @Override ++ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { ++ return Collections.emptyList(); ++ } ++ ++ @Override ++ public boolean execute(CommandSender sender, String commandLabel, String[] args) { ++ if (!testPermission(sender)) return true; ++ ++ MinecraftServer server = MinecraftServer.getServer(); ++ ++ List times = new ArrayList<>(); ++ times.addAll(eval(server.tickTimes5s.getTimes())); ++ times.addAll(eval(server.tickTimes10s.getTimes())); ++ times.addAll(eval(server.tickTimes60s.getTimes())); ++ ++ sender.sendMessage("§6Server tick NS times §e(§7avg§e/§7min§e/§7max§e)§6 from last 5s§7,§6 10s§7,§6 1m§e:"); ++ sender.sendMessage(String.format("§6◴ %s§7/%s§7/%s§e, %s§7/%s§7/%s§e, %s§7/%s§7/%s", times.toArray())); ++ return true; ++ } ++ ++ private static List eval(long[] times) { ++ long min = Integer.MAX_VALUE; ++ long max = 0L; ++ long total = 0L; ++ for (long value : times) { ++ if (value > 0L && value < min) min = value; ++ if (value > max) max = value; ++ total += value; ++ } ++ double avgD = ((double) total / (double) times.length); ++ return Arrays.asList(getColor(avgD), getColor(min), getColor(max)); ++ } ++ ++ private static String getColor(double avg) { ++ return ChatColor.COLOR_CHAR + (avg >= 5E+7 ? "c" : avg >= (4E+7) ? "e" : "a") + avg; ++ } ++} +diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +index 50f232c956f68d3d9c3eaf645810e38d805f4531..98b78bd015218a39b7512c67e0db9ba0451e3d6d 100644 +--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java ++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +@@ -6,11 +6,14 @@ import java.io.IOException; + import java.lang.reflect.InvocationTargetException; + import java.lang.reflect.Method; + import java.lang.reflect.Modifier; ++import java.util.HashMap; + import java.util.List; ++import java.util.Map; + import java.util.concurrent.TimeUnit; + import java.util.logging.Level; + import java.util.regex.Pattern; + import org.bukkit.Bukkit; ++import org.bukkit.command.Command; + import org.bukkit.configuration.InvalidConfigurationException; + import org.bukkit.configuration.file.YamlConfiguration; + +@@ -24,6 +27,7 @@ public class YatopiaConfig { + public static YamlConfiguration config; + public static int version; // since we're remapping sidestreams' configs we need this public + public static boolean verbose; // since we're remapping sidestreams' configs we need this public ++ private static Map commands; + /*========================================================================*/ + + public static void init(File configFile) { +@@ -39,6 +43,8 @@ public class YatopiaConfig { + config.options().header(HEADER); + config.options().copyDefaults(true); + verbose = getBoolean("verbose", false); ++ commands = new HashMap<>(); ++ commands.put("nspt", new NSPTCommand("nspt")); + + version = getInt("config-version", 1); + set("config-version", 1); +@@ -46,6 +52,12 @@ public class YatopiaConfig { + readConfig(YatopiaConfig.class, null); + } + ++ public static void registerCommands() { ++ for (Map.Entry entry : commands.entrySet()) { ++ net.minecraft.server.MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Yatopia", entry.getValue()); ++ } ++ } ++ + private static void removeLeftovers() { + // this method is only to remove non-used values in the config + diff --git a/patches/server/remap in progress/0038-Configurable-flight-checks.patch b/patches/server/remap in progress/0038-Configurable-flight-checks.patch new file mode 100644 index 00000000..4aafbb8a --- /dev/null +++ b/patches/server/remap in progress/0038-Configurable-flight-checks.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: l_MrBoom_l +Date: Wed, 30 Sep 2020 18:20:12 +0300 +Subject: [PATCH] Configurable flight checks + + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 0c47ea59ec05efdf1f9e25bf837e6039c79f6692..3b4bebc25b550904cbf9f53f40f9bb9418defde0 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -328,7 +328,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + ++this.e; + this.processedMovePackets = this.receivedMovePackets; + if (this.B && !this.player.isSleeping()) { +- if (++this.C > 80) { ++ if (org.yatopiamc.yatopia.server.YatopiaConfig.checkFlying && ++this.C > 80) { // Yatopia + PlayerConnection.LOGGER.warn("{} was kicked for floating too long!", this.player.getDisplayName().getString()); + this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_PLAYER); // Paper - use configurable kick message & kick event cause + return; +@@ -347,7 +347,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + this.w = this.r.locY(); + this.x = this.r.locZ(); + if (this.D && this.player.getRootVehicle().getRidingPassenger() == this.player) { +- if (++this.E > 80) { ++ if (org.yatopiamc.yatopia.server.YatopiaConfig.checkVehicleFlying && ++this.E > 80) { // Yatopia + PlayerConnection.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getDisplayName().getString()); + this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_VEHICLE); // Paper - use configurable kick message & kick event cause + return; +diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +index 98b78bd015218a39b7512c67e0db9ba0451e3d6d..90760a81f2d66082d4603df430f931403e5989b4 100644 +--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java ++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +@@ -218,4 +218,11 @@ public class YatopiaConfig { + private static void fixFallDistance() { + fixFallDistance = getBoolean("settings.fixFallDistance", false); + } ++ ++ public static boolean checkFlying = true; ++ public static boolean checkVehicleFlying = true; ++ private static void flightChecks() { ++ checkFlying = getBoolean("settings.checks.flight", checkFlying); ++ checkVehicleFlying = getBoolean("settings.checks.vehicle-flight", checkVehicleFlying); ++ } + } diff --git a/patches/server/remap in progress/0039-Heavily-optimize-recipe-lookups-in-CraftingManager.patch b/patches/server/remap in progress/0039-Heavily-optimize-recipe-lookups-in-CraftingManager.patch new file mode 100644 index 00000000..25675adf --- /dev/null +++ b/patches/server/remap in progress/0039-Heavily-optimize-recipe-lookups-in-CraftingManager.patch @@ -0,0 +1,180 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mykyta Komarn +Date: Thu, 1 Oct 2020 06:57:43 -0700 +Subject: [PATCH] Heavily optimize recipe lookups in CraftingManager + +Recipe lookups are now cached in CraftingManager, which prevent unnecessary ArrayLists being created for every lookup. Additionally, an EMPTY_MAP variable was added to prevent bottlenecks during map creation, since that map is only ever iterated. + +These changes knock off an extra ~10ms of tick duration with a sample of ~7,700 running furnaces on a server. + +Co-authored-by: Ivan Pekov +Co-authored-by: ishland + +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 81ceeff37f7e03eead177cbd49f79a74be3aeeb2..3bda167c4436a4f926850b2f3c06d1a0dce7c171 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -640,6 +640,7 @@ public final class ItemStack { + return !this.e() ? this.doMaterialsMatch(itemstack) : !itemstack.isEmpty() && this.getItem() == itemstack.getItem(); + } + ++ public final String getTranslationKey() { return j(); } // Yatopia - OBFHELPER + public String j() { + return this.getItem().f(this); + } +diff --git a/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java b/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java +index 5ba58bf1a47c696235e6e7a4a6815104bc23de80..f1180c57a76883c007393bc187de680618f60de3 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java ++++ b/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java +@@ -35,6 +35,7 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; // CraftBukkit ++import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Yatopia + + public class CraftingManager extends ResourceDataJson { + +@@ -42,6 +43,10 @@ public class CraftingManager extends ResourceDataJson { + private static final Logger LOGGER = LogManager.getLogger(); + public Map, Object2ObjectLinkedOpenHashMap>> recipes = ImmutableMap.of(); // CraftBukkit + private boolean d; ++ // Yatopia start ++ private final List> ALL_RECIPES_CACHE = new ObjectArrayList<>(); ++ private final Map, List>> TYPES_CACHE = new Object2ObjectLinkedOpenHashMap<>(); ++ // Yatopia end + + public CraftingManager() { + super(CraftingManager.a, "recipes"); +@@ -49,6 +54,7 @@ public class CraftingManager extends ResourceDataJson { + + protected void a(Map map, IResourceManager iresourcemanager, GameProfilerFiller gameprofilerfiller) { + this.d = false; ++ clearRecipes(); // Yatopia + // CraftBukkit start - SPIGOT-5667 make sure all types are populated and mutable + Map, Object2ObjectLinkedOpenHashMap>> map1 = Maps.newHashMap(); + for (Recipes recipeType : IRegistry.RECIPE_TYPE) { +@@ -74,9 +80,17 @@ public class CraftingManager extends ResourceDataJson { + } + } + ++ // Yatopia start - nuke stream & cache all recipes for constant access in b() ++ /* + this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { + return entry1.getValue(); // CraftBukkit // Paper - decompile fix - *shrugs internally* + })); ++ */ ++ this.recipes = ImmutableMap.copyOf(map1); ++ for (Object2ObjectLinkedOpenHashMap> recipesMap : map1.values()) { ++ ALL_RECIPES_CACHE.addAll(recipesMap.values()); ++ } ++ // Yatopia end + CraftingManager.LOGGER.info("Loaded {} recipes", map1.size()); + } + +@@ -90,33 +104,65 @@ public class CraftingManager extends ResourceDataJson { + } else { + map.putAndMoveToFirst(irecipe.getKey(), irecipe); // CraftBukkit - SPIGOT-4638: last recipe gets priority + } ++ ALL_RECIPES_CACHE.add(irecipe); // Yatopia + } + // CraftBukkit end + + public > Optional craft(Recipes recipes, C c0, World world) { + // CraftBukkit start ++ // Yatopia start - replace stream ++ /* + Optional recipe = this.b(recipes).values().stream().flatMap((irecipe) -> { + return SystemUtils.a(recipes.a(irecipe, world, c0)); + }).findFirst(); ++ */ ++ // Yatopia start - replace stream ++ Collection> allTypes = this.b(recipes).values(); ++ Optional recipe = Optional.empty(); ++ ++ for (IRecipe possible : allTypes) { ++ Optional possibleRecipe = recipes.a(possible, world, c0); ++ if (possibleRecipe.isPresent()) { ++ recipe = possibleRecipe; ++ break; ++ } ++ } ++ // Yatopia end + c0.setCurrentRecipe(recipe.orElse(null)); // CraftBukkit - Clear recipe when no recipe is found + // CraftBukkit end + return recipe; + } + + public > List a(Recipes recipes) { ++ // Yatopia start - replaced logic ++ /* + return (List) this.b(recipes).values().stream().map((irecipe) -> { + return irecipe; + }).collect(Collectors.toList()); ++ */ ++ return (List) TYPES_CACHE.computeIfAbsent(recipes, recipes1 -> new me.jellysquid.mods.lithium.common.util.collections.HashedList<>(new ObjectArrayList<>(getRecipesMap(recipes).values()))); ++ // Yatopia end + } + + public > List b(Recipes recipes, C c0, World world) { ++ // Yatopia start - replace stream ++ /* + return (List) this.b(recipes).values().stream().flatMap((irecipe) -> { + return SystemUtils.a(recipes.a(irecipe, world, c0)); + }).sorted(Comparator.comparing((irecipe) -> { + return irecipe.getResult().j(); + })).collect(Collectors.toList()); ++ */ ++ List ret = new ObjectArrayList<>(); ++ for (IRecipe recipe : this.b(recipes).values()) { ++ recipes.a(recipe, world, c0).ifPresent(ret::add); ++ } ++ ret.sort(Comparator.comparing(recipe -> recipe.getResult().getTranslationKey())); ++ return ret; ++ // Yatopia end + } + ++ private > Map> getRecipesMap(Recipes recipes) { return b(recipes); } // Yatopia - OBFHELPER + private > Map> b(Recipes recipes) { + return (Map) this.recipes.getOrDefault(recipes, new Object2ObjectLinkedOpenHashMap<>()); // CraftBukkit + } +@@ -138,15 +184,26 @@ public class CraftingManager extends ResourceDataJson { + } + + public Optional> getRecipe(MinecraftKey minecraftkey) { ++ // Yatopia start - replace stream ++ /* + return this.recipes.values().stream().map((map) -> { + return map.get(minecraftkey); // CraftBukkit - decompile error + }).filter(Objects::nonNull).findFirst(); ++ */ ++ for (Map> map : recipes.values()) { ++ IRecipe recipe = map.get(minecraftkey); ++ if (recipe != null) { ++ return Optional.of(recipe); ++ } ++ } ++ return Optional.empty(); ++ // Yatopia end + } + + public Collection> b() { +- return (Collection) this.recipes.values().stream().flatMap((map) -> { +- return map.values().stream(); +- }).collect(Collectors.toSet()); ++ // Yatopia start - O(1) constant complexity ++ return ALL_RECIPES_CACHE; ++ // Yatopia end + } + + public Stream d() { +@@ -166,6 +223,10 @@ public class CraftingManager extends ResourceDataJson { + // CraftBukkit start + public void clearRecipes() { + this.recipes = Maps.newHashMap(); ++ // Yatopia start - also clear cache ++ ALL_RECIPES_CACHE.clear(); ++ TYPES_CACHE.clear(); ++ // Yatopia end + + for (Recipes recipeType : IRegistry.RECIPE_TYPE) { + this.recipes.put(recipeType, new Object2ObjectLinkedOpenHashMap<>()); diff --git a/patches/server/remap in progress/0040-Optimize-advancement-loading.patch b/patches/server/remap in progress/0040-Optimize-advancement-loading.patch new file mode 100644 index 00000000..5bc35fc5 --- /dev/null +++ b/patches/server/remap in progress/0040-Optimize-advancement-loading.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Tue, 6 Oct 2020 15:10:12 +0300 +Subject: [PATCH] Optimize advancement loading + +Removed some object allocations and reduced loops + +diff --git a/src/main/java/net/minecraft/advancements/Advancement.java b/src/main/java/net/minecraft/advancements/Advancement.java +index 23567430901284ab9d4d4873e53a1c8a06da6862..33771338bbf7e409da7210dc096c63b74a2d215f 100644 +--- a/src/main/java/net/minecraft/advancements/Advancement.java ++++ b/src/main/java/net/minecraft/advancements/Advancement.java +@@ -82,6 +82,7 @@ public class Advancement { + return this.display; + } + ++ public final AdvancementRewards getRewards() { return d(); } // Yatopia - OBFHELPER + public AdvancementRewards d() { + return this.rewards; + } +diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java +index 4720644ae82f76f835f14c0b3a00e7b7874fb1e2..9d1879e2fd502c939b9f5caeab8a47ed9ced90d8 100644 +--- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java ++++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java +@@ -180,11 +180,16 @@ public class AdvancementDataPlayer { + throw new JsonParseException("Found null for advancements"); + } + ++ /* // Yatopia start - streams no good + Stream> stream = map.entrySet().stream().sorted(Comparator.comparing(Entry::getValue)); + Iterator iterator = ((List) stream.collect(Collectors.toList())).iterator(); + + while (iterator.hasNext()) { + Entry entry = (Entry) iterator.next(); ++ */ ++ Entry[] entries = map.entrySet().toArray(new Entry[0]); ++ java.util.Arrays.sort(entries, Entry.comparingByValue()); ++ for (Entry entry : entries) { // Yatopia end + Advancement advancement = advancementdataworld.a((MinecraftKey) entry.getKey()); + + if (advancement == null) { +@@ -222,11 +227,37 @@ public class AdvancementDataPlayer { + } + } + ++ /* // Yatopia start + this.c(advancementdataworld); + this.c(); + this.b(advancementdataworld); ++ */ ++ loadAdvancements(advancementdataworld); ++ // Yatopia end + } + ++ // Yatopia start - reduce overload by post io load of advancements ++ // this combines c(AdvancementDataWorld), c() and b(AdvancementDataWorld) into 1 method ++ // the changes done: loops thru all the advancements only once, does not create an additional list ++ // and does not loop thru the additional list, does not create an additional set when checking for progress and ++ // does not additionally loop thru it ++ private void loadAdvancements(AdvancementDataWorld serverAdvancementManager) { ++ for (Advancement advancement : serverAdvancementManager.getAdvancements()) { ++ if (advancement.getCriteria().isEmpty()) { ++ grantCriteria(advancement, ""); ++ advancement.getRewards().a(player); // todo: too lazy to import AdvancementRewards for an obfhelper ++ } ++ AdvancementProgress progress = getProgress(advancement); ++ if (progress.isDone()) { ++ this.j.add(advancement); ++ updateVisibility(advancement); ++ continue; // Do not double check isDone ++ } ++ beginTrackingNoIsDone(advancement, progress); ++ } ++ } ++ // Yatopia end ++ + public void b() { + if (org.spigotmc.SpigotConfig.disableAdvancementSaving) return; // Spigot + Map map = Maps.newHashMap(); +@@ -365,6 +396,11 @@ public class AdvancementDataPlayer { + AdvancementProgress advancementprogress = this.getProgress(advancement); + + if (!advancementprogress.isDone()) { ++ // Yatopia start - beginTrackig with no isDone check ++ beginTrackingNoIsDone(advancement, advancementprogress); ++ } ++ } ++ private void beginTrackingNoIsDone(Advancement advancement, AdvancementProgress advancementprogress) { + Iterator iterator = advancement.getCriteria().entrySet().iterator(); + + while (iterator.hasNext()) { +@@ -384,7 +420,7 @@ public class AdvancementDataPlayer { + } + } + +- } ++ //} // Yatopia end + } + + private void d(Advancement advancement) { +@@ -479,6 +515,7 @@ public class AdvancementDataPlayer { + this.data.put(advancement, advancementprogress); + } + ++ private final void updateVisibility(Advancement advancement) { e(advancement); } // Yatopia + private void e(Advancement advancement) { + // Paper start + e(advancement, IterationEntryPoint.ROOT); diff --git a/patches/server/remap in progress/0041-lithium-PerlinNoiseSamplerMixin.patch b/patches/server/remap in progress/0041-lithium-PerlinNoiseSamplerMixin.patch new file mode 100644 index 00000000..e2e49766 --- /dev/null +++ b/patches/server/remap in progress/0041-lithium-PerlinNoiseSamplerMixin.patch @@ -0,0 +1,181 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Sat, 26 Sep 2020 11:37:25 -0500 +Subject: [PATCH] lithium PerlinNoiseSamplerMixin + +This is a more optimized version of Lithium's PerlinNoiseSamplerMixin. +Original code by JellySquid, licensed under LGPLv3 +you can find the original code on https://github.com/CaffeineMC/lithium-fabric/ (Yarn mappings) + +Co-authored-by: Bud Gidiere + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/synth/NoiseGeneratorPerlin.java b/src/main/java/net/minecraft/world/level/levelgen/synth/NoiseGeneratorPerlin.java +index 6f5745c8bc17ce3e45ad07fc6ba02ff7aac5a9f1..e27269813f7c617b59abc01a0b890c6b4aaadd62 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/synth/NoiseGeneratorPerlin.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/synth/NoiseGeneratorPerlin.java +@@ -1,5 +1,6 @@ + package net.minecraft.world.level.levelgen.synth; + ++import org.apache.commons.math3.util.FastMath; // Yatopia + import java.util.Random; + import net.minecraft.util.MathHelper; + +@@ -9,6 +10,12 @@ public final class NoiseGeneratorPerlin { + public final double a; + public final double b; + public final double c; ++ // Yatopia start - Faster Perlin ++ private static final int GRADIENT_STRIDE = 4; ++ private static final int GRADIENT_STRIDE_SH = 2; ++ ++ private final byte[] gradientTable = new byte[256 * GRADIENT_STRIDE]; ++ // Yatopia end + + public NoiseGeneratorPerlin(Random random) { + this.a = random.nextDouble() * 256.0D; +@@ -30,8 +37,19 @@ public final class NoiseGeneratorPerlin { + this.d[i + j] = b0; + } + ++ // Yatopia start ++ for (i = 0; i < 256; i++) { ++ int hash = this.d[i & 255] & 15; ++ ++ for (int j = 0; j < 3; j++) { ++ this.gradientTable[(i * GRADIENT_STRIDE) + j] = (byte) NoiseGenerator3Handler.a[hash][j]; ++ } ++ } ++ // Yatopia end + } + ++ // Yatopia start - replaced logic ++ /* + public double a(double d0, double d1, double d2, double d3, double d4) { + double d5 = d0 + this.a; + double d6 = d1 + this.b; +@@ -56,6 +74,125 @@ public final class NoiseGeneratorPerlin { + } + + return this.a(i, j, k, d8, d9 - d14, d10, d11, d12, d13); ++ */ ++ public final double sample(double x, double y, double z, double d, double e) { return a(x, y, z, d, e); } // Yatopia - OBFHELPER ++ public final double a(double x, double y, double z, double d, double e) { ++ final double ox = x + this.a; ++ final double oy = y + this.b; ++ final double oz = z + this.c; ++ ++ final double fox = FastMath.floor(ox); ++ final double foy = FastMath.floor(oy); ++ final double foz = FastMath.floor(oz); ++ ++ final double oox = ox - fox; ++ double ooy = oy - foy; ++ final double ooz = oz - foz; ++ ++ final double fx = oox * oox * oox * (oox * (oox * 6.0 - 15.0) + 10.0); ++ final double fy = ooy * ooy * ooy * (ooy * (ooy * 6.0 - 15.0) + 10.0); ++ final double fz = ooz * ooz * ooz * (ooz * (ooz * 6.0 - 15.0) + 10.0); ++ ++ if (d != 0.0D) { ooy = ooy - (FastMath.floor(FastMath.min(e, ooy) / d) * d); } ++ ++ final int sectionX = (int) fox; ++ final int sectionY = (int) foy; ++ final int sectionZ = (int) foz; ++ ++ final byte[] perm = this.d; ++ ++ final int i = (perm[sectionX & 255] & 255) + sectionY; ++ final int l = (perm[(sectionX + 1) & 255] & 255) + sectionY; ++ ++ final int j = (perm[255 & i] & 255) + sectionZ; ++ final int m = (perm[l & 255] & 255) + sectionZ; ++ ++ final int k = (perm[(i + 1) & 255] & 255) + sectionZ; ++ final int n = (perm[(l + 1) & 255] & 255) + sectionZ; ++ ++ final double localX2 = oox - 1.0D; ++ final double localY2 = ooy - 1.0D; ++ final double localZ2 = ooz - 1.0D; ++ ++ final int d00 = (j & 255) << GRADIENT_STRIDE_SH; ++ final int d01 = (m & 255) << GRADIENT_STRIDE_SH; ++ final int d02 = (k & 255) << GRADIENT_STRIDE_SH; ++ final int d03 = (n & 255) << GRADIENT_STRIDE_SH; ++ ++ final int d10 = ((j + 1) & 255) << GRADIENT_STRIDE_SH; ++ final int d11 = ((m + 1) & 255) << GRADIENT_STRIDE_SH; ++ final int d12 = ((k + 1) & 255) << GRADIENT_STRIDE_SH; ++ final int d13 = ((n + 1) & 255) << GRADIENT_STRIDE_SH; ++ ++ final byte[] grad = this.gradientTable; ++ ++ final double g00x = grad[d00] * oox; ++ final double g00y = grad[d00 + 1] * ooy; ++ final double g00z = grad[d00 + 2] * ooz; ++ ++ final double g01x = grad[d01] * localX2; ++ final double g01y = grad[d01 + 1] * ooy; ++ final double g01z = grad[d01 + 2] * ooz; ++ ++ final double g02x = grad[d02] * oox; ++ final double g02y = grad[d02 + 1] * localY2; ++ final double g02z = grad[d02 + 2] * ooz; ++ ++ final double g03x = grad[d03] * localX2; ++ final double g03y = grad[d03 + 1] * localY2; ++ final double g03z = grad[d03 + 2] * ooz; ++ ++ final double g10x = grad[d10] * oox; ++ final double g10y = grad[d10 + 1] * ooy; ++ final double g10z = grad[d10 + 2] * localZ2; ++ ++ final double g11x = grad[d11] * localX2; ++ final double g11y = grad[d11 + 1] * ooy; ++ final double g11z = grad[d11 + 2] * localZ2; ++ ++ final double g12x = grad[d12] * oox; ++ final double g12y = grad[d12 + 1] * localY2; ++ final double g12z = grad[d12 + 2] * localZ2; ++ ++ final double g13x = grad[d13] * localX2; ++ final double g13y = grad[d13 + 1] * localY2; ++ final double g13z = grad[d13 + 2] * localZ2; ++ ++ final double g00 = g00x + g00y + g00z; ++ final double g01 = g01x + g01y + g01z; ++ final double g02 = g02x + g02y + g02z; ++ final double g03 = g03x + g03y + g03z; ++ final double g10 = g10x + g10y + g10z; ++ final double g11 = g11x + g11y + g11z; ++ final double g12 = g12x + g12y + g12z; ++ final double g13 = g13x + g13y + g13z; ++ ++ final double ba1 = g01 - g00; ++ final double ba2 = g11 - g10; ++ final double dc1 = g03 - g02; ++ final double dc2 = g13 - g12; ++ ++ final double dba1 = fx * ba1; ++ final double dba2 = fx * ba2; ++ final double ddc1 = fx * dc1; ++ final double ddc2 = fx * dc2; ++ ++ final double dd0 = g00 + dba1; ++ final double dd1 = g10 + dba2; ++ final double dd2 = g02 + ddc1; ++ final double dd3 = g12 + ddc2; ++ ++ final double aa0 = dd2 - dd0; ++ final double aa1 = dd3 - dd1; ++ ++ final double y20 = fy * aa0; ++ final double y31 = fy * aa1; ++ ++ final double aa2 = dd0 + y20; ++ final double aa3 = dd1 + y31; ++ ++ return dd0 + y20 + (fz * (aa3 - aa2)); ++ // Yatopia end + } + + private static double a(int i, double d0, double d1, double d2) { diff --git a/patches/server/remap in progress/0042-lithium-VoronoiBiomeAccessTypeMixin.patch b/patches/server/remap in progress/0042-lithium-VoronoiBiomeAccessTypeMixin.patch new file mode 100644 index 00000000..82dbc426 --- /dev/null +++ b/patches/server/remap in progress/0042-lithium-VoronoiBiomeAccessTypeMixin.patch @@ -0,0 +1,112 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Sat, 26 Sep 2020 15:45:09 -0500 +Subject: [PATCH] lithium VoronoiBiomeAccessTypeMixin + +Original code by JellySquid, licensed under LGPLv3 +you can find the original code on https://github.com/CaffeineMC/lithium-fabric/ (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/level/biome/GenLayerZoomVoronoi.java b/src/main/java/net/minecraft/world/level/biome/GenLayerZoomVoronoi.java +index 821adbf2c7c32ab659d23974b3871e2d11762ee6..715d6a21d1a1a84dd92b375cce13834f0eff3dbb 100644 +--- a/src/main/java/net/minecraft/world/level/biome/GenLayerZoomVoronoi.java ++++ b/src/main/java/net/minecraft/world/level/biome/GenLayerZoomVoronoi.java +@@ -10,6 +10,8 @@ public enum GenLayerZoomVoronoi implements GenLayerZoomer { + + @Override + public BiomeBase a(long i, int j, int k, int l, BiomeManager.Provider biomemanager_provider) { ++ // Yatopia start - replaced logic ++ /* + int i1 = j - 2; + int j1 = k - 2; + int k1 = l - 2; +@@ -56,6 +58,75 @@ public enum GenLayerZoomVoronoi implements GenLayerZoomer { + l2 = (k2 & 2) == 0 ? i2 : i2 + 1; + i3 = (k2 & 1) == 0 ? j2 : j2 + 1; + return biomemanager_provider.getBiome(k3, l2, i3); ++ */ ++ int x1 = j - 2; ++ int y1 = k - 2; ++ int z1 = l - 2; ++ ++ int x2 = x1 >> 2; ++ int y2 = y1 >> 2; ++ int z2 = z1 >> 2; ++ ++ double x3 = (double) (x1 & 3) / 4.0D; ++ double y3 = (double) (y1 & 3) / 4.0D; ++ double z3 = (double) (z1 & 3) / 4.0D; ++ ++ int retX = Integer.MIN_VALUE; ++ int retY = Integer.MIN_VALUE; ++ int retZ = Integer.MIN_VALUE; ++ ++ // This code would normally allocate an array to store each iteration's results, then scan back over it ++ // to determine the closest one. We can avoid the unnecessary step and simply keep track of the nearest one. ++ double minDist = Double.POSITIVE_INFINITY; ++ ++ for (int i1 = 0; i1 < 8; i1++) { ++ // Block sample positions ++ int bX; ++ int bY; ++ int bZ; ++ ++ // Sample positions ++ double sX; ++ double sY; ++ double sZ; ++ ++ if ((i1 & 0b100) == 0) { ++ bX = x2; ++ sX = x3; ++ } else { ++ bX = x2 + 1; ++ sX = x3 - 1.0D; ++ } ++ ++ if ((i1 & 0b010) == 0) { ++ bY = y2; ++ sY = y3; ++ } else { ++ bY = y2 + 1; ++ sY = y3 - 1.0D; ++ } ++ ++ if ((i1 & 0b001) == 0) { ++ bZ = z2; ++ sZ = z3; ++ } else { ++ bZ = z2 + 1; ++ sZ = z3 - 1.0D; ++ } ++ ++ double dist = a(i, bX, bY, bZ, sX, sY, sZ); ++ ++ if (minDist > dist) { ++ minDist = dist; ++ ++ retX = bX; ++ retY = bY; ++ retZ = bZ; ++ } ++ } ++ ++ return biomemanager_provider.getBiome(retX, retY, retZ); ++ // Yatopia end + } + + private static double a(long i, int j, int k, int l, double d0, double d1, double d2) { +@@ -78,9 +149,14 @@ public enum GenLayerZoomVoronoi implements GenLayerZoomer { + } + + private static double a(long i) { ++ // Yatopia start - replaced logic ++ /* + double d0 = (double) ((int) Math.floorMod(i >> 24, 1024L)) / 1024.0D; + + return (d0 - 0.5D) * 0.9D; ++ */ ++ return (((i >> 24) & 1023L) - 512) * 0.00087890625; // * 0.9 / 1024.0d ++ // Yatopia end + } + + private static double a(double d0) { diff --git a/patches/server/remap in progress/0043-lithium-NoiseChunkGeneratorMixin.patch b/patches/server/remap in progress/0043-lithium-NoiseChunkGeneratorMixin.patch new file mode 100644 index 00000000..15256915 --- /dev/null +++ b/patches/server/remap in progress/0043-lithium-NoiseChunkGeneratorMixin.patch @@ -0,0 +1,169 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Fri, 23 Oct 2020 16:45:51 -0500 +Subject: [PATCH] lithium NoiseChunkGeneratorMixin + +Additional Optimizations By YatopiaMC, +Original code by SuperCoder79, licensed under LGPLv3 +you can find the original code on https://github.com/CaffeineMC/lithium-fabric/ (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java +index 369fb0bda22f02e76b901b6eb8990651c53c7577..916e893cf771a2ea825d60104115282295529119 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java +@@ -5,6 +5,8 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; + import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import it.unimi.dsi.fastutil.objects.ObjectList; + import it.unimi.dsi.fastutil.objects.ObjectListIterator; ++import org.apache.commons.math3.util.FastMath; // Yatopia Fast Math ++ + import java.util.Iterator; + import java.util.List; + import java.util.Random; +@@ -146,7 +148,15 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { + return this.w == i && ((GeneratorSettingBase) this.h.get()).a(resourcekey); + } + ++ // Yatopia start ++ private static double sampleOctave(NoiseGeneratorPerlin sampler, double x, double y, double z, double scaledVerticalSize, double scaledY, double frequency) { ++ return sampler.sample(x, y, z, scaledVerticalSize, scaledY) / frequency; ++ } ++ // Yatopia end ++ + private double a(int i, int j, int k, double d0, double d1, double d2, double d3) { ++ // Yatopia start - replaced logic ++ /* + double d4 = 0.0D; + double d5 = 0.0D; + double d6 = 0.0D; +@@ -182,7 +192,85 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { + } + + return MathHelper.b(d4 / 512.0D, d5 / 512.0D, (d6 / 10.0D + 1.0D) / 2.0D); ++ */ ++ double frequency = 1.0; ++ double interpolationValue = 0.0; ++ ++ // Calculate interpolation data to decide what noise to sample. ++ for (int octave = 0; octave < 8; octave++) { ++ double scaledVerticalScale = d3 * frequency; ++ double scaledY = j * scaledVerticalScale; ++ ++ interpolationValue += sampleOctave(this.s.a(octave), ++ NoiseGeneratorOctaves.a(i * d2 * frequency), ++ NoiseGeneratorOctaves.a(scaledY), ++ NoiseGeneratorOctaves.a(k * d2 * frequency), scaledVerticalScale, scaledY, frequency); ++ ++ frequency /= 2.0; ++ } ++ ++ double clampedInterpolation = (interpolationValue / 10.0 + 1.0) / 2.0; ++ ++ if (clampedInterpolation >= 1) { ++ // Sample only upper noise, as the lower noise will be interpolated out. ++ frequency = 1.0; ++ double noise = 0.0; ++ for (int octave = 0; octave < 16; octave++) { ++ double scaledVerticalScale = d1 * frequency; ++ double scaledY = j * scaledVerticalScale; ++ ++ noise += sampleOctave(this.r.a(octave), ++ NoiseGeneratorOctaves.a(i * d0 * frequency), ++ NoiseGeneratorOctaves.a(scaledY), ++ NoiseGeneratorOctaves.a(k * d0 * frequency), scaledVerticalScale, scaledY, frequency); ++ ++ frequency /= 2.0; ++ } ++ ++ return noise / 512.0; ++ } else if (clampedInterpolation <= 0) { ++ // Sample only lower noise, as the upper noise will be interpolated out. ++ frequency = 1.0; ++ double noise = 0.0; ++ for (int octave = 0; octave < 16; octave++) { ++ double scaledVerticalScale = d1 * frequency; ++ double scaledY = j * scaledVerticalScale; ++ noise += sampleOctave(this.q.a(octave), ++ NoiseGeneratorOctaves.a(i * d0 * frequency), ++ NoiseGeneratorOctaves.a(scaledY), ++ NoiseGeneratorOctaves.a(k * d0 * frequency), scaledVerticalScale, scaledY, frequency); ++ ++ frequency /= 2.0; ++ } ++ ++ return noise / 512.0; ++ } else { ++ // [VanillaCopy] SurfaceChunkGenerator#sampleNoise ++ // Sample both and interpolate, as in vanilla. ++ ++ frequency = 1.0; ++ double lowerNoise = 0.0; ++ double upperNoise = 0.0; ++ ++ for (int octave = 0; octave < 16; octave++) { ++ // Pre calculate these values to share them ++ double scaledVerticalScale = d1 * frequency; ++ double scaledY = j * scaledVerticalScale; ++ double xVal = NoiseGeneratorOctaves.a(i * d0 * frequency); ++ double yVal = NoiseGeneratorOctaves.a(scaledY); ++ double zVal = NoiseGeneratorOctaves.a(k * d0 * frequency); ++ ++ upperNoise += sampleOctave(this.r.a(octave), xVal, yVal, zVal, scaledVerticalScale, scaledY, frequency); ++ lowerNoise += sampleOctave(this.q.a(octave), xVal, yVal, zVal, scaledVerticalScale, scaledY, frequency); ++ ++ frequency /= 2.0; ++ } ++ ++ // Vanilla behavior, return interpolated noise ++ return MathHelper.d(clampedInterpolation, lowerNoise / 512.0, upperNoise / 512.0); ++ } + } ++ // Yatopia end + + private double[] b(int i, int j) { + double[] adouble = new double[this.o + 1]; +@@ -308,7 +396,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { + + double d2 = d1 * 24.575625D - 2.0D; + +- return d2 < 0.0D ? d2 * 0.009486607142857142D : Math.min(d2, 1.0D) * 0.006640625D; ++ return d2 < 0.0D ? d2 * 0.009486607142857142D : FastMath.min(d2, 1.0D) * 0.006640625D; // Yatopia Fast Math + } + + @Override +@@ -325,10 +413,10 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { + } + + private int a(int i, int j, @Nullable IBlockData[] aiblockdata, @Nullable Predicate predicate) { +- int k = Math.floorDiv(i, this.m); +- int l = Math.floorDiv(j, this.m); +- int i1 = Math.floorMod(i, this.m); +- int j1 = Math.floorMod(j, this.m); ++ int k = FastMath.floorDiv(i, this.m); // Yatopia Fast Math ++ int l = FastMath.floorDiv(j, this.m); // Yatopia Fast Math ++ int i1 = FastMath.floorMod(i, this.m); // Yatopia Fast Math ++ int j1 = FastMath.floorMod(j, this.m); // Yatopia Fast Math + double d0 = (double) i1 / (double) this.m; + double d1 = (double) j1 / (double) this.m; + double[][] adouble = new double[][]{this.b(k, l), this.b(k, l + 1), this.b(k + 1, l), this.b(k + 1, l + 1)}; +@@ -567,9 +655,9 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { + StructurePiece structurepiece = (StructurePiece) objectlistiterator.next(); + StructureBoundingBox structureboundingbox = structurepiece.g(); + +- k4 = Math.max(0, Math.max(structureboundingbox.a - j3, j3 - structureboundingbox.d)); ++ k4 = FastMath.max(0, FastMath.max(structureboundingbox.a - j3, j3 - structureboundingbox.d)); // Yatopia Fast Math + l4 = j2 - (structureboundingbox.b + (structurepiece instanceof WorldGenFeaturePillagerOutpostPoolPiece ? ((WorldGenFeaturePillagerOutpostPoolPiece) structurepiece).d() : 0)); +- i5 = Math.max(0, Math.max(structureboundingbox.c - i4, i4 - structureboundingbox.f)); ++ i5 = FastMath.max(0, FastMath.max(structureboundingbox.c - i4, i4 - structureboundingbox.f)); // Yatopia Fast Math + } + + objectlistiterator.back(objectlist.size()); +@@ -624,7 +712,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { + double d0 = (double) (i * i + k * k); + double d1 = (double) j + 0.5D; + double d2 = d1 * d1; +- double d3 = Math.pow(2.718281828459045D, -(d2 / 16.0D + d0 / 16.0D)); ++ double d3 = FastMath.pow(2.718281828459045D, -(d2 / 16.0D + d0 / 16.0D)); // Yatopia Fast Math + double d4 = -d1 * MathHelper.i(d2 / 2.0D + d0 / 2.0D) / 2.0D; + + return d4 * d3; diff --git a/patches/server/remap in progress/0044-lithium-reduce-allocations.patch b/patches/server/remap in progress/0044-lithium-reduce-allocations.patch new file mode 100644 index 00000000..15a6d131 --- /dev/null +++ b/patches/server/remap in progress/0044-lithium-reduce-allocations.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Sat, 24 Oct 2020 19:36:50 -0500 +Subject: [PATCH] lithium reduce allocations + +This patch reduces object allocations in several places. + +Parts of this patch were created for the Lithium project by JellySquid and 2No2Name under the GNU LGPLv3 license. +Portions of this patch that were sourced from Lithium were remapped from Yarn mappings by Mykyta Komarnytskyy . + +Co-authored-by: Mykyta Komarnytskyy + +diff --git a/src/main/java/net/minecraft/world/level/block/BlockComposter.java b/src/main/java/net/minecraft/world/level/block/BlockComposter.java +index c0b235d5edf3cd14021696d1b4f76ce3de41f5d5..0b58efe27878f1a07579f2e02d3939edefb47933 100644 +--- a/src/main/java/net/minecraft/world/level/block/BlockComposter.java ++++ b/src/main/java/net/minecraft/world/level/block/BlockComposter.java +@@ -356,7 +356,7 @@ public class BlockComposter extends Block implements IInventoryHolder { + + @Override + public int[] getSlotsForFace(EnumDirection enumdirection) { +- return enumdirection == EnumDirection.UP ? new int[]{0} : new int[0]; ++ return enumdirection == EnumDirection.UP ? org.yatopiamc.yatopia.server.util.Constants.ZERO_ARRAY : org.yatopiamc.yatopia.server.util.Constants.EMPTY_ARRAY; // Yatopia - avoid array allocation + } + + @Override +@@ -406,7 +406,7 @@ public class BlockComposter extends Block implements IInventoryHolder { + + @Override + public int[] getSlotsForFace(EnumDirection enumdirection) { +- return enumdirection == EnumDirection.DOWN ? new int[]{0} : new int[0]; ++ return enumdirection == EnumDirection.DOWN ? org.yatopiamc.yatopia.server.util.Constants.ZERO_ARRAY : org.yatopiamc.yatopia.server.util.Constants.EMPTY_ARRAY; // Yatopia - avoid array allocation + } + + @Override +@@ -442,7 +442,7 @@ public class BlockComposter extends Block implements IInventoryHolder { + + @Override + public int[] getSlotsForFace(EnumDirection enumdirection) { +- return new int[0]; ++ return org.yatopiamc.yatopia.server.util.Constants.EMPTY_ARRAY; // Yatopia - avoid array allocation + } + + @Override diff --git a/patches/server/remap in progress/0045-Smarter-statistics-ticking.patch b/patches/server/remap in progress/0045-Smarter-statistics-ticking.patch new file mode 100644 index 00000000..934aaf81 --- /dev/null +++ b/patches/server/remap in progress/0045-Smarter-statistics-ticking.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mykyta Komarnytskyy +Date: Sat, 24 Oct 2020 21:03:53 -0500 +Subject: [PATCH] Smarter statistics ticking + +In vanilla, statistics that count time spent for an action (i.e. time played or sneak time) are incremented every tick. This is retarded. With this patch and a configured interval of 20, the statistics are only ticked every 20th tick and are incremented by 20 ticks at a time. This means a lot less ticking with the same accurate counting. + +With an interval of 20, this patch saves roughly 3ms per tick on a server w/ 80 players online. + +diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +index 6c16db02cc405fb8a7d9ac2fa70882a6e6edbfec..b484f02c994869787bdf65dbc5ef1f1af3889b69 100644 +--- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java ++++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java +@@ -279,18 +279,23 @@ public abstract class EntityHuman extends EntityLiving { + this.p(); + if (!this.world.isClientSide) { + this.foodData.a(this); +- this.a(StatisticList.PLAY_ONE_MINUTE); ++ // Yatopia start ++ int interval = org.yatopiamc.yatopia.server.YatopiaConfig.playerTimeStatisticsInterval; ++ if (ticksLived % interval == 0) { ++ this.a(StatisticList.PLAY_ONE_MINUTE, interval); ++ // Yatopia end + if (this.isAlive()) { +- this.a(StatisticList.TIME_SINCE_DEATH); ++ this.a(StatisticList.TIME_SINCE_DEATH, interval); // Yatopia + } + + if (this.bx()) { +- this.a(StatisticList.SNEAK_TIME); ++ this.a(StatisticList.SNEAK_TIME, interval); // Yatopia + } + + if (!this.isSleeping()) { +- this.a(StatisticList.TIME_SINCE_REST); ++ this.a(StatisticList.TIME_SINCE_REST, interval); // Yatopia + } ++ } // Yatopia + } + + int i = 29999999; +diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +index 90760a81f2d66082d4603df430f931403e5989b4..db1f0c57adbe2aacba9422820cf1a8757ea9ad4f 100644 +--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java ++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +@@ -225,4 +225,9 @@ public class YatopiaConfig { + checkFlying = getBoolean("settings.checks.flight", checkFlying); + checkVehicleFlying = getBoolean("settings.checks.vehicle-flight", checkVehicleFlying); + } ++ ++ public static int playerTimeStatisticsInterval = 1; ++ private static void intervals() { ++ playerTimeStatisticsInterval = Math.max(1, getInt("settings.intervals.player-time-statistics", 1)); ++ } + } diff --git a/patches/server/remap in progress/0046-Configurable-criterion-triggers.patch b/patches/server/remap in progress/0046-Configurable-criterion-triggers.patch new file mode 100644 index 00000000..f87fc104 --- /dev/null +++ b/patches/server/remap in progress/0046-Configurable-criterion-triggers.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mykyta Komarnytskyy +Date: Sat, 24 Oct 2020 21:08:17 -0500 +Subject: [PATCH] Configurable criterion triggers + +This patch adds toggles for three criterion triggers that are called every tick. These can be very unnecessary, and especially in the case of CriterionTriggerEnterBlock, quite heavy. + +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 753fc239b9968d76541c536184b2039526d80005..85f0b1e789858d840d0d709fc1974d6b7419f7ef 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -577,6 +577,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + + @Override + protected void a(IBlockData iblockdata) { ++ if (org.yatopiamc.yatopia.server.YatopiaConfig.criterionTriggerEnterBlock) // Yatopia + CriterionTriggers.d.a(this, iblockdata); + } + +@@ -907,7 +908,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + this.playerConnection.sendPacket(new PacketPlayOutExperience(this.exp, this.expTotal, this.expLevel)); + } + +- if (this.ticksLived % 20 == 0) { ++ if (org.yatopiamc.yatopia.server.YatopiaConfig.criterionTriggerLocation && this.ticksLived % 20 == 0) { // Yatopia + CriterionTriggers.p.a(this); + } + +diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +index db1f0c57adbe2aacba9422820cf1a8757ea9ad4f..8e87389f2323576e292bcca1730c2c49bf0eadba 100644 +--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java ++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +@@ -230,4 +230,14 @@ public class YatopiaConfig { + private static void intervals() { + playerTimeStatisticsInterval = Math.max(1, getInt("settings.intervals.player-time-statistics", 1)); + } ++ ++ public static boolean criterionTriggerLocation = true; ++ public static boolean criterionTriggerEnterBlock = true; ++ public static boolean criterionTriggerTick = true; ++ private static void criterionTriggers() { ++ criterionTriggerLocation = getBoolean("settings.criterion-triggers.location", true); ++ criterionTriggerEnterBlock = getBoolean("settings.criterion-triggers.enter-block", true); ++ criterionTriggerTick = getBoolean("settings.criterion-triggers.tick", true); ++ } ++ + } diff --git a/patches/server/remap in progress/0047-Configurable-BlockPhysicsEvent.patch b/patches/server/remap in progress/0047-Configurable-BlockPhysicsEvent.patch new file mode 100644 index 00000000..2fd2e11d --- /dev/null +++ b/patches/server/remap in progress/0047-Configurable-BlockPhysicsEvent.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mykyta Komarnytskyy +Date: Sat, 24 Oct 2020 21:12:45 -0500 +Subject: [PATCH] Configurable BlockPhysicsEvent + +Bukkit's BlockPhysicsEvent is *ridiculously* spammy and can easily rack in 1,600 calls/sec on a server with just one player. This hogs a ton of CPU time. +Paper does alleviate this quite well by only firing if plugins are listening, but a lot of common world protection plugins use this event do not offer toggles for their listeners, which makes Paper's change ineffective for most servers. +This patch implements a hard toggle for the event. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index c50e6c9199e6577a1a1a2b09f53b939e08589501..2572b5ab8c13f20a4f7efc168fdd8c7adafbcfcd 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1550,7 +1550,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper ++ worldserver.hasPhysicsEvent = org.yatopiamc.yatopia.server.YatopiaConfig.fireBlockPhysicsEvent && org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper // Yatopia + worldserver.hasEntityMoveEvent = EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper + worldserver.hasRidableMoveEvent = net.pl3x.purpur.event.entity.RidableMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Purpur + TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper +diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +index 8e87389f2323576e292bcca1730c2c49bf0eadba..aea5f614fca3fcbd132d562052178fb23340754b 100644 +--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java ++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +@@ -240,4 +240,8 @@ public class YatopiaConfig { + criterionTriggerTick = getBoolean("settings.criterion-triggers.tick", true); + } + ++ public static boolean fireBlockPhysicsEvent = true; ++ private static void fireBlockPhysicsEvent() { ++ fireBlockPhysicsEvent = getBoolean("settings.fire-block-physics-event", true); ++ } + } diff --git a/patches/server/remap in progress/0048-Custom-Locale-Support.patch b/patches/server/remap in progress/0048-Custom-Locale-Support.patch new file mode 100644 index 00000000..ab09fa77 --- /dev/null +++ b/patches/server/remap in progress/0048-Custom-Locale-Support.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zoe +Date: Sun, 25 Oct 2020 11:45:38 -0500 +Subject: [PATCH] Custom Locale Support + +All Server Jars Come with a pre-baked, usually English, locale file. This patch allows you to change the locale file by creating a locale.json file in the root directory of your server. Note that while custom locale files are supported by the server no support will be given for non-official Mojang locale files. + +diff --git a/src/main/java/net/minecraft/locale/LocaleLanguage.java b/src/main/java/net/minecraft/locale/LocaleLanguage.java +index 5218214225b50ac4059ab704086a457318e93e00..9b25594c612ec335bebb7178dd6e56861556ae6c 100644 +--- a/src/main/java/net/minecraft/locale/LocaleLanguage.java ++++ b/src/main/java/net/minecraft/locale/LocaleLanguage.java +@@ -31,9 +31,19 @@ public abstract class LocaleLanguage { + private static LocaleLanguage c() { + Builder builder = ImmutableMap.builder(); + BiConsumer biconsumer = builder::put; // Paper - decompile fix ++ boolean usingCustomLocale = false; // Yatopia + + try { +- InputStream inputstream = LocaleLanguage.class.getResourceAsStream("/assets/minecraft/lang/en_us.json"); ++ // Yatopia Start - Custom Locale ++ InputStream inputstream; ++ java.io.File file = new java.io.File("./locale.json"); ++ if (file.isFile() && file.canRead()) { ++ usingCustomLocale = true; ++ inputstream = new java.io.FileInputStream(file); ++ } else { ++ inputstream = LocaleLanguage.class.getResourceAsStream("/assets/minecraft/lang/en_us.json"); ++ } ++ // Yatopia End + Throwable throwable = null; + + try { +@@ -56,7 +66,11 @@ public abstract class LocaleLanguage { + + } + } catch (JsonParseException | IOException ioexception) { ++ if (!usingCustomLocale) { // Yatopia + LocaleLanguage.LOGGER.error("Couldn't read strings from /assets/minecraft/lang/en_us.json", ioexception); ++ } else { // Yatopia start ++ LocaleLanguage.LOGGER.error("Couldn't read strings from custom locale file. Please check that your custom Locale File is formatted correctly", ioexception); ++ } // Yatopia end + } + + final Map map = builder.build(); diff --git a/patches/server/remap in progress/0049-Configurable-movement-checks.patch b/patches/server/remap in progress/0049-Configurable-movement-checks.patch new file mode 100644 index 00000000..7f30a53c --- /dev/null +++ b/patches/server/remap in progress/0049-Configurable-movement-checks.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: l_MrBoom_l +Date: Sun, 8 Nov 2020 19:07:14 +0200 +Subject: [PATCH] Configurable movement checks + + +diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java +index 3b4bebc25b550904cbf9f53f40f9bb9418defde0..74178c4f613980b4e481e225bc3a5d3aeb12d282 100644 +--- a/src/main/java/net/minecraft/server/network/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java +@@ -614,7 +614,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + } + // Paper end + +- if (d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isExemptPlayer()) { ++ if (org.yatopiamc.yatopia.server.YatopiaConfig.checkVehicleMovedQuickly && d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isExemptPlayer()) { // Yatopia - Configurable movement checks + // CraftBukkit end + PlayerConnection.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", entity.getDisplayName().getString(), this.player.getDisplayName().getString(), d6, d7, d8); + this.networkManager.sendPacket(new PacketPlayOutVehicleMove(entity)); +@@ -641,7 +641,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + d10 = d6 * d6 + d7 * d7 + d8 * d8; + boolean flag1 = false; + +- if (d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot ++ if (org.yatopiamc.yatopia.server.YatopiaConfig.checkVehicleMovedWrongly && d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot // Yatopia - Configurable movement checks + flag1 = true; // Tuinity - diff on change, this should be moved wrongly + PlayerConnection.LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", entity.getDisplayName().getString(), this.player.getDisplayName().getString(), Math.sqrt(d10)); + } +@@ -1397,7 +1397,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + if (!this.player.H() && (!this.player.getWorldServer().getGameRules().getBoolean(GameRules.DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isGliding())) { + float f2 = this.player.isGliding() ? 300.0F : 100.0F; + +- if (d11 - d10 > Math.max(f2, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isExemptPlayer()) { ++ if (org.yatopiamc.yatopia.server.YatopiaConfig.checkMovedQuickly && d11 - d10 > Math.max(f2, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isExemptPlayer()) { // Yatopia - Configurable movement checks + // CraftBukkit end + PlayerConnection.LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getDisplayName().getString(), d7, d8, d9); + this.a(this.player.locX(), this.player.locY(), this.player.locZ(), this.player.yaw, this.player.pitch); +@@ -1463,7 +1463,7 @@ public class PlayerConnection implements PacketListenerPlayIn { + d11 = d7 * d7 + d8 * d8 + d9 * d9; + boolean flag1 = false; + +- if (!this.player.H() && d11 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.playerInteractManager.isCreative() && this.player.playerInteractManager.getGameMode() != EnumGamemode.SPECTATOR) { // Spigot ++ if (org.yatopiamc.yatopia.server.YatopiaConfig.checkMovedWrongly && !this.player.H() && d11 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.playerInteractManager.isCreative() && this.player.playerInteractManager.getGameMode() != EnumGamemode.SPECTATOR) { // Spigot // Yatopia - Configurable movement checks + flag1 = true; // Tuinity - diff on change, this should be moved wrongly + PlayerConnection.LOGGER.warn("{} moved wrongly! ({})", this.player.getDisplayName().getString(), d11); // Purpur + } +diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +index aea5f614fca3fcbd132d562052178fb23340754b..688df989493888edb7eff917158fc65a24a9b20e 100644 +--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java ++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +@@ -244,4 +244,15 @@ public class YatopiaConfig { + private static void fireBlockPhysicsEvent() { + fireBlockPhysicsEvent = getBoolean("settings.fire-block-physics-event", true); + } ++ ++ public static boolean checkMovedQuickly = true; ++ public static boolean checkMovedWrongly = true; ++ public static boolean checkVehicleMovedQuickly = true; ++ public static boolean checkVehicleMovedWrongly = true; ++ private static void movementChecks() { ++ checkMovedQuickly = getBoolean("settings.checks.moved-quickly", checkMovedQuickly); ++ checkMovedWrongly = getBoolean("settings.checks.moved-wrongly", checkMovedWrongly); ++ checkVehicleMovedQuickly = getBoolean("settings.checks.vehicle-moved-quickly", checkVehicleMovedQuickly); ++ checkVehicleMovedWrongly = getBoolean("settings.checks.vehicle-moved-wrongly", checkVehicleMovedWrongly); ++ } + } diff --git a/patches/server/remap in progress/0050-Configurable-enchanting-table-tick.patch b/patches/server/remap in progress/0050-Configurable-enchanting-table-tick.patch new file mode 100644 index 00000000..f55dc9a1 --- /dev/null +++ b/patches/server/remap in progress/0050-Configurable-enchanting-table-tick.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Wed, 23 Dec 2020 08:42:18 +0200 +Subject: [PATCH] Configurable enchanting table tick + +Also don't tick blockentity beehive if there are no bees in it. +This patch is a leftover from the original tile entity optimisations, which was majorly flawed. + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java +index 6fbd8ee31c517cd08ce4d1374a278dd748f9933e..95479df9fb009c5ca1872f8ee89b13e9c66d0bb6 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java +@@ -309,6 +309,7 @@ public class TileEntityBeehive extends TileEntity implements ITickable { + + @Override + public void tick() { ++ if (this.bees.size() == 0) { return; } // Yatopia - TE optimizations + if (!this.world.isClientSide) { + this.y(); + BlockPosition blockposition = this.getPosition(); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnchantTable.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnchantTable.java +index 7d81c45f8b514df1a9dafd3b1294a9ad852251f8..4b1cb089355b455c6210f2df1af797cc363997cf 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnchantTable.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnchantTable.java +@@ -50,6 +50,7 @@ public class TileEntityEnchantTable extends TileEntity implements INamableTileEn + + @Override + public void tick() { ++ if (!org.yatopiamc.yatopia.server.YatopiaConfig.shouldTickEnchantingTables) { return; } // Yatopia - TE optimizations + this.j = this.i; + this.l = this.k; + EntityHuman entityhuman = this.world.a((double) this.position.getX() + 0.5D, (double) this.position.getY() + 0.5D, (double) this.position.getZ() + 0.5D, 3.0D, false); +diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +index 688df989493888edb7eff917158fc65a24a9b20e..1eb56babfea75054dffd4c6b9cb00ddd93ebdf96 100644 +--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java ++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +@@ -255,4 +255,9 @@ public class YatopiaConfig { + checkVehicleMovedQuickly = getBoolean("settings.checks.vehicle-moved-quickly", checkVehicleMovedQuickly); + checkVehicleMovedWrongly = getBoolean("settings.checks.vehicle-moved-wrongly", checkVehicleMovedWrongly); + } ++ ++ public static boolean shouldTickEnchantingTables = false; ++ private static void tickEnchantingTables() { ++ shouldTickEnchantingTables = getBoolean("settings.tick.enchanting-tables", shouldTickEnchantingTables); ++ } + } diff --git a/patches/server/remap in progress/0051-Optimised-hallowen-checker.patch b/patches/server/remap in progress/0051-Optimised-hallowen-checker.patch new file mode 100644 index 00000000..cbd05b34 --- /dev/null +++ b/patches/server/remap in progress/0051-Optimised-hallowen-checker.patch @@ -0,0 +1,144 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Mon, 4 Jan 2021 20:12:36 +0200 +Subject: [PATCH] Optimised hallowen checker + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 2572b5ab8c13f20a4f7efc168fdd8c7adafbcfcd..5392a9bc509008ecfcdad44189c903fd5b57285c 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1478,6 +1478,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant= 20 || j == 11 && i <= 3; ++ */ ++ return org.yatopiamc.yatopia.server.entity.HalloweenChecker.isHalloweenSeason(); ++ // Yatopia end + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java +index 1676fbb80e5573c2591c1de7a6a858cf4824b48f..9b4ec2ae5df12fc605770ad6243970a7753dd8dc 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java +@@ -163,11 +163,15 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR + this.eL(); + this.setCanPickupLoot(this.world.paperConfig.skeletonsAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * difficultydamagescaler.d()); // Paper + if (this.getEquipment(EnumItemSlot.HEAD).isEmpty()) { ++ /* // Yatopia start - optimised halloween checker + LocalDate localdate = LocalDate.now(); + int i = localdate.get(ChronoField.DAY_OF_MONTH); + int j = localdate.get(ChronoField.MONTH_OF_YEAR); + + if (j == 10 && i == 31 && this.random.nextFloat() < 0.25F) { ++ */ ++ if (org.yatopiamc.yatopia.server.entity.HalloweenChecker.isHalloweenDay() && this.random.nextFloat() < 0.25F) { ++ // Yatopia end + this.setSlot(EnumItemSlot.HEAD, new ItemStack(this.random.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); + this.dropChanceArmor[EnumItemSlot.HEAD.b()] = 0.0F; + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +index bce7b674ef4450c1f6e932cba1b06ae8730cedfe..446d967f87ce252f62e568c18af54c50d63cb586 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java +@@ -590,11 +590,15 @@ public class EntityZombie extends EntityMonster { + } + + if (this.getEquipment(EnumItemSlot.HEAD).isEmpty()) { ++ /* // Yatopia start - optimised halloween checker + LocalDate localdate = LocalDate.now(); + int i = localdate.get(ChronoField.DAY_OF_MONTH); + int j = localdate.get(ChronoField.MONTH_OF_YEAR); + + if (j == 10 && i == 31 && this.random.nextFloat() < 0.25F) { ++ */ ++ if (org.yatopiamc.yatopia.server.entity.HalloweenChecker.isHalloweenDay() && this.random.nextFloat() < 0.25F) { ++ // Yatopia end + this.setSlot(EnumItemSlot.HEAD, new ItemStack(this.random.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); + this.dropChanceArmor[EnumItemSlot.HEAD.b()] = 0.0F; + } +diff --git a/src/main/java/org/yatopiamc/yatopia/server/entity/HalloweenChecker.java b/src/main/java/org/yatopiamc/yatopia/server/entity/HalloweenChecker.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b9e8c25fa4c4cc088a12c2b865887751c8cdbcd8 +--- /dev/null ++++ b/src/main/java/org/yatopiamc/yatopia/server/entity/HalloweenChecker.java +@@ -0,0 +1,59 @@ ++package org.yatopiamc.yatopia.server.entity; ++ ++import java.time.LocalDate; ++import java.time.temporal.ChronoField; ++import net.minecraft.server.MinecraftServer; ++ ++/** ++ * Entity halloween checker ++ *

++ * Checks whether or not it is halloween at a specific rate rather than every time when ++ * a entity is being spawned. ++ *

++ * The rate changes depending on how much TPS the server has. By default, the rate is every ++ * 2 hours, or every 144k ticks (if the server has _that_ much uptime) ++ * ++ * @author MrIvanPlays ++ */ ++public class HalloweenChecker { ++ ++ private static boolean halloweenSeason = false; ++ private static boolean halloweenDay = false; ++ ++ private static int delay = (20 * 60 * 60) * 2; ++ private static int lastCheckTick = -delay; ++ ++ public static void tick() { ++ if (MinecraftServer.currentTick % 100 == 0) { ++ // update the delay every 100 ticks ++ if (MinecraftServer.TPS >= 20) { ++ delay = (20 * 60 * 60) * 2; ++ } ++ if (MinecraftServer.TPS < 15) { ++ delay = delay + (20 * 60 * 15); ++ } ++ if (MinecraftServer.TPS < 10) { ++ delay = delay + (20 * 60 * 30); ++ } ++ } ++ if (MinecraftServer.currentTick - lastCheckTick > delay) { ++ LocalDate now = LocalDate.now(); ++ int day = now.getDayOfMonth(); ++ int month = now.get(ChronoField.MONTH_OF_YEAR); ++ ++ halloweenDay = (month == 10) && (day == 31); ++ halloweenSeason = ((month == 10) && (day >= 20)) || ((month == 11) && (day <= 3)); ++ ++ lastCheckTick = MinecraftServer.currentTick; ++ } ++ } ++ ++ public static boolean isHalloweenSeason() { ++ return halloweenSeason; ++ } ++ ++ public static boolean isHalloweenDay() { ++ return halloweenDay; ++ } ++ ++} diff --git a/patches/server/remap in progress/0052-Smol-entity-optimisations.patch b/patches/server/remap in progress/0052-Smol-entity-optimisations.patch new file mode 100644 index 00000000..84753c89 --- /dev/null +++ b/patches/server/remap in progress/0052-Smol-entity-optimisations.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ivan Pekov +Date: Mon, 4 Jan 2021 20:32:06 +0200 +Subject: [PATCH] Smol entity optimisations + + +diff --git a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java +index b8ff1af80e87d0715d71d62256f78f1646d82e01..75879558a4e3a209aed7dc006c6ffbe35323fe91 100644 +--- a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java ++++ b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java +@@ -293,7 +293,7 @@ public class EntityBat extends EntityAmbient { + if (blockposition.getY() >= generatoraccess.getSeaLevel()) { + return false; + } else { +- int i = generatoraccess.getLightLevel(blockposition); ++ //int i = generatoraccess.getLightLevel(blockposition); // Yatopia - moved down + byte b0 = 4; + + if (eJ()) { +@@ -302,6 +302,7 @@ public class EntityBat extends EntityAmbient { + return false; + } + ++ int i = generatoraccess.getLightLevel(blockposition); // Yatopia - moved from above + return i > random.nextInt(b0) ? false : a(entitytypes, generatoraccess, enummobspawn, blockposition, random); + } + } diff --git a/patches/server/remap in progress/0053-add-config-for-logging-login-location.patch b/patches/server/remap in progress/0053-add-config-for-logging-login-location.patch new file mode 100644 index 00000000..6bcee872 --- /dev/null +++ b/patches/server/remap in progress/0053-add-config-for-logging-login-location.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Simon Gardling +Date: Wed, 20 Jan 2021 16:36:48 -0500 +Subject: [PATCH] add config for logging login location + + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index bc3adc076870cc7cfb61ac1fa9e4c939b714ef57..27fdce74d3ff886ceea4b74cb5465b20c74ebe93 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -480,7 +480,14 @@ public abstract class PlayerList { + } + // Paper end + // CraftBukkit - Moved from above, added world ++ ++ // Yatopia start - configurable logging of player login location ++ if (org.yatopiamc.yatopia.server.YatopiaConfig.logPlayerLoginLoc) { + PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", entityplayer.getDisplayName().getString(), s1, entityplayer.getId(), worldserver1.worldDataServer.getName(), entityplayer.locX(), entityplayer.locY(), entityplayer.locZ()); ++ } else { ++ PlayerList.LOGGER.info("{}[{}] logged in with entity id {}", entityplayer.getDisplayName().getString(), s1, entityplayer.getId()); ++ } ++ // Yatopia end - configurable logging of player login location + } + + public void sendScoreboard(ScoreboardServer scoreboardserver, EntityPlayer entityplayer) { +diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +index 1eb56babfea75054dffd4c6b9cb00ddd93ebdf96..b246e6450130964cf91d0be81fbddae6598d9d8c 100644 +--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java ++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java +@@ -260,4 +260,10 @@ public class YatopiaConfig { + private static void tickEnchantingTables() { + shouldTickEnchantingTables = getBoolean("settings.tick.enchanting-tables", shouldTickEnchantingTables); + } ++ ++ public static boolean logPlayerLoginLoc = true; ++ private static void general() { ++ logPlayerLoginLoc = getBoolean("settings.log-player-login-location", logPlayerLoginLoc); ++ } ++ + } diff --git a/patches/server/remap in progress/0054-Preload-ProtocolLib-EnumWrappers.patch b/patches/server/remap in progress/0054-Preload-ProtocolLib-EnumWrappers.patch new file mode 100644 index 00000000..cba59216 --- /dev/null +++ b/patches/server/remap in progress/0054-Preload-ProtocolLib-EnumWrappers.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ishland +Date: Wed, 27 Jan 2021 20:16:47 +0800 +Subject: [PATCH] Preload ProtocolLib EnumWrappers + +Currently, ProtocolLib load EnumWrappers lazily and causing memory effects issues. This patch preloads EnumWrappers to prevent further NPE. + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 5392a9bc509008ecfcdad44189c903fd5b57285c..cda0f9bf15fead921ced0e984dc9cf80ead88286 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1092,6 +1092,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant +Date: Fri, 22 Jan 2021 16:38:19 -0500 +Subject: [PATCH] lithium: cache chunk gen sea level + +Chunk generator settings are passed to the noise chunk generator through a supplier, which retrieves a given chunk generator settings registry key from the registry. The problem arises as this setting is retrieved from the supplier to get the sea level, which is called every single time a block is placed by the generator, for a total of 65536 registry lookups per chunk. As you can imagine this isn't all that fast and removing it speeds up the chunk generation time by a moderate amount (13% of CPU time spent in populateNoise without the patch vs 10% with the patch). My solution to this was to stick the supplier into a Lazy<> so it's computed once and then cached, but I'm open to suggestions. (The sea level can't be computed ahead of time due to a quirk in the new registry system, which would have been the best option here.) + +This code was originally made by SuperCoder7979 in a Pull Request to lithium (https://github.com/CaffeineMC/lithium-fabric/pull/179) + +This code was orignally licensed under the LGPL-3.0 license. + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java +index 916e893cf771a2ea825d60104115282295529119..f39b0b2b259cf9cecf460331b789bd8009090677 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java +@@ -52,6 +52,7 @@ import net.minecraft.world.level.levelgen.synth.NoiseGeneratorPerlin; + + public final class ChunkGeneratorAbstract extends ChunkGenerator { + ++ private int cachedSeaLevel; // Yatopia - lithium cache chunk gen settings + public static final Codec d = RecordCodecBuilder.create((instance) -> { + return instance.group(WorldChunkManager.a.fieldOf("biome_source").forGetter((chunkgeneratorabstract) -> { + return chunkgeneratorabstract.b; +@@ -136,6 +137,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { + } else { + this.v = null; + } ++ this.cachedSeaLevel = ((GeneratorSettingBase) this.h.get()).g(); // Yatopia - lithium cache chunk gen settings + + } + +@@ -723,10 +725,18 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { + return this.x; + } + ++ // Yatopia start - lithium cache chunk gen settings ++ /** ++ * Use cached sea level instead of retrieving from the registry every time. ++ * This method is called for every block in the chunk so this will save a lot of registry lookups. ++ * ++ * @author SuperCoder79 ++ */ + @Override +- public int getSeaLevel() { +- return ((GeneratorSettingBase) this.h.get()).g(); ++ public int getSeaLevel() { // Cached method of getting sealevel ++ return this.cachedSeaLevel; + } ++ // Yatopia end + + @Override + public List getMobsFor(BiomeBase biomebase, StructureManager structuremanager, EnumCreatureType enumcreaturetype, BlockPosition blockposition) { diff --git a/patches/server/remap in progress/0056-New-nbt-cache.patch b/patches/server/remap in progress/0056-New-nbt-cache.patch new file mode 100644 index 00000000..9904bdb3 --- /dev/null +++ b/patches/server/remap in progress/0056-New-nbt-cache.patch @@ -0,0 +1,137 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Hugo Planque +Date: Thu, 21 Jan 2021 17:56:03 +0100 +Subject: [PATCH] New nbt cache + +The goal of this patch is to reduce I/O operations from the main thread while saving player data and also to avoid too many I/O operations while reading NBT Player file by using a cache (Which start to delete the oldest data when there is too much player compared to the map size) + +Co-authored-by: ishland + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index cda0f9bf15fead921ced0e984dc9cf80ead88286..ed4a8f34c0f48adb9d90e53ac5c9ca584e400a47 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -955,7 +955,9 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { try { NBTCompressedStreamTools.a(nbttagcompound, file); + File file1 = new File(this.playerDir, entityhuman.getUniqueIDString() + ".dat"); + File file2 = new File(this.playerDir, entityhuman.getUniqueIDString() + ".dat_old"); + + SystemUtils.a(file1, file, file2); ++ } catch (Exception exception) { ++ WorldNBTStorage.LOGGER.error("Failed to save player data for {}", entityhuman.getName(), exception); // Paper ++ } ++ }; ++ synchronized (this.dataCache){ ++ this.dataCache.put(file, nbttagcompound); ++ } ++ this.executorService.execute(task); ++ // Yatopia end + } catch (Exception exception) { + WorldNBTStorage.LOGGER.error("Failed to save player data for {}", entityhuman.getName(), exception); // Paper + } +@@ -57,9 +73,18 @@ public class WorldNBTStorage { + // Spigot Start + boolean usingWrongFile = false; + boolean normalFile = file.exists() && file.isFile(); // Akarin - ensures normal file +- if ( org.bukkit.Bukkit.getOnlineMode() && !normalFile ) // Paper - Check online mode first // Akarin - ensures normal file ++ // if ( org.bukkit.Bukkit.getOnlineMode() && !normalFile ) // Paper - Check online mode first // Akarin - ensures normal file // Yatopia ++ // Yatopia start - NBT Cache system ++ NBTTagCompound playerData; ++ synchronized (this.dataCache){ ++ playerData = this.dataCache.get(file); ++ } ++ if (playerData == null && org.bukkit.Bukkit.getOnlineMode() && !normalFile ) // Paper - Check online mode first // Akarin - ensures normal file + { + file = new File( this.playerDir, java.util.UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + entityhuman.getName() ).getBytes( "UTF-8" ) ).toString() + ".dat"); ++ synchronized (this.dataCache){ ++ playerData = this.dataCache.get(file); ++ } + if ( file.exists() ) + { + usingWrongFile = true; +@@ -67,10 +92,13 @@ public class WorldNBTStorage { + } + } + // Spigot End +- +- if (normalFile) { // Akarin - avoid double I/O operation ++ // if (normalFile) { // Akarin - avoid double I/O operation // Yatopia ++ if (playerData != null) { ++ nbttagcompound = playerData; ++ } else if (normalFile) { // Akarin - avoid double I/O operation + nbttagcompound = NBTCompressedStreamTools.a(file); + } ++ // Yatopia end + // Spigot Start + if ( usingWrongFile ) + { +diff --git a/src/main/java/org/yatopiamc/yatopia/server/cache/NBTCache.java b/src/main/java/org/yatopiamc/yatopia/server/cache/NBTCache.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d739a71c91b54d156f6e1d8487add372a06d5939 +--- /dev/null ++++ b/src/main/java/org/yatopiamc/yatopia/server/cache/NBTCache.java +@@ -0,0 +1,32 @@ ++package org.yatopiamc.yatopia.server.cache; ++ ++import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenCustomHashMap; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.nbt.NBTTagCompound; ++ ++import java.io.File; ++ ++public class NBTCache extends Object2ObjectLinkedOpenCustomHashMap { ++ ++ public NBTCache() { ++ super(100, 0.75F, new Strategy() { ++ @Override ++ public int hashCode(File k) { ++ return k.hashCode(); ++ } ++ ++ @Override ++ public boolean equals(File k, File k1) { ++ return k.equals(k1); ++ } ++ }); ++ } ++ ++ @Override ++ public NBTTagCompound put(File k, NBTTagCompound v) { ++ if (this.size() > MinecraftServer.getServer().getPlayerCount()) { ++ this.removeLast(); ++ } ++ return super.putAndMoveToFirst(k, v); ++ } ++} diff --git a/patches/server/remap in progress/0057-Suspected-plugins-report.patch b/patches/server/remap in progress/0057-Suspected-plugins-report.patch new file mode 100644 index 00000000..b9b63cf6 --- /dev/null +++ b/patches/server/remap in progress/0057-Suspected-plugins-report.patch @@ -0,0 +1,207 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ishland +Date: Wed, 27 Jan 2021 23:35:30 +0800 +Subject: [PATCH] Suspected plugins report + +Added "Suspected Plugins" to Watchdog, crash reports and exception messages + +diff --git a/src/main/java/net/minecraft/CrashReport.java b/src/main/java/net/minecraft/CrashReport.java +index 9b7a51890c667601b195ff15b2bf0d6c76c7f19f..d7dd6208d1fc47dd95badecaaee0ed98292a5f7f 100644 +--- a/src/main/java/net/minecraft/CrashReport.java ++++ b/src/main/java/net/minecraft/CrashReport.java +@@ -87,6 +87,8 @@ public class CrashReport { + if (this.h != null && this.h.length > 0) { + stringbuilder.append("-- Head --\n"); + stringbuilder.append("Thread: ").append(Thread.currentThread().getName()).append("\n"); ++ org.yatopiamc.yatopia.api.internal.StackTraceUtils.print(this.h, stringbuilder::append); // Yatopia - detailed report ++ stringbuilder.append("\n"); // Yatopia + stringbuilder.append("Stacktrace:\n"); + StackTraceElement[] astacktraceelement = this.h; + int i = astacktraceelement.length; +diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java +index 1dce5d3b1e994a060067de4901912dd5a9be7e15..c5cc8cee3eaac3410512b678d11c7aaf743ffa35 100644 +--- a/src/main/java/net/minecraft/network/NetworkManager.java ++++ b/src/main/java/net/minecraft/network/NetworkManager.java +@@ -423,6 +423,11 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); + // Paper start + } catch (Exception e) { ++ // Yatopia - detailed report ++ LOGGER.error("Encountered unexpected exception sending packets"); ++ org.yatopiamc.yatopia.api.internal.StackTraceUtils.print(e, LOGGER::error); ++ LOGGER.error(org.yatopiamc.yatopia.api.internal.StackTraceUtils.EXCEPTION_DETAILS_BELOW); ++ // Yatopia end + LOGGER.error("NetworkException: " + player, e); + close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; + packet.onPacketDispatchFinish(player, null); +@@ -462,6 +467,11 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); + // Paper start + } catch (Exception e) { ++ // Yatopia start - detailed report ++ LOGGER.error("Encountered unexpected exception sending packets"); ++ org.yatopiamc.yatopia.api.internal.StackTraceUtils.print(e, LOGGER::error); ++ LOGGER.error(org.yatopiamc.yatopia.api.internal.StackTraceUtils.EXCEPTION_DETAILS_BELOW); ++ // Yatopia end + LOGGER.error("NetworkException: " + player, e); + close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; + packet.onPacketDispatchFinish(player, null); +@@ -497,6 +507,11 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); + // Paper start + } catch (Exception e) { ++ // Yatopia start - detailed report ++ LOGGER.error("Encountered unexpected exception sending packets"); ++ org.yatopiamc.yatopia.api.internal.StackTraceUtils.print(e, LOGGER::error); ++ LOGGER.error(org.yatopiamc.yatopia.api.internal.StackTraceUtils.EXCEPTION_DETAILS_BELOW); ++ // Yatopia end + LOGGER.error("NetworkException: " + player, e); + close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; + packet.onPacketDispatchFinish(player, null); +diff --git a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java +index 71a000edfab27c9965d1929af78582821d5af97a..5c5ac70b4dae5d51303ab974261055aaefb5aec2 100644 +--- a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java ++++ b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java +@@ -57,6 +57,11 @@ public class PlayerConnectionUtils { + // Paper start + catch (Exception e) { + NetworkManager networkmanager = t0.a(); ++ // Yatopia start - detailed report ++ LOGGER.error("Encountered unexpected exception sending packets"); ++ org.yatopiamc.yatopia.api.internal.StackTraceUtils.print(e, LOGGER::error); ++ LOGGER.error(org.yatopiamc.yatopia.api.internal.StackTraceUtils.EXCEPTION_DETAILS_BELOW); ++ // Yatopia end + if (networkmanager.getPlayer() != null) { + LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getName(), networkmanager.getSocketAddress(), e); + } else { +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index ed4a8f34c0f48adb9d90e53ac5c9ca584e400a47..b298b95f96c382dbed29e641740fb4265d6e5587 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1172,7 +1172,11 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant task.getOwner().getLogger().log(Level.SEVERE, _msg)); ++ task.getOwner().getLogger().log(Level.SEVERE, org.yatopiamc.yatopia.api.internal.StackTraceUtils.EXCEPTION_DETAILS_BELOW, throwable); ++ // Yatopia end + } + org.bukkit.Bukkit.getServer().getPluginManager().callEvent( + new ServerExceptionEvent(new ServerSchedulerException(msg, throwable, task))); +@@ -493,6 +497,7 @@ public class CraftScheduler implements BukkitScheduler { + // We don't need to parse pending + // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) + } ++ lastSyncTask = null; // Yatopia - detailed report + final long period = task.getPeriod(); // State consistency + if (period > 0) { + task.setNextRun(currentTick + period); +@@ -646,4 +651,10 @@ public class CraftScheduler implements BukkitScheduler { + }; + } + // Paper end ++ // Yatopia start - detailed report ++ private volatile CraftTask lastSyncTask = null; ++ public CraftTask getLastSyncTask() { ++ return lastSyncTask; ++ } ++ // Yatopia end + } +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index b15db666281227d1dc486e4e57dae1831fbf78ec..eded1fce68bb021c0b61d3355e6b52d2527679fd 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -134,6 +134,15 @@ public class WatchdogThread extends Thread + log.log(Level.SEVERE, "Handling packet for connection: " + packetListener); + } + } ++ // Yatopia start - detailed report - Scheduler ++ if (Bukkit.getScheduler() instanceof org.bukkit.craftbukkit.scheduler.CraftScheduler) { ++ final org.bukkit.craftbukkit.scheduler.CraftScheduler scheduler = (org.bukkit.craftbukkit.scheduler.CraftScheduler) Bukkit.getScheduler(); ++ final org.bukkit.craftbukkit.scheduler.CraftTask lastSyncTask = scheduler.getLastSyncTask(); ++ if (lastSyncTask != null) { ++ log.log(Level.SEVERE, "Running task " + lastSyncTask.getTaskId() + " for '" + lastSyncTask.getOwner().getDescription().getFullName() + "', TaskClass: " + lastSyncTask.getTaskClass()); ++ } ++ } else log.log(Level.SEVERE, "Unofficial scheduler, unable to get task information"); ++ // Yatopia end + } + // Tuinity end - log detailed tick information + +@@ -266,6 +275,10 @@ public class WatchdogThread extends Thread + log.log( Level.SEVERE, "\t\tLocked on:" + monitor.getLockedStackFrame() ); + } + } ++ // Yatopia start - dump plugins info ++ org.yatopiamc.yatopia.api.internal.StackTraceUtils.print(thread.getStackTrace(), msg -> log.log(Level.SEVERE, msg)); ++ log.log(Level.SEVERE, ""); ++ // Yatopia end + log.log( Level.SEVERE, "\tStack:" ); + // + for ( StackTraceElement stack : thread.getStackTrace() ) diff --git a/patches/server/remap in progress/0058-Port-Cadmium.patch b/patches/server/remap in progress/0058-Port-Cadmium.patch new file mode 100644 index 00000000..3ef5f8a1 --- /dev/null +++ b/patches/server/remap in progress/0058-Port-Cadmium.patch @@ -0,0 +1,1248 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lucy-t <64509677+Lucy-t@users.noreply.github.com> +Date: Thu, 7 Jan 2021 00:24:16 -0500 +Subject: [PATCH] Port Cadmium + +Code from LucilleTea's port of cadmium to 1.16: https://github.com/LucilleTea/DataFixerUpper + +diff --git a/src/main/java/com/mojang/datafixers/DataFixUtils.java b/src/main/java/com/mojang/datafixers/DataFixUtils.java +index cf8959aea3e48c1276ae9536d4de0f0127e1801e..b730a4c0b8b8c9036641d033568b3554062999cb 100644 +--- a/src/main/java/com/mojang/datafixers/DataFixUtils.java ++++ b/src/main/java/com/mojang/datafixers/DataFixUtils.java +@@ -54,6 +54,15 @@ public class DataFixUtils { + return other; + } + ++ // Yatopia start - Cadmium port ++ public static U orElse(final U nullable, final U other) { ++ if (nullable!=null) { ++ return nullable; ++ } ++ return other; ++ } ++ // Yatopia end ++ + public static U orElseGet(final Optional optional, final Supplier other) { + if (optional.isPresent()) { + return optional.get(); +diff --git a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java +index abc265b00044b14abb55c2628d454ee01fef467b..c8c19535fa64edc392fa18093ba47b16a168ebaf 100644 +--- a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java ++++ b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java +@@ -64,13 +64,17 @@ public class DataFixerBuilder { + public DataFixer build(final Executor executor) { + final DataFixerUpper fixerUpper = new DataFixerUpper(new Int2ObjectAVLTreeMap<>(schemas), new ArrayList<>(globalList), new IntAVLTreeSet(fixerVersions)); + ++ // Yatopia start - Cadmium port ++ long startTime = System.nanoTime(); ++ final List> futures = Lists.newArrayList(); ++ // Yatopia end + final IntBidirectionalIterator iterator = fixerUpper.fixerVersions().iterator(); + while (iterator.hasNext()) { + final int versionKey = iterator.nextInt(); + if (versionKey < minDataFixPrecacheVersion) continue; // Paper + final Schema schema = schemas.get(versionKey); + for (final String typeName : schema.types()) { +- CompletableFuture.runAsync(() -> { ++ futures.add(CompletableFuture.runAsync(() -> { // Yatopia - Cadmium port + final Type dataType = schema.getType(() -> typeName); + final TypeRewriteRule rule = fixerUpper.getRule(DataFixUtils.getVersion(versionKey), dataVersion); + dataType.rewrite(rule, DataFixerUpper.OPTIMIZATION_RULE); +@@ -78,9 +82,16 @@ public class DataFixerBuilder { + LOGGER.error("Unable to build datafixers", e); + Runtime.getRuntime().exit(1); + return null; +- }); ++ })); // Yatopia - Cadmium port + } + } ++ // Yatopia start - Cadmium port ++ CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) ++ .thenAccept((res) -> { ++ long endTime = System.nanoTime(); ++ LOGGER.info("Finished building data fixers after {}ms", (endTime - startTime) / 1_000_000); ++ }); ++ // Yatopia end + + return fixerUpper; + } +diff --git a/src/main/java/com/mojang/datafixers/FieldFinder.java b/src/main/java/com/mojang/datafixers/FieldFinder.java +index a20a9dedcff2f3d633c5fd09d238a98fe18968c0..7ae4fab4c448ec3444624b6e671364a89243f6dc 100644 +--- a/src/main/java/com/mojang/datafixers/FieldFinder.java ++++ b/src/main/java/com/mojang/datafixers/FieldFinder.java +@@ -118,7 +118,7 @@ public final class FieldFinder implements OpticFinder { + (Type>) choiceType, + type, + type, +- new Proj1<>() ++ Proj1.instance() // Yatopia - Cadmium port + ); + } + +diff --git a/src/main/java/com/mojang/datafixers/TypeRewriteRule.java b/src/main/java/com/mojang/datafixers/TypeRewriteRule.java +index 6f836c3382ed83e07000c0a5e4b6e9b69f8c45bf..37690009f2f3782e741f71272df525e9093794bc 100644 +--- a/src/main/java/com/mojang/datafixers/TypeRewriteRule.java ++++ b/src/main/java/com/mojang/datafixers/TypeRewriteRule.java +@@ -105,20 +105,24 @@ public interface TypeRewriteRule { + } + } + +- static TypeRewriteRule orElse(final TypeRewriteRule first, final TypeRewriteRule second) { ++ // Yatopia start - Cadmium port ++ static TypeRewriteRule orElse(final TypeRewriteRule first, final TypeRewriteRule second) { ++ /* + return orElse(first, () -> second); + } + + static TypeRewriteRule orElse(final TypeRewriteRule first, final Supplier second) { +- return new OrElse(first, second); +- } ++ */ ++ return new OrElse(first, second); ++ } ++ // Yatopia end + + final class OrElse implements TypeRewriteRule { + protected final TypeRewriteRule first; +- protected final Supplier second; ++ protected final TypeRewriteRule second; // Yatopia - Cadmium port + private final int hashCode; + +- public OrElse(final TypeRewriteRule first, final Supplier second) { ++ public OrElse(final TypeRewriteRule first, final TypeRewriteRule second) { // Yatopia - Cadmium port + this.first = first; + this.second = second; + hashCode = Objects.hash(first, second); +@@ -130,7 +134,7 @@ public interface TypeRewriteRule { + if (view.isPresent()) { + return view; + } +- return second.get().rewrite(type); ++ return second.rewrite(type); // Yatopia - Cadmium port + } + + @Override +@@ -159,9 +163,13 @@ public interface TypeRewriteRule { + return new One(rule); + } + ++ // Yatopia start - Cadmium port ++ /* + static TypeRewriteRule once(final TypeRewriteRule rule) { + return orElse(rule, () -> one(once(rule))); + } ++ */ ++ // Yatopia end + + static TypeRewriteRule checkOnce(final TypeRewriteRule rule, final Consumer> onFail) { + // TODO: toggle somehow +diff --git a/src/main/java/com/mojang/datafixers/Typed.java b/src/main/java/com/mojang/datafixers/Typed.java +index 55c55beba58fb0505ccf8270a27d6c6ffc01c629..4b84d12d51eedf99d0b5d2168f31c8a2f819b432 100644 +--- a/src/main/java/com/mojang/datafixers/Typed.java ++++ b/src/main/java/com/mojang/datafixers/Typed.java +@@ -184,11 +184,11 @@ public final class Typed { + } + + public Typed> inj1(final Type type) { +- return new Typed<>(DSL.or(this.type, type), ops, new Inj1().build(value)); ++ return new Typed<>(DSL.or(this.type, type), ops, Inj1.instance().build(value)); // Yatopia - Cadmium port + } + + public Typed> inj2(final Type type) { +- return new Typed<>(DSL.or(type, this.type), ops, new Inj2().build(value)); ++ return new Typed<>(DSL.or(type, this.type), ops, Inj2.instance().build(value)); // Yatopia - Cadmium port + } + + public static Typed> pair(final Typed first, final Typed second) { +diff --git a/src/main/java/com/mojang/datafixers/TypedOptic.java b/src/main/java/com/mojang/datafixers/TypedOptic.java +index 10c5565709510609f8b6c4c39bb25b163dd878bc..9e2b6e46ad846ebd964b969932da84c671ebc651 100644 +--- a/src/main/java/com/mojang/datafixers/TypedOptic.java ++++ b/src/main/java/com/mojang/datafixers/TypedOptic.java +@@ -131,7 +131,7 @@ public final class TypedOptic { + DSL.and(newType, gType), + fType, + newType, +- new Proj1<>() ++ Proj1.instance() // Yatopia - Cadmium port + ); + } + +@@ -142,7 +142,7 @@ public final class TypedOptic { + DSL.and(fType, newType), + gType, + newType, +- new Proj2<>() ++ Proj2.instance() // Yatopia - Cadmium port + ); + } + +@@ -153,7 +153,7 @@ public final class TypedOptic { + DSL.or(newType, gType), + fType, + newType, +- new Inj1<>() ++ Inj1.instance() // Yatopia - Cadmium port + ); + } + +@@ -164,7 +164,7 @@ public final class TypedOptic { + DSL.or(fType, newType), + gType, + newType, +- new Inj2<>() ++ Inj2.instance() // Yatopia - Cadmium port + ); + } + +diff --git a/src/main/java/com/mojang/datafixers/View.java b/src/main/java/com/mojang/datafixers/View.java +index 4139dc999917d84c7dea5b02117a50af51206f04..58f856d95405f02c107fad12e830e98d1e1a8337 100644 +--- a/src/main/java/com/mojang/datafixers/View.java ++++ b/src/main/java/com/mojang/datafixers/View.java +@@ -11,7 +11,6 @@ import com.mojang.datafixers.types.Type; + import com.mojang.serialization.DynamicOps; + + import java.util.Objects; +-import java.util.Optional; + import java.util.function.Function; + + public final class View implements App2 { +@@ -73,9 +72,15 @@ public final class View implements App2 { + return Objects.hash(type, newType, function); + } + +- public Optional> rewrite(final PointFreeRule rule) { +- return rule.rewrite(DSL.func(type, newType), function()).map(f -> create(type, newType, f)); ++ // Yatopia start - Cadmium port ++ public View rewrite(final PointFreeRule rule) { ++ PointFree> result = rule.rewrite(DSL.func(type, newType), function()); ++ if (result!=null) { ++ return create(type, newType, result); ++ } ++ return null; + } ++ // Yatopia end + + public View rewriteOrNop(final PointFreeRule rule) { + return DataFixUtils.orElse(rewrite(rule), this); +diff --git a/src/main/java/com/mojang/datafixers/functions/Apply.java b/src/main/java/com/mojang/datafixers/functions/Apply.java +index 32c55622c7a6de4d4eb4c70c62f4fbf11385667b..89793b452e95c9ae8bec42d22bebd762533a8046 100644 +--- a/src/main/java/com/mojang/datafixers/functions/Apply.java ++++ b/src/main/java/com/mojang/datafixers/functions/Apply.java +@@ -3,11 +3,11 @@ + package com.mojang.datafixers.functions; + + import com.mojang.datafixers.DSL; ++import com.mojang.datafixers.DataFixUtils; // Yatopia - Cadmium port + import com.mojang.datafixers.types.Type; + import com.mojang.serialization.DynamicOps; + + import java.util.Objects; +-import java.util.Optional; + import java.util.function.Function; + + final class Apply extends PointFree { +@@ -31,20 +31,33 @@ final class Apply extends PointFree { + return "(ap " + func.toString(level + 1) + "\n" + indent(level + 1) + arg.toString(level + 1) + "\n" + indent(level) + ")"; + } + ++ // Yatopia start - Cadmium port + @Override +- public Optional> all(final PointFreeRule rule, final Type type) { +- return Optional.of(Functions.app( +- rule.rewrite(DSL.func(argType, type), func).map(f1 -> (PointFree>) f1).orElse(func), +- rule.rewrite(argType, arg).map(f -> (PointFree) f).orElse(arg), +- argType +- )); ++ public PointFree all(final PointFreeRule rule, final Type type) { ++ return Functions.app( ++ DataFixUtils.orElse(rule.rewrite(DSL.func(argType, type), func), func), ++ DataFixUtils.orElse(rule.rewrite(argType, arg), arg), ++ argType ++ ); + } + + @Override +- public Optional> one(final PointFreeRule rule, final Type type) { +- return rule.rewrite(DSL.func(argType, type), func).map(f -> Optional.of(Functions.app(f, arg, argType))) +- .orElseGet(() -> rule.rewrite(argType, arg).map(a -> Functions.app(func, a, argType))); ++ public PointFree one(final PointFreeRule rule, final Type type) { ++ final PointFree> result1 = rule.rewrite(DSL.func(argType, type), func); ++ ++ if (result1!=null) { ++ return Functions.app(result1, arg, argType); ++ } ++ ++ final PointFree result2 = rule.rewrite(argType, arg); ++ ++ if (result2!=null) { ++ return Functions.app(func, result2, argType); ++ } ++ ++ return null; + } ++ // Yatopia end + + @Override + public boolean equals(final Object o) { +diff --git a/src/main/java/com/mojang/datafixers/functions/Comp.java b/src/main/java/com/mojang/datafixers/functions/Comp.java +index a7a0ba66c715709801c2839018a6bb19df5cfdc6..6ea5ecad576f880783b9503ec370a5171d4f4da4 100644 +--- a/src/main/java/com/mojang/datafixers/functions/Comp.java ++++ b/src/main/java/com/mojang/datafixers/functions/Comp.java +@@ -3,12 +3,12 @@ + package com.mojang.datafixers.functions; + + import com.mojang.datafixers.DSL; ++import com.mojang.datafixers.DataFixUtils; // Yatopia - Cadmium port + import com.mojang.datafixers.types.Func; + import com.mojang.datafixers.types.Type; + import com.mojang.serialization.DynamicOps; + + import java.util.Objects; +-import java.util.Optional; + import java.util.function.Function; + + final class Comp extends PointFree> { +@@ -28,21 +28,34 @@ final class Comp extends PointFree> { + } + + @Override +- public Optional>> all(final PointFreeRule rule, final Type> type) { ++ // Yatopia start - Cadmium port ++ public PointFree> all(final PointFreeRule rule, final Type> type) { + final Func funcType = (Func) type; +- return Optional.of(Functions.comp( +- middleType, +- rule.rewrite(DSL.func(middleType, funcType.second()), first).map(f -> (PointFree>) f).orElse(first), +- rule.rewrite(DSL.func(funcType.first(), middleType), second).map(f1 -> (PointFree>) f1).orElse(second) +- )); ++ return Functions.comp( ++ middleType, ++ DataFixUtils.orElse(rule.rewrite(DSL.func(middleType, funcType.second()), first), first), ++ DataFixUtils.orElse(rule.rewrite(DSL.func(funcType.first(), middleType), second), second) ++ ); + } + + @Override +- public Optional>> one(final PointFreeRule rule, final Type> type) { ++ public PointFree> one(final PointFreeRule rule, final Type> type) { + final Func funcType = (Func) type; +- return rule.rewrite(DSL.func(middleType, funcType.second()), first).map(f -> Optional.of(Functions.comp(middleType, f, second))) +- .orElseGet(() -> rule.rewrite(DSL.func(funcType.first(), middleType), second).map(s -> Functions.comp(middleType, first, s))); ++ final PointFree> result1 = rule.rewrite(DSL.func(middleType, funcType.second()), first); ++ ++ if (result1!=null) { ++ return Functions.comp(middleType, result1, second); ++ } ++ ++ final PointFree> result2 = rule.rewrite(DSL.func(funcType.first(), middleType), second); ++ ++ if (result2!=null) { ++ return Functions.comp(middleType, first, result2); ++ } ++ ++ return null; + } ++ // Yatopia end + + @Override + public boolean equals(final Object o) { +diff --git a/src/main/java/com/mojang/datafixers/functions/PointFree.java b/src/main/java/com/mojang/datafixers/functions/PointFree.java +index f7593e3baf71a8992aa094719d9a369399996d46..b743d6d7188c53ac04ec087d9f89b6f87374e811 100644 +--- a/src/main/java/com/mojang/datafixers/functions/PointFree.java ++++ b/src/main/java/com/mojang/datafixers/functions/PointFree.java +@@ -7,7 +7,6 @@ import com.mojang.serialization.DynamicOps; + import org.apache.commons.lang3.StringUtils; + + import javax.annotation.Nullable; +-import java.util.Optional; + import java.util.function.Function; + + public abstract class PointFree { +@@ -30,13 +29,15 @@ public abstract class PointFree { + + public abstract Function, T> eval(); + +- Optional> all(final PointFreeRule rule, final Type type) { +- return Optional.of(this); ++ // Yatopia start - Cadmium port ++ PointFree all(final PointFreeRule rule, final Type type) { ++ return this; + } + +- Optional> one(final PointFreeRule rule, final Type type) { +- return Optional.empty(); ++ PointFree one(final PointFreeRule rule, final Type type) { ++ return null; + } ++ // Yatopia end + + @Override + public final String toString() { +diff --git a/src/main/java/com/mojang/datafixers/functions/PointFreeRule.java b/src/main/java/com/mojang/datafixers/functions/PointFreeRule.java +index eaee52d2eb5c9051b1114ae307022d83984e5840..0e31fe8412cef25b209c72a628756d5b67cce79f 100644 +--- a/src/main/java/com/mojang/datafixers/functions/PointFreeRule.java ++++ b/src/main/java/com/mojang/datafixers/functions/PointFreeRule.java +@@ -25,16 +25,23 @@ import org.apache.commons.lang3.ObjectUtils; + import java.util.BitSet; + import java.util.List; + import java.util.Objects; +-import java.util.Optional; + import java.util.function.Function; + import java.util.function.Supplier; + + public interface PointFreeRule { +- Optional> rewrite(final Type type, final PointFree expr); ++ // Yatopia start - Cadmium port ++ PointFree rewrite(final Type type, final PointFree expr); + +- default Optional> rewrite(final View view) { +- return rewrite(view.getFuncType(), view.function()).map(pf -> View.create(view.type(), view.newType(), pf)); ++ default View rewrite(final View view) { ++ PointFree> result = rewrite(view.getFuncType(), view.function()); ++ ++ if (result!=null) { ++ return View.create(view.type(), view.newType(), result); ++ } ++ ++ return null; + } ++ // Yatopia end + + default PointFree rewriteOrNop(final Type type, final PointFree expr) { + return DataFixUtils.orElse(rewrite(type, expr), expr); +@@ -52,9 +59,11 @@ public interface PointFreeRule { + INSTANCE; + + @Override +- public Optional> rewrite(final Type type, final PointFree expr) { +- return Optional.of(expr); ++ // Yatopia start - Cadmium port ++ public PointFree rewrite(final Type type, final PointFree expr) { ++ return expr; + } ++ // Yatopia end + + @Override + public PointFreeRule get() { +@@ -67,25 +76,28 @@ public interface PointFreeRule { + + @SuppressWarnings("unchecked") + @Override +- public Optional> rewrite(final Type type, final PointFree expr) { ++ // Yatopia start - Cadmium port ++ public PointFree rewrite(final Type type, final PointFree expr) { + if (expr instanceof Bang) { +- return Optional.empty(); ++ return null; + } + if (type instanceof Func) { + final Func func = (Func) type; + if (func.second() instanceof EmptyPart) { +- return Optional.of((PointFree) Functions.bang()); ++ return (PointFree) Functions.bang(); + } + } +- return Optional.empty(); ++ return null; + } ++ // Yatopia end + } + + enum CompAssocLeft implements PointFreeRule { + INSTANCE; + + @Override +- public Optional> rewrite(final Type type, final PointFree expr) { ++ // Yatopia start - Cadmium port ++ public PointFree rewrite(final Type type, final PointFree expr) { + if (expr instanceof Comp) { + final Comp comp2 = (Comp) expr; + final PointFree> second = comp2.second; +@@ -94,13 +106,14 @@ public interface PointFreeRule { + return swap(comp1, comp2); + } + } +- return Optional.empty(); ++ return null; + } ++ // Yatopia end + + @SuppressWarnings("unchecked") +- private static Optional> swap(final Comp comp1, final Comp comp2raw) { ++ private static PointFree swap(final Comp comp1, final Comp comp2raw) { // Yatopia - Cadmium port + final Comp comp2 = (Comp) comp2raw; +- return Optional.of((PointFree) new Comp<>(comp1.middleType, new Comp<>(comp2.middleType, comp2.first, comp1.first), comp1.second)); ++ return (PointFree) new Comp<>(comp1.middleType, new Comp<>(comp2.middleType, comp2.first, comp1.first), comp1.second); // Yatopia - Cadmium port + } + } + +@@ -108,7 +121,7 @@ public interface PointFreeRule { + INSTANCE; + + @Override +- public Optional> rewrite(final Type type, final PointFree expr) { ++ public PointFree rewrite(final Type type, final PointFree expr) { // Yatopia - Cadmium port + if (expr instanceof Comp) { + final Comp comp1 = (Comp) expr; + final PointFree> first = comp1.first; +@@ -117,13 +130,13 @@ public interface PointFreeRule { + return swap(comp1, comp2); + } + } +- return Optional.empty(); ++ return null; // Yatopia - Cadmium port + } + + @SuppressWarnings("unchecked") +- private static Optional> swap(final Comp comp1, final Comp comp2raw) { ++ private static PointFree swap(final Comp comp1, final Comp comp2raw) { // Yatopia - Cadmium port + final Comp comp2 = (Comp) comp2raw; +- return Optional.of((PointFree) new Comp<>(comp2.middleType, comp2.first, new Comp<>(comp1.middleType, comp2.second, comp1.second))); ++ return (PointFree) new Comp<>(comp2.middleType, comp2.first, new Comp<>(comp1.middleType, comp2.second, comp1.second)); // Yatopia - Cadmium port + } + } + +@@ -133,15 +146,15 @@ public interface PointFreeRule { + // (ap lens id) -> id + @SuppressWarnings("unchecked") + @Override +- public Optional> rewrite(final Type type, final PointFree expr) { ++ public PointFree rewrite(final Type type, final PointFree expr) { // Yatopia - Cadmium port + if (expr instanceof Apply) { + final Apply apply = (Apply) expr; + final PointFree> func = apply.func; + if (func instanceof ProfunctorTransformer && Objects.equals(apply.arg, Functions.id())) { +- return Optional.of((PointFree) Functions.id()); ++ return (PointFree) Functions.id(); // Yatopia - Cadmium port + } + } +- return Optional.empty(); ++ return null; + } + } + +@@ -150,7 +163,7 @@ public interface PointFreeRule { + + // (ap f1 (ap f2 arg)) -> (ap (f1 ◦ f2) arg) + @Override +- public Optional> rewrite(final Type type, final PointFree expr) { ++ public PointFree rewrite(final Type type, final PointFree expr) { // Yatopia - Cadmium port + if (expr instanceof Apply) { + final Apply applyFirst = (Apply) expr; + if (applyFirst.arg instanceof Apply) { +@@ -158,46 +171,54 @@ public interface PointFreeRule { + return cap(applyFirst, applySecond); + } + } +- return Optional.empty(); ++ return null; // Yatopia - Cadmium port + } + + @SuppressWarnings("unchecked") +- private Optional> cap(final Apply applyFirst, final Apply applySecond) { ++ private PointFree cap(final Apply applyFirst, final Apply applySecond) { // Yatopia - Cadmium port + final PointFree func = applySecond.func; +- return Optional.of((PointFree) Functions.app(Functions.comp(applyFirst.argType, applyFirst.func, (PointFree>) func), applySecond.arg, applySecond.argType)); ++ return (PointFree) Functions.app(Functions.comp(applyFirst.argType, applyFirst.func, (PointFree>) func), applySecond.arg, applySecond.argType); // Yatopia - Cadmium port + } + } + + interface CompRewrite extends PointFreeRule { + @Override +- default Optional> rewrite(final Type type, final PointFree expr) { ++ default PointFree rewrite(final Type type, final PointFree expr) { // Yatopia - Cadmium port + if (expr instanceof Comp) { + final Comp comp = (Comp) expr; + final PointFree> first = comp.first; + final PointFree> second = comp.second; + if (first instanceof Comp) { + final Comp firstComp = (Comp) first; +- return doRewrite(type, comp.middleType, firstComp.second, comp.second).map(result -> { ++ final PointFree result = doRewrite(type, comp.middleType, firstComp.second, comp.second); // Yatopia - Cadmium port ++ ++ if (result!=null) { // Yatopia - Cadmium port + if (result instanceof Comp) { + final Comp resultComp = (Comp) result; + return buildLeftNested(resultComp, firstComp); + } + return buildRight(firstComp, result); +- }); ++ } // Yatopia - Cadmium port ++ ++ return null; + } + if (second instanceof Comp) { + final Comp secondComp = (Comp) second; +- return doRewrite(type, comp.middleType, comp.first, secondComp.first).map(result -> { ++ final PointFree result = doRewrite(type, comp.middleType, comp.first, secondComp.first); // Yatopia - Cadmium port ++ ++ if (result!=null) { // Yatopia - Cadmium port + if (result instanceof Comp) { + final Comp resultComp = (Comp) result; + return buildRightNested(secondComp, resultComp); + } + return buildLeft(result, secondComp); +- }); ++ } ++ ++ return null; // Yatopia - Cadmium port + } +- return (Optional>) doRewrite(type, comp.middleType, comp.first, comp.second); ++ return (PointFree) doRewrite(type, comp.middleType, comp.first, comp.second); // Yatopia - Cadmium port + } +- return Optional.empty(); ++ return null; // Yatopia - Cadmium port + } + + @SuppressWarnings("unchecked") +@@ -222,7 +243,7 @@ public interface PointFreeRule { + return (PointFree) new Comp<>(comp2.middleType, comp2.first, new Comp<>(comp1.middleType, comp2.second, comp1.second)); + } + +- Optional> doRewrite(Type type, Type middleType, PointFree> first, PointFree> second); ++ PointFree doRewrite(Type type, Type middleType, PointFree> first, PointFree> second); // Yatopia - Cadmium port + } + + enum SortProj implements CompRewrite { +@@ -230,7 +251,7 @@ public interface PointFreeRule { + + // (ap π1 f)◦(ap π2 g) -> (ap π2 g)◦(ap π1 f) + @Override +- public Optional> doRewrite(final Type type, final Type middleType, final PointFree> first, final PointFree> second) { ++ public PointFree doRewrite(final Type type, final Type middleType, final PointFree> first, final PointFree> second) { // Yatopia - Cadmium port + if (first instanceof Apply && second instanceof Apply) { + final Apply applyFirst = (Apply) first; + final Apply applySecond = (Apply) second; +@@ -253,11 +274,11 @@ public interface PointFreeRule { + if (Objects.equals(fo, Optics.proj2()) && Objects.equals(so, Optics.proj1())) { + final Func firstArg = (Func) applyFirst.argType; + final Func secondArg = (Func) applySecond.argType; +- return Optional.of(cap(firstArg, secondArg, applyFirst, applySecond)); ++ return cap(firstArg, secondArg, applyFirst, applySecond); // Yatopia - Cadmium port + } + } + } +- return Optional.empty(); ++ return null; // Yatopia - Cadmium port + } + + @SuppressWarnings("unchecked") +@@ -275,7 +296,7 @@ public interface PointFreeRule { + + // (ap i1 f)◦(ap i2 g) -> (ap i2 g)◦(ap i1 f) + @Override +- public Optional> doRewrite(final Type type, final Type middleType, final PointFree> first, final PointFree> second) { ++ public PointFree doRewrite(final Type type, final Type middleType, final PointFree> first, final PointFree> second) { // Yatopia - Cadmium port + if (first instanceof Apply && second instanceof Apply) { + final Apply applyFirst = (Apply) first; + final Apply applySecond = (Apply) second; +@@ -298,11 +319,11 @@ public interface PointFreeRule { + if (Objects.equals(fo, Optics.inj2()) && Objects.equals(so, Optics.inj1())) { + final Func firstArg = (Func) applyFirst.argType; + final Func secondArg = (Func) applySecond.argType; +- return Optional.of(cap(firstArg, secondArg, applyFirst, applySecond)); ++ return cap(firstArg, secondArg, applyFirst, applySecond); // Yatopia - Cadmium port + } + } + } +- return Optional.empty(); ++ return null; // Yatopia - Cadmium port + } + + @SuppressWarnings("unchecked") +@@ -320,7 +341,7 @@ public interface PointFreeRule { + + // Optic[o1] ◦ Optic[o2] -> Optic[o1 ◦ o2] + @Override +- public Optional> rewrite(final Type type, final PointFree expr) { ++ public PointFree rewrite(final Type type, final PointFree expr) { // Yatopia - Cadmium port + if (expr instanceof Comp) { + final Comp comp = (Comp) expr; + final PointFree> first = comp.first; +@@ -328,10 +349,10 @@ public interface PointFreeRule { + if (first instanceof ProfunctorTransformer && second instanceof ProfunctorTransformer) { + final ProfunctorTransformer firstOptic = (ProfunctorTransformer) first; + final ProfunctorTransformer secondOptic = (ProfunctorTransformer) second; +- return Optional.of(cap(firstOptic, secondOptic)); ++ return cap(firstOptic, secondOptic); // Yatopia - Cadmium port + } + } +- return Optional.empty(); ++ return null; // Yatopia - Cadmium port + } + + @SuppressWarnings("unchecked") +@@ -345,9 +366,8 @@ public interface PointFreeRule { + INSTANCE; + + // (ap lens f)◦(ap lens g) -> (ap lens (f ◦ g)) +- @SuppressWarnings("unchecked") + @Override +- public Optional> doRewrite(final Type type, final Type middleType, final PointFree> first, final PointFree> second) { ++ public PointFree doRewrite(final Type type, final Type middleType, final PointFree> first, final PointFree> second) { // Yatopia - Cadmium port + if (first instanceof Apply && second instanceof Apply) { + final Apply applyFirst = (Apply) first; + final Apply applySecond = (Apply) second; +@@ -364,17 +384,17 @@ public interface PointFreeRule { + } + } + } +- return Optional.empty(); ++ return null; // Yatopia - Cadmium port + } + +- private Optional> cap(final ProfunctorTransformer l1, final ProfunctorTransformer l2, final PointFree f1, final PointFree f2, final Func firstType, final Func secondType) { ++ private PointFree cap(final ProfunctorTransformer l1, final ProfunctorTransformer l2, final PointFree f1, final PointFree f2, final Func firstType, final Func secondType) { // Yatopia - Cadmium port + return cap2(l1, (ProfunctorTransformer) l2, (PointFree>) f1, (PointFree>) f2, (Func) firstType, (Func) secondType); + } + +- private Optional> cap2(final ProfunctorTransformer l1, final ProfunctorTransformer l2, final PointFree> f1, final PointFree> f2, final Func firstType, final Func secondType) { ++ private PointFree cap2(final ProfunctorTransformer l1, final ProfunctorTransformer l2, final PointFree> f1, final PointFree> f2, final Func firstType, final Func secondType) { // Yatopia - Cadmium port + final PointFree, Function>> lens = (PointFree, Function>>) (PointFree) l1; + final PointFree> arg = Functions.comp(firstType.first(), f1, f2); +- return Optional.of((PointFree) Functions.app(lens, arg, DSL.func(secondType.first(), firstType.second()))); ++ return (PointFree) Functions.app(lens, arg, DSL.func(secondType.first(), firstType.second())); // Yatopia - Cadmium port + } + } + +@@ -382,15 +402,14 @@ public interface PointFreeRule { + INSTANCE; + + // (fold g ◦ in) ◦ fold (f ◦ in) -> fold ( g ◦ f ◦ in), <== g ◦ in ◦ fold (f ◦ in) ◦ out == in ◦ fold (f ◦ in) ◦ out ◦ g <== g doesn't touch fold's index +- @SuppressWarnings("unchecked") + @Override +- public Optional> doRewrite(final Type type, final Type middleType, final PointFree> first, final PointFree> second) { ++ public PointFree doRewrite(final Type type, final Type middleType, final PointFree> first, final PointFree> second) { // Yatopia - Cadmium port + if (first instanceof Fold && second instanceof Fold) { + // fold (_) ◦ fold (_) + final Fold firstFold = (Fold) first; + final Fold secondFold = (Fold) second; + final RecursiveTypeFamily family = firstFold.aType.family(); +- if (Objects.equals(family, secondFold.aType.family()) && firstFold.index == secondFold.index) { ++ if (firstFold.index==secondFold.index && Objects.equals(family, secondFold.aType.family())) { // Yatopia - Cadmium port + // same fold + final List> newAlgebra = Lists.newArrayList(); + +@@ -399,8 +418,8 @@ public interface PointFreeRule { + boolean foundOne = false; + for (int i = 0; i < family.size(); i++) { + final RewriteResult firstAlgFunc = firstFold.algebra.apply(i); +- final RewriteResult secondAlgFunc = secondFold.algebra.apply(i); + final boolean firstId = Objects.equals(CompAssocRight.INSTANCE.rewriteOrNop(firstAlgFunc.view()).function(), Functions.id()); ++ /* + final boolean secondId = Objects.equals(secondAlgFunc.view().function(), Functions.id()); + + if (firstId && secondId) { +@@ -408,15 +427,37 @@ public interface PointFreeRule { + } else if (!foundOne && !firstId && !secondId) { + newAlgebra.add(getCompose(firstAlgFunc, secondAlgFunc)); + foundOne = true; ++ */ ++ // Yatopia start - Cadmium port ++ if (firstId) { ++ final RewriteResult secondAlgFunc = secondFold.algebra.apply(i); ++ final boolean secondId = Objects.equals(secondAlgFunc.view().function(), Functions.id()); ++ ++ if (secondId) { ++ newAlgebra.add(firstFold.algebra.apply(i)); ++ } else { ++ return null; ++ } ++ } else if (!foundOne) { ++ final RewriteResult secondAlgFunc = secondFold.algebra.apply(i); ++ final boolean secondId = Objects.equals(secondAlgFunc.view().function(), Functions.id()); ++ ++ if (!secondId) { ++ newAlgebra.add(getCompose(firstAlgFunc, secondAlgFunc)); ++ foundOne = true; ++ } else { ++ return null; ++ } ++ // Yatopia end + } else { +- return Optional.empty(); ++ return null; // Yatopia - Cadmium port + } + } + final Algebra algebra = new ListAlgebra("FusedSame", newAlgebra); +- return Optional.of((PointFree) family.fold(algebra).apply(firstFold.index).view().function()); ++ return family.fold(algebra).apply(firstFold.index).view().function(); // Yatopia - Cadmium port + } + } +- return Optional.empty(); ++ return null; // Yatopia - Cadmium port + } + + @SuppressWarnings("unchecked") +@@ -431,13 +472,14 @@ public interface PointFreeRule { + // (fold g ◦ in) ◦ fold (f ◦ in) -> fold ( g ◦ f ◦ in), <== g ◦ in ◦ fold (f ◦ in) ◦ out == in ◦ fold (f ◦ in) ◦ out ◦ g <== g doesn't touch fold's index + @SuppressWarnings("unchecked") + @Override +- public Optional> doRewrite(final Type type, final Type middleType, final PointFree> first, final PointFree> second) { ++ public PointFree doRewrite(final Type type, final Type middleType, final PointFree> first, final PointFree> second) { // Yatopia - Cadmium port + if (first instanceof Fold && second instanceof Fold) { + // fold (_) ◦ fold (_) + final Fold firstFold = (Fold) first; + final Fold secondFold = (Fold) second; + final RecursiveTypeFamily family = firstFold.aType.family(); +- if (Objects.equals(family, secondFold.aType.family()) && firstFold.index == secondFold.index) { ++ // if (Objects.equals(family, secondFold.aType.family()) && firstFold.index == secondFold.index) { ++ if (firstFold.index==secondFold.index && Objects.equals(family, secondFold.aType.family())) { // Yatopia - Cadmium port + // same fold + final List> newAlgebra = Lists.newArrayList(); + +@@ -460,46 +502,57 @@ public interface PointFreeRule { + // TODO: verify that this is enough + for (int i = 0; i < family.size(); i++) { + final RewriteResult firstAlgFunc = firstFold.algebra.apply(i); ++ // Yatopia start - Cadmium port ++ if (firstAlgFunc.recData().intersects(secondModifies)) { ++ // outer function depends on the result of the inner one ++ return null; ++ } ++ // Yatopia end + final RewriteResult secondAlgFunc = secondFold.algebra.apply(i); ++ /* + final PointFree firstF = CompAssocRight.INSTANCE.rewriteOrNop(firstAlgFunc.view()).function(); + final PointFree secondF = CompAssocRight.INSTANCE.rewriteOrNop(secondAlgFunc.view()).function(); + final boolean firstId = Objects.equals(firstF, Functions.id()); + final boolean secondId = Objects.equals(secondF, Functions.id()); + if (firstAlgFunc.recData().intersects(secondModifies) || secondAlgFunc.recData().intersects(firstModifies)) { ++ */ ++ // Yatopia start - Cadmium port ++ if (secondAlgFunc.recData().intersects(firstModifies)) { + // outer function depends on the result of the inner one +- return Optional.empty(); ++ return null; + } +- if (firstId) { ++ // Yatopia end ++ if (Objects.equals(CompAssocRight.INSTANCE.rewriteOrNop(firstAlgFunc.view()).function(), Functions.id())) { // Yatopia - Cadmium port + newAlgebra.add(secondAlgFunc); +- } else if (secondId) { ++ } else if (Objects.equals(CompAssocRight.INSTANCE.rewriteOrNop(secondAlgFunc.view()).function(), Functions.id())) { // Yatopia - Cadmium port + newAlgebra.add(firstAlgFunc); + } else { +- return Optional.empty(); ++ return null; // Yatopia - Cadmium port + } + } + // have new algebra - make a new fold + + final Algebra algebra = new ListAlgebra("FusedDifferent", newAlgebra); +- return Optional.of((PointFree) family.fold(algebra).apply(firstFold.index).view().function()); ++ return family.fold(algebra).apply(firstFold.index).view().function(); // Yatopia - Cadmium port + } + } +- return Optional.empty(); ++ return null; // Yatopia - Cadmium port + } + } + + /*final class ReflexCata implements Rule { + @SuppressWarnings("unchecked") + @Override +- public Optional> rewrite(final Type type, final PF expr) { ++ public PF rewrite(final Type type, final PF expr) { // Yatopia - Cadmium port + if (type instanceof Type.Func && expr instanceof PF.Cata) { + final Type.Func funcType = (Type.Func) type; + final PF.Cata cata = (PF.Cata) expr; + // TODO better equality + if (Objects.equals(cata.alg, PF.genBF(cata.family.to)) && Objects.equals(funcType.first, funcType.second)) { +- return Optional.of((PF) PF.id()); ++ return (PF) PF.id(); // Yatopia - Cadmium port + } + } +- return Optional.empty(); ++ return null; // Yatopia - Cadmium port + } + }*/ + +@@ -518,14 +571,20 @@ public interface PointFreeRule { + this.rules = ImmutableList.copyOf(rules); + } + ++ // Yatopia start - Cadmium port + @Override +- public Optional> rewrite(final Type type, final PointFree expr) { +- Optional> result = Optional.of(expr); ++ public PointFree rewrite(final Type type, final PointFree expr) { ++ PointFree result = expr; + for (final Supplier rule : rules) { +- result = result.flatMap(pf -> rule.get().rewrite(type, pf)); ++ if (result==null) { ++ return null; ++ } ++ ++ result = rule.get().rewrite(type, result); + } + return result; + } ++ // Yatopia end + + @Override + public boolean equals(final Object obj) { +@@ -546,30 +605,28 @@ public interface PointFreeRule { + } + + static PointFreeRule orElse(final PointFreeRule first, final PointFreeRule second) { +- return new OrElse(first, () -> second); +- } +- +- static PointFreeRule orElseStrict(final PointFreeRule first, final Supplier second) { + return new OrElse(first, second); + } + + final class OrElse implements PointFreeRule { + protected final PointFreeRule first; +- protected final Supplier second; ++ protected final PointFreeRule second; // Yatopia - Cadmium port + +- public OrElse(final PointFreeRule first, final Supplier second) { ++ public OrElse(final PointFreeRule first, final PointFreeRule second) { // Yatopia - Cadmium port + this.first = first; + this.second = second; + } + ++ // Yatopia start - Cadmium port + @Override +- public Optional> rewrite(final Type type, final PointFree expr) { +- final Optional> view = first.rewrite(type, expr); +- if (view.isPresent()) { ++ public PointFree rewrite(final Type type, final PointFree expr) { ++ final PointFree view = first.rewrite(type, expr); ++ if (view!=null) { + return view; + } +- return second.get().rewrite(type, expr); ++ return second.rewrite(type, expr); + } ++ // Yatopia end + + @Override + public boolean equals(final Object obj) { +@@ -589,6 +646,42 @@ public interface PointFreeRule { + } + } + ++ // Yatopia start - Cadmium port ++ final class OrElseStrict implements PointFreeRule { ++ protected final PointFreeRule rule; ++ ++ public OrElseStrict(final PointFreeRule rule) { ++ this.rule = rule; ++ } ++ ++ @Override ++ public PointFree rewrite(final Type type, final PointFree expr) { ++ final PointFree view = rule.rewrite(type, expr); ++ if (view!=null) { ++ return view; ++ } ++ return expr.one(this, type); ++ } ++ ++ @Override ++ public boolean equals(final Object obj) { ++ if (obj == this) { ++ return true; ++ } ++ if (!(obj instanceof OrElse)) { ++ return false; ++ } ++ final OrElse that = (OrElse) obj; ++ return Objects.equals(rule, that.first); ++ } ++ ++ @Override ++ public int hashCode() { ++ return Objects.hash(rule); ++ } ++ } ++ // Yatopia end ++ + static PointFreeRule all(final PointFreeRule rule) { + return new All(rule); + } +@@ -598,7 +691,7 @@ public interface PointFreeRule { + } + + static PointFreeRule once(final PointFreeRule rule) { +- return orElseStrict(rule, () -> one(once(rule))); ++ return new OrElseStrict(rule); // Yatopia - Cadmium port + } + + static PointFreeRule many(final PointFreeRule rule) { +@@ -617,7 +710,7 @@ public interface PointFreeRule { + } + + @Override +- public Optional> rewrite(final Type type, final PointFree expr) { ++ public PointFree rewrite(final Type type, final PointFree expr) { // Yatopia - Cadmium port + return expr.all(rule, type); + } + +@@ -647,7 +740,7 @@ public interface PointFreeRule { + } + + @Override +- public Optional> rewrite(final Type type, final PointFree expr) { ++ public PointFree rewrite(final Type type, final PointFree expr) { // Yatopia - Cadmium port + return expr.one(rule, type); + } + +@@ -676,17 +769,22 @@ public interface PointFreeRule { + this.rule = rule; + } + ++ // Yatopia start - Cadmium port + @Override +- public Optional> rewrite(final Type type, final PointFree expr) { +- Optional> result = Optional.of(expr); ++ public PointFree rewrite(final Type type, final PointFree expr) { ++ PointFree result = expr; + while (true) { +- final Optional> newResult = result.flatMap(e -> rule.rewrite(type, e).map(r -> r)); +- if (!newResult.isPresent()) { ++ if (result==null) { ++ return null; ++ } ++ final PointFree newResult = rule.rewrite(type, result); ++ if (newResult==null) { + return result; + } + result = newResult; + } + } ++ // Yatopia end + + @Override + public boolean equals(final Object o) { +diff --git a/src/main/java/com/mojang/datafixers/optics/IdAdapter.java b/src/main/java/com/mojang/datafixers/optics/IdAdapter.java +index 3f1793aca685a627d0e925d037f663a257522d8d..0e4bf4b58710be135e6573ccff3f8c0a2a41191a 100644 +--- a/src/main/java/com/mojang/datafixers/optics/IdAdapter.java ++++ b/src/main/java/com/mojang/datafixers/optics/IdAdapter.java +@@ -3,6 +3,14 @@ + package com.mojang.datafixers.optics; + + class IdAdapter implements Adapter { ++ // Yatopia start - Cadmium port ++ private static final Adapter INSTANCE = new IdAdapter<>(); ++ ++ private IdAdapter() { ++ ++ } ++ // Yatopia end ++ + @Override + public S from(final S s) { + return s; +@@ -22,4 +30,11 @@ class IdAdapter implements Adapter { + public String toString() { + return "id"; + } ++ ++ // Yatopia start - Cadmium port ++ @SuppressWarnings("unchecked") ++ public static Adapter instance() { ++ return (Adapter) INSTANCE; ++ } ++ // Yatopia end + } +diff --git a/src/main/java/com/mojang/datafixers/optics/Inj1.java b/src/main/java/com/mojang/datafixers/optics/Inj1.java +index 8c56955c9d6c3d6021d5c9fda452e39774ac587c..4813f335cd536d1b32b9095dbd76e18c22a6dea1 100644 +--- a/src/main/java/com/mojang/datafixers/optics/Inj1.java ++++ b/src/main/java/com/mojang/datafixers/optics/Inj1.java +@@ -5,6 +5,14 @@ package com.mojang.datafixers.optics; + import com.mojang.datafixers.util.Either; + + public final class Inj1 implements Prism, Either, F, F2> { ++ // Yatopia start - Cadmium port ++ private static final Inj1 INSTANCE = new Inj1<>(); ++ ++ private Inj1() { ++ ++ } ++ // Yatopia end ++ + @Override + public Either, F> match(final Either either) { + return either.map(Either::right, g -> Either.left(Either.right(g))); +@@ -24,4 +32,11 @@ public final class Inj1 implements Prism, Either, + public boolean equals(final Object obj) { + return obj instanceof Inj1; + } ++ ++ // Yatopia start - Cadmium port ++ @SuppressWarnings("unchecked") ++ public static Inj1 instance() { ++ return (Inj1) INSTANCE; ++ } ++ // Yatopia end + } +diff --git a/src/main/java/com/mojang/datafixers/optics/Inj2.java b/src/main/java/com/mojang/datafixers/optics/Inj2.java +index 2f95715f310faec6e43c715cbf204a092bfc107e..ad2400ccdb159cbf8b882d0b5afc53d3e220f770 100644 +--- a/src/main/java/com/mojang/datafixers/optics/Inj2.java ++++ b/src/main/java/com/mojang/datafixers/optics/Inj2.java +@@ -2,9 +2,18 @@ + // Licensed under the MIT license. + package com.mojang.datafixers.optics; + ++import com.mojang.datafixers.DataFixerBuilder; // Yatopia - Cadmium port + import com.mojang.datafixers.util.Either; + + public final class Inj2 implements Prism, Either, G, G2> { ++ // Yatopia start - Cadmium port ++ private static final Inj2 INSTANCE = new Inj2<>(); ++ ++ private Inj2() { ++ ++ } ++ // Yatopia end ++ + @Override + public Either, G> match(final Either either) { + return either.map(f -> Either.left(Either.left(f)), Either::right); +@@ -24,4 +33,11 @@ public final class Inj2 implements Prism, Either, + public boolean equals(final Object obj) { + return obj instanceof Inj2; + } ++ ++ // Yatopia start - Cadmium port ++ @SuppressWarnings("unchecked") ++ public static Inj2 instance() { ++ return (Inj2) INSTANCE; ++ } ++ // Yatopia end + } +diff --git a/src/main/java/com/mojang/datafixers/optics/Optics.java b/src/main/java/com/mojang/datafixers/optics/Optics.java +index 4bf469df6a9092a554df4dafdbfe37f51da28f32..cec492b8e633adedbf6c4d83cf257f640412de06 100644 +--- a/src/main/java/com/mojang/datafixers/optics/Optics.java ++++ b/src/main/java/com/mojang/datafixers/optics/Optics.java +@@ -65,7 +65,7 @@ public abstract class Optics { + } + + public static Adapter id() { +- return new IdAdapter<>(); ++ return IdAdapter.instance(); // Yatopia - Cadmium port + } + + public static Adapter adapter(final Function from, final Function to) { +@@ -223,19 +223,19 @@ public abstract class Optics { + } + + public static Proj1 proj1() { +- return new Proj1<>(); ++ return Proj1.instance(); // Yatopia - Cadmium port + } + + public static Proj2 proj2() { +- return new Proj2<>(); ++ return Proj2.instance(); // Yatopia - Cadmium port + } + + public static Inj1 inj1() { +- return new Inj1<>(); ++ return Inj1.instance(); // Yatopia - Cadmium port + } + + public static Inj2 inj2() { +- return new Inj2<>(); ++ return Inj2.instance(); // Yatopia - Cadmium port + } + + /*public static Optic, Either, A, B> choosing(final Optic first, final Optic second) { +diff --git a/src/main/java/com/mojang/datafixers/optics/Proj1.java b/src/main/java/com/mojang/datafixers/optics/Proj1.java +index 488e4cd9a87178a441eda0ee5bff9c5feca69e6d..ae8850e52feeff51f61c4527c792446ef5e23344 100644 +--- a/src/main/java/com/mojang/datafixers/optics/Proj1.java ++++ b/src/main/java/com/mojang/datafixers/optics/Proj1.java +@@ -5,6 +5,14 @@ package com.mojang.datafixers.optics; + import com.mojang.datafixers.util.Pair; + + public final class Proj1 implements Lens, Pair, F, F2> { ++ // Yatopia start - Cadmium port ++ private static final Proj1 INSTANCE = new Proj1<>(); ++ ++ private Proj1() { ++ ++ } ++ // Yatopia end ++ + @Override + public F view(final Pair pair) { + return pair.getFirst(); +@@ -24,4 +32,11 @@ public final class Proj1 implements Lens, Pair, F, F + public boolean equals(final Object obj) { + return obj instanceof Proj1; + } ++ ++ // Yatopia start - Cadmium port ++ @SuppressWarnings("unchecked") ++ public static Proj1 instance() { ++ return (Proj1) INSTANCE; ++ } ++ // Yatopia end + } +diff --git a/src/main/java/com/mojang/datafixers/optics/Proj2.java b/src/main/java/com/mojang/datafixers/optics/Proj2.java +index 3bd3689115f25d34fceaa8f8f915c21656267af5..76d05449689808e3d0435aea7480dcad134730f1 100644 +--- a/src/main/java/com/mojang/datafixers/optics/Proj2.java ++++ b/src/main/java/com/mojang/datafixers/optics/Proj2.java +@@ -5,6 +5,14 @@ package com.mojang.datafixers.optics; + import com.mojang.datafixers.util.Pair; + + public final class Proj2 implements Lens, Pair, G, G2> { ++ // Yatopia start - Cadmium port ++ private static final Proj2 INSTANCE = new Proj2<>(); ++ ++ private Proj2() { ++ ++ } ++ // Yatopia end ++ + @Override + public G view(final Pair pair) { + return pair.getSecond(); +@@ -24,4 +32,11 @@ public final class Proj2 implements Lens, Pair, G, G + public boolean equals(final Object obj) { + return obj instanceof Proj2; + } ++ ++ // Yatopia start - Cadmium port ++ @SuppressWarnings("unchecked") ++ public static Proj2 instance() { ++ return (Proj2) INSTANCE; ++ } ++ // Yatopia end + } +diff --git a/src/main/java/com/mojang/datafixers/types/Type.java b/src/main/java/com/mojang/datafixers/types/Type.java +index 4592da3c75e639164d10cc05518c27d8f488a103..53ab2332aaff5970e5f3825734906fc7f1f8c53c 100644 +--- a/src/main/java/com/mojang/datafixers/types/Type.java ++++ b/src/main/java/com/mojang/datafixers/types/Type.java +@@ -87,7 +87,7 @@ public abstract class Type implements App { + } + + public Optional> everywhere(final TypeRewriteRule rule, final PointFreeRule optimizationRule, final boolean recurse, final boolean checkIndex) { +- final TypeRewriteRule rule2 = TypeRewriteRule.seq(TypeRewriteRule.orElse(rule, TypeRewriteRule::nop), TypeRewriteRule.all(TypeRewriteRule.everywhere(rule, optimizationRule, recurse, checkIndex), recurse, checkIndex)); ++ final TypeRewriteRule rule2 = TypeRewriteRule.seq(TypeRewriteRule.orElse(rule, TypeRewriteRule.Nop.INSTANCE), TypeRewriteRule.all(TypeRewriteRule.everywhere(rule, optimizationRule, recurse, checkIndex), recurse, checkIndex)); // Yatopia - Cadmium port + return rewrite(rule2, optimizationRule); + } + +@@ -187,7 +187,17 @@ public abstract class Type implements App { + }); + + if (ref.getValue() != null) { +- Optional> result = rule.rewrite(this).flatMap(r -> r.view().rewrite(fRule).map(view -> RewriteResult.create(view, r.recData()))); ++ // Yatopia start - Cadmium port ++ Optional> result = rule.rewrite(this).flatMap(r -> { ++ View view = r.view().rewrite(fRule); ++ ++ if (view!=null) { ++ return Optional.of(RewriteResult.create(view, r.recData())); ++ } ++ ++ return Optional.empty(); ++ }); ++ // Yatopia end + REWRITE_CACHE.put(key, result); + pending.complete(result); + PENDING_REWRITE_CACHE.remove(key); diff --git a/patches/server/remap in progress/0059-Lithium-CompactSineLUT.patch b/patches/server/remap in progress/0059-Lithium-CompactSineLUT.patch new file mode 100644 index 00000000..52daea0b --- /dev/null +++ b/patches/server/remap in progress/0059-Lithium-CompactSineLUT.patch @@ -0,0 +1,138 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Fri, 5 Feb 2021 00:16:30 -0600 +Subject: [PATCH] Lithium: CompactSineLUT + +Original code by JellySquid, licensed under GNU Lesser General Public License v3.0 +you can find the original code on https://github.com/CaffeineMC/lithium-fabric/ (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/util/MathHelper.java b/src/main/java/net/minecraft/util/MathHelper.java +index e9e7fcf2b63febe2a7d055826fabb86bc13a5cf3..b95115aca72ba0cf6451096ddbd8b50a8f3bb5c6 100644 +--- a/src/main/java/net/minecraft/util/MathHelper.java ++++ b/src/main/java/net/minecraft/util/MathHelper.java +@@ -5,6 +5,7 @@ import java.util.UUID; + import java.util.function.IntPredicate; + import net.minecraft.SystemUtils; + import net.minecraft.core.BaseBlockPosition; ++import org.yatopiamc.yatopia.server.math.CompactSineLUT; + + public class MathHelper { + +@@ -15,6 +16,7 @@ public class MathHelper { + } + + }); ++ public static float[] getSinTable() { return b; } // Yatopia - OBFHELPER + private static final Random c = new Random(); + private static final int[] d = new int[]{0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9}; + private static final double e = Double.longBitsToDouble(4805340802404319232L); +@@ -22,11 +24,11 @@ public class MathHelper { + private static final double[] g = new double[257]; + + public static float sin(float f) { +- return MathHelper.b[(int) (f * 10430.378F) & '\uffff']; ++ return CompactSineLUT.sin(f); // Yatopia - CompactSineLUT + } + + public static float cos(float f) { +- return MathHelper.b[(int) (f * 10430.378F + 16384.0F) & '\uffff']; ++ return CompactSineLUT.cos(f); // Yatopia - CompactSineLUT + } + + public static float c(float f) { +diff --git a/src/main/java/org/yatopiamc/yatopia/server/math/CompactSineLUT.java b/src/main/java/org/yatopiamc/yatopia/server/math/CompactSineLUT.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1bb8ba3836af872bc2e58898f16a0b91036b9b02 +--- /dev/null ++++ b/src/main/java/org/yatopiamc/yatopia/server/math/CompactSineLUT.java +@@ -0,0 +1,90 @@ ++package org.yatopiamc.yatopia.server.math; ++ ++import net.minecraft.util.MathHelper; ++ ++/** ++ * A replacement for the sine angle lookup table used in {@link MathHelper}, both reducing the size of LUT and improving ++ * the access patterns for common paired sin/cos operations. ++ * ++ * sin(-x) = -sin(x) ++ * ... to eliminate negative angles from the LUT. ++ * ++ * sin(x) = sin(pi/2 - x) ++ * ... to eliminate supplementary angles from the LUT. ++ * ++ * Using these identities allows us to reduce the LUT from 64K entries (256 KB) to just 16K entries (64 KB), enabling ++ * it to better fit into the CPU's caches at the expense of some cycles on the fast path. The implementation has been ++ * tightly optimized to avoid branching where possible and to use very quick integer operations. ++ * ++ * Generally speaking, reducing the size of a lookup table is always a good optimization, but since we need to spend ++ * extra CPU cycles trying to maintain parity with vanilla, there is the potential risk that this implementation ends ++ * up being slower than vanilla when the lookup table is able to be kept in cache memory. ++ * ++ * Unlike other "fast math" implementations, the values returned by this class are *bit-for-bit identical* with those ++ * from {@link MathHelper}. Validation is performed during runtime to ensure that the table is correct. ++ * ++ * @author coderbot16 Author of the original (and very clever) implementation in Rust: ++ * https://gitlab.com/coderbot16/i73/-/tree/master/i73-trig/src ++ * @author jellysquid3 Additional optimizations, port to Java ++ */ ++public class CompactSineLUT { ++ private static final int[] SINE_TABLE_INT = new int[16384 + 1]; ++ private static final float SINE_TABLE_MIDPOINT; ++ ++ static { ++ final float[] SINE_TABLE = MathHelper.getSinTable(); ++ // Copy the sine table, covering to raw int bits ++ for (int i = 0; i < SINE_TABLE_INT.length; i++) { ++ SINE_TABLE_INT[i] = Float.floatToRawIntBits(SINE_TABLE[i]); ++ } ++ ++ SINE_TABLE_MIDPOINT = SINE_TABLE[SINE_TABLE.length / 2]; ++ ++ // Test that the lookup table is correct during runtime ++ for (int i = 0; i < SINE_TABLE.length; i++) { ++ float expected = SINE_TABLE[i]; ++ float value = lookup(i); ++ ++ if (expected != value) { ++ throw new IllegalArgumentException(String.format("LUT error at index %d (expected: %s, found: %s)", i, expected, value)); ++ } ++ } ++ } ++ ++ // [VanillaCopy] MathHelper#sin(float) ++ public static float sin(float f) { ++ return lookup((int) (f * 10430.38) & 0xFFFF); ++ } ++ ++ // [VanillaCopy] MathHelper#cos(float) ++ public static float cos(float f) { ++ return lookup((int) (f * 10430.38 + 16384.0) & 0xFFFF); ++ } ++ ++ private static float lookup(int index) { ++ // A special case... Is there some way to eliminate this? ++ if (index == 32768) { ++ return SINE_TABLE_MIDPOINT; ++ } ++ ++ // Trigonometric identity: sin(-x) = -sin(x) ++ // Given a domain of 0 <= x <= 2*pi, just negate the value if x > pi. ++ // This allows the sin table size to be halved. ++ int neg = (index & 0x8000) << 16; ++ ++ // All bits set if (pi/2 <= x), none set otherwise ++ // Extracts the 15th bit from 'half' ++ int mask = (index << 17) >> 31; ++ ++ // Trigonometric identity: sin(x) = sin(pi/2 - x) ++ int pos = (0x8001 & mask) + (index ^ mask); ++ ++ // Wrap the position in the table. Moving this down to immediately before the array access ++ // seems to help the Hotspot compiler optimize the bit math better. ++ pos &= 0x7fff; ++ ++ // Fetch the corresponding value from the LUT and invert the sign bit as needed ++ // This directly manipulate the sign bit on the float bits to simplify logic ++ return Float.intBitsToFloat(SINE_TABLE_INT[pos] ^ neg); ++ } ++} diff --git a/patches/server/remap in progress/0060-tic-tacs-unblocking.patch b/patches/server/remap in progress/0060-tic-tacs-unblocking.patch new file mode 100644 index 00000000..16c1dc6c --- /dev/null +++ b/patches/server/remap in progress/0060-tic-tacs-unblocking.patch @@ -0,0 +1,407 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Gegy +Date: Tue, 9 Feb 2021 13:23:12 -0500 +Subject: [PATCH] tic-tacs: unblocking + +Code originally licenced under LGPLv3 for the tic-tacs project: https://github.com/Gegy/tic-tacs + +diff --git a/src/main/java/net/gegy1000/tictacs/NonBlockingWorldAccess.java b/src/main/java/net/gegy1000/tictacs/NonBlockingWorldAccess.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0d99f3b4930045632d88fa4acb3b8159ee9cf9f3 +--- /dev/null ++++ b/src/main/java/net/gegy1000/tictacs/NonBlockingWorldAccess.java +@@ -0,0 +1,29 @@ ++package net.gegy1000.tictacs; ++ ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.material.Fluid; ++import net.minecraft.world.level.material.FluidTypes; ++import net.minecraft.core.BlockPosition; ++import net.minecraft.world.level.IWorldReader; ++import net.minecraft.world.level.material.FluidTypes; ++ ++public interface NonBlockingWorldAccess extends IWorldReader { ++ ++ public static final IBlockData DEFAULT_BLOCK_STATE = Blocks.AIR.getBlockData(); ++ public static final Fluid DEFAULT_FLUID_STATE = FluidTypes.EMPTY.getFluidData(); ++ ++ default IBlockData getBlockStateIfLoaded(BlockPosition pos) { ++ if (this.isLoaded(pos)) { ++ return this.getType(pos); ++ } ++ return DEFAULT_BLOCK_STATE; ++ } ++ ++ default Fluid getFluidStateIfLoaded(BlockPosition pos) { ++ if (this.isLoaded(pos)) { ++ return this.getFluid(pos); ++ } ++ return DEFAULT_FLUID_STATE; ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java +index 85f0b1e789858d840d0d709fc1974d6b7419f7ef..f33c22c3b1a922a6bedf8076c9eb447d2518d3cc 100644 +--- a/src/main/java/net/minecraft/server/level/EntityPlayer.java ++++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java +@@ -663,6 +663,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + } + + public void playerTick() { ++ if (!this.world.isLoaded(this.getChunkCoordinates())) return; // Yatopia - tic-tac unblocking ++ + try { + if (valid && !this.isSpectator() || this.world.isLoaded(this.getChunkCoordinates())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) + super.tick(); +diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +index aacf99c418b692fa9e29c00ad449b0c8c8c9ef71..537c05601492306e7b37b11594f193c7c668e11b 100644 +--- a/src/main/java/net/minecraft/server/level/WorldServer.java ++++ b/src/main/java/net/minecraft/server/level/WorldServer.java +@@ -176,8 +176,9 @@ import org.bukkit.event.weather.LightningStrikeEvent; + import org.bukkit.event.world.TimeSkipEvent; + // CraftBukkit end + import it.unimi.dsi.fastutil.ints.IntArrayList; // Tuinity ++import net.gegy1000.tictacs.NonBlockingWorldAccess; // Yatopia + +-public class WorldServer extends World implements GeneratorAccessSeed { ++public class WorldServer extends World implements GeneratorAccessSeed, NonBlockingWorldAccess { // Yatopia + + public static final BlockPosition a = new BlockPosition(100, 50, 0); + private static final Logger LOGGER = LogManager.getLogger(); +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 286e14bb39509328844e1f57d8faa04b20014f83..2ed54208faf35ea5b4ea8540e95886b56d4d11fe 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -141,9 +141,12 @@ import org.bukkit.event.entity.EntityPoseChangeEvent; + import org.bukkit.event.player.PlayerTeleportEvent; + import org.bukkit.plugin.PluginManager; + // CraftBukkit end ++import net.gegy1000.tictacs.NonBlockingWorldAccess; // Yatopia + + public abstract class Entity implements INamableTileEntity, ICommandListener, net.minecraft.server.KeyedObject { // Paper + ++ public boolean updateNeeded; // Yatopia ++ private boolean chunkPosUpdateRequested; // Yatopia + // CraftBukkit start + private static final int CURRENT_LEVEL = 2; + public boolean preserveMotion = true; // Paper - keep initial motion on first setPositionRotation +@@ -802,6 +805,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + // Tuinity end - detailed watchdog information + public void move(EnumMoveType enummovetype, Vec3D vec3d) { ++ // Yatopia start - tic-tacs unblocking ++ BlockPosition pos = this.getChunkCoordinates(); ++ if (!this.world.isLoaded(pos)) { ++ return; ++ } ++ // Yatopia end + // Tuinity start - detailed watchdog information + com.tuinity.tuinity.util.TickThread.ensureTickThread("Cannot move an entity off-main"); + synchronized (this.posLock) { +@@ -852,7 +861,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + this.v = vec3d.y != vec3d1.y; + this.onGround = this.v && vec3d.y < 0.0D; + BlockPosition blockposition = this.ap(); +- IBlockData iblockdata = this.world.getType(blockposition); ++ IBlockData iblockdata = this.world.getBlockStateIfLoaded(blockposition); // Yatopia + + this.a(vec3d1.y, this.onGround, iblockdata, blockposition); + Vec3D vec3d2 = this.getMot(); +@@ -966,9 +975,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + int k = MathHelper.floor(this.loc.z); + BlockPosition blockposition = new BlockPosition(i, j, k); + +- if (this.world.getType(blockposition).isAir()) { ++ if (this.world.getBlockStateIfLoaded(blockposition).isAir()) { // Yatopia + BlockPosition blockposition1 = blockposition.down(); +- IBlockData iblockdata = this.world.getType(blockposition1); ++ IBlockData iblockdata = this.world.getBlockStateIfLoaded(blockposition1); // Yatopia + Block block = iblockdata.getBlock(); + + if (block.a((Tag) TagsBlock.FENCES) || block.a((Tag) TagsBlock.WALLS) || block instanceof BlockFenceGate) { +@@ -980,17 +989,21 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + protected float getBlockJumpFactor() { +- float f = this.world.getType(this.getChunkCoordinates()).getBlock().getJumpFactor(); +- float f1 = this.world.getType(this.as()).getBlock().getJumpFactor(); ++ // Yatopia start - tic-tacs unblocking ++ float f = this.world.getBlockStateIfLoaded(this.getChunkCoordinates()).getBlock().getJumpFactor(); ++ float f1 = this.world.getBlockStateIfLoaded(this.as()).getBlock().getJumpFactor(); ++ // Yatopia end + + return (double) f == 1.0D ? f1 : f; + } + + protected float getBlockSpeedFactor() { +- Block block = this.world.getType(this.getChunkCoordinates()).getBlock(); ++ // Yatopia start - tic-tacs unblocking ++ Block block = this.world.getBlockStateIfLoaded(this.getChunkCoordinates()).getBlock(); + float f = block.getSpeedFactor(); + +- return block != Blocks.WATER && block != Blocks.BUBBLE_COLUMN ? ((double) f == 1.0D ? this.world.getType(this.as()).getBlock().getSpeedFactor() : f) : f; ++ return block != Blocks.WATER && block != Blocks.BUBBLE_COLUMN ? ((double) f == 1.0D ? this.world.getBlockStateIfLoaded(this.as()).getBlock().getSpeedFactor() : f) : f; ++ // Yatopia end + } + + protected BlockPosition as() { +@@ -1335,7 +1348,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + for (int i = blockposition.getX(); i <= blockposition1.getX(); ++i) { + // Tuinity end - reorder iteration to more cache aware + blockposition_mutableblockposition.d(i, j, k); +- IBlockData iblockdata = this.world.getType(blockposition_mutableblockposition); ++ IBlockData iblockdata = this.world.getBlockStateIfLoaded(blockposition_mutableblockposition); + + // Tuinity start - move fire checking in here - reuse getType from this method + if (checkFire) { +@@ -1371,7 +1384,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + + protected void b(BlockPosition blockposition, IBlockData iblockdata) { + if (!iblockdata.getMaterial().isLiquid()) { +- IBlockData iblockdata1 = this.world.getType(blockposition.up()); ++ IBlockData iblockdata1 = this.world.getBlockStateIfLoaded(blockposition.up()); // Yatopia + SoundEffectType soundeffecttype = iblockdata1.a(Blocks.SNOW) ? iblockdata1.getStepSound() : iblockdata.getStepSound(); + + this.playSound(soundeffecttype.getStepSound(), soundeffecttype.getVolume() * 0.15F, soundeffecttype.getPitch()); +@@ -1462,7 +1475,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + + public final boolean isInBubbleColumn() { return k(); } // Paper - OBFHELPER + private boolean k() { +- return this.world.getType(this.getChunkCoordinates()).a(Blocks.BUBBLE_COLUMN); ++ return this.world.getBlockStateIfLoaded(this.getChunkCoordinates()).a(Blocks.BUBBLE_COLUMN); // Yatopia + } + + public boolean isInWaterOrRain() { +@@ -1533,7 +1546,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + BlockPosition blockposition = new BlockPosition(this.locX(), d0, this.locZ()); +- Fluid fluid = this.world.getFluid(blockposition); ++ Fluid fluid = this.world.getFluidStateIfLoaded(blockposition); // Yatopia + Iterator iterator = TagsFluid.b().iterator(); + + Tag tag; +@@ -1591,7 +1604,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + protected IBlockData aN() { +- return this.world.getType(this.ap()); ++ return this.world.getBlockStateIfLoaded(this.ap()); // Yatopia + } + + public boolean aO() { +@@ -1603,7 +1616,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + int j = MathHelper.floor(this.locY() - 0.20000000298023224D); + int k = MathHelper.floor(this.locZ()); + BlockPosition blockposition = new BlockPosition(i, j, k); +- IBlockData iblockdata = this.world.getType(blockposition); ++ IBlockData iblockdata = this.world.getBlockStateIfLoaded(blockposition); // Yatopia + + if (iblockdata.h() != EnumRenderType.INVISIBLE) { + Vec3D vec3d = this.getMot(); +@@ -2857,7 +2870,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + EnumDirection enumdirection1 = aenumdirection[j]; + + blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, enumdirection1); +- if (!this.world.getType(blockposition_mutableblockposition).r(this.world, blockposition_mutableblockposition)) { ++ if (!this.world.getBlockStateIfLoaded(blockposition_mutableblockposition).r(this.world, blockposition_mutableblockposition)) { // Yatopia + double d4 = vec3d.a(enumdirection1.n()); + double d5 = enumdirection1.e() == EnumDirection.EnumAxisDirection.POSITIVE ? 1.0D - d4 : d4; + +@@ -3073,14 +3086,14 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + + return (ShapeDetectorShape) this.findOrCreatePortal(worldserver, blockposition, flag2, event.getSearchRadius(), event.getCanCreatePortal(), event.getCreationRadius()).map((blockutil_rectangle) -> { + // CraftBukkit end +- IBlockData iblockdata = this.world.getType(this.ac); ++ IBlockData iblockdata = this.world.getBlockStateIfLoaded(this.ac); // Yatopia + EnumDirection.EnumAxis enumdirection_enumaxis; + Vec3D vec3d; + + if (iblockdata.b(BlockProperties.E)) { + enumdirection_enumaxis = (EnumDirection.EnumAxis) iblockdata.get(BlockProperties.E); + BlockUtil.Rectangle blockutil_rectangle1 = BlockUtil.a(this.ac, enumdirection_enumaxis, 21, EnumDirection.EnumAxis.Y, 21, (blockposition1) -> { +- return this.world.getType(blockposition1) == iblockdata; ++ return this.world.getBlockStateIfLoaded(blockposition1) == iblockdata; // Yatopia + }); + + vec3d = this.a(enumdirection_enumaxis, blockutil_rectangle1); +@@ -3447,6 +3460,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + } + + public boolean cl() { ++ if (!this.updateNeeded) this.chunkPosUpdateRequested = true; // Yatopia + boolean flag = this.au; + + this.au = false; +@@ -3650,7 +3664,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + for (int i2 = k; i2 < l; ++i2) { + for (int j2 = i1; j2 < j1; ++j2) { + blockposition_mutableblockposition.d(l1, i2, j2); +- Fluid fluid = this.world.getFluid(blockposition_mutableblockposition); ++ Fluid fluid = this.world.getFluidStateIfLoaded(blockposition_mutableblockposition); // Yatopia + + if (fluid.a(tag)) { + double d2 = (double) ((float) i2 + fluid.getHeight(this.world, blockposition_mutableblockposition)); +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 7b8a2332b0992c4e4b20eedacef4347dd5dc929e..89ec42a757060688c088baef3dd95280205c2a3d 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -140,6 +140,7 @@ import org.bukkit.event.entity.EntityTeleportEvent; + import org.bukkit.event.player.PlayerItemConsumeEvent; + // CraftBukkit end + ++import net.gegy1000.tictacs.NonBlockingWorldAccess; // Yatopia + + public abstract class EntityLiving extends Entity { + +@@ -396,7 +397,7 @@ public abstract class EntityLiving extends Entity { + boolean flag1 = flag && ((EntityHuman) this).abilities.isInvulnerable; + + if (this.isAlive()) { +- if (this.a((Tag) TagsFluid.WATER) && !this.world.getType(new BlockPosition(this.locX(), this.getHeadY(), this.locZ())).a(Blocks.BUBBLE_COLUMN)) { ++ if (this.a((Tag) TagsFluid.WATER) && !this.world.getBlockStateIfLoaded(new BlockPosition(this.locX(), this.getHeadY(), this.locZ())).a(Blocks.BUBBLE_COLUMN)) { // Yatopia + if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { // Paper - use OBFHELPER so it can be overridden + this.setAirTicks(this.l(this.getAirTicks())); + if (this.getAirTicks() == -this.world.purpurConfig.drowningDamageInterval) { // Purpur +@@ -489,7 +490,7 @@ public abstract class EntityLiving extends Entity { + } + + protected boolean cP() { +- return this.world.getType(this.as()).a((Tag) TagsBlock.SOUL_SPEED_BLOCKS); ++ return this.world.getBlockStateIfLoaded(this.as()).a((Tag) TagsBlock.SOUL_SPEED_BLOCKS); // Yatopia + } + + @Override +@@ -537,6 +538,8 @@ public abstract class EntityLiving extends Entity { + } + + protected void c(BlockPosition blockposition) { ++ if (!this.world.isLoaded(blockposition)) return; // Yatopia ++ + int i = EnchantmentManager.a(Enchantments.FROST_WALKER, this); + + if (i > 0) { +@@ -1604,7 +1607,7 @@ public abstract class EntityLiving extends Entity { + BlockPosition blockposition = this.getChunkCoordinates(); + IBlockData iblockdata = Blocks.WITHER_ROSE.getBlockData(); + +- if (this.world.getType(blockposition).isAir() && iblockdata.canPlace(this.world, blockposition)) { ++ if (this.world.getBlockStateIfLoaded(blockposition).isAir() && iblockdata.canPlace(this.world, blockposition)) { // Yatopia + this.world.setTypeAndData(blockposition, iblockdata, 3); + flag = true; + } +@@ -1809,12 +1812,12 @@ public abstract class EntityLiving extends Entity { + // Airplane end + + public IBlockData ds() { +- return this.world.getType(this.getChunkCoordinates()); ++ return this.world.getBlockStateIfLoaded(this.getChunkCoordinates()); // Yatopia + } + + private boolean c(BlockPosition blockposition, IBlockData iblockdata) { + if ((Boolean) iblockdata.get(BlockTrapdoor.OPEN)) { +- IBlockData iblockdata1 = this.world.getType(blockposition.down()); ++ IBlockData iblockdata1 = this.world.getBlockStateIfLoaded(blockposition.down()); // Yatopia + + if (iblockdata1.a(Blocks.LADDER) && iblockdata1.get(BlockLadder.FACING) == iblockdata.get(BlockTrapdoor.FACING)) { + return true; +@@ -1861,7 +1864,7 @@ public abstract class EntityLiving extends Entity { + int i = MathHelper.floor(this.locX()); + int j = MathHelper.floor(this.locY() - 0.20000000298023224D); + int k = MathHelper.floor(this.locZ()); +- IBlockData iblockdata = this.world.getType(new BlockPosition(i, j, k)); ++ IBlockData iblockdata = this.world.getBlockStateIfLoaded(new BlockPosition(i, j, k)); // Yatopia + + if (!iblockdata.isAir()) { + SoundEffectType soundeffecttype = iblockdata.getStepSound(); +@@ -2358,7 +2361,7 @@ public abstract class EntityLiving extends Entity { + private void a(Entity entity) { + Vec3D vec3d; + +- if (!entity.dead && !this.world.getType(entity.getChunkCoordinates()).getBlock().a((Tag) TagsBlock.PORTALS)) { ++ if (!entity.dead && !this.world.getBlockStateIfLoaded(entity.getChunkCoordinates()).getBlock().a((Tag) TagsBlock.PORTALS)) { // Yatopia + vec3d = entity.b(this); + } else { + vec3d = new Vec3D(entity.locX(), entity.locY() + (double) entity.getHeight(), entity.locZ()); +@@ -2412,7 +2415,7 @@ public abstract class EntityLiving extends Entity { + this.fallDistance = 0.0F; + } + +- Fluid fluid = this.world.getFluid(this.getChunkCoordinates()); ++ Fluid fluid = this.world.getFluidStateIfLoaded(this.getChunkCoordinates()); // Yatopia + double d1; + float f; + +@@ -2528,7 +2531,7 @@ public abstract class EntityLiving extends Entity { + } + } else { + BlockPosition blockposition = this.as(); +- float f5 = this.world.getType(blockposition).getBlock().getFrictionFactor(); ++ float f5 = this.world.getBlockStateIfLoaded(blockposition).getBlock().getFrictionFactor(); // Yatopia + + f = this.onGround ? f5 * 0.91F : 0.91F; + Vec3D vec3d6 = this.a(vec3d, f5); +@@ -3624,7 +3627,7 @@ public abstract class EntityLiving extends Entity { + + while (!flag2 && blockposition.getY() > 0) { + BlockPosition blockposition1 = blockposition.down(); +- IBlockData iblockdata = world.getType(blockposition1); ++ IBlockData iblockdata = this.world.getBlockStateIfLoaded(blockposition1); // Yatopia + + if (iblockdata.getMaterial().isSolid()) { + flag2 = true; +@@ -3736,7 +3739,7 @@ public abstract class EntityLiving extends Entity { + this.stopRiding(); + } + +- IBlockData iblockdata = this.world.getType(blockposition); ++ IBlockData iblockdata = this.world.getBlockStateIfLoaded(blockposition); // Yatopia + + if (iblockdata.getBlock() instanceof BlockBed) { + this.world.setTypeAndData(blockposition, (IBlockData) iblockdata.set(BlockBed.OCCUPIED, true), 3); +@@ -3755,7 +3758,7 @@ public abstract class EntityLiving extends Entity { + + private boolean x() { + return (Boolean) this.getBedPosition().map((blockposition) -> { +- return this.world.getType(blockposition).getBlock() instanceof BlockBed; ++ return this.world.getBlockStateIfLoaded(blockposition).getBlock() instanceof BlockBed; // Yatopia + }).orElse(false); + } + +@@ -3765,7 +3768,7 @@ public abstract class EntityLiving extends Entity { + + this.world.getClass(); + optional.filter(world::isLoaded).ifPresent((blockposition) -> { +- IBlockData iblockdata = this.world.getType(blockposition); ++ IBlockData iblockdata = this.world.getBlockStateIfLoaded(blockposition); // Yatopia + + if (iblockdata.getBlock() instanceof BlockBed) { + this.world.setTypeAndData(blockposition, (IBlockData) iblockdata.set(BlockBed.OCCUPIED, false), 3); +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index eb6c4e3a98783a0a2f0d4e988efd6e326defc29b..b058c1fa8637b947e8e4a5009258cbee75f536c3 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -97,7 +97,9 @@ import org.bukkit.craftbukkit.block.data.CraftBlockData; + import org.bukkit.event.block.BlockPhysicsEvent; + // CraftBukkit end + +-public abstract class World implements GeneratorAccess, AutoCloseable { ++import net.gegy1000.tictacs.NonBlockingWorldAccess; // Yatopia ++ ++public abstract class World implements GeneratorAccess, AutoCloseable, NonBlockingWorldAccess { // Yatopia + + protected static final Logger LOGGER = LogManager.getLogger(); + public static final Codec> f = MinecraftKey.a.xmap(ResourceKey.b(IRegistry.L), ResourceKey::a); +diff --git a/src/main/java/net/minecraft/world/level/material/FluidType.java b/src/main/java/net/minecraft/world/level/material/FluidType.java +index 6a60f53407db840150b84f4d2a709cc2e92362a4..bf3300607f9142486dc790a600d4c2ffa998d376 100644 +--- a/src/main/java/net/minecraft/world/level/material/FluidType.java ++++ b/src/main/java/net/minecraft/world/level/material/FluidType.java +@@ -38,6 +38,7 @@ public abstract class FluidType { + this.a = fluid; + } + ++ public final Fluid getFluidData() { return this.h(); } // Yatopia - OBFHELPER + public final Fluid h() { + return this.a; + } diff --git a/patches/server/remap in progress/0061-lithium-optimize-BlockPos.iterateOutwards-by-caching.patch b/patches/server/remap in progress/0061-lithium-optimize-BlockPos.iterateOutwards-by-caching.patch new file mode 100644 index 00000000..59807181 --- /dev/null +++ b/patches/server/remap in progress/0061-lithium-optimize-BlockPos.iterateOutwards-by-caching.patch @@ -0,0 +1,196 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2No2Name <50278648+2No2Name@users.noreply.github.com> +Date: Mon, 15 Feb 2021 14:58:55 -0500 +Subject: [PATCH] lithium: optimize `BlockPos.iterateOutwards` by caching + offsets + +Code taken from: https://github.com/CaffeineMC/lithium-fabric/pull/123 by 2No2Name licenced under the LGPLv3 License + +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/IterateOutwardsCache.java b/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/IterateOutwardsCache.java +new file mode 100644 +index 0000000000000000000000000000000000000000..50e9df6056f713b2f1eaf0cb4a23875e0c6c2e2c +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/IterateOutwardsCache.java +@@ -0,0 +1,72 @@ ++package me.jellysquid.mods.lithium.common.cached_blockpos_iteration; ++ ++import it.unimi.dsi.fastutil.longs.LongArrayList; ++import it.unimi.dsi.fastutil.longs.LongList; ++import net.minecraft.core.BlockPosition; ++ ++import java.util.Iterator; ++import java.util.Random; ++import java.util.concurrent.ConcurrentHashMap; ++ ++/** ++ * @author 2No2Name, original implemenation by SuperCoder7979 and Gegy1000 ++ */ ++public class IterateOutwardsCache { ++ //POS_ZERO must not be replaced with BlockPos.ORIGIN, otherwise iterateOutwards at BlockPos.ORIGIN will not use the cache ++ public static final BlockPosition POS_ZERO = new BlockPosition(0,0,0); ++ ++ ++ private final ConcurrentHashMap table; ++ private final int capacity; ++ private final Random random; ++ ++ public IterateOutwardsCache(int capacity) { ++ this.capacity = capacity; ++ this.table = new ConcurrentHashMap<>(31); ++ this.random = new Random(); ++ } ++ ++ private void fillPositionsWithIterateOutwards(LongList entry, int xRange, int yRange, int zRange) { ++ // Add all positions to the cached list ++ for (BlockPosition pos : BlockPosition.iterateOutwards(POS_ZERO, xRange, yRange, zRange)) { ++ entry.add(pos.asLong()); ++ } ++ } ++ ++ public LongList getOrCompute(int xRange, int yRange, int zRange) { ++ long key = BlockPosition.asLong(xRange, yRange, zRange); ++ ++ LongArrayList entry = this.table.get(key); ++ if (entry != null) { ++ return entry; ++ } ++ ++ // Cache miss: compute and store ++ entry = new LongArrayList(128); ++ ++ this.fillPositionsWithIterateOutwards(entry, xRange, yRange, zRange); ++ ++ //decrease the array size, as of now it won't be modified anymore anyways ++ entry.trim(); ++ ++ //this might overwrite an entry as the same entry could have been computed and added during this thread's computation ++ //we do not use computeIfAbsent, as it can delay other threads for too long ++ Object previousEntry = this.table.put(key, entry); ++ ++ ++ if (previousEntry == null && this.table.size() > this.capacity) { ++ //prevent a memory leak by randomly removing about 1/8th of the elements when the exceed the desired capacity is exceeded ++ final Iterator iterator = this.table.keySet().iterator(); ++ //prevent an unlikely infinite loop caused by another thread filling the table concurrently using counting ++ for (int i = -this.capacity; iterator.hasNext() && i < 5; i++) { ++ Long key2 = iterator.next(); ++ //random is not threadsafe, but it doesn't matter here, because we don't need quality random numbers ++ if (this.random.nextInt(8) == 0 && key2 != key) { ++ iterator.remove(); ++ } ++ } ++ } ++ ++ return entry; ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/LongList2BlockPosMutableIterable.java b/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/LongList2BlockPosMutableIterable.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e2e4f7968a399b4641df07b2931fff6dbc85ddb3 +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/LongList2BlockPosMutableIterable.java +@@ -0,0 +1,47 @@ ++package me.jellysquid.mods.lithium.common.cached_blockpos_iteration; ++ ++import it.unimi.dsi.fastutil.longs.LongIterator; ++import it.unimi.dsi.fastutil.longs.LongList; ++import net.minecraft.core.BlockPosition; ++ ++import java.util.Iterator; ++ ++/** ++ * @author 2No2Name ++ */ ++public class LongList2BlockPosMutableIterable implements Iterable { ++ ++ private final LongList positions; ++ private final int xOffset, yOffset, zOffset; ++ ++ public LongList2BlockPosMutableIterable(BlockPosition offset, LongList posList) { ++ this.xOffset = offset.getX(); ++ this.yOffset = offset.getY(); ++ this.zOffset = offset.getZ(); ++ this.positions = posList; ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return new Iterator() { ++ ++ private final LongIterator it = LongList2BlockPosMutableIterable.this.positions.iterator(); ++ private final BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(); ++ ++ @Override ++ public boolean hasNext() { ++ return it.hasNext(); ++ } ++ ++ @Override ++ public BlockPosition next() { ++ long nextPos = this.it.nextLong(); ++ return this.pos.setValues( ++ LongList2BlockPosMutableIterable.this.xOffset + BlockPosition.unpackLongX(nextPos), ++ LongList2BlockPosMutableIterable.this.yOffset + BlockPosition.unpackLongY(nextPos), ++ LongList2BlockPosMutableIterable.this.zOffset + BlockPosition.unpackLongZ(nextPos)); ++ } ++ }; ++ } ++ ++} +\ No newline at end of file +diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java +index 092de56e31257c1817a04cc9fc2f9c300bbfa058..bf2b1b19b7fa348c5fee61dd0e58144e2c06072f 100644 +--- a/src/main/java/net/minecraft/core/BlockPosition.java ++++ b/src/main/java/net/minecraft/core/BlockPosition.java +@@ -18,10 +18,16 @@ import net.minecraft.world.phys.Vec3D; + import org.apache.commons.lang3.Validate; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import me.jellysquid.mods.lithium.common.cached_blockpos_iteration.IterateOutwardsCache; // Yatopia ++import me.jellysquid.mods.lithium.common.cached_blockpos_iteration.LongList2BlockPosMutableIterable; // Yatopia ++import it.unimi.dsi.fastutil.longs.LongList; // Yatopia + + @Immutable + public class BlockPosition extends BaseBlockPosition { + ++ private static final IterateOutwardsCache ITERATE_OUTWARDS_CACHE = new IterateOutwardsCache(50); // Yatopia ++ private static final LongList HOGLIN_PIGLIN_CACHE = ITERATE_OUTWARDS_CACHE.getOrCompute(8, 4, 8); // Yatopia ++ + public static final Codec a = Codec.INT_STREAM.comapFlatMap((intstream) -> { + return SystemUtils.a(intstream, 3).map((aint) -> { + return new BlockPosition(aint[0], aint[1], aint[2]); +@@ -77,14 +83,17 @@ public class BlockPosition extends BaseBlockPosition { + return a((int) (i >> 38) + j, (int) ((i << 52) >> 52) + k, (int) ((i << 26) >> 38) + l); // Paper - simplify/inline + } + ++ public static int unpackLongX(long i) { return BlockPosition.b(i); } // Yatopia - OBFHELPER + public static int b(long i) { + return (int) (i >> 38); // Paper - simplify/inline + } + ++ public static int unpackLongY(long i) { return BlockPosition.c(i); } // Yatopia - OBFHELPER + public static int c(long i) { + return (int) ((i << 52) >> 52); // Paper - simplify/inline + } + ++ public static int unpackLongZ(long i) { return BlockPosition.d(i); } // Yatopia - OBFHELPER + public static int d(long i) { + return (int) ((i << 26) >> 38); // Paper - simplify/inline + } +@@ -265,7 +274,15 @@ public class BlockPosition extends BaseBlockPosition { + }; + } + ++ public static Iterable iterateOutwards(BlockPosition blockposition, int p_i, int p_j, int p_k) { return BlockPosition.a(blockposition, p_i, p_j, p_k); } // Yatopia - OBFHELPER + public static Iterable a(BlockPosition blockposition, int p_i, int p_j, int p_k) { // Paper - decompile issues - variable name conflicts to inner class field refs ++ // Yatopia start - lithium: optimize `BlockPos.iterateOutwards` by caching offsets ++ if (blockposition != me.jellysquid.mods.lithium.common.cached_blockpos_iteration.IterateOutwardsCache.POS_ZERO) { ++ final LongList positions = p_i == 8 && p_j == 4 && p_k == 8 ? HOGLIN_PIGLIN_CACHE : ITERATE_OUTWARDS_CACHE.getOrCompute(p_i, p_j, p_j); ++ return new LongList2BlockPosMutableIterable(blockposition, positions); ++ } ++ // Yatopia end ++ + int l_decompiled = p_i + p_j + p_k; // Paper - decompile issues + int i1 = blockposition.getX(); + int j1 = blockposition.getY(); diff --git a/patches/server/remap in progress/0062-lithium-block.patch b/patches/server/remap in progress/0062-lithium-block.patch new file mode 100644 index 00000000..f9aaddd7 --- /dev/null +++ b/patches/server/remap in progress/0062-lithium-block.patch @@ -0,0 +1,232 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Sun, 24 Jan 2021 16:57:03 +0100 +Subject: [PATCH] lithium block + +Co-authored-by: Hugo Planque + +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/tuples/FinalObject.java b/src/main/java/me/jellysquid/mods/lithium/common/util/tuples/FinalObject.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f78927e71258e859154cca8ba78d17130b0d82c1 +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/util/tuples/FinalObject.java +@@ -0,0 +1,20 @@ ++package me.jellysquid.mods.lithium.common.util.tuples; ++ ++/** ++ * The purpose of this class is safe publication of the wrapped value. (JLS 17.5) ++ */ ++public class FinalObject { ++ private final T value; ++ ++ public FinalObject(T value) { ++ this.value = value; ++ } ++ ++ public FinalObject of(T value) { ++ return new FinalObject<>(value); ++ } ++ ++ public T getValue() { ++ return value; ++ } ++} +diff --git a/src/main/java/net/minecraft/core/EnumDirection.java b/src/main/java/net/minecraft/core/EnumDirection.java +index b8fe75b8c37ef1968519e69e078444b1a3c5c359..a825b17e454138e181926df3f2faa6d9d7af4055 100644 +--- a/src/main/java/net/minecraft/core/EnumDirection.java ++++ b/src/main/java/net/minecraft/core/EnumDirection.java +@@ -100,6 +100,7 @@ public enum EnumDirection implements INamable { + return new EnumDirection[]{enumdirection, enumdirection1, enumdirection2, enumdirection2.opposite(), enumdirection1.opposite(), enumdirection.opposite()}; + } + ++ public int get3DDataValue(){ return c(); } // Yatopia - OBFHELPER + public int c() { + return this.g; + } +diff --git a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java +index 58c7a52612fe0f5c1e4ddacc0bf93cd81f1286b8..af2a8fdcaf5962334dcc20717f3a1ad14aebcbcb 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java +@@ -29,9 +29,9 @@ import net.minecraft.world.phys.shapes.VoxelShapes; + public class TileEntityPiston extends TileEntity implements ITickable { + + private IBlockData a; +- private EnumDirection b; +- private boolean c; +- private boolean g; ++ private EnumDirection b; public EnumDirection getFacing() { return b; } // Yatopia - OBFHELPER ++ private boolean c; public boolean isExtending() { return c; } // Yatopia - OBFHELPER ++ private boolean g; public boolean isSource() { return g; } // Yatopia - OBFHELPER + private static final ThreadLocal h = ThreadLocal.withInitial(() -> { + return null; + }); +@@ -40,6 +40,74 @@ public class TileEntityPiston extends TileEntity implements ITickable { + private long k; + private int l; + ++ // Yatopia start - Port Lithium ++ private static final VoxelShape[] PISTON_BASE_WITH_MOVING_HEAD_SHAPES = precomputePistonBaseWithMovingHeadShapes(); ++ /** ++ * We cache the offset and simplified VoxelShapes that are otherwise constructed on every call of getCollisionShape. ++ * For each offset direction and distance (6 directions, 2 distances each, and no direction with 0 distance) we ++ * store the offset and simplified VoxelShapes in the original VoxelShape when they are accessed the first time. ++ * We use safe publication, because both the Render and Server thread are using the cache. ++ * ++ * @param blockShape the original shape, must not be modified after passing it as an argument to this method ++ * @param offset the offset distance ++ * @param direction the offset direction ++ * @return blockShape offset and simplified ++ */ ++ private static VoxelShape getOffsetAndSimplified(VoxelShape blockShape, float offset, EnumDirection direction) { ++ VoxelShape offsetSimplifiedShape = blockShape.getOffsetSimplifiedShape(offset, direction); ++ if (offsetSimplifiedShape == null) { ++ //create the offset shape and store it for later use ++ offsetSimplifiedShape = blockShape.offset(direction.getAdjacentX() * offset, direction.getAdjacentY() * offset, direction.getAdjacentZ() * offset).simplify(); ++ blockShape.setShape(offset, direction, offsetSimplifiedShape); ++ } ++ return offsetSimplifiedShape; ++ } ++ ++ /** ++ * Precompute all 18 possible configurations for the merged piston base and head shape. ++ * ++ * @return The array of the merged VoxelShapes, indexed by {@link TileEntityPiston#getIndexForMergedShape(float, EnumDirection)} ++ */ ++ private static VoxelShape[] precomputePistonBaseWithMovingHeadShapes() { ++ float[] offsets = {0f, 0.5f, 1f}; ++ EnumDirection[] directions = EnumDirection.values(); ++ ++ VoxelShape[] mergedShapes = new VoxelShape[offsets.length * directions.length]; ++ ++ for (EnumDirection facing : directions) { ++ VoxelShape baseShape = Blocks.PISTON.getBlockData().set(BlockPiston.EXTENDED, true) ++ .set(BlockPiston.FACING, facing).getCollisionShape(null, null); ++ for (float offset : offsets) { ++ //this cache is only required for the merged piston head + base shape. ++ //this shape is only used when !this.extending ++ //here: isShort = this.extending != 1.0F - this.progress < 0.25F can be simplified to: ++ //isShort = f < 0.25F , because f = getAmountExtended(this.progress) can be simplified to f == 1.0F - this.progress ++ //therefore isShort is dependent on the offset: ++ boolean isShort = offset < 0.25f; ++ ++ VoxelShape headShape = (Blocks.PISTON_HEAD.getBlockData().set(BlockPistonExtension.FACING, facing)) ++ .set(BlockPistonExtension.SHORT, isShort).getCollisionShape(null, null); ++ ++ VoxelShape offsetHead = headShape.offset(facing.getAdjacentX() * offset, ++ facing.getAdjacentY() * offset, ++ facing.getAdjacentZ() * offset); ++ mergedShapes[getIndexForMergedShape(offset, facing)] = VoxelShapes.union(baseShape, offsetHead); ++ } ++ ++ } ++ ++ return mergedShapes; ++ } ++ ++ private static int getIndexForMergedShape(float offset, EnumDirection direction) { ++ if (offset != 0f && offset != 0.5f && offset != 1f) { ++ return -1; ++ } ++ //shape of offset 0 is still dependent on the direction, due to piston head and base being directional blocks ++ return (int) (2 * offset) + (3 * direction.get3DDataValue()); ++ } ++ // Yatopia End ++ + public TileEntityPiston() { + super(TileEntityTypes.PISTON); + } +@@ -350,13 +418,21 @@ public class TileEntityPiston extends TileEntity implements ITickable { + } else { + iblockdata = this.a; + } ++ float f = this.e(this.i); // Yatopia Start - Port Lithium ++ if (this.isExtending() || !this.isSource()) { ++ //here voxelShape2.isEmpty() is guaranteed, vanilla code would call union() which calls simplify() ++ VoxelShape blockShape = iblockdata.getCollisionShape(iblockaccess, blockposition); ++ ++ //we cache the simplified shapes, as the simplify() method costs a lot of CPU time and allocates several objects ++ VoxelShape offsetAndSimplified = getOffsetAndSimplified(blockShape, Math.abs(f), f < 0f ? this.getFacing().opposite() : this.getFacing()); ++ return offsetAndSimplified; ++ } else { ++ //retracting piston heads have to act like their base as well, as the base block is replaced with the moving block ++ //f >= 0f is guaranteed (assuming no other mod interferes) ++ int index = getIndexForMergedShape(f, this.getFacing()); ++ return PISTON_BASE_WITH_MOVING_HEAD_SHAPES[index]; ++ } // Yatopia End + +- float f = this.e(this.i); +- double d0 = (double) ((float) this.b.getAdjacentX() * f); +- double d1 = (double) ((float) this.b.getAdjacentY() * f); +- double d2 = (double) ((float) this.b.getAdjacentZ() * f); +- +- return VoxelShapes.a(voxelshape, iblockdata.getCollisionShape(iblockaccess, blockposition).a(d0, d1, d2)); + } + } + +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java +index 9567630593da7c77a0173b93c9a57ceb7887a59b..fbc5fab9946b6f9233f3014f0e69f2576b2138d7 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java +@@ -13,9 +13,50 @@ import net.minecraft.util.MathHelper; + import net.minecraft.world.phys.AxisAlignedBB; + import net.minecraft.world.phys.MovingObjectPositionBlock; + import net.minecraft.world.phys.Vec3D; ++import me.jellysquid.mods.lithium.common.util.tuples.FinalObject; // Yatopia + + public abstract class VoxelShape { + ++ // Yatopia - Port Lithium ++ private FinalObject[] offsetAndSimplified; ++ ++ public void setShape(float offset, EnumDirection direction, VoxelShape offsetShape) { ++ if (offsetShape == null) { ++ throw new IllegalArgumentException("offsetShape must not be null!"); ++ } ++ int index = getIndexForOffsetSimplifiedShapes(offset, direction); ++ FinalObject[] offsetAndSimplified = this.offsetAndSimplified; ++ if (offsetAndSimplified == null) { ++ //noinspection unchecked ++ this.offsetAndSimplified = (offsetAndSimplified = new FinalObject[1 + (2 * 6)]); ++ } ++ //using FinalObject as it stores the value in a final field, which guarantees safe publication ++ offsetAndSimplified[index] = new FinalObject<>(offsetShape); ++ } ++ ++ public VoxelShape getOffsetSimplifiedShape(float offset, EnumDirection direction) { ++ FinalObject[] offsetAndSimplified = this.offsetAndSimplified; ++ if (offsetAndSimplified == null) { ++ return null; ++ } ++ int index = getIndexForOffsetSimplifiedShapes(offset, direction); ++ //usage of FinalObject guarantees that we are seeing a fully initialized VoxelShape here, even when it was created on a different thread ++ FinalObject wrappedShape = offsetAndSimplified[index]; ++ //noinspection FinalObjectAssignedToNull,FinalObjectGetWithoutIsPresent ++ return wrappedShape == null ? null : wrappedShape.getValue(); ++ } ++ ++ private static int getIndexForOffsetSimplifiedShapes(float offset, EnumDirection direction) { ++ if (offset != 0f && offset != 0.5f && offset != 1f) { ++ throw new IllegalArgumentException("offset must be one of {0f, 0.5f, 1f}"); ++ } ++ if (offset == 0f) { ++ return 0; //can treat offsetting by 0 in all directions the same ++ } ++ return (int) (2 * offset) + 2 * direction.get3DDataValue(); ++ } ++ // Yatopia End ++ + protected final VoxelShapeDiscrete a; public final VoxelShapeDiscrete getShape() { return this.a; } // Tuinity - OBFHELPER + @Nullable + private VoxelShape[] b; +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +index 98e787e6383a39de1708428137fd7f9e057ff153..049aa5f51e7517744b25f8c2c4b5e7a7de24a73e 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +@@ -187,6 +187,7 @@ public final class VoxelShapes { + return (long) i * (long) (j / IntMath.gcd(i, j)); + } + ++ public static VoxelShape union(VoxelShape voxelshape, VoxelShape voxelshape1) { return a(voxelshape, voxelshape1); } // Yatopia - OBFHELPER + public static VoxelShape a(VoxelShape voxelshape, VoxelShape voxelshape1) { + return a(voxelshape, voxelshape1, OperatorBoolean.OR); + } diff --git a/patches/server/remap in progress/0063-lithium-entity.patch b/patches/server/remap in progress/0063-lithium-entity.patch new file mode 100644 index 00000000..15b913a0 --- /dev/null +++ b/patches/server/remap in progress/0063-lithium-entity.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Sun, 24 Jan 2021 22:55:55 +0100 +Subject: [PATCH] lithium entity + +Co-authored-by: Hugo Planque + +diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +index 89ec42a757060688c088baef3dd95280205c2a3d..583657316fd404d2373b4777fe26a0f4d081100a 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java ++++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java +@@ -282,6 +282,9 @@ public abstract class EntityLiving extends Entity { + this.shouldBurnInDay = false; // Purpur + } + ++ private IBlockData lastStateAtFeet = null; ++ ++ private long lastPos = Long.MIN_VALUE; + protected void initAttributes() {} // Purpur + + public BehaviorController getBehaviorController() { +@@ -358,6 +361,10 @@ public abstract class EntityLiving extends Entity { + + @Override + public void entityBaseTick() { ++ // Yatopia start - port lithium ++ this.lastStateAtFeet = null; ++ this.lastPos = Long.MIN_VALUE; ++ // Yatopia end + this.ar = this.as; + if (this.justCreated) { + this.getBedPosition().ifPresent(this::a); +@@ -1812,7 +1819,24 @@ public abstract class EntityLiving extends Entity { + // Airplane end + + public IBlockData ds() { +- return this.world.getBlockStateIfLoaded(this.getChunkCoordinates()); // Yatopia ++ // Yatopia start - port lithium ++ int x = MathHelper.floor(this.locX()); ++ int y = MathHelper.floor(this.locY()); ++ int z = MathHelper.floor(this.locZ()); ++ ++ long pos = getChunkCoordinates().asLong(); ++ ++ if (this.lastPos == pos) { ++ return this.lastStateAtFeet; ++ } ++ ++ IBlockData state = this.world.getBlockStateIfLoaded(this.getChunkCoordinates()); ++ ++ this.lastPos = pos; ++ this.lastStateAtFeet = state; ++ ++ return state; ++ // Yatopia end + } + + private boolean c(BlockPosition blockposition, IBlockData iblockdata) { diff --git a/patches/server/remap in progress/0064-lithium-shape.patch b/patches/server/remap in progress/0064-lithium-shape.patch new file mode 100644 index 00000000..4bf582a3 --- /dev/null +++ b/patches/server/remap in progress/0064-lithium-shape.patch @@ -0,0 +1,358 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Wed, 27 Jan 2021 21:05:05 +0100 +Subject: [PATCH] lithium shape + +Co-authored-by: Hugo Planque + +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/block/LithiumEntityShapeContext.java b/src/main/java/me/jellysquid/mods/lithium/common/block/LithiumEntityShapeContext.java +new file mode 100644 +index 0000000000000000000000000000000000000000..85d55d144a38a16d0f148a29cd11985d7febe880 +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/block/LithiumEntityShapeContext.java +@@ -0,0 +1,55 @@ ++package me.jellysquid.mods.lithium.common.block; ++ ++import net.minecraft.core.BlockPosition; ++import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.EntityLiving; ++import net.minecraft.core.EnumDirection; ++import net.minecraft.world.level.material.Fluid; ++import net.minecraft.world.level.material.FluidTypeFlowing; ++import net.minecraft.world.item.Item; ++import net.minecraft.world.item.Items; ++import net.minecraft.world.phys.shapes.VoxelShape; ++import net.minecraft.world.phys.shapes.VoxelShapeCollision; ++ ++/** ++ * A replacement for EntityShapeContext that does not calculate the heldItem on construction. As most instances never ++ * use this field, a lazy evaluation is faster on average. The initialization of the heldItem field takes about 1% of ++ * the server thread CPU time in a fresh world with lots of animals (singleplayer 1.16.5, renderdistance 24). ++ * ++ * @author 2No2Name ++ */ ++public class LithiumEntityShapeContext implements VoxelShapeCollision { ++ private final Entity entity; ++ private final boolean descending; ++ private final double minY; ++ private Item heldItem; ++ ++ public LithiumEntityShapeContext(Entity entity) { ++ this.entity = entity; ++ this.descending = entity.isDescending(); ++ this.minY = entity.locY(); ++ } ++ ++ @Override ++ public boolean a(Item item) { ++ if (this.heldItem == null) { ++ this.heldItem = entity instanceof EntityLiving ? ((EntityLiving)entity).getItemInMainHand().getItem() : Items.AIR; ++ } ++ return this.heldItem == item; ++ } ++ ++ @Override ++ public boolean a(Fluid aboveState, FluidTypeFlowing fluid) { ++ return this.entity instanceof EntityLiving && ((EntityLiving) this.entity).a(fluid) && !aboveState.getType().a(fluid); ++ } ++ ++ @Override ++ public boolean b() { ++ return this.descending; ++ } ++ ++ @Override ++ public boolean a(VoxelShape shape, BlockPosition pos, boolean defaultValue) { ++ return this.minY > (double)pos.getY() + shape.getMax(EnumDirection.EnumAxis.Y) - 9.999999747378752E-6D; ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/shapes/pairs/LithiumDoublePairList.java b/src/main/java/me/jellysquid/mods/lithium/common/shapes/pairs/LithiumDoublePairList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..bfa06e714050260779fc8727b4b2cabb6f811398 +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/shapes/pairs/LithiumDoublePairList.java +@@ -0,0 +1,117 @@ ++package me.jellysquid.mods.lithium.common.shapes.pairs; ++ ++import it.unimi.dsi.fastutil.doubles.DoubleArrayList; ++import it.unimi.dsi.fastutil.doubles.DoubleList; ++import net.minecraft.world.phys.shapes.VoxelShapeMerger; ++ ++/** ++ * Optimized variant of {@link net.minecraft.util.shape.SimplePairList}. This implementation works directly against ++ * flat arrays and tries to organize code in a manner that hits the JIT's happy path. In my testing, this is about ++ * ~50% faster than the vanilla implementation. ++ */ ++public final class LithiumDoublePairList implements VoxelShapeMerger { ++ private final double[] merged; ++ private final int[] indicesFirst; ++ private final int[] indicesSecond; ++ ++ private final DoubleArrayList pairs; ++ ++ public LithiumDoublePairList(DoubleList aPoints, DoubleList bPoints, boolean flag1, boolean flag2) { ++ int size = aPoints.size() + bPoints.size(); ++ ++ this.merged = new double[size]; ++ this.indicesFirst = new int[size]; ++ this.indicesSecond = new int[size]; ++ ++ this.pairs = DoubleArrayList.wrap(this.merged); ++ ++ this.merge(getArray(aPoints), getArray(bPoints), aPoints.size(), bPoints.size(), flag1, flag2); ++ } ++ ++ private void merge(double[] aPoints, double[] bPoints, int aSize, int bSize, boolean flag1, boolean flag2) { ++ int aIdx = 0; ++ int bIdx = 0; ++ ++ double prev = 0.0D; ++ ++ int a1 = 0, a2 = 0; ++ ++ while (true) { ++ boolean aWithinBounds = aIdx < aSize; ++ boolean bWithinBounds = bIdx < bSize; ++ ++ if (!aWithinBounds && !bWithinBounds) { ++ break; ++ } ++ ++ boolean flip = aWithinBounds && (!bWithinBounds || aPoints[aIdx] < bPoints[bIdx] + 1.0E-7D); ++ ++ double value; ++ ++ if (flip) { ++ value = aPoints[aIdx++]; ++ } else { ++ value = bPoints[bIdx++]; ++ } ++ ++ if ((aIdx == 0 || !aWithinBounds) && !flip && !flag2) { ++ continue; ++ } ++ ++ if ((bIdx == 0 || !bWithinBounds) && flip && !flag1) { ++ continue; ++ } ++ ++ if (a2 == 0 || prev < value - 1.0E-7D) { ++ this.indicesFirst[a1] = aIdx - 1; ++ this.indicesSecond[a1] = bIdx - 1; ++ this.merged[a2] = value; ++ ++ a1++; ++ a2++; ++ prev = value; ++ } else if (a2 > 0) { ++ this.indicesFirst[a1 - 1] = aIdx - 1; ++ this.indicesSecond[a1 - 1] = bIdx - 1; ++ } ++ } ++ ++ if (a2 == 0) { ++ this.merged[a2++] = Math.min(aPoints[aSize - 1], bPoints[bSize - 1]); ++ } ++ ++ this.pairs.size(a2); ++ } ++ ++ @Override ++ public boolean a(VoxelShapeMerger.a predicate) { ++ int l = this.pairs.size() - 1; ++ ++ for (int i = 0; i < l; i++) { ++ if (!predicate.merge(this.indicesFirst[i], this.indicesSecond[i], i)) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ ++ @Override ++ public DoubleList a() { ++ return this.pairs; ++ } ++ ++ private static double[] getArray(DoubleList list) { ++ if (list instanceof DoubleArrayList) { ++ return ((DoubleArrayList) list).elements(); ++ } ++ ++ double[] points = new double[list.size()]; ++ ++ for (int i = 0; i < points.length; i++) { ++ points[i] = list.getDouble(i); ++ } ++ ++ return points; ++ } ++} +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/collections/Object2BooleanCacheTable.java b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/Object2BooleanCacheTable.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e210e0fa39b74805429832c3d232fadb33975414 +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/Object2BooleanCacheTable.java +@@ -0,0 +1,61 @@ ++package me.jellysquid.mods.lithium.common.util.collections; ++ ++import it.unimi.dsi.fastutil.HashCommon; ++import net.minecraft.util.MathHelper; ++ ++import java.util.function.Predicate; ++ ++/** ++ * A lossy hashtable implementation that stores a mapping between an object and a boolean. ++ *

++ * Any hash collisions will result in an overwrite: this is safe because the correct value can always be recomputed, ++ * given that the given operator is deterministic. ++ *

++ * This implementation is safe to use from multiple threads ++ */ ++public final class Object2BooleanCacheTable { ++ private final int capacity; ++ private final int mask; ++ ++ private final Node[] nodes; ++ ++ private final Predicate operator; ++ ++ @SuppressWarnings("unchecked") ++ public Object2BooleanCacheTable(int capacity, Predicate operator) { ++ this.capacity = MathHelper.smallestEncompassingPowerOfTwo(capacity); ++ this.mask = this.capacity - 1; ++ ++ this.nodes = (Node[]) new Node[this.capacity]; ++ ++ this.operator = operator; ++ } ++ ++ private static int hash(T key) { ++ return HashCommon.mix(key.hashCode()); ++ } ++ ++ public boolean get(T key) { ++ int idx = hash(key) & this.mask; ++ ++ Node node = this.nodes[idx]; ++ if (node != null && key.equals(node.key)) { ++ return node.value; ++ } ++ ++ boolean test = this.operator.test(key); ++ this.nodes[idx] = new Node<>(key, test); ++ ++ return test; ++ } ++ ++ static class Node { ++ final T key; ++ final boolean value; ++ ++ Node(T key, boolean value) { ++ this.key = key; ++ this.value = value; ++ } ++ } ++} +diff --git a/src/main/java/net/minecraft/util/MathHelper.java b/src/main/java/net/minecraft/util/MathHelper.java +index b95115aca72ba0cf6451096ddbd8b50a8f3bb5c6..0afb8c643cb3e5938e12183c6132797d6ed645bb 100644 +--- a/src/main/java/net/minecraft/util/MathHelper.java ++++ b/src/main/java/net/minecraft/util/MathHelper.java +@@ -198,6 +198,7 @@ public class MathHelper { + return c(f, f + f3, f2); + } + ++ public static int smallestEncompassingPowerOfTwo(int i){ return c(i); } // Yatopia - OBFHELPER + public static int c(int i) { + int j = i - 1; + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 2ed54208faf35ea5b4ea8540e95886b56d4d11fe..4b64a8f7ca507a54871c3b4929e663a60897870d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -2676,6 +2676,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne + return this.isSneaking(); + } + ++ public boolean isDescending() { return by(); } // Yatopia - OBFHELPER + public boolean by() { + return this.isSneaking(); + } +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index a835285d230ea0dffa1b28c2a7a006041f2e6b2a..ccb35c1ddbf83a7e644f88ed17b8881ff305685a 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -54,6 +54,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.phys.shapes.VoxelShapes; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import me.jellysquid.mods.lithium.common.util.collections.Object2BooleanCacheTable; + + public class Block extends BlockBase implements IMaterial { + +@@ -216,8 +217,14 @@ public class Block extends BlockBase implements IMaterial { + return a(voxelshape1); + } + ++ // Yatopia start - Port lithium ++ private static final Object2BooleanCacheTable FULL_CUBE_CACHE = new Object2BooleanCacheTable<>( ++ 512, ++ shape -> !VoxelShapes.applyOperation(VoxelShapes.fullCube(), shape, OperatorBoolean.NOT_SAME) ++ ); ++ + public static boolean a(VoxelShape voxelshape) { +- return (Boolean) Block.a.getUnchecked(voxelshape); ++ return FULL_CUBE_CACHE.get(voxelshape); // Yatopia end + } + + public boolean b(IBlockData iblockdata, IBlockAccess iblockaccess, BlockPosition blockposition) { +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java +index fbc5fab9946b6f9233f3014f0e69f2576b2138d7..012892063405616c8ae35b6e06020008dfd147df 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java +@@ -71,6 +71,7 @@ public abstract class VoxelShape { + return i >= this.a.c(enumdirection_enumaxis) ? Double.POSITIVE_INFINITY : this.a(enumdirection_enumaxis, i); + } + ++ public double getMax(EnumDirection.EnumAxis enumdirection_enumaxis) { return c(enumdirection_enumaxis); } // Yatopia - OBFHELPER + public double c(EnumDirection.EnumAxis enumdirection_enumaxis) { + int i = this.a.b(enumdirection_enumaxis); + +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMerger.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMerger.java +index d2a46ce0c5c980d34dc2f4b716a174a81a68f1d0..0c594866cb291abb2e90b149d52445a628331879 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMerger.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMerger.java +@@ -2,7 +2,7 @@ package net.minecraft.world.phys.shapes; + + import it.unimi.dsi.fastutil.doubles.DoubleList; + +-interface VoxelShapeMerger { ++public interface VoxelShapeMerger { // Yatopia - make Public + + DoubleList a(); + +diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +index 049aa5f51e7517744b25f8c2c4b5e7a7de24a73e..173197e9dc6acb31aa41ce645224fd9a2733f27c 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java +@@ -5,6 +5,8 @@ import com.google.common.math.DoubleMath; + import com.google.common.math.IntMath; + import it.unimi.dsi.fastutil.doubles.DoubleArrayList; + import it.unimi.dsi.fastutil.doubles.DoubleList; ++import me.jellysquid.mods.lithium.common.shapes.pairs.LithiumDoublePairList; // Yatopia ++ + import java.util.Arrays; + import java.util.Iterator; + import java.util.Objects; +@@ -476,7 +478,7 @@ public final class VoxelShapes { + // doublelist is usually a DoubleArrayList with Infinite head/tails that falls to the final else clause + // This is actually the most common path, so jump to it straight away + if (doublelist.getDouble(0) == Double.NEGATIVE_INFINITY && doublelist.getDouble(doublelist.size() - 1) == Double.POSITIVE_INFINITY) { +- return new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1); ++ return new LithiumDoublePairList(doublelist, doublelist1, flag, flag1); // Yatopia - Port lithium + } + // Split out rest to hopefully inline the above + return lessCommonMerge(i, doublelist, doublelist1, flag, flag1); diff --git a/patches/server/remap in progress/0065-lithium-skip-ticking-block-entities-that-are-doing-n.patch b/patches/server/remap in progress/0065-lithium-skip-ticking-block-entities-that-are-doing-n.patch new file mode 100644 index 00000000..3510429a --- /dev/null +++ b/patches/server/remap in progress/0065-lithium-skip-ticking-block-entities-that-are-doing-n.patch @@ -0,0 +1,1217 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 2No2Name <50278648+2No2Name@users.noreply.github.com> +Date: Sun, 21 Feb 2021 21:34:18 -0500 +Subject: [PATCH] lithium: skip ticking block entities that are doing nothing + + +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/collections/ListeningList.java b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/ListeningList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..edcc9ec27cc7d8dc5bf04e1f70362b505742570c +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/ListeningList.java +@@ -0,0 +1,255 @@ ++package me.jellysquid.mods.lithium.common.util.collections; ++ ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.*; ++import java.util.function.Consumer; ++import java.util.function.Predicate; ++import java.util.function.UnaryOperator; ++import java.util.stream.Stream; ++ ++public class ListeningList implements List { ++ private final List delegate; ++ private final Runnable changeCallback; ++ ++ public ListeningList(List delegate, Runnable changeCallback) { ++ this.delegate = delegate; ++ this.changeCallback = changeCallback; ++ } ++ ++ private void onChange() { ++ this.changeCallback.run(); ++ } ++ ++ ++ @Override ++ public int size() { ++ return this.delegate.size(); ++ } ++ ++ @Override ++ public boolean isEmpty() { ++ return this.delegate.isEmpty(); ++ } ++ ++ @Override ++ public boolean contains(Object o) { ++ return this.delegate.contains(o); ++ } ++ ++ @NotNull ++ @Override ++ public Iterator iterator() { ++ return this.listIterator(); ++ } ++ ++ @NotNull ++ @Override ++ public Object[] toArray() { ++ return this.delegate.toArray(); ++ } ++ ++ @Override ++ public void forEach(Consumer consumer) { ++ this.delegate.forEach(consumer); ++ } ++ ++ @NotNull ++ @Override ++ public T1[] toArray(@NotNull T1[] t1s) { ++ //noinspection SuspiciousToArrayCall ++ return this.delegate.toArray(t1s); ++ } ++ ++ @Override ++ public boolean add(T t) { ++ boolean add = this.delegate.add(t); ++ this.onChange(); ++ //noinspection ConstantConditions ++ return add; ++ } ++ ++ @Override ++ public boolean remove(Object o) { ++ boolean remove = this.delegate.remove(o); ++ this.onChange(); ++ return remove; ++ } ++ ++ @Override ++ public boolean containsAll(@NotNull Collection collection) { ++ return this.delegate.containsAll(collection); ++ } ++ ++ @Override ++ public boolean addAll(@NotNull Collection collection) { ++ boolean addAll = this.delegate.addAll(collection); ++ this.onChange(); ++ return addAll; ++ } ++ ++ @Override ++ public boolean addAll(int i, @NotNull Collection collection) { ++ boolean addAll = this.delegate.addAll(i, collection); ++ this.onChange(); ++ return addAll; ++ } ++ ++ @Override ++ public boolean removeAll(@NotNull Collection collection) { ++ boolean b = this.delegate.removeAll(collection); ++ this.onChange(); ++ return b; ++ } ++ ++ @Override ++ public boolean removeIf(Predicate predicate) { ++ boolean b = this.delegate.removeIf(predicate); ++ this.onChange(); ++ return b; ++ } ++ ++ @Override ++ public boolean retainAll(@NotNull Collection collection) { ++ boolean b = this.delegate.retainAll(collection); ++ this.onChange(); ++ return b; ++ } ++ ++ @Override ++ public void replaceAll(UnaryOperator unaryOperator) { ++ this.delegate.replaceAll( unaryOperator); ++ this.onChange(); ++ } ++ ++ @Override ++ public void sort(Comparator comparator) { ++ this.delegate.sort(comparator); ++ this.onChange(); ++ } ++ ++ @Override ++ public void clear() { ++ this.delegate.clear(); ++ this.onChange(); ++ } ++ ++ @Override ++ public T get(int i) { ++ return this.delegate.get(i); ++ } ++ ++ @Override ++ public T set(int i, T t) { ++ T set = this.delegate.set(i, t); ++ this.onChange(); ++ return set; ++ } ++ ++ @Override ++ public void add(int i, T t) { ++ this.delegate.add(i, t); ++ this.onChange(); ++ } ++ ++ @Override ++ public T remove(int i) { ++ T remove = this.delegate.remove(i); ++ this.onChange(); ++ return remove; ++ } ++ ++ @Override ++ public int indexOf(Object o) { ++ return this.delegate.indexOf(o); ++ } ++ ++ @Override ++ public int lastIndexOf(Object o) { ++ return this.delegate.lastIndexOf(o); ++ } ++ ++ @NotNull ++ @Override ++ public ListIterator listIterator() { ++ return this.listIterator(0); ++ } ++ ++ @NotNull ++ @Override ++ public ListIterator listIterator(int i) { ++ return new ListIterator() { ++ final ListIterator itDelegate = ListeningList.this.delegate.listIterator(i); ++ ++ @Override ++ public boolean hasNext() { ++ return this.itDelegate.hasNext(); ++ } ++ ++ @Override ++ public T next() { ++ return this.itDelegate.next(); ++ } ++ ++ @Override ++ public boolean hasPrevious() { ++ return this.itDelegate.hasPrevious(); ++ } ++ ++ @Override ++ public T previous() { ++ return this.itDelegate.previous(); ++ } ++ ++ @Override ++ public int nextIndex() { ++ return this.itDelegate.nextIndex(); ++ } ++ ++ @Override ++ public int previousIndex() { ++ return this.itDelegate.previousIndex(); ++ } ++ ++ @Override ++ public void remove() { ++ this.itDelegate.remove(); ++ ListeningList.this.onChange(); ++ } ++ ++ @Override ++ public void set(T t) { ++ this.itDelegate.set(t); ++ ListeningList.this.onChange(); ++ ++ } ++ ++ @Override ++ public void add(T t) { ++ this.itDelegate.add(t); ++ ListeningList.this.onChange(); ++ } ++ }; ++ } ++ ++ @NotNull ++ @Override ++ public List subList(int i, int i1) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public Spliterator spliterator() { ++ return this.delegate.spliterator(); ++ } ++ ++ @Override ++ public Stream stream() { ++ return this.delegate.stream(); ++ } ++ ++ @Override ++ public Stream parallelStream() { ++ return this.delegate.parallelStream(); ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/collections/MaskedTickingBlockEntityList.java b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/MaskedTickingBlockEntityList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7f7e4810a9aca382d75862e56b0cf93157b54b92 +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/MaskedTickingBlockEntityList.java +@@ -0,0 +1,320 @@ ++package me.jellysquid.mods.lithium.common.util.collections; ++ ++import com.google.common.collect.Iterators; ++import it.unimi.dsi.fastutil.ints.IntArrayList; ++import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ReferenceArrayList; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.*; ++import java.util.function.Predicate; ++ ++public class MaskedTickingBlockEntityList implements List { ++ private final Predicate mayContain; ++ ++ private final Reference2IntOpenHashMap allElements2Index; ++ private final ReferenceArrayList allElements; ++ ++ private final IntArrayList filteredSuccessor; ++ private final BitSet filteredElementsMask; ++ ++ private int firstRemovedIndex; ++ ++ //Visualization of the internal datastructures ++ //indices: 0 1 2 3 4 5 6 7 8 9 ++ //allElements: A B C D - F G H I J //E was fully removed, C,F,G,I were filtered away ++ //filteredMask: 1 1 0 1 0 0 0 1 0 1 ++ //successor: 0 1 3 - 7 - - - 9 - - (index offset by 1, due to the first successor having to point to the first element) ++ //Removals from the allElements ArrayList are done by setting the value to null ++ //The successor list is used to iterate through the allElements ArrayList with an increasing index, but skipping long chains of null elements. ++ //The BitSet mask is used to find the predecessor and successor quickly (not asymptotically fast, but fast enough) ++ ++ public MaskedTickingBlockEntityList(List list, Predicate mayContain) { ++ this.mayContain = mayContain; ++ this.allElements = new ReferenceArrayList<>(); ++ this.allElements2Index = new Reference2IntOpenHashMap<>(); ++ this.allElements2Index.defaultReturnValue(-1); ++ this.filteredSuccessor = new IntArrayList(); ++ this.filteredElementsMask = new BitSet(); ++ this.firstRemovedIndex = Integer.MAX_VALUE; ++ ++ for (T t : list) { ++ if (this.mayContain.test(t)) { ++ int index = this.allElements.size(); ++ this.allElements.add(t); ++ this.filteredElementsMask.set(index); ++ this.filteredSuccessor.add(index); ++ this.allElements2Index.put(t, index); ++ } ++ } ++ this.filteredSuccessor.add(-1); ++ } ++ ++ public void setEntryVisible(T t, boolean value) { ++ this.setEntryVisible(this.allElements2Index.getOrDefault(t, -1), value); ++ } ++ ++ public void setEntryVisible(int index, boolean value) { ++ //Visualization of the operations possible ++ //All: A B C D - F G H I J (- for null) ++ //filteredMask:1 1 0 1 0 0 0 1 0 1 ++ //indices: 0 1 2 3 4 5 6 7 8 9 ++ //successor: 0 1 3 - 7 - - - 9 - - (- for no successor) ++ //Set F visible: ++ //All: A B C D - F G H I J ++ //filteredMask:1 1 0 1 0 1 0 1 0 1 //set mask at F to 1 ++ //indices: 0 1 2 3 4 5 6 7 8 9 ++ //successor: 0 1 3 - 5 - 7 - 9 - - //update successor of predecessor to F and set F's successor to old successor of predecessor ++ //Set D filtered: ++ //All: A B C D - F G H I J ++ //Mask: 1 1 0 0 0 1 0 1 0 1 //set mask at D to 0 ++ //indices: 0 1 2 3 4 5 6 7 8 9 ++ //successor: 0 1 5 - - - 7 - 9 - - //update successor of predecessor to old successor of D and remove D's successor value ++ ++ //These calls do not modify the size, they can't cause rehashing, they are safe to use during iteration ++ if (index == -1 || value == this.filteredElementsMask.get(index)) { ++ return; ++ } ++ ++ this.filteredElementsMask.set(index, value); ++ int predecessor = this.filteredElementsMask.previousSetBit(index - 1); ++ if (value) { ++ int successor = this.filteredSuccessor.getInt(predecessor + 1); ++ this.filteredSuccessor.set(predecessor + 1, index); ++ this.filteredSuccessor.set(index + 1, successor); ++ } else { ++ int successor = this.filteredSuccessor.getInt(index + 1); ++ this.filteredSuccessor.set(predecessor + 1, successor); ++ this.filteredSuccessor.set(index + 1, -2); //no successor as this element cannot be reached ++ } ++ } ++ ++ private void compact() { ++ int targetSize = this.size(); ++ int newIndex = this.firstRemovedIndex - 1; ++ int lastVisible = this.filteredElementsMask.previousSetBit(newIndex); ++ ++ ++ for (int i = newIndex + 1; i < this.allElements.size(); i++) { ++ T t = this.allElements.get(i); ++ if (t == null) { ++ continue; ++ } ++ boolean visible = this.filteredElementsMask.get(i); ++ //shift all entries to the lower indices (filling the gaps created by remove() setting null) ++ newIndex++; ++ //i is guaranteed to not be smaller than newIndex, therefore we can write to the same collections ++ ++ this.allElements.set(newIndex, t); ++ this.allElements2Index.put(t, newIndex); ++ this.filteredElementsMask.set(newIndex, visible); ++ ++ //update the successor links ++ this.filteredSuccessor.set(newIndex + 1, -2); //no successor as there is no next entry yet ++ if (visible) { ++ this.filteredSuccessor.set(lastVisible + 1, newIndex); ++ lastVisible = newIndex; ++ } ++ } ++ ++ if (newIndex + 1 != targetSize) { ++ throw new IllegalStateException("Compaction ended up with incorrect size: Should be: " + targetSize + " but is: " + (newIndex + 1)); ++ } ++ ++ this.filteredSuccessor.set(lastVisible + 1, -1); //-1 means this was the last element ++ this.firstRemovedIndex = Integer.MAX_VALUE; ++ ++ this.filteredSuccessor.removeElements(targetSize + 1, this.filteredSuccessor.size()); ++ this.allElements.removeElements(targetSize, this.allElements.size()); ++ this.filteredElementsMask.clear(targetSize, this.filteredElementsMask.size()); ++ ++ this.filteredSuccessor.trim(targetSize * 4); ++ this.allElements.trim(targetSize * 4); ++ this.allElements2Index.trim(targetSize * 4); ++ } ++ ++ public Iterator filteredIterator() { ++ return new Iterator() { ++ int next = MaskedTickingBlockEntityList.this.filteredSuccessor.getInt(0); ++ T prev; ++ ++ @Override ++ public boolean hasNext() { ++ return this.next != -1; ++ } ++ ++ @Override ++ public T next() { ++ int next = this.next; ++ T prev = MaskedTickingBlockEntityList.this.allElements.get(next); ++ this.prev = prev; ++ this.next = MaskedTickingBlockEntityList.this.filteredSuccessor.getInt(next + 1); ++ return prev; ++ } ++ ++ @Override ++ public void remove() { ++ MaskedTickingBlockEntityList.this.remove(this.prev); ++ } ++ }; ++ } ++ ++ @Override ++ public int size() { ++ return this.allElements2Index.size(); ++ } ++ ++ @Override ++ public boolean isEmpty() { ++ return this.size() == 0; ++ } ++ ++ @Override ++ public boolean contains(Object o) { ++ //noinspection SuspiciousMethodCalls ++ return this.allElements2Index.containsKey(o); ++ } ++ ++ @Override ++ public @NotNull Iterator iterator() { ++ return Iterators.unmodifiableIterator(this.allElements2Index.keySet().iterator()); ++ } ++ ++ @Override ++ public Object[] toArray() { ++ return this.allElements2Index.keySet().toArray(); ++ } ++ ++ @NotNull ++ @Override ++ public T1[] toArray(@NotNull T1[] t1s) { ++ //noinspection SuspiciousToArrayCall ++ return this.allElements2Index.keySet().toArray(t1s); ++ } ++ ++ @Override ++ public boolean add(T t) { ++ int arraySize = this.allElements.size(); ++ int invalidEntries = arraySize - this.size(); ++ //Compaction is done during the add operation as it is guaranteed to not happen during iteration ++ if ((arraySize > 2048 && invalidEntries > (arraySize >> 1)) || arraySize >= Integer.MAX_VALUE - 1 && invalidEntries != 0) { ++ this.compact(); ++ } ++ ++ if (!this.mayContain.test(t)) { ++ return false; ++ } ++ ++ int index = this.allElements.size(); ++ int i = this.allElements2Index.putIfAbsent(t, index); ++ if (i != -1) { ++ return false; ++ } ++ this.allElements.add(t); ++ this.filteredSuccessor.add(0);//increase size so setEntryVisible doesn't crash with indexOutOfBounds ++ this.setEntryVisible(index, true); ++ ++ return true; ++ } ++ ++ @Override ++ public boolean remove(Object o) { ++ int index = this.allElements2Index.removeInt(o); ++ if (index == -1) { ++ return false; ++ } ++ this.setEntryVisible(index, false); ++ this.allElements.set(index, null); ++ this.firstRemovedIndex = Math.min(this.firstRemovedIndex, index); ++ return true; ++ } ++ ++ @Override ++ public boolean containsAll(@NotNull Collection c) { ++ return this.allElements2Index.keySet().containsAll(c); ++ } ++ ++ @Override ++ public boolean addAll(@NotNull Collection c) { ++ boolean b = false; ++ for (T t : c) { ++ this.add(t); ++ b = true; ++ } ++ return b; ++ } ++ ++ @Override ++ public boolean addAll(int index, @NotNull Collection c) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public boolean removeAll(@NotNull Collection c) { ++ boolean b = false; ++ for (Object t : c) { ++ b |= this.remove(t); ++ } ++ return b; ++ } ++ ++ @Override ++ public boolean retainAll(@NotNull Collection c) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public void clear() { ++ this.allElements2Index.clear(); ++ this.allElements.clear(); ++ this.filteredSuccessor.clear(); ++ this.filteredElementsMask.clear(); ++ this.firstRemovedIndex = Integer.MAX_VALUE; ++ this.filteredSuccessor.add(-1); ++ } ++ ++ @Override ++ public T get(int index) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public T set(int index, T element) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public void add(int index, T element) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public T remove(int index) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public int indexOf(Object o) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public int lastIndexOf(Object o) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public @NotNull ListIterator listIterator() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public @NotNull ListIterator listIterator(int index) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public @NotNull List subList(int fromIndex, int toIndex) { ++ throw new UnsupportedOperationException(); ++ } ++} +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/world/blockentity/BlockEntitySleepTracker.java b/src/main/java/me/jellysquid/mods/lithium/common/world/blockentity/BlockEntitySleepTracker.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c54e1e1f9c6b09022c0f20d5ea4d552bd3ceed55 +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/world/blockentity/BlockEntitySleepTracker.java +@@ -0,0 +1,7 @@ ++package me.jellysquid.mods.lithium.common.world.blockentity; ++ ++import net.minecraft.world.level.block.entity.TileEntity; ++ ++public interface BlockEntitySleepTracker { ++ void setAwake(TileEntity tileEntity, boolean needsTicking); ++} +\ No newline at end of file +diff --git a/src/main/java/me/jellysquid/mods/lithium/common/world/blockentity/SleepingBlockEntity.java b/src/main/java/me/jellysquid/mods/lithium/common/world/blockentity/SleepingBlockEntity.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4e765ab19ffb300b6c810333b2dc797637ae5c1b +--- /dev/null ++++ b/src/main/java/me/jellysquid/mods/lithium/common/world/blockentity/SleepingBlockEntity.java +@@ -0,0 +1,7 @@ ++package me.jellysquid.mods.lithium.common.world.blockentity; ++ ++public interface SleepingBlockEntity { ++ default boolean canTickOnSide(boolean isClient) { ++ return true; ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +index b058c1fa8637b947e8e4a5009258cbee75f536c3..6dce1577a42585a415ea137336c7aa9be6e6a7ed 100644 +--- a/src/main/java/net/minecraft/world/level/World.java ++++ b/src/main/java/net/minecraft/world/level/World.java +@@ -98,8 +98,11 @@ import org.bukkit.event.block.BlockPhysicsEvent; + // CraftBukkit end + + import net.gegy1000.tictacs.NonBlockingWorldAccess; // Yatopia ++import me.jellysquid.mods.lithium.common.util.collections.MaskedTickingBlockEntityList; // Yatopia ++import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker; // Yatopia ++import me.jellysquid.mods.lithium.common.world.blockentity.SleepingBlockEntity; // Yatopia + +-public abstract class World implements GeneratorAccess, AutoCloseable, NonBlockingWorldAccess { // Yatopia ++public abstract class World implements GeneratorAccess, AutoCloseable, NonBlockingWorldAccess, BlockEntitySleepTracker { // Yatopia + + protected static final Logger LOGGER = LogManager.getLogger(); + public static final Codec> f = MinecraftKey.a.xmap(ResourceKey.b(IRegistry.L), ResourceKey::a); +@@ -108,9 +111,17 @@ public abstract class World implements GeneratorAccess, AutoCloseable, NonBlocki + public static final ResourceKey THE_END = ResourceKey.a(IRegistry.L, new MinecraftKey("the_end")); + private static final EnumDirection[] a = EnumDirection.values(); + //public final List tileEntityList = Lists.newArrayList(); // Paper - remove unused list +- public final List tileEntityListTick = me.jellysquid.mods.lithium.common.util.collections.HashedList.wrapper(Lists.newArrayList()); // Yatopia ++ public List tileEntityListTick = me.jellysquid.mods.lithium.common.util.collections.HashedList.wrapper(Lists.newArrayList()); // Yatopia + protected final List tileEntityListPending = me.jellysquid.mods.lithium.common.util.collections.HashedList.wrapper(Lists.newArrayList()); // Yatopia + protected final java.util.Set tileEntityListUnload = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>()); // Airplane - use set with faster contains ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ private MaskedTickingBlockEntityList tileEntityListTick$lithium; ++ ++ @Override ++ public void setAwake(TileEntity tileEntity, boolean needsTicking) { ++ this.tileEntityListTick$lithium.setEntryVisible(tileEntity, needsTicking); ++ } ++ // Yatopia end + public final Thread serverThread; + private final boolean debugWorld; + private int d; +@@ -378,6 +389,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable, NonBlocki + this.keepSpawnInMemory = this.paperConfig.keepSpawnInMemory; // Paper + this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); + this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); ++ this.tileEntityListTick$lithium = new MaskedTickingBlockEntityList<>(this.tileEntityListTick, blockEntity -> ((SleepingBlockEntity) blockEntity).canTickOnSide(false)); // Yatopia ++ this.tileEntityListTick = tileEntityListTick$lithium; // Yatopia + } + + // Paper start +@@ -1042,6 +1055,15 @@ public abstract class World implements GeneratorAccess, AutoCloseable, NonBlocki + + } + ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ public Iterator getAwakeBlockEntities(List list) { ++ if (list == this.tileEntityListTick && list instanceof MaskedTickingBlockEntityList) { ++ return ((MaskedTickingBlockEntityList) list).filteredIterator(); ++ } ++ return list.iterator(); ++ } ++ // Yatopia end ++ + public void tickBlockEntities() { + GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); + +@@ -1064,11 +1086,19 @@ public abstract class World implements GeneratorAccess, AutoCloseable, NonBlocki + + this.tickingTileEntities = true; + // Spigot start ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing + // Iterator iterator = this.tileEntityListTick.iterator(); ++ Iterator iterator = getAwakeBlockEntities(this.tileEntityListTick); ++ + int tilesThisCycle = 0; ++ while (iterator.hasNext()) { ++ TileEntity tileentity = (TileEntity) iterator.next(); ++ /* + for (tileTickPosition = 0; tileTickPosition < tileEntityListTick.size(); tileTickPosition++) { // Paper - Disable tick limiters + tileTickPosition = (tileTickPosition < tileEntityListTick.size()) ? tileTickPosition : 0; + TileEntity tileentity = (TileEntity) this.tileEntityListTick.get(tileTickPosition); ++ */ ++ // Yatopia end + // Spigot start + if (tileentity == null) { + getServer().getLogger().severe("Spigot has detected a null entity and has removed it, preventing a crash"); +@@ -1106,8 +1136,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable, NonBlocki + throwable.printStackTrace(); + getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); + // Paper end +- tilesThisCycle--; +- this.tileEntityListTick.remove(tileTickPosition--); ++ iterator.remove(); // Yatopia + continue; + // Paper end + // Spigot start +@@ -1120,8 +1149,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable, NonBlocki + + if (tileentity.isRemoved()) { + // Spigot start +- tilesThisCycle--; +- this.tileEntityListTick.remove(tileTickPosition--); ++ iterator.remove(); // Yatopia + // Spigot end + //this.tileEntityList.remove(tileentity); // Paper - remove unused list + // Paper - prevent double chunk lookups +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +index 35c4d5414db66b977a354ac50d35a6aa0fcd4cf8..35aef3647c025eaa763e2b9a5a4e266d556725f5 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java +@@ -28,8 +28,9 @@ import org.bukkit.inventory.InventoryHolder; + import org.spigotmc.CustomTimingsHandler; // Spigot + import co.aikar.timings.MinecraftTimings; // Paper + import co.aikar.timings.Timing; // Paper ++import me.jellysquid.mods.lithium.common.world.blockentity.SleepingBlockEntity; + +-public abstract class TileEntity implements net.minecraft.server.KeyedObject { // Paper ++public abstract class TileEntity implements net.minecraft.server.KeyedObject, SleepingBlockEntity { // Paper // Yatopia + + public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper + // CraftBukkit start - data containers +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java +index 95479df9fb009c5ca1872f8ee89b13e9c66d0bb6..52243bce89b28572efae9af54348502f599fb896 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java +@@ -23,6 +23,9 @@ import net.minecraft.world.level.block.BlockBeehive; + import net.minecraft.world.level.block.BlockCampfire; + import net.minecraft.world.level.block.BlockFire; + import net.minecraft.world.level.block.state.IBlockData; ++import me.jellysquid.mods.lithium.common.util.collections.ListeningList; ++import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker; ++import java.util.ArrayList; + + public class TileEntityBeehive extends TileEntity implements ITickable { + +@@ -30,11 +33,24 @@ public class TileEntityBeehive extends TileEntity implements ITickable { + @Nullable + public BlockPosition flowerPos = null; + public int maxBees = net.pl3x.purpur.PurpurConfig.beeInsideBeeHive; // CraftBukkit - allow setting max amount of bees a hive can hold // Purpur - Change max bees inside beehive and bee_nest ++ public boolean doInit = true; // Yatopia ++ public boolean isTicking = true; // Yatopia + + public TileEntityBeehive() { + super(TileEntityTypes.BEEHIVE); + } + ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ public void checkSleepState() { ++ if (this.world != null ) { ++ if ((this.bees.size() == 0) == this.isTicking) { ++ this.isTicking = !this.isTicking; ++ ((BlockEntitySleepTracker) this.world).setAwake(this, this.isTicking); ++ } ++ } ++ } ++ // Yatopia end ++ + @Override + public void update() { + if (this.d()) { +@@ -309,6 +325,12 @@ public class TileEntityBeehive extends TileEntity implements ITickable { + + @Override + public void tick() { ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ if (this.doInit) { ++ this.doInit = false; ++ this.checkSleepState(); ++ } ++ // Yatopia end + if (this.bees.size() == 0) { return; } // Yatopia - TE optimizations + if (!this.world.isClientSide) { + this.y(); +@@ -329,6 +351,7 @@ public class TileEntityBeehive extends TileEntity implements ITickable { + @Override + public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) { + super.load(iblockdata, nbttagcompound); ++ this.checkSleepState(); // Yatopia + this.bees.clear(); + NBTTagList nbttaglist = nbttagcompound.getList("Bees", 10); + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java +index 84f9f52c5b632621b509448ac1c760f64de6b062..c4c983b15c28db856be7335e53637a21af2c1b2f 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java +@@ -20,6 +20,7 @@ import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.level.World; + import net.minecraft.world.phys.AxisAlignedBB; + import org.apache.commons.lang3.mutable.MutableInt; ++import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker; + + public class TileEntityBell extends TileEntity implements ITickable { + +@@ -30,6 +31,8 @@ public class TileEntityBell extends TileEntity implements ITickable { + private List h; private List getEntitiesAtRing() { return this.h; } // Paper - OBFHELPER + private boolean i; private boolean getShouldReveal() { return this.i; } // Paper - OBFHELPER + private int j; ++ public boolean ringing; // Yatopia ++ public boolean resonating; // Yatopia + + public TileEntityBell() { + super(TileEntityTypes.BELL); +@@ -37,6 +40,11 @@ public class TileEntityBell extends TileEntity implements ITickable { + + @Override + public boolean setProperty(int i, int j) { ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ if (!this.ringing && i == 1 && this.world != null) { ++ ((BlockEntitySleepTracker) this.world).setAwake(this, true); ++ } ++ // Yatopia end + if (i == 1) { + this.f(); + this.j = 0; +@@ -81,6 +89,11 @@ public class TileEntityBell extends TileEntity implements ITickable { + } + } + ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ if (!this.ringing && !this.resonating && this.world != null) { ++ ((BlockEntitySleepTracker)this.world).setAwake(this, false); ++ } ++ // Yatopia end + } + + private void d() { +@@ -88,6 +101,11 @@ public class TileEntityBell extends TileEntity implements ITickable { + } + + public void a(EnumDirection enumdirection) { ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ if (!this.ringing && this.world != null) { ++ ((BlockEntitySleepTracker)this.world).setAwake(this, true); ++ } ++ // Yatopia end + BlockPosition blockposition = this.getPosition(); + + this.c = enumdirection; +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBrewingStand.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBrewingStand.java +index 95ca7d9e1eadbe5cc5674ed7352c1ed4d707363d..b5d5f38e520bb5d7912cc86d8ee25858bbd0786b 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBrewingStand.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBrewingStand.java +@@ -34,6 +34,7 @@ import org.bukkit.event.inventory.BrewEvent; + import org.bukkit.event.inventory.BrewingStandFuelEvent; + import org.bukkit.inventory.InventoryHolder; + // CraftBukkit end ++import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker; + + public class TileEntityBrewingStand extends TileEntityContainer implements IWorldInventory, ITickable { + +@@ -50,6 +51,7 @@ public class TileEntityBrewingStand extends TileEntityContainer implements IWorl + private int lastTick = MinecraftServer.currentTick; + public List transaction = new java.util.ArrayList(); + private int maxStack = 64; ++ public boolean isTicking = true; // Yatopia + + public void onOpen(CraftHumanEntity who) { + transaction.add(who); +@@ -72,6 +74,17 @@ public class TileEntityBrewingStand extends TileEntityContainer implements IWorl + return maxStack; + } + ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ @Override ++ public void update() { ++ super.update(); ++ if (!this.isTicking && this.world != null) { ++ this.isTicking = true; ++ ((BlockEntitySleepTracker)this.world).setAwake(this, true); ++ } ++ } ++ // Yatopia end ++ + public void setMaxStackSize(int size) { + maxStack = size; + } +@@ -141,6 +154,12 @@ public class TileEntityBrewingStand extends TileEntityContainer implements IWorl + + @Override + public void tick() { ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ if (this.brewTime == 0 && this.world != null) { ++ this.isTicking = false; ++ ((BlockEntitySleepTracker)this.world).setAwake(this, false); ++ } ++ // Yatopia end + ItemStack itemstack = (ItemStack) this.items.get(4); + + if (this.fuelLevel <= 0 && itemstack.getItem() == Items.BLAZE_POWDER) { +@@ -280,6 +299,12 @@ public class TileEntityBrewingStand extends TileEntityContainer implements IWorl + @Override + public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) { + super.load(iblockdata, nbttagcompound); ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ if (!this.isTicking && this.world != null) { ++ this.isTicking = true; ++ ((BlockEntitySleepTracker) this.world).setAwake(this, true); ++ } ++ // Yatopia end + this.items = NonNullList.a(this.getSize(), ItemStack.b); + ContainerUtil.b(nbttagcompound, this.items); + this.brewTime = nbttagcompound.getShort("BrewTime"); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java +index 08759f461ec947c0d5655557f49d8717afee6f00..cdff01d4da417ef1be6238d3faaf464ee7884bd5 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java +@@ -27,12 +27,18 @@ import org.bukkit.craftbukkit.block.CraftBlock; + import org.bukkit.craftbukkit.inventory.CraftItemStack; + import org.bukkit.event.block.BlockCookEvent; + // CraftBukkit end ++import net.minecraft.core.NonNullList; ++import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker; + + public class TileEntityCampfire extends TileEntity implements Clearable, ITickable { + + private final NonNullList items; + public final int[] cookingTimes; + public final int[] cookingTotalTimes; ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ public boolean isTicking = true; ++ public boolean doInit = true; ++ // Yatopia end + + public TileEntityCampfire() { + super(TileEntityTypes.CAMPFIRE); +@@ -41,8 +47,50 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab + this.cookingTotalTimes = new int[4]; + } + ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ @Override ++ public void update() { ++ super.update(); ++ this.checkSleepState(); ++ } ++ ++ @Override ++ public void invalidateBlockCache() { ++ super.invalidateBlockCache(); ++ this.checkSleepState(); ++ } ++ ++ public void checkSleepState() { ++ if (this.world == null) { ++ return; ++ } ++ boolean shouldTick = false; ++ NonNullList beingCooked = this.items; ++ for (int i = 0; i < beingCooked.size(); i++) { ++ ItemStack stack = beingCooked.get(i); ++ if (!stack.isEmpty()) { ++ if (this.cookingTimes[i] > 0 || this.getBlock().get(BlockCampfire.LIT)) { ++ shouldTick = true; ++ break; ++ } ++ } ++ } ++ ++ if (shouldTick != this.isTicking) { ++ this.isTicking = shouldTick; ++ ((BlockEntitySleepTracker)this.world).setAwake(this, shouldTick); ++ } ++ } ++ // Yatopia end ++ + @Override + public void tick() { ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ if (this.doInit) { ++ this.doInit = false; ++ this.checkSleepState(); ++ } ++ // Yatopia end + boolean flag = (Boolean) this.getBlock().get(BlockCampfire.LIT); + boolean flag1 = this.world.isClientSide; + +@@ -149,6 +197,7 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab + @Override + public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) { + super.load(iblockdata, nbttagcompound); ++ this.checkSleepState(); // Yatopia - lithium: skip ticking block entities that are doing nothing + this.items.clear(); + ContainerUtil.b(nbttagcompound, this.items); + int[] aint; +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java +index cfabc9047cd3e972af84700725355d0fe149b221..4f5f050a947cd708ab375565192fde03ba79d7c4 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java +@@ -33,14 +33,27 @@ import net.minecraft.world.level.block.Blocks; + import org.bukkit.craftbukkit.entity.CraftHumanEntity; + import org.bukkit.entity.HumanEntity; + // CraftBukkit end ++ import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker; // Yatopia + + public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITickable + + private gg.airplane.structs.ItemListWithBitset items; // Airplane + protected float a; ++ private float getAnimationAngle() { return a; } // Yatopia - OBFHELPER + protected float b; ++ private float getLastAnimationAngle() { return b; } // Yatopia - OBFHELPER + public int viewingCount; + private int j; ++ private int ticksOpen = j; // Yatopia - OBFHELPER ++ private int lastTime; // Yatopia ++ ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ public void checkWakeUp() { ++ if ((this.viewingCount != 0 || this.getAnimationAngle() != 0.0F || this.getLastAnimationAngle() != 0) && this.world != null) { ++ ((BlockEntitySleepTracker) this.world).setAwake(this, true); ++ } ++ } ++ // Yatopia end + + // CraftBukkit start - add fields and methods + public List transaction = new java.util.ArrayList(); +@@ -135,11 +148,27 @@ public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITic + } + + public void tick() { ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ // noinspection ConstantConditions ++ int time = (int) this.world.getTime(); ++ // ticksOpen == 0 implies most likely that this is the first tick. We don't want to update the value then. ++ // overflow case is handled by not going to sleep when this.ticksOpen == 0 ++ if (this.ticksOpen != 0) { ++ this.ticksOpen += time - this.lastTime - 1; ++ } ++ this.lastTime = time; ++ // Yatopia end ++ + int i = this.position.getX(); + int j = this.position.getY(); + int k = this.position.getZ(); + + ++this.j; ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ if (this.viewingCount == 0 && this.getAnimationAngle() == 0.0F && this.getLastAnimationAngle() == 0 && this.ticksOpen != 0 && this.world != null) { ++ ((BlockEntitySleepTracker) this.world).setAwake(this, false); ++ } ++ // Yatopia end + } + + public void doOpenLogic() { +@@ -245,6 +274,7 @@ public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITic + + @Override + public boolean setProperty(int i, int j) { ++ this.checkWakeUp(); // Yatopia - lithium: skip ticking block entities that are doing nothing + if (i == 1) { + this.viewingCount = j; + return true; +@@ -276,7 +306,7 @@ public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITic + // CraftBukkit end + this.onOpen(); + } +- ++ this.checkWakeUp(); // Yatopia - lithium: skip ticking block entities that are doing nothing + } + + @Override +@@ -297,6 +327,7 @@ public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITic + // CraftBukkit end + this.onOpen(); + } ++ this.checkWakeUp(); // Yatopia - lithium: skip ticking block entities that are doing nothing + + } + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnchantTable.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnchantTable.java +index 4b1cb089355b455c6210f2df1af797cc363997cf..0049a675557cbc05e361c12e9fb84a38a3a21160 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnchantTable.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnchantTable.java +@@ -9,6 +9,7 @@ import net.minecraft.util.MathHelper; + import net.minecraft.world.INamableTileEntity; + import net.minecraft.world.entity.player.EntityHuman; + import net.minecraft.world.level.block.state.IBlockData; ++import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker; + + public class TileEntityEnchantTable extends TileEntity implements INamableTileEntity, ITickable { + +@@ -51,6 +52,7 @@ public class TileEntityEnchantTable extends TileEntity implements INamableTileEn + @Override + public void tick() { + if (!org.yatopiamc.yatopia.server.YatopiaConfig.shouldTickEnchantingTables) { return; } // Yatopia - TE optimizations ++ ((BlockEntitySleepTracker) this.world).setAwake(this, false); // Yatopia + this.j = this.i; + this.l = this.k; + EntityHuman entityhuman = this.world.a((double) this.position.getX() + 0.5D, (double) this.position.getY() + 0.5D, (double) this.position.getZ() + 0.5D, 3.0D, false); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +index 8ec9ed518a3b5f70c5a5d74605a1f17d0f47b300..d8ef6d464ed32fe61dd9d1d5ff7c70994998f934 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java +@@ -53,9 +53,11 @@ import org.bukkit.event.inventory.FurnaceBurnEvent; + import org.bukkit.event.inventory.FurnaceExtractEvent; + import org.bukkit.event.inventory.FurnaceSmeltEvent; + // CraftBukkit end ++import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker; + + public abstract class TileEntityFurnace extends TileEntityContainer implements IWorldInventory, RecipeHolder, AutoRecipeOutput, ITickable { + ++ private boolean isTicking = true; // Yatopia + private static final int[] g = new int[]{0}; + private static final int[] h = new int[]{2, 1}; + private static final int[] i = new int[]{1}; +@@ -197,6 +199,17 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + private int maxStack = MAX_STACK; + public List transaction = new java.util.ArrayList(); + ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ @Override ++ public void update() { ++ super.update(); ++ if (!this.isTicking && this.world != null) { ++ this.isTicking = true; ++ ((BlockEntitySleepTracker) this.world).setAwake(this, true); ++ } ++ } ++ // Yatopia end ++ + public List getContents() { + return this.items; + } +@@ -259,6 +272,12 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + @Override + public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) { + super.load(iblockdata, nbttagcompound); ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ if (!this.isTicking && this.world != null) { ++ this.isTicking = true; ++ ((BlockEntitySleepTracker)this.world).setAwake(this, true); ++ } ++ // Yatopia end + this.items = NonNullList.a(this.getSize(), ItemStack.b); + ContainerUtil.b(nbttagcompound, this.items); + this.burnTime = nbttagcompound.getShort("BurnTime"); +@@ -389,7 +408,12 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I + if (flag1) { + this.update(); + } +- ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ if (!this.isTicking && this.world != null) { ++ this.isTicking = true; ++ ((BlockEntitySleepTracker)this.world).setAwake(this, true); ++ } ++ // Yatopia end + } + + protected boolean canBurn(@Nullable IRecipe irecipe) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityShulkerBox.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityShulkerBox.java +index c1a90eb01689b8b91200ba49d58360d5ea2004c4..8095740f1848443e87fd52c14d19dabb00a3ecd4 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityShulkerBox.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityShulkerBox.java +@@ -33,6 +33,7 @@ import net.minecraft.world.phys.shapes.VoxelShapes; + import org.bukkit.craftbukkit.entity.CraftHumanEntity; + import org.bukkit.entity.HumanEntity; + // CraftBukkit end ++import me.jellysquid.mods.lithium.common.world.blockentity.BlockEntitySleepTracker; + + public class TileEntityShulkerBox extends TileEntityLootable implements IWorldInventory, ITickable { + +@@ -41,7 +42,9 @@ public class TileEntityShulkerBox extends TileEntityLootable implements IWorldIn + public int viewingCount; + private TileEntityShulkerBox.AnimationPhase i; + private float j; ++ public float animationProgress = j; // Yatopia - OBFHELPER + private float k; ++ public float prevAnimationProgress = k; // Yatopia - OBFHELPER + @Nullable + private EnumColor l; + private boolean m; +@@ -96,6 +99,11 @@ public class TileEntityShulkerBox extends TileEntityLootable implements IWorldIn + this.m(); + } + ++ // Yatopia start - lithium: skip ticking block entities that are doing nothing ++ if (this.getAnimationPhase() == TileEntityShulkerBox.AnimationPhase.CLOSED && this.prevAnimationProgress == 0f && this.animationProgress == 0f && this.world != null) { ++ ((BlockEntitySleepTracker) this.world).setAwake(this, false); ++ } ++ // Yatopia end + } + + protected void h() { +@@ -127,6 +135,7 @@ public class TileEntityShulkerBox extends TileEntityLootable implements IWorldIn + + } + ++ public TileEntityShulkerBox.AnimationPhase getAnimationPhase() {return this.j(); } // Yatopia - OBFHELPER + public TileEntityShulkerBox.AnimationPhase j() { + return this.i; + } +@@ -209,6 +218,7 @@ public class TileEntityShulkerBox extends TileEntityLootable implements IWorldIn + + @Override + public boolean setProperty(int i, int j) { ++ if (this.world != null && i == 1) ((BlockEntitySleepTracker) this.world).setAwake(this, true); // Yatopia + if (i == 1) { + this.viewingCount = j; + if (j == 0) {