Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/main/java/com/riprod/hexcode/Hexcode.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
import com.riprod.hexcode.state.StateRouter;
import com.riprod.patchly.PatchManager;

import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;

import com.hypixel.hytale.assetstore.AssetRegistry;
Expand Down Expand Up @@ -124,6 +125,7 @@
import com.riprod.hexcode.api.event.CraftingEvent;
import com.riprod.hexcode.api.event.GlyphFizzleEvent;
import com.riprod.hexcode.api.event.GlyphDrawnEvent;
import com.riprod.hexcode.builtin.eventListeners.GlyphDrawNotificationListener;
import com.riprod.hexcode.builtin.eventListeners.GlyphMemoryListener;
import com.riprod.hexcode.core.common.memories.GlyphMemory;
import com.riprod.hexcode.core.common.memories.GlyphMemoryProvider;
Expand Down Expand Up @@ -153,7 +155,7 @@ public Hexcode(JavaPluginInit init) {
}

@Override
public java.util.concurrent.CompletableFuture<Void> preLoad() {
public CompletableFuture<Void> preLoad() {
return super.preLoad();
}

Expand Down Expand Up @@ -481,6 +483,7 @@ private void registerEvents() {
this.getEventRegistry().registerGlobal(HexStateChangeEvent.class, new HexStateDiagnosticListener());
this.getEventRegistry().registerGlobal(CraftingEvent.class, new CraftingNotificationListener());
this.getEventRegistry().registerGlobal(GlyphDrawnEvent.class, new GlyphMemoryListener());
this.getEventRegistry().registerGlobal(GlyphDrawnEvent.class, new GlyphDrawNotificationListener());
this.getEventRegistry().register(EventPriority.LAST, LoadAssetEvent.class, e -> {
GlyphIconStore.generateMissing(this.getManifest());
patchManager.rebuildAndApply("boot:LoadAssetEvent");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.riprod.hexcode.builtin.eventListeners;

import java.util.function.Consumer;

import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.core.util.NotificationUtil;
import com.riprod.hexcode.api.event.GlyphDrawnEvent;
import com.riprod.hexcode.core.common.glyphs.component.Glyph;
import com.riprod.hexcode.core.common.glyphs.registry.GlyphAsset;

public class GlyphDrawNotificationListener implements Consumer<GlyphDrawnEvent> {

private static final String ICON_DIR = "UI/Custom/Pages/Memories/glyphs/";

@Override
public void accept(GlyphDrawnEvent event) {
Ref<EntityStore> playerRef = event.getPlayerRef();
if (playerRef == null || !playerRef.isValid()) return;

Glyph glyph = event.getGlyph();
if (glyph == null || glyph.getGlyphId() == null) return;

Store<EntityStore> store = playerRef.getStore();
PlayerRef pr = store.getComponent(playerRef, PlayerRef.getComponentType());
if (pr == null) return;

GlyphAsset asset = event.getMatchedGlyphAsset();
Message name = asset != null && asset.getTitle() != null
? Message.translation(asset.getTitle())
: Message.raw(glyph.getGlyphId());

String icon = ICON_DIR + glyph.getGlyphId() + ".png";
NotificationUtil.sendNotification(pr.getPacketHandler(), name, icon);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,12 @@ private boolean tryConsumePerHopVolatility(ArcState state, HexContext hexContext
VolatilityTracker tracker = hexContext.getVolatilityTracker();
if (tracker == null) return false;

int usage = tracker.getGlyphUsage(arcGlyph.getId());
float baseCost = VolatilityTracker.computeGlyphCost(arcGlyph, usage);
float baseCost = VolatilityTracker.computeGlyphCost(arcGlyph);
float rangeScale = state.getMaxJumpDistance() / DEFAULT_JUMP_RANGE;
float finalCost = baseCost * rangeScale;

if (hexContext.getHexRoot() == null) return true;
boolean ok = tracker.consumeVolatility(finalCost);
if (ok) {
tracker.incrementGlyphUsage(arcGlyph.getId());
}
return ok;
return tracker.consumeVolatility(finalCost);
}

private boolean hopToNext(ArcState state, HexStatus<ArcState> status, ConstructTickContext ctx) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ public boolean consumeVolatility(Glyph glyph, HexContext hexContext) {
GlyphAsset asset = GlyphAsset.getAssetMap().getAsset(glyph.getGlyphId());
float areaScale = computeAreaScale(GlyphHandler.sphereVolume(radius), asset);

int repeatCount = tracker.getGlyphUsage(glyph.getId());
float cost = VolatilityTracker.computeGlyphCost(glyph, repeatCount)
float cost = VolatilityTracker.computeGlyphCost(glyph)
* VOLATILITY_COST_MULTIPLIER * areaScale;
if (cost <= 0) return true;
return tracker.consumeVolatility(cost);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ public boolean consumeVolatility(Glyph glyph, HexContext hexContext) {
GlyphAsset asset = GlyphAsset.getAssetMap().getAsset(glyph.getGlyphId());
float areaScale = computeAreaScale(magnitude, asset);

int repeatCount = tracker.getGlyphUsage(glyph.getId());
float cost = VolatilityTracker.computeGlyphCost(glyph, repeatCount) * areaScale;
float cost = VolatilityTracker.computeGlyphCost(glyph) * areaScale;
return tracker.consumeVolatility(cost);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,25 +50,20 @@ private void fireReleaseAndKillHeld(HexStatus<ConcentrationState> status,
if (trigger == null || heldCtx == null)
return;

// q-cancel zeroes the held tracker; in that case skip the release branch
// entirely
VolatilityTracker heldTracker = heldCtx.getVolatilityTracker();
if (heldTracker != null && heldTracker.getRemainingBudget() <= 0f)
return;

// strip the held-time bonus so the release branch inherits the unboosted budget
ConcentrationState state = status.getState();
float bonus = state != null ? state.getVolatilityBonus() : 0f;
if (heldTracker != null && bonus > 0f) {
float adjusted = Math.max(0f, heldTracker.getRemainingBudget() - bonus);
heldTracker.setBudget(adjusted);
}

// deep copy gives the release branch its own VolatilityTracker so zeroing the
// held one (to kill any sustaining children of NEXT) won't take it down too
HexContext releaseCtx = HexContext.cloneState(heldCtx);
releaseCtx.updateRuntimeAccessors(buffer);

// register the release tracker so subsequent q presses can still cancel it
HexcasterIdleComponent idle = buffer.getComponent(
casterRef, HexcasterIdleComponent.getComponentType());
if (idle != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,7 @@ public boolean consumeVolatility(Glyph glyph, HexContext hexContext) {
GlyphAsset asset = GlyphAsset.getAssetMap().getAsset(glyph.getGlyphId());
float areaScale = computeAreaScale(volume, asset);

int repeatCount = tracker.getGlyphUsage(glyph.getId());
float cost = VolatilityTracker.computeGlyphCost(glyph, repeatCount) * areaScale;
float cost = VolatilityTracker.computeGlyphCost(glyph) * areaScale;
return tracker.consumeVolatility(cost);
}

Expand Down Expand Up @@ -158,8 +157,6 @@ public void execute(Glyph glyph, HexContext hexContext) {

ConjureZoneComponent zoneComp = new ConjureZoneComponent(halfExtents, interval, durationSeconds);

Vector3f debugColor = ConjureStyle.resolveColor(hexContext);

HitboxCollisionConfig collisionConfig = HitboxCollisionConfig.getAssetMap()
.getAsset(HARD_COLLISION_ID);

Expand All @@ -169,11 +166,15 @@ public void execute(Glyph glyph, HexContext hexContext) {
holder.ensureComponent(PropComponent.getComponentType());
holder.ensureComponent(ProjectileModule.get().getProjectileComponentType());
holder.ensureComponent(EffectControllerComponent.getComponentType());
DebugComponent debugComp = new DebugComponent(DebugShape.Cube, debugColor, size, 0.1f);
debugComp.setOpacity(hexContext.getColors().getPrimaryAlpha() * 0.5f);
debugComp.setIntervalMultiplier(0.01f);
debugComp.setFlags(DebugUtils.FLAG_NO_WIREFRAME);
holder.addComponent(DebugComponent.getComponentType(), debugComp);
// alpha of 0 means an invisible zone: skip the debug shape but keep the functional zone
if (hexContext.getColors().getPrimaryAlpha() != 0f) {
Vector3f debugColor = ConjureStyle.resolveColor(hexContext);
DebugComponent debugComp = new DebugComponent(DebugShape.Cube, debugColor, size, 0.1f);
debugComp.setOpacity(hexContext.getColors().getPrimaryAlpha() * 0.5f);
debugComp.setIntervalMultiplier(0.01f);
debugComp.setFlags(DebugUtils.FLAG_NO_WIREFRAME);
holder.addComponent(DebugComponent.getComponentType(), debugComp);
}
holder.addComponent(BoundingBox.getComponentType(),
new BoundingBox(Box.horizontallyCentered(halfExtents.x * 2, halfExtents.y * 2,
halfExtents.z * 2)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public void onFirstTick(HexStatus<NoState> status, ConstructTickContext ctx) {
UUID entityId = ctx.getBuffer().getComponent(ctx.getEntityRef(), UUIDComponent.getComponentType())
.getUuid();

hexContext.setVariable(hexContext.getDefaultSlot(), new EntityVar(entityId, ctx.getEntityRef()));
hexContext.setDefaultVariable(new EntityVar(entityId, ctx.getEntityRef()));
HexExecuter.continueExecution(Arrays.asList(links), hexContext);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ private void dump(Glyph glyph, HexContext hexContext) {
}
}

HexVar defaultVar = hexContext.getDefaultVariable();
sb.append("Default: ").append(defaultVar != null ? defaultVar.describe() : "[none]").append("\n");

Map<String, HexVar> vars = hexContext.getVariables();
if (vars.isEmpty()) {
sb.append("Vars: [empty]");
Expand Down
111 changes: 64 additions & 47 deletions src/main/java/com/riprod/hexcode/builtin/glyphs/delay/DelayGlyph.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@
import com.riprod.hexcode.core.common.execution.component.HexContext;
import com.riprod.hexcode.core.common.glyphs.component.Glyph;
import com.riprod.hexcode.core.common.glyphs.component.GlyphHandler;
import com.riprod.hexcode.core.common.glyphs.variables.BlockVar;
import com.riprod.hexcode.core.common.glyphs.variables.EntityVar;
import com.riprod.hexcode.core.common.glyphs.variables.HexVar;
import com.riprod.hexcode.api.event.GlyphFizzleEvent;
import com.riprod.hexcode.core.common.glyphs.variables.PositionVar;
import com.riprod.hexcode.core.common.glyphs.variables.RotationVar;
import com.riprod.hexcode.api.event.GlyphFizzleEvent;
import com.riprod.hexcode.utils.HexVarUtil;

public class DelayGlyph implements GlyphHandler {
Expand All @@ -49,30 +50,73 @@ public void execute(Glyph glyph, HexContext hexContext) {
float seconds = HexVarUtil.numberOrDefault(
glyph.readSlot(DelayGlyphSlots.DURATION, hexContext), 1.0).floatValue();

if (seconds <= 0f) {
HexExecuter.continueFromSlot(glyph, Glyph.NEXT_SLOT, hexContext);
return;
CommandBuffer<EntityStore> accessor = hexContext.getAccessor();

HexVar incomingDefault = hexContext.getDefaultVariable();
HexVar sourceVar = glyph.readSlot(DelayGlyphSlots.SOURCE, hexContext);
if (sourceVar == null) {
sourceVar = incomingDefault;
}

if (seconds < 0.5f) { // early gate
boolean indefinite = seconds < 0f;
EntityVar entityVar = sourceVar instanceof EntityVar ev ? ev : null;

// check if the delay is shorter than the TPS of the world
World world = hexContext.getAccessor().getExternalData().getWorld();
if (1.0f / world.getTps() > seconds) {
if (!indefinite && entityVar == null) {
if (seconds <= 0f) {
HexExecuter.continueFromSlot(glyph, Glyph.NEXT_SLOT, hexContext);
return;
}
if (seconds < 0.5f) {
World world = accessor.getExternalData().getWorld();
if (1.0f / world.getTps() > seconds) {
HexExecuter.continueFromSlot(glyph, Glyph.NEXT_SLOT, hexContext);
return;
}
}
}

List<String> nextLinks = glyph.getNextLinks();
if (nextLinks.isEmpty()) {

DelayState state = new DelayState(seconds, new ArrayList<>(nextLinks),
hexContext.getColors(), entityVar == null);

if (entityVar != null) {
Ref<EntityStore> targetRef = entityVar.getRef(accessor);
if (targetRef == null || !targetRef.isValid()) {
HexExecuter.fail(glyph, hexContext,
GlyphFizzleEvent.Reason.HANDLER_FAILED,
"delay target entity gone");
return;
}
TransformComponent targetTransform = accessor.getComponent(
targetRef, TransformComponent.getComponentType());
if (targetTransform != null) {
DelayStyle.renderAt(targetTransform.getPosition(), hexContext);
}
HexConstructSpawner.applyWithState(accessor, targetRef, hexContext, glyph, ID, state);
return;
}

CommandBuffer<EntityStore> accessor = hexContext.getAccessor();

HexVar defaultVar = hexContext.getVariable(hexContext.getDefaultSlot());
Vector3d spawnPos = HexVarUtil.position(defaultVar, accessor);
Vector3d spawnPos;
Rotation3f rot;
switch (sourceVar) {
case RotationVar r -> {
rot = HexVarUtil.rotation(r, accessor);
spawnPos = HexVarUtil.position(incomingDefault, accessor);
}
case PositionVar p -> {
spawnPos = HexVarUtil.position(p, accessor);
rot = HexVarUtil.rotation(incomingDefault, accessor);
}
case BlockVar b -> {
spawnPos = HexVarUtil.position(b, accessor);
rot = HexVarUtil.rotation(b, accessor);
}
case null, default -> {
spawnPos = HexVarUtil.position(incomingDefault, accessor);
rot = HexVarUtil.rotation(incomingDefault, accessor);
}
}
if (spawnPos == null) {
Ref<EntityStore> casterRef = hexContext.getCasterRef();
if (casterRef != null && casterRef.isValid()) {
Expand All @@ -83,51 +127,24 @@ public void execute(Glyph glyph, HexContext hexContext) {
spawnPos = new Vector3d();
}
}
EntityVar entityVar = HexVarUtil.resolveEntityVar(defaultVar, hexContext);

DelayStyle.render(hexContext);

DelayState state = new DelayState(seconds, new ArrayList<>(nextLinks), hexContext.getColors(),
seconds >= 1f || entityVar == null);
DelayStyle.renderAt(spawnPos, hexContext);

if (seconds < 1f && entityVar != null) {
Ref<EntityStore> targetRef = entityVar.getRef(accessor);
if (targetRef == null || !targetRef.isValid()) {
HexExecuter.fail(glyph, hexContext,
GlyphFizzleEvent.Reason.HANDLER_FAILED,
"delay target entity gone");
return;
}
HexConstructSpawner.applyWithState(accessor, targetRef, hexContext, glyph, ID, state);
return;
}
Holder<EntityStore> holder = HexConstructSpawner.createWithState(
accessor, hexContext, glyph, DelayGlyph.ID, spawnPos, state);

if (rot != null) {
holder.putComponent(TransformComponent.getComponentType(),
new TransformComponent(spawnPos, rot));
}

ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset(MODEL_ID);
if (modelAsset != null) {
Model model = new Model(modelAsset.getId(), 1.0f, (Map<String, String>) null,
modelAsset.getAttachments(null),
modelAsset.getBoundingBox(), modelAsset.getModel(), modelAsset.getTexture(),
modelAsset.getGradientSet(), modelAsset.getGradientId(), modelAsset.getEyeHeight(),
modelAsset.getCrouchOffset(), modelAsset.getSittingOffset(),
modelAsset.getSleepingOffset(),
modelAsset.getAnimationSetMap(), modelAsset.getCamera(),
modelAsset.getLight(), modelAsset.getParticles(), modelAsset.getTrails(),
modelAsset.getPhysicsValues(),
modelAsset.getDetailBoxes(), modelAsset.getPhobia(),
modelAsset.getPhobiaModelAssetId()
);
Model model = Model.createScaledModel(modelAsset, 1.0f);

holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model));
holder.addComponent(PersistentModel.getComponentType(),
new PersistentModel(model.toReference()));

Rotation3f rotVar = HexVarUtil.rotation(defaultVar, accessor);
if (rotVar != null) {
holder.putComponent(TransformComponent.getComponentType(),
new TransformComponent(spawnPos, rotVar));
}
} else {
LOGGER.atWarning().log("delay: model asset '%s' not found", MODEL_ID);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ private DelayGlyphSlots() {
}

public static final String DURATION = "duration";
public static final String SOURCE = "Source";
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ public float getRemainingSeconds() {
}

public void tick(float dt) {
remainingSeconds -= dt;
if (remainingSeconds > 0f) {
remainingSeconds = Math.max(0f, remainingSeconds - dt);
}
}

public boolean isExpired() {
return remainingSeconds <= 0f;
return remainingSeconds == 0f;
}

public List<String> getNextGlyphIds() {
Expand Down
Loading
Loading