commit
f19f3292d7
|
|
@ -1,4 +1,4 @@
|
||||||
# 版本 0.0.3.8 提前介绍c[最终版本对于0.0.4] 【注意:本解釋簡繁混寫,因爲趕時間,所以並不怎麽規範,請諒解】
|
# 版本 0.0.3.9 提前介绍c[最终版本对于0.0.4] 【注意:本解釋簡繁混寫,因爲趕時間,所以並不怎麽規範,請諒解】
|
||||||
## 简介
|
## 简介
|
||||||
现在开始你可以用拴绳拴住玩家,也可以拴住自己了,不如尝试拴住彼此来通关我的世界吧(
|
现在开始你可以用拴绳拴住玩家,也可以拴住自己了,不如尝试拴住彼此来通关我的世界吧(
|
||||||
|
|
||||||
|
|
@ -34,6 +34,8 @@
|
||||||
|
|
||||||
* `/lp motion [<实体[可多个对象]>] add/set/multiply <x> <y> <z>` - 给实体添加/设置/倍乘 加速度
|
* `/lp motion [<实体[可多个对象]>] add/set/multiply <x> <y> <z>` - 给实体添加/设置/倍乘 加速度
|
||||||
|
|
||||||
|
* `/lp tick ...` - 用法同原版Tick,但权限降为2,只用于调试,切勿滥用,后期考虑可能写成区域性的
|
||||||
|
|
||||||
## 游戏规则
|
## 游戏规则
|
||||||
|
|
||||||
* `LP.TeleportWithLeashedPlayers` - 此規則啓用后, 被栓玩家將會随玩家拴绳持有者一起传送 [默认值: True]
|
* `LP.TeleportWithLeashedPlayers` - 此規則啓用后, 被栓玩家將會随玩家拴绳持有者一起传送 [默认值: True]
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ plugins {
|
||||||
id 'eclipse'
|
id 'eclipse'
|
||||||
id 'idea'
|
id 'idea'
|
||||||
id 'maven-publish'
|
id 'maven-publish'
|
||||||
id 'net.neoforged.gradle.userdev' version '7.0.165'
|
id 'net.neoforged.gradle.userdev' version '7.0.145'
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named('wrapper', Wrapper).configure {
|
tasks.named('wrapper', Wrapper).configure {
|
||||||
|
|
@ -74,7 +74,7 @@ runs {
|
||||||
// workingDirectory project.file('run-data')
|
// workingDirectory project.file('run-data')
|
||||||
systemProperty('gradle.task', 'runData')
|
systemProperty('gradle.task', 'runData')
|
||||||
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
|
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
|
||||||
getArguments().addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
|
programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ minecraft_version=1.21.1
|
||||||
# as they do not follow standard versioning conventions.
|
# as they do not follow standard versioning conventions.
|
||||||
minecraft_version_range=[1.21,1.22)
|
minecraft_version_range=[1.21,1.22)
|
||||||
# The Neo version must agree with the Minecraft version to get a valid artifact
|
# The Neo version must agree with the Minecraft version to get a valid artifact
|
||||||
neo_version=21.1.61
|
neo_version=21.0.157
|
||||||
# The Neo version range can use any version of Neo as bounds
|
# The Neo version range can use any version of Neo as bounds
|
||||||
neo_version_range=[21.0.0-beta,)
|
neo_version_range=[21.0.0-beta,)
|
||||||
# The loader version range can only use the major version of FML as bounds
|
# The loader version range can only use the major version of FML as bounds
|
||||||
|
|
@ -32,7 +32,7 @@ mod_name=Leashed Player
|
||||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||||
mod_license=MIT
|
mod_license=MIT
|
||||||
# The mod version. See https://semver.org/
|
# The mod version. See https://semver.org/
|
||||||
mod_version=0.0.3.8
|
mod_version=0.0.3.9
|
||||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
||||||
# This should match the base package used for the mod sources.
|
# This should match the base package used for the mod sources.
|
||||||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.r3944realms.leashedplayer;
|
||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
import com.r3944realms.leashedplayer.content.commands.LeashCommand;
|
import com.r3944realms.leashedplayer.content.commands.LeashCommand;
|
||||||
import com.r3944realms.leashedplayer.content.commands.MotionCommand;
|
import com.r3944realms.leashedplayer.content.commands.MotionCommand;
|
||||||
|
import com.r3944realms.leashedplayer.content.commands.TickCommand;
|
||||||
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
|
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
|
||||||
import net.minecraft.commands.CommandSourceStack;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
import net.minecraft.world.level.block.DispenserBlock;
|
import net.minecraft.world.level.block.DispenserBlock;
|
||||||
|
|
@ -20,6 +21,7 @@ public class CommonEventHandler {
|
||||||
CommandDispatcher<CommandSourceStack> dispatcher = event.getDispatcher();
|
CommandDispatcher<CommandSourceStack> dispatcher = event.getDispatcher();
|
||||||
LeashCommand.register(dispatcher);
|
LeashCommand.register(dispatcher);
|
||||||
MotionCommand.register(dispatcher);
|
MotionCommand.register(dispatcher);
|
||||||
|
TickCommand.register(dispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,181 @@
|
||||||
|
package com.r3944realms.leashedplayer.content.commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
|
import com.mojang.brigadier.arguments.FloatArgumentType;
|
||||||
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import com.r3944realms.leashedplayer.config.LeashPlayerCommonConfig;
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
import net.minecraft.commands.Commands;
|
||||||
|
import net.minecraft.commands.SharedSuggestionProvider;
|
||||||
|
import net.minecraft.commands.arguments.TimeArgument;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.server.ServerTickRateManager;
|
||||||
|
import net.minecraft.util.TimeUtil;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.r3944realms.leashedplayer.content.commands.Command.getLiterArgumentBuilderOfCSS;
|
||||||
|
|
||||||
|
public class TickCommand {
|
||||||
|
private static final float MAX_TICKRATE = 10000.0F;
|
||||||
|
private static final String DEFAULT_TICKRATE = String.valueOf(20);
|
||||||
|
|
||||||
|
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||||
|
boolean shouldUsePrefix = LeashPlayerCommonConfig.EnableLeashPlayerCommandPrefix.get();
|
||||||
|
@Nullable List<LiteralArgumentBuilder<CommandSourceStack>> nodeList = shouldUsePrefix ? null : new ArrayList<>();
|
||||||
|
LiteralArgumentBuilder<CommandSourceStack> literalArgumentBuilder = Commands.literal(com.r3944realms.leashedplayer.content.commands.Command.PREFIX);
|
||||||
|
LiteralArgumentBuilder<CommandSourceStack> $$TickRoot = getLiterArgumentBuilderOfCSS("tick", !shouldUsePrefix, nodeList);
|
||||||
|
|
||||||
|
LiteralArgumentBuilder<CommandSourceStack> Tick = $$TickRoot.requires(p_308941_ -> p_308941_.hasPermission(2))
|
||||||
|
.then(Commands.literal("query").executes(p_308950_ -> tickQuery(p_308950_.getSource())))
|
||||||
|
.then(
|
||||||
|
Commands.literal("rate")
|
||||||
|
.then(
|
||||||
|
Commands.argument("rate", FloatArgumentType.floatArg(1.0F, 10000.0F))
|
||||||
|
.suggests((p_308897_, p_308880_) -> SharedSuggestionProvider.suggest(new String[]{DEFAULT_TICKRATE}, p_308880_))
|
||||||
|
.executes(p_309119_ -> setTickingRate(p_309119_.getSource(), FloatArgumentType.getFloat(p_309119_, "rate")))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
Commands.literal("step")
|
||||||
|
.executes(p_309496_ -> step(p_309496_.getSource(), 1))
|
||||||
|
.then(Commands.literal("stop").executes(p_309035_ -> stopStepping(p_309035_.getSource())))
|
||||||
|
.then(
|
||||||
|
Commands.argument("time", TimeArgument.time(1))
|
||||||
|
.suggests((p_309113_, p_309105_) -> SharedSuggestionProvider.suggest(new String[]{"1t", "1s"}, p_309105_))
|
||||||
|
.executes(p_308930_ -> step(p_308930_.getSource(), IntegerArgumentType.getInteger(p_308930_, "time")))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
Commands.literal("sprint")
|
||||||
|
.then(Commands.literal("stop").executes(p_309190_ -> stopSprinting(p_309190_.getSource())))
|
||||||
|
.then(
|
||||||
|
Commands.argument("time", TimeArgument.time(1))
|
||||||
|
.suggests((p_308987_, p_309101_) -> SharedSuggestionProvider.suggest(new String[]{"60s", "1d", "3d"}, p_309101_))
|
||||||
|
.executes(p_308904_ -> sprint(p_308904_.getSource(), IntegerArgumentType.getInteger(p_308904_, "time")))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("unfreeze").executes(p_309184_ -> setFreeze(p_309184_.getSource(), false)))
|
||||||
|
.then(Commands.literal("freeze").executes(p_309070_ -> setFreeze(p_309070_.getSource(), true)));
|
||||||
|
if(shouldUsePrefix){
|
||||||
|
literalArgumentBuilder.then(Tick);
|
||||||
|
dispatcher.register(literalArgumentBuilder);
|
||||||
|
} else {
|
||||||
|
nodeList.forEach(dispatcher::register);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String nanosToMilisString(long nanos) {
|
||||||
|
return String.format("%.1f", (float)nanos / (float) TimeUtil.NANOSECONDS_PER_MILLISECOND);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int setTickingRate(CommandSourceStack source, float tickRate) {
|
||||||
|
ServerTickRateManager servertickratemanager = source.getServer().tickRateManager();
|
||||||
|
servertickratemanager.setTickRate(tickRate);
|
||||||
|
String s = String.format("%.1f", tickRate);
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.tick.rate.success", s), true);
|
||||||
|
return (int)tickRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int tickQuery(CommandSourceStack source) {
|
||||||
|
ServerTickRateManager servertickratemanager = source.getServer().tickRateManager();
|
||||||
|
String s = nanosToMilisString(source.getServer().getAverageTickTimeNanos());
|
||||||
|
float f = servertickratemanager.tickrate();
|
||||||
|
String s1 = String.format("%.1f", f);
|
||||||
|
if (servertickratemanager.isSprinting()) {
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.tick.status.sprinting"), false);
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.tick.query.rate.sprinting", s1, s), false);
|
||||||
|
} else {
|
||||||
|
if (servertickratemanager.isFrozen()) {
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.tick.status.frozen"), false);
|
||||||
|
} else if (servertickratemanager.nanosecondsPerTick() < source.getServer().getAverageTickTimeNanos()) {
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.tick.status.lagging"), false);
|
||||||
|
} else {
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.tick.status.running"), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
String s2 = nanosToMilisString(servertickratemanager.nanosecondsPerTick());
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.tick.query.rate.running", s1, s, s2), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
long[] along = Arrays.copyOf(source.getServer().getTickTimesNanos(), source.getServer().getTickTimesNanos().length);
|
||||||
|
Arrays.sort(along);
|
||||||
|
String s3 = nanosToMilisString(along[along.length / 2]);
|
||||||
|
String s4 = nanosToMilisString(along[(int)((double)along.length * 0.95)]);
|
||||||
|
String s5 = nanosToMilisString(along[(int)((double)along.length * 0.99)]);
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.tick.query.percentiles", s3, s4, s5, along.length), false);
|
||||||
|
return (int)f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int sprint(CommandSourceStack source, int sprintTime) {
|
||||||
|
boolean flag = source.getServer().tickRateManager().requestGameToSprint(sprintTime);
|
||||||
|
if (flag) {
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.tick.sprint.stop.success"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.tick.status.sprinting"), true);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int setFreeze(CommandSourceStack source, boolean frozen) {
|
||||||
|
ServerTickRateManager servertickratemanager = source.getServer().tickRateManager();
|
||||||
|
if (frozen) {
|
||||||
|
if (servertickratemanager.isSprinting()) {
|
||||||
|
servertickratemanager.stopSprinting();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (servertickratemanager.isSteppingForward()) {
|
||||||
|
servertickratemanager.stopStepping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
servertickratemanager.setFrozen(frozen);
|
||||||
|
if (frozen) {
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.tick.status.frozen"), true);
|
||||||
|
} else {
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.tick.status.running"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return frozen ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int step(CommandSourceStack source, int ticks) {
|
||||||
|
ServerTickRateManager servertickratemanager = source.getServer().tickRateManager();
|
||||||
|
boolean flag = servertickratemanager.stepGameIfPaused(ticks);
|
||||||
|
if (flag) {
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.tick.step.success", ticks), true);
|
||||||
|
} else {
|
||||||
|
source.sendFailure(Component.translatable("commands.tick.step.fail"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int stopStepping(CommandSourceStack source) {
|
||||||
|
ServerTickRateManager servertickratemanager = source.getServer().tickRateManager();
|
||||||
|
boolean flag = servertickratemanager.stopStepping();
|
||||||
|
if (flag) {
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.tick.step.stop.success"), true);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
source.sendFailure(Component.translatable("commands.tick.step.stop.fail"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int stopSprinting(CommandSourceStack source) {
|
||||||
|
ServerTickRateManager servertickratemanager = source.getServer().tickRateManager();
|
||||||
|
boolean flag = servertickratemanager.stopSprinting();
|
||||||
|
if (flag) {
|
||||||
|
source.sendSuccess(() -> Component.translatable("commands.tick.sprint.stop.success"), true);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
source.sendFailure(Component.translatable("commands.tick.sprint.stop.fail"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -180,6 +180,7 @@ public class LeashRopeArrow extends AbstractArrow {
|
||||||
protected void onHitEntity(@NotNull EntityHitResult pResult) {
|
protected void onHitEntity(@NotNull EntityHitResult pResult) {
|
||||||
if(!level().isClientSide()){
|
if(!level().isClientSide()){
|
||||||
Entity entity = pResult.getEntity();
|
Entity entity = pResult.getEntity();
|
||||||
|
hitOnEntityHandler(entity);
|
||||||
if(entity instanceof LivingEntity livingEntity){
|
if(entity instanceof LivingEntity livingEntity){
|
||||||
if(livingEntity.equals(this.getOwner())) return;
|
if(livingEntity.equals(this.getOwner())) return;
|
||||||
if(this.getOwner() == null && livingEntity instanceof PlayerLeashable pL) { //发射器发出或命令生成
|
if(this.getOwner() == null && livingEntity instanceof PlayerLeashable pL) { //发射器发出或命令生成
|
||||||
|
|
@ -193,12 +194,15 @@ public class LeashRopeArrow extends AbstractArrow {
|
||||||
} else if (this.getOwner() instanceof PlayerLeashable pL) {
|
} else if (this.getOwner() instanceof PlayerLeashable pL) {
|
||||||
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level());
|
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level());
|
||||||
if(leashDataEntity != null) pL.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow));
|
if(leashDataEntity != null) pL.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow));
|
||||||
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getSelfItemStack());
|
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack());
|
||||||
ILivingEntityExtension pLL = (ILivingEntityExtension) pL;
|
ILivingEntityExtension pLL = (ILivingEntityExtension) pL;
|
||||||
pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID));
|
pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID));
|
||||||
pL.setLeashedTo(pResult.getEntity(), true);
|
pL.setLeashedTo(pResult.getEntity(), true);
|
||||||
this.level().addFreshEntity(arrow);
|
this.level().addFreshEntity(arrow);
|
||||||
discard();
|
discard();
|
||||||
|
} else {
|
||||||
|
ItemEntity lead = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, Items.LEAD.getDefaultInstance());
|
||||||
|
this.level().addFreshEntity(lead);
|
||||||
}
|
}
|
||||||
} else if (entity instanceof LeashFenceKnotEntity leashKnotFence) {
|
} else if (entity instanceof LeashFenceKnotEntity leashKnotFence) {
|
||||||
if (getOwner() instanceof PlayerLeashable pL) {
|
if (getOwner() instanceof PlayerLeashable pL) {
|
||||||
|
|
@ -212,6 +216,9 @@ public class LeashRopeArrow extends AbstractArrow {
|
||||||
discard();
|
discard();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ItemEntity lead = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, Items.LEAD.getDefaultInstance());
|
||||||
|
this.level().addFreshEntity(lead);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.onHitEntity(pResult);
|
super.onHitEntity(pResult);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.world.effect.MobEffectInstance;
|
import net.minecraft.world.effect.MobEffectInstance;
|
||||||
import net.minecraft.world.effect.MobEffects;
|
import net.minecraft.world.effect.MobEffects;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.EntityType;
|
import net.minecraft.world.entity.EntityType;
|
||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.entity.projectile.AbstractArrow;
|
import net.minecraft.world.entity.projectile.AbstractArrow;
|
||||||
|
|
@ -68,4 +69,13 @@ public class SpectralLeashRopeArrow extends LeashRopeArrow {
|
||||||
protected ItemStack getSelfItemStack() {
|
protected ItemStack getSelfItemStack() {
|
||||||
return ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get().getDefaultInstance();
|
return ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get().getDefaultInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void hitOnEntityHandler(Entity pEntity) {
|
||||||
|
if(pEntity instanceof LivingEntity livingEntity) {
|
||||||
|
livingEntity.addEffect(new MobEffectInstance(MobEffects.GLOWING, this.duration, 0));
|
||||||
|
} else {
|
||||||
|
super.hitOnEntityHandler(pEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user