mirror of
https://github.com/TheWhiteDog9487/RandomTeleporter.git
synced 2026-06-17 12:14:46 +08:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39027e398e | ||
|
|
50e7bb0a77 | ||
|
|
4f28e84e90 | ||
|
|
f83911a27e | ||
|
|
7254230a2c | ||
|
|
5f5172f65c | ||
|
|
e8d7f56150 | ||
|
|
6dff863d3f | ||
|
|
4137a166ae | ||
|
|
8b03098280 | ||
|
|
a0a6e1c35d | ||
|
|
5f3ca6c68f | ||
|
|
5788f78a4d | ||
|
|
2f5e154cc4 | ||
|
|
c579c266a5 | ||
|
|
62c8267311 | ||
|
|
74046be828 | ||
|
|
33e01b3d35 | ||
|
|
e7f9ac069a | ||
|
|
eb85fff326 | ||
|
|
48a5027cce | ||
|
|
62c3484c5e | ||
| d47907cdf4 | |||
| 8c55311f27 | |||
| 35ac4dd842 | |||
| 34ea09dfd9 | |||
| ad014a2b1b | |||
| 4de867d6aa | |||
| 9770b72448 | |||
| 66a1529132 | |||
| 96a69f3262 |
9
.gitattributes
vendored
Normal file
9
.gitattributes
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#
|
||||||
|
# https://help.github.com/articles/dealing-with-line-endings/
|
||||||
|
#
|
||||||
|
# Linux start script should use lf
|
||||||
|
/gradlew text eol=lf
|
||||||
|
|
||||||
|
# These are Windows script files and should use crlf
|
||||||
|
*.bat text eol=crlf
|
||||||
|
|
||||||
30
.github/workflows/build.yml
vendored
Normal file
30
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# Automatically build the project and run any configured tests for every push
|
||||||
|
# and submitted pull request. This can help catch issues that only occur on
|
||||||
|
# certain platforms or Java versions, and provides a first line of defence
|
||||||
|
# against bad commits.
|
||||||
|
|
||||||
|
name: build
|
||||||
|
on: [pull_request, push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: checkout repository
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
- name: validate gradle wrapper
|
||||||
|
uses: gradle/actions/wrapper-validation@v6
|
||||||
|
- name: setup jdk
|
||||||
|
uses: actions/setup-java@v5
|
||||||
|
with:
|
||||||
|
java-version: '25'
|
||||||
|
distribution: 'microsoft'
|
||||||
|
- name: make gradle wrapper executable
|
||||||
|
run: chmod +x ./gradlew
|
||||||
|
- name: build
|
||||||
|
run: ./gradlew build
|
||||||
|
- name: capture build artifacts
|
||||||
|
uses: actions/upload-artifact@v7
|
||||||
|
with:
|
||||||
|
name: Artifacts
|
||||||
|
path: build/libs/
|
||||||
135
README.md
135
README.md
@@ -1,61 +1,118 @@
|
|||||||
|
[//]: # (如果你是正在执行翻译任务的LLM:)
|
||||||
|
[//]: # (请将这几行注释内容翻译到你的目标语言)
|
||||||
|
[//]: # (移除下方div内部第一行和第二行的注释符号,并翻译其内容)
|
||||||
|
[//]: # (不要翻译下方div内部a标签的文本内容和链接地址)
|
||||||
|
[//]: # (不要改动下方div标签的align="center"属性)
|
||||||
|
[//]: # (不要翻译最后一段“一些小彩蛋”,直接将其从翻译版本中移除)
|
||||||
|
[//]: # (将翻译的结果放置到正确的文件内,目标文件的位置和主README.md同级,文件名格式是 README_<LANG>.md ,其中<LANG>的值是目标语言的IETF语言标签)
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<!-- <strong>注意:本文档由中文编写,使用AI翻译到其他语言。如果条件允许,建议阅读原始的中文文档而不是其他的翻译版本。</strong> -->
|
||||||
|
<!-- <br/> -->
|
||||||
|
<a href="https://github.com/TheWhiteDog9487/RandomTeleporter/blob/%E4%B8%BB%E8%A6%81/README.md">简体中文(GitHub)</a>
|
||||||
|
<a href="https://git.thewhitedog9487.xyz/TheWhiteDog9487/RandomTeleporter/src/branch/%E4%B8%BB%E8%A6%81/README.md">简体中文(Gitea)</a>
|
||||||
|
<a href="https://github.com/TheWhiteDog9487/RandomTeleporter/blob/%E4%B8%BB%E8%A6%81/README_EN.md">English(GitHub)</a>
|
||||||
|
<a href="https://git.thewhitedog9487.xyz/TheWhiteDog9487/RandomTeleporter/src/branch/%E4%B8%BB%E8%A6%81/README_EN.md">English(Gitea)</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
# 介绍
|
# 介绍
|
||||||
这个模组增加了一个命令(/rtp),用于将玩家随机传送到世界的任何一个位置。
|
这个模组增加了一个命令 `/rtp`,用于将玩家随机传送到世界的任何一个位置。
|
||||||
|
|
||||||
# 命令格式
|
# 命令格式
|
||||||
- /rtp
|
- `/rtp`
|
||||||
- /rtp <Radius(半径)>
|
- `/rtp back`
|
||||||
- /rtp <被传送玩家名(PlayerID)>
|
- `/rtp back <被传送玩家ID>`
|
||||||
- /rtp <Radius(半径)> <被传送玩家名(PlayerID)>
|
- `/rtp <被传送玩家ID> back`
|
||||||
- /rtp <被传送玩家名(PlayerID)> <Radius(半径)>
|
- `/rtp <随机半径>`
|
||||||
- /rtp <Radius(半径)> <OriginPos(随机中心,坐标)>
|
- `/rtp <被传送玩家ID>`
|
||||||
- /rtp <Radius(半径)> <被传送玩家名(PlayerID)> <OriginEntity(随机中心,实体)>
|
- `/rtp <随机半径> <被传送玩家ID>`
|
||||||
- /rtp <Radius(半径)> <被传送玩家名(PlayerID)> <OriginPos(随机中心,坐标)>
|
- `/rtp <被传送玩家ID> <随机半径>`
|
||||||
- /rtp <被传送玩家名(PlayerID)> <Radius(半径)> <OriginEntity(随机中心,实体)>
|
- `/rtp <随机半径> <随机中心点坐标>`
|
||||||
- /rtp <被传送玩家名(PlayerID)> <Radius(半径)> <OriginPos(随机中心,坐标)>
|
- `/rtp <随机半径> <被传送玩家ID> <作为随机中心的实体>`
|
||||||
|
- `/rtp <随机半径> <被传送玩家ID> <随机中心点坐标>`
|
||||||
|
- `/rtp <被传送玩家ID> <随机半径> <作为随机中心的实体>`
|
||||||
|
- `/rtp <被传送玩家ID> <随机半径> <随机中心点坐标>`
|
||||||
|
- `/rtp <随机区域起点坐标> <随机区域终点坐标>`
|
||||||
|
- `/rtp <随机区域起点坐标> <随机区域终点坐标> <被传送玩家ID>`
|
||||||
|
- `/rtp <被传送玩家ID> <随机区域起点坐标> <随机区域终点坐标>`
|
||||||
|
- `/rtp <随机区域起点实体> <随机区域终点实体>`
|
||||||
|
- `/rtp <随机区域起点实体> <随机区域终点实体> <被传送玩家ID>`
|
||||||
|
|
||||||
## 命令示例
|
## 命令示例
|
||||||
- /rtp
|
- `/rtp`
|
||||||
将执行命令的玩家随机传送到以(0,0)为中心点,2.9e7 - 1e4作为随机半径的范围内的随机一点
|
将执行命令的玩家随机传送到以`(0,0)`为中心点, $2.9 \times 10^7 - 10^4$ 作为随机半径的范围内的随机一点
|
||||||
2.9e+7 = 2.9 x 10^7 = 29000000 = 两千九百万
|
$2.9 \times 10^7 = 29,000,000$ = 两千九百万
|
||||||
1e4 = 10^4 = 10000 = 一万
|
$10^4 = 10,000$ = 一万
|
||||||
|
|
||||||
- /rtp 1000
|
- `/rtp back`
|
||||||
将执行命令的玩家随机传送到以(0,0)为中心点,1000作为随机半径的范围内的随机一点
|
将执行命令的玩家传送回最近一次使用随机传送前的位置
|
||||||
|
**注意:这个功能保存的上一次随机传送前的位置信息只会在游戏(服务器)运行期间存在,游戏(服务器)关闭后就会丢失**
|
||||||
|
|
||||||
- /rtp TheWhiteDog9487
|
- `/rtp back TheWhiteDog9487`
|
||||||
将TheWhiteDog9487随机传送到以(0,0)为中心点,2.9e7 - 1e4作为随机半径的范围内的随机一点
|
将TheWhiteDog9487传送回其最近一次使用随机传送前的位置
|
||||||
|
|
||||||
- /rtp TheWhiteDog9487 1000
|
- `/rtp TheWhiteDog9487 back`
|
||||||
将TheWhiteDog9487随机传送到以(0,0)为中心点,1000作为随机半径的范围内的随机一点
|
将TheWhiteDog9487传送回其最近一次使用随机传送前的位置
|
||||||
|
|
||||||
- /rtp 1000 TheWhiteDog9487
|
- `/rtp 1000`
|
||||||
将TheWhiteDog9487随机传送到以(0,0)为中心点,1000作为随机半径的范围内的随机一点
|
将执行命令的玩家随机传送到以`(0,0)`为中心点,1000作为随机半径的范围内的随机一点
|
||||||
|
|
||||||
- /rtp 1000 10000 10000
|
- `/rtp TheWhiteDog9487`
|
||||||
将执行命令的玩家随机传送到以(10000,10000)为中心点,1000作为随机半径的范围内的随机一点
|
将TheWhiteDog9487随机传送到以`(0,0)`为中心点, $2.9 \times 10^7 - 10^4$ 作为随机半径的范围内的随机一点
|
||||||
|
|
||||||
- /rtp 1000 TheWhiteDog9487 TheWhiteDog_CN
|
- `/rtp TheWhiteDog9487 1000`
|
||||||
|
将TheWhiteDog9487随机传送到以`(0,0)`为中心点,1000作为随机半径的范围内的随机一点
|
||||||
|
|
||||||
|
- `/rtp 1000 TheWhiteDog9487`
|
||||||
|
将TheWhiteDog9487随机传送到以`(0,0)`为中心点,1000作为随机半径的范围内的随机一点
|
||||||
|
|
||||||
|
- `/rtp 1000 10000 10000`
|
||||||
|
将执行命令的玩家随机传送到以`(10000,10000)`为中心点,1000作为随机半径的范围内的随机一点
|
||||||
|
|
||||||
|
- `/rtp 1000 TheWhiteDog9487 TheWhiteDog_CN`
|
||||||
将TheWhiteDog9487随机传送到以TheWhiteDog_CN所在位置为中心点,1000作为随机半径的范围内的随机一点
|
将TheWhiteDog9487随机传送到以TheWhiteDog_CN所在位置为中心点,1000作为随机半径的范围内的随机一点
|
||||||
|
|
||||||
- /rtp 1000 TheWhiteDog9487 10000 10000
|
- `/rtp 1000 TheWhiteDog9487 10000 10000`
|
||||||
将TheWhiteDog9487随机传送到以(10000,10000)为中心点,1000作为随机半径的范围内的随机一点
|
将TheWhiteDog9487随机传送到以`(10000,10000)`为中心点,1000作为随机半径的范围内的随机一点
|
||||||
|
|
||||||
- /rtp TheWhiteDog9487 1000 TheWhiteDog_CN
|
- `/rtp TheWhiteDog9487 1000 TheWhiteDog_CN`
|
||||||
将TheWhiteDog9487随机传送到以TheWhiteDog_CN所在位置为中心点,1000作为随机半径的范围内的随机一点
|
将TheWhiteDog9487随机传送到以TheWhiteDog_CN所在位置为中心点,1000作为随机半径的范围内的随机一点
|
||||||
|
|
||||||
- /rtp TheWhiteDog9487 1000 10000 10000
|
- `/rtp TheWhiteDog9487 1000 10000 10000`
|
||||||
将TheWhiteDog9487随机传送到以(10000,10000)为中心点,1000作为随机半径的范围内的随机一点
|
将TheWhiteDog9487随机传送到以`(10000,10000)`为中心点,1000作为随机半径的范围内的随机一点
|
||||||
|
|
||||||
|
- `/rtp 10000.0 10000.0 20000.0 20000.0`
|
||||||
|
将执行命令的玩家随机传送到以`(10000,10000)`,`(20000,10000)`,`(20000,20000)`,`(10000,20000)`四个顶点围成的长方形区域内的随机一点
|
||||||
|
您需要提供的坐标是这个长方形的任意一个顶点和这个顶点对应的斜对角顶点的位置
|
||||||
|
|
||||||
|
- `/rtp TheWhiteDog9487 10000.0 10000.0 20000.0 20000.0`
|
||||||
|
将TheWhiteDog9487随机传送到以`(10000,10000)`,`(20000,10000)`,`(20000,20000)`,`(10000,20000)`四个顶点围成的长方形区域内的随机一点
|
||||||
|
|
||||||
|
- `/rtp 10000.0 10000.0 20000.0 20000.0 TheWhiteDog9487`
|
||||||
|
将TheWhiteDog9487随机传送到以`(10000,10000)`,`(20000,10000)`,`(20000,20000)`,`(10000,20000)`四个顶点围成的长方形区域内的随机一点
|
||||||
|
|
||||||
|
- `/rtp TheWhiteDog9487 TheWhiteDog_CN`
|
||||||
|
将命令执行者传送到以TheWhiteDog9487和TheWhiteDog_CN当前所在位置为对角线的长方形区域内的随机一点
|
||||||
|
|
||||||
|
- `/rtp TheWhiteDog9487 TheWhiteDog_CN TheWhiteDog4568`
|
||||||
|
将TheWhiteDog4568随机传送到以TheWhiteDog9487和TheWhiteDog_CN当前所在位置为对角线的长方形区域内的随机一点
|
||||||
|
|
||||||
### 特别提示
|
### 特别提示
|
||||||
/rtp <Radius(半径)> <Origin(随机中心,实体)> 这种格式不存在。
|
`/rtp <随机半径> <作为随机中心的实体>` 这种格式不存在。
|
||||||
因为第二个参数可能是被传送玩家名,也可能是做随机中心点的实体。
|
因为第二个参数可能是被传送玩家名,也可能是做随机中心点的实体。
|
||||||
这两种都是实体类型,无法区分到底是哪一种,存在歧义。
|
这两种都是实体类型,无法区分到底是哪一种,存在歧义。
|
||||||
|
同样,`/rtp <被传送玩家ID> <随机区域起点实体> <随机区域终点实体>` 这一组也是不存在的
|
||||||
|
三个参数都是实体类型,没办法区分`被传送玩家ID`是第一个还是第三个
|
||||||
|
|
||||||
# 依赖项
|
# 依赖项
|
||||||
由于我使用了fabric.api.command.v2中的CommandRegistrationCallback.EVENT来向游戏注册命令,所以这个模组需要依赖Fabric API
|
- [Fabric API](https://modrinth.com/mod/fabric-api)
|
||||||
|
- [Fabric Language Kotlin](https://modrinth.com/mod/fabric-language-kotlin)
|
||||||
|
|
||||||
|
# 支持的游戏版本
|
||||||
|
目前仅提供对最新正式版游戏的活跃支持
|
||||||
|
|
||||||
# 关于玩家权限
|
# 关于玩家权限
|
||||||
我参照原版的 /tp 命令,给 /rtp 设置了2级的权限要求。
|
我参照原版的 `/tp` 命令,给 `/rtp` 设置了2级的权限要求。
|
||||||
如果是原版或者类原版,你只需要让玩家有作弊的权限就可以用。
|
如果是原版或者类原版,你只需要让玩家有作弊的权限就可以用。
|
||||||
插件服务器方面那些具体的权限分配,因为我自己没玩过所以我也没法给出参考意见。
|
插件服务器方面那些具体的权限分配,因为我自己没玩过所以我也没法给出参考意见。
|
||||||
|
|
||||||
@@ -67,7 +124,7 @@
|
|||||||
2. 单人游戏 + 开放局域网
|
2. 单人游戏 + 开放局域网
|
||||||
1. 使用客户端内置的服务器,开放局域网的那位玩家的客户端需要安装
|
1. 使用客户端内置的服务器,开放局域网的那位玩家的客户端需要安装
|
||||||
2. 其他加入游戏的玩家不需要安装
|
2. 其他加入游戏的玩家不需要安装
|
||||||
3. 使用独立服务器(类似server.jar这种文件)
|
3. 使用独立服务器(类似`server.jar`这种文件)
|
||||||
1. 服务器需要安装
|
1. 服务器需要安装
|
||||||
2. 客户端不需要
|
2. 客户端不需要
|
||||||
|
|
||||||
@@ -75,11 +132,11 @@
|
|||||||
如果有查看多语言翻译文本的需求 ,那建议还是都装一下吧。**
|
如果有查看多语言翻译文本的需求 ,那建议还是都装一下吧。**
|
||||||
|
|
||||||
# 一些小彩蛋
|
# 一些小彩蛋
|
||||||
你可以使用 /随机传送 来替代 /rtp
|
你可以使用 `/随机传送` 来替代 `/rtp`
|
||||||
没错,Minecraft的命令是可以存在非ASCII字符的,所以我就整了一个
|
没错,Minecraft的命令是可以存在非ASCII字符的,所以我就整了一个
|
||||||
例如:
|
例如:
|
||||||
- /rtp TheWhiteDog9487 1000
|
- `/rtp TheWhiteDog9487 1000`
|
||||||
- /随机传送 TheWhiteDog9487 1000
|
- `/随机传送 TheWhiteDog9487 1000`
|
||||||
|
|
||||||
这两个命令的效果没有任何差别
|
这两个命令的效果没有任何差别
|
||||||
玩家权限限制和 /rtp 当然也是一样的,都是2级
|
玩家权限限制和 `/rtp` 当然也是一样的,都是2级
|
||||||
125
README_EN.md
Normal file
125
README_EN.md
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
[//]: # (If you are an LLM performing a translation task:)
|
||||||
|
[//]: # (Please translate these comment lines into your target language)
|
||||||
|
[//]: # (Remove the comment markers from the first and second lines inside the div below, and translate their content)
|
||||||
|
[//]: # (Do not translate the text or links of the a tags inside the div below)
|
||||||
|
[//]: # (Do not change the align="center" attribute of the div below)
|
||||||
|
[//]: # (Do not translate the final “Some Easter Eggs” section; remove it directly from the translated version)
|
||||||
|
[//]: # (Place the translated result in the correct file, alongside the main README.md, using the filename format README_<LANG>.md, where <LANG> is the IETF language tag of the target language)
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<strong>Note: This document was originally written in Chinese and translated into other languages using AI. If circumstances permit, it's recommended to read the original Chinese documentation instead of other translated versions.</strong>
|
||||||
|
<br/>
|
||||||
|
<a href="https://github.com/TheWhiteDog9487/RandomTeleporter/blob/%E4%B8%BB%E8%A6%81/README.md">简体中文(GitHub)</a>
|
||||||
|
<a href="https://git.thewhitedog9487.xyz/TheWhiteDog9487/RandomTeleporter/src/branch/%E4%B8%BB%E8%A6%81/README.md">简体中文(Gitea)</a>
|
||||||
|
<a href="https://github.com/TheWhiteDog9487/RandomTeleporter/blob/%E4%B8%BB%E8%A6%81/README_EN.md">English(GitHub)</a>
|
||||||
|
<a href="https://git.thewhitedog9487.xyz/TheWhiteDog9487/RandomTeleporter/src/branch/%E4%B8%BB%E8%A6%81/README_EN.md">English(Gitea)</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
# Introduction
|
||||||
|
This mod adds a command, `/rtp`, which randomly teleports players to any location in the world.
|
||||||
|
|
||||||
|
# Command Formats
|
||||||
|
- `/rtp`
|
||||||
|
- `/rtp back`
|
||||||
|
- `/rtp back <PlayerID>`
|
||||||
|
- `/rtp <PlayerID> back`
|
||||||
|
- `/rtp <Radius>`
|
||||||
|
- `/rtp <PlayerID>`
|
||||||
|
- `/rtp <Radius> <PlayerID>`
|
||||||
|
- `/rtp <PlayerID> <Radius>`
|
||||||
|
- `/rtp <Radius> <OriginPos>`
|
||||||
|
- `/rtp <Radius> <PlayerID> <OriginEntity>`
|
||||||
|
- `/rtp <Radius> <PlayerID> <OriginPos>`
|
||||||
|
- `/rtp <PlayerID> <Radius> <OriginEntity>`
|
||||||
|
- `/rtp <PlayerID> <Radius> <OriginPos>`
|
||||||
|
- `/rtp <RegionFromPos> <RegionToPos>`
|
||||||
|
- `/rtp <RegionFromPos> <RegionToPos> <PlayerID>`
|
||||||
|
- `/rtp <PlayerID> <RegionFromPos> <RegionToPos>`
|
||||||
|
- `/rtp <RegionFromEntity> <RegionToEntity>`
|
||||||
|
- `/rtp <RegionFromEntity> <RegionToEntity> <PlayerID>`
|
||||||
|
|
||||||
|
## Command Examples
|
||||||
|
- `/rtp`
|
||||||
|
Teleports the player executing the command to a random point within the area centered at `(0,0)` with a random radius of $2.9 \times 10^7 - 10^4$.
|
||||||
|
$2.9 \times 10^7 = 29,000,000$ = twenty-nine million
|
||||||
|
$10^4 = 10,000$ = ten thousand
|
||||||
|
|
||||||
|
- `/rtp back`
|
||||||
|
Teleports the player back to their position before the most recent random teleport.
|
||||||
|
**Note: The previous-position information saved by this feature exists only while the game (server) is running. It will be lost after the game (server) is closed.**
|
||||||
|
|
||||||
|
- `/rtp back TheWhiteDog9487`
|
||||||
|
Teleports `TheWhiteDog9487` back to their position before their last random teleport.
|
||||||
|
|
||||||
|
- `/rtp TheWhiteDog9487 back`
|
||||||
|
Teleports `TheWhiteDog9487` back to their position before their last random teleport.
|
||||||
|
|
||||||
|
- `/rtp 1000`
|
||||||
|
Teleports the player to a random point within a radius of `1000` centered at `(0,0)`.
|
||||||
|
|
||||||
|
- `/rtp TheWhiteDog9487`
|
||||||
|
Teleports `TheWhiteDog9487` to a random point within the area centered at `(0,0)` with a random radius of $2.9 \times 10^7 - 10^4$.
|
||||||
|
|
||||||
|
- `/rtp TheWhiteDog9487 1000`
|
||||||
|
Teleports `TheWhiteDog9487` to a random point within a radius of `1000` centered at `(0,0)`.
|
||||||
|
|
||||||
|
- `/rtp 1000 TheWhiteDog9487`
|
||||||
|
Teleports `TheWhiteDog9487` to a random point within a radius of `1000` centered at `(0,0)`.
|
||||||
|
|
||||||
|
- `/rtp 1000 10000 10000`
|
||||||
|
Teleports the player to a random point within a radius of `1000` centered at `(10000,10000)`.
|
||||||
|
|
||||||
|
- `/rtp 1000 TheWhiteDog9487 TheWhiteDog_CN`
|
||||||
|
Teleports `TheWhiteDog9487` to a random point within a radius of `1000` centered at `TheWhiteDog_CN`'s location.
|
||||||
|
|
||||||
|
- `/rtp 1000 TheWhiteDog9487 10000 10000`
|
||||||
|
Teleports `TheWhiteDog9487` to a random point within a radius of `1000` centered at `(10000,10000)`.
|
||||||
|
|
||||||
|
- `/rtp TheWhiteDog9487 1000 TheWhiteDog_CN`
|
||||||
|
Teleports `TheWhiteDog9487` to a random point within a radius of `1000` centered at `TheWhiteDog_CN`'s location.
|
||||||
|
|
||||||
|
- `/rtp TheWhiteDog9487 1000 10000 10000`
|
||||||
|
Teleports `TheWhiteDog9487` to a random point within a radius of `1000` centered at `(10000,10000)`.
|
||||||
|
|
||||||
|
- `/rtp 10000.0 10000.0 20000.0 20000.0`
|
||||||
|
Teleports the player to a random point within the rectangular region formed by the vertices `(10000,10000)`, `(20000,10000)`, `(20000,20000)`, and `(10000,20000)`.
|
||||||
|
You only need to provide any one vertex of the rectangle and the diagonally opposite vertex.
|
||||||
|
|
||||||
|
- `/rtp TheWhiteDog9487 10000.0 10000.0 20000.0 20000.0`
|
||||||
|
Teleports `TheWhiteDog9487` to a random point within the same rectangular region described above.
|
||||||
|
|
||||||
|
- `/rtp 10000.0 10000.0 20000.0 20000.0 TheWhiteDog9487`
|
||||||
|
Teleports `TheWhiteDog9487` to a random point within the same rectangular region described above.
|
||||||
|
|
||||||
|
- `/rtp TheWhiteDog9487 TheWhiteDog_CN`
|
||||||
|
Teleports the command executor to a random point within a rectangular region whose diagonals are the current positions of `TheWhiteDog9487` and `TheWhiteDog_CN`.
|
||||||
|
|
||||||
|
- `/rtp TheWhiteDog9487 TheWhiteDog_CN TheWhiteDog4568`
|
||||||
|
Teleports `TheWhiteDog4568` to a random point within a rectangular region whose diagonals are the current positions of `TheWhiteDog9487` and `TheWhiteDog_CN`.
|
||||||
|
|
||||||
|
### Special Notes
|
||||||
|
The format `/rtp <Radius> <OriginEntity>` does not exist because the second parameter could be either the teleported player's name or the entity used as the random center. Both are entity types, so there is no way to tell which one it is. Likewise, `/rtp <PlayerID> <RegionFromEntity> <RegionToEntity>` does not exist either, because all three parameters are entity types, making it impossible to determine which one is the player ID.
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
- [Fabric API](https://modrinth.com/mod/fabric-api)
|
||||||
|
- [Fabric Language Kotlin](https://modrinth.com/mod/fabric-language-kotlin)
|
||||||
|
|
||||||
|
# Supported Game Versions
|
||||||
|
Currently, only the latest official release is actively supported.
|
||||||
|
|
||||||
|
# About Player Permissions
|
||||||
|
Following the vanilla `/tp` command, `/rtp` is set to require permission level `2`. In vanilla or vanilla-like environments, players only need cheat permissions enabled to use it. As for plugin servers, I do not have enough firsthand experience to give specific advice about permission setup.
|
||||||
|
|
||||||
|
# Install on the Client or on the Server?
|
||||||
|
It depends on the case:
|
||||||
|
1. Singleplayer
|
||||||
|
1. There is no physical server, so the server side does not matter.
|
||||||
|
2. Installing it on the client is enough.
|
||||||
|
2. Singleplayer + Open to LAN
|
||||||
|
1. This uses the client’s built-in server, so the player who opens the LAN world needs the mod installed on their client.
|
||||||
|
2. Other players who join do not need to install it.
|
||||||
|
3. Dedicated server (something like a `server.jar` file)
|
||||||
|
1. The server needs the mod installed.
|
||||||
|
2. Clients do not need it.
|
||||||
|
|
||||||
|
**Note: In cases 2 and 3, if other players do not install this mod, they will not be able to see the command feedback in the correct translated language, and the default display in that case is Chinese text. If you need to view multilingual translation text, it is probably best for everyone to install it.**
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
|
import java.nio.file.Paths
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("fabric-loom") version "1.9-SNAPSHOT"
|
id("net.fabricmc.fabric-loom")
|
||||||
id("maven-publish")
|
`maven-publish`
|
||||||
|
id("org.jetbrains.kotlin.jvm") version "2.4.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
version = "${project.extra["mod_version"]}"
|
version = providers.gradleProperty("mod_version").get()
|
||||||
group = project.extra["maven_group"] as String
|
group = providers.gradleProperty("maven_group").get()
|
||||||
|
|
||||||
base {
|
|
||||||
archivesName.set(project.extra["archives_base_name"] as String)
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
// Add repositories to retrieve artifacts from in here.
|
// Add repositories to retrieve artifacts from in here.
|
||||||
@@ -21,45 +21,72 @@ repositories {
|
|||||||
url = uri("https://maven.terraformersmc.com/") }
|
url = uri("https://maven.terraformersmc.com/") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
val MixinJarPath = configurations.loaderLibraries.get().resolvedConfiguration
|
||||||
|
.resolvedArtifacts
|
||||||
|
.find { it.moduleVersion.id.group == "net.fabricmc" && it.moduleVersion.id.name == "sponge-mixin" }!!
|
||||||
|
.file
|
||||||
|
val IsSupportDceVM = Paths.get(System.getProperty("java.home"))
|
||||||
|
.resolve("bin")
|
||||||
|
.resolve("java")
|
||||||
|
.toFile()
|
||||||
|
.let {
|
||||||
|
val ReturnCode = ProcessBuilder(it.absolutePath, "-XX:+AllowEnhancedClassRedefinition", "-version")
|
||||||
|
.start()
|
||||||
|
.waitFor()
|
||||||
|
return@let ReturnCode == 0 }
|
||||||
|
loom.runs.named("client") {
|
||||||
|
jvmArguments.add("-javaagent:${MixinJarPath.absolutePath}")
|
||||||
|
if (IsSupportDceVM == true) jvmArguments.add("-XX:+AllowEnhancedClassRedefinition") }
|
||||||
|
loom.runs.named("server") {
|
||||||
|
jvmArguments.add("-javaagent:${MixinJarPath.absolutePath}")
|
||||||
|
if (IsSupportDceVM == true) jvmArguments.add("-XX:+AllowEnhancedClassRedefinition") } }
|
||||||
|
|
||||||
loom {
|
loom {
|
||||||
splitEnvironmentSourceSets()
|
splitEnvironmentSourceSets()
|
||||||
|
|
||||||
mods {
|
mods {
|
||||||
create("randomteleporter") {
|
register("randomteleporter") {
|
||||||
sourceSet(sourceSets["main"])
|
sourceSet(sourceSets.main.get())
|
||||||
sourceSet(sourceSets["client"])
|
sourceSet(sourceSets.getByName("client"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// To change the versions see the gradle.properties file
|
// To change the versions see the gradle.properties file
|
||||||
minecraft("com.mojang:minecraft:${project.extra["minecraft_version"]}")
|
minecraft("com.mojang:minecraft:${providers.gradleProperty("minecraft_version").get()}")
|
||||||
mappings("net.fabricmc:yarn:${project.extra["yarn_mappings"]}:v2")
|
|
||||||
modImplementation("net.fabricmc:fabric-loader:${project.extra["loader_version"]}")
|
implementation("net.fabricmc:fabric-loader:${providers.gradleProperty("loader_version").get()}")
|
||||||
|
|
||||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||||
modImplementation("net.fabricmc.fabric-api:fabric-api:${project.extra["fabric_version"]}")
|
implementation("net.fabricmc.fabric-api:fabric-api:${providers.gradleProperty("fabric_api_version").get()}")
|
||||||
|
implementation("net.fabricmc:fabric-language-kotlin:${providers.gradleProperty("fabric_kotlin_version").get()}")
|
||||||
|
|
||||||
// Uncomment the following line to enable the deprecated Fabric API modules.
|
// Uncomment the following line to enable the deprecated Fabric API modules.
|
||||||
// These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time.
|
// These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time.
|
||||||
// "modImplementation"("net.fabricmc.fabric-api:fabric-api-deprecated:${project.extra["fabric_version"]}")
|
// "modImplementation"("net.fabricmc.fabric-api:fabric-api-deprecated:${project.extra["fabric_version"]}")
|
||||||
|
|
||||||
// ↓ 开发测试用
|
// ↓ 开发测试用
|
||||||
modRuntimeOnly("com.terraformersmc:modmenu:${project.extra["modmenu_version"]}")
|
runtimeOnly("com.terraformersmc:modmenu:${providers.gradleProperty("modmenu_version").get()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tasks.processResources {
|
tasks.processResources {
|
||||||
inputs.property("version", project.version)
|
val version = version
|
||||||
|
inputs.property("version", version)
|
||||||
|
|
||||||
filesMatching("fabric.mod.json") {
|
filesMatching("fabric.mod.json") {
|
||||||
expand("version" to project.version)
|
expand("version" to version)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<JavaCompile> {
|
tasks.withType<JavaCompile>().configureEach {
|
||||||
options.release.set(21)
|
options.release = 25 }
|
||||||
}
|
|
||||||
|
kotlin {
|
||||||
|
compilerOptions {
|
||||||
|
jvmTarget = JvmTarget.JVM_25 } }
|
||||||
|
|
||||||
java {
|
java {
|
||||||
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
|
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
|
||||||
@@ -67,27 +94,26 @@ java {
|
|||||||
// If you remove this line, sources will not be generated.
|
// If you remove this line, sources will not be generated.
|
||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_21
|
sourceCompatibility = JavaVersion.VERSION_25
|
||||||
targetCompatibility = JavaVersion.VERSION_21
|
targetCompatibility = JavaVersion.VERSION_25 }
|
||||||
}
|
|
||||||
|
|
||||||
tasks.jar {
|
tasks.jar {
|
||||||
from("LICENSE") {
|
val projectName = project.name
|
||||||
rename { "${it}_${project.base.archivesName.get()}" } }
|
inputs.property("projectName", projectName)
|
||||||
}
|
|
||||||
|
from("LICENSE") {
|
||||||
|
rename { "${it}_$projectName" } }
|
||||||
|
|
||||||
tasks.remapJar{
|
|
||||||
// https://docs.gradle.org/current/dsl/org.gradle.api.tasks.bundling.Jar.html#org.gradle.api.tasks.bundling.Jar:archiveFileName
|
// https://docs.gradle.org/current/dsl/org.gradle.api.tasks.bundling.Jar.html#org.gradle.api.tasks.bundling.Jar:archiveFileName
|
||||||
// 用这个属性设置jar包的文件名格式
|
archiveFileName = "RandomTeleporter-${project.version} mc${project.extra["minecraft_version"]}.jar"}
|
||||||
// 别用上面那个Jar任务的配置,会被remapJar覆盖掉
|
|
||||||
archiveFileName = "${project.base.archivesName.get()}-${project.version} mc${project.extra["minecraft_version"]}.jar"}
|
tasks.named<Jar>("sourcesJar") {
|
||||||
tasks.remapSourcesJar{
|
archiveFileName = "RandomTeleporter-${project.version} mc${project.extra["minecraft_version"]}-sources.jar"}
|
||||||
archiveFileName = "${project.base.archivesName.get()}-${project.version} mc${project.extra["minecraft_version"]}-sources.jar"}
|
|
||||||
|
|
||||||
// configure the maven publication
|
// configure the maven publication
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
create<MavenPublication>("mavenJava") {
|
register<MavenPublication>("mavenJava") {
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,24 +4,22 @@ org.gradle.parallel=true
|
|||||||
|
|
||||||
# Fabric Properties
|
# Fabric Properties
|
||||||
# check these on https://fabricmc.net/develop
|
# check these on https://fabricmc.net/develop
|
||||||
minecraft_version=1.21.4
|
minecraft_version=26.2
|
||||||
yarn_mappings=1.21.4+build.1
|
loader_version=0.19.3
|
||||||
loader_version=0.16.9
|
loom_version=1.17-SNAPSHOT
|
||||||
|
|
||||||
|
# Fabric API
|
||||||
|
fabric_api_version=0.152.1+26.2
|
||||||
|
|
||||||
|
# https://modrinth.com/mod/fabric-language-kotlin/versions
|
||||||
|
fabric_kotlin_version=1.13.12+kotlin.2.4.0
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=0.3.5
|
mod_version=0.5.3
|
||||||
maven_group=xyz.thewhitedog9487
|
maven_group=xyz.thewhitedog9487
|
||||||
archives_base_name=RandomTeleporter
|
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
fabric_version=0.110.5+1.21.4
|
|
||||||
|
|
||||||
# https://modrinth.com/mod/modmenu/versions
|
# https://modrinth.com/mod/modmenu/versions
|
||||||
# https://maven.terraformersmc.com/releases/com/terraformersmc/modmenu
|
# https://maven.terraformersmc.com/releases/com/terraformersmc/modmenu
|
||||||
modmenu_version=13.0.0-beta.1
|
modmenu_version=20.0.0-beta.2
|
||||||
|
|
||||||
# loom_libraries_base=https://bmclapi2.bangbang93.com/maven/
|
|
||||||
# loom_resources_base=https://bmclapi2.bangbang93.com/assets/
|
|
||||||
# loom_version_manifests=https://bmclapi2.bangbang93.com/mc/game/version_manifest.json
|
|
||||||
# loom_experimental_versions=https://maven.fabricmc.net/net/minecraft/experimental_versions.json
|
|
||||||
# loom_fabric_repository=https://repository.hanbings.io/proxy/
|
|
||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https://services.gradle.org/distributions/gradle-8.11.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-all.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
27
gradlew
vendored
27
gradlew
vendored
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright © 2015-2021 the original authors.
|
# Copyright © 2015 the original authors.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -15,6 +15,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
@@ -55,7 +57,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
@@ -84,7 +86,7 @@ done
|
|||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
@@ -112,7 +114,6 @@ case "$( uname )" in #(
|
|||||||
NONSTOP* ) nonstop=true ;;
|
NONSTOP* ) nonstop=true ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
@@ -145,7 +146,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
max*)
|
max*)
|
||||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
# shellcheck disable=SC3045
|
# shellcheck disable=SC2039,SC3045
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
warn "Could not query maximum file descriptor limit"
|
warn "Could not query maximum file descriptor limit"
|
||||||
esac
|
esac
|
||||||
@@ -153,7 +154,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||||||
'' | soft) :;; #(
|
'' | soft) :;; #(
|
||||||
*)
|
*)
|
||||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
# shellcheck disable=SC3045
|
# shellcheck disable=SC2039,SC3045
|
||||||
ulimit -n "$MAX_FD" ||
|
ulimit -n "$MAX_FD" ||
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
esac
|
esac
|
||||||
@@ -170,7 +171,6 @@ fi
|
|||||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
if "$cygwin" || "$msys" ; then
|
if "$cygwin" || "$msys" ; then
|
||||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
|
||||||
|
|
||||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
@@ -202,16 +202,15 @@ fi
|
|||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Collect all arguments for the java command;
|
# Collect all arguments for the java command:
|
||||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
# shell script including quotes and variable substitutions, so put them in
|
# and any embedded shellness will be escaped.
|
||||||
# double quotes to make sure that they get re-expanded; and
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
# * put everything else in single quotes, so that it's not re-expanded.
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
-classpath "$CLASSPATH" \
|
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||||
org.gradle.wrapper.GradleWrapperMain \
|
|
||||||
"$@"
|
"$@"
|
||||||
|
|
||||||
# Stop when "xargs" is not available.
|
# Stop when "xargs" is not available.
|
||||||
|
|||||||
25
gradlew.bat
vendored
25
gradlew.bat
vendored
@@ -13,6 +13,8 @@
|
|||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
|
|||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
@@ -57,22 +59,21 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
|||||||
@@ -6,4 +6,11 @@ pluginManagement {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("net.fabricmc.fabric-loom") version providers.gradleProperty("loom_version")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should match your modid
|
||||||
|
rootProject.name = "randomteleporter"
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
package xyz.thewhitedog9487;
|
|
||||||
|
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
|
||||||
|
|
||||||
public class RandomTeleporterClient implements ClientModInitializer {
|
|
||||||
@Override
|
|
||||||
public void onInitializeClient() {
|
|
||||||
// This entrypoint is suitable for setting up client-specific logic, such as rendering.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
package xyz.thewhitedog9487.mixin.client;
|
package xyz.thewhitedog9487.client.mixin;
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.Minecraft;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
@Mixin(MinecraftClient.class)
|
@Mixin(Minecraft.class)
|
||||||
public class ExampleClientMixin {
|
public class ExampleClientMixin {
|
||||||
@Inject(at = @At("HEAD"), method = "run")
|
@Inject(at = @At("HEAD"), method = "run")
|
||||||
private void run(CallbackInfo info) {
|
private void run(CallbackInfo info) {
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package xyz.thewhitedog9487.client
|
||||||
|
|
||||||
|
import net.fabricmc.api.ClientModInitializer
|
||||||
|
|
||||||
|
object RandomTeleporterClient : ClientModInitializer {
|
||||||
|
override fun onInitializeClient() {
|
||||||
|
// This entrypoint is suitable for setting up client-specific logic, such as rendering.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
{
|
{
|
||||||
"required": false,
|
"required": true,
|
||||||
"package": "xyz.thewhitedog9487.mixin.client",
|
"package": "xyz.thewhitedog9487.client.mixin",
|
||||||
"compatibilityLevel": "JAVA_21",
|
"compatibilityLevel": "JAVA_25",
|
||||||
"client": [
|
"client": [
|
||||||
|
"ExampleClientMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
},
|
||||||
|
"overwrites": {
|
||||||
|
"requireAnnotations": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,262 +0,0 @@
|
|||||||
package xyz.thewhitedog9487;
|
|
||||||
|
|
||||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
|
||||||
import net.minecraft.block.Blocks;
|
|
||||||
import net.minecraft.command.argument.EntityArgumentType;
|
|
||||||
import net.minecraft.command.argument.Vec2ArgumentType;
|
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.util.math.Vec2f;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.SplittableRandom;
|
|
||||||
|
|
||||||
import static net.minecraft.server.command.CommandManager.argument;
|
|
||||||
import static net.minecraft.server.command.CommandManager.literal;
|
|
||||||
|
|
||||||
public class CommandRegister {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 世界边界
|
|
||||||
* <br>
|
|
||||||
* @see <a href="https://zh.minecraft.wiki/w/%E4%B8%96%E7%95%8C%E8%BE%B9%E7%95%8C#%E5%A4%A7%E5%B0%8F">Minecraft Wiki (中文)</a>
|
|
||||||
* @see <a href="https://minecraft.wiki/w/World_border#General_information">Minecraft Wiki (English)</a>
|
|
||||||
*/
|
|
||||||
final static Integer WorldBorder = (int) 2.9e7;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行命令所需权限等级
|
|
||||||
* @see net.minecraft.server.command.TeleportCommand
|
|
||||||
*/
|
|
||||||
final static byte PermissionLevel = 2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用Fabric API向游戏内注册命令
|
|
||||||
* @param Name 根命令名
|
|
||||||
* <br>
|
|
||||||
* @see <a href="https://docs.fabricmc.net/zh_cn/develop/commands/basics">Fabric Wiki (新样式,中文)</a>
|
|
||||||
* @see <a href="https://wiki.fabricmc.net/zh_cn:tutorial:commands">Fabric Wiki (旧样式,中文)</a>
|
|
||||||
* @see <a href="https://docs.fabricmc.net/develop/commands/basics">Fabric Wiki (New style,English)</a>
|
|
||||||
* @see <a href="https://wiki.fabricmc.net/tutorial:commands">Fabric Wiki (Old style,English)</a>
|
|
||||||
*/
|
|
||||||
public static void Register(String Name){
|
|
||||||
// /rtp
|
|
||||||
CommandRegistrationCallback.EVENT
|
|
||||||
.register((dispatcher, registryAccess, environment) ->{
|
|
||||||
dispatcher.register(literal(Name)
|
|
||||||
.requires(source -> source.hasPermissionLevel(PermissionLevel))
|
|
||||||
.executes(context -> execute_command(
|
|
||||||
context.getSource(),null,null, null)));});
|
|
||||||
|
|
||||||
// /rtp <Radius(半径)>
|
|
||||||
CommandRegistrationCallback.EVENT
|
|
||||||
.register((dispatcher, registryAccess, environment) -> {
|
|
||||||
dispatcher.register(literal(Name)
|
|
||||||
.then(argument("Radius(半径)", IntegerArgumentType.integer())
|
|
||||||
.requires(source -> source.hasPermissionLevel(PermissionLevel))
|
|
||||||
.executes(context -> execute_command(
|
|
||||||
context.getSource(),
|
|
||||||
IntegerArgumentType.getInteger(context, "Radius(半径)"),
|
|
||||||
null,
|
|
||||||
null))));});
|
|
||||||
|
|
||||||
// /rtp <被传送玩家名(PlayerID)>
|
|
||||||
CommandRegistrationCallback.EVENT
|
|
||||||
.register((dispatcher, registryAccess, environment) -> {
|
|
||||||
dispatcher.register(literal(Name)
|
|
||||||
.then(argument("被传送玩家名(PlayerID)", EntityArgumentType.entity())
|
|
||||||
.requires(source -> source.hasPermissionLevel(PermissionLevel))
|
|
||||||
.executes(context -> execute_command(
|
|
||||||
context.getSource(),
|
|
||||||
null,
|
|
||||||
EntityArgumentType.getEntity(context,"被传送玩家名(PlayerID)"),
|
|
||||||
null))));});
|
|
||||||
|
|
||||||
// /rtp <Radius(半径)> <被传送玩家名(PlayerID)>
|
|
||||||
CommandRegistrationCallback.EVENT
|
|
||||||
.register((dispatcher, registryAccess, environment) -> {
|
|
||||||
dispatcher.register(literal(Name)
|
|
||||||
.then(argument("Radius(半径)", IntegerArgumentType.integer())
|
|
||||||
.then(argument("被传送玩家名(PlayerID)", EntityArgumentType.entity())
|
|
||||||
.requires(source -> source.hasPermissionLevel(PermissionLevel))
|
|
||||||
.executes(context -> execute_command(
|
|
||||||
context.getSource(),
|
|
||||||
IntegerArgumentType.getInteger(context, "Radius(半径)"),
|
|
||||||
EntityArgumentType.getEntity(context,"被传送玩家名(PlayerID)"),
|
|
||||||
null)))));});
|
|
||||||
|
|
||||||
// /rtp <被传送玩家名(PlayerID)> <Radius(半径)>
|
|
||||||
CommandRegistrationCallback.EVENT
|
|
||||||
.register((dispatcher, registryAccess, environment) -> {
|
|
||||||
dispatcher.register(literal(Name)
|
|
||||||
.then(argument("被传送玩家名(PlayerID)", EntityArgumentType.entity())
|
|
||||||
.then(argument("Radius(半径)", IntegerArgumentType.integer())
|
|
||||||
.requires(source -> source.hasPermissionLevel(PermissionLevel))
|
|
||||||
.executes(context -> execute_command(
|
|
||||||
context.getSource(),
|
|
||||||
IntegerArgumentType.getInteger(context, "Radius(半径)"),
|
|
||||||
EntityArgumentType.getEntity(context,"被传送玩家名(PlayerID)"),
|
|
||||||
null)))));});
|
|
||||||
|
|
||||||
// // /rtp <Radius(半径)> <Origin(随机中心)>
|
|
||||||
// CommandRegistrationCallback.EVENT
|
|
||||||
// .register((dispatcher, registryAccess, environment) -> {
|
|
||||||
// dispatcher.register(literal(Name)
|
|
||||||
// .then(argument("Radius(半径)", LongArgumentType.longArg())
|
|
||||||
// .then(argument("Origin(随机中心)",EntityArgumentType.player())
|
|
||||||
// .requires(source -> source.hasPermissionLevel(PermissionLevel))
|
|
||||||
// .executes(context -> execute_command_origin(
|
|
||||||
// context.getSource(),
|
|
||||||
// LongArgumentType.getLong(context, "Radius(半径)"),
|
|
||||||
// null,
|
|
||||||
// EntityArgumentType.getEntity(context,"Origin(随机中心)"))))));});
|
|
||||||
|
|
||||||
// /rtp <Radius(半径)> <OriginPos(随机中心,坐标)>
|
|
||||||
CommandRegistrationCallback.EVENT
|
|
||||||
.register((dispatcher, registryAccess, environment) -> {
|
|
||||||
dispatcher.register(literal(Name)
|
|
||||||
.then(argument("Radius(半径)", IntegerArgumentType.integer())
|
|
||||||
.then(argument("OriginPos(随机中心,坐标)",Vec2ArgumentType.vec2())
|
|
||||||
.requires(source -> source.hasPermissionLevel(PermissionLevel))
|
|
||||||
.executes(context -> execute_command(
|
|
||||||
context.getSource(),
|
|
||||||
IntegerArgumentType.getInteger(context, "Radius(半径)"),
|
|
||||||
null,
|
|
||||||
Vec2ArgumentType.getVec2(context,"OriginPos(随机中心,坐标)"))))));});
|
|
||||||
|
|
||||||
// /rtp <Radius(半径)> <被传送玩家名(PlayerID)> <OriginEntity(随机中心,实体)>
|
|
||||||
CommandRegistrationCallback.EVENT
|
|
||||||
.register((dispatcher, registryAccess, environment) -> {
|
|
||||||
dispatcher.register(literal(Name)
|
|
||||||
.then(argument("Radius(半径)", IntegerArgumentType.integer())
|
|
||||||
.then(argument("被传送玩家名(PlayerID)", EntityArgumentType.entity())
|
|
||||||
.then(argument("OriginEntity(随机中心,实体)",EntityArgumentType.entity())
|
|
||||||
.requires(source -> source.hasPermissionLevel(PermissionLevel))
|
|
||||||
.executes(context -> execute_command(
|
|
||||||
context.getSource(),
|
|
||||||
IntegerArgumentType.getInteger(context, "Radius(半径)"),
|
|
||||||
EntityArgumentType.getEntity(context,"被传送玩家名(PlayerID)"),
|
|
||||||
new Vec2f( (float) EntityArgumentType.getEntity( context,"OriginEntity(随机中心,实体)").getPos().x,
|
|
||||||
(float) EntityArgumentType.getEntity( context,"OriginEntity(随机中心,实体)").getPos().z )))))));});
|
|
||||||
|
|
||||||
// /rtp <Radius(半径)> <被传送玩家名(PlayerID)> <OriginPos(随机中心,坐标)>
|
|
||||||
CommandRegistrationCallback.EVENT
|
|
||||||
.register((dispatcher, registryAccess, environment) -> {
|
|
||||||
dispatcher.register(literal(Name)
|
|
||||||
.then(argument("Radius(半径)", IntegerArgumentType.integer())
|
|
||||||
.then(argument("被传送玩家名(PlayerID)", EntityArgumentType.entity())
|
|
||||||
.then(argument("OriginPos(随机中心,坐标)",Vec2ArgumentType.vec2())
|
|
||||||
.requires(source -> source.hasPermissionLevel(PermissionLevel))
|
|
||||||
.executes(context -> execute_command(
|
|
||||||
context.getSource(),
|
|
||||||
IntegerArgumentType.getInteger(context, "Radius(半径)"),
|
|
||||||
EntityArgumentType.getEntity(context,"被传送玩家名(PlayerID)"),
|
|
||||||
Vec2ArgumentType.getVec2(context,"OriginPos(随机中心,坐标)")))))));});
|
|
||||||
|
|
||||||
// /rtp <被传送玩家名(PlayerID)> <Radius(半径)> <OriginEntity(随机中心,实体)>
|
|
||||||
CommandRegistrationCallback.EVENT
|
|
||||||
.register((dispatcher, registryAccess, environment) -> {
|
|
||||||
dispatcher.register(literal(Name)
|
|
||||||
.then(argument("被传送玩家名(PlayerID)", EntityArgumentType.entity())
|
|
||||||
.then(argument("Radius(半径)", IntegerArgumentType.integer())
|
|
||||||
.then(argument("OriginEntity(随机中心,实体)",EntityArgumentType.entity())
|
|
||||||
.requires(source -> source.hasPermissionLevel(PermissionLevel))
|
|
||||||
.executes(context -> execute_command(
|
|
||||||
context.getSource(),
|
|
||||||
IntegerArgumentType.getInteger(context, "Radius(半径)"),
|
|
||||||
EntityArgumentType.getEntity(context,"被传送玩家名(PlayerID)"),
|
|
||||||
new Vec2f( (float) EntityArgumentType.getEntity( context,"OriginEntity(随机中心,实体)").getPos().x,
|
|
||||||
(float) EntityArgumentType.getEntity( context,"OriginEntity(随机中心,实体)").getPos().z )))))));});
|
|
||||||
|
|
||||||
// /rtp <被传送玩家名(PlayerID)> <Radius(半径)> <OriginPos(随机中心,坐标)>
|
|
||||||
CommandRegistrationCallback.EVENT
|
|
||||||
.register((dispatcher, registryAccess, environment) -> {
|
|
||||||
dispatcher.register(literal(Name)
|
|
||||||
.then(argument("被传送玩家名(PlayerID)", EntityArgumentType.entity())
|
|
||||||
.then(argument("Radius(半径)", IntegerArgumentType.integer())
|
|
||||||
.then(argument("OriginPos(随机中心,坐标)",Vec2ArgumentType.vec2())
|
|
||||||
.requires(source -> source.hasPermissionLevel(PermissionLevel))
|
|
||||||
.executes(context -> execute_command(
|
|
||||||
context.getSource(),
|
|
||||||
IntegerArgumentType.getInteger(context, "Radius(半径)"),
|
|
||||||
EntityArgumentType.getEntity(context,"被传送玩家名(PlayerID)"),
|
|
||||||
Vec2ArgumentType.getVec2(context,"OriginPos(随机中心,坐标)")))))));});}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 向游戏内注册命令
|
|
||||||
* <br>
|
|
||||||
* 是 {@link CommandRegister#Register(String)} 的包装器
|
|
||||||
* @see CommandRegister#Register(String)
|
|
||||||
*/
|
|
||||||
public static void Register(){
|
|
||||||
Register("随机传送");
|
|
||||||
Register("rtp");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param Source 命令执行者
|
|
||||||
* @param Radius 随机选择的目的坐标距离参数 {@code Origin} 的最大距离
|
|
||||||
* @param Player 被传送的玩家
|
|
||||||
* @param Origin 随机选择的目的坐标的中心
|
|
||||||
* @return 命令运行是否成功
|
|
||||||
*/
|
|
||||||
static int execute_command(ServerCommandSource Source, @Nullable Integer Radius, @Nullable Entity Player, @Nullable Vec2f Origin){
|
|
||||||
Entity entity = Player == null ? Source.getPlayer() : Player;
|
|
||||||
/*
|
|
||||||
↑
|
|
||||||
Entity entity = null;
|
|
||||||
if (Player == null){
|
|
||||||
entity = Source.getPlayer();}
|
|
||||||
else{
|
|
||||||
entity = Player;}
|
|
||||||
*/
|
|
||||||
if (entity == null) {
|
|
||||||
Source.sendFeedback(()->{ return Text.translatableWithFallback("error.no_target","不存在被传送目标,由非玩家物体执行命令时请显式指定被传送玩家ID"); }, true);
|
|
||||||
return -1;}
|
|
||||||
if (Radius == null){Radius = (int) (WorldBorder - 1e4);}
|
|
||||||
// ↑ 远离世界边界
|
|
||||||
Radius = Math.abs(Radius);
|
|
||||||
int Coordinate_X;
|
|
||||||
int Coordinate_Z;
|
|
||||||
if (Origin == null){
|
|
||||||
Coordinate_X = new SplittableRandom().nextInt(-Radius, Radius);
|
|
||||||
Coordinate_Z = new SplittableRandom().nextInt(-Radius, Radius);}
|
|
||||||
else{
|
|
||||||
Coordinate_X = new SplittableRandom().nextInt((int) Origin.x - Radius, (int) Origin.x + Radius);
|
|
||||||
Coordinate_Z = new SplittableRandom().nextInt((int) Origin.y - Radius, (int) Origin.y + Radius);}
|
|
||||||
int Coordinate_Y = 320;
|
|
||||||
for (var CurrentBlock = Source.getWorld().getBlockState(new BlockPos(Coordinate_X, Coordinate_Y, Coordinate_Z)).getBlock();
|
|
||||||
// 从世界顶层往下找,直到遇到一个非空气方块
|
|
||||||
Blocks.AIR == CurrentBlock ||
|
|
||||||
Blocks.VOID_AIR == CurrentBlock ||
|
|
||||||
Blocks.CAVE_AIR == CurrentBlock
|
|
||||||
;CurrentBlock = Source.getWorld().getBlockState(new BlockPos(Coordinate_X, Coordinate_Y, Coordinate_Z)).getBlock()){
|
|
||||||
Coordinate_Y--;}
|
|
||||||
for (int x = -1; x <= 1; x++) {
|
|
||||||
for (int z = -1; z <= 1; z++) {
|
|
||||||
// 如果传送到的位置周围一圈是空气、水或岩浆,将其替换为玻璃
|
|
||||||
var BlockPos = new BlockPos(Coordinate_X - x, Coordinate_Y, Coordinate_Z - z);
|
|
||||||
var CurrentBlock = Source.getWorld().getBlockState(BlockPos).getBlock();
|
|
||||||
if ( CurrentBlock == Blocks.AIR ||
|
|
||||||
CurrentBlock == Blocks.VOID_AIR ||
|
|
||||||
CurrentBlock == Blocks.CAVE_AIR ||
|
|
||||||
CurrentBlock == Blocks.WATER ||
|
|
||||||
CurrentBlock == Blocks.LAVA ){
|
|
||||||
// 只替换空气、水和岩浆,其余保留
|
|
||||||
Source.getWorld().setBlockState(BlockPos, Blocks.GLASS.getDefaultState());}}}
|
|
||||||
// if ( String.valueOf(entity.getWorld().getBiome(new BlockPos(Math.toIntExact(Coordinate_X), Coordinate_Y, Math.toIntExact(Coordinate_Z))).getKey()).equals("minecraft:the_void") ) {
|
|
||||||
// Coordinate_Y++;}
|
|
||||||
Coordinate_Y++;
|
|
||||||
// ↑ 高一层,人别站在土里了
|
|
||||||
entity.teleport(Source.getWorld(),Coordinate_X + 0.5, Coordinate_Y, Coordinate_Z + 0.5, new HashSet<>(), entity.getYaw(), entity.getPitch(), false);
|
|
||||||
int finalCoordinate_Y = Coordinate_Y;
|
|
||||||
// ↑ "lambda 表达式中使用的变量应为 final 或有效 final"
|
|
||||||
final var FeedbackFallbackString = String.format("已将玩家%s传送到%d %d %d", entity.getName().getString(), Coordinate_X, finalCoordinate_Y, Coordinate_Z);
|
|
||||||
Source.sendFeedback(()->{ return Text.translatableWithFallback("info.success", FeedbackFallbackString, entity.getName(), Coordinate_X, finalCoordinate_Y, Coordinate_Z); },true);
|
|
||||||
return 16;}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package xyz.thewhitedog9487;
|
|
||||||
|
|
||||||
import net.fabricmc.api.ModInitializer;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class RandomTeleporter implements ModInitializer {
|
|
||||||
// This logger is used to write text to the console and the log file.
|
|
||||||
// It is considered best practice to use your mod id as the logger's name.
|
|
||||||
// That way, it's clear which mod wrote info, warnings, and errors.
|
|
||||||
public static final Logger LOGGER = LoggerFactory.getLogger("randomteleporter");
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInitialize() {
|
|
||||||
// This code runs as soon as Minecraft is in a mod-load-ready state.
|
|
||||||
// However, some things (like resources) may still be uninitialized.
|
|
||||||
// Proceed with mild caution.
|
|
||||||
LOGGER.info("RandomTeleporter Loading!");
|
|
||||||
|
|
||||||
CommandRegister.Register();
|
|
||||||
|
|
||||||
LOGGER.info("RandomTeleporter Loaded!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,7 +8,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
|
|
||||||
@Mixin(MinecraftServer.class)
|
@Mixin(MinecraftServer.class)
|
||||||
public class ExampleMixin {
|
public class ExampleMixin {
|
||||||
@Inject(at = @At("HEAD"), method = "loadWorld")
|
@Inject(at = @At("HEAD"), method = "loadLevel")
|
||||||
private void init(CallbackInfo info) {
|
private void init(CallbackInfo info) {
|
||||||
// This code is injected into the start of MinecraftServer.loadWorld()V
|
// This code is injected into the start of MinecraftServer.loadWorld()V
|
||||||
}
|
}
|
||||||
|
|||||||
330
src/main/kotlin/xyz/thewhitedog9487/CommandRegister.kt
Normal file
330
src/main/kotlin/xyz/thewhitedog9487/CommandRegister.kt
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
package xyz.thewhitedog9487
|
||||||
|
|
||||||
|
import com.mojang.brigadier.Command
|
||||||
|
import com.mojang.brigadier.arguments.IntegerArgumentType
|
||||||
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback
|
||||||
|
import net.minecraft.commands.CommandSourceStack
|
||||||
|
import net.minecraft.commands.Commands
|
||||||
|
import net.minecraft.commands.arguments.EntityArgument
|
||||||
|
import net.minecraft.commands.arguments.coordinates.Vec2Argument
|
||||||
|
import net.minecraft.core.BlockPos
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
|
import net.minecraft.server.commands.TeleportCommand
|
||||||
|
import net.minecraft.server.level.ServerLevel
|
||||||
|
import net.minecraft.world.entity.Entity
|
||||||
|
import net.minecraft.world.level.block.Blocks
|
||||||
|
import net.minecraft.world.level.chunk.status.ChunkStatus
|
||||||
|
import net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING_NO_LEAVES
|
||||||
|
import net.minecraft.world.phys.Vec2
|
||||||
|
import net.minecraft.world.phys.Vec3
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
import kotlin.random.Random
|
||||||
|
import kotlin.random.nextInt
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传送后用于生成保护平台的方块
|
||||||
|
*/
|
||||||
|
val TargetBlock = Blocks.GLASS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传送后会被 [TargetBlock] 替换掉的方块
|
||||||
|
* <br></br>
|
||||||
|
* 替换中心:被传送目标脚下方块
|
||||||
|
* <br></br>
|
||||||
|
* 替换范围:替换中心周围半径为一的正方形区域
|
||||||
|
*/
|
||||||
|
val ReplaceToTargetBlock = setOf(
|
||||||
|
Blocks.AIR,
|
||||||
|
Blocks.VOID_AIR,
|
||||||
|
Blocks.CAVE_AIR,
|
||||||
|
Blocks.WATER,
|
||||||
|
Blocks.LAVA,
|
||||||
|
Blocks.SHORT_GRASS,
|
||||||
|
Blocks.VINE )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 世界边界
|
||||||
|
* <br></br>
|
||||||
|
* @see <a href="https://zh.minecraft.wiki/w/%E4%B8%96%E7%95%8C%E8%BE%B9%E7%95%8C#%E5%A4%A7%E5%B0%8F">Minecraft Wiki (中文)</a>
|
||||||
|
* @see <a href="https://minecraft.wiki/w/World_border#General_information">Minecraft Wiki (English)</a>
|
||||||
|
**/
|
||||||
|
const val WorldBorder = 2.9e7.toInt()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行命令所需权限等级
|
||||||
|
* @see TeleportCommand
|
||||||
|
* @see Commands
|
||||||
|
* @see <a href="https://zh.minecraft.wiki/w/%E6%9D%83%E9%99%90%E7%AD%89%E7%BA%A7">Minecraft Wiki (中文)</a>
|
||||||
|
* @see <a href="https://minecraft.wiki/w/Permission_level">Minecraft Wiki (English)</a>
|
||||||
|
*/
|
||||||
|
val PermissionLevel = Commands.LEVEL_GAMEMASTERS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在传送之前记录当前位置,以支持传送回去
|
||||||
|
*/
|
||||||
|
var OldPositions: MutableMap<UUID, Vec3> = mutableMapOf()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命令执行失败时的返回值
|
||||||
|
* @see <a href="https://zh.minecraft.wiki/w/%E5%91%BD%E4%BB%A4#%E7%BB%93%E6%9E%9C">Minecraft Wiki (中文)</a>
|
||||||
|
* @see <a href="https://minecraft.wiki/w/Commands">Minecraft Wiki (English)</a>
|
||||||
|
*/
|
||||||
|
const val CommandExecuteFailure = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根命令名
|
||||||
|
*/
|
||||||
|
val CommandRootNodeName = setOf(
|
||||||
|
"随机传送",
|
||||||
|
"rtp" )
|
||||||
|
/**
|
||||||
|
* 使用Fabric API向游戏内注册命令
|
||||||
|
* <br>
|
||||||
|
* @see <a href="https://docs.fabricmc.net/zh_cn/develop/commands/basics">Fabric Docs (中文)</a>
|
||||||
|
* @see <a href="https://wiki.fabricmc.net/zh_cn:tutorial:commands">Fabric Wiki (中文)</a>
|
||||||
|
* @see <a href="https://docs.fabricmc.net/develop/commands/basics">Fabric Docs (English)</a>
|
||||||
|
* @see <a href="https://wiki.fabricmc.net/tutorial:commands">Fabric Wiki (English)</a>
|
||||||
|
*/
|
||||||
|
fun CommandRegister() {
|
||||||
|
for (RootNodeName in CommandRootNodeName) {
|
||||||
|
CommandRegistrationCallback.EVENT.register { dispatcher, context, selection ->
|
||||||
|
dispatcher.register(Commands.literal(RootNodeName)
|
||||||
|
// /rtp
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes{ commandContext -> ExecuteCommand(commandContext.source) }
|
||||||
|
|
||||||
|
// /rtp back
|
||||||
|
.then(Commands.literal("back")
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> TeleportBack(commandContext.source) } )
|
||||||
|
|
||||||
|
// /rtp back <PlayerID(被传送玩家名)>
|
||||||
|
.then(Commands.literal("back")
|
||||||
|
.then(Commands.argument(CommandArgumentName_Target, EntityArgument.entity())
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> TeleportBack(commandContext.source,
|
||||||
|
EntityArgument.getEntity(commandContext, CommandArgumentName_Target)) } ) )
|
||||||
|
|
||||||
|
// /rtp <PlayerID(被传送玩家名)> back
|
||||||
|
.then(Commands.argument(CommandArgumentName_Target, EntityArgument.entity())
|
||||||
|
.then(Commands.literal("back")
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> TeleportBack(commandContext.source,
|
||||||
|
EntityArgument.getEntity(commandContext, CommandArgumentName_Target)) } ) )
|
||||||
|
|
||||||
|
// /rtp <Radius(半径)>
|
||||||
|
.then(Commands.argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> ExecuteCommand(commandContext.source,
|
||||||
|
Radius = IntegerArgumentType.getInteger(commandContext, CommandArgumentName_Radius)) } )
|
||||||
|
|
||||||
|
// /rtp <PlayerID(被传送玩家名)>
|
||||||
|
.then(Commands.argument(CommandArgumentName_Target, EntityArgument.entity())
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> ExecuteCommand(commandContext.source,
|
||||||
|
Entity = EntityArgument.getEntity(commandContext, CommandArgumentName_Target)) } )
|
||||||
|
|
||||||
|
// /rtp <Radius(半径)> <PlayerID(被传送玩家名)>
|
||||||
|
.then(Commands.argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
|
||||||
|
.then(Commands.argument(CommandArgumentName_Target, EntityArgument.entity())
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> ExecuteCommand(commandContext.source,
|
||||||
|
Radius = IntegerArgumentType.getInteger(commandContext, CommandArgumentName_Radius),
|
||||||
|
Entity = EntityArgument.getEntity(commandContext, CommandArgumentName_Target)) } ) )
|
||||||
|
|
||||||
|
// /rtp <PlayerID(被传送玩家名)> <Radius(半径)>
|
||||||
|
.then(Commands.argument(CommandArgumentName_Target, EntityArgument.entity())
|
||||||
|
.then(Commands.argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> ExecuteCommand(commandContext.source,
|
||||||
|
Radius = IntegerArgumentType.getInteger(commandContext, CommandArgumentName_Radius),
|
||||||
|
Entity = EntityArgument.getEntity(commandContext, CommandArgumentName_Target)) } ) )
|
||||||
|
|
||||||
|
// /rtp <Radius(半径)> <OriginPos(随机中心,坐标)>
|
||||||
|
.then(Commands.argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
|
||||||
|
.then(Commands.argument(CommandArgumentName_OriginPosition, Vec2Argument.vec2())
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> ExecuteCommand(commandContext.source,
|
||||||
|
Radius = IntegerArgumentType.getInteger(commandContext, CommandArgumentName_Radius),
|
||||||
|
Origin = Vec2Argument.getVec2(commandContext, CommandArgumentName_OriginPosition)) } ) )
|
||||||
|
|
||||||
|
// /rtp <Radius(半径)> <PlayerID(被传送玩家名)> <OriginEntity(随机中心,实体)>
|
||||||
|
.then(Commands.argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
|
||||||
|
.then(Commands.argument(CommandArgumentName_Target, EntityArgument.entity())
|
||||||
|
.then(Commands.argument(CommandArgumentName_OriginEntity, EntityArgument.entity())
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> ExecuteCommand(commandContext.source,
|
||||||
|
Radius = IntegerArgumentType.getInteger(commandContext, CommandArgumentName_Radius),
|
||||||
|
Entity = EntityArgument.getEntity(commandContext, CommandArgumentName_Target),
|
||||||
|
Origin = Vec2(
|
||||||
|
EntityArgument.getEntity(commandContext, CommandArgumentName_OriginEntity).position().x.toFloat(),
|
||||||
|
EntityArgument.getEntity(commandContext, CommandArgumentName_OriginEntity).position().z.toFloat() ) ) } ) ) )
|
||||||
|
|
||||||
|
// /rtp <Radius(半径)> <PlayerID(被传送玩家名)> <OriginPos(随机中心,坐标)>
|
||||||
|
.then(Commands.argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
|
||||||
|
.then(Commands.argument(CommandArgumentName_Target, EntityArgument.entity())
|
||||||
|
.then(Commands.argument(CommandArgumentName_OriginPosition, Vec2Argument.vec2())
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> ExecuteCommand(commandContext.source,
|
||||||
|
Radius = IntegerArgumentType.getInteger(commandContext, CommandArgumentName_Radius),
|
||||||
|
Entity = EntityArgument.getEntity(commandContext, CommandArgumentName_Target),
|
||||||
|
Origin = Vec2Argument.getVec2(commandContext, CommandArgumentName_OriginPosition) ) } ) ) )
|
||||||
|
|
||||||
|
// /rtp <PlayerID(被传送玩家名)> <Radius(半径)> <OriginEntity(随机中心,实体)>
|
||||||
|
.then(Commands.argument(CommandArgumentName_Target, EntityArgument.entity())
|
||||||
|
.then(Commands.argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
|
||||||
|
.then(Commands.argument(CommandArgumentName_OriginEntity, EntityArgument.entity())
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> ExecuteCommand(commandContext.source,
|
||||||
|
Radius = IntegerArgumentType.getInteger(commandContext, CommandArgumentName_Radius),
|
||||||
|
Entity = EntityArgument.getEntity(commandContext, CommandArgumentName_Target),
|
||||||
|
Origin = Vec2(
|
||||||
|
EntityArgument.getEntity(commandContext, CommandArgumentName_OriginEntity).position().x.toFloat(),
|
||||||
|
EntityArgument.getEntity(commandContext, CommandArgumentName_OriginEntity).position().z.toFloat() ) ) } ) ) )
|
||||||
|
|
||||||
|
// /rtp <PlayerID(被传送玩家名)> <Radius(半径)> <OriginPos(随机中心,坐标)>
|
||||||
|
.then(Commands.argument(CommandArgumentName_Target, EntityArgument.entity())
|
||||||
|
.then(Commands.argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
|
||||||
|
.then(Commands.argument(CommandArgumentName_OriginPosition, Vec2Argument.vec2())
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> ExecuteCommand(commandContext.source,
|
||||||
|
Radius = IntegerArgumentType.getInteger(commandContext, CommandArgumentName_Radius),
|
||||||
|
Entity = EntityArgument.getEntity(commandContext, CommandArgumentName_Target),
|
||||||
|
Origin = Vec2Argument.getVec2(commandContext, CommandArgumentName_OriginPosition) ) } ) ) )
|
||||||
|
|
||||||
|
// /rtp <RegionFrom(随机区域起点,坐标)> <RegionTo(随机区域终点,坐标)>
|
||||||
|
.then(Commands.argument(CommandArgumentName_RegionFromPosition, Vec2Argument.vec2())
|
||||||
|
.then(Commands.argument(CommandArgumentName_RegionToPosition, Vec2Argument.vec2())
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> ExecuteCommand(commandContext.source,
|
||||||
|
RegionFrom = Vec2Argument.getVec2(commandContext, CommandArgumentName_RegionFromPosition),
|
||||||
|
RegionTo = Vec2Argument.getVec2(commandContext, CommandArgumentName_RegionToPosition) ) } ) )
|
||||||
|
|
||||||
|
// /rtp <RegionFrom(随机区域起点,坐标)> <RegionTo(随机区域终点,坐标)> <PlayerID(被传送玩家名)>
|
||||||
|
.then(Commands.argument(CommandArgumentName_RegionFromPosition, Vec2Argument.vec2())
|
||||||
|
.then(Commands.argument(CommandArgumentName_RegionToPosition, Vec2Argument.vec2())
|
||||||
|
.then(Commands.argument(CommandArgumentName_Target, EntityArgument.entity())
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> ExecuteCommand(commandContext.source,
|
||||||
|
Entity = EntityArgument.getEntity(commandContext, CommandArgumentName_Target),
|
||||||
|
RegionFrom = Vec2Argument.getVec2(commandContext, CommandArgumentName_RegionFromPosition),
|
||||||
|
RegionTo = Vec2Argument.getVec2(commandContext, CommandArgumentName_RegionToPosition) ) } ) ) )
|
||||||
|
|
||||||
|
// /rtp <PlayerID(被传送玩家名)> <RegionFrom(随机区域起点,坐标)> <RegionTo(随机区域终点,坐标)>
|
||||||
|
.then(Commands.argument(CommandArgumentName_Target, EntityArgument.entity())
|
||||||
|
.then(Commands.argument(CommandArgumentName_RegionFromPosition, Vec2Argument.vec2())
|
||||||
|
.then(Commands.argument(CommandArgumentName_RegionToPosition, Vec2Argument.vec2())
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> ExecuteCommand(commandContext.source,
|
||||||
|
Entity = EntityArgument.getEntity(commandContext, CommandArgumentName_Target),
|
||||||
|
RegionFrom = Vec2Argument.getVec2(commandContext, CommandArgumentName_RegionFromPosition),
|
||||||
|
RegionTo = Vec2Argument.getVec2(commandContext, CommandArgumentName_RegionToPosition) ) } ) ) )
|
||||||
|
|
||||||
|
// /rtp <RegionFrom(随机区域起点,实体)> <RegionTo(随机区域终点,实体)>
|
||||||
|
.then(Commands.argument(CommandArgumentName_RegionFromEntity, EntityArgument.entity())
|
||||||
|
.then(Commands.argument(CommandArgumentName_RegionToEntity, EntityArgument.entity())
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> ExecuteCommand(commandContext.source,
|
||||||
|
RegionFrom = Vec2(
|
||||||
|
EntityArgument.getEntity(commandContext, CommandArgumentName_RegionFromEntity).position().x.toFloat(),
|
||||||
|
EntityArgument.getEntity(commandContext, CommandArgumentName_RegionFromEntity).position().z.toFloat() ),
|
||||||
|
RegionTo = Vec2(
|
||||||
|
EntityArgument.getEntity(commandContext, CommandArgumentName_RegionToEntity).position().x.toFloat(),
|
||||||
|
EntityArgument.getEntity(commandContext, CommandArgumentName_RegionToEntity).position().z.toFloat() ) ) } ) )
|
||||||
|
|
||||||
|
// /rtp <RegionFrom(随机区域起点,实体)> <RegionTo(随机区域终点,实体)> <PlayerID(被传送玩家名)>
|
||||||
|
.then(Commands.argument(CommandArgumentName_RegionFromEntity, EntityArgument.entity())
|
||||||
|
.then(Commands.argument(CommandArgumentName_RegionToEntity, EntityArgument.entity())
|
||||||
|
.then(Commands.argument(CommandArgumentName_Target, EntityArgument.entity())
|
||||||
|
.requires(Commands.hasPermission(PermissionLevel))
|
||||||
|
.executes { commandContext -> ExecuteCommand(commandContext.source,
|
||||||
|
Entity = EntityArgument.getEntity(commandContext, CommandArgumentName_Target),
|
||||||
|
RegionFrom = Vec2(
|
||||||
|
EntityArgument.getEntity(commandContext, CommandArgumentName_RegionFromEntity).position().x.toFloat(),
|
||||||
|
EntityArgument.getEntity(commandContext, CommandArgumentName_RegionFromEntity).position().z.toFloat() ),
|
||||||
|
RegionTo = Vec2(
|
||||||
|
EntityArgument.getEntity(commandContext, CommandArgumentName_RegionToEntity).position().x.toFloat(),
|
||||||
|
EntityArgument.getEntity(commandContext, CommandArgumentName_RegionToEntity).position().z.toFloat() ) ) } ) ) )
|
||||||
|
) } } }
|
||||||
|
|
||||||
|
fun ExecuteCommand(
|
||||||
|
Source: CommandSourceStack,
|
||||||
|
Radius: Int = WorldBorder - 1e4.toInt(),
|
||||||
|
Entity: Entity? = Source.player,
|
||||||
|
Origin: Vec2? = null,
|
||||||
|
RegionFrom: Vec2? = null,
|
||||||
|
RegionTo: Vec2? = null ): Int {
|
||||||
|
|
||||||
|
val TargetEntity = Entity ?: run {
|
||||||
|
Source.sendFailure( Component.translatableWithFallback("error.no_target","不存在被传送目标,由非玩家物体执行命令时请显式指定被传送玩家ID") )
|
||||||
|
return CommandExecuteFailure }
|
||||||
|
val RandomRadius = Radius.absoluteValue.toFloat()
|
||||||
|
|
||||||
|
var (RandomRegionFrom, RandomRegionTo) = if (RegionFrom == null && RegionTo == null) Pair(
|
||||||
|
Vec2(-RandomRadius, -RandomRadius), Vec2(RandomRadius, RandomRadius) )
|
||||||
|
else Pair(
|
||||||
|
Vec2(min(RegionFrom!!.x, RegionTo!!.x), min(RegionFrom.y, RegionTo.y)),
|
||||||
|
Vec2(max(RegionFrom.x, RegionTo.x), max(RegionFrom.y, RegionTo.y)))
|
||||||
|
|
||||||
|
if (Origin != null) {
|
||||||
|
RandomRegionFrom = Vec2(Origin.x - RandomRadius, Origin.y - RandomRadius)
|
||||||
|
RandomRegionTo = Vec2(Origin.x + RandomRadius, Origin.y + RandomRadius) }
|
||||||
|
|
||||||
|
var (TargetX, TargetZ) = Pair(
|
||||||
|
Random.nextInt(RandomRegionFrom.x.toInt() until RandomRegionTo.x.toInt() + 1),
|
||||||
|
Random.nextInt(RandomRegionFrom.y.toInt() until RandomRegionTo.y.toInt() + 1) )
|
||||||
|
TargetX = Math.clamp(TargetX.toLong(), -(WorldBorder - 1e4).toInt(), WorldBorder - 1e4.toInt() )
|
||||||
|
TargetZ = Math.clamp(TargetZ.toLong(), -(WorldBorder - 1e4).toInt(), WorldBorder - 1e4.toInt() )
|
||||||
|
|
||||||
|
val EntityWorld = TargetEntity.level()
|
||||||
|
EntityWorld.getChunk(TargetX shr 4, TargetZ shr 4, ChunkStatus.FULL, true)
|
||||||
|
val TargetY = EntityWorld.getHeight(MOTION_BLOCKING_NO_LEAVES, TargetX, TargetZ)
|
||||||
|
val BlockPosInstance = BlockPos.MutableBlockPos()
|
||||||
|
for (x in -1..1) {
|
||||||
|
for (z in -1..1) {
|
||||||
|
BlockPosInstance.set(TargetX - x, TargetY - 1, TargetZ - z)
|
||||||
|
val CurrentBlock = EntityWorld.getBlockState(BlockPosInstance).block
|
||||||
|
if (ReplaceToTargetBlock.contains(CurrentBlock)) {
|
||||||
|
EntityWorld.setBlockAndUpdate(BlockPosInstance, TargetBlock.defaultBlockState()) } } }
|
||||||
|
OldPositions[TargetEntity.uuid] = TargetEntity.position()
|
||||||
|
TargetEntity.teleportTo(EntityWorld as ServerLevel, TargetX + 0.5, TargetY.toDouble(), TargetZ + 0.5, setOf(), TargetEntity.yRot, TargetEntity.xRot, false)
|
||||||
|
val FeedbackFallbackString = String.format("已将玩家%s传送到%d %d %d", TargetEntity.name.string, TargetX, TargetY, TargetZ)
|
||||||
|
Source.sendSuccess({ Component.translatableWithFallback("info.success", FeedbackFallbackString, TargetEntity.name, TargetX, TargetY, TargetZ) }, true)
|
||||||
|
return Command.SINGLE_SUCCESS }
|
||||||
|
|
||||||
|
fun TeleportBack(Source: CommandSourceStack,
|
||||||
|
TargetEntity: Entity? = Source.player): Int {
|
||||||
|
|
||||||
|
if (TargetEntity == null) {
|
||||||
|
Source.sendFailure(
|
||||||
|
Component.translatableWithFallback(
|
||||||
|
"error.no_target",
|
||||||
|
"不存在被传送目标,由非玩家物体执行命令时请显式指定被传送玩家ID"))
|
||||||
|
return CommandExecuteFailure }
|
||||||
|
OldPositions[TargetEntity.uuid].also {
|
||||||
|
if (it == null) {
|
||||||
|
Source.sendFailure(
|
||||||
|
Component.translatableWithFallback(
|
||||||
|
"error.no_old_position",
|
||||||
|
"%s还未使用过随机传送,因此无法回溯",
|
||||||
|
TargetEntity.name.string ) )
|
||||||
|
return@TeleportBack CommandExecuteFailure }
|
||||||
|
|
||||||
|
TargetEntity.teleportTo(
|
||||||
|
TargetEntity.level() as ServerLevel,
|
||||||
|
it.x,
|
||||||
|
it.y,
|
||||||
|
it.z,
|
||||||
|
setOf(),
|
||||||
|
TargetEntity.yRot,
|
||||||
|
TargetEntity.xRot,
|
||||||
|
false)
|
||||||
|
Source.sendSuccess({
|
||||||
|
Component.translatableWithFallback(
|
||||||
|
"info.success.back",
|
||||||
|
"已将玩家%s传送回原位置",
|
||||||
|
TargetEntity.name.string ) }, true)
|
||||||
|
return@TeleportBack Command.SINGLE_SUCCESS } }
|
||||||
26
src/main/kotlin/xyz/thewhitedog9487/RandomTeleporter.kt
Normal file
26
src/main/kotlin/xyz/thewhitedog9487/RandomTeleporter.kt
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package xyz.thewhitedog9487
|
||||||
|
|
||||||
|
import net.fabricmc.api.ModInitializer
|
||||||
|
import org.slf4j.Logger
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
|
const val ModID = "randomteleporter"
|
||||||
|
const val FriendlyModID = "RandomTeleporter"
|
||||||
|
val ModLogger: Logger = LoggerFactory.getLogger(FriendlyModID)
|
||||||
|
|
||||||
|
object RandomTeleporter : ModInitializer {
|
||||||
|
|
||||||
|
override fun onInitialize() {
|
||||||
|
// This code runs as soon as Minecraft is in a mod-load-ready state.
|
||||||
|
// However, some things (like resources) may still be uninitialized.
|
||||||
|
// Proceed with mild caution.
|
||||||
|
|
||||||
|
// This code runs as soon as Minecraft is in a mod-load-ready state.
|
||||||
|
// However, some things (like resources) may still be uninitialized.
|
||||||
|
// Proceed with mild caution.
|
||||||
|
|
||||||
|
ServerLifecycleListenerRegister()
|
||||||
|
ResourceReloaderListenerRegister()
|
||||||
|
CommandRegister()
|
||||||
|
ModLogger.info("RandomTeleporter已写入命令注册回调,目标命令将会在该注册的时候被注册") }
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package xyz.thewhitedog9487
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.resource.v1.ResourceLoader
|
||||||
|
import net.fabricmc.fabric.api.resource.v1.reloader.SimpleReloadListener
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
|
import net.minecraft.resources.Identifier
|
||||||
|
import net.minecraft.server.packs.PackType
|
||||||
|
import net.minecraft.server.packs.resources.PreparableReloadListener
|
||||||
|
|
||||||
|
var CommandArgumentName_Radius = "Radius(半径)"
|
||||||
|
var CommandArgumentName_Target = "PlayerID(被传送玩家名)"
|
||||||
|
var CommandArgumentName_OriginPosition = "OriginPos(随机中心,坐标)"
|
||||||
|
var CommandArgumentName_OriginEntity = "OriginEntity(随机中心,实体)"
|
||||||
|
var CommandArgumentName_RegionFromPosition = "RegionFrom(随机范围起始位置,坐标)"
|
||||||
|
var CommandArgumentName_RegionToPosition = "RegionTo(随机范围结束位置,坐标)"
|
||||||
|
var CommandArgumentName_RegionFromEntity = "RegionFrom(随机范围起始位置,实体)"
|
||||||
|
var CommandArgumentName_RegionToEntity = "RegionTo(随机范围结束位置,实体)"
|
||||||
|
|
||||||
|
fun ResourceReloaderListenerRegister() {
|
||||||
|
ResourceLoader.get(PackType.CLIENT_RESOURCES).registerReloadListener(
|
||||||
|
Identifier.fromNamespaceAndPath(ModID,
|
||||||
|
"translate_text_apply"), object: SimpleReloadListener<Unit>() {
|
||||||
|
override fun prepare(p0: PreparableReloadListener.SharedState) {}
|
||||||
|
|
||||||
|
override fun apply(p0: Unit, p1: PreparableReloadListener.SharedState) {
|
||||||
|
CommandArgumentName_Radius =
|
||||||
|
Component.translatableWithFallback("command.argument.radius", "Radius(半径)").string
|
||||||
|
CommandArgumentName_Target =
|
||||||
|
Component.translatableWithFallback("command.argument.target", "PlayerID(被传送玩家名)").string
|
||||||
|
CommandArgumentName_OriginPosition =
|
||||||
|
Component.translatableWithFallback("command.argument.origin_pos", "OriginPos(随机中心,坐标)").string
|
||||||
|
CommandArgumentName_OriginEntity =
|
||||||
|
Component.translatableWithFallback("command.argument.origin_entity", "OriginEntity(随机中心,实体)").string
|
||||||
|
CommandArgumentName_RegionFromPosition = Component.translatableWithFallback(
|
||||||
|
"command.argument.region_from_pos",
|
||||||
|
"RegionFrom(随机范围起始位置,坐标)").string
|
||||||
|
CommandArgumentName_RegionToPosition = Component.translatableWithFallback(
|
||||||
|
"command.argument.region_to_pos",
|
||||||
|
"RegionTo(随机范围结束位置,坐标)").string
|
||||||
|
CommandArgumentName_RegionFromEntity = Component.translatableWithFallback(
|
||||||
|
"command.argument.region_from_entity",
|
||||||
|
"RegionFrom(随机范围起始位置,实体)").string
|
||||||
|
CommandArgumentName_RegionToEntity = Component.translatableWithFallback(
|
||||||
|
"command.argument.region_to_entity",
|
||||||
|
"RegionTo(随机范围结束位置,实体)").string } } ) }
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package xyz.thewhitedog9487
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents
|
||||||
|
|
||||||
|
fun ServerLifecycleListenerRegister() {
|
||||||
|
ServerLifecycleEvents.SERVER_STARTED.register { server ->
|
||||||
|
OldPositions.clear()
|
||||||
|
ModLogger.info("已清空传送历史记录") } }
|
||||||
@@ -2,6 +2,16 @@
|
|||||||
"modmenu.nameTranslation.randomteleporter": "RandomTeleporter",
|
"modmenu.nameTranslation.randomteleporter": "RandomTeleporter",
|
||||||
"modmenu.descriptionTranslation.randomteleporter": "Added two commands for random teleportation",
|
"modmenu.descriptionTranslation.randomteleporter": "Added two commands for random teleportation",
|
||||||
"info.success": "Teleported %s to %d %d %d",
|
"info.success": "Teleported %s to %d %d %d",
|
||||||
|
"info.success.back": "Teleported %s back to original position",
|
||||||
"error.no_target": "There is no teleported target, and the teleported player ID is explicitly specified when executed by a non-player object",
|
"error.no_target": "There is no teleported target, and the teleported player ID is explicitly specified when executed by a non-player object",
|
||||||
"bilibili": "Bilibili"
|
"error.no_old_position": "%s has not used random teleport yet, so it cannot be traced back",
|
||||||
|
"bilibili": "Bilibili",
|
||||||
|
"command.argument.radius": "radius",
|
||||||
|
"command.argument.target": "teleported entity",
|
||||||
|
"command.argument.origin_pos": "origin(pos)",
|
||||||
|
"command.argument.origin_entity": "origin(entity)",
|
||||||
|
"command.argument.region_from_pos": "region start(pos)",
|
||||||
|
"command.argument.region_to_pos": "region end(pos)",
|
||||||
|
"command.argument.region_from_entity": "region start(entity)",
|
||||||
|
"command.argument.region_to_entity": "region end(entity)"
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,16 @@
|
|||||||
"modmenu.nameTranslation.randomteleporter": "随机传送",
|
"modmenu.nameTranslation.randomteleporter": "随机传送",
|
||||||
"modmenu.descriptionTranslation.randomteleporter": "增加了两个用于随机传送的命令",
|
"modmenu.descriptionTranslation.randomteleporter": "增加了两个用于随机传送的命令",
|
||||||
"info.success": "已将玩家%s传送到%d %d %d",
|
"info.success": "已将玩家%s传送到%d %d %d",
|
||||||
|
"info.success.back": "已将玩家%s传送回原位置",
|
||||||
"error.no_target": "不存在被传送目标,由非玩家物体执行命令时请显式指定被传送玩家ID",
|
"error.no_target": "不存在被传送目标,由非玩家物体执行命令时请显式指定被传送玩家ID",
|
||||||
"bilibili": "TheWhiteDog9487的哔哩哔哩主页"
|
"error.no_old_position": "%s还未使用过随机传送,因此无法回溯",
|
||||||
|
"bilibili": "TheWhiteDog9487的哔哩哔哩主页",
|
||||||
|
"command.argument.radius": "半径",
|
||||||
|
"command.argument.target": "被传送实体",
|
||||||
|
"command.argument.origin_pos": "随机中心(坐标)",
|
||||||
|
"command.argument.origin_entity": "随机中心(实体)",
|
||||||
|
"command.argument.region_from_pos": "坐标选取区域起点(坐标)",
|
||||||
|
"command.argument.region_to_pos": "坐标选取区域终点(坐标)",
|
||||||
|
"command.argument.region_from_entity": "坐标选取区域起点(实体)",
|
||||||
|
"command.argument.region_to_entity": "坐标选取区域终点(实体)"
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,11 @@
|
|||||||
"environment": "*",
|
"environment": "*",
|
||||||
"entrypoints": {
|
"entrypoints": {
|
||||||
"main": [
|
"main": [
|
||||||
"xyz.thewhitedog9487.RandomTeleporter"]
|
{
|
||||||
|
"value": "xyz.thewhitedog9487.RandomTeleporter",
|
||||||
|
"adapter": "kotlin"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"randomteleporter.mixins.json",
|
"randomteleporter.mixins.json",
|
||||||
@@ -27,10 +31,11 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"depends": {
|
"depends": {
|
||||||
"fabricloader": ">=0.16.9",
|
"fabricloader": ">=0.9.3",
|
||||||
"minecraft": "1.21.4",
|
"minecraft": "26.2",
|
||||||
"java": ">=21",
|
"java": ">=25",
|
||||||
"fabric-api": ">=0.110.5"
|
"fabric-api": ">=0.152.1",
|
||||||
|
"fabric-language-kotlin": "*"
|
||||||
},
|
},
|
||||||
"suggests": {
|
"suggests": {
|
||||||
"another-mod": "*"
|
"another-mod": "*"
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
{
|
{
|
||||||
"required": false,
|
"required": true,
|
||||||
"package": "xyz.thewhitedog9487.mixin",
|
"package": "xyz.thewhitedog9487.mixin",
|
||||||
"compatibilityLevel": "JAVA_21",
|
"compatibilityLevel": "JAVA_25",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
|
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
},
|
||||||
|
"overwrites": {
|
||||||
|
"requireAnnotations": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user