probably fix #327?

This commit is contained in:
petrak@ 2022-11-29 14:21:38 -05:00
parent 3a8dfa6cc8
commit 725aa894d4
5 changed files with 56 additions and 40 deletions

View file

@ -34,7 +34,7 @@ public class PatternRegistry {
new ConcurrentHashMap<>();
public static void mapPattern(HexPattern pattern, ResourceLocation id,
Action action) throws RegisterPatternException {
Action action) throws RegisterPatternException {
mapPattern(pattern, id, action, false);
}
@ -42,7 +42,7 @@ public class PatternRegistry {
* Associate a given angle signature with a SpellOperator.
*/
public static void mapPattern(HexPattern pattern, ResourceLocation id, Action action,
boolean isPerWorld) throws RegisterPatternException {
boolean isPerWorld) throws RegisterPatternException {
if (actionLookup.containsKey(id)) {
throw new RegisterPatternException("The operator with id `%s` was already registered to: %s", id,
actionLookup.get(id));
@ -83,7 +83,7 @@ public class PatternRegistry {
* Internal use only.
*/
public static Pair<Action, ResourceLocation> matchPatternAndID(HexPattern pat,
ServerLevel overworld) throws MishapInvalidPattern {
ServerLevel overworld) throws MishapInvalidPattern {
// Pipeline:
// patterns are registered here every time the game boots
// when we try to look
@ -143,7 +143,8 @@ public class PatternRegistry {
return actionLookup.get(it.opId);
}
// Currently, there's no way to look up the name of a Great Spell, as the client is unaware of the correct mapping.
// Currently, there's no way to look up the name of a Great Spell, as the client is unaware of the correct
// mapping.
// TODO: add code to match any pattern in the shape of a Great Spell to its operator.
// var ds = overworld.getDataStorage();
@ -160,6 +161,8 @@ public class PatternRegistry {
/**
* Internal use only.
* <p>
* Map of signatures to (op id, canonical start dir)
*/
public static Map<String, Pair<ResourceLocation, HexDir>> getPerWorldPatterns(ServerLevel overworld) {
var ds = overworld.getDataStorage();
@ -301,7 +304,8 @@ public class PatternRegistry {
return new Save(map, missingEntries);
}
private static void scrungle(Map<String, Pair<ResourceLocation, HexDir>> lookup, HexPattern prototype, ResourceLocation opId, long seed) {
private static void scrungle(Map<String, Pair<ResourceLocation, HexDir>> lookup, HexPattern prototype,
ResourceLocation opId, long seed) {
var scrungled = EulerPathFinder.findAltDrawing(prototype, seed, it -> {
var sig = it.anglesSignature();
return !lookup.containsKey(sig) &&

View file

@ -47,7 +47,7 @@ object OpBlink : SpellAction {
private data class Spell(val target: Entity, val delta: Double) : RenderedSpell {
override fun cast(ctx: CastingContext) {
val delta = target.lookAngle.scale(delta)
OpTeleport.teleportRespectSticky(target, delta)
OpTeleport.teleportRespectSticky(target, delta, ctx.world)
}
}
}

View file

@ -9,9 +9,13 @@ import at.petrak.hexcasting.api.spell.mishaps.MishapLocationTooFarAway
import at.petrak.hexcasting.common.lib.HexEntityTags
import at.petrak.hexcasting.common.network.MsgBlinkAck
import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.core.BlockPos
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.server.level.TicketType
import net.minecraft.world.entity.Entity
import net.minecraft.world.item.enchantment.EnchantmentHelper
import net.minecraft.world.level.ChunkPos
import net.minecraft.world.phys.Vec3
// TODO while we're making breaking changes I *really* want to have the vector in the entity's local space
@ -51,7 +55,7 @@ object OpTeleport : SpellAction {
// TODO make this not a magic number (config?)
if (distance < 32768.0) {
teleportRespectSticky(teleportee, delta)
teleportRespectSticky(teleportee, delta, ctx.world)
}
if (teleportee is ServerPlayer && teleportee == ctx.caster) {
@ -87,8 +91,9 @@ object OpTeleport : SpellAction {
}
}
fun teleportRespectSticky(teleportee: Entity, delta: Vec3) {
fun teleportRespectSticky(teleportee: Entity, delta: Vec3, world: ServerLevel) {
val base = teleportee.rootVehicle
val target = base.position().add(delta)
val playersToUpdate = mutableListOf<ServerPlayer>()
val indirect = base.indirectPassengers
@ -100,7 +105,6 @@ object OpTeleport : SpellAction {
if (sticky) {
// this handles teleporting the passengers
val target = base.position().add(delta)
base.teleportTo(target.x, target.y, target.z)
indirect
.filterIsInstance<ServerPlayer>()
@ -109,14 +113,21 @@ object OpTeleport : SpellAction {
// Break it into two stacks
teleportee.stopRiding()
teleportee.passengers.forEach(Entity::stopRiding)
teleportee.setPos(teleportee.position().add(delta))
if (teleportee is ServerPlayer) {
playersToUpdate.add(teleportee)
} else {
teleportee.setPos(teleportee.position().add(delta))
}
}
for (player in playersToUpdate) {
// See TeleportCommand
val chunkPos = ChunkPos(BlockPos(delta))
// the `1` is apparently for "distance." i'm not sure what it does but this is what
// /tp does
world.chunkSource.addRegionTicket(TicketType.POST_TELEPORT, chunkPos, 1, player.id)
player.connection.resetPosition()
player.setPos(target)
IXplatAbstractions.INSTANCE.sendPacketToPlayer(player, MsgBlinkAck(delta))
}
}

View file

@ -22,32 +22,33 @@ import java.util.List;
public class ListPatternsCommand {
public static void add(LiteralArgumentBuilder<CommandSourceStack> cmd) {
cmd.then(Commands.literal("patterns")
.requires(dp -> dp.hasPermission(Commands.LEVEL_GAMEMASTERS))
.then(Commands.literal("list")
.executes(ctx -> list(ctx.getSource())))
.then(Commands.literal("give")
.then(Commands.argument("patternName", PatternResLocArgument.id())
.executes(ctx ->
giveOne(ctx.getSource(),
getDefaultTarget(ctx.getSource()),
ResourceLocationArgument.getId(ctx, "patternName"),
PatternResLocArgument.getPattern(ctx, "patternName")))
.then(Commands.argument("targets", EntityArgument.players())
.executes(ctx ->
giveOne(ctx.getSource(),
EntityArgument.getPlayers(ctx, "targets"),
ResourceLocationArgument.getId(ctx, "patternName"),
PatternResLocArgument.getPattern(ctx, "patternName"))))))
.then(Commands.literal("giveAll")
.requires(dp -> dp.hasPermission(Commands.LEVEL_GAMEMASTERS))
.then(Commands.literal("list")
.executes(ctx -> list(ctx.getSource())))
.then(Commands.literal("give")
.then(Commands.argument("patternName", PatternResLocArgument.id())
.executes(ctx ->
giveAll(ctx.getSource(),
getDefaultTarget(ctx.getSource())))
giveOne(ctx.getSource(),
getDefaultTarget(ctx.getSource()),
ResourceLocationArgument.getId(ctx, "patternName"),
PatternResLocArgument.getPattern(ctx, "patternName")))
.then(Commands.argument("targets", EntityArgument.players())
.executes(ctx ->
giveAll(ctx.getSource(),
EntityArgument.getPlayers(ctx, "targets")))))
);
giveOne(ctx.getSource(),
EntityArgument.getPlayers(ctx, "targets"),
ResourceLocationArgument.getId(ctx, "patternName"),
PatternResLocArgument.getPattern(ctx, "patternName"))))))
.then(Commands.literal("giveAll")
.executes(ctx ->
giveAll(ctx.getSource(),
getDefaultTarget(ctx.getSource())))
.then(Commands.argument("targets", EntityArgument.players())
.executes(ctx ->
giveAll(ctx.getSource(),
EntityArgument.getPlayers(ctx, "targets")))))
);
}
private static Collection<ServerPlayer> getDefaultTarget(CommandSourceStack source) {
if (source.getEntity() instanceof ServerPlayer player) {
return List.of(player);
@ -78,14 +79,14 @@ public class ListPatternsCommand {
if (!targets.isEmpty()) {
var lookup = PatternRegistry.getPerWorldPatterns(source.getLevel());
lookup.forEach((pattern, entry) -> {
lookup.forEach((sig, entry) -> {
var opId = entry.getFirst();
var startDir = entry.getSecond();
var tag = new CompoundTag();
tag.putString(ItemScroll.TAG_OP_ID, opId.toString());
tag.put(ItemScroll.TAG_PATTERN,
HexPattern.fromAngles(pattern, startDir).serializeToNBT());
HexPattern.fromAngles(sig, startDir).serializeToNBT());
var stack = new ItemStack(HexItems.SCROLL_LARGE);
stack.setTag(tag);
@ -110,12 +111,12 @@ public class ListPatternsCommand {
}
}
private static int giveOne(CommandSourceStack source, Collection<ServerPlayer> targets, ResourceLocation patternName, HexPattern pat) {
private static int giveOne(CommandSourceStack source, Collection<ServerPlayer> targets,
ResourceLocation patternName, HexPattern pat) {
if (!targets.isEmpty()) {
var tag = new CompoundTag();
tag.putString(ItemScroll.TAG_OP_ID, patternName.toString());
tag.put(ItemScroll.TAG_PATTERN,
pat.serializeToNBT());
tag.put(ItemScroll.TAG_PATTERN, pat.serializeToNBT());
var stack = new ItemStack(HexItems.SCROLL_LARGE);
stack.setTag(tag);

View file

@ -36,10 +36,10 @@ public class PatternResLocArgument extends ResourceLocationArgument {
var targetId = ctx.getArgument(pName, ResourceLocation.class);
var lookup = PatternRegistry.getPerWorldPatterns(ctx.getSource().getLevel());
HexPattern foundPat = null;
for (var key : lookup.keySet()) {
var rhs = lookup.get(key);
for (var sig : lookup.keySet()) {
var rhs = lookup.get(sig);
if (rhs.getFirst().equals(targetId)) {
foundPat = HexPattern.fromAngles(key, rhs.getSecond());
foundPat = HexPattern.fromAngles(sig, rhs.getSecond());
break;
}
}