Skip to content

Commit 63a4860

Browse files
authored
Merge pull request #16 from SkriptDev/dev/feature
Dev/feature - Future Feature Release
2 parents c15230a + e0d8d3b commit 63a4860

170 files changed

Lines changed: 6927 additions & 358 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/contributing.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ This way the team can discuss with you whether or not we want this in HySkript.
2424
- Use descriptive commit messages
2525
- Use descriptive PR titles
2626
- Ensure you follow the code style of this project
27-
- Do make sure you add tests and run the test to make sure it works.
28-
- See the [Testing Guide](https://github.com/SkriptDev/HySkript/tree/master/src/test/README.md) for more information.
27+
- Do make sure you add tests and run the test to make sure it works.
28+
- See the [Testing Guide](https://github.com/SkriptDev/HySkript/tree/master/src/test/README.md) for more information.
2929

3030
### Don't:
3131
- Don't commit directly to `master`

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,6 @@ bin/
4343
### Mac OS ###
4444
.DS_Store
4545
**/.DS_Store
46+
47+
### Run Folder ###
48+
run/

build.gradle.kts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,17 @@ java.sourceCompatibility = JavaVersion.VERSION_25
99

1010
group = "com.github.SkriptDev"
1111
val projectVersion = "1.0.0"
12-
val hytaleVersion = "2026.02.06-aa1b071c2"
12+
val hytaleVersion = "2026.02.19-1a311a592"
1313
// You can find Hytale versions on their maven repo:
1414
// https://maven.hytale.com/release/com/hypixel/hytale/Server/maven-metadata.xml
1515
// https://maven.hytale.com/pre-release/com/hypixel/hytale/Server/maven-metadata.xml
1616
// (Pre-releases shouldn't be used for production)
1717

18+
// Location of the Hytale Server Assets
19+
// This is used in testing
20+
// Change this to wherever you have it on your computer
21+
val assetLocation = "/Users/ShaneBee/Desktop/Server/Hytale/Assets/Assets.zip"
22+
1823
repositories {
1924
mavenCentral()
2025
mavenLocal()
@@ -26,14 +31,20 @@ repositories {
2631
dependencies {
2732
compileOnly("com.hypixel.hytale:Server:${hytaleVersion}")
2833
compileOnly("org.jetbrains:annotations:26.0.2")
29-
implementation("com.github.SkriptDev:skript-parser:1.0.8") {
34+
implementation("com.github.SkriptDev:skript-parser:1.0.9") {
3035
isTransitive = false
3136
}
3237
implementation("com.github.Zoltus:TinyMessage:2.0.1") {
3338
isTransitive = false
3439
}
3540
}
3641

42+
// This is used to enable Gson in the test environment via HytaleServer
43+
val testRunnerClasspath by configurations.creating {
44+
extendsFrom(configurations.compileOnly.get())
45+
isCanBeResolved = true
46+
}
47+
3748
tasks {
3849
register("server", Copy::class) {
3950
dependsOn("jar")
@@ -42,6 +53,14 @@ tasks {
4253
destinationDir = file("/Users/ShaneBee/Desktop/Server/Hytale/Creative/mods/")
4354
}
4455
}
56+
register<JavaExec>("testRunner") {
57+
dependsOn("jar")
58+
group = "application"
59+
mainClass.set("com.github.skriptdev.skript.api.skript.testing.TestRunnerMain")
60+
args(hytaleVersion, projectVersion, assetLocation)
61+
62+
classpath = sourceSets["main"].runtimeClasspath + testRunnerClasspath
63+
}
4564
processResources {
4665
filesNotMatching("assets/**") {
4766
expand("pluginVersion" to projectVersion, "hytaleVersion" to hytaleVersion)
@@ -71,7 +90,8 @@ tasks {
7190
options.encoding = Charsets.UTF_8.name()
7291
exclude(
7392
"com/github/skriptdev/skript/plugin/elements",
74-
"com/github/skriptdev/skript/plugin/command"
93+
"com/github/skriptdev/skript/plugin/command",
94+
"com/github/skriptdev/skript/api/skript/testing/elements"
7595
)
7696
(options as StandardJavadocDocletOptions).links(
7797
"https://javadoc.io/doc/org.jetbrains/annotations/latest/",

src/main/java/com/github/skriptdev/skript/api/hytale/Block.java

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,34 @@
11
package com.github.skriptdev.skript.api.hytale;
22

3-
import com.github.skriptdev.skript.api.utils.Utils;
3+
import com.github.skriptdev.skript.api.hytale.utils.StoreUtils;
4+
import com.hypixel.hytale.component.CommandBuffer;
45
import com.hypixel.hytale.component.Ref;
56
import com.hypixel.hytale.component.Store;
67
import com.hypixel.hytale.math.util.ChunkUtil;
78
import com.hypixel.hytale.math.vector.Location;
89
import com.hypixel.hytale.math.vector.Vector3i;
910
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
1011
import com.hypixel.hytale.server.core.asset.type.fluid.Fluid;
12+
import com.hypixel.hytale.server.core.entity.LivingEntity;
13+
import com.hypixel.hytale.server.core.inventory.ItemStack;
14+
import com.hypixel.hytale.server.core.modules.blockhealth.BlockHealth;
15+
import com.hypixel.hytale.server.core.modules.blockhealth.BlockHealthChunk;
16+
import com.hypixel.hytale.server.core.modules.blockhealth.BlockHealthModule;
17+
import com.hypixel.hytale.server.core.modules.interaction.BlockHarvestUtils;
18+
import com.hypixel.hytale.server.core.universe.PlayerRef;
1119
import com.hypixel.hytale.server.core.universe.Universe;
1220
import com.hypixel.hytale.server.core.universe.world.World;
1321
import com.hypixel.hytale.server.core.universe.world.chunk.ChunkColumn;
1422
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
1523
import com.hypixel.hytale.server.core.universe.world.chunk.section.FluidSection;
1624
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
25+
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
1726
import org.jetbrains.annotations.NotNull;
1827
import org.jetbrains.annotations.Nullable;
1928

29+
import java.util.Map;
30+
import java.util.function.Predicate;
31+
2032
/**
2133
* Represents a block in a world.
2234
* Hytale doesn't appear to have a representation of a block in the world.
@@ -137,7 +149,6 @@ public void setFluid(@NotNull Fluid fluid, @Nullable Integer level) {
137149
if (fluidLevel <= 0) fluidLevel = (byte) fluid.getMaxFluidLevel();
138150
}
139151
fluidLevel = (byte) Math.clamp((int) fluidLevel, 0, fluid.getMaxFluidLevel());
140-
Utils.log("Set fluid level to %s", fluidLevel);
141152
fluidSection.setFluid(this.pos.getX(), this.pos.getY(), this.pos.getZ(), fluid, fluidLevel);
142153
}
143154
return chunk;
@@ -148,6 +159,75 @@ public void breakBlock(int settings) {
148159
this.world.breakBlock(this.pos.getX(), this.pos.getY(), this.pos.getZ(), settings);
149160
}
150161

162+
public void damage(@Nullable LivingEntity performer, @Nullable ItemStack itemStack, float damage) {
163+
WorldChunk chunk = this.world.getChunk(ChunkUtil.indexChunkFromBlock(this.pos.getX(), this.pos.getZ()));
164+
if (chunk == null) return;
165+
166+
Ref<ChunkStore> ref = chunk.getReference();
167+
Store<ChunkStore> chunkStore = this.world.getChunkStore().getStore();
168+
CommandBuffer<EntityStore> commandBuffer = StoreUtils.getCommandBuffer(this.world.getEntityStore().getStore());
169+
170+
if (performer == null) {
171+
BlockHarvestUtils.performBlockDamage(
172+
this.pos,
173+
null,
174+
null,
175+
damage,
176+
0,
177+
ref,
178+
commandBuffer,
179+
chunkStore);
180+
} else {
181+
BlockHarvestUtils.performBlockDamage(
182+
performer,
183+
performer.getReference(),
184+
this.pos,
185+
itemStack,
186+
null,
187+
null, // TODO figure out how to get this
188+
false,
189+
damage,
190+
0,
191+
ref,
192+
commandBuffer,
193+
chunkStore);
194+
}
195+
}
196+
197+
public float getBlockHealth() {
198+
WorldChunk chunk = this.world.getChunk(ChunkUtil.indexChunkFromBlock(this.pos.getX(), this.pos.getZ()));
199+
if (chunk == null) return 0;
200+
201+
Ref<ChunkStore> ref = chunk.getReference();
202+
Store<ChunkStore> chunkStore = this.world.getChunkStore().getStore();
203+
204+
BlockHealthChunk component = chunkStore.getComponent(ref, BlockHealthModule.get().getBlockHealthChunkComponentType());
205+
if (component == null) return 0;
206+
207+
return component.getBlockHealth(this.pos);
208+
}
209+
210+
public void setBlockHealth(float health) {
211+
WorldChunk chunk = this.world.getChunk(ChunkUtil.indexChunkFromBlock(this.pos.getX(), this.pos.getZ()));
212+
if (chunk == null) return;
213+
214+
Ref<ChunkStore> ref = chunk.getReference();
215+
Store<ChunkStore> chunkStore = this.world.getChunkStore().getStore();
216+
BlockHealthChunk component = chunkStore.getComponent(ref, BlockHealthModule.get().getBlockHealthChunkComponentType());
217+
if (component == null) return;
218+
219+
Map<Vector3i, BlockHealth> blockHealthMap = component.getBlockHealthMap();
220+
BlockHealth blockHealth = blockHealthMap.getOrDefault(this.pos, new BlockHealth());
221+
blockHealth.setHealth(health);
222+
blockHealthMap.put(this.pos, blockHealth);
223+
224+
if (!blockHealth.isDestroyed()) {
225+
Predicate<PlayerRef> filter = (player) -> true;
226+
world.getNotificationHandler().updateBlockDamage(this.pos.getX(), this.pos.getY(),
227+
this.pos.getZ(), blockHealth.getHealth(), health, filter);
228+
}
229+
}
230+
151231
public @NotNull World getWorld() {
152232
return this.world;
153233
}

src/main/java/com/github/skriptdev/skript/api/hytale/Direction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public String getVariableName() {
5353

5454
private static Location create(Location location, Number offset, int x, int y, int z) {
5555
double value = offset.doubleValue();
56-
Vector3d add = location.getPosition().add(x * value, y * value, z * value);
56+
Vector3d add = location.getPosition().clone().add(x * value, y * value, z * value);
5757
return new Location(location.getWorld(), add);
5858
}
5959

src/main/java/com/github/skriptdev/skript/api/hytale/utils/AssetStoreUtils.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.github.skriptdev.skript.api.hytale.utils;
22

33
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
4+
import com.hypixel.hytale.server.core.asset.type.environment.config.Environment;
45
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
56
import com.hypixel.hytale.server.core.inventory.ItemStack;
67
import org.jetbrains.annotations.NotNull;
@@ -42,4 +43,24 @@ public class AssetStoreUtils {
4243
return null;
4344
}
4445

46+
/**
47+
* Get the AssetStore index of an Environment
48+
*
49+
* @param environment Environment to get index from
50+
* @return Index from Environment
51+
*/
52+
public static int getEnvironmentIndex(Environment environment) {
53+
return Environment.getAssetMap().getIndex(environment.getId());
54+
}
55+
56+
/**
57+
* Get an Environment from its AssetStore index.
58+
*
59+
* @param index Index to grab Environment from
60+
* @return Environment from index, or null if not found
61+
*/
62+
public static Environment getEnvironment(int index) {
63+
return Environment.getAssetMap().getAsset(index);
64+
}
65+
4566
}

src/main/java/com/github/skriptdev/skript/api/hytale/utils/EntityUtils.java

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.github.skriptdev.skript.api.hytale.utils;
22

3+
import com.github.skriptdev.skript.api.skript.registration.NPCRegistry;
4+
import com.github.skriptdev.skript.api.utils.Utils;
35
import com.hypixel.hytale.component.AddReason;
46
import com.hypixel.hytale.component.Component;
57
import com.hypixel.hytale.component.ComponentType;
@@ -20,6 +22,9 @@
2022
import com.hypixel.hytale.server.core.modules.entitystats.EntityStatsModule;
2123
import com.hypixel.hytale.server.core.universe.world.World;
2224
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
25+
import com.hypixel.hytale.server.npc.entities.NPCEntity;
26+
import com.hypixel.hytale.server.npc.role.Role;
27+
import com.hypixel.hytale.server.npc.systems.RoleChangeSystem;
2328
import io.github.syst3ms.skriptparser.util.Pair;
2429
import org.jetbrains.annotations.NotNull;
2530
import org.jetbrains.annotations.Nullable;
@@ -99,7 +104,7 @@ public static void setNameplateName(Entity entity, @Nullable String name) {
99104
}
100105

101106
/**
102-
* Get a component from an Entity
107+
* Get a component from an Entity.
103108
*
104109
* @param entity Entity to get component from
105110
* @param type Component type to get
@@ -116,6 +121,61 @@ public static void setNameplateName(Entity entity, @Nullable String name) {
116121
return store.getComponent(reference, type);
117122
}
118123

124+
/**
125+
* Get a component from an Entity or create it if not present.
126+
*
127+
* @param entity Entity to get component from
128+
* @param type Component type to get
129+
* @param <ECS> EntityStore Type
130+
* @param <T> Type of returned component
131+
* @return Component from entity if available otherwise will create/add a new one
132+
*/
133+
@SuppressWarnings("unchecked")
134+
public static <ECS, T extends Component<ECS>> @NotNull T ensureAndGetComponent(Entity entity, ComponentType<ECS, T> type) {
135+
Ref<ECS> reference = (Ref<ECS>) entity.getReference();
136+
if (reference == null) {
137+
throw new IllegalStateException("Entity '" + entity + "' does not have a reference");
138+
}
139+
140+
Store<ECS> store = reference.getStore();
141+
return store.ensureAndGetComponent(reference, type);
142+
}
143+
144+
/**
145+
* Put a component on an Entity.
146+
*
147+
* @param entity Entity to add component to
148+
* @param type Type of component to add
149+
* @param component Component to add
150+
* @param <ECS> EntityStore Type
151+
* @param <T> Type of component
152+
*/
153+
@SuppressWarnings("unchecked")
154+
public static <ECS, T extends Component<ECS>> void putComponent(Entity entity, ComponentType<ECS, T> type, Component<ECS> component) {
155+
Ref<ECS> reference = (Ref<ECS>) entity.getReference();
156+
if (reference == null) {
157+
throw new IllegalStateException("Entity '" + entity + "' does not have a reference");
158+
}
159+
reference.getStore().addComponent(reference, type, (T) component);
160+
}
161+
162+
/**
163+
* Try to remove a component from an Entity.
164+
*
165+
* @param entity Entity to remove component from
166+
* @param type Type of component to remove
167+
* @param <ECS> Store type
168+
* @param <T> Component type
169+
*/
170+
@SuppressWarnings("unchecked")
171+
public static <ECS, T extends Component<ECS>> void tryRemoveComponent(Entity entity, ComponentType<ECS, T> type) {
172+
Ref<ECS> reference = (Ref<ECS>) entity.getReference();
173+
if (reference == null) {
174+
throw new IllegalStateException("Entity '" + entity + "' does not have a reference");
175+
}
176+
reference.getStore().tryRemoveComponent(reference, type);
177+
}
178+
119179
/**
120180
* Get the EntityStatMap component of an entity.
121181
*
@@ -173,4 +233,54 @@ public static void setNameplateName(Entity entity, @Nullable String name) {
173233
return new Pair<>(com.hypixel.hytale.server.core.entity.EntityUtils.getEntity(itemEntityHolder), itemComponent);
174234
}
175235

236+
public static boolean isTameable(NPCEntity npcEntity) {
237+
Role role = npcEntity.getRole();
238+
if (role == null) return false;
239+
240+
String roleName = role.getRoleName();
241+
if (roleName.contains("Tamed_")) {
242+
return true;
243+
}
244+
// I know this is hacky, but Hytale doesn't have any API for taming
245+
// Maybe we'll get lucky and Hytale will create API for this
246+
NPCRegistry.NPCRole parse = NPCRegistry.parse("tamed_" + roleName);
247+
return parse != null;
248+
}
249+
250+
public static boolean isTamed(NPCEntity npcEntity) {
251+
Role role = npcEntity.getRole();
252+
if (role == null) return false;
253+
254+
// I know this is hacky, but Hytale doesn't have any API for taming
255+
// Maybe we'll get lucky and Hytale will create API for this
256+
String roleName = role.getRoleName();
257+
return roleName.startsWith("Tamed_");
258+
}
259+
260+
public static void setTamed(NPCEntity npcEntity, boolean tamed) {
261+
if (!isTameable(npcEntity)) {
262+
return;
263+
}
264+
if ((tamed && isTamed(npcEntity)) || (!tamed && !isTamed(npcEntity))) {
265+
return;
266+
}
267+
Ref<EntityStore> reference = npcEntity.getReference();
268+
if (reference == null) return;
269+
270+
Store<EntityStore> store = reference.getStore();
271+
272+
// I know this is hacky, but Hytale doesn't have any API for taming
273+
// Maybe we'll get lucky and Hytale will create API for this
274+
Role currentRole = npcEntity.getRole();
275+
if (currentRole == null || currentRole.isRoleChangeRequested()) return;
276+
277+
String roleName = currentRole.getRoleName();
278+
roleName = tamed ? "Tamed_" + roleName : roleName.replace("Tamed_", "");
279+
280+
NPCRegistry.NPCRole parse = NPCRegistry.parse(roleName);
281+
282+
Utils.log("Changing role to %s", parse.name());
283+
RoleChangeSystem.requestRoleChange(reference, currentRole, parse.index(), true, store);
284+
}
285+
176286
}

0 commit comments

Comments
 (0)