Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
6a645a6
Block - remove holder of Type as this may cause issues when a block c…
ShaneBeee Feb 2, 2026
b338614
ExprLocationOf - fix rotation being NaN
ShaneBeee Feb 2, 2026
5a742fa
SecSpawnNPC: - a lil bit of cleanup
ShaneBeee Feb 2, 2026
65d7413
Exprfluid - fix fluid level not clamping properly
ShaneBeee Feb 2, 2026
7175586
Block - remove old constructor
ShaneBeee Feb 2, 2026
7d4aad1
Block - set type on correct world thread.
ShaneBeee Feb 2, 2026
7d130ed
CondPlayerIsCrouching - fix pattern
ShaneBeee Feb 2, 2026
2a60ae5
ExprLocationOf - clone new locations
ShaneBeee Feb 2, 2026
a23bdbc
Block Iterator/Sphere expressions added
ShaneBeee Feb 2, 2026
26d5eb2
EffCancelEvent - remove debug message
ShaneBeee Feb 2, 2026
d8de552
JsonDocPrinter - fix some things
ShaneBeee Feb 2, 2026
4794b53
JsonDocPrinter - more changes with experimental
ShaneBeee Feb 2, 2026
9cd7003
MarkdownDocPrinter - add experimental message
ShaneBeee Feb 2, 2026
155bbdf
JsonDocPrinter - add serializable tag
ShaneBeee Feb 2, 2026
c67256c
build.gradle.kts - forgot to switch the parser to the dev branch
ShaneBeee Feb 2, 2026
1eaa216
EffSpawnEntity - add spawn entity effect
ShaneBeee Feb 2, 2026
d7a8044
Chunk stuff:
ShaneBeee Feb 3, 2026
0bb6008
EntityComponentUtils - add shortcut method to get component of an entity
ShaneBeee Feb 3, 2026
5cf7039
ExprEntityVelocity - add expression to get/modify entity velocity
ShaneBeee Feb 3, 2026
d2a36e2
BlockContext - add a block context
ShaneBeee Feb 3, 2026
29b0ef1
AssetStoreUtils - add new util
ShaneBeee Feb 3, 2026
8d03345
EvtPlayerPlaceBlock - add event
ShaneBeee Feb 3, 2026
5c04784
DefaultConverters - add converter for Player -> PlayerRef
ShaneBeee Feb 3, 2026
0cbc542
SecPlaySound - add sound section
ShaneBeee Feb 3, 2026
c067f67
EvtEntityPickupItem - add pickup event
ShaneBeee Feb 3, 2026
fc3c5e9
ContextValue overhaul
ShaneBeee Feb 3, 2026
2c4aeb5
EvtPlayerChat - update docs
ShaneBeee Feb 3, 2026
957b23b
JsonVariableStorage - fix legacy file loading
ShaneBeee Feb 3, 2026
5ce340e
build.gradle.kts - update parser
ShaneBeee Feb 3, 2026
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
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ repositories {
dependencies {
compileOnly("com.hypixel.hytale:Server:${hytaleVersion}")
compileOnly("org.jetbrains:annotations:26.0.2")
implementation("com.github.SkriptDev:skript-parser:1.0.2") {
implementation("com.github.SkriptDev:skript-parser:1.0.3") {
isTransitive = false
}
implementation("com.github.Zoltus:TinyMessage:2.0.1") {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.github.skriptdev.skript.api.hytale;

import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
import com.hypixel.hytale.server.core.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* Quick utility methods for working with AssetStore
*/
public class AssetStoreUtils {

/**
* Get a BlockType from ID
*
* @param blockId ID of the BlockType
* @return BlockType from ID if found, otherwise null
*/
public static @Nullable BlockType getBlockType(@NotNull String blockId) {
return BlockType.getAssetMap().getAsset(blockId);
}

/**
* Get a BlockType from ItemStack
*
* @param itemStack ItemStack to get BlockType from
* @return BlockType from ItemStack if found, otherwise null
*/
public static @Nullable BlockType getBlockType(@NotNull ItemStack itemStack) {
return getBlockType(itemStack.getItem());
}

/**
* Get a BlockType from Item
*
* @param item Item to get BlockType from
* @return BlockType from Item if found, otherwise null
*/
public static @Nullable BlockType getBlockType(@NotNull Item item) {
if (item.hasBlockType()) return getBlockType(item.getBlockId());
return null;
}

}
56 changes: 29 additions & 27 deletions src/main/java/com/github/skriptdev/skript/api/hytale/Block.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.skriptdev.skript.api.hytale;

import com.github.skriptdev.skript.api.utils.Utils;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.math.util.ChunkUtil;
Expand All @@ -13,51 +14,45 @@
import com.hypixel.hytale.server.core.universe.world.chunk.section.FluidSection;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import org.jetbrains.annotations.NotNull;

import java.util.Objects;
import org.jetbrains.annotations.Nullable;

/**
* Represents a block in a world.
* Hytale doesn't appear to have a representation of a block in a world.
* Hytale doesn't appear to have a representation of a block in the world.
* This class provides a wrapper around Hytale's block system, allowing for easy interaction with blocks in a world.
* This may be changed/removed in the future.
*/
@SuppressWarnings("unused")
public class Block {

private final @NotNull World world;
private @NotNull BlockType type;
private final @NotNull Vector3i pos;

public Block(@NotNull World world, @NotNull Vector3i pos) {
this.world = world;
this.pos = pos;
this.type = Objects.requireNonNull(world.getBlockType(pos));
}

public Block(@NotNull World world, @NotNull Vector3i pos, @NotNull BlockType type) {
this.world = world;
this.pos = pos;
this.type = type;
}

public Block(@NotNull Location location) {
World world = Universe.get().getWorld(location.getWorld());
if (world == null) {
throw new IllegalArgumentException("World '" + location.getWorld() + "' not found.");
}
BlockType blockType = world.getBlockType(location.getPosition().toVector3i());
assert blockType != null;
this(world, location.getPosition().toVector3i(), blockType);
this(world, location.getPosition().toVector3i());
}

public @NotNull BlockType getType() {
return this.type;
BlockType blockType = this.world.getBlockType(this.pos);
return blockType != null ? blockType : BlockType.EMPTY;
}

public void setType(@NotNull BlockType type, int settings) {
this.type = type;
this.world.setBlock(this.pos.getX(), this.pos.getY(), this.pos.getZ(), type.getId(), settings);
Runnable r = () -> Block.this.world.setBlock(Block.this.pos.getX(), Block.this.pos.getY(), Block.this.pos.getZ(), type.getId(), settings);
if (this.world.isInThread()) {
r.run();
} else {
this.world.execute(r);
}
}

public byte getFluidLevel() {
Expand Down Expand Up @@ -91,10 +86,10 @@ public void setFluidLevel(byte level) {
return null;
}


Fluid fluid = fluidSection.getFluid(this.pos.getX(), this.pos.getY(), this.pos.getZ());
if (fluid == null) return null;
fluidSection.setFluid(this.pos.getX(), this.pos.getY(), this.pos.getZ(), fluid, level);
byte fluidLevel = (byte) Math.clamp((int) level, 0, fluid.getMaxFluidLevel());
fluidSection.setFluid(this.pos.getX(), this.pos.getY(), this.pos.getZ(), fluid, fluidLevel);
}
return chunk;
});
Expand All @@ -108,7 +103,7 @@ public Fluid getFluid() {
return Fluid.getAssetMap().getAsset(fluidId);
}

public void setFluid(@NotNull Fluid fluid) {
public void setFluid(@NotNull Fluid fluid, @Nullable Integer level) {
long index = ChunkUtil.indexChunkFromBlock(this.pos.getX(), this.pos.getZ());
this.world.getChunkAsync(index).thenApply((chunk) -> {
Ref<ChunkStore> columnRef = chunk.getReference();
Expand All @@ -126,9 +121,16 @@ public void setFluid(@NotNull Fluid fluid) {
}


byte level = fluidSection.getFluidLevel(this.pos.getX(), this.pos.getY(), this.pos.getZ());
if (level <= 0) level = 8;
fluidSection.setFluid(this.pos.getX(), this.pos.getY(), this.pos.getZ(), fluid, level);
byte fluidLevel;
if (level != null) {
fluidLevel = level.byteValue();
} else {
fluidLevel = fluidSection.getFluidLevel(this.pos.getX(), this.pos.getY(), this.pos.getZ());
if (fluidLevel <= 0) fluidLevel = (byte) fluid.getMaxFluidLevel();
}
fluidLevel = (byte) Math.clamp((int) fluidLevel, 0, fluid.getMaxFluidLevel());
Utils.log("Set fluid level to %s", fluidLevel);
fluidSection.setFluid(this.pos.getX(), this.pos.getY(), this.pos.getZ(), fluid, fluidLevel);
}
return chunk;
});
Expand All @@ -152,15 +154,15 @@ public void breakBlock(int settings) {

public String toTypeString() {
return String.format("[%s] block at (%s,%s,%s) in '%s'",
this.type.getId(), this.pos.getX(), this.pos.getY(), this.pos.getZ(), this.world.getName());
this.getType().getId(), this.pos.getX(), this.pos.getY(), this.pos.getZ(), this.world.getName());
}

@Override
public String toString() {
return "Block{" +
"world=" + world.getName() +
", type=" + type +
", pos=" + pos +
"world=" + this.world.getName() +
", type=" + this.getType() +
", pos=" + this.pos +
'}';
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.github.skriptdev.skript.api.hytale;

import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.component.Component;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
Expand All @@ -27,6 +29,24 @@
@SuppressWarnings("UnusedReturnValue")
public class EntityComponentUtils {

/**
* Get a component from an Entity
*
* @param entity Entity to get component from
* @param type Component type to get
* @param <ECS_TYPE> EntityStore Type
* @param <T> Type of returned component
* @return Component from entity if available otherwise null
*/
@SuppressWarnings("unchecked")
public static <ECS_TYPE, T extends Component<ECS_TYPE>> @Nullable T getComponent(Entity entity, ComponentType<ECS_TYPE, T> type) {
Ref<ECS_TYPE> reference = (Ref<ECS_TYPE>) entity.getReference();
if (reference == null) return null;

Store<ECS_TYPE> store = reference.getStore();
return store.getComponent(reference, type);
}

/**
* Get the EntityStatMap component of an entity.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,10 @@ private void printStructures(BsonDocument mainDocs, SkriptRegistration registrat
Documentation documentation = event.getDocumentation();
if (documentation.isNoDoc()) return;

BsonDocument structureDoc = new BsonDocument();

if (Structure.class.isAssignableFrom(event.getSyntaxClass())) {
BsonDocument structureDoc = new BsonDocument();
printDocumentation("structure", structureDoc, event);
structuresArray.add(structureDoc);
}
});

Expand Down Expand Up @@ -307,18 +307,23 @@ private void printEffects(BsonDocument mainDocs, SkriptRegistration registration
private void printTypes(BsonDocument mainDocs, SkriptRegistration registration) {
BsonArray typesArray = mainDocs.getArray("types", new BsonArray());

String addonName = registration.getRegisterer().getAddonName().toLowerCase(Locale.ROOT).replace(" ", "_");

registration.getTypes().forEach(type -> {
Documentation documentation = type.getDocumentation();
if (documentation.isNoDoc()) return;

BsonDocument syntaxDoc = new BsonDocument();

// NAME and ID
String baseName = type.getBaseName();
String docName = documentation.getName();
syntaxDoc.put("name", new BsonString(docName != null ? docName : baseName));
syntaxDoc.put("id", getId("type", baseName));

// EXPERIMENTAL
if (documentation.isExperimental()) {
syntaxDoc.put("experimental", new BsonString(documentation.getExperimentalMessage()));
}

// DESCRIPTION
BsonArray descriptionArray = new BsonArray();
for (String s : documentation.getDescription()) {
Expand Down Expand Up @@ -349,6 +354,9 @@ private void printTypes(BsonDocument mainDocs, SkriptRegistration registration)
syntaxDoc.put("examples", exampleArray);
}

// SERIALIZABLE
syntaxDoc.put("serializable", new BsonBoolean(type.getSerializer().isPresent()));

// SINCE
String since = documentation.getSince();
if (since != null) {
Expand Down Expand Up @@ -385,7 +393,9 @@ private void printDocumentation(String type, BsonDocument syntaxDoc, SyntaxInfo<
syntaxDoc.put("id", getId(type, syntaxInfo));

// EXPERIMENTAL
// TODO
if (documentation.isExperimental()) {
syntaxDoc.put("experimental", new BsonString(documentation.getExperimentalMessage()));
}

// DESCRIPTION
BsonArray descriptionArray = new BsonArray();
Expand All @@ -402,7 +412,7 @@ private void printDocumentation(String type, BsonDocument syntaxDoc, SyntaxInfo<

// PATTERNS
List<PatternElement> patterns = syntaxInfo.getPatterns();
if (patterns.isEmpty()) {
if (!patterns.isEmpty()) {
BsonArray patternArray = new BsonArray();
patterns.forEach(pattern -> patternArray.add(new BsonString(pattern.toString())));
syntaxDoc.put("patterns", patternArray);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ private static void printDocumentation(String type, PrintWriter writer, Document
if (documentation.isExperimental()) {
writer.println("> [!WARNING]");
writer.println("> **This is an experimental feature!** ");
writer.println("> Things may not work as expected and may change without notice. ");
writer.println("> " + documentation.getExperimentalMessage());
}
String[] description = documentation.getDescription();
if (description.length > 0) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.github.skriptdev.skript.api.skript.event;

import com.github.skriptdev.skript.api.hytale.Block;
import io.github.syst3ms.skriptparser.lang.TriggerContext;

/**
* Represents a {@link TriggerContext} which includes a {@link Block}
*/
public interface BlockContext extends TriggerContext {

Block getBlock();

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
*/
public interface PlayerContext extends TriggerContext {

Player[] getPlayer();
Player getPlayer();

}
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,17 @@ private void loadVariablesFromFile() {
if (this.bsonDocument.containsKey("variables")) {
variablesDocument = this.bsonDocument.getDocument("variables");
} else {
// Legacy file format (TODO remove before first release)
this.logger.warn("Your variables file is outdated. HySkript will create a backup then convert for you.");
Files.move(this.file.toPath(), this.file.toPath().resolveSibling(this.file.getName() + ".bak"));
variablesDocument = this.bsonDocument.clone();
this.bsonDocument = new BsonDocument();
if (!this.bsonDocument.isEmpty() && !this.bsonDocument.containsKey("data")) {
// Legacy file format (TODO remove before first release)
this.logger.warn("Your variables file is outdated. HySkript will create a backup then convert for you.");
Files.move(this.file.toPath(), this.file.toPath().resolveSibling(this.file.getName() + ".bak"));
variablesDocument = this.bsonDocument.clone();
this.bsonDocument.clear();
this.bsonDocument.put("variables", variablesDocument);
} else {
variablesDocument = this.bsonDocument.getDocument("variables", new BsonDocument());
}
//this.bsonDocument = new BsonDocument();
}
JsonElement jsonElement = BsonUtil.translateBsonToJson(variablesDocument);
if (jsonElement instanceof JsonObject jsonObject) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
public class EffectCommands {

public static void register(Skript skript, String token, boolean allowOps, String permission) {
skript.getSkriptRegistration().newContextValue(PlayerEffectContext.class, Player.class, true, "me", PlayerEffectContext::getPlayer)
skript.getSkriptRegistration().newSingleContextValue(PlayerEffectContext.class, Player.class, "me", PlayerEffectContext::getPlayer)
.setUsage(Usage.EXPRESSION_OR_ALONE)
.register();

Expand Down Expand Up @@ -99,8 +99,8 @@ public static void register(Skript skript, String token, boolean allowOps, Strin

private record PlayerEffectContext(Player player) implements PlayerContext {

public Player[] getPlayer() {
return new Player[]{this.player};
public Player getPlayer() {
return this.player;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class CondPlayerIsCrouching extends ConditionalExpression {

public static void register(SkriptRegistration reg) {
reg.newExpression(CondPlayerIsCrouching.class, Boolean.class, true,
"%players% (is|are)[neg:( not|n't)] crouching",
"%players% (is|are) crouching",
"%players% (isn't|is not|aren't|are not) crouching")
.name("Player is Crouching")
.description("Checks if the player is crouching.")
Expand Down
Loading
Loading