2022-05-31 15:21:53 +02:00

177 lines
8.2 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package semmiedev.disc_jockey;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.enums.Instrument;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.hud.ChatHud;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
import net.minecraft.state.property.Properties;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameMode;
import java.util.ArrayList;
import java.util.HashMap;
public class SongPlayer implements ClientTickEvents.StartWorldTick {
public boolean running;
public Song song;
private int index;
private float tick;
private HashMap<Instrument, HashMap<Byte, BlockPos>> noteBlocks = null;
private boolean tuned;
private int tuneDelay = 5;
public void start(Song song) {
if (running) stop();
this.song = song;
Main.TICK_LISTENERS.add(this);
running = true;
}
public void stop() {
MinecraftClient.getInstance().send(() -> Main.TICK_LISTENERS.remove(this));
running = false;
index = 0;
tick = 0;
noteBlocks = null;
tuned = false;
}
@Override
public void onStartTick(ClientWorld world) {
if (!running) return;
if (noteBlocks == null) {
noteBlocks = new HashMap<>();
ClientPlayerEntity player = MinecraftClient.getInstance().player;
ArrayList<Note> capturedNotes = new ArrayList<>();
Vec3d playerPos = player.getEyePos();
for (int x = -7; x <= 7; x++) {
for (int y = -7; y <= 7; y++) {
for (int z = -7; z <= 7; z++) {
Vec3d pos = playerPos.add(x, y, z);
BlockPos blockPos = new BlockPos(pos);
if (playerPos.squaredDistanceTo(pos) < 4.5 * 4.5) {
BlockState blockState = world.getBlockState(blockPos);
if (blockState.isOf(Blocks.NOTE_BLOCK) && world.isAir(blockPos.up())) {
for (Note note : song.uniqueNotes) {
if (!capturedNotes.contains(note) && blockState.get(Properties.INSTRUMENT) == note.instrument) {
getNotes(note.instrument).put(note.note, blockPos);
capturedNotes.add(note);
break;
}
}
}
}
}
}
}
ArrayList<Note> missingNotes = new ArrayList<>(song.uniqueNotes);
missingNotes.removeAll(capturedNotes);
if (!missingNotes.isEmpty()) {
ChatHud chatHud = MinecraftClient.getInstance().inGameHud.getChatHud();
chatHud.addMessage(Text.translatable(Main.MOD_ID+".player.invalid_note_blocks").formatted(Formatting.RED));
HashMap<Block, Integer> missing = new HashMap<>();
for (Note note : missingNotes) {
Block block = Note.INSTRUMENT_BLOCKS.get(note.instrument);
Integer got = missing.get(block);
if (got == null) got = 0;
missing.put(block, got + 1);
}
missing.forEach((block, integer) -> chatHud.addMessage(Text.literal(block.getName().getString()+" × "+integer).formatted(Formatting.RED)));
stop();
}
} else if (!tuned) {
if (tuneDelay > 0) {
tuneDelay--;
return;
}
tuned = true;
MinecraftClient client = MinecraftClient.getInstance();
int tuneAmount = 0;
for (Note note : song.uniqueNotes) {
BlockPos blockPos = noteBlocks.get(note.instrument).get(note.note);
BlockState blockState = world.getBlockState(blockPos);
if (blockState.contains(Properties.NOTE)) {
if (blockState.get(Properties.NOTE) != note.note) {
if (client.player.getEyePos().squaredDistanceTo(Vec3d.ofCenter(blockPos, 0.5)) >= 4.5 * 4.5) {
stop();
client.inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".player.to_far").formatted(Formatting.RED));
return;
}
Vec3d unit = Vec3d.ofCenter(blockPos, 0.5).subtract(client.player.getEyePos()).normalize();
client.getNetworkHandler().sendPacket(new PlayerMoveC2SPacket.LookAndOnGround(MathHelper.wrapDegrees((float)(MathHelper.atan2(unit.z, unit.x) * 57.2957763671875) - 90.0f), MathHelper.wrapDegrees((float)(-(MathHelper.atan2(unit.y, Math.sqrt(unit.x * unit.x + unit.z * unit.z)) * 57.2957763671875))), true));
client.interactionManager.interactBlock(client.player, Hand.MAIN_HAND, new BlockHitResult(Vec3d.of(blockPos), Direction.UP, blockPos, false));
client.player.swingHand(Hand.MAIN_HAND);
tuned = false;
tuneDelay = 5;
if (++tuneAmount == 6) break;
}
} else {
noteBlocks = null;
break;
}
}
} else {
while (running) {
MinecraftClient client = MinecraftClient.getInstance();
GameMode gameMode = client.interactionManager.getCurrentGameMode();
if (!gameMode.isSurvivalLike()) {
client.inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".player.invalid_game_mode", gameMode.getTranslatableName()).formatted(Formatting.RED));
stop();
return;
}
long note = song.notes[index];
if ((short)note == Math.round(tick)) {
BlockPos blockPos = noteBlocks.get(Note.INSTRUMENTS[(byte)(note >> Note.INSTRUMENT_SHIFT)]).get((byte)(note >> Note.NOTE_SHIFT));
// TODO: 5/30/2022 Check if the cube is inside of a sphere with a centre of 4.5 centered on the eye pos instead
if (client.player.getEyePos().squaredDistanceTo(Vec3d.ofCenter(blockPos, 0.5)) >= 4.5 * 4.5) {
stop();
client.inGameHud.getChatHud().addMessage(Text.translatable(Main.MOD_ID+".player.to_far").formatted(Formatting.RED));
return;
}
Vec3d unit = Vec3d.ofCenter(blockPos, 0.5).subtract(client.player.getEyePos()).normalize();
client.getNetworkHandler().sendPacket(new PlayerMoveC2SPacket.LookAndOnGround(MathHelper.wrapDegrees((float)(MathHelper.atan2(unit.z, unit.x) * 57.2957763671875) - 90.0f), MathHelper.wrapDegrees((float)(-(MathHelper.atan2(unit.y, Math.sqrt(unit.x * unit.x + unit.z * unit.z)) * 57.2957763671875))), true));
// TODO: 5/30/2022 Check if the block needs tuning
client.interactionManager.attackBlock(blockPos, Direction.UP);
client.player.swingHand(Hand.MAIN_HAND);
index++;
if (index >= song.notes.length) {
stop();
break;
}
} else {
break;
}
}
tick += song.tempo / 100f / 20f;
}
}
private HashMap<Byte, BlockPos> getNotes(Instrument instrument) {
return noteBlocks.computeIfAbsent(instrument, k -> new HashMap<>());
}
}