diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 00000000..0bd68b3d
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,105 @@
+pipeline {
+ agent { label 'slave' }
+ options { timestamps() }
+ triggers {
+ pollSCM('H/10 * * * *')
+ }
+ stages {
+ stage('Cleanup') {
+ steps {
+ sh 'rm -rf ./target'
+ sh 'rm -rf ./Tuinity/Paper/Paper-API ./Tuinity/Paper/Paper-Server ./Tuinity/Paper/work/Spigot/Spigot-API ./Tuinity/Paper/work/Spigot/Spigot-Server'
+ sh 'rm -rf ./Tuinity/Tuinity-API ./Tuinity/Tuinity-Server ./Tuinity/mc-dev'
+ sh 'rm -rf ./Yatopia-API ./Yatopia-Server'
+ sh 'chmod +x ./scripts/*.sh'
+ }
+ }
+ stage('Init project & submodules') {
+ steps {
+ sh './yatopia init'
+ }
+ }
+ stage('Decompile & apply patches') {
+ tools {
+ jdk "OpenJDK 8"
+ }
+ steps {
+ withMaven(
+ maven: '3',
+ mavenLocalRepo: '.repository',
+ publisherStrategy: 'EXPLICIT',
+ ) {
+ sh '''
+ set -e
+ source "./scripts/functions.sh"
+ basedir
+ $scriptdir/updateUpstream.sh "$basedir" false true || exit 1
+ set -e
+ $scriptdir/applyPatches.sh "$basedir" || exit 1
+ '''
+ }
+ }
+ }
+ stage('Build API') {
+ tools {
+ jdk "OpenJDK 8"
+ }
+ steps {
+ withMaven(
+ maven: '3',
+ mavenLocalRepo: '.repository',
+ publisherStrategy: 'EXPLICIT'
+ ) {
+ sh 'mvn -N install org.apache.maven.plugins:maven-deploy-plugin:2.8.2:deploy'
+ sh 'cd Yatopia-API && mvn install org.apache.maven.plugins:maven-deploy-plugin:2.8.2:deploy'
+ sh 'cd ./Tuinity/Paper/Paper-MojangAPI && mvn install'
+ }
+ }
+ }
+ stage('Build Server') {
+ tools {
+ jdk "OpenJDK 8"
+ }
+ steps {
+ withMaven(
+ maven: '3',
+ mavenLocalRepo: '.repository',
+ publisherStrategy: 'EXPLICIT'
+ ) {
+ sh 'cd Yatopia-Server && mvn install org.apache.maven.plugins:maven-deploy-plugin:2.8.2:deploy -DaltDeploymentRepository=codemc-snapshots::default::https://repo.codemc.org/repository/nms-local/'
+ }
+ }
+ }
+ stage('Build Launcher') {
+ tools {
+ jdk "OpenJDK 8"
+ }
+ steps {
+ withMaven(
+ maven: '3',
+ mavenLocalRepo: '.repository',
+ publisherStrategy: 'EXPLICIT'
+ ) {
+ sh '''
+ basedir=$(pwd)
+ paperworkdir="$basedir/Tuinity/Paper/work"
+ mcver=$(cat "$paperworkdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4)
+ serverjar="$basedir/Yatopia-Server/target/yatopia-$mcver.jar"
+ vanillajar="$paperworkdir/Minecraft/$mcver/$mcver.jar"
+ (
+ cd "$paperworkdir/Paperclip"
+ mvn clean package "-Dmcver=$mcver" "-Dpaperjar=$serverjar" "-Dvanillajar=$vanillajar"
+ )
+ mkdir -p "./target"
+ cp "$paperworkdir/Paperclip/assembly/target/paperclip-$mcver.jar" "./target/yatopia-$mcver-paperclip-b$BUILD_NUMBER.jar"
+ '''
+ }
+ }
+ post {
+ success {
+ archiveArtifacts "target/*.jar"
+ }
+ }
+ }
+ }
+}
diff --git a/PATCHES.md b/PATCHES.md
index 7ba5c06b..49d3fb14 100644
--- a/PATCHES.md
+++ b/PATCHES.md
@@ -56,6 +56,7 @@ # Patches
| server | Fix lead fall dmg config | tr7zw | |
| server | Fix recipe crash | Ivan Pekov | |
| server | Fix the dead lagging the server | William Blake Galbreath | |
+| server | Further improve tuinity's portal crash fix | Ivan Pekov | |
| server | Giants AI settings | William Blake Galbreath | |
| server | Global Eula file | tr7zw | |
| server | Heavily optimize furnance fuel and recipe lookups | tr7zw | |
@@ -88,6 +89,8 @@ # Patches
| server | Per entity (type) collision settings | MrIvanPlays | tr7zw |
| server | Phantoms attracted to crystals and crystals shoot phantoms | William Blake Galbreath | |
| server | Player-saving-async-FileIO | tr7zw | |
+| api | ProxyForwardDataEvent | Ivan Pekov | |
+| server | ProxyForwardDataEvent | Ivan Pekov | |
| server | Purpur config files | William Blake Galbreath | |
| server | Rabbit naturally spawn toast and killer | William Blake Galbreath | |
| server | Redirect Configs | tr7zw | |
diff --git a/README.md b/README.md
index 29d07b72..55b2d673 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,7 @@
The Most Powerful Minecraft Server Software
[![Github-CI](https://github.com/YatopiaMC/Yatopia/workflows/CI/badge.svg)](https://github.com/YatopiaMC/Yatopia/actions?query=workflow%3ACI)
+[![CodeMC](https://ci.codemc.io/buildStatus/icon?job=YatopiaMC%2FYatopia%2Fver%252F1.16.2)](https://ci.codemc.io/job/YatopiaMC/job/Yatopia/job/ver%252F1.16.2/)
[![Discord](https://img.shields.io/discord/342814924310970398?color=%237289DA&label=Discord&logo=discord&logoColor=white)](https://discord.io/YatopiaMC)
![API](https://img.shields.io/website?down_color=lightgrey&down_message=offline&label=API&up_color=green&up_message=online&url=http%3A%2F%2Fapi.yatopia.net%2F)
diff --git a/patches/api/0002-Modify-POM.patch b/patches/api/0002-Modify-POM.patch
index e05e0fae..1a4ab65b 100644
--- a/patches/api/0002-Modify-POM.patch
+++ b/patches/api/0002-Modify-POM.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Modify POM
diff --git a/pom.xml b/pom.xml
-index 95a99b7b55a980b9ad81a0d536507cf890464260..5ab7c79fa4e3df9b98be7f53b4f081d6ba78eea1 100644
+index 95a99b7b55a980b9ad81a0d536507cf890464260..9f87bd4e200d35746e19e4f0a96a626da15e90f4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,18 +3,18 @@
@@ -32,3 +32,23 @@ index 95a99b7b55a980b9ad81a0d536507cf890464260..5ab7c79fa4e3df9b98be7f53b4f081d6
An enhanced plugin API for Minecraft servers.
+@@ -24,6 +24,19 @@
+ UTF-8
+
+
++
++
++
++ codemc-releases
++ https://repo.codemc.org/repository/maven-releases/
++
++
++ codemc-snapshots
++ https://repo.codemc.org/repository/maven-snapshots/
++
++
++
++
+
+
true
diff --git a/patches/api/0007-ProxyForwardDataEvent.patch b/patches/api/0007-ProxyForwardDataEvent.patch
new file mode 100644
index 00000000..5a9df263
--- /dev/null
+++ b/patches/api/0007-ProxyForwardDataEvent.patch
@@ -0,0 +1,126 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Ivan Pekov
+Date: Wed, 9 Sep 2020 16:14:00 +0300
+Subject: [PATCH] ProxyForwardDataEvent
+
+
+diff --git a/src/main/java/net/yatopia/api/event/ProxyForwardDataEvent.java b/src/main/java/net/yatopia/api/event/ProxyForwardDataEvent.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..8ffef40a2645124fd2de0dc45fa209431bfc1a3c
+--- /dev/null
++++ b/src/main/java/net/yatopia/api/event/ProxyForwardDataEvent.java
+@@ -0,0 +1,114 @@
++package net.yatopia.api.event;
++
++import com.google.common.collect.ImmutableList;
++import com.mojang.authlib.properties.Property;
++import java.util.List;
++import java.util.UUID;
++import org.bukkit.event.Event;
++import org.bukkit.event.HandlerList;
++import org.jetbrains.annotations.NotNull;
++
++/**
++ * Called when a proxy such as BungeeCord or Velocity forwards player data to the server.
++ */
++public class ProxyForwardDataEvent extends Event {
++
++ private final UUID uuid;
++ private final String name;
++ private List properties;
++
++ public ProxyForwardDataEvent(boolean async, UUID uuid, String name, List properties) {
++ super(async);
++ this.uuid = uuid;
++ this.name = name;
++ this.properties = properties;
++ }
++
++ /**
++ * Returns the unique id of the profile forwarded.
++ *
++ * @return unique id
++ */
++ public UUID getUuid() {
++ return uuid;
++ }
++
++ /**
++ * Returns the name of the profile forwarded.
++ *
++ * @return name
++ */
++ public String getName() {
++ return name;
++ }
++
++ /**
++ * Returns an immutable copy of the forwarded properties.
++ *
++ * @return properties
++ */
++ public List getProperties() {
++ return ImmutableList.copyOf(properties);
++ }
++
++ /**
++ * Adds a property to this game profile. If the property already exists, it overrides it.
++ *
++ * @param property property
++ */
++ public void addProperty(Property property) {
++ if (hasProperty(property.getName())) {
++ removeProperty(property.getName());
++ }
++ properties.add(property);
++ }
++
++ /**
++ * Returns the property with the specified name.
++ *
++ * @param property the property's name you want to get
++ * @return property if present
++ */
++ public Property getProperty(String property) {
++ for (Property prop : properties) {
++ if (prop.getName().toLowerCase().equalsIgnoreCase(property.toLowerCase())) {
++ return prop;
++ }
++ }
++ return null;
++ }
++
++ /**
++ * Returns whether or not there's a property with the specified name.
++ *
++ * @param property the name of the property you want to check if exists
++ * @return boolean value
++ */
++ public boolean hasProperty(String property) {
++ return getProperty(property) != null;
++ }
++
++ /**
++ * Removes the specified property if present
++ *
++ * @param property the property's name you want to remove
++ */
++ public void removeProperty(String property) {
++ properties.removeIf(prop -> prop.getName().toLowerCase().equalsIgnoreCase(property.toLowerCase()));
++ }
++
++ /**
++ * Removes the specified property if present
++ *
++ * @param property the property you want to remove
++ */
++ public void removeProperty(Property property) {
++ properties.remove(property);
++ }
++
++ //
++ private static final HandlerList handlers = new HandlerList();
++ @NotNull @Override public HandlerList getHandlers() { return handlers; }
++ public static HandlerList getHandlerList() { return handlers; }
++ //
++}
diff --git a/patches/server/0002-Modify-POM.patch b/patches/server/0002-Modify-POM.patch
index 8f00b86a..d84fb5ab 100644
--- a/patches/server/0002-Modify-POM.patch
+++ b/patches/server/0002-Modify-POM.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Modify POM
diff --git a/pom.xml b/pom.xml
-index 4f45b815860f3ab137c828c408f56030fc209ffe..4f2593a9870f4abb425114b961d125de8e42442d 100644
+index 4f45b815860f3ab137c828c408f56030fc209ffe..bfe2ed3a3d48c8c0dced87620d1f4844f1d9911d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,11 +1,11 @@
@@ -23,7 +23,7 @@ index 4f45b815860f3ab137c828c408f56030fc209ffe..4f2593a9870f4abb425114b961d125de
-@@ -18,16 +18,16 @@
+@@ -18,16 +18,25 @@
@@ -35,6 +35,15 @@ index 4f45b815860f3ab137c828c408f56030fc209ffe..4f2593a9870f4abb425114b961d125de
../pom.xml
++
++
++
++ codemc-snapshots
++ https://repo.codemc.org/repository/nms-local/
++
++
++
++
- com.tuinity
@@ -44,7 +53,7 @@ index 4f45b815860f3ab137c828c408f56030fc209ffe..4f2593a9870f4abb425114b961d125de
${project.version}
compile
-@@ -153,6 +153,15 @@
+@@ -153,6 +162,15 @@
spigotmc-public
https://hub.spigotmc.org/nexus/content/groups/public/
@@ -60,7 +69,7 @@ index 4f45b815860f3ab137c828c408f56030fc209ffe..4f2593a9870f4abb425114b961d125de
-@@ -164,15 +173,15 @@
+@@ -164,15 +182,15 @@
diff --git a/patches/server/0003-Brandings.patch b/patches/server/0003-Brandings.patch
index 2d312b45..1be959b1 100644
--- a/patches/server/0003-Brandings.patch
+++ b/patches/server/0003-Brandings.patch
@@ -31,7 +31,7 @@ index 8005f7eb073270a46f38601705ca4e89899015b1..4f228fd552b7edbb810dc85636123a92
public CrashReport b(CrashReport crashreport) {
diff --git a/src/main/java/net/yatopia/server/YatopiaVersionFetcher.java b/src/main/java/net/yatopia/server/YatopiaVersionFetcher.java
new file mode 100644
-index 0000000000000000000000000000000000000000..f30ef479696fbe3a3ff31ec1c6de882d236e8c1b
+index 0000000000000000000000000000000000000000..b0d5d8df1c1107294ee0cd7cbad271395e2eb76b
--- /dev/null
+++ b/src/main/java/net/yatopia/server/YatopiaVersionFetcher.java
@@ -0,0 +1,96 @@
@@ -58,7 +58,7 @@ index 0000000000000000000000000000000000000000..f30ef479696fbe3a3ff31ec1c6de882d
+
+ @Override
+ public long getCacheTime() {
-+ return Long.MAX_VALUE;
++ return 720000;
+ }
+
+ @Nonnull
@@ -172,7 +172,7 @@ index 001b1e5197eaa51bfff9031aa6c69876c9a47960..0525370b7e3bf24147b4948caf522ad7
if (stream != null) {
diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java
-index 4d310908489953d6d061b2358f614142edacb62e..870a3b64aaf933ba22c32b699b576a96ca4dae25 100644
+index 4d310908489953d6d061b2358f614142edacb62e..fd3e1d363a8ed18af6132421e927e83680ff8e76 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
@@ -202,7 +202,7 @@ index 4d310908489953d6d061b2358f614142edacb62e..870a3b64aaf933ba22c32b699b576a96
//
if ( net.minecraft.server.World.lastPhysicsProblem != null )
{
-@@ -188,7 +188,7 @@ public class WatchdogThread extends Thread
+@@ -188,12 +188,12 @@ public class WatchdogThread extends Thread
// Paper end
} else
{
@@ -211,6 +211,12 @@ index 4d310908489953d6d061b2358f614142edacb62e..870a3b64aaf933ba22c32b699b576a96
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 );
@@ -209,7 +209,7 @@ public class WatchdogThread extends Thread
dumpThread( thread, log );
}
diff --git a/patches/server/0009-Add-NBT-API-as-a-first-class-lib.patch b/patches/server/0009-Add-NBT-API-as-a-first-class-lib.patch
index ed822f20..0d92253a 100644
--- a/patches/server/0009-Add-NBT-API-as-a-first-class-lib.patch
+++ b/patches/server/0009-Add-NBT-API-as-a-first-class-lib.patch
@@ -5,10 +5,10 @@ Subject: [PATCH] Add NBT API as a first-class lib
diff --git a/pom.xml b/pom.xml
-index 4f2593a9870f4abb425114b961d125de8e42442d..e9d4dea6685d603808994aa6f752fd20ec19f46b 100644
+index bfe2ed3a3d48c8c0dced87620d1f4844f1d9911d..b072a6a21ead442851ac5d511f5ddc83ca0eff48 100644
--- a/pom.xml
+++ b/pom.xml
-@@ -311,6 +311,10 @@
+@@ -320,6 +320,10 @@
net.minecraft.server
net.minecraft.server.v${minecraft_version}
diff --git a/patches/server/0044-ProxyForwardDataEvent.patch b/patches/server/0044-ProxyForwardDataEvent.patch
new file mode 100644
index 00000000..6aea9f69
--- /dev/null
+++ b/patches/server/0044-ProxyForwardDataEvent.patch
@@ -0,0 +1,96 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Ivan Pekov
+Date: Wed, 9 Sep 2020 16:15:22 +0300
+Subject: [PATCH] ProxyForwardDataEvent
+
+
+diff --git a/src/main/java/net/minecraft/server/HandshakeListener.java b/src/main/java/net/minecraft/server/HandshakeListener.java
+index 5dde738b7499fbf432dc3dbae295eb96d5b90347..0fc3b46df54d40133c059d819b1a198e4e65dc23 100644
+--- a/src/main/java/net/minecraft/server/HandshakeListener.java
++++ b/src/main/java/net/minecraft/server/HandshakeListener.java
+@@ -92,6 +92,7 @@ public class HandshakeListener implements PacketHandshakingInListener {
+ this.getNetworkManager().socketAddress = new java.net.InetSocketAddress(event.getSocketAddressHostname(), ((java.net.InetSocketAddress) this.getNetworkManager().getSocketAddress()).getPort());
+ this.getNetworkManager().spoofedUUID = event.getUniqueId();
+ this.getNetworkManager().spoofedProfile = gson.fromJson(event.getPropertiesJson(), com.mojang.authlib.properties.Property[].class);
++ if (proxyLogicEnabled) c.proxyProfileSpoof = true; // Yatopia
+ handledByEvent = true; // Hooray, we did it!
+ }
+ }
+@@ -105,6 +106,7 @@ public class HandshakeListener implements PacketHandshakingInListener {
+ packethandshakinginsetprotocol.hostname = split[0];
+ c.socketAddress = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) c.getSocketAddress()).getPort());
+ c.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] );
++ c.proxyProfileSpoof = true; // Yatopia
+ } else
+ {
+ chatmessage = new ChatMessage("If you wish to use IP forwarding, please enable it in your BungeeCord config as well!");
+diff --git a/src/main/java/net/minecraft/server/LoginListener.java b/src/main/java/net/minecraft/server/LoginListener.java
+index 57a3a8d09427012e5c8aba5085d187c6be047652..fa0a8a7e00a64df4d3ba09407193d984e1ff0952 100644
+--- a/src/main/java/net/minecraft/server/LoginListener.java
++++ b/src/main/java/net/minecraft/server/LoginListener.java
+@@ -124,6 +124,23 @@ public class LoginListener implements PacketLoginInListener {
+
+ this.i = new GameProfile( uuid, this.i.getName() );
+
++ // Yatopia start - situate this around an event
++ if (networkManager.proxyProfileSpoof) {
++ java.util.List properties;
++ if (networkManager.spoofedProfile != null) {
++ properties = new java.util.ArrayList<>(Arrays.asList(networkManager.spoofedProfile));
++ } else {
++ properties = new java.util.ArrayList<>();
++ }
++ net.yatopia.api.event.ProxyForwardDataEvent event = new net.yatopia.api.event.ProxyForwardDataEvent(
++ !org.bukkit.Bukkit.isPrimaryThread(), uuid, i.getName(), properties
++ );
++ if (event.callEvent()) {
++ for (com.mojang.authlib.properties.Property property : event.getProperties()) {
++ i.getProperties().put(property.getName(), property);
++ }
++ }
++ } else {
+ if (networkManager.spoofedProfile != null)
+ {
+ for ( com.mojang.authlib.properties.Property property : networkManager.spoofedProfile )
+@@ -131,6 +148,7 @@ public class LoginListener implements PacketLoginInListener {
+ this.i.getProperties().put( property.getName(), property );
+ }
+ }
++ } // Yatopia end
+ }
+ // Spigot end
+
+@@ -355,11 +373,20 @@ public class LoginListener implements PacketLoginInListener {
+
+ this.networkManager.socketAddress = new java.net.InetSocketAddress(com.destroystokyo.paper.proxy.VelocityProxy.readAddress(buf), ((java.net.InetSocketAddress) this.networkManager.getSocketAddress()).getPort());
+
+- this.setGameProfile(com.destroystokyo.paper.proxy.VelocityProxy.createProfile(buf));
++ // Yatopia start - how about spoofed uuid and profile
++ //this.setGameProfile(com.destroystokyo.paper.proxy.VelocityProxy.createProfile(buf));
++ com.mojang.authlib.GameProfile profile = com.destroystokyo.paper.proxy.VelocityProxy.createProfile(buf);
++ networkManager.spoofedUUID = profile.getId();
++ if (!profile.getProperties().isEmpty()) {
++ networkManager.spoofedProfile = profile.getProperties().values().toArray(new com.mojang.authlib.properties.Property[0]);
++ }
++ networkManager.proxyProfileSpoof = true;
++ // Yatopia end
+
+ // Proceed with login
+ authenticatorPool.execute(() -> {
+ try {
++ initUUID(); // Yatopia
+ new LoginHandler().fireEvents();
+ } catch (Exception ex) {
+ disconnect("Failed to verify username!");
+diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java
+index 5b4901acf7d4661e52839a7ab0ebe24b93bec0d6..4bc33861b015937a2081541f6b1ff2470a01d895 100644
+--- a/src/main/java/net/minecraft/server/NetworkManager.java
++++ b/src/main/java/net/minecraft/server/NetworkManager.java
+@@ -49,6 +49,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> {
+ // Spigot Start
+ public java.util.UUID spoofedUUID;
+ public com.mojang.authlib.properties.Property[] spoofedProfile;
++ public boolean proxyProfileSpoof = false; // Yatopia
+ public boolean preparing = true;
+ // Spigot End
+ private PacketListener packetListener;
diff --git a/patches/server/0045-Further-improve-tuinity-s-portal-crash-fix.patch b/patches/server/0045-Further-improve-tuinity-s-portal-crash-fix.patch
new file mode 100644
index 00000000..347064d8
--- /dev/null
+++ b/patches/server/0045-Further-improve-tuinity-s-portal-crash-fix.patch
@@ -0,0 +1,28 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Ivan Pekov
+Date: Wed, 9 Sep 2020 16:49:11 +0300
+Subject: [PATCH] Further improve tuinity's portal crash fix
+
+so we never have equal directions if the direction block property isn't present on the given block data
+
+diff --git a/src/main/java/net/minecraft/server/BlockPortalShape.java b/src/main/java/net/minecraft/server/BlockPortalShape.java
+index a848447260f77b85e5f1bfaedeb16d7d068e00d8..993f58a2a0c168d705fc956e388c5a15c8bca31e 100644
+--- a/src/main/java/net/minecraft/server/BlockPortalShape.java
++++ b/src/main/java/net/minecraft/server/BlockPortalShape.java
+@@ -228,6 +228,16 @@ public class BlockPortalShape {
+ BlockPosition blockposition = blockutil_rectangle.origin;
+ IBlockData iblockdata = worldserver.getType(blockposition);
+ EnumDirection.EnumAxis enumdirection_enumaxis1 = !iblockdata.contains(BlockProperties.E) ? enumdirection_enumaxis : (EnumDirection.EnumAxis) iblockdata.get(BlockProperties.E); // Tuinity - use provided direction if the block doesn't have one
++ // Yatopia start - improve tuinity's fix
++ // basically cycle thru the X and Z direction so we never have equal directions if we don't have that block property
++ if (!iblockdata.contains(BlockProperties.E)) {
++ if (enumdirection_enumaxis1 == EnumDirection.EnumAxis.X) {
++ enumdirection_enumaxis1 = EnumDirection.EnumAxis.Z;
++ } else if (enumdirection_enumaxis1 == EnumDirection.EnumAxis.Z || enumdirection_enumaxis == EnumDirection.EnumAxis.Y) {
++ enumdirection_enumaxis1 = EnumDirection.EnumAxis.X;
++ }
++ }
++ // Yatopia end
+ double d0 = (double) blockutil_rectangle.side1;
+ double d1 = (double) blockutil_rectangle.side2;
+ int i = enumdirection_enumaxis == enumdirection_enumaxis1 ? 0 : 90;