Skip to content

Commit 46d6d3d

Browse files
feat: lucky block gamemode for skywars
1 parent beef742 commit 46d6d3d

File tree

77 files changed

+5777
-633
lines changed

Some content is hidden

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

77 files changed

+5777
-633
lines changed

service.orchestrator/src/main/java/net/swofty/service/orchestrator/OrchestratorCache.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
public class OrchestratorCache {
1313
private static final Map<String, GameServerState> serversByShortName = new ConcurrentHashMap<>();
1414
private static final Map<UUID, GameWithServer> gamesByGameId = new ConcurrentHashMap<>();
15-
private static final long HEARTBEAT_TTL_MS = 20000; // 20s
15+
private static final long HEARTBEAT_TTL_MS = 10000; // 10s
1616

1717
public static void handleHeartbeat(UUID uuid,
1818
String shortName,
@@ -170,7 +170,7 @@ public static GameWithServer findPlayerGame(UUID playerUuid) {
170170
return null;
171171
}
172172

173-
private static void cleanup() {
173+
public static void cleanup() {
174174
long now = Instant.now().toEpochMilli();
175175

176176
// Remove stale servers
@@ -214,6 +214,7 @@ public static Collection<GameWithServer> getAllActiveGames() {
214214
}
215215

216216
public static GameServerState getServerByUuid(UUID serverUuid) {
217+
cleanup();
217218
return serversByShortName.values().stream()
218219
.filter(server -> server.uuid().equals(serverUuid))
219220
.findFirst()

service.orchestrator/src/main/java/net/swofty/service/orchestrator/OrchestratorService.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,21 @@
55
import net.swofty.service.generic.redis.ServiceEndpoint;
66

77
import java.util.List;
8+
import java.util.concurrent.Executors;
9+
import java.util.concurrent.ScheduledExecutorService;
10+
import java.util.concurrent.TimeUnit;
811

912
public class OrchestratorService implements SkyBlockService {
1013

1114
public static void main(String[] args) {
1215
SkyBlockService.init(new OrchestratorService());
16+
17+
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(r -> {
18+
Thread t = new Thread(r, "orchestrator-cleanup");
19+
t.setDaemon(true);
20+
return t;
21+
});
22+
scheduler.scheduleAtFixedRate(OrchestratorCache::cleanup, 5, 5, TimeUnit.SECONDS);
1323
}
1424

1525
@Override

type.skywarsgame/src/main/java/net/swofty/type/skywarsgame/events/ActionGameCustomItems.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import net.minestom.server.event.player.PlayerUseItemEvent;
55
import net.minestom.server.event.player.PlayerUseItemOnBlockEvent;
66
import net.swofty.type.skywarsgame.TypeSkywarsGameLoader;
7+
import net.swofty.type.skywarsgame.luckyblock.items.LuckyBlockItemHandler;
8+
import net.swofty.type.skywarsgame.user.SkywarsPlayer;
79
import net.swofty.type.generic.event.EventNodes;
810
import net.swofty.type.generic.event.HypixelEvent;
911
import net.swofty.type.generic.event.HypixelEventClass;
@@ -13,11 +15,19 @@ public class ActionGameCustomItems implements HypixelEventClass {
1315
@HypixelEvent(node = EventNodes.ALL, requireDataLoaded = false)
1416
public void run(PlayerUseItemOnBlockEvent event) {
1517
TypeSkywarsGameLoader.getItemHandler().onItemUseOnBlock(event);
18+
19+
if (event.getPlayer() instanceof SkywarsPlayer player) {
20+
LuckyBlockItemHandler.processItemUse(player, event.getItemStack());
21+
}
1622
}
1723

1824
@HypixelEvent(node = EventNodes.ALL, requireDataLoaded = false)
1925
public void run(PlayerUseItemEvent event) {
2026
TypeSkywarsGameLoader.getItemHandler().onItemUse(event);
27+
28+
if (event.getPlayer() instanceof SkywarsPlayer player) {
29+
LuckyBlockItemHandler.processItemUse(player, event.getItemStack());
30+
}
2131
}
2232

2333
@HypixelEvent(node = EventNodes.ALL, requireDataLoaded = false)
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package net.swofty.type.skywarsgame.events;
2+
3+
import net.minestom.server.coordinate.Pos;
4+
import net.minestom.server.coordinate.Vec;
5+
import net.minestom.server.entity.Entity;
6+
import net.minestom.server.entity.LivingEntity;
7+
import net.minestom.server.event.entity.EntityShootEvent;
8+
import net.minestom.server.event.entity.projectile.ProjectileCollideWithBlockEvent;
9+
import net.minestom.server.event.entity.projectile.ProjectileCollideWithEntityEvent;
10+
import net.minestom.server.instance.Instance;
11+
import net.minestom.server.item.ItemStack;
12+
import net.minestom.server.potion.Potion;
13+
import net.minestom.server.potion.PotionEffect;
14+
import net.swofty.type.generic.event.EventNodes;
15+
import net.swofty.type.generic.event.HypixelEvent;
16+
import net.swofty.type.generic.event.HypixelEventClass;
17+
import net.swofty.type.skywarsgame.luckyblock.items.LuckyBlockItemRegistry;
18+
import net.swofty.type.skywarsgame.luckyblock.items.weapons.ExplosiveBow;
19+
import net.swofty.type.skywarsgame.luckyblock.items.weapons.Invisibow;
20+
import net.swofty.type.skywarsgame.user.SkywarsPlayer;
21+
22+
import java.util.Map;
23+
import java.util.UUID;
24+
import java.util.concurrent.ConcurrentHashMap;
25+
26+
public class ActionLuckyBlockArrows implements HypixelEventClass {
27+
28+
private static final Map<UUID, String> arrowBowMap = new ConcurrentHashMap<>();
29+
30+
@HypixelEvent(node = EventNodes.ALL, requireDataLoaded = false)
31+
public void onArrowShoot(EntityShootEvent event) {
32+
if (!(event.getEntity() instanceof SkywarsPlayer player)) return;
33+
34+
ItemStack bow = player.getItemInMainHand();
35+
String bowId = bow.getTag(LuckyBlockItemRegistry.LUCKY_BLOCK_ITEM_TAG);
36+
37+
if (bowId != null) {
38+
arrowBowMap.put(event.getProjectile().getUuid(), bowId);
39+
}
40+
}
41+
42+
@HypixelEvent(node = EventNodes.ALL, requireDataLoaded = false)
43+
public void onArrowHitBlock(ProjectileCollideWithBlockEvent event) {
44+
Entity projectile = event.getEntity();
45+
String bowId = arrowBowMap.remove(projectile.getUuid());
46+
47+
if (bowId == null) return;
48+
49+
handleArrowEffect(bowId, projectile, event.getCollisionPosition(), null);
50+
}
51+
52+
@HypixelEvent(node = EventNodes.ALL, requireDataLoaded = false)
53+
public void onArrowHitEntity(ProjectileCollideWithEntityEvent event) {
54+
Entity projectile = event.getEntity();
55+
String bowId = arrowBowMap.get(projectile.getUuid());
56+
57+
if (bowId == null) return;
58+
59+
Entity target = event.getTarget();
60+
handleArrowEffect(bowId, projectile, event.getCollisionPosition(), target);
61+
62+
arrowBowMap.remove(projectile.getUuid());
63+
}
64+
65+
private void handleArrowEffect(String bowId, Entity projectile, Pos hitPos, Entity target) {
66+
Instance instance = projectile.getInstance();
67+
if (instance == null) return;
68+
69+
switch (bowId) {
70+
case ExplosiveBow.ID -> {
71+
double radius = ExplosiveBow.EXPLOSION_RADIUS;
72+
for (Entity entity : instance.getNearbyEntities(hitPos, radius)) {
73+
if (entity instanceof LivingEntity living && entity != projectile) {
74+
Vec direction = entity.getPosition().sub(hitPos).asVec().normalize();
75+
double distance = entity.getPosition().distance(hitPos);
76+
double force = (1.0 - distance / radius) * 20;
77+
living.setVelocity(direction.mul(force).withY(force * 0.5));
78+
}
79+
}
80+
}
81+
82+
case Invisibow.ID -> {
83+
if (target instanceof LivingEntity living) {
84+
living.addEffect(new Potion(
85+
PotionEffect.INVISIBILITY,
86+
(byte) 0,
87+
Invisibow.INVISIBILITY_DURATION_TICKS
88+
));
89+
}
90+
}
91+
}
92+
}
93+
}

type.skywarsgame/src/main/java/net/swofty/type/skywarsgame/events/ActionLuckyBlockBreak.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,22 @@ public void onBlockBreak(PlayerBlockBreakEvent event) {
2121
SkywarsGame game = TypeSkywarsGameLoader.getPlayerGame(player);
2222
if (game == null) return;
2323

24-
if (game.getGameType() != SkywarsGameType.SOLO_LUCKY_BLOCK) return;
25-
2624
if (game.getGameStatus() != SkywarsGameStatus.IN_PROGRESS) return;
2725

26+
Pos blockPos = new Pos(event.getBlockPosition());
27+
28+
if (game.getChestManager().isChestPosition(blockPos)) {
29+
event.setCancelled(true);
30+
return;
31+
}
32+
33+
if (game.getGameType() != SkywarsGameType.SOLO_LUCKY_BLOCK) return;
34+
2835
Block block = event.getBlock();
2936
LuckyBlock luckyBlockManager = game.getLuckyBlockManager();
3037

3138
if (luckyBlockManager != null && luckyBlockManager.isLuckyBlockMaterial(block)) {
32-
Pos blockPos = new Pos(event.getBlockPosition());
33-
3439
event.setCancelled(true);
35-
3640
luckyBlockManager.breakLuckyBlock(player, blockPos);
3741
}
3842
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package net.swofty.type.skywarsgame.events;
2+
3+
import net.minestom.server.coordinate.Pos;
4+
import net.minestom.server.event.player.PlayerBlockPlaceEvent;
5+
import net.minestom.server.item.ItemStack;
6+
import net.minestom.server.item.Material;
7+
import net.swofty.commons.skywars.SkywarsGameType;
8+
import net.swofty.type.generic.event.EventNodes;
9+
import net.swofty.type.generic.event.HypixelEvent;
10+
import net.swofty.type.generic.event.HypixelEventClass;
11+
import net.swofty.type.skywarsgame.TypeSkywarsGameLoader;
12+
import net.swofty.type.skywarsgame.game.SkywarsGame;
13+
import net.swofty.type.skywarsgame.game.SkywarsGameStatus;
14+
import net.swofty.type.skywarsgame.luckyblock.LuckyBlock;
15+
import net.swofty.type.skywarsgame.luckyblock.LuckyBlockType;
16+
import net.swofty.type.skywarsgame.user.SkywarsPlayer;
17+
18+
public class ActionLuckyBlockPlace implements HypixelEventClass {
19+
@HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false)
20+
public void onBlockPlace(PlayerBlockPlaceEvent event) {
21+
if (!(event.getPlayer() instanceof SkywarsPlayer player)) return;
22+
23+
ItemStack itemInHand = player.getItemInMainHand();
24+
if (itemInHand.material() != Material.PLAYER_HEAD) return;
25+
26+
String luckyBlockTypeName = itemInHand.getTag(LuckyBlockType.LUCKY_BLOCK_TYPE_TAG);
27+
if (luckyBlockTypeName == null) return;
28+
29+
LuckyBlockType type = LuckyBlockType.fromName(luckyBlockTypeName);
30+
if (type == null) return;
31+
32+
event.setCancelled(true);
33+
34+
SkywarsGame game = TypeSkywarsGameLoader.getPlayerGame(player);
35+
if (game == null) return;
36+
37+
if (game.getGameType() != SkywarsGameType.SOLO_LUCKY_BLOCK) return;
38+
39+
if (game.getGameStatus() != SkywarsGameStatus.IN_PROGRESS) return;
40+
41+
LuckyBlock luckyBlockManager = game.getLuckyBlockManager();
42+
if (luckyBlockManager == null) return;
43+
44+
Pos blockPos = new Pos(event.getBlockPosition());
45+
luckyBlockManager.placeLuckyBlock(blockPos, type);
46+
47+
ItemStack newStack = itemInHand.withAmount(itemInHand.amount() - 1);
48+
player.setItemInMainHand(newStack);
49+
}
50+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package net.swofty.type.skywarsgame.events;
2+
3+
import net.minestom.server.entity.Entity;
4+
import net.minestom.server.entity.EntityCreature;
5+
import net.minestom.server.entity.EntityType;
6+
import net.minestom.server.entity.LivingEntity;
7+
import net.minestom.server.entity.attribute.Attribute;
8+
import net.minestom.server.entity.damage.Damage;
9+
import net.minestom.server.entity.damage.DamageType;
10+
import net.minestom.server.event.entity.EntityAttackEvent;
11+
import net.swofty.type.generic.event.EventNodes;
12+
import net.swofty.type.generic.event.HypixelEvent;
13+
import net.swofty.type.generic.event.HypixelEventClass;
14+
import net.swofty.type.skywarsgame.TypeSkywarsGameLoader;
15+
import net.swofty.type.skywarsgame.game.SkywarsGame;
16+
import net.swofty.type.skywarsgame.game.SkywarsGameStatus;
17+
import net.swofty.type.skywarsgame.user.SkywarsPlayer;
18+
19+
public class ActionMobAttack implements HypixelEventClass {
20+
21+
@HypixelEvent(node = EventNodes.ALL, requireDataLoaded = false)
22+
public void onMobAttack(EntityAttackEvent event) {
23+
Entity attacker = event.getEntity();
24+
Entity target = event.getTarget();
25+
26+
if (attacker instanceof SkywarsPlayer) return;
27+
if (!(attacker instanceof EntityCreature mob)) return;
28+
if (!(target instanceof SkywarsPlayer victim)) return;
29+
30+
SkywarsGame game = TypeSkywarsGameLoader.getPlayerGame(victim);
31+
if (game == null || game.getGameStatus() != SkywarsGameStatus.IN_PROGRESS) return;
32+
if (victim.isEliminated()) return;
33+
34+
float damage = getMobDamage(mob);
35+
36+
victim.damage(new Damage(DamageType.MOB_ATTACK, mob, mob, null, damage));
37+
}
38+
39+
private float getMobDamage(EntityCreature mob) {
40+
EntityType type = mob.getEntityType();
41+
42+
if (type == EntityType.ZOMBIE) return 3.0f;
43+
if (type == EntityType.SKELETON) return 2.0f;
44+
if (type == EntityType.SPIDER) return 2.0f;
45+
if (type == EntityType.CAVE_SPIDER) return 2.0f;
46+
if (type == EntityType.CREEPER) return 0.0f;
47+
if (type == EntityType.SLIME) return 2.0f;
48+
if (type == EntityType.SILVERFISH) return 1.0f;
49+
if (type == EntityType.ENDERMAN) return 7.0f;
50+
if (type == EntityType.WOLF) return 4.0f;
51+
if (type == EntityType.BLAZE) return 6.0f;
52+
if (type == EntityType.WITHER_SKELETON) return 8.0f;
53+
if (type == EntityType.WITCH) return 0.0f;
54+
if (type == EntityType.VINDICATOR) return 13.0f;
55+
if (type == EntityType.PIGLIN) return 5.0f;
56+
if (type == EntityType.PIGLIN_BRUTE) return 13.0f;
57+
if (type == EntityType.ZOMBIFIED_PIGLIN) return 5.0f;
58+
if (type == EntityType.IRON_GOLEM) return 21.0f;
59+
if (type == EntityType.RAVAGER) return 12.0f;
60+
return 2.0f;
61+
}
62+
}

type.skywarsgame/src/main/java/net/swofty/type/skywarsgame/events/ActionPlayerCombat.java

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import net.swofty.type.skywarsgame.TypeSkywarsGameLoader;
1010
import net.swofty.type.skywarsgame.game.SkywarsGame;
1111
import net.swofty.type.skywarsgame.game.SkywarsGameStatus;
12-
import net.swofty.type.skywarsgame.luckyblock.oprule.OPRuleManager;
1312
import net.swofty.type.skywarsgame.user.SkywarsPlayer;
1413

1514
public class ActionPlayerCombat implements HypixelEventClass {
@@ -28,22 +27,7 @@ public void onDamage(EntityDamageEvent event) {
2827
return;
2928
}
3029

31-
OPRuleManager opRuleManager = game.getOpRuleManager();
32-
DamageType damageType = event.getDamage().getType().asValue();
33-
34-
if (opRuleManager != null && opRuleManager.shouldPreventFallDamage()) {
35-
if (damageType == DamageType.FALL.asValue()) {
36-
event.setCancelled(true);
37-
return;
38-
}
39-
}
40-
4130
float damageAmount = event.getDamage().getAmount();
42-
if (opRuleManager != null && opRuleManager.isInstantKillActive()) {
43-
if (event.getDamage().getAttacker() instanceof SkywarsPlayer) {
44-
damageAmount = 1000f;
45-
}
46-
}
4731

4832
if (event.getDamage().getAttacker() instanceof SkywarsPlayer attacker) {
4933
if (!attacker.equals(victim)) {

0 commit comments

Comments
 (0)