9 Commits

Author SHA1 Message Date
TheWhiteDog9487
327dd5d168 更新到Minecraft 1.21.10 2025-10-08 09:19:23 +08:00
TheWhiteDog9487
dca7fa256e 将命令参数文本抽离到各个文字的翻译文件内,现在只会显示当前语言的提示文字了
但是单人游戏内切换语言后必须重进世界才能完成游戏内热更新,并且独立服务器用不了这个特性,开放局域网的话应该是跟随主机的语言配置
2025-10-05 15:34:06 +08:00
TheWhiteDog9487
74046be828 使用Minecraft内部方法搜索指定坐标内可传送玩家的合适Y
更换大量new BlockPos为BlockPos.Mutable
2025-10-05 14:18:43 +08:00
TheWhiteDog9487
33e01b3d35 现在被传送实体会在自己所在世界内被传送,不会受到命令执行方所在世界和自己不一致的影响
重命名函数和变量
2025-10-05 14:14:16 +08:00
TheWhiteDog9487
e7f9ac069a 将 随机数生成器 需要被替换的方块列表 和 替换目标方块 提取到静态常量
并且让随机数的上界+1以使随机范围成为完整闭区间
2025-10-05 14:11:00 +08:00
TheWhiteDog9487
eb85fff326 使单个根名称的命令树一次性完成注册
并且现在由Minecraft自己的命令解析器确保用户输入的随机半径>=0
返回标准Command.SINGLE_SUCCESS
2025-10-05 14:09:11 +08:00
TheWhiteDog9487
48a5027cce 更新至Minecraft 1.21.9 2025-10-03 16:51:17 +08:00
TheWhiteDog9487
62c3484c5e 更新Gradle到9.1.0 2025-10-03 16:50:50 +08:00
d47907cdf4 更新至Minecraft 1.21.8
Feature Drop和Bugfix混用小版本号的话,年底,不,甚至暑假结束之前有望突破1.21.10
2025-07-18 11:19:41 +08:00
9 changed files with 208 additions and 181 deletions

View File

@@ -1,9 +1,9 @@
plugins { plugins {
id("fabric-loom") version "1.10-SNAPSHOT" id("fabric-loom") version "1.11-SNAPSHOT"
id("maven-publish") id("maven-publish")
} }
version = "${project.extra["mod_version"]}" version = project.extra["mod_version"] as String
group = project.extra["maven_group"] as String group = project.extra["maven_group"] as String
base { base {

View File

@@ -4,18 +4,18 @@ 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.7 minecraft_version=1.21.10
yarn_mappings=1.21.7+build.1 yarn_mappings=1.21.10+build.1
loader_version=0.16.14 loader_version=0.17.2
# Mod Properties # Mod Properties
mod_version=0.3.6 mod_version=0.4.0
maven_group=xyz.thewhitedog9487 maven_group=xyz.thewhitedog9487
archives_base_name=RandomTeleporter archives_base_name=RandomTeleporter
# Dependencies # Dependencies
fabric_version=0.128.1+1.21.7 fabric_version=0.134.1+1.21.10
# 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=15.0.0-beta.3 modmenu_version=16.0.0-rc.1

View File

@@ -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.14-bin.zip distributionUrl=https://services.gradle.org/distributions/gradle-9.1.0-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@@ -1,25 +1,59 @@
package xyz.thewhitedog9487; package xyz.thewhitedog9487;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.command.argument.EntityArgumentType; import net.minecraft.command.argument.EntityArgumentType;
import net.minecraft.command.argument.Vec2ArgumentType; import net.minecraft.command.argument.Vec2ArgumentType;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec2f; import net.minecraft.util.math.Vec2f;
import net.minecraft.world.World;
import net.minecraft.world.chunk.ChunkStatus;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set;
import java.util.SplittableRandom; import java.util.SplittableRandom;
import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal; import static net.minecraft.server.command.CommandManager.literal;
import static net.minecraft.world.Heightmap.Type.MOTION_BLOCKING_NO_LEAVES;
import static xyz.thewhitedog9487.ResourceReloaderListener.*;
public class CommandRegister { public class CommandRegister {
/**
* 随机数生成器
*/
final static SplittableRandom SR = new SplittableRandom();
/**
* 传送后用于生成保护平台的方块
*/
final static Block TargetBlock = Blocks.GLASS;
/**
* 传送后会被 {@link CommandRegister#TargetBlock} 替换掉的方块
* <br>
* 替换中心:被传送目标脚下方块
* <br>
* 替换范围:替换中心周围半径为一的正方形区域
*/
final static Set<Block> ReplaceToTargetBlock = Set.of(
Blocks.AIR,
Blocks.VOID_AIR,
Blocks.CAVE_AIR,
Blocks.WATER,
Blocks.LAVA,
Blocks.SHORT_GRASS,
Blocks.VINE );
/** /**
* 世界边界 * 世界边界
* <br> * <br>
@@ -44,147 +78,108 @@ public class CommandRegister {
* @see <a href="https://wiki.fabricmc.net/tutorial:commands">Fabric Wiki (Old style,English)</a> * @see <a href="https://wiki.fabricmc.net/tutorial:commands">Fabric Wiki (Old style,English)</a>
*/ */
public static void Register(String Name){ public static void Register(String Name){
// /rtp
CommandRegistrationCallback.EVENT CommandRegistrationCallback.EVENT
.register((dispatcher, registryAccess, environment) ->{ .register((dispatcher, registryAccess, environment) ->{
dispatcher.register(literal(Name) dispatcher.register(literal(Name)
// /rtp
.requires(source -> source.hasPermissionLevel(PermissionLevel)) .requires(source -> source.hasPermissionLevel(PermissionLevel))
.executes(context -> execute_command( .executes(context -> ExecuteCommand(
context.getSource(),null,null, null)));}); context.getSource(),null,null, null))
// /rtp <Radius(半径)>
// /rtp <Radius(半径)> .then(argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
CommandRegistrationCallback.EVENT
.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(literal(Name)
.then(argument("Radius(半径)", IntegerArgumentType.integer())
.requires(source -> source.hasPermissionLevel(PermissionLevel)) .requires(source -> source.hasPermissionLevel(PermissionLevel))
.executes(context -> execute_command( .executes(context -> ExecuteCommand(
context.getSource(), context.getSource(),
IntegerArgumentType.getInteger(context, "Radius(半径)"), IntegerArgumentType.getInteger(context, CommandArgumentName_Radius),
null, null,
null))));}); null)))
// /rtp <被传送玩家名(PlayerID)>
// /rtp <被传送玩家名(PlayerID)> .then(argument(CommandArgumentName_Target, EntityArgumentType.entity())
CommandRegistrationCallback.EVENT
.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(literal(Name)
.then(argument("被传送玩家名(PlayerID)", EntityArgumentType.entity())
.requires(source -> source.hasPermissionLevel(PermissionLevel)) .requires(source -> source.hasPermissionLevel(PermissionLevel))
.executes(context -> execute_command( .executes(context -> ExecuteCommand(
context.getSource(), context.getSource(),
null, null,
EntityArgumentType.getEntity(context,"被传送玩家名(PlayerID)"), EntityArgumentType.getEntity(context,CommandArgumentName_Target),
null))));}); null)))
// /rtp <Radius(半径)> <被传送玩家名(PlayerID)>
// /rtp <Radius(半径)> <被传送玩家名(PlayerID)> .then(argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
CommandRegistrationCallback.EVENT .then(argument(CommandArgumentName_Target, EntityArgumentType.entity())
.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(literal(Name)
.then(argument("Radius(半径)", IntegerArgumentType.integer())
.then(argument("被传送玩家名(PlayerID)", EntityArgumentType.entity())
.requires(source -> source.hasPermissionLevel(PermissionLevel)) .requires(source -> source.hasPermissionLevel(PermissionLevel))
.executes(context -> execute_command( .executes(context -> ExecuteCommand(
context.getSource(), context.getSource(),
IntegerArgumentType.getInteger(context, "Radius(半径)"), IntegerArgumentType.getInteger(context, CommandArgumentName_Radius),
EntityArgumentType.getEntity(context,"被传送玩家名(PlayerID)"), EntityArgumentType.getEntity(context,CommandArgumentName_Target),
null)))));}); null))))
// /rtp <被传送玩家名(PlayerID)> <Radius(半径)>
// /rtp <被传送玩家名(PlayerID)> <Radius(半径)> .then(argument(CommandArgumentName_Target, EntityArgumentType.entity())
CommandRegistrationCallback.EVENT .then(argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
.register((dispatcher, registryAccess, environment) -> {
dispatcher.register(literal(Name)
.then(argument("被传送玩家名(PlayerID)", EntityArgumentType.entity())
.then(argument("Radius(半径)", IntegerArgumentType.integer())
.requires(source -> source.hasPermissionLevel(PermissionLevel)) .requires(source -> source.hasPermissionLevel(PermissionLevel))
.executes(context -> execute_command( .executes(context -> ExecuteCommand(
context.getSource(), context.getSource(),
IntegerArgumentType.getInteger(context, "Radius(半径)"), IntegerArgumentType.getInteger(context, CommandArgumentName_Radius),
EntityArgumentType.getEntity(context,"被传送玩家名(PlayerID)"), EntityArgumentType.getEntity(context,CommandArgumentName_Target),
null)))));}); null))))
// // /rtp <Radius(半径)> <Origin(随机中心)>
// // /rtp <Radius(半径)> <Origin(随机中心)> // .then(argument("Radius(半径)", LongArgumentType.longArg())
// CommandRegistrationCallback.EVENT // .then(argument("Origin(随机中心)",EntityArgumentType.player())
// .register((dispatcher, registryAccess, environment) -> { // .requires(source -> source.hasPermissionLevel(PermissionLevel))
// dispatcher.register(literal(Name) // .executes(context -> execute_command_origin(
// .then(argument("Radius(半径)", LongArgumentType.longArg()) // context.getSource(),
// .then(argument("Origin(随机中心)",EntityArgumentType.player()) // LongArgumentType.getLong(context, "Radius(半径)"),
// .requires(source -> source.hasPermissionLevel(PermissionLevel)) // null,
// .executes(context -> execute_command_origin( // EntityArgumentType.getEntity(context,"Origin(随机中心)")))))
// context.getSource(), // /rtp <Radius(半径)> <OriginPos(随机中心,坐标)>
// LongArgumentType.getLong(context, "Radius(半径)"), .then(argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
// null, .then(argument(CommandArgumentName_OriginPosition,Vec2ArgumentType.vec2())
// 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)) .requires(source -> source.hasPermissionLevel(PermissionLevel))
.executes(context -> execute_command( .executes(context -> ExecuteCommand(
context.getSource(), context.getSource(),
IntegerArgumentType.getInteger(context, "Radius(半径)"), IntegerArgumentType.getInteger(context, CommandArgumentName_Radius),
null, null,
Vec2ArgumentType.getVec2(context,"OriginPos(随机中心,坐标)"))))));}); Vec2ArgumentType.getVec2(context,CommandArgumentName_OriginPosition)))))
// /rtp <Radius(半径)> <被传送玩家名(PlayerID)> <OriginEntity(随机中心,实体)>
// /rtp <Radius(半径)> <被传送玩家名(PlayerID)> <OriginEntity(随机中心,实体)> .then(argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
CommandRegistrationCallback.EVENT .then(argument(CommandArgumentName_Target, EntityArgumentType.entity())
.register((dispatcher, registryAccess, environment) -> { .then(argument(CommandArgumentName_OriginEntity,EntityArgumentType.entity())
dispatcher.register(literal(Name)
.then(argument("Radius(半径)", IntegerArgumentType.integer())
.then(argument("被传送玩家名(PlayerID)", EntityArgumentType.entity())
.then(argument("OriginEntity(随机中心,实体)",EntityArgumentType.entity())
.requires(source -> source.hasPermissionLevel(PermissionLevel)) .requires(source -> source.hasPermissionLevel(PermissionLevel))
.executes(context -> execute_command( .executes(context -> ExecuteCommand(
context.getSource(), context.getSource(),
IntegerArgumentType.getInteger(context, "Radius(半径)"), IntegerArgumentType.getInteger(context, CommandArgumentName_Radius),
EntityArgumentType.getEntity(context,"被传送玩家名(PlayerID)"), EntityArgumentType.getEntity(context,CommandArgumentName_Target),
new Vec2f( (float) EntityArgumentType.getEntity( context,"OriginEntity(随机中心,实体)").getPos().x, new Vec2f( (float) EntityArgumentType.getEntity( context,CommandArgumentName_OriginEntity).getEntityPos().x,
(float) EntityArgumentType.getEntity( context,"OriginEntity(随机中心,实体)").getPos().z )))))));}); (float) EntityArgumentType.getEntity( context,CommandArgumentName_OriginEntity).getEntityPos().z ))))))
// /rtp <Radius(半径)> <被传送玩家名(PlayerID)> <OriginPos(随机中心,坐标)>
// /rtp <Radius(半径)> <被传送玩家名(PlayerID)> <OriginPos(随机中心,坐标)> .then(argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
CommandRegistrationCallback.EVENT .then(argument(CommandArgumentName_Target, EntityArgumentType.entity())
.register((dispatcher, registryAccess, environment) -> { .then(argument(CommandArgumentName_OriginPosition,Vec2ArgumentType.vec2())
dispatcher.register(literal(Name) .requires(source -> source.hasPermissionLevel(PermissionLevel))
.then(argument("Radius(半径)", IntegerArgumentType.integer()) .executes(context -> ExecuteCommand(
.then(argument("被传送玩家名(PlayerID)", EntityArgumentType.entity()) context.getSource(),
.then(argument("OriginPos(随机中心,坐标)",Vec2ArgumentType.vec2()) IntegerArgumentType.getInteger(context, CommandArgumentName_Radius),
.requires(source -> source.hasPermissionLevel(PermissionLevel)) EntityArgumentType.getEntity(context,CommandArgumentName_Target),
.executes(context -> execute_command( Vec2ArgumentType.getVec2(context,CommandArgumentName_OriginPosition))))))
context.getSource(), // /rtp <被传送玩家名(PlayerID)> <Radius(半径)> <OriginEntity(随机中心,实体)>
IntegerArgumentType.getInteger(context, "Radius(半径)"), .then(argument(CommandArgumentName_Target, EntityArgumentType.entity())
EntityArgumentType.getEntity(context,"被传送玩家名(PlayerID)"), .then(argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
Vec2ArgumentType.getVec2(context,"OriginPos(随机中心,坐标)")))))));}); .then(argument(CommandArgumentName_OriginEntity,EntityArgumentType.entity())
.requires(source -> source.hasPermissionLevel(PermissionLevel))
// /rtp <被传送玩家名(PlayerID)> <Radius(半径)> <OriginEntity(随机中心,实体)> .executes(context -> ExecuteCommand(
CommandRegistrationCallback.EVENT context.getSource(),
.register((dispatcher, registryAccess, environment) -> { IntegerArgumentType.getInteger(context, CommandArgumentName_Radius),
dispatcher.register(literal(Name) EntityArgumentType.getEntity(context,CommandArgumentName_Target),
.then(argument("被传送玩家名(PlayerID)", EntityArgumentType.entity()) new Vec2f( (float) EntityArgumentType.getEntity( context,CommandArgumentName_OriginEntity).getEntityPos().x,
.then(argument("Radius(半径)", IntegerArgumentType.integer()) (float) EntityArgumentType.getEntity( context,CommandArgumentName_OriginEntity).getEntityPos().z ))))))
.then(argument("OriginEntity(随机中心,实体)",EntityArgumentType.entity()) // /rtp <被传送玩家名(PlayerID)> <Radius(半径)> <OriginPos(随机中心,坐标)>
.requires(source -> source.hasPermissionLevel(PermissionLevel)) .then(argument(CommandArgumentName_Target, EntityArgumentType.entity())
.executes(context -> execute_command( .then(argument(CommandArgumentName_Radius, IntegerArgumentType.integer(0))
context.getSource(), .then(argument(CommandArgumentName_OriginPosition,Vec2ArgumentType.vec2())
IntegerArgumentType.getInteger(context, "Radius(半径)"), .requires(source -> source.hasPermissionLevel(PermissionLevel))
EntityArgumentType.getEntity(context,"被传送玩家名(PlayerID)"), .executes(context -> ExecuteCommand(
new Vec2f( (float) EntityArgumentType.getEntity( context,"OriginEntity(随机中心,实体)").getPos().x, context.getSource(),
(float) EntityArgumentType.getEntity( context,"OriginEntity(随机中心,实体)").getPos().z )))))));}); IntegerArgumentType.getInteger(context, CommandArgumentName_Radius),
EntityArgumentType.getEntity(context,CommandArgumentName_Target),
// /rtp <被传送玩家名(PlayerID)> <Radius(半径)> <OriginPos(随机中心,坐标)> Vec2ArgumentType.getVec2(context,CommandArgumentName_OriginPosition)))))) );});}
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(随机中心,坐标)")))))));});}
/** /**
* 向游戏内注册命令 * 向游戏内注册命令
@@ -201,35 +196,34 @@ public class CommandRegister {
* *
* @param Source 命令执行者 * @param Source 命令执行者
* @param Radius 随机选择的目的坐标距离参数 {@code Origin} 的最大距离 * @param Radius 随机选择的目的坐标距离参数 {@code Origin} 的最大距离
* @param Player 被传送的玩家 * @param Entity 被传送的实体
* @param Origin 随机选择的目的坐标的中心 * @param Origin 随机选择的目的坐标的中心
* @return 命令运行是否成功 * @return 命令运行是否成功
*/ */
static int execute_command(ServerCommandSource Source, @Nullable Integer Radius, @Nullable Entity Player, @Nullable Vec2f Origin){ static int ExecuteCommand(ServerCommandSource Source, @Nullable Integer Radius, @Nullable Entity Entity, @Nullable Vec2f Origin){
Entity entity = Player == null ? Source.getPlayer() : Player; Entity TargetEntity = Entity == null ? Source.getPlayer() : Entity;
/* /*
Entity entity = null; Entity TargetEntity = null;
if (Player == null){ if (TargetEntity == null){
entity = Source.getPlayer();} TargetEntity = Source.getPlayer();}
else{ else{
entity = Player;} TargetEntity = Entity;}
*/ */
if (entity == null) { if (TargetEntity == null) {
Source.sendFeedback(()->{ return Text.translatableWithFallback("error.no_target","不存在被传送目标由非玩家物体执行命令时请显式指定被传送玩家ID"); }, true); Source.sendFeedback(()->{ return Text.translatableWithFallback("error.no_target","不存在被传送目标由非玩家物体执行命令时请显式指定被传送玩家ID"); }, true);
return -1;} return -1;}
if (Radius == null){Radius = (int) (WorldBorder - 1e4);} if (Radius == null){Radius = (int) (WorldBorder - 1e4);}
// ↑ 远离世界边界 // ↑ 远离世界边界
Radius = Math.abs(Radius);
int Coordinate_X = 0; int Coordinate_X = 0;
int Coordinate_Z = 0; int Coordinate_Z = 0;
try { try {
if (Origin == null){ if (Origin == null){
Coordinate_X = new SplittableRandom().nextInt(-Radius, Radius); Coordinate_X = SR.nextInt(-Radius, Radius + 1);
Coordinate_Z = new SplittableRandom().nextInt(-Radius, Radius);} Coordinate_Z = SR.nextInt(-Radius, Radius + 1); }
else{ else{
Coordinate_X = new SplittableRandom().nextInt((int) Origin.x - Radius, (int) Origin.x + Radius); Coordinate_X = SR.nextInt((int) Origin.x - Radius, (int) Origin.x + Radius + 1);
Coordinate_Z = new SplittableRandom().nextInt((int) Origin.y - Radius, (int) Origin.y + Radius);}} Coordinate_Z = SR.nextInt((int) Origin.y - Radius, (int) Origin.y + Radius + 1); } }
catch (IllegalArgumentException e) { catch (IllegalArgumentException e) {
// 半径为零 // 半径为零
if (Origin == null) { if (Origin == null) {
@@ -242,36 +236,27 @@ public class CommandRegister {
int finalCoordinate_Z1 = Coordinate_Z; int finalCoordinate_Z1 = Coordinate_Z;
// ↑ "lambda 表达式中使用的变量应为 final 或有效 final" // ↑ "lambda 表达式中使用的变量应为 final 或有效 final"
Source.sendFeedback(()->{ return Text.translatableWithFallback("warning.radius_equal_zero", "警告由于你设置的随机半径为0因此在选择出合适高度之后将直接把你传送至%d %d", finalCoordinate_X1, finalCoordinate_Z1); },true);}} Source.sendFeedback(()->{ return Text.translatableWithFallback("warning.radius_equal_zero", "警告由于你设置的随机半径为0因此在选择出合适高度之后将直接把你传送至%d %d", finalCoordinate_X1, finalCoordinate_Z1); },true);}}
int Coordinate_Y = 320; World EntityWorld = TargetEntity.getEntityWorld();
for (var CurrentBlock = Source.getWorld().getBlockState(new BlockPos(Coordinate_X, Coordinate_Y, Coordinate_Z)).getBlock(); EntityWorld.getChunk(Coordinate_X >> 4, Coordinate_Z >> 4, ChunkStatus.FULL, true);
// 从世界顶层往下找,直到遇到一个非空气方块 // ↑ 加载目标区块不然下面获取到的Coordinate_Y一定是-64
Blocks.AIR == CurrentBlock || // 必须是 >> 4 ,不能是 / 16
Blocks.VOID_AIR == CurrentBlock || int Coordinate_Y = EntityWorld.getTopY(MOTION_BLOCKING_NO_LEAVES, Coordinate_X, Coordinate_Z);
Blocks.CAVE_AIR == CurrentBlock BlockPos.Mutable BlockPos = new BlockPos.Mutable();
;CurrentBlock = Source.getWorld().getBlockState(new BlockPos(Coordinate_X, Coordinate_Y, Coordinate_Z)).getBlock()){ for (int x = -1; x <= 1; x++) {
Coordinate_Y--;} for (int z = -1; z <= 1; z++) {
for (int x = -1; x <= 1; x++) { // 如果传送到的位置周围一圈是ReplaceToTargetBlock的方块将其替换为TargetBlock
for (int z = -1; z <= 1; z++) { BlockPos.set(Coordinate_X - x, Coordinate_Y - 1, Coordinate_Z - z);
// 如果传送到的位置周围一圈是空气、水或岩浆,将其替换为玻璃 var CurrentBlock = EntityWorld.getBlockState(BlockPos).getBlock();
var BlockPos = new BlockPos(Coordinate_X - x, Coordinate_Y, Coordinate_Z - z); if ( ReplaceToTargetBlock.contains(CurrentBlock) ) {
var CurrentBlock = Source.getWorld().getBlockState(BlockPos).getBlock(); // 只替换ReplaceToTargetBlock内的方块其余保留
if ( CurrentBlock == Blocks.AIR || EntityWorld.setBlockState(BlockPos, TargetBlock.getDefaultState());}}}
CurrentBlock == Blocks.VOID_AIR || // if ( String.valueOf(TargetEntity.getWorld().getBiome(new BlockPos(Math.toIntExact(Coordinate_X), Coordinate_Y, Math.toIntExact(Coordinate_Z))).getKey()).equals("minecraft:the_void") ) {
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++;}
Coordinate_Y++; TargetEntity.teleport((ServerWorld) EntityWorld,Coordinate_X + 0.5, Coordinate_Y, Coordinate_Z + 0.5, new HashSet<>(), TargetEntity.getYaw(), TargetEntity.getPitch(), false);
// ↑ 高一层,人别站在土里了
entity.teleport(Source.getWorld(),Coordinate_X + 0.5, Coordinate_Y, Coordinate_Z + 0.5, new HashSet<>(), entity.getYaw(), entity.getPitch(), false);
int finalCoordinate_X = Coordinate_X; int finalCoordinate_X = Coordinate_X;
int finalCoordinate_Y = Coordinate_Y;
int finalCoordinate_Z = Coordinate_Z; int finalCoordinate_Z = Coordinate_Z;
// ↑ "lambda 表达式中使用的变量应为 final 或有效 final" // ↑ "lambda 表达式中使用的变量应为 final 或有效 final"
final var FeedbackFallbackString = String.format("已将玩家%s传送到%d %d %d", entity.getName().getString(), Coordinate_X, finalCoordinate_Y, Coordinate_Z); final var FeedbackFallbackString = String.format("已将玩家%s传送到%d %d %d", TargetEntity.getName().getString(), Coordinate_X, Coordinate_Y, Coordinate_Z);
Source.sendFeedback(()->{ return Text.translatableWithFallback("info.success", FeedbackFallbackString, entity.getName(), finalCoordinate_X, finalCoordinate_Y, finalCoordinate_Z); },true); Source.sendFeedback(()->{ return Text.translatableWithFallback("info.success", FeedbackFallbackString, TargetEntity.getName(), finalCoordinate_X, Coordinate_Y, finalCoordinate_Z); },true);
return 16;} return Command.SINGLE_SUCCESS;}
} }

View File

@@ -9,17 +9,17 @@ public class RandomTeleporter implements ModInitializer {
// This logger is used to write text to the console and the log file. // 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. // 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. // That way, it's clear which mod wrote info, warnings, and errors.
public static final Logger LOGGER = LoggerFactory.getLogger("randomteleporter"); public static final String MOD_ID = "randomteleporter";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
@Override @Override
public void onInitialize() { public void onInitialize() {
// This code runs as soon as Minecraft is in a mod-load-ready state. // This code runs as soon as Minecraft is in a mod-load-ready state.
// However, some things (like resources) may still be uninitialized. // However, some things (like resources) may still be uninitialized.
// Proceed with mild caution. // Proceed with mild caution.
LOGGER.info("RandomTeleporter Loading!");
ResourceReloaderListener.Register();
CommandRegister.Register(); CommandRegister.Register();
LOGGER.info("RandomTeleporter已写入命令注册回调目标命令将会在该注册的时候被注册");
LOGGER.info("RandomTeleporter Loaded!");
} }
} }

View File

@@ -0,0 +1,34 @@
package xyz.thewhitedog9487;
import net.fabricmc.fabric.api.resource.v1.ResourceLoader;
import net.fabricmc.fabric.api.resource.v1.reloader.SimpleResourceReloader;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import static net.minecraft.resource.ResourceType.CLIENT_RESOURCES;
import static xyz.thewhitedog9487.RandomTeleporter.MOD_ID;
/**
* 在游戏资源重新加载之后刷新翻译文本
*/
public class ResourceReloaderListener {
public static String CommandArgumentName_Radius = "Radius(半径)";
public static String CommandArgumentName_Target = "被传送玩家名(PlayerID)";
public static String CommandArgumentName_OriginPosition = "OriginPos(随机中心,坐标)";
public static String CommandArgumentName_OriginEntity = "OriginEntity(随机中心,实体)";
public static void Register(){
ResourceLoader.get(CLIENT_RESOURCES).registerReloader(Identifier.of(MOD_ID, "translate_text_apply"), new SimpleResourceReloader<Void>() {
/**
* 用不到,不用管
*/
@Override
protected Void prepare(Store store) {
return null; }
@Override
protected void apply(Void prepared, Store store) {
CommandArgumentName_Radius = Text.translatableWithFallback("command.argument.radius", "Radius(半径)").getString();
CommandArgumentName_Target = Text.translatableWithFallback("command.argument.target", "被传送玩家名(PlayerID)").getString();
CommandArgumentName_OriginPosition = Text.translatableWithFallback("command.argument.origin_pos", "OriginPos(随机中心,坐标)").getString();
CommandArgumentName_OriginEntity = Text.translatableWithFallback("command.argument.origin_entity", "OriginEntity(随机中心,实体)").getString(); } } ); } }

View File

@@ -5,5 +5,9 @@
"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",
"warning.radius_equal_zero": "Warning: Since you set a random radius of 0, selecting the right height will teleport you directly to %d %d", "warning.radius_equal_zero": "Warning: Since you set a random radius of 0, selecting the right height will teleport you directly to %d %d",
"warning.radius_equal_zero_no_target": "Warning: Since you set a random radius of 0 and you don't set a random center point coordinates, nothing happens", "warning.radius_equal_zero_no_target": "Warning: Since you set a random radius of 0 and you don't set a random center point coordinates, nothing happens",
"bilibili": "Bilibili" "bilibili": "Bilibili",
"command.argument.radius": "radius",
"command.argument.target": "teleported entity",
"command.argument.origin_pos": "origin(pos)",
"command.argument.origin_entity": "origin(entity)"
} }

View File

@@ -5,5 +5,9 @@
"error.no_target": "不存在被传送目标由非玩家物体执行命令时请显式指定被传送玩家ID", "error.no_target": "不存在被传送目标由非玩家物体执行命令时请显式指定被传送玩家ID",
"warning.radius_equal_zero": "警告由于你设置的随机半径为0因此在选择出合适高度之后将直接把你传送至%d %d", "warning.radius_equal_zero": "警告由于你设置的随机半径为0因此在选择出合适高度之后将直接把你传送至%d %d",
"warning.radius_equal_zero_no_target": "警告由于你设置的随机半径为0并且未设置随机中心点坐标因此什么都不会发生", "warning.radius_equal_zero_no_target": "警告由于你设置的随机半径为0并且未设置随机中心点坐标因此什么都不会发生",
"bilibili": "TheWhiteDog9487的哔哩哔哩主页" "bilibili": "TheWhiteDog9487的哔哩哔哩主页",
"command.argument.radius": "半径",
"command.argument.target": "被传送实体",
"command.argument.origin_pos": "随机中心(坐标)",
"command.argument.origin_entity": "随机中心(实体)"
} }

View File

@@ -27,10 +27,10 @@
} }
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.14", "fabricloader": ">=0.17.2",
"minecraft": "1.21.7", "minecraft": "1.21.10",
"java": ">=21", "java": ">=21",
"fabric-api": ">=0.128.1" "fabric-api": ">=0.134.1"
}, },
"suggests": { "suggests": {
"another-mod": "*" "another-mod": "*"