some bugfixes, very untested
|
@ -1,21 +1,12 @@
|
|||
package at.petrak.hex;
|
||||
|
||||
import at.petrak.hex.api.PatternRegistry;
|
||||
import at.petrak.hex.api.SpellOperator;
|
||||
import at.petrak.hex.common.casting.SpellDatum;
|
||||
import at.petrak.hex.common.casting.SpellWidget;
|
||||
import at.petrak.hex.common.casting.operators.*;
|
||||
import at.petrak.hex.common.casting.operators.math.*;
|
||||
import at.petrak.hex.common.casting.operators.spells.*;
|
||||
import at.petrak.hex.common.casting.RegisterSpells;
|
||||
import at.petrak.hex.common.items.HexItems;
|
||||
import at.petrak.hex.common.network.HexMessages;
|
||||
import at.petrak.hex.server.TickScheduler;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
@ -44,97 +35,7 @@ public class HexMod {
|
|||
HexItems.ITEMS.register(evbus);
|
||||
HexMessages.register();
|
||||
MinecraftForge.EVENT_BUS.register(TickScheduler.INSTANCE);
|
||||
}
|
||||
|
||||
// I guess this means the client will have a big empty map for patterns
|
||||
@SubscribeEvent
|
||||
public static void registerSpellPatterns(FMLCommonSetupEvent evt) {
|
||||
int count = 0;
|
||||
try {
|
||||
for (Pair<String, SpellOperator> p : new Pair[]{
|
||||
// == Getters ==
|
||||
|
||||
new Pair<>("qaq", OpGetCaster.INSTANCE),
|
||||
new Pair<>("ede", OpGetCaster.INSTANCE),
|
||||
new Pair<>("aa", OpEntityPos.INSTANCE),
|
||||
new Pair<>("dd", OpEntityPos.INSTANCE),
|
||||
new Pair<>("wa", OpEntityLook.INSTANCE),
|
||||
new Pair<>("wd", OpEntityLook.INSTANCE),
|
||||
|
||||
new Pair<>("wqaawdd", OpBlockRaycast.INSTANCE),
|
||||
new Pair<>("weddwaa", OpBlockAxisRaycast.INSTANCE),
|
||||
new Pair<>("weaqa", OpEntityRaycast.INSTANCE),
|
||||
|
||||
// == Modify Stack ==
|
||||
|
||||
new Pair<>("a", OpUndo.INSTANCE),
|
||||
new Pair<>("d", SpellWidget.NULL),
|
||||
new Pair<>("aadaa", OpDuplicate.INSTANCE),
|
||||
new Pair<>("aawdd", OpSwap.INSTANCE),
|
||||
|
||||
// == Math ==
|
||||
new Pair<>("waaw", OpAdd.INSTANCE),
|
||||
new Pair<>("wddw", OpSub.INSTANCE),
|
||||
new Pair<>("waqaw", OpMulDot.INSTANCE),
|
||||
new Pair<>("wdedw", OpDivCross.INSTANCE),
|
||||
new Pair<>("wqaqw", OpAbsLen.INSTANCE),
|
||||
new Pair<>("wedew", OpPowProj.INSTANCE),
|
||||
|
||||
// == Spells ==
|
||||
|
||||
new Pair<>("de", OpPrint.INSTANCE),
|
||||
new Pair<>("aq", OpPrint.INSTANCE),
|
||||
new Pair<>("aawaawaa", OpExplode.INSTANCE),
|
||||
new Pair<>("weeewdq", OpAddMotion.INSTANCE),
|
||||
new Pair<>("qaqqqqq", OpPlaceBlock.INSTANCE),
|
||||
new Pair<>("eeeeede", OpBreakBlock.INSTANCE),
|
||||
new Pair<>("waadwawdaaweewq", OpLightning.INSTANCE),
|
||||
|
||||
// == Meta stuff ==
|
||||
new Pair<>("qqq", SpellWidget.OPEN_PAREN),
|
||||
new Pair<>("eee", SpellWidget.CLOSE_PAREN),
|
||||
new Pair<>("qqqaw", SpellWidget.ESCAPE),
|
||||
// http://www.toroidalsnark.net/mkss3-pix/CalderheadJMM2014.pdf
|
||||
// eval being a space filling curve feels apt doesn't it
|
||||
new Pair<>("deaqq", OpEval.INSTANCE),
|
||||
new Pair<>("aqqqqq", OpRead.INSTANCE),
|
||||
new Pair<>("deeeee", OpWrite.INSTANCE),
|
||||
}) {
|
||||
PatternRegistry.addRegularPattern(p.getFirst(), p.getSecond());
|
||||
count++;
|
||||
}
|
||||
} catch (PatternRegistry.RegisterPatternException exn) {
|
||||
exn.printStackTrace();
|
||||
}
|
||||
|
||||
// Add zilde->number
|
||||
PatternRegistry.addSpecialHandler(pat -> {
|
||||
var sig = pat.anglesSignature();
|
||||
if (sig.startsWith("aqaa") || sig.startsWith("dedd")) {
|
||||
var negate = sig.startsWith("dedd");
|
||||
var accumulator = 0.0;
|
||||
for (char ch : sig.substring(4).toCharArray()) {
|
||||
if (ch == 'w') {
|
||||
accumulator += 1;
|
||||
} else if (ch == 'q') {
|
||||
accumulator += 5;
|
||||
} else if (ch == 'e') {
|
||||
accumulator += 10;
|
||||
} else if (ch == 'a') {
|
||||
accumulator *= 2;
|
||||
} else if (ch == 'd') {
|
||||
accumulator /= 2;
|
||||
}
|
||||
}
|
||||
if (negate) {
|
||||
accumulator = -accumulator;
|
||||
}
|
||||
return SpellOperator.makeConstantOp(SpellDatum.make(accumulator));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
HexMod.LOGGER.info("Registered {} patterns", count);
|
||||
evbus.register(RegisterSpells.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,12 @@ public class RegisterClientStuff {
|
|||
public static void init(final FMLClientSetupEvent evt) {
|
||||
evt.enqueueWork(() -> ItemProperties.register(HexItems.FOCUS.get(), ItemFocus.PREDICATE,
|
||||
(stack, level, holder, holderID) -> {
|
||||
var tag = stack.getOrCreateTag();
|
||||
var isSealed = tag.getBoolean(ItemFocus.TAG_SEALED);
|
||||
var baseNum = isSealed ? 100f : 0f;
|
||||
if (stack.hasTag()) {
|
||||
var tagname = stack.getTag().getCompound(ItemFocus.TAG_DATA).getAllKeys().iterator().next();
|
||||
return switch (tagname) {
|
||||
var typename = tag.getCompound(ItemFocus.TAG_DATA).getAllKeys().iterator().next();
|
||||
return baseNum + switch (typename) {
|
||||
case SpellDatum.TAG_ENTITY -> 1f;
|
||||
case SpellDatum.TAG_DOUBLE -> 2f;
|
||||
case SpellDatum.TAG_VEC3 -> 3f;
|
||||
|
@ -29,7 +32,7 @@ public class RegisterClientStuff {
|
|||
default -> 0f; // uh oh
|
||||
};
|
||||
} else {
|
||||
return 0f;
|
||||
return baseNum;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
|
120
src/main/java/at/petrak/hex/common/casting/RegisterSpells.java
Normal file
|
@ -0,0 +1,120 @@
|
|||
package at.petrak.hex.common.casting;
|
||||
|
||||
import at.petrak.hex.HexMod;
|
||||
import at.petrak.hex.api.PatternRegistry;
|
||||
import at.petrak.hex.api.SpellOperator;
|
||||
import at.petrak.hex.common.casting.operators.*;
|
||||
import at.petrak.hex.common.casting.operators.math.*;
|
||||
import at.petrak.hex.common.casting.operators.spells.*;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
|
||||
public class RegisterSpells {
|
||||
// I guess this means the client will have a big empty map for patterns
|
||||
@SubscribeEvent
|
||||
public static void registerSpellPatterns(FMLCommonSetupEvent evt) {
|
||||
int count = 0;
|
||||
try {
|
||||
// In general:
|
||||
// - CCW is the normal or construction version
|
||||
// - CW is the special or destruction version
|
||||
for (Pair<String, SpellOperator> p : new Pair[]{
|
||||
// == Getters ==
|
||||
|
||||
new Pair<>("qaq", OpGetCaster.INSTANCE),
|
||||
new Pair<>("ede", OpGetCaster.INSTANCE),
|
||||
new Pair<>("aa", OpEntityPos.INSTANCE),
|
||||
new Pair<>("dd", OpEntityPos.INSTANCE),
|
||||
new Pair<>("wa", OpEntityLook.INSTANCE),
|
||||
new Pair<>("wd", OpEntityLook.INSTANCE),
|
||||
|
||||
new Pair<>("wqaawdd", OpBlockRaycast.INSTANCE),
|
||||
new Pair<>("weddwaa", OpBlockAxisRaycast.INSTANCE),
|
||||
new Pair<>("weaqa", OpEntityRaycast.INSTANCE),
|
||||
|
||||
// == Modify Stack ==
|
||||
|
||||
new Pair<>("a", OpUndo.INSTANCE),
|
||||
new Pair<>("d", SpellWidget.NULL),
|
||||
new Pair<>("aadaa", OpDuplicate.INSTANCE),
|
||||
new Pair<>("aawdd", OpSwap.INSTANCE),
|
||||
|
||||
// == Math ==
|
||||
new Pair<>("waaw", OpAdd.INSTANCE),
|
||||
new Pair<>("wddw", OpSub.INSTANCE),
|
||||
new Pair<>("waqaw", OpMulDot.INSTANCE),
|
||||
new Pair<>("wdedw", OpDivCross.INSTANCE),
|
||||
new Pair<>("wqaqw", OpAbsLen.INSTANCE),
|
||||
new Pair<>("wedew", OpPowProj.INSTANCE),
|
||||
new Pair<>("eqqqqq", OpConstructVec.INSTANCE),
|
||||
new Pair<>("qeeeee", OpDeconstructVec.INSTANCE),
|
||||
|
||||
// == Spells ==
|
||||
|
||||
new Pair<>("de", OpPrint.INSTANCE),
|
||||
new Pair<>("aq", OpPrint.INSTANCE),
|
||||
new Pair<>("aawaawaa", OpExplode.INSTANCE),
|
||||
new Pair<>("weeewdq", OpAddMotion.INSTANCE),
|
||||
new Pair<>("qaqqqqq", OpPlaceBlock.INSTANCE),
|
||||
new Pair<>("eeeeede", OpBreakBlock.INSTANCE),
|
||||
new Pair<>("waadwawdaaweewq", OpLightning.INSTANCE),
|
||||
|
||||
// == Meta stuff ==
|
||||
new Pair<>("qqq", SpellWidget.OPEN_PAREN),
|
||||
new Pair<>("eee", SpellWidget.CLOSE_PAREN),
|
||||
new Pair<>("qqqaw", SpellWidget.ESCAPE),
|
||||
// http://www.toroidalsnark.net/mkss3-pix/CalderheadJMM2014.pdf
|
||||
// eval being a space filling curve feels apt doesn't it
|
||||
new Pair<>("deaqq", OpEval.INSTANCE),
|
||||
new Pair<>("aqqqqq", OpRead.INSTANCE),
|
||||
new Pair<>("deeeee", OpWrite.INSTANCE),
|
||||
|
||||
// == Consts ==
|
||||
new Pair<>("qqqqqqea", SpellOperator.makeConstantOp(SpellDatum.make(new Vec3(1.0, 0.0, 0.0)))),
|
||||
new Pair<>("qqqqqqew", SpellOperator.makeConstantOp(SpellDatum.make(new Vec3(1.0, 1.0, 0.0)))),
|
||||
new Pair<>("qqqqqqed", SpellOperator.makeConstantOp(SpellDatum.make(new Vec3(1.0, 0.0, 1.0)))),
|
||||
new Pair<>("eeeeeeqa", SpellOperator.makeConstantOp(SpellDatum.make(new Vec3(-1.0, 0.0, 0.0)))),
|
||||
new Pair<>("eeeeeeqw", SpellOperator.makeConstantOp(SpellDatum.make(new Vec3(1.0, -1.0, 0.0)))),
|
||||
new Pair<>("eeeeeeqd", SpellOperator.makeConstantOp(SpellDatum.make(new Vec3(1.0, 0.0, -1.0)))),
|
||||
|
||||
}) {
|
||||
PatternRegistry.addRegularPattern(p.getFirst(), p.getSecond());
|
||||
count++;
|
||||
}
|
||||
} catch (PatternRegistry.RegisterPatternException exn) {
|
||||
exn.printStackTrace();
|
||||
}
|
||||
|
||||
// Add zilde->number
|
||||
PatternRegistry.addSpecialHandler(pat -> {
|
||||
var sig = pat.anglesSignature();
|
||||
if (sig.startsWith("aqaa") || sig.startsWith("dedd")) {
|
||||
var negate = sig.startsWith("dedd");
|
||||
var accumulator = 0.0;
|
||||
for (char ch : sig.substring(4).toCharArray()) {
|
||||
if (ch == 'w') {
|
||||
accumulator += 1;
|
||||
} else if (ch == 'q') {
|
||||
accumulator += 5;
|
||||
} else if (ch == 'e') {
|
||||
accumulator += 10;
|
||||
} else if (ch == 'a') {
|
||||
accumulator *= 2;
|
||||
} else if (ch == 'd') {
|
||||
accumulator /= 2;
|
||||
}
|
||||
}
|
||||
if (negate) {
|
||||
accumulator = -accumulator;
|
||||
}
|
||||
return SpellOperator.makeConstantOp(SpellDatum.make(accumulator));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
HexMod.LOGGER.info("Registered {} patterns", count);
|
||||
}
|
||||
}
|
|
@ -169,11 +169,12 @@ class SpellDatum<T : Any> private constructor(val payload: T) {
|
|||
const val TAG_VEC3 = "vec3"
|
||||
const val TAG_LIST = "list"
|
||||
const val TAG_SPELL = "spell"
|
||||
const val TAG_SPELL_NAME = "impler"
|
||||
const val TAG_SPELL_ARGS = "args"
|
||||
const val TAG_WIDGET = "widget"
|
||||
const val TAG_PATTERN = "pattern"
|
||||
|
||||
const val TAG_SPELL_NAME = "impler"
|
||||
const val TAG_SPELL_ARGS = "args"
|
||||
|
||||
fun <T : Any> IsValidType(checkee: T): Boolean =
|
||||
if (checkee is List<*>) {
|
||||
// note it should be impossible to pass a spell datum that doesn't contain a valid type,
|
||||
|
|
|
@ -29,7 +29,14 @@ object OpBlockRaycast : ConstManaOperator {
|
|||
|
||||
return SpellOperator.spellListOf(
|
||||
if (blockHitResult.type == HitResult.Type.BLOCK) {
|
||||
blockHitResult.location
|
||||
// the position on the bhr is the position of the specific *hit point*, which is actually on the outside of the block
|
||||
// this is weird (for example, casting OpBreakBlock at this position will not break the block we're looking at)
|
||||
// so we return the block pos instead
|
||||
Vec3(
|
||||
blockHitResult.blockPos.x.toDouble(),
|
||||
blockHitResult.blockPos.y.toDouble(),
|
||||
blockHitResult.blockPos.z.toDouble()
|
||||
)
|
||||
} else {
|
||||
SpellWidget.NULL
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package at.petrak.hex.common.casting.operators.math
|
||||
|
||||
import at.petrak.hex.api.ConstManaOperator
|
||||
import at.petrak.hex.api.SpellOperator.Companion.getChecked
|
||||
import at.petrak.hex.api.SpellOperator.Companion.spellListOf
|
||||
import at.petrak.hex.common.casting.CastingContext
|
||||
import at.petrak.hex.common.casting.SpellDatum
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
object OpConstructVec : ConstManaOperator {
|
||||
override val argc = 3
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
val x = args.getChecked<Double>(0)
|
||||
val y = args.getChecked<Double>(1)
|
||||
val z = args.getChecked<Double>(2)
|
||||
return spellListOf(Vec3(x, y, z))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package at.petrak.hex.common.casting.operators.math
|
||||
|
||||
import at.petrak.hex.api.ConstManaOperator
|
||||
import at.petrak.hex.api.SpellOperator.Companion.getChecked
|
||||
import at.petrak.hex.api.SpellOperator.Companion.spellListOf
|
||||
import at.petrak.hex.common.casting.CastingContext
|
||||
import at.petrak.hex.common.casting.SpellDatum
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
object OpDeconstructVec : ConstManaOperator {
|
||||
override val argc = 1
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
val v = args.getChecked<Vec3>(0)
|
||||
return spellListOf(v.x, v.y, v.z)
|
||||
}
|
||||
}
|
|
@ -8,6 +8,9 @@ import at.petrak.hex.common.casting.RenderedSpell
|
|||
import at.petrak.hex.common.casting.RenderedSpellImpl
|
||||
import at.petrak.hex.common.casting.SpellDatum
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.particles.BlockParticleOption
|
||||
import net.minecraft.core.particles.ParticleTypes
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.item.BlockItem
|
||||
import net.minecraft.world.item.context.UseOnContext
|
||||
|
@ -63,6 +66,14 @@ object OpPlaceBlock : SimpleOperator, RenderedSpellImpl {
|
|||
ctx.caster.setItemInHand(ctx.wandHand, oldStack)
|
||||
if (res != InteractionResult.FAIL) {
|
||||
ctx.withdrawItem(placee, 1, true)
|
||||
|
||||
ctx.world.playSound(
|
||||
ctx.caster,
|
||||
vec.x, vec.y, vec.z, bstate.soundType.placeSound, SoundSource.BLOCKS, 1.0f,
|
||||
1.0f + (Math.random() * 0.5 - 0.25).toFloat()
|
||||
)
|
||||
val particle = BlockParticleOption(ParticleTypes.BLOCK, bstate)
|
||||
ctx.world.sendParticles(particle, vec.x, vec.y, vec.z, 4, 0.1, 0.2, 0.1, 0.1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
public class ItemFocus extends ItemDataHolder {
|
||||
public static final ResourceLocation PREDICATE = new ResourceLocation(HexMod.MOD_ID, "datatype");
|
||||
public static final String TAG_DATA = "data";
|
||||
public static final String TAG_SEALED = "sealed";
|
||||
|
||||
public ItemFocus(Properties pProperties) {
|
||||
super(pProperties);
|
||||
|
|
|
@ -20,47 +20,23 @@ public class ItemModels extends ItemModelProvider {
|
|||
simpleItem(HexItems.WAND.get());
|
||||
simpleItem(HexItems.SPELLBOOK.get());
|
||||
|
||||
simpleItem(modLoc("focus_empty"));
|
||||
simpleItem(modLoc("focus_entity"));
|
||||
simpleItem(modLoc("focus_double"));
|
||||
simpleItem(modLoc("focus_vec3"));
|
||||
simpleItem(modLoc("focus_spell"));
|
||||
simpleItem(modLoc("focus_widget"));
|
||||
simpleItem(modLoc("focus_list"));
|
||||
simpleItem(modLoc("focus_patterns"));
|
||||
getBuilder(HexItems.FOCUS.get().getRegistryName().getPath())
|
||||
.override()
|
||||
.predicate(ItemFocus.PREDICATE, -0.01f)
|
||||
.model(new ModelFile.UncheckedModelFile(modLoc("item/focus_empty")))
|
||||
.end()
|
||||
.override()
|
||||
.predicate(ItemFocus.PREDICATE, 1 - 0.01f)
|
||||
.model(new ModelFile.UncheckedModelFile(modLoc("item/focus_entity")))
|
||||
.end()
|
||||
.override()
|
||||
.predicate(ItemFocus.PREDICATE, 2 - 0.01f)
|
||||
.model(new ModelFile.UncheckedModelFile(modLoc("item/focus_double")))
|
||||
.end()
|
||||
.override()
|
||||
.predicate(ItemFocus.PREDICATE, 3 - 0.01f)
|
||||
.model(new ModelFile.UncheckedModelFile(modLoc("item/focus_vec3")))
|
||||
.end()
|
||||
.override()
|
||||
.predicate(ItemFocus.PREDICATE, 4 - 0.01f)
|
||||
.model(new ModelFile.UncheckedModelFile(modLoc("item/focus_spell")))
|
||||
.end()
|
||||
.override()
|
||||
.predicate(ItemFocus.PREDICATE, 5 - 0.01f)
|
||||
.model(new ModelFile.UncheckedModelFile(modLoc("item/focus_widget")))
|
||||
.end()
|
||||
.override()
|
||||
.predicate(ItemFocus.PREDICATE, 6 - 0.01f)
|
||||
.model(new ModelFile.UncheckedModelFile(modLoc("item/focus_list")))
|
||||
.end()
|
||||
.override()
|
||||
.predicate(ItemFocus.PREDICATE, 7 - 0.01f)
|
||||
.model(new ModelFile.UncheckedModelFile(modLoc("item/focus_patterns")))
|
||||
.end();
|
||||
String[] focusTypes = new String[]{
|
||||
"empty", "entity", "double", "vec3", "spell", "widget", "list", "pattern"
|
||||
};
|
||||
for (int i = 0, stringsLength = focusTypes.length; i < stringsLength; i++) {
|
||||
String type = focusTypes[i];
|
||||
simpleItem(modLoc("focus_" + type));
|
||||
getBuilder(HexItems.FOCUS.get().getRegistryName().getPath())
|
||||
.override()
|
||||
.predicate(ItemFocus.PREDICATE, -0.01f + i)
|
||||
.model(new ModelFile.UncheckedModelFile(modLoc("item/focus_" + type)))
|
||||
.end()
|
||||
.override()
|
||||
.predicate(ItemFocus.PREDICATE, -0.01f + 100 + i)
|
||||
.model(new ModelFile.UncheckedModelFile(modLoc("item/focus_" + type + "_sealed")))
|
||||
.end();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void simpleItem(Item item) {
|
||||
|
|
After Width: | Height: | Size: 425 B |
After Width: | Height: | Size: 423 B |
After Width: | Height: | Size: 421 B |
After Width: | Height: | Size: 428 B |
Before Width: | Height: | Size: 416 B After Width: | Height: | Size: 416 B |
After Width: | Height: | Size: 423 B |
After Width: | Height: | Size: 423 B |
BIN
src/main/resources/assets/hex/textures/item/focus_template.ase
Normal file
After Width: | Height: | Size: 428 B |
After Width: | Height: | Size: 421 B |