diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 543b0bb..344c385 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,19 +6,14 @@ on: tags: - '*' -env: - # For any reason, specifying this in the modrinth step does not work? - # But it is also well documented here, so this should be ok to do - MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} - jobs: build: runs-on: ubuntu-latest + strategy: + matrix: + version: ['1.19', '1.19.1', '1.19.2', '1.19.3', '1.19.4', '1.20', '1.20.1', '1.20.2'] + fail-fast: true steps: - - name: Check tag condition - if: startsWith(github.ref, 'refs/tags/') - run: echo "Ref is a tag" - - name: Check out project if: success() uses: actions/checkout@v3 @@ -36,14 +31,38 @@ jobs: if: success() uses: gradle/gradle-build-action@v2 with: - gradle-version: 7.4.2 + gradle-version: 8.3 - name: Build if: success() - run: gradle remapJar + run: gradle remapJar -Pv=${{ matrix.version }} + + - name: Upload artifact + if: success() + uses: actions/upload-artifact@v3 + with: + name: build-${{ matrix.version }} + path: | + **/libs/server-portals-*.jar + + release: + runs-on: ubuntu-latest + needs: build + steps: + - name: Check out metadata + uses: actions/checkout@v3 + with: + sparse-checkout: | + README.md + CHANGELOG.md + LICENSE + + - name: Download artifacts + if: success() + uses: actions/download-artifact@v3 - - name: Release on GitHub - if: success() && startsWith(github.ref, 'refs/tags/') # Failsafe check again + - name: Release on github + if: success() # No git tag check, since action-gh-release fails if not valid uses: softprops/action-gh-release@v1 with: files: | @@ -56,6 +75,57 @@ jobs: prerelease: false fail_on_unmatched_files: true - - name: Upload to modrinth + publish: + runs-on: ubuntu-latest + needs: release + strategy: + matrix: + version: ['1.19', '1.19.1', '1.19.2', '1.19.3', '1.19.4', '1.20', '1.20.1', '1.20.2'] + fail-fast: true + steps: + - name: Check out metadata + uses: actions/checkout@v3 + with: + sparse-checkout: | + CHANGELOG.md + + - name: Download artifact + if: success() + uses: actions/download-artifact@v3 + with: + name: build-${{ matrix.version }} + + - name: Publish on modrinth + if: success() && startsWith(github.ref, 'refs/tags/') # Failsafe check + # See https://github.com/Kir-Antipov/mc-publish + uses: Kir-Antipov/mc-publish@v3.3 + with: + modrinth-id: server-portals + modrinth-token: ${{ secrets.MODRINTH_TOKEN }} + modrinth-featured: false + files: | + **/libs/server-portals-*.jar + name: Server Portals ${{ github.ref_name }} + version: ${{ github.ref_name }}+${{ matrix.version }} + version-type: "${{ contains(github.ref_name, 'SNAPSHOT') && 'alpha' || 'release' }}" + changelog-file: CHANGELOG.md + #loaders: fabric + game-versions: "=${{ matrix.version }}" + #dependencies: + + publish_readme: + runs-on: ubuntu-latest + needs: publish + steps: + - name: Check out metadata + uses: actions/checkout@v3 + with: + sparse-checkout: | + README.md + + - name: Update readme if: success() - run: gradle modrinth + run: | + readme="$(sed 's/\\/\\\\/g; s/"/\\"/g; s/$/\\n/' README.md)" + json="{ \"body\": \"$readme\" }" + echo "$json" | curl -XPATCH -H "Authorization: ${{ secrets.MODRINTH_TOKEN }}" -H "Content-type: application/json" -d @- 'https://api.modrinth.com/v2/project/server-portals' diff --git a/.github/workflows/remove-old-artifacts.yml b/.github/workflows/remove-old-artifacts.yml new file mode 100644 index 0000000..b22ded2 --- /dev/null +++ b/.github/workflows/remove-old-artifacts.yml @@ -0,0 +1,23 @@ +# See https://github.com/marketplace/actions/remove-artifacts +name: Remove old artifacts + +on: + schedule: + # Every day at 1am + - cron: '0 1 * * *' + +jobs: + remove-old-artifacts: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Remove old artifacts + uses: c-hive/gha-remove-artifacts@v1 + with: + # ' ', e.g. 5 days, 2 years, 90 seconds, parsed by Moment.js + age: '2 days' + + # Optional inputs + # skip-tags: true + # skip-recent: 5 diff --git a/CHANGELOG.md b/CHANGELOG.md index 54ebdb7..b04f7cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1 +1 @@ -Initial project creation +Support for MC 1.19 - 1.20.2 \ No newline at end of file diff --git a/README.md b/README.md index 83ba003..45fff74 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,10 @@ because of that with [Polymer](https://polymer.pb4.eu/). ## Usage instructions -**NOTE: The server must get restarted to load these changes!** + +NOTE: The server must get restarted to load these changes!
+So after every change of the portals, restart the server (unfortunately)! +
--- List configured portals: diff --git a/build.allprojects.gradle b/build.allprojects.gradle new file mode 100644 index 0000000..8c8c275 --- /dev/null +++ b/build.allprojects.gradle @@ -0,0 +1,34 @@ +allprojects { + // This can get extracted into a root build.gradle if needed + ext { + getLatestTag = { + new ByteArrayOutputStream().withStream { os -> + exec { + executable = "git" + args = ["describe", "--tags", "--abbrev=0"] + standardOutput = os + } + return os.toString().trim() + } + } + + getCurrentCommitCount = { + new ByteArrayOutputStream().withStream { os -> + exec { + executable = "git" + args = ["rev-list", "--all", "--count"] + standardOutput = os + } + return os.toString().trim() + } + } + } + + try { + project.version = "${project.getLatestTag()}.${project.getCurrentCommitCount()}" + } catch (Exception ignored) { + println('Either git is not set up properly, or there is no tag yet in the repository. Falling back to version \'0\'') + project.version = '0' + } + project.group = 'michiruf' +} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 433700d..14aa4e4 100644 --- a/build.gradle +++ b/build.gradle @@ -1,92 +1,63 @@ +import de.michiruf.gradle.findversion.FindVersion + plugins { - id 'fabric-loom' version '1.0-SNAPSHOT' - id 'com.modrinth.minotaur' version '2.+' + id 'java' + id 'fabric-loom' version '1.4-SNAPSHOT' } -allprojects { - // This can get extracted into a root build.gradle if needed - ext { - getLatestTag = { - new ByteArrayOutputStream().withStream { os -> - exec { - executable = "git" - args = ["describe", "--tags", "--abbrev=0"] - standardOutput = os - } - return os.toString().trim() - } - } +apply from: 'build.allprojects.gradle' +apply from: 'build.versions.gradle' - getCurrentCommitCount = { - new ByteArrayOutputStream().withStream { os -> - exec { - executable = "git" - args = ["rev-list", "--all", "--count"] - standardOutput = os - } - return os.toString().trim() - } - } - } +def minecraftVersion = project.minecraftVersion as String ?: '1.20.2' +def minecraftVersionDefinitions = ext.minecraftVersionDefinitions +def minecraftVersionDefinition = minecraftVersionDefinitions[minecraftVersion] +project.version = "${project.version}+${minecraftVersion}" - try { - project.version = "${project.ext.getLatestTag()}-${project.ext.getCurrentCommitCount()}" - } catch (Exception ignored) { - println('Either git is not set up properly, or there is no tag yet in the repository. Falling back to version \'0\'') - project.version = '0' - } - project.group = 'michiruf' +sourceSets { + main.java.srcDirs = [ + 'src/main/java', + "src/registry/${FindVersion.findClosestLowerOrEqualVersionInDirectory(file('src/registry'), minecraftVersion)}", + "src/message/${FindVersion.findClosestLowerOrEqualVersionInDirectory(file('src/message'), minecraftVersion)}", + "src/customportalapi-polymer/${FindVersion.findClosestLowerOrEqualVersionInDirectory(file('src/customportalapi-polymer'), minecraftVersion)}" + ] } repositories { mavenCentral() maven { url 'https://maven.wispforest.io' } // Owo config maven { url 'https://maven.kyrptonaught.dev' } // Custom portal api - maven { url 'https://maven.nucleoid.xyz' } // Custom portal api transitive + maven { url 'https://maven.nucleoid.xyz' } // Custom portal api transitive (polymer) + maven { url 'https://api.modrinth.com/maven' } // Custom portal api transitive (sodium) } dependencies { - // To change the versions see the gradle.properties file - minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - - // Fabric API - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + // Minecraft and fabric + minecraft "com.mojang:minecraft:${minecraftVersion}" + mappings "net.fabricmc:yarn:${minecraftVersionDefinition['mappings']}:v2" + modImplementation "net.fabricmc:fabric-loader:${minecraftVersionDefinition['fabric']}" + modImplementation "net.fabricmc.fabric-api:fabric-api:${minecraftVersionDefinition['fabricApi']}" // Owo config - annotationProcessor modImplementation('io.wispforest:owo-lib:0.9.2+1.19') + modImplementation annotationProcessor("io.wispforest:owo-lib:${minecraftVersionDefinition['owo']}") { exclude group: 'net.fabricmc.fabric-api' } + // We could include owo-sentinel for auto download, see https://github.com/wisp-forest/owo-lib // Custom portal api - modImplementation(include('net.kyrptonaught:customportalapi:0.0.1-beta54-1.19')) - modImplementation(include('net.kyrptonaught:cpa-polymer:1.0.0-1.19')) - modImplementation(include('eu.pb4:polymer:0.2.18+1.19.2')) + modImplementation include("net.kyrptonaught:customportalapi:${minecraftVersionDefinition['customportalapi']}") { exclude group: 'net.fabricmc.fabric-api' } + modImplementation include("eu.pb4:${minecraftVersionDefinition['polymer']}") { exclude group: 'net.fabricmc.fabric-api' } } -modrinth { - projectId = 'server-portals' - versionNumber = project.version - versionType = project.version.contains('SNAPSHOT') ? 'alpha' : 'release' - gameVersions = ['1.19.2'] - loaders = ['fabric'] - dependencies { - required.project 'fabric-api' - required.project 'owo-lib' - } - uploadFile = remapJar - syncBodyFrom = rootProject.file("README.md").text - - // Use the environment variable `$MODRINTH_TOKEN` for the token - // token = 'mySecretToken' -} -tasks.modrinth.dependsOn(tasks.modrinthSyncBody) - processResources { - inputs.property 'version', project.version + var replaceProperties = [ + version : project.version, + minecraft: minecraftVersion, + mappings : minecraftVersionDefinition['mappings'], + fabric : minecraftVersionDefinition['fabric'], + fabricApi: minecraftVersionDefinition['fabricApi'] + ] + inputs.properties replaceProperties filteringCharset 'UTF-8' - filesMatching('fabric.mod.json') { - expand 'version': project.version + expand replaceProperties } } @@ -107,7 +78,6 @@ java { if (JavaVersion.current() < javaVersion) { toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) } - archivesBaseName = project.archives_base_name // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task // if it is present. // If you remove this line, sources will not be generated. diff --git a/build.versions.gradle b/build.versions.gradle new file mode 100644 index 0000000..4098678 --- /dev/null +++ b/build.versions.gradle @@ -0,0 +1,82 @@ +// Check mappings, fabric and fabricApi on: https://modmuss50.me/fabric.html +// Check owo on: https://maven.wispforest.io/io/wispforest/owo-lib/0.11.2%2B1.20/ +// Check customportalapi on: https://maven.kyrptonaught.dev/ +// Check polymer-core on: https://maven.nucleoid.xyz/eu/pb4/polymer-core/ +ext.minecraftVersionDefinitions = [ + '1.19' : [ + mappings : '1.19+build.4', + fabric : '0.12.12', // TODO Check this up again? + fabricApi : '0.58.0+1.19', + owo : '0.9.3+1.19', + customportalapi: '0.0.1-beta54-1.19', // Does not work: '0.0.1-beta62-1.19' AND '0.0.1-beta63.5-1.19.X' + polymer : 'polymer:0.2.10+1.19' + ], + '1.19.1': [ + mappings : '1.19.1+build.6', + fabric : '0.15.0', + fabricApi : '0.58.5+1.19.1', + owo : '0.9.3+1.19', + customportalapi: '0.0.1-beta54-1.19', // Does not work: '0.0.1-beta62-1.19' AND '0.0.1-beta63.5-1.19.X' + polymer : 'polymer:0.2.10+1.19.1' + ], + '1.19.2': [ + mappings : '1.19.2+build.28', + fabric : '0.15.0', + fabricApi : '0.77.0+1.19.2', + owo : '0.9.3+1.19', + customportalapi: '0.0.1-beta54-1.19', // Does not work: '0.0.1-beta62-1.19' AND '0.0.1-beta63.5-1.19.X' + polymer : 'polymer:0.2.28+1.19.2' + ], + '1.19.3': [ + mappings : '1.19.3+build.5', + fabric : '0.15.0', + fabricApi : '0.76.1+1.19.3', + owo : '0.9.3+1.19.3', + customportalapi: '0.0.1-beta63-1.19.3', + polymer : 'polymer-core:0.3.0+1.19.3' + ], + '1.19.4': [ + mappings : '1.19.4+build.2', + fabric : '0.15.1', + fabricApi : '0.87.2+1.19.4', + owo : '0.10.6+1.19.4', // Theres also 0.11.0 for MC 1.19.4 + customportalapi: '0.0.1-beta63-1.19.4', + polymer : 'polymer-core:0.4.11+1.19.4' + ], + '1.20' : [ + mappings : '1.20+build.1', + fabric : '0.15.1', + fabricApi : '0.83.0+1.20', + owo : '0.11.2+1.20', + customportalapi: '0.0.1-beta64-1.20', // beta63 also available + polymer : 'polymer-core:0.5.0+1.20' + ], + '1.20.1': [ + mappings : '1.20.1+build.10', + fabric : '0.15.1', + fabricApi : '0.91.0+1.20.1', + owo : '0.11.2+1.20', // No 1.20.1 artifact + customportalapi: '0.0.1-beta64-1.20', // No 1.20.1 artifact + polymer : 'polymer-core:0.5.18+1.20.1' + ], + '1.20.2': [ + mappings : '1.20.2+build.4', + fabric : '0.15.1', + fabricApi : '0.89.3+1.20.2', // Newest is '0.91.2+1.20.2', but customportalapi needs older + owo : '0.11.4+1.20.2', + customportalapi: '0.0.1-beta64-1.20.2', + polymer : 'polymer-core:0.6.3+1.20.2' + ] + // NOTE There is no customportalapi after 1.20.2 and since this one needs an older fabric api, + // it is probably not worth continuing to newer versions +] + +// Predefine as null to retrieve without checks in build.gradle +ext.minecraftVersion = null + +if (project.hasProperty('v')) + ext.minecraftVersion = project.property('v') + +def minecraftVersionEnv = System.getenv('minecraft_version') ?: "" +if (!minecraftVersionEnv.isEmpty()) + ext.minecraftVersion = minecraftVersionEnv diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle new file mode 100644 index 0000000..5fa53bb --- /dev/null +++ b/buildSrc/build.gradle @@ -0,0 +1,12 @@ +plugins { + id 'java-library' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation gradleApi() + implementation 'org.apache.maven:maven-artifact:3.9.6' +} diff --git a/buildSrc/src/main/java/de/michiruf/gradle/findversion/FindVersion.java b/buildSrc/src/main/java/de/michiruf/gradle/findversion/FindVersion.java new file mode 100644 index 0000000..cb84f28 --- /dev/null +++ b/buildSrc/src/main/java/de/michiruf/gradle/findversion/FindVersion.java @@ -0,0 +1,40 @@ +package de.michiruf.gradle.findversion; + +import org.apache.maven.artifact.versioning.ComparableVersion; + +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +public class FindVersion { + + public static String findClosestLowerOrEqualVersionInDirectory(File directory, String targetVersion) { + return findClosestLowerOrEqualVersionInDirectory(directory, targetVersion, true); + } + + public static String findClosestLowerOrEqualVersionInDirectory(File directory, String targetVersion, boolean onlySubdirectories) { + if (!directory.isDirectory()) + throw new IllegalArgumentException("Given file is not a directory"); + + var contents = onlySubdirectories ? directory.listFiles(File::isDirectory) : directory.listFiles(); + var contentsString = Arrays.stream(Objects.requireNonNull(contents)) + .map(File::getName) + .toList(); + return findClosestLowerOrEqualVersion(contentsString, targetVersion); + } + + public static String findClosestLowerOrEqualVersion(List versions, String targetVersion) { + var comparableTargetVersion = new ComparableVersion(targetVersion); + var result = versions.stream() + .map(ComparableVersion::new) + .filter(comparableVersion -> comparableVersion.compareTo(comparableTargetVersion) <= 0) + .max(ComparableVersion::compareTo); + if (result.isEmpty()) { + System.err.println("No version found. Did you pass versions to the function?"); + return null; + } + + return result.get().toString(); + } +} diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..55cb6c8 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,20 @@ +mc: + container_name: mc + image: itzg/minecraft-server:java17-alpine + ports: + - '25565:25565' + environment: + EULA: 'true' + OVERRIDE_SERVER_PROPERTIES: 'true' + TYPE: FABRIC + VERSION: 1.19.3 + MODRINTH_PROJECTS: fabric-api,owo-lib + MODRINTH_ALLOWED_VERSION_TYPE: alpha + USE_AIKAR_FLAGS: 'true' + REMOVE_OLD_MODS: 'true' + volumes: + - 'mc_data:/data/' + - '../build/libs/:/mods/' + - '/etc/timezone:/etc/timezone:ro' + tty: true + restart: always diff --git a/gradle.properties b/gradle.properties index 737a882..5cacfe8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,12 +1,2 @@ # Done to increase the memory available to gradle. org.gradle.jvmargs=-Xmx1G -# Fabric Properties -# check these on https://modmuss50.me/fabric.html -minecraft_version=1.19.2 -yarn_mappings=1.19.2+build.28 -loader_version=0.14.11 -# Mod Properties -archives_base_name=server-portals -# Dependencies -# check this on https://modmuss50.me/fabric.html -fabric_version=0.68.0+1.19.2 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa991fc..db9a6b8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle b/settings.gradle index f91a4fe..5be140b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,5 +5,15 @@ pluginManagement { url = 'https://maven.fabricmc.net/' } gradlePluginPortal() + + // For sponge snapshot plugin 'org.spongepowered.gradle.vanilla' + // NOTE May remove this if unused + // Got from: https://github.com/jaredlll08/MultiLoader-Template/blob/1.20.2/settings.gradle + maven { + name = 'Sponge' + url = 'https://repo.spongepowered.org/repository/maven-public/' + } } } + +rootProject.name = 'server-portals' diff --git a/src/customportalapi-polymer/1.19.3/net/kyrptonaught/servercustomportals/mixin/VirtualPortalBlock.java b/src/customportalapi-polymer/1.19.3/net/kyrptonaught/servercustomportals/mixin/VirtualPortalBlock.java new file mode 100644 index 0000000..b72a09f --- /dev/null +++ b/src/customportalapi-polymer/1.19.3/net/kyrptonaught/servercustomportals/mixin/VirtualPortalBlock.java @@ -0,0 +1,52 @@ +package net.kyrptonaught.servercustomportals.mixin; + +import eu.pb4.polymer.core.api.block.PolymerBlock; +import eu.pb4.polymer.core.api.block.PolymerBlockUtils; +import net.kyrptonaught.customportalapi.CustomPortalBlock; +import net.kyrptonaught.customportalapi.networking.ForcePlacePortalPacket; +import net.kyrptonaught.customportalapi.util.CustomPortalHelper; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.NetherPortalBlock; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import org.spongepowered.asm.mixin.Mixin; + +// See https://github.com/kyrptonaught/CustomPortalApi-Polymer/blob/1.18/src/main/java/net/kyrptonaught/servercustomportals/mixin/VirtualPortalBlock.java +// Manually edited to match polymer-core, but similar to changes on github +@Mixin(CustomPortalBlock.class) +public class VirtualPortalBlock implements PolymerBlock { + + @Override + public Block getPolymerBlock(BlockState state) { + Direction.Axis dir = CustomPortalHelper.getAxisFrom(state); + if (dir == Direction.Axis.Y) + return Blocks.END_PORTAL; + return Blocks.NETHER_PORTAL; + } + + @Override + public BlockState getPolymerBlockState(BlockState state) { + Direction.Axis dir = CustomPortalHelper.getAxisFrom(state); + if (dir == Direction.Axis.Y) + return Blocks.END_PORTAL.getDefaultState(); + + if (dir == Direction.Axis.Z) + return this.getPolymerBlock(state).getDefaultState().with(NetherPortalBlock.AXIS, Direction.Axis.Z); + + return this.getPolymerBlock(state).getDefaultState(); + } + + @Override + public void onPolymerBlockSend(BlockState blockState, BlockPos.Mutable pos, ServerPlayerEntity player) { + Direction.Axis dir = CustomPortalHelper.getAxisFrom(blockState); + if (dir == Direction.Axis.Y) { + player.networkHandler.sendPacket(PolymerBlockUtils.createBlockEntityPacket(pos, BlockEntityType.END_PORTAL, new NbtCompound())); + } + ForcePlacePortalPacket.sendForcePacket(player, pos.toImmutable(), dir); + } +} \ No newline at end of file diff --git a/src/customportalapi-polymer/1.19/net/kyrptonaught/servercustomportals/mixin/VirtualPortalBlock.java b/src/customportalapi-polymer/1.19/net/kyrptonaught/servercustomportals/mixin/VirtualPortalBlock.java new file mode 100644 index 0000000..20f3038 --- /dev/null +++ b/src/customportalapi-polymer/1.19/net/kyrptonaught/servercustomportals/mixin/VirtualPortalBlock.java @@ -0,0 +1,51 @@ +package net.kyrptonaught.servercustomportals.mixin; + +import eu.pb4.polymer.api.block.PolymerBlock; +import eu.pb4.polymer.api.block.PolymerBlockUtils; +import net.kyrptonaught.customportalapi.CustomPortalBlock; +import net.kyrptonaught.customportalapi.networking.ForcePlacePortalPacket; +import net.kyrptonaught.customportalapi.util.CustomPortalHelper; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.NetherPortalBlock; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import org.spongepowered.asm.mixin.Mixin; + +// See https://github.com/kyrptonaught/CustomPortalApi-Polymer/blob/1.18/src/main/java/net/kyrptonaught/servercustomportals/mixin/VirtualPortalBlock.java +@Mixin(CustomPortalBlock.class) +public class VirtualPortalBlock implements PolymerBlock { + + @Override + public Block getPolymerBlock(BlockState state) { + Direction.Axis dir = CustomPortalHelper.getAxisFrom(state); + if (dir == Direction.Axis.Y) + return Blocks.END_PORTAL; + return Blocks.NETHER_PORTAL; + } + + @Override + public BlockState getPolymerBlockState(BlockState state) { + Direction.Axis dir = CustomPortalHelper.getAxisFrom(state); + if (dir == Direction.Axis.Y) + return Blocks.END_PORTAL.getDefaultState(); + + if (dir == Direction.Axis.Z) + return this.getPolymerBlock(state).getDefaultState().with(NetherPortalBlock.AXIS, Direction.Axis.Z); + + return this.getPolymerBlock(state).getDefaultState(); + } + + @Override + public void onPolymerBlockSend(ServerPlayerEntity player, BlockPos.Mutable pos, BlockState blockState) { + Direction.Axis dir = CustomPortalHelper.getAxisFrom(blockState); + if (dir == Direction.Axis.Y) { + player.networkHandler.sendPacket(PolymerBlockUtils.createBlockEntityPacket(pos, BlockEntityType.END_PORTAL, new NbtCompound())); + } + ForcePlacePortalPacket.sendForcePacket(player, pos.toImmutable()); + } +} \ No newline at end of file diff --git a/src/main/java/de/michiruf/serverportals/Command.java b/src/main/java/de/michiruf/serverportals/Command.java index 342ff93..77244c3 100644 --- a/src/main/java/de/michiruf/serverportals/Command.java +++ b/src/main/java/de/michiruf/serverportals/Command.java @@ -5,20 +5,16 @@ import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.tree.LiteralCommandNode; import de.michiruf.serverportals.config.PortalRegistrationData; +import de.michiruf.serverportals.versioned.VersionedMessageSender; +import de.michiruf.serverportals.versioned.VersionedRegistry; import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.argument.BlockStateArgumentType; import net.minecraft.command.argument.ColorArgumentType; import net.minecraft.command.argument.ItemStackArgumentType; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.Text; -import net.minecraft.util.registry.Registry; import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.function.Supplier; import java.util.stream.Collectors; /** @@ -34,8 +30,6 @@ */ public class Command { - private static final Map> commands = new HashMap<>(); - public static void registerCommands(CommandDispatcher dispatcher, CommandRegistryAccess registry, CommandManager.RegistrationEnvironment environment) { @@ -43,9 +37,9 @@ public static void registerCommands(CommandDispatcher dispa .literal("serverportals") .requires(cmd -> cmd.hasPermissionLevel(4)) .executes(context -> { - context.getSource().sendMessage(Text.literal("Usage: /serverportals list")); - context.getSource().sendMessage(Text.literal("Usage: /serverportals register name frameBlock lightWith color command")); - context.getSource().sendMessage(Text.literal("Usage: /serverportals unregister name")); + VersionedMessageSender.send(context, "Usage: /serverportals list"); + VersionedMessageSender.send(context, "Usage: /serverportals register name frameBlock lightWith color command"); + VersionedMessageSender.send(context, "Usage: /serverportals unregister name"); return 1; }) .build(); @@ -68,9 +62,9 @@ private static int executeListCommand(CommandContext contex .map(PortalRegistrationData::toString) .collect(Collectors.joining("\n")) : ""; - if (listString.length() == 0) + if (listString.isEmpty()) listString = "None"; - context.getSource().sendMessage(Text.literal(listString)); + VersionedMessageSender.send(context, listString); return 0; } @@ -78,7 +72,7 @@ private static void registerRegisterCommand(LiteralCommandNode { - context.getSource().sendMessage(Text.literal("Invalid usage. See /serverportals")); + VersionedMessageSender.send(context, "Invalid usage. See /serverportals"); return 1; }) .then(CommandManager.argument("index", StringArgumentType.word()) @@ -114,14 +108,14 @@ private static int executeRegisterCommand(CommandContext co .toList(); if (registeredIndexes.contains(index)) { ServerPortalsMod.LOGGER.error("Portal with index {} is already registered. Unregister it first", index); - context.getSource().sendMessage(Text.literal("Portal with index " + index + " is already registered. Unregister it first")); + VersionedMessageSender.send(context, "Portal with index " + index + " is already registered. Unregister it first"); return 2; } var portal = new PortalRegistrationData( index, - Registry.BLOCK.getId(frameBlock.getBlockState().getBlock()).toString(), - Registry.ITEM.getId(lightWith.getItem()).toString(), + VersionedRegistry.block().getId(frameBlock.getBlockState().getBlock()).toString(), + VersionedRegistry.item().getId(lightWith.getItem()).toString(), color.getColorValue() != null ? color.getColorValue() : 0, command); // Save must be trigger manually here, because it is a list and cannot observe changes (even when calling @@ -130,7 +124,7 @@ private static int executeRegisterCommand(CommandContext co ServerPortalsMod.CONFIG.save(); ServerPortalsMod.LOGGER.error("Registered portal {}", portal); - context.getSource().sendMessage(Text.literal("Registered portal " + portal)); + VersionedMessageSender.send(context, "Registered portal " + portal); printRestartInfo(context); return 0; @@ -140,7 +134,7 @@ private static void registerUnregisterCommand(LiteralCommandNode { - context.getSource().sendMessage(Text.literal("Invalid usage. See /serverportals")); + VersionedMessageSender.send(context, "Invalid usage. See /serverportals"); return 1; }) .then(CommandManager.argument("index", StringArgumentType.word()) @@ -155,7 +149,7 @@ private static int executeUnregisterCommand(CommandContext // Cancel if not list exists if (ServerPortalsMod.CONFIG.portals() == null) { ServerPortalsMod.LOGGER.error("Portal list does not exist"); - context.getSource().sendMessage(Text.literal("Portal list does not exist")); + VersionedMessageSender.send(context, "Portal list does not exist"); return 2; } @@ -168,7 +162,7 @@ private static int executeUnregisterCommand(CommandContext if (index.equals(portal.index())) { contained = ServerPortalsMod.CONFIG.portals().remove(portal); ServerPortalsMod.LOGGER.error("Unregistered portal {}", portal); - context.getSource().sendMessage(Text.literal("Unregistered portal " + portal)); + VersionedMessageSender.send(context, "Unregistered portal " + portal); } } } while (contained); @@ -183,6 +177,6 @@ private static int executeUnregisterCommand(CommandContext private static void printRestartInfo(CommandContext context) { ServerPortalsMod.LOGGER.info("For this configuration to take effect, restart the server"); - context.getSource().sendMessage(Text.literal("For this configuration to take effect, restart the server")); + VersionedMessageSender.send(context, "For this configuration to take effect, restart the server"); } } diff --git a/src/main/java/de/michiruf/serverportals/ServerPortalsMod.java b/src/main/java/de/michiruf/serverportals/ServerPortalsMod.java index c7a05a2..ea2842b 100644 --- a/src/main/java/de/michiruf/serverportals/ServerPortalsMod.java +++ b/src/main/java/de/michiruf/serverportals/ServerPortalsMod.java @@ -3,10 +3,10 @@ import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.DedicatedServerModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; import net.kyrptonaught.customportalapi.api.CustomPortalBuilder; import net.kyrptonaught.customportalapi.util.SHOULDTP; import net.minecraft.entity.Entity; +import net.minecraft.util.Identifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,6 +43,9 @@ private void registerPluginHooks() { private void registerPortals() { for (var portal : CONFIG.portals()) { CustomPortalBuilder.beginPortal() + // It is essential to set this id since 0.0.1-beta63-1.19.3 + // TODO May this version work now on older minecraft target versions aswell? + .destDimID(Identifier.of("serverportals", "undefined")) .frameBlock(portal.frameBlock()) .lightWithItem(portal.lightWithItem()) .tintColor(portal.color()) diff --git a/src/main/java/de/michiruf/serverportals/config/PortalRegistrationData.java b/src/main/java/de/michiruf/serverportals/config/PortalRegistrationData.java index 3d7ac03..ef7e33b 100644 --- a/src/main/java/de/michiruf/serverportals/config/PortalRegistrationData.java +++ b/src/main/java/de/michiruf/serverportals/config/PortalRegistrationData.java @@ -1,9 +1,9 @@ package de.michiruf.serverportals.config; +import de.michiruf.serverportals.versioned.VersionedRegistry; import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; /** * @author Michael Ruf @@ -36,11 +36,11 @@ public PortalRegistrationData( } public Block frameBlock() { - return Registry.BLOCK.get(new Identifier(frameBlockId)); + return VersionedRegistry.block().get(new Identifier(frameBlockId)); } public Item lightWithItem() { - return Registry.ITEM.get(new Identifier(lightWithItemId)); + return VersionedRegistry.item().get(new Identifier(lightWithItemId)); } public String index() { diff --git a/src/main/resources/customportalapi-polymer.mixins.json b/src/main/resources/customportalapi-polymer.mixins.json new file mode 100644 index 0000000..9df5506 --- /dev/null +++ b/src/main/resources/customportalapi-polymer.mixins.json @@ -0,0 +1,11 @@ +{ + "required": true, + "package": "net.kyrptonaught.servercustomportals.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "VirtualPortalBlock" + ], + "injectors": { + "defaultRequire": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 8e7d596..ea1e548 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -21,11 +21,16 @@ "de.michiruf.serverportals.ServerPortalsMod" ] }, - "mixins": [], + "mixins": [ + { + "config": "customportalapi-polymer.mixins.json", + "environment": "server" + } + ], "depends": { - "fabricloader": ">=0.14.11", + "minecraft": ">=${minecraft}", + "fabricloader": ">=${fabric}", "fabric": "*", - "minecraft": "1.19.2", "owo-lib": ">=0.8.5" } } diff --git a/src/message/1.19.1/de/michiruf/serverportals/versioned/VersionedMessageSender.java b/src/message/1.19.1/de/michiruf/serverportals/versioned/VersionedMessageSender.java new file mode 100644 index 0000000..fc21337 --- /dev/null +++ b/src/message/1.19.1/de/michiruf/serverportals/versioned/VersionedMessageSender.java @@ -0,0 +1,16 @@ +package de.michiruf.serverportals.versioned; + +import com.mojang.brigadier.context.CommandContext; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.Text; + +/** + * @author Michael Ruf + * @since 2023-12-13 + */ +public class VersionedMessageSender { + + public static void send(CommandContext context, String text) { + context.getSource().sendMessage(Text.literal(text)); + } +} diff --git a/src/message/1.19/de/michiruf/serverportals/versioned/VersionedMessageSender.java b/src/message/1.19/de/michiruf/serverportals/versioned/VersionedMessageSender.java new file mode 100644 index 0000000..b05b193 --- /dev/null +++ b/src/message/1.19/de/michiruf/serverportals/versioned/VersionedMessageSender.java @@ -0,0 +1,23 @@ +package de.michiruf.serverportals.versioned; + +import com.mojang.brigadier.context.CommandContext; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.Text; + +/** + * @author Michael Ruf + * @since 2023-12-13 + */ +public class VersionedMessageSender { + + public static void send(CommandContext context, String text) { + var source = context.getSource(); + var serverPlayerEntity = source.getPlayer(); + if (serverPlayerEntity != null) { + serverPlayerEntity.sendMessage(Text.literal(text)); + } else { + // MRU: I am not entirely sure, if sendFeedback or sendError should be the option to go here + source.sendFeedback(Text.literal(text), false); + } + } +} diff --git a/src/registry/1.19.3/de/michiruf/serverportals/versioned/VersionedRegistry.java b/src/registry/1.19.3/de/michiruf/serverportals/versioned/VersionedRegistry.java new file mode 100644 index 0000000..33b0129 --- /dev/null +++ b/src/registry/1.19.3/de/michiruf/serverportals/versioned/VersionedRegistry.java @@ -0,0 +1,21 @@ +package de.michiruf.serverportals.versioned; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.registry.Registries; +import net.minecraft.registry.Registry; + +/** + * @author Michael Ruf + * @since 2023-01-18 + */ +public class VersionedRegistry { + + public static Registry block() { + return Registries.BLOCK; + } + + public static Registry item() { + return Registries.ITEM; + } +} diff --git a/src/registry/1.19/de/michiruf/serverportals/versioned/VersionedRegistry.java b/src/registry/1.19/de/michiruf/serverportals/versioned/VersionedRegistry.java new file mode 100644 index 0000000..8b91dd7 --- /dev/null +++ b/src/registry/1.19/de/michiruf/serverportals/versioned/VersionedRegistry.java @@ -0,0 +1,20 @@ +package de.michiruf.serverportals.versioned; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.util.registry.Registry; + +/** + * @author Michael Ruf + * @since 2023-01-18 + */ +public class VersionedRegistry { + + public static Registry block() { + return Registry.BLOCK; + } + + public static Registry item() { + return Registry.ITEM; + } +} \ No newline at end of file