171 lines
4.8 KiB
Java
171 lines
4.8 KiB
Java
package carpet.patches;
|
|
|
|
import carpet.CarpetServer;
|
|
import net.minecraft.server.MinecraftServer;
|
|
import net.minecraft.server.ServerTickRateManager;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.util.TimeUtil;
|
|
import net.minecraft.world.level.border.BorderChangeListener;
|
|
import net.minecraft.world.level.border.BorderStatus;
|
|
import net.minecraft.world.level.border.WorldBorder;
|
|
import net.minecraft.world.phys.shapes.BooleanOp;
|
|
import net.minecraft.world.phys.shapes.Shapes;
|
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
/**
|
|
* This class is essentially a copy of {@link net.minecraft.world.level.border.WorldBorder.MovingBorderExtent}
|
|
* but instead of using real time to lerp the border
|
|
* this class uses the in game ticks.
|
|
*/
|
|
@SuppressWarnings("JavadocReference")
|
|
public class TickSyncedBorderExtent implements WorldBorder.BorderExtent
|
|
{
|
|
private final WorldBorder border;
|
|
private final long realDuration;
|
|
private final double tickDuration;
|
|
private final double from;
|
|
private final double to;
|
|
|
|
private int ticks;
|
|
|
|
public TickSyncedBorderExtent(WorldBorder border, long realDuration, double from, double to)
|
|
{
|
|
this.border = border;
|
|
this.realDuration = realDuration;
|
|
this.tickDuration = realDuration / 50.0;
|
|
this.from = from;
|
|
this.to = to;
|
|
this.ticks = 0;
|
|
}
|
|
|
|
@Override
|
|
public double getMinX()
|
|
{
|
|
int maxSize = this.border.getAbsoluteMaxSize();
|
|
return Mth.clamp(this.border.getCenterX() - this.getSize() / 2.0, -maxSize, maxSize);
|
|
}
|
|
|
|
@Override
|
|
public double getMaxX()
|
|
{
|
|
int maxSize = this.border.getAbsoluteMaxSize();
|
|
return Mth.clamp(this.border.getCenterX() + this.getSize() / 2.0, -maxSize, maxSize);
|
|
}
|
|
|
|
@Override
|
|
public double getMinZ()
|
|
{
|
|
int maxSize = this.border.getAbsoluteMaxSize();
|
|
return Mth.clamp(this.border.getCenterZ() - this.getSize() / 2.0, -maxSize, maxSize);
|
|
}
|
|
|
|
@Override
|
|
public double getMaxZ()
|
|
{
|
|
int maxSize = this.border.getAbsoluteMaxSize();
|
|
return Mth.clamp(this.border.getCenterZ() + this.getSize() / 2.0, -maxSize, maxSize);
|
|
}
|
|
|
|
@Override
|
|
public double getSize()
|
|
{
|
|
double progress = this.ticks / this.tickDuration;
|
|
return progress < 1.0 ? Mth.lerp(progress, this.from, this.to) : this.to;
|
|
}
|
|
|
|
@Override
|
|
public double getLerpSpeed()
|
|
{
|
|
return Math.abs(this.from - this.to) / this.realDuration;
|
|
}
|
|
|
|
@Override
|
|
public long getLerpTime()
|
|
{
|
|
// Rough estimation
|
|
MinecraftServer server = CarpetServer.minecraft_server;
|
|
double ms;
|
|
if (server == null)
|
|
{
|
|
// can this even happen?
|
|
ms = 50.0;
|
|
}
|
|
else
|
|
{
|
|
ms = ((double)server.getAverageTickTimeNanos())/ TimeUtil.NANOSECONDS_PER_MILLISECOND;
|
|
ServerTickRateManager trm = server.tickRateManager();
|
|
if (!trm.isSprinting())
|
|
{
|
|
ms = Math.max(ms, trm.millisecondsPerTick());
|
|
}
|
|
}
|
|
double tps = 1_000.0D / ms;
|
|
return (long) ((this.tickDuration - this.ticks) / tps * 1_000);
|
|
}
|
|
|
|
@Override
|
|
public double getLerpTarget()
|
|
{
|
|
return this.to;
|
|
}
|
|
|
|
@NotNull
|
|
@Override
|
|
public BorderStatus getStatus()
|
|
{
|
|
return this.to < this.from ? BorderStatus.SHRINKING : BorderStatus.GROWING;
|
|
}
|
|
|
|
@Override
|
|
public void onAbsoluteMaxSizeChange()
|
|
{
|
|
|
|
}
|
|
|
|
@Override
|
|
public void onCenterChange()
|
|
{
|
|
|
|
}
|
|
|
|
@NotNull
|
|
@Override
|
|
public WorldBorder.BorderExtent update()
|
|
{
|
|
if (this.ticks++ % 20 == 0)
|
|
{
|
|
// We need to update any listeners
|
|
// Most importantly those that send updates to the client
|
|
// This is because the client logic uses real time
|
|
// So if the tick speed has changed we need to tell the client
|
|
for (BorderChangeListener listener : this.border.getListeners())
|
|
{
|
|
// We do not want to update DelegateBorderChangeListener
|
|
// This updates borders in other dimensions
|
|
listener.onLerpSize(this.border, this.from, this.to, this.realDuration);
|
|
}
|
|
}
|
|
|
|
return this.ticks >= this.tickDuration ? this.border.new StaticBorderExtent(this.to) : this;
|
|
}
|
|
|
|
@NotNull
|
|
@Override
|
|
public VoxelShape getCollisionShape()
|
|
{
|
|
return Shapes.join(
|
|
Shapes.INFINITY,
|
|
Shapes.box(
|
|
Math.floor(this.getMinX()),
|
|
Double.NEGATIVE_INFINITY,
|
|
Math.floor(this.getMinZ()),
|
|
Math.ceil(this.getMaxX()),
|
|
Double.POSITIVE_INFINITY,
|
|
Math.ceil(this.getMaxZ())
|
|
),
|
|
BooleanOp.ONLY_FIRST
|
|
);
|
|
}
|
|
}
|