Skip to content

Commit c56091d

Browse files
committed
A lot of things :)
1 parent 0d45579 commit c56091d

17 files changed

+267
-81
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Loop-de-loop
22

3-
A small game where you try to fly through all the hoops. First to do it wins!
3+
Soar amongst the clouds in this game of graceful flight. The first fly through all the hoops wins!
44

55
![A screenshot of the game](screenshot.png)

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ dependencies {
2626

2727
implementation 'com.google.code.findbugs:jsr305:3.0.1'
2828

29-
modImplementation 'xyz.nucleoid:plasmid:0.1.0+build.57'
29+
modImplementation 'xyz.nucleoid:plasmid:0.1.0+build.68'
3030

3131
modRuntime("com.github.SuperCoder7979:databreaker:0.2.6") {
3232
exclude module: "fabric-loader"

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ minecraft_version=1.16.2
55
yarn_mappings=1.16.2+build.6
66
loader_version=0.9.1+build.205
77
# Mod Properties
8-
mod_version=1.0.4
8+
mod_version=1.1.0
99
maven_group=io.github.restioson
1010
archives_base_name=loopdeloop
1111
# Dependencies

src/main/java/io/github/restioson/loopdeloop/LoopDeLoop.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
import io.github.restioson.loopdeloop.game.LoopDeLoopConfig;
44
import io.github.restioson.loopdeloop.game.LoopDeLoopWaiting;
55
import net.fabricmc.api.ModInitializer;
6-
import xyz.nucleoid.plasmid.game.GameType;
76
import net.minecraft.util.Identifier;
87
import org.apache.logging.log4j.LogManager;
98
import org.apache.logging.log4j.Logger;
9+
import xyz.nucleoid.plasmid.game.GameType;
1010

1111
public final class LoopDeLoop implements ModInitializer {
1212
public static final String ID = "loopdeloop";

src/main/java/io/github/restioson/loopdeloop/game/LoopDeLoopActive.java

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,23 @@
2323
import net.minecraft.sound.SoundEvents;
2424
import net.minecraft.text.LiteralText;
2525
import net.minecraft.text.Text;
26+
import net.minecraft.util.ActionResult;
2627
import net.minecraft.util.Formatting;
28+
import net.minecraft.util.Pair;
2729
import net.minecraft.util.math.BlockPos;
2830
import net.minecraft.util.math.MathHelper;
2931
import net.minecraft.util.math.Vec3d;
3032
import net.minecraft.world.GameMode;
3133
import xyz.nucleoid.plasmid.game.GameWorld;
32-
import xyz.nucleoid.plasmid.game.event.GameCloseListener;
33-
import xyz.nucleoid.plasmid.game.event.GameOpenListener;
34-
import xyz.nucleoid.plasmid.game.event.GameTickListener;
35-
import xyz.nucleoid.plasmid.game.event.OfferPlayerListener;
36-
import xyz.nucleoid.plasmid.game.event.PlayerAddListener;
37-
import xyz.nucleoid.plasmid.game.event.PlayerDamageListener;
38-
import xyz.nucleoid.plasmid.game.event.PlayerDeathListener;
39-
import xyz.nucleoid.plasmid.game.event.PlayerRemoveListener;
34+
import xyz.nucleoid.plasmid.game.event.*;
4035
import xyz.nucleoid.plasmid.game.player.JoinResult;
4136
import xyz.nucleoid.plasmid.game.rule.GameRule;
4237
import xyz.nucleoid.plasmid.game.rule.RuleResult;
4338
import xyz.nucleoid.plasmid.util.ItemStackBuilder;
4439

4540
import javax.annotation.Nullable;
46-
import java.util.ArrayList;
47-
import java.util.Iterator;
48-
import java.util.List;
49-
import java.util.Map;
50-
import java.util.Set;
41+
import java.util.*;
42+
5143

5244
public final class LoopDeLoopActive {
5345
private final GameWorld gameWorld;
@@ -56,10 +48,12 @@ public final class LoopDeLoopActive {
5648
private final List<LoopDeLoopWinner> finished;
5749
private final LoopDeLoopSpawnLogic spawnLogic;
5850
private final LoopDeLoopTimerBar timerBar = new LoopDeLoopTimerBar();
51+
private LoopDeLoopScoreboard scoreboard;
5952
// Only stores flying players, i.e non-completed players
6053
private final Object2ObjectMap<ServerPlayerEntity, LoopDeLoopPlayer> player_states;
6154
@Nullable
6255
private ServerPlayerEntity lastCompleter;
56+
private final List<Pair<ServerPlayerEntity, LoopDeLoopPlayer>> topPlayers;
6357
@Nullable
6458
Team team;
6559
private long closeTime = -1;
@@ -73,6 +67,7 @@ private LoopDeLoopActive(GameWorld gameWorld, LoopDeLoopMap map, LoopDeLoopConfi
7367
this.finished = new ArrayList<>();
7468
this.spawnLogic = new LoopDeLoopSpawnLogic(gameWorld, map);
7569
this.player_states = new Object2ObjectOpenHashMap<>();
70+
this.topPlayers = new ArrayList<>();
7671

7772
for (ServerPlayerEntity player : participants) {
7873
this.player_states.put(player, new LoopDeLoopPlayer());
@@ -125,11 +120,17 @@ private void onOpen() {
125120
long time = world.getTime();
126121
this.startTime = time - (time % 20) + (4 * 20) + 19;
127122
this.finishTime = this.startTime + (this.config.timeLimit * 20);
123+
this.scoreboard = new LoopDeLoopScoreboard(
124+
this.gameWorld.getWorld().getScoreboard(),
125+
this.config.loops
126+
);
127+
this.scoreboard.render(this.topPlayers);
128128
}
129129

130130
private void onClose() {
131131
this.gameWorld.getWorld().getScoreboard().removeTeam(this.team);
132132
this.timerBar.close();
133+
this.scoreboard.close();
133134
}
134135

135136
private void addPlayer(ServerPlayerEntity player) {
@@ -247,47 +248,65 @@ private void tickPlayers(long time) {
247248

248249
LoopDeLoopHoop hoop = this.map.hoops.get(nextHoop);
249250

250-
int lastHoopZ;
251-
int lastHoopX;
251+
double lastHoopZ;
252+
double lastHoopX;
253+
int lastHoopRadius;
252254
if (state.lastHoop == -1) {
253255
lastHoopZ = -5;
254256
lastHoopX = 0;
257+
lastHoopRadius = 10;
255258
} else {
256-
BlockPos last = this.map.hoops.get(state.lastHoop).centre;
257-
lastHoopZ = last.getZ();
258-
lastHoopX = last.getX();
259+
LoopDeLoopHoop last = this.map.hoops.get(state.lastHoop);
260+
lastHoopZ = Vec3d.ofCenter(last.centre).getZ();
261+
lastHoopX = Vec3d.ofCenter(last.centre).getX();
262+
lastHoopRadius = last.radius;
259263
}
260264

261265
BlockPos centre = hoop.centre;
262266

263-
double yMax = ((double) this.config.maxYVariation / 2) + 30;
267+
double yMax = ((double) this.config.yVarMax / 2) + 30;
264268
boolean outOfBounds = Math.floor(player.getZ()) > centre.getZ() ||
265269
player.getZ() < lastHoopZ - 10 ||
266-
player.getY() < 75 - yMax ||
267-
player.getY() > 75 + yMax ||
270+
player.getY() < 128 - yMax ||
271+
player.getY() > 128 + yMax ||
268272
player.getY() < 0 ||
269-
player.getX() > Math.max(centre.getX(), lastHoopX) + 30 ||
270-
player.getX() < Math.min(centre.getX(), lastHoopX) - 30;
273+
player.getX() > Math.max(centre.getX() + hoop.radius, lastHoopX + lastHoopRadius) + 30 ||
274+
player.getX() < Math.min(centre.getX() + hoop.radius, lastHoopX + lastHoopRadius) - 30;
271275

272276
if (hoop.intersectsSegment(state.lastPos, player.getPos())) {
273277
player.playSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.PLAYERS, 1.0F, 1.0F);
274278
giveRocket(player, 1);
275279
state.lastHoop += 1;
280+
state.previousFails = 0;
281+
state.lastFailOrSuccess = time;
282+
283+
if (this.topPlayers.stream().noneMatch(i -> i.getLeft().getUuid() == player.getUuid())) {
284+
this.topPlayers.add(new Pair<>(player, state));
285+
}
286+
287+
this.topPlayers.sort(Comparator.comparing(i -> i.getRight().lastHoop));
288+
289+
if (this.topPlayers.size() > 5) {
290+
this.topPlayers.remove(5);
291+
}
292+
293+
this.scoreboard.render(this.topPlayers);
276294
} else if (outOfBounds) {
277-
this.failHoop(player, state, time);
295+
this.failHoop(player, state, time);
278296
}
279297

280298
state.lastPos = player.getPos();
281299
}
282300
}
283301

284302
private void failHoop(ServerPlayerEntity player, LoopDeLoopPlayer state, long time) {
285-
if (time - state.lastFailTp < 20) {
303+
if (time - state.lastFailOrSuccess < 10) {
286304
return;
287305
}
288306

289-
state.lastFailTp = time;
290-
giveRocket(player, 1);
307+
state.previousFails += 1;
308+
state.lastFailOrSuccess = time;
309+
giveRocket(player, Math.min(state.previousFails, 3));
291310

292311
ServerWorld world = this.gameWorld.getWorld();
293312
List<FireworkRocketEntity> rockets = world.getEntitiesByType(
@@ -321,7 +340,7 @@ private void broadcastWin() {
321340
StringBuilder message_builder = new StringBuilder();
322341
message_builder.append("The game has ended!\n");
323342

324-
for (int i = 0; i < 3 && i < this.finished.size(); i++) {
343+
for (int i = 0; i < 5 && i < this.finished.size(); i++) {
325344
LoopDeLoopWinner player = this.finished.get(i);
326345
message_builder.append(String.format(
327346
" %s place - %s in %.2fs\n",
@@ -345,10 +364,10 @@ private boolean onPlayerDamage(ServerPlayerEntity player, DamageSource source, f
345364
return true;
346365
}
347366

348-
private boolean onPlayerDeath(ServerPlayerEntity player, DamageSource source) {
367+
private ActionResult onPlayerDeath(ServerPlayerEntity player, DamageSource source) {
349368
long time = this.gameWorld.getWorld().getTime();
350369
this.failHoop(player, this.player_states.get(player), time);
351-
return true;
370+
return ActionResult.FAIL;
352371
}
353372

354373
private void spawnParticipant(ServerPlayerEntity player) {
@@ -382,7 +401,7 @@ private void broadcastMessage(Text message) {
382401

383402
private void broadcastTitle(Text message) {
384403
for (ServerPlayerEntity player : this.gameWorld.getPlayers()) {
385-
TitleS2CPacket packet = new TitleS2CPacket(TitleS2CPacket.Action.TITLE, message, 1, 5, 3);
404+
TitleS2CPacket packet = new TitleS2CPacket(TitleS2CPacket.Action.TITLE, message, 1, 5, 3);
386405
player.networkHandler.sendPacket(packet);
387406
}
388407
}

src/main/java/io/github/restioson/loopdeloop/game/LoopDeLoopConfig.java

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,59 @@
66

77
public final class LoopDeLoopConfig {
88
public static final Codec<LoopDeLoopConfig> CODEC = RecordCodecBuilder.create(instance -> instance.group(
9-
PlayerConfig.CODEC.fieldOf("players").forGetter(config -> config.players),
9+
PlayerConfig.CODEC.fieldOf("players").orElse(new PlayerConfig(1, 100)).forGetter(config -> config.players),
1010
Codec.INT.fieldOf("time_limit_secs").forGetter(config -> config.timeLimit),
1111
Codec.INT.fieldOf("loops").forGetter(config -> config.loops),
12+
Codec.INT.fieldOf("loop_radius").orElse(5).forGetter(config -> config.loopRadius),
1213
Codec.INT.fieldOf("start_rockets").forGetter(config -> config.startRockets),
13-
Codec.INT.fieldOf("max_y_variation").forGetter(config -> config.maxYVariation)
14+
Codec.INT.fieldOf("y_var_max").forGetter(config -> config.yVarMax),
15+
ZVariation.CODEC.fieldOf("z_var_max").forGetter(config -> config.zVarMax),
16+
ZVariation.CODEC.fieldOf("z_var_min").forGetter(config -> config.zVarMin)
1417
).apply(instance, LoopDeLoopConfig::new));
1518

1619
public final PlayerConfig players;
1720
public final int timeLimit;
1821
public final int loops;
22+
public final int loopRadius;
1923
public final int startRockets;
20-
public final int maxYVariation;
24+
public final int yVarMax;
25+
public final ZVariation zVarMax;
26+
public final ZVariation zVarMin;
2127

22-
public LoopDeLoopConfig(PlayerConfig players, int timeLimit, int loops, int startRockets, int maxYVariation) {
28+
public LoopDeLoopConfig(
29+
PlayerConfig players,
30+
int timeLimit,
31+
int loops,
32+
int loopRadius,
33+
int startRockets,
34+
int yVarMax,
35+
ZVariation zVarMax,
36+
ZVariation zVarMin
37+
) {
2338
this.players = players;
2439
this.timeLimit = timeLimit;
2540
this.loops = loops;
41+
this.loopRadius = loopRadius;
2642
this.startRockets = startRockets;
27-
this.maxYVariation = maxYVariation;
43+
this.yVarMax = yVarMax;
44+
this.zVarMax = zVarMax;
45+
this.zVarMin = zVarMin;
46+
47+
System.out.println(String.format("HERE loops: %s; radius: %s", loops, loopRadius));
48+
}
49+
50+
public static class ZVariation {
51+
public static final Codec<ZVariation> CODEC = RecordCodecBuilder.create(instance -> instance.group(
52+
Codec.INT.fieldOf("start").forGetter(config -> config.start),
53+
Codec.INT.fieldOf("end").forGetter(config -> config.end)
54+
).apply(instance, ZVariation::new));
55+
56+
public final int start;
57+
public final int end;
58+
59+
public ZVariation(int start, int end) {
60+
this.start = start;
61+
this.end = end;
62+
}
2863
}
2964
}

src/main/java/io/github/restioson/loopdeloop/game/LoopDeLoopPlayer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
public class LoopDeLoopPlayer {
66
public int lastHoop = -1;
77
public Vec3d lastPos;
8-
public long lastFailTp = -1;
8+
public long lastFailOrSuccess = -1;
9+
public int previousFails = -1;
910
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package io.github.restioson.loopdeloop.game;
2+
3+
4+
import net.minecraft.scoreboard.ScoreboardCriterion;
5+
import net.minecraft.scoreboard.ScoreboardObjective;
6+
import net.minecraft.scoreboard.ScoreboardPlayerScore;
7+
import net.minecraft.scoreboard.ServerScoreboard;
8+
import net.minecraft.server.network.ServerPlayerEntity;
9+
import net.minecraft.text.LiteralText;
10+
import net.minecraft.util.Formatting;
11+
import net.minecraft.util.Pair;
12+
13+
import java.util.ArrayList;
14+
import java.util.Collection;
15+
import java.util.List;
16+
17+
public class LoopDeLoopScoreboard {
18+
19+
ServerScoreboard scoreboard;
20+
ScoreboardObjective hoops;
21+
int totalHoops;
22+
23+
public LoopDeLoopScoreboard(ServerScoreboard scoreboard, int totalHoops) {
24+
ScoreboardObjective scoreboardObjective = new ScoreboardObjective(
25+
scoreboard,
26+
"loopdeloop_hoops",
27+
ScoreboardCriterion.DUMMY,
28+
new LiteralText("Loop-de-loop").formatted(Formatting.BLUE, Formatting.BOLD),
29+
ScoreboardCriterion.RenderType.INTEGER
30+
);
31+
scoreboard.addScoreboardObjective(scoreboardObjective);
32+
scoreboard.setObjectiveSlot(1, scoreboardObjective);
33+
this.hoops = scoreboardObjective;
34+
this.scoreboard = scoreboard;
35+
this.totalHoops = totalHoops;
36+
}
37+
38+
public void render(List<Pair<ServerPlayerEntity, LoopDeLoopPlayer>> topPlayers) {
39+
String top = String.format(
40+
"%sTotal hoops:%s %s",
41+
Formatting.AQUA + Formatting.BOLD.toString(),
42+
Formatting.RESET,
43+
this.totalHoops
44+
);
45+
46+
List<String> lines = new ArrayList<>();
47+
lines.add(top);
48+
49+
for (Pair<ServerPlayerEntity, LoopDeLoopPlayer> pair : topPlayers) {
50+
String line = String.format(
51+
"%s%s:%s %d hoops",
52+
Formatting.AQUA,
53+
pair.getLeft().getEntityName(),
54+
Formatting.RESET,
55+
pair.getRight().lastHoop + 1
56+
);
57+
lines.add(line);
58+
}
59+
60+
this.renderObjective(this.hoops, lines);
61+
}
62+
63+
private void renderObjective(ScoreboardObjective objective, List<String> lines) {
64+
System.out.println(lines);
65+
this.clear(objective);
66+
for (int i = 0; i < lines.size(); i++) {
67+
String line = lines.get(i);
68+
scoreboard.getPlayerScore(line, objective).setScore(lines.size() - i);
69+
}
70+
}
71+
72+
private void clear(ScoreboardObjective objective) {
73+
Collection<ScoreboardPlayerScore> existing = this.scoreboard.getAllPlayerScores(objective);
74+
for (ScoreboardPlayerScore score : existing) {
75+
this.scoreboard.resetPlayerScore(score.getPlayerName(), objective);
76+
}
77+
}
78+
79+
public void close() {
80+
scoreboard.removeObjective(this.hoops);
81+
}
82+
}

src/main/java/io/github/restioson/loopdeloop/game/LoopDeLoopSpawnLogic.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
import io.github.restioson.loopdeloop.LoopDeLoop;
44
import io.github.restioson.loopdeloop.game.map.LoopDeLoopMap;
5-
import xyz.nucleoid.plasmid.game.GameWorld;
65
import net.minecraft.entity.effect.StatusEffectInstance;
76
import net.minecraft.entity.effect.StatusEffects;
87
import net.minecraft.server.network.ServerPlayerEntity;
98
import net.minecraft.server.world.ServerWorld;
109
import net.minecraft.util.math.BlockPos;
1110
import net.minecraft.util.math.MathHelper;
1211
import net.minecraft.world.GameMode;
12+
import xyz.nucleoid.plasmid.game.GameWorld;
1313

1414
public final class LoopDeLoopSpawnLogic {
1515
private final GameWorld gameWorld;

0 commit comments

Comments
 (0)