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

View file

@ -47,7 +47,7 @@ object OpBlink : SpellAction {
private data class Spell(val target: Entity, val delta: Double) : RenderedSpell { private data class Spell(val target: Entity, val delta: Double) : RenderedSpell {
override fun cast(ctx: CastingContext) { override fun cast(ctx: CastingContext) {
val delta = target.lookAngle.scale(delta) 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.lib.HexEntityTags
import at.petrak.hexcasting.common.network.MsgBlinkAck import at.petrak.hexcasting.common.network.MsgBlinkAck
import at.petrak.hexcasting.xplat.IXplatAbstractions 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.ServerPlayer
import net.minecraft.server.level.TicketType
import net.minecraft.world.entity.Entity import net.minecraft.world.entity.Entity
import net.minecraft.world.item.enchantment.EnchantmentHelper import net.minecraft.world.item.enchantment.EnchantmentHelper
import net.minecraft.world.level.ChunkPos
import net.minecraft.world.phys.Vec3 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 // 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?) // TODO make this not a magic number (config?)
if (distance < 32768.0) { if (distance < 32768.0) {
teleportRespectSticky(teleportee, delta) teleportRespectSticky(teleportee, delta, ctx.world)
} }
if (teleportee is ServerPlayer && teleportee == ctx.caster) { 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 base = teleportee.rootVehicle
val target = base.position().add(delta)
val playersToUpdate = mutableListOf<ServerPlayer>() val playersToUpdate = mutableListOf<ServerPlayer>()
val indirect = base.indirectPassengers val indirect = base.indirectPassengers
@ -100,7 +105,6 @@ object OpTeleport : SpellAction {
if (sticky) { if (sticky) {
// this handles teleporting the passengers // this handles teleporting the passengers
val target = base.position().add(delta)
base.teleportTo(target.x, target.y, target.z) base.teleportTo(target.x, target.y, target.z)
indirect indirect
.filterIsInstance<ServerPlayer>() .filterIsInstance<ServerPlayer>()
@ -109,14 +113,21 @@ object OpTeleport : SpellAction {
// Break it into two stacks // Break it into two stacks
teleportee.stopRiding() teleportee.stopRiding()
teleportee.passengers.forEach(Entity::stopRiding) teleportee.passengers.forEach(Entity::stopRiding)
teleportee.setPos(teleportee.position().add(delta))
if (teleportee is ServerPlayer) { if (teleportee is ServerPlayer) {
playersToUpdate.add(teleportee) playersToUpdate.add(teleportee)
} else {
teleportee.setPos(teleportee.position().add(delta))
} }
} }
for (player in playersToUpdate) { 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.connection.resetPosition()
player.setPos(target)
IXplatAbstractions.INSTANCE.sendPacketToPlayer(player, MsgBlinkAck(delta)) IXplatAbstractions.INSTANCE.sendPacketToPlayer(player, MsgBlinkAck(delta))
} }
} }

View file

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

View file

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