1.0.0
This commit is contained in:
parent
a91692ded7
commit
f1c52e4371
38 changed files with 1854 additions and 35 deletions
|
@ -16,16 +16,16 @@ show_testing_output = false
|
||||||
# Mod Information
|
# Mod Information
|
||||||
# HIGHLY RECOMMEND complying with SemVer for mod_version: https://semver.org/
|
# HIGHLY RECOMMEND complying with SemVer for mod_version: https://semver.org/
|
||||||
mod_version = 1.0.0
|
mod_version = 1.0.0
|
||||||
root_package = com.example
|
root_package = ru.octol1ttle
|
||||||
mod_id = modid
|
mod_id = knockdowns
|
||||||
mod_name = Mod Name
|
mod_name = Knockdowns (Legacy)
|
||||||
|
|
||||||
# Mod Metadata (Optional)
|
# Mod Metadata (Optional)
|
||||||
mod_description =
|
mod_description =
|
||||||
mod_url =
|
mod_url =
|
||||||
mod_update_json =
|
mod_update_json =
|
||||||
# Delimit authors with commas
|
# Delimit authors with commas
|
||||||
mod_authors =
|
mod_authors = Octol1ttle
|
||||||
mod_credits =
|
mod_credits =
|
||||||
mod_logo_path =
|
mod_logo_path =
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ access_transformer_locations = ${mod_id}_at.cfg
|
||||||
# Powerful tool to do runtime description changes of classes
|
# Powerful tool to do runtime description changes of classes
|
||||||
# Wiki: https://github.com/SpongePowered/Mixin/wiki + https://github.com/CleanroomMC/MixinBooter/ + https://cleanroommc.com/wiki/forge-mod-development/mixin/preface
|
# Wiki: https://github.com/SpongePowered/Mixin/wiki + https://github.com/CleanroomMC/MixinBooter/ + https://cleanroommc.com/wiki/forge-mod-development/mixin/preface
|
||||||
# Only use mixins once you understand the underlying structure
|
# Only use mixins once you understand the underlying structure
|
||||||
use_mixins = false
|
use_mixins = true
|
||||||
mixin_booter_version = 9.1
|
mixin_booter_version = 9.1
|
||||||
# A configuration defines a mixin set, and you may have as many mixin sets as you require for your application.
|
# A configuration defines a mixin set, and you may have as many mixin sets as you require for your application.
|
||||||
# Each config can only have one and only one package root.
|
# Each config can only have one and only one package root.
|
||||||
|
@ -115,9 +115,9 @@ mixin_refmap = mixins.${mod_id}.refmap.json
|
||||||
# Only make a coremod if you are absolutely sure of what you are doing
|
# Only make a coremod if you are absolutely sure of what you are doing
|
||||||
# Change the property `coremod_includes_mod` to false if your coremod doesn't have a @Mod annotation
|
# Change the property `coremod_includes_mod` to false if your coremod doesn't have a @Mod annotation
|
||||||
# You MUST state a class name for `coremod_plugin_class_name` if you are making a coremod, the class should implement `IFMLLoadingPlugin`
|
# You MUST state a class name for `coremod_plugin_class_name` if you are making a coremod, the class should implement `IFMLLoadingPlugin`
|
||||||
is_coremod = false
|
is_coremod = true
|
||||||
coremod_includes_mod = true
|
coremod_includes_mod = true
|
||||||
coremod_plugin_class_name =
|
coremod_plugin_class_name = ru.octol1ttle.knockdowns.common.KnockdownsFMLLoadingPlugin
|
||||||
|
|
||||||
# AssetMover
|
# AssetMover
|
||||||
# Convenient way to allow downloading of assets from official vanilla Minecraft servers, CurseForge, or any direct links
|
# Convenient way to allow downloading of assets from official vanilla Minecraft servers, CurseForge, or any direct links
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
package com.example.modid;
|
|
||||||
|
|
||||||
import com.example.modid.Tags;
|
|
||||||
import net.minecraftforge.fml.common.Mod;
|
|
||||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
@Mod(modid = Tags.MOD_ID, name = Tags.MOD_NAME, version = Tags.VERSION)
|
|
||||||
public class ExampleMod {
|
|
||||||
|
|
||||||
public static final Logger LOGGER = LogManager.getLogger(Tags.MOD_NAME);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <a href="https://cleanroommc.com/wiki/forge-mod-development/event#overview">
|
|
||||||
* Take a look at how many FMLStateEvents you can listen to via the @Mod.EventHandler annotation here
|
|
||||||
* </a>
|
|
||||||
*/
|
|
||||||
@Mod.EventHandler
|
|
||||||
public void preInit(FMLPreInitializationEvent event) {
|
|
||||||
LOGGER.info("Hello From {}!", Tags.MOD_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package ru.octol1ttle.knockdowns.client;
|
||||||
|
|
||||||
|
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
|
||||||
|
import net.minecraftforge.fml.relauncher.Side;
|
||||||
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||||
|
import ru.octol1ttle.knockdowns.client.event.KnockdownsKeyListener;
|
||||||
|
import ru.octol1ttle.knockdowns.common.IClientProxy;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class ClientProxy implements IClientProxy {
|
||||||
|
@Override
|
||||||
|
public void onFMLInit(FMLInitializationEvent event) {
|
||||||
|
KnockdownsKeyListener.registerKeyBindings();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package ru.octol1ttle.knockdowns.client.communication;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraftforge.fml.relauncher.Side;
|
||||||
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||||
|
import ru.octol1ttle.knockdowns.client.util.Callout;
|
||||||
|
import ru.octol1ttle.knockdowns.client.util.DirectionalCallSound;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.s2c.PlayerCalloutS2CPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.registry.KnockdownsSoundEvents;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class CalloutManager {
|
||||||
|
private static final Minecraft client = Minecraft.getMinecraft();
|
||||||
|
private static final Map<Integer, Callout> callouts = new HashMap<>();
|
||||||
|
|
||||||
|
public static Set<Map.Entry<Integer, Callout>> getCallouts() {
|
||||||
|
return callouts.entrySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean addOrUpdateCallout(PlayerCalloutS2CPacket message) {
|
||||||
|
return callouts.put(message.playerId, new Callout(message.position, message.type, client.world.getTotalWorldTime())) == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void playCalloutSound(PlayerCalloutS2CPacket message) {
|
||||||
|
client.getSoundHandler().playSound(new DirectionalCallSound(KnockdownsSoundEvents.CALLOUT, client.world.getEntityByID(message.playerId), message.position));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearCallouts() {
|
||||||
|
callouts.clear();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package ru.octol1ttle.knockdowns.client.communication;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraftforge.fml.relauncher.Side;
|
||||||
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||||
|
import ru.octol1ttle.knockdowns.client.util.KnockedPlayerData;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class KnockedNotificationManager {
|
||||||
|
private static final Minecraft client = Minecraft.getMinecraft();
|
||||||
|
private static final List<KnockedPlayerData> knockedDatas = new ArrayList<>();
|
||||||
|
|
||||||
|
public static void addKnockedNotification(int playerId, Vec3d position) {
|
||||||
|
knockedDatas.add(new KnockedPlayerData(playerId, position, client.world.getTotalWorldTime()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Collection<KnockedPlayerData> getKnockedPlayerDatas() {
|
||||||
|
return knockedDatas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearDatas() {
|
||||||
|
knockedDatas.clear();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package ru.octol1ttle.knockdowns.client.event;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraftforge.client.event.RenderGameOverlayEvent;
|
||||||
|
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.gameevent.InputEvent;
|
||||||
|
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||||
|
import net.minecraftforge.fml.relauncher.Side;
|
||||||
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||||
|
import ru.octol1ttle.knockdowns.Tags;
|
||||||
|
import ru.octol1ttle.knockdowns.client.communication.CalloutManager;
|
||||||
|
import ru.octol1ttle.knockdowns.client.communication.KnockedNotificationManager;
|
||||||
|
import ru.octol1ttle.knockdowns.client.gui.CommunicationGui;
|
||||||
|
import ru.octol1ttle.knockdowns.client.gui.KnockedNotificationGui;
|
||||||
|
import ru.octol1ttle.knockdowns.client.gui.ReviveGui;
|
||||||
|
import ru.octol1ttle.knockdowns.common.ReviverTracker;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.KnockdownsNetwork;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.c2s.CancelReviveC2SPacket;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
@Mod.EventBusSubscriber(value = Side.CLIENT, modid = Tags.MOD_ID)
|
||||||
|
public class KnockdownsClientEventListener {
|
||||||
|
private static final Minecraft client = Minecraft.getMinecraft();
|
||||||
|
private static final CommunicationGui communicationGui = new CommunicationGui();
|
||||||
|
private static final KnockedNotificationGui notificationGui = new KnockedNotificationGui();
|
||||||
|
private static final ReviveGui reviveGui = new ReviveGui();
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onTick(TickEvent.ClientTickEvent event) {
|
||||||
|
if (event.phase == TickEvent.Phase.START) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (client.world == null) {
|
||||||
|
CalloutManager.clearCallouts();
|
||||||
|
KnockedNotificationManager.clearDatas();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CalloutManager.getCallouts().removeIf(callout -> client.world.getTotalWorldTime() - callout.getValue().getReceiveTime() > 60);
|
||||||
|
KnockedNotificationManager.getKnockedPlayerDatas().removeIf(notification -> client.world.getTotalWorldTime() - notification.getReceiveTime() > 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onPlayerTick(TickEvent.PlayerTickEvent event) {
|
||||||
|
List<EntityPlayer> revivers = ReviverTracker.getRevivers(event.player);
|
||||||
|
if (revivers.contains(client.player) && !event.player.equals(client.pointedEntity)) {
|
||||||
|
KnockdownsNetwork.sendToServer(new CancelReviveC2SPacket());
|
||||||
|
revivers.remove(client.player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onRenderWorldLast(RenderWorldLastEvent event) {
|
||||||
|
communicationGui.renderCallouts(event.getPartialTicks());
|
||||||
|
notificationGui.renderNotifications(event.getPartialTicks());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onRenderGameOverlay(RenderGameOverlayEvent.Chat event) {
|
||||||
|
communicationGui.render(event.getPartialTicks(), event.getResolution());
|
||||||
|
reviveGui.render(event.getPartialTicks(), event.getResolution());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onKeyInput(InputEvent.KeyInputEvent event) {
|
||||||
|
KnockdownsKeyListener.tickKeys();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package ru.octol1ttle.knockdowns.client.event;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.settings.KeyBinding;
|
||||||
|
import net.minecraftforge.fml.client.registry.ClientRegistry;
|
||||||
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
import net.minecraftforge.fml.relauncher.Side;
|
||||||
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||||
|
import org.lwjgl.input.Keyboard;
|
||||||
|
import ru.octol1ttle.knockdowns.Tags;
|
||||||
|
import ru.octol1ttle.knockdowns.common.communication.CalloutType;
|
||||||
|
import ru.octol1ttle.knockdowns.common.data.IKnockdownsPlayerData;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.KnockdownsNetwork;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.c2s.PlayerCalloutC2SPacket;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
@Mod.EventBusSubscriber(value = Side.CLIENT, modid = Tags.MOD_ID)
|
||||||
|
public class KnockdownsKeyListener {
|
||||||
|
private static final Minecraft client = Minecraft.getMinecraft();
|
||||||
|
public static final Map<KeyBinding, Supplier<CalloutType>> calloutBindings = new HashMap<>();
|
||||||
|
|
||||||
|
public static void registerKeyBindings() {
|
||||||
|
calloutBindings.put(
|
||||||
|
new KeyBinding("knockdowns.key.callout.danger", Keyboard.KEY_LEFT, "knockdowns.key.category"),
|
||||||
|
() -> CalloutType.DANGER
|
||||||
|
);
|
||||||
|
calloutBindings.put(
|
||||||
|
new KeyBinding("knockdowns.key.callout.booyah", Keyboard.KEY_DOWN, "knockdowns.key.category"),
|
||||||
|
() -> CalloutType.BOOYAH
|
||||||
|
);
|
||||||
|
calloutBindings.put(
|
||||||
|
new KeyBinding("knockdowns.key.callout.this_way_help", Keyboard.KEY_UP, "knockdowns.key.category"),
|
||||||
|
() -> IKnockdownsPlayerData.get(client.player).isKnockedDown() ? CalloutType.HELP : CalloutType.THIS_WAY
|
||||||
|
);
|
||||||
|
calloutBindings.put(
|
||||||
|
new KeyBinding("knockdowns.key.callout.ouch", Keyboard.KEY_RIGHT, "knockdowns.key.category"),
|
||||||
|
() -> CalloutType.OUCH
|
||||||
|
);
|
||||||
|
|
||||||
|
for (KeyBinding binding : calloutBindings.keySet()) {
|
||||||
|
ClientRegistry.registerKeyBinding(binding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void tickKeys() {
|
||||||
|
for (KeyBinding binding : calloutBindings.keySet()) {
|
||||||
|
if (binding.isPressed()) {
|
||||||
|
KnockdownsNetwork.sendToServer(new PlayerCalloutC2SPacket(calloutBindings.get(binding).get()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,175 @@
|
||||||
|
package ru.octol1ttle.knockdowns.client.gui;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.FontRenderer;
|
||||||
|
import net.minecraft.client.gui.ScaledResolution;
|
||||||
|
import net.minecraft.client.renderer.GlStateManager;
|
||||||
|
import net.minecraft.client.resources.I18n;
|
||||||
|
import net.minecraft.client.settings.KeyBinding;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraftforge.fml.relauncher.Side;
|
||||||
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||||
|
import org.lwjgl.input.Keyboard;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import ru.octol1ttle.knockdowns.Tags;
|
||||||
|
import ru.octol1ttle.knockdowns.client.communication.CalloutManager;
|
||||||
|
import ru.octol1ttle.knockdowns.client.event.KnockdownsKeyListener;
|
||||||
|
import ru.octol1ttle.knockdowns.client.util.Callout;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class CommunicationGui extends KnockdownsBaseGui {
|
||||||
|
private static final Minecraft client = Minecraft.getMinecraft();
|
||||||
|
private static final ResourceLocation LEFT_ARROW = new ResourceLocation(Tags.MOD_ID, "textures/gui/left_arrow.png");
|
||||||
|
private static final ResourceLocation DOWN_ARROW = new ResourceLocation(Tags.MOD_ID, "textures/gui/down_arrow.png");
|
||||||
|
private static final ResourceLocation UP_ARROW = new ResourceLocation(Tags.MOD_ID, "textures/gui/up_arrow.png");
|
||||||
|
private static final ResourceLocation RIGHT_ARROW = new ResourceLocation(Tags.MOD_ID, "textures/gui/right_arrow.png");
|
||||||
|
private static final int SCREEN_EDGE_MARGIN = 5;
|
||||||
|
private static final int SEPARATOR_MARGIN = 2;
|
||||||
|
private static final int KEY_SIZE = 17;
|
||||||
|
private float totalPartialTicks;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(float partialTicks, ScaledResolution resolution) {
|
||||||
|
FontRenderer font = client.fontRenderer;
|
||||||
|
|
||||||
|
int x = SCREEN_EDGE_MARGIN;
|
||||||
|
int y = resolution.getScaledHeight() - SCREEN_EDGE_MARGIN - font.FONT_HEIGHT;
|
||||||
|
|
||||||
|
KeyBinding[] sortedBindings = new KeyBinding[4];
|
||||||
|
for (KeyBinding binding : KnockdownsKeyListener.calloutBindings.keySet())
|
||||||
|
{
|
||||||
|
switch (binding.getKeyCode()) {
|
||||||
|
case Keyboard.KEY_LEFT:
|
||||||
|
sortedBindings[0] = binding;
|
||||||
|
break;
|
||||||
|
case Keyboard.KEY_DOWN:
|
||||||
|
sortedBindings[1] = binding;
|
||||||
|
break;
|
||||||
|
case Keyboard.KEY_UP:
|
||||||
|
sortedBindings[2] = binding;
|
||||||
|
break;
|
||||||
|
case Keyboard.KEY_RIGHT:
|
||||||
|
sortedBindings[3] = binding;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyBinding leftCallout = sortedBindings[0];
|
||||||
|
if (leftCallout != null) {
|
||||||
|
String text = I18n.format(KnockdownsKeyListener.calloutBindings.get(leftCallout).get().getTextKey());
|
||||||
|
font.drawStringWithShadow(
|
||||||
|
text,
|
||||||
|
x,
|
||||||
|
y - 12,
|
||||||
|
0xFFFFFF
|
||||||
|
);
|
||||||
|
|
||||||
|
x += font.getStringWidth(text) + SEPARATOR_MARGIN;
|
||||||
|
client.getTextureManager().bindTexture(LEFT_ARROW);
|
||||||
|
this.drawTexture(
|
||||||
|
x,
|
||||||
|
y - KEY_SIZE,
|
||||||
|
KEY_SIZE,
|
||||||
|
KEY_SIZE
|
||||||
|
);
|
||||||
|
x += KEY_SIZE + SEPARATOR_MARGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyBinding downCallout = sortedBindings[1];
|
||||||
|
if (downCallout != null) {
|
||||||
|
String text = I18n.format(KnockdownsKeyListener.calloutBindings.get(downCallout).get().getTextKey());
|
||||||
|
font.drawStringWithShadow(
|
||||||
|
text,
|
||||||
|
x + KEY_SIZE * 0.5f - font.getStringWidth(text) * 0.5f,
|
||||||
|
y + SEPARATOR_MARGIN,
|
||||||
|
0xFFFFFF
|
||||||
|
);
|
||||||
|
client.getTextureManager().bindTexture(DOWN_ARROW);
|
||||||
|
this.drawTexture(
|
||||||
|
x,
|
||||||
|
y - KEY_SIZE,
|
||||||
|
KEY_SIZE,
|
||||||
|
KEY_SIZE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyBinding upCallout = sortedBindings[2];
|
||||||
|
if (upCallout != null) {
|
||||||
|
String text = I18n.format(KnockdownsKeyListener.calloutBindings.get(upCallout).get().getTextKey());
|
||||||
|
font.drawStringWithShadow(
|
||||||
|
text,
|
||||||
|
x + KEY_SIZE * 0.5f - font.getStringWidth(text) * 0.5f,
|
||||||
|
y - KEY_SIZE * 2 - 12,
|
||||||
|
0xFFFFFF
|
||||||
|
);
|
||||||
|
|
||||||
|
client.getTextureManager().bindTexture(UP_ARROW);
|
||||||
|
this.drawTexture(
|
||||||
|
x,
|
||||||
|
y - KEY_SIZE * 2 - 2,
|
||||||
|
KEY_SIZE,
|
||||||
|
KEY_SIZE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyBinding rightCallout = sortedBindings[3];
|
||||||
|
if (rightCallout != null) {
|
||||||
|
x += KEY_SIZE + SEPARATOR_MARGIN;
|
||||||
|
String text = I18n.format(KnockdownsKeyListener.calloutBindings.get(rightCallout).get().getTextKey());
|
||||||
|
font.drawStringWithShadow(
|
||||||
|
text,
|
||||||
|
x + KEY_SIZE + SEPARATOR_MARGIN,
|
||||||
|
y - 12,
|
||||||
|
0xFFFFFF
|
||||||
|
);
|
||||||
|
|
||||||
|
client.getTextureManager().bindTexture(RIGHT_ARROW);
|
||||||
|
this.drawTexture(
|
||||||
|
x,
|
||||||
|
y - KEY_SIZE,
|
||||||
|
KEY_SIZE,
|
||||||
|
KEY_SIZE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renderCallouts(float partialTicks) {
|
||||||
|
totalPartialTicks += partialTicks;
|
||||||
|
for (Map.Entry<Integer, Callout> calloutEntry : CalloutManager.getCallouts()) {
|
||||||
|
Entity entity = client.world.getEntityByID(calloutEntry.getKey());
|
||||||
|
renderCallout(
|
||||||
|
I18n.format(calloutEntry.getValue().getType().getTextKey()),
|
||||||
|
entity != null ? entity.getPositionEyes(partialTicks).add(0, 1, 0) : calloutEntry.getValue().getPosition(),
|
||||||
|
client.getRenderManager().playerViewX,
|
||||||
|
client.getRenderManager().playerViewY,
|
||||||
|
client.getRenderManager().options.thirdPersonView == 2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderCallout(String text, Vec3d position, float pitch, float yaw, boolean isThirdPersonFrontal) {
|
||||||
|
FontRenderer font = client.fontRenderer;
|
||||||
|
|
||||||
|
Vec3d deltaPos = position.subtract(client.getRenderManager().viewerPosX, client.getRenderManager().viewerPosY, client.getRenderManager().viewerPosZ);
|
||||||
|
|
||||||
|
GlStateManager.pushMatrix();
|
||||||
|
GlStateManager.translate(deltaPos.x, deltaPos.y, deltaPos.z);
|
||||||
|
GlStateManager.rotate(-yaw, 0.0F, 1.0F, 0.0F);
|
||||||
|
GlStateManager.rotate((float)(isThirdPersonFrontal ? -1 : 1) * pitch, 1.0F, 0.0F, 0.0F);
|
||||||
|
float scale = (float) Math.max(deltaPos.length() / 8.0f, 1.0f) * (0.75f + MathHelper.abs((float) (MathHelper.sin(totalPartialTicks / 10F) / Math.PI)));
|
||||||
|
GlStateManager.scale(-0.025F * scale, -0.025F * scale, 0.025F * scale);
|
||||||
|
GlStateManager.color(1f, 1f, 1f, 1f);
|
||||||
|
GlStateManager.disableCull();
|
||||||
|
GlStateManager.depthFunc(GL11.GL_ALWAYS);
|
||||||
|
|
||||||
|
font.drawStringWithShadow(text, -font.getStringWidth(text) * 0.5f, -font.FONT_HEIGHT * 0.5f, 0xFFFFFF);
|
||||||
|
|
||||||
|
GlStateManager.depthFunc(GL11.GL_LEQUAL);
|
||||||
|
GlStateManager.enableCull();
|
||||||
|
GlStateManager.popMatrix();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package ru.octol1ttle.knockdowns.client.gui;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.Gui;
|
||||||
|
import net.minecraft.client.gui.ScaledResolution;
|
||||||
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||||
|
import net.minecraftforge.fml.relauncher.Side;
|
||||||
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public abstract class KnockdownsBaseGui extends Gui {
|
||||||
|
public abstract void render(float partialTicks, ScaledResolution resolution);
|
||||||
|
|
||||||
|
protected void drawTexture(int x, int y, int width, int height) {
|
||||||
|
Tessellator tessellator = Tessellator.getInstance();
|
||||||
|
BufferBuilder bufferbuilder = tessellator.getBuffer();
|
||||||
|
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX);
|
||||||
|
bufferbuilder.pos(x, y, this.zLevel).tex(0, 0).endVertex();
|
||||||
|
bufferbuilder.pos(x, y + height, this.zLevel).tex(0, 1).endVertex();
|
||||||
|
bufferbuilder.pos(x + width, y + height, this.zLevel).tex(1, 1).endVertex();
|
||||||
|
bufferbuilder.pos(x + width, y, this.zLevel).tex(1, 0).endVertex();
|
||||||
|
tessellator.draw();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package ru.octol1ttle.knockdowns.client.gui;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.ScaledResolution;
|
||||||
|
import net.minecraft.client.renderer.GlStateManager;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import ru.octol1ttle.knockdowns.Tags;
|
||||||
|
import ru.octol1ttle.knockdowns.client.communication.KnockedNotificationManager;
|
||||||
|
import ru.octol1ttle.knockdowns.client.util.KnockedPlayerData;
|
||||||
|
|
||||||
|
public class KnockedNotificationGui extends KnockdownsBaseGui {
|
||||||
|
private static final Minecraft client = Minecraft.getMinecraft();
|
||||||
|
private static final int KNOCKED_ICON_SIZE = 18;
|
||||||
|
private static final ResourceLocation KNOCKED_ICON = new ResourceLocation(Tags.MOD_ID, "textures/gui/knocked_icon.png");
|
||||||
|
private float totalPartialTicks;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
@Override
|
||||||
|
public void render(float partialTicks, ScaledResolution resolution) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renderNotifications(float partialTicks) {
|
||||||
|
totalPartialTicks += partialTicks;
|
||||||
|
for (KnockedPlayerData data : KnockedNotificationManager.getKnockedPlayerDatas()) {
|
||||||
|
Entity entity = client.world.getEntityByID(data.getPlayerId());
|
||||||
|
renderKnockedNotification(
|
||||||
|
entity != null ? entity.getPositionEyes(partialTicks).add(0, 1, 0) : data.getPosition(),
|
||||||
|
client.getRenderManager().playerViewX,
|
||||||
|
client.getRenderManager().playerViewY,
|
||||||
|
client.getRenderManager().options.thirdPersonView == 2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderKnockedNotification(Vec3d position, float pitch, float yaw, boolean isThirdPersonFrontal) {
|
||||||
|
Vec3d deltaPos = position.subtract(client.getRenderManager().viewerPosX, client.getRenderManager().viewerPosY, client.getRenderManager().viewerPosZ);
|
||||||
|
|
||||||
|
GlStateManager.pushMatrix();
|
||||||
|
GlStateManager.translate(deltaPos.x, deltaPos.y, deltaPos.z);
|
||||||
|
GlStateManager.rotate(-yaw, 0.0F, 1.0F, 0.0F);
|
||||||
|
GlStateManager.rotate((float)(isThirdPersonFrontal ? -1 : 1) * pitch, 1.0F, 0.0F, 0.0F);
|
||||||
|
float scale = (float) Math.max(deltaPos.length() / 8.0f, 1.0f) * (0.75f + MathHelper.abs((float) (MathHelper.sin(totalPartialTicks / 10F) / Math.PI)));
|
||||||
|
GlStateManager.scale(0.05F * scale, 0.05F * scale, 0.05F * scale);
|
||||||
|
GlStateManager.color(1f, 1f, 1f, 1f);
|
||||||
|
GlStateManager.disableCull();
|
||||||
|
GlStateManager.depthFunc(GL11.GL_ALWAYS);
|
||||||
|
|
||||||
|
client.getTextureManager().bindTexture(KNOCKED_ICON);
|
||||||
|
this.drawTexture(
|
||||||
|
-KNOCKED_ICON_SIZE / 2,
|
||||||
|
-KNOCKED_ICON_SIZE / 2,
|
||||||
|
KNOCKED_ICON_SIZE,
|
||||||
|
KNOCKED_ICON_SIZE
|
||||||
|
);
|
||||||
|
|
||||||
|
GlStateManager.depthFunc(GL11.GL_LEQUAL);
|
||||||
|
GlStateManager.enableCull();
|
||||||
|
GlStateManager.popMatrix();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package ru.octol1ttle.knockdowns.client.gui;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.FontRenderer;
|
||||||
|
import net.minecraft.client.gui.ScaledResolution;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.util.text.TextFormatting;
|
||||||
|
import ru.octol1ttle.knockdowns.common.KnockdownsUtils;
|
||||||
|
import ru.octol1ttle.knockdowns.common.ReviverTracker;
|
||||||
|
import ru.octol1ttle.knockdowns.common.data.IKnockdownsPlayerData;
|
||||||
|
|
||||||
|
public class ReviveGui extends KnockdownsBaseGui {
|
||||||
|
private static final Minecraft client = Minecraft.getMinecraft();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(float partialTicks, ScaledResolution resolution) {
|
||||||
|
EntityPlayer reviving =
|
||||||
|
client.pointedEntity instanceof EntityPlayer && ReviverTracker.getRevivers((EntityPlayer) client.pointedEntity).contains(client.player)
|
||||||
|
? (EntityPlayer) client.pointedEntity
|
||||||
|
: client.player;
|
||||||
|
if (IKnockdownsPlayerData.get(reviving).getReviveTimeLeft() == KnockdownsUtils.INITIAL_REVIVE_TIME_LEFT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
IKnockdownsPlayerData data = IKnockdownsPlayerData.get(reviving);
|
||||||
|
|
||||||
|
FontRenderer font = client.fontRenderer;
|
||||||
|
|
||||||
|
String timerText = String.format("%.1f", data.getReviveTimeLeft() / 20.0f);
|
||||||
|
float timerX = (resolution.getScaledWidth() - font.getStringWidth(timerText)) * 0.5f;
|
||||||
|
|
||||||
|
int reviverCount = ReviverTracker.getRevivers(reviving).size();
|
||||||
|
TextFormatting color;
|
||||||
|
if (reviverCount == 0) {
|
||||||
|
color = TextFormatting.RED;
|
||||||
|
} else if (reviverCount == 1) {
|
||||||
|
color = TextFormatting.WHITE;
|
||||||
|
} else {
|
||||||
|
color = TextFormatting.GREEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
String reviverCountText = "x" + reviverCount;
|
||||||
|
float reviveCountX = (resolution.getScaledWidth() - font.getStringWidth(reviverCountText)) * 0.5f;
|
||||||
|
|
||||||
|
font.drawStringWithShadow(color + timerText, timerX, resolution.getScaledHeight() * 0.5f + 5, 553648127);
|
||||||
|
font.drawStringWithShadow(color + reviverCountText, reviveCountX, resolution.getScaledHeight() * 0.5f + 14, 553648127);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,145 @@
|
||||||
|
package ru.octol1ttle.knockdowns.client.network;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||||
|
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
|
||||||
|
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
|
||||||
|
import net.minecraftforge.fml.relauncher.Side;
|
||||||
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||||
|
import ru.octol1ttle.knockdowns.client.communication.CalloutManager;
|
||||||
|
import ru.octol1ttle.knockdowns.client.communication.KnockedNotificationManager;
|
||||||
|
import ru.octol1ttle.knockdowns.client.util.DirectionalCallSound;
|
||||||
|
import ru.octol1ttle.knockdowns.common.ReviverTracker;
|
||||||
|
import ru.octol1ttle.knockdowns.common.data.IKnockdownsPlayerData;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.s2c.PlayerCalloutS2CPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.s2c.PlayerKnockedDownS2CPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.s2c.SynchronizePlayerDataS2CPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.s2c.SynchronizeReviversS2CPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.registry.KnockdownsSoundEvents;
|
||||||
|
|
||||||
|
import static ru.octol1ttle.knockdowns.common.KnockdownsUtils.INITIAL_REVIVE_TIME_LEFT;
|
||||||
|
|
||||||
|
public class KnockdownsClientPacketHandler {
|
||||||
|
public static class Callout implements IMessageHandler<PlayerCalloutS2CPacket, IMessage> {
|
||||||
|
private static final Minecraft client = Minecraft.getMinecraft();
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
@Override
|
||||||
|
public IMessage onMessage(PlayerCalloutS2CPacket message, MessageContext ctx) {
|
||||||
|
client.addScheduledTask(() -> {
|
||||||
|
if (CalloutManager.addOrUpdateCallout(message)) {
|
||||||
|
CalloutManager.playCalloutSound(message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PlayerKnockedDown implements IMessageHandler<PlayerKnockedDownS2CPacket, IMessage> {
|
||||||
|
private static final Minecraft client = Minecraft.getMinecraft();
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
@Override
|
||||||
|
public IMessage onMessage(PlayerKnockedDownS2CPacket message, MessageContext ctx) {
|
||||||
|
client.addScheduledTask(() -> {
|
||||||
|
EntityPlayer entity = (EntityPlayer) client.world.getEntityByID(message.playerId);
|
||||||
|
if (entity != null) {
|
||||||
|
IKnockdownsPlayerData data = IKnockdownsPlayerData.get(entity);
|
||||||
|
data.setKnockedDown(true);
|
||||||
|
data.setReviveTimeLeft(INITIAL_REVIVE_TIME_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client.player.dimension == message.dimensionId) {
|
||||||
|
client.getSoundHandler().playSound(new DirectionalCallSound(KnockdownsSoundEvents.KNOCKED_DOWN, entity, message.position));
|
||||||
|
KnockedNotificationManager.addKnockedNotification(message.playerId, message.position);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SynchronizePlayerData {
|
||||||
|
private static final Minecraft client = Minecraft.getMinecraft();
|
||||||
|
|
||||||
|
public static class KnockedDown implements IMessageHandler<SynchronizePlayerDataS2CPacket.KnockedDown, IMessage> {
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
@Override
|
||||||
|
public IMessage onMessage(SynchronizePlayerDataS2CPacket.KnockedDown message, MessageContext ctx) {
|
||||||
|
client.addScheduledTask(() -> {
|
||||||
|
EntityPlayer entity = (EntityPlayer) client.world.getEntityByID(message.playerId);
|
||||||
|
if (entity != null) {
|
||||||
|
IKnockdownsPlayerData data = IKnockdownsPlayerData.get(entity);
|
||||||
|
data.setKnockedDown(message.knockedDown);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ReviveTimeLeft implements IMessageHandler<SynchronizePlayerDataS2CPacket.ReviveTimeLeft, IMessage> {
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
@Override
|
||||||
|
public IMessage onMessage(SynchronizePlayerDataS2CPacket.ReviveTimeLeft message, MessageContext ctx) {
|
||||||
|
client.addScheduledTask(() -> {
|
||||||
|
EntityPlayer entity = (EntityPlayer) client.world.getEntityByID(message.playerId);
|
||||||
|
if (entity != null) {
|
||||||
|
IKnockdownsPlayerData data = IKnockdownsPlayerData.get(entity);
|
||||||
|
data.setReviveTimeLeft(message.reviveTimeLeft);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Full implements IMessageHandler<SynchronizePlayerDataS2CPacket.Full, IMessage> {
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
@Override
|
||||||
|
public IMessage onMessage(SynchronizePlayerDataS2CPacket.Full message, MessageContext ctx) {
|
||||||
|
client.addScheduledTask(() -> {
|
||||||
|
EntityPlayer entity = (EntityPlayer) client.world.getEntityByID(message.playerId);
|
||||||
|
if (entity != null) {
|
||||||
|
IKnockdownsPlayerData data = IKnockdownsPlayerData.get(entity);
|
||||||
|
data.setKnockedDown(message.knockedDown);
|
||||||
|
data.setReviveTimeLeft(message.reviveTimeLeft);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SynchronizeRevivers {
|
||||||
|
private static final Minecraft client = Minecraft.getMinecraft();
|
||||||
|
|
||||||
|
public static class Add implements IMessageHandler<SynchronizeReviversS2CPacket.Add, IMessage> {
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
@Override
|
||||||
|
public IMessage onMessage(SynchronizeReviversS2CPacket.Add message, MessageContext ctx) {
|
||||||
|
client.addScheduledTask(() -> {
|
||||||
|
EntityPlayer knocked = (EntityPlayer) client.world.getEntityByID(message.knockedId);
|
||||||
|
EntityPlayer reviver = (EntityPlayer) client.world.getEntityByID(message.reviverId);
|
||||||
|
if (knocked != null && reviver != null) {
|
||||||
|
ReviverTracker.startReviving(knocked, reviver);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Remove implements IMessageHandler<SynchronizeReviversS2CPacket.Remove, IMessage> {
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
@Override
|
||||||
|
public IMessage onMessage(SynchronizeReviversS2CPacket.Remove message, MessageContext ctx) {
|
||||||
|
client.addScheduledTask(() -> {
|
||||||
|
EntityPlayer knocked = (EntityPlayer) client.world.getEntityByID(message.knockedId);
|
||||||
|
EntityPlayer reviver = (EntityPlayer) client.world.getEntityByID(message.reviverId);
|
||||||
|
if (knocked != null && reviver != null) {
|
||||||
|
ReviverTracker.stopReviving(knocked, reviver);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package ru.octol1ttle.knockdowns.client.util;
|
||||||
|
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraftforge.fml.relauncher.Side;
|
||||||
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||||
|
import ru.octol1ttle.knockdowns.common.communication.CalloutType;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class Callout {
|
||||||
|
private final Vec3d position;
|
||||||
|
private final CalloutType type;
|
||||||
|
private final long receiveTime;
|
||||||
|
|
||||||
|
public Callout(Vec3d position, CalloutType type, long receiveTime) {
|
||||||
|
this.position = position;
|
||||||
|
this.type = type;
|
||||||
|
this.receiveTime = receiveTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec3d getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CalloutType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getReceiveTime() {
|
||||||
|
return receiveTime;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package ru.octol1ttle.knockdowns.client.util;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.audio.MovingSound;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.util.SoundCategory;
|
||||||
|
import net.minecraft.util.SoundEvent;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraftforge.fml.relauncher.Side;
|
||||||
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class DirectionalCallSound extends MovingSound {
|
||||||
|
private final @Nullable Entity entity;
|
||||||
|
private final Vec3d position;
|
||||||
|
private int time;
|
||||||
|
|
||||||
|
public DirectionalCallSound(SoundEvent event, @Nullable Entity entity, Vec3d position) {
|
||||||
|
super(event, SoundCategory.PLAYERS);
|
||||||
|
this.entity = entity;
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
this.time++;
|
||||||
|
if (this.time > 40 || this.entity != null && this.entity.isDead) {
|
||||||
|
this.donePlaying = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Minecraft client = Minecraft.getMinecraft();
|
||||||
|
Vec3d calloutPos = this.entity != null ? this.entity.getPositionVector() : this.position;
|
||||||
|
Vec3d directionVec = calloutPos.subtract(client.player.getPositionVector()).normalize();
|
||||||
|
Vec3d finalPos = client.player.getPositionVector().add(directionVec);
|
||||||
|
|
||||||
|
this.xPosF = (float) finalPos.x;
|
||||||
|
this.yPosF = (float) finalPos.y;
|
||||||
|
this.zPosF = (float) finalPos.z;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package ru.octol1ttle.knockdowns.client.util;
|
||||||
|
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
public class KnockedPlayerData {
|
||||||
|
private final int playerId;
|
||||||
|
private final Vec3d position;
|
||||||
|
private final long receiveTime;
|
||||||
|
|
||||||
|
public KnockedPlayerData(int playerId, Vec3d position, long receiveTime) {
|
||||||
|
this.playerId = playerId;
|
||||||
|
this.position = position;
|
||||||
|
this.receiveTime = receiveTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPlayerId() {
|
||||||
|
return playerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec3d getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getReceiveTime() {
|
||||||
|
return receiveTime;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common;
|
||||||
|
|
||||||
|
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
|
||||||
|
|
||||||
|
public interface IClientProxy {
|
||||||
|
void onFMLInit(FMLInitializationEvent event);
|
||||||
|
|
||||||
|
class Dummy implements IClientProxy {
|
||||||
|
@Override
|
||||||
|
public void onFMLInit(FMLInitializationEvent event) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,239 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import net.minecraft.client.resources.I18n;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityLiving;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
|
import net.minecraft.init.MobEffects;
|
||||||
|
import net.minecraft.potion.PotionEffect;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.util.DamageSource;
|
||||||
|
import net.minecraft.util.EnumActionResult;
|
||||||
|
import net.minecraft.util.SoundEvent;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.text.TextComponentTranslation;
|
||||||
|
import net.minecraftforge.event.AttachCapabilitiesEvent;
|
||||||
|
import net.minecraftforge.event.RegistryEvent;
|
||||||
|
import net.minecraftforge.event.entity.living.LivingDeathEvent;
|
||||||
|
import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent;
|
||||||
|
import net.minecraftforge.event.entity.player.AttackEntityEvent;
|
||||||
|
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||||
|
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
|
||||||
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent;
|
||||||
|
import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedOutEvent;
|
||||||
|
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||||
|
import ru.octol1ttle.knockdowns.Tags;
|
||||||
|
import ru.octol1ttle.knockdowns.common.data.IKnockdownsPlayerData;
|
||||||
|
import ru.octol1ttle.knockdowns.common.data.KnockdownsCapability;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.KnockdownsNetwork;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.s2c.PlayerKnockedDownS2CPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.s2c.SynchronizePlayerDataS2CPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.s2c.SynchronizeReviversS2CPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.registry.KnockdownsSoundEvents;
|
||||||
|
|
||||||
|
import static ru.octol1ttle.knockdowns.common.KnockdownsUtils.INITIAL_REVIVE_TIME_LEFT;
|
||||||
|
import static ru.octol1ttle.knockdowns.common.KnockdownsUtils.KNOCKED_HURT_PERIOD;
|
||||||
|
import static ru.octol1ttle.knockdowns.common.KnockdownsUtils.KNOCKED_INVULNERABILITY_TICKS;
|
||||||
|
import static ru.octol1ttle.knockdowns.common.KnockdownsUtils.KNOCKED_TENACITY;
|
||||||
|
import static ru.octol1ttle.knockdowns.common.KnockdownsUtils.allPlayersKnocked;
|
||||||
|
import static ru.octol1ttle.knockdowns.common.KnockdownsUtils.resetKnockedState;
|
||||||
|
|
||||||
|
@Mod.EventBusSubscriber(modid = Tags.MOD_ID)
|
||||||
|
public class KnockdownsCommonEventListener {
|
||||||
|
public static void onFMLInit(FMLInitializationEvent event) {
|
||||||
|
KnockdownsNetwork.registerPackets();
|
||||||
|
KnockdownsCapability.register();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onSoundsRegister(RegistryEvent.Register<SoundEvent> event) {
|
||||||
|
event.getRegistry().register(KnockdownsSoundEvents.CALLOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onCapabilitiesAttach(AttachCapabilitiesEvent<Entity> event) {
|
||||||
|
if (event.getObject() instanceof EntityPlayer) {
|
||||||
|
event.addCapability(KnockdownsCapability.ID, new KnockdownsCapability());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onPlayerTick(TickEvent.PlayerTickEvent event) {
|
||||||
|
MinecraftServer server = event.player.getServer();
|
||||||
|
if (event.phase == TickEvent.Phase.START || server == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EntityPlayerMP player = (EntityPlayerMP) event.player;
|
||||||
|
IKnockdownsPlayerData data = IKnockdownsPlayerData.get(player);
|
||||||
|
if (!data.isKnockedDown()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allPlayersKnocked(server, player)) {
|
||||||
|
player.attackEntityFrom(DamageSource.GENERIC, player.getMaxHealth());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<EntityPlayer> revivers = ReviverTracker.getRevivers(player);
|
||||||
|
if (!revivers.isEmpty()) {
|
||||||
|
data.setReviveTimeLeft(data.getReviveTimeLeft() - revivers.size());
|
||||||
|
KnockdownsNetwork.sendToMultiple(
|
||||||
|
new SynchronizePlayerDataS2CPacket.ReviveTimeLeft(player.getEntityId(), data.getReviveTimeLeft()),
|
||||||
|
revivers,
|
||||||
|
player
|
||||||
|
);
|
||||||
|
|
||||||
|
if (data.getReviveTimeLeft() <= 0) {
|
||||||
|
resetKnockedState(player, data);
|
||||||
|
|
||||||
|
player.setEntityInvulnerable(false);
|
||||||
|
player.setHealth(player.getMaxHealth() * 0.3f);
|
||||||
|
player.setAbsorptionAmount(0.0f);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int oldReviveTimeLeft = data.getReviveTimeLeft();
|
||||||
|
data.setReviveTimeLeft(Math.min(INITIAL_REVIVE_TIME_LEFT, oldReviveTimeLeft + 1));
|
||||||
|
if (data.getReviveTimeLeft() != oldReviveTimeLeft) {
|
||||||
|
KnockdownsNetwork.sendToPlayer(
|
||||||
|
new SynchronizePlayerDataS2CPacket.ReviveTimeLeft(player.getEntityId(), data.getReviveTimeLeft()),
|
||||||
|
player
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.setTicksKnocked(data.getTicksKnocked() + 1);
|
||||||
|
|
||||||
|
int period = MathHelper.floor(KNOCKED_HURT_PERIOD * 20);
|
||||||
|
if (data.getTicksKnocked() >= KNOCKED_INVULNERABILITY_TICKS && data.getTicksKnocked() % period == 0) {
|
||||||
|
player.setEntityInvulnerable(false);
|
||||||
|
player.attackEntityFrom(DamageSource.GENERIC, player.getMaxHealth() / (KNOCKED_TENACITY / KNOCKED_HURT_PERIOD));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onPlayerDeath(LivingDeathEvent event) {
|
||||||
|
if (!(event.getEntityLiving() instanceof EntityPlayerMP)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityPlayerMP player = (EntityPlayerMP) event.getEntityLiving();
|
||||||
|
IKnockdownsPlayerData data = player.getCapability(KnockdownsCapability.CAPABILITY, null);
|
||||||
|
if (data == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.isKnockedDown() || allPlayersKnocked(player.getServer(), player)) {
|
||||||
|
ReviverTracker.clearRevivers(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.clearActivePotions();
|
||||||
|
player.setEntityInvulnerable(true);
|
||||||
|
player.setHealth(1.0f);
|
||||||
|
player.setAbsorptionAmount(player.getMaxHealth() - 1.0f);
|
||||||
|
player.extinguish();
|
||||||
|
player.setAir(300);
|
||||||
|
player.clearElytraFlying();
|
||||||
|
|
||||||
|
player.addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, 6000, 3));
|
||||||
|
|
||||||
|
Entity trueSource = event.getSource().getTrueSource();
|
||||||
|
if (trueSource instanceof EntityLiving) {
|
||||||
|
((EntityLiving) trueSource).setAttackTarget(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.setKnockedDown(true);
|
||||||
|
data.setReviveTimeLeft(INITIAL_REVIVE_TIME_LEFT);
|
||||||
|
data.setTicksKnocked(0);
|
||||||
|
|
||||||
|
KnockdownsNetwork.sendToAll(new PlayerKnockedDownS2CPacket(player.getEntityId(), player.dimension, player.getPositionEyes(1).add(0, 1, 0)));
|
||||||
|
|
||||||
|
TextComponentTranslation deathMessage = (TextComponentTranslation) player.getCombatTracker().getDeathMessage();
|
||||||
|
|
||||||
|
String knockdownKey = deathMessage.getKey().replace("death.", "knockdown.");
|
||||||
|
player.getServer().getPlayerList().sendMessage(
|
||||||
|
I18n.hasKey(knockdownKey)
|
||||||
|
? new TextComponentTranslation(knockdownKey, deathMessage.getFormatArgs())
|
||||||
|
: deathMessage,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
event.setCanceled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onMobTarget(LivingSetAttackTargetEvent event) {
|
||||||
|
if (event.getTarget() instanceof EntityPlayer && IKnockdownsPlayerData.get((EntityPlayer) event.getTarget()).isKnockedDown()) {
|
||||||
|
((EntityLiving)event.getEntityLiving()).setAttackTarget(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onPlayerStartTracking(PlayerEvent.StartTracking event) {
|
||||||
|
if (event.getTarget() instanceof EntityPlayerMP) {
|
||||||
|
IKnockdownsPlayerData data = IKnockdownsPlayerData.get((EntityPlayer) event.getTarget());
|
||||||
|
if (data.isKnockedDown()) {
|
||||||
|
KnockdownsNetwork.sendToPlayer(
|
||||||
|
new SynchronizePlayerDataS2CPacket.KnockedDown(
|
||||||
|
event.getTarget().getEntityId(),
|
||||||
|
data.isKnockedDown()
|
||||||
|
),
|
||||||
|
(EntityPlayerMP) event.getEntityPlayer()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onKnockedAttack(AttackEntityEvent event) {
|
||||||
|
if (IKnockdownsPlayerData.get(event.getEntityPlayer()).isKnockedDown()) {
|
||||||
|
event.setCanceled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onKnockedInteraction(PlayerInteractEvent event) {
|
||||||
|
if (IKnockdownsPlayerData.get(event.getEntityPlayer()).isKnockedDown()) {
|
||||||
|
if (!(event instanceof PlayerInteractEvent.RightClickBlock) && event.isCancelable()) {
|
||||||
|
event.setCanceled(true);
|
||||||
|
event.setCancellationResult(EnumActionResult.FAIL);
|
||||||
|
}
|
||||||
|
} else if (event instanceof PlayerInteractEvent.EntityInteract) {
|
||||||
|
onPlayerInteraction((PlayerInteractEvent.EntityInteract) event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onPlayerInteraction(PlayerInteractEvent.EntityInteract event) {
|
||||||
|
if (event.getEntityLiving() instanceof EntityPlayerMP) {
|
||||||
|
EntityPlayerMP knocked = (EntityPlayerMP) event.getEntityLiving();
|
||||||
|
if (IKnockdownsPlayerData.get(knocked).isKnockedDown()) {
|
||||||
|
KnockdownsNetwork.sendToMultiple(
|
||||||
|
new SynchronizeReviversS2CPacket.Add(event.getEntityLiving().getEntityId(), event.getEntityPlayer().getEntityId()),
|
||||||
|
ReviverTracker.getRevivers(knocked),
|
||||||
|
knocked
|
||||||
|
);
|
||||||
|
ReviverTracker.startReviving(knocked, event.getEntityPlayer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onPlayerJoin(PlayerLoggedInEvent event) {
|
||||||
|
IKnockdownsPlayerData data = IKnockdownsPlayerData.get(event.player);
|
||||||
|
KnockdownsNetwork.sendToPlayer(
|
||||||
|
new SynchronizePlayerDataS2CPacket.Full(event.player.getEntityId(), data.isKnockedDown(), data.getReviveTimeLeft()),
|
||||||
|
(EntityPlayerMP) event.player
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onPlayerLeave(PlayerLoggedOutEvent event) {
|
||||||
|
ReviverTracker.clearRevivers(event.player);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
|
||||||
|
import zone.rong.mixinbooter.IEarlyMixinLoader;
|
||||||
|
|
||||||
|
@IFMLLoadingPlugin.MCVersion("1.12.2")
|
||||||
|
public class KnockdownsFMLLoadingPlugin implements IFMLLoadingPlugin, IEarlyMixinLoader {
|
||||||
|
@Override
|
||||||
|
public String[] getASMTransformerClass() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModContainerClass() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getSetupClass() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void injectData(Map<String, Object> data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAccessTransformerClass() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getMixinConfigs() {
|
||||||
|
ArrayList<String> list = new ArrayList<>();
|
||||||
|
list.add("mixins.knockdowns.json");
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common;
|
||||||
|
|
||||||
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
import net.minecraftforge.fml.common.SidedProxy;
|
||||||
|
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import ru.octol1ttle.knockdowns.Tags;
|
||||||
|
|
||||||
|
@Mod(modid = Tags.MOD_ID, name = Tags.MOD_NAME, version = Tags.VERSION)
|
||||||
|
public class KnockdownsMod {
|
||||||
|
public static final Logger LOGGER = LogManager.getLogger(Tags.MOD_NAME);
|
||||||
|
@SidedProxy(clientSide = "ru.octol1ttle.knockdowns.client.ClientProxy", serverSide = "ru.octol1ttle.knockdowns.common.IClientProxy$Dummy")
|
||||||
|
public static IClientProxy clientProxy;
|
||||||
|
|
||||||
|
@Mod.EventHandler
|
||||||
|
public void onFMLInit(FMLInitializationEvent event) {
|
||||||
|
clientProxy.onFMLInit(event);
|
||||||
|
KnockdownsCommonEventListener.onFMLInit(event);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common;
|
||||||
|
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
|
import net.minecraft.init.MobEffects;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import ru.octol1ttle.knockdowns.common.data.IKnockdownsPlayerData;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.KnockdownsNetwork;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.s2c.SynchronizePlayerDataS2CPacket;
|
||||||
|
|
||||||
|
public class KnockdownsUtils {
|
||||||
|
public static final int INITIAL_REVIVE_TIME_LEFT = 200;
|
||||||
|
public static final float KNOCKED_INVULNERABILITY_TICKS = 3.0f * 20.0f;
|
||||||
|
public static final float KNOCKED_HURT_PERIOD = 1.2f;
|
||||||
|
public static final float KNOCKED_TENACITY = 60.0f;
|
||||||
|
|
||||||
|
public static boolean allPlayersKnocked(MinecraftServer server, EntityPlayer except) {
|
||||||
|
for (EntityPlayer player : server.getPlayerList().getPlayers()) {
|
||||||
|
if (player.equals(except)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
IKnockdownsPlayerData data = IKnockdownsPlayerData.get(player);
|
||||||
|
if (player.isEntityAlive() && !data.isKnockedDown()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetKnockedState(EntityPlayerMP player, IKnockdownsPlayerData data) {
|
||||||
|
player.removePotionEffect(MobEffects.SLOWNESS);
|
||||||
|
data.setKnockedDown(false);
|
||||||
|
data.setReviveTimeLeft(INITIAL_REVIVE_TIME_LEFT);
|
||||||
|
data.setTicksKnocked(0);
|
||||||
|
|
||||||
|
KnockdownsNetwork.sendToTrackingAndSelf(
|
||||||
|
new SynchronizePlayerDataS2CPacket.KnockedDown(player.getEntityId(), data.isKnockedDown()),
|
||||||
|
player
|
||||||
|
);
|
||||||
|
|
||||||
|
ReviverTracker.clearRevivers(player);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
|
||||||
|
public class ReviverTracker {
|
||||||
|
private static final Map<EntityPlayer, List<EntityPlayer>> knockedToReviversMap = new HashMap<>();
|
||||||
|
|
||||||
|
public static void startReviving(EntityPlayer knocked, EntityPlayer reviver) {
|
||||||
|
getRevivers(knocked).add(reviver);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void stopReviving(EntityPlayer knocked, EntityPlayer reviver) {
|
||||||
|
getRevivers(knocked).remove(reviver);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearRevivers(EntityPlayer knocked) {
|
||||||
|
getRevivers(knocked).clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<EntityPlayer> getRevivers(EntityPlayer knocked) {
|
||||||
|
return knockedToReviversMap.computeIfAbsent(knocked, player -> new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Set<Map.Entry<EntityPlayer, List<EntityPlayer>>> getAllRevivers() {
|
||||||
|
return knockedToReviversMap.entrySet();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.communication;
|
||||||
|
|
||||||
|
public enum CalloutType {
|
||||||
|
DANGER((byte) 0, "knockdowns.callout.danger"),
|
||||||
|
BOOYAH((byte) 1, "knockdowns.callout.booyah"),
|
||||||
|
THIS_WAY((byte) 2, "knockdowns.callout.this_way"),
|
||||||
|
OUCH((byte) 3, "knockdowns.callout.ouch"),
|
||||||
|
HELP((byte) 4, "knockdowns.callout.help");
|
||||||
|
|
||||||
|
private final byte id;
|
||||||
|
private final String textKey;
|
||||||
|
|
||||||
|
CalloutType(byte id, String textKey) {
|
||||||
|
this.id = id;
|
||||||
|
this.textKey = textKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTextKey() {
|
||||||
|
return textKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CalloutType byId(byte id) {
|
||||||
|
for (CalloutType type : CalloutType.values()) {
|
||||||
|
if (id == type.getId()) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.data;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraftforge.common.util.INBTSerializable;
|
||||||
|
|
||||||
|
public interface IKnockdownsPlayerData extends INBTSerializable<NBTTagCompound> {
|
||||||
|
boolean isKnockedDown();
|
||||||
|
void setKnockedDown(boolean knockedDown);
|
||||||
|
|
||||||
|
int getReviveTimeLeft();
|
||||||
|
void setReviveTimeLeft(int reviveTimeLeft);
|
||||||
|
|
||||||
|
int getTicksKnocked();
|
||||||
|
void setTicksKnocked(int ticksKnocked);
|
||||||
|
|
||||||
|
static IKnockdownsPlayerData get(EntityPlayer player) {
|
||||||
|
return Objects.requireNonNull(player.getCapability(KnockdownsCapability.CAPABILITY, null));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.data;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import net.minecraft.nbt.NBTBase;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.util.EnumFacing;
|
||||||
|
import net.minecraft.util.LazyLoadBase;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
|
import net.minecraftforge.common.capabilities.CapabilityInject;
|
||||||
|
import net.minecraftforge.common.capabilities.CapabilityManager;
|
||||||
|
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
||||||
|
import ru.octol1ttle.knockdowns.Tags;
|
||||||
|
|
||||||
|
public class KnockdownsCapability implements ICapabilitySerializable<NBTTagCompound> {
|
||||||
|
@CapabilityInject(IKnockdownsPlayerData.class)
|
||||||
|
public static Capability<IKnockdownsPlayerData> CAPABILITY;
|
||||||
|
public static final ResourceLocation ID = new ResourceLocation(Tags.MOD_ID, "data");
|
||||||
|
|
||||||
|
private KnockdownsPlayerData playerData = null;
|
||||||
|
private final LazyLoadBase<KnockdownsPlayerData> lazy = new LazyLoadBase<KnockdownsPlayerData>() {
|
||||||
|
@Override
|
||||||
|
protected KnockdownsPlayerData load() {
|
||||||
|
return playerData == null ? (playerData = new KnockdownsPlayerData()) : playerData;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static void register() {
|
||||||
|
CapabilityManager.INSTANCE.register(IKnockdownsPlayerData.class, new Capability.IStorage<IKnockdownsPlayerData>() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public NBTBase writeNBT(Capability<IKnockdownsPlayerData> capability, IKnockdownsPlayerData instance, EnumFacing side) {
|
||||||
|
return instance.serializeNBT();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readNBT(Capability<IKnockdownsPlayerData> capability, IKnockdownsPlayerData instance, EnumFacing side, NBTBase nbt) {
|
||||||
|
instance.deserializeNBT((NBTTagCompound) nbt);
|
||||||
|
}
|
||||||
|
}, KnockdownsPlayerData::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {
|
||||||
|
return capability == CAPABILITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {
|
||||||
|
return capability == CAPABILITY ? (T) lazy.getValue() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NBTTagCompound serializeNBT() {
|
||||||
|
return lazy.getValue().serializeNBT();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deserializeNBT(NBTTagCompound nbt) {
|
||||||
|
lazy.getValue().deserializeNBT(nbt);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.data;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import ru.octol1ttle.knockdowns.common.KnockdownsUtils;
|
||||||
|
|
||||||
|
public class KnockdownsPlayerData implements IKnockdownsPlayerData {
|
||||||
|
private static final String KEY_KNOCKED_DOWN = "KnockedDown";
|
||||||
|
private static final String KEY_REVIVE_TIME_LEFT = "ReviveTimeLeft";
|
||||||
|
private static final String KEY_TICKS_KNOCKED = "TicksKnocked";
|
||||||
|
private boolean knockedDown = false;
|
||||||
|
private int reviveTimeLeft = KnockdownsUtils.INITIAL_REVIVE_TIME_LEFT;
|
||||||
|
private int ticksKnocked = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isKnockedDown() {
|
||||||
|
return this.knockedDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setKnockedDown(boolean knockedDown) {
|
||||||
|
this.knockedDown = knockedDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getReviveTimeLeft() {
|
||||||
|
return this.reviveTimeLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReviveTimeLeft(int reviveTimeLeft) {
|
||||||
|
this.reviveTimeLeft = reviveTimeLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTicksKnocked() {
|
||||||
|
return this.ticksKnocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTicksKnocked(int ticksKnocked) {
|
||||||
|
this.ticksKnocked = ticksKnocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NBTTagCompound serializeNBT() {
|
||||||
|
NBTTagCompound nbt = new NBTTagCompound();
|
||||||
|
nbt.setBoolean(KEY_KNOCKED_DOWN, this.knockedDown);
|
||||||
|
nbt.setInteger(KEY_REVIVE_TIME_LEFT, this.reviveTimeLeft);
|
||||||
|
nbt.setInteger(KEY_TICKS_KNOCKED, this.ticksKnocked);
|
||||||
|
return nbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deserializeNBT(NBTTagCompound nbt) {
|
||||||
|
this.knockedDown = nbt.getBoolean(KEY_KNOCKED_DOWN);
|
||||||
|
this.reviveTimeLeft = nbt.getInteger(KEY_REVIVE_TIME_LEFT);
|
||||||
|
this.ticksKnocked = nbt.getInteger(KEY_TICKS_KNOCKED);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.mixins;
|
||||||
|
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
import ru.octol1ttle.knockdowns.common.KnockdownsUtils;
|
||||||
|
import ru.octol1ttle.knockdowns.common.data.IKnockdownsPlayerData;
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantValue")
|
||||||
|
@Mixin(EntityLivingBase.class)
|
||||||
|
public abstract class EntityLivingBaseMixin extends Entity {
|
||||||
|
public EntityLivingBaseMixin(World worldIn) {
|
||||||
|
super(worldIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "checkTotemDeathProtection", at = @At("RETURN"))
|
||||||
|
public void onTotemActivation(CallbackInfoReturnable<Boolean> cir) {
|
||||||
|
if (cir.getReturnValue() && ((Object) this) instanceof EntityPlayerMP) {
|
||||||
|
EntityPlayerMP player = (EntityPlayerMP) (Object) this;
|
||||||
|
IKnockdownsPlayerData data = IKnockdownsPlayerData.get(player);
|
||||||
|
if (data.isKnockedDown()) {
|
||||||
|
KnockdownsUtils.resetKnockedState(player, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.mixins;
|
||||||
|
|
||||||
|
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import ru.octol1ttle.knockdowns.common.data.IKnockdownsPlayerData;
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantValue")
|
||||||
|
@Mixin(EntityPlayer.class)
|
||||||
|
public class EntityPlayerMixin {
|
||||||
|
@ModifyReturnValue(method = "shouldHeal", at = @At("RETURN"))
|
||||||
|
private boolean dontHealIfKnockedDown(boolean original) {
|
||||||
|
if (((Object) this) instanceof EntityPlayer) {
|
||||||
|
EntityPlayer player = (EntityPlayer) (Object) this;
|
||||||
|
if (IKnockdownsPlayerData.get(player).isKnockedDown()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.network;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
|
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
||||||
|
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||||
|
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
|
||||||
|
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
|
||||||
|
import net.minecraftforge.fml.relauncher.Side;
|
||||||
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||||
|
import ru.octol1ttle.knockdowns.Tags;
|
||||||
|
import ru.octol1ttle.knockdowns.client.network.KnockdownsClientPacketHandler;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.c2s.CancelReviveC2SPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.c2s.PlayerCalloutC2SPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.s2c.PlayerCalloutS2CPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.s2c.PlayerKnockedDownS2CPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.s2c.SynchronizePlayerDataS2CPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.s2c.SynchronizeReviversS2CPacket;
|
||||||
|
|
||||||
|
public class KnockdownsNetwork {
|
||||||
|
private static final SimpleNetworkWrapper INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(Tags.MOD_ID);
|
||||||
|
private static int packetId = 0;
|
||||||
|
|
||||||
|
public static void registerPackets() {
|
||||||
|
INSTANCE.registerMessage(KnockdownsServerPacketHandler.Callout.class, PlayerCalloutC2SPacket.class, packetId++, Side.SERVER);
|
||||||
|
INSTANCE.registerMessage(KnockdownsServerPacketHandler.CancelRevive.class, CancelReviveC2SPacket.class, packetId++, Side.SERVER);
|
||||||
|
|
||||||
|
INSTANCE.registerMessage(KnockdownsClientPacketHandler.Callout.class, PlayerCalloutS2CPacket.class, packetId++, Side.CLIENT);
|
||||||
|
INSTANCE.registerMessage(KnockdownsClientPacketHandler.PlayerKnockedDown.class, PlayerKnockedDownS2CPacket.class, packetId++, Side.CLIENT);
|
||||||
|
INSTANCE.registerMessage(KnockdownsClientPacketHandler.SynchronizePlayerData.KnockedDown.class, SynchronizePlayerDataS2CPacket.KnockedDown.class, packetId++, Side.CLIENT);
|
||||||
|
INSTANCE.registerMessage(KnockdownsClientPacketHandler.SynchronizePlayerData.ReviveTimeLeft.class, SynchronizePlayerDataS2CPacket.ReviveTimeLeft.class, packetId++, Side.CLIENT);
|
||||||
|
INSTANCE.registerMessage(KnockdownsClientPacketHandler.SynchronizePlayerData.Full.class, SynchronizePlayerDataS2CPacket.Full.class, packetId++, Side.CLIENT);
|
||||||
|
INSTANCE.registerMessage(KnockdownsClientPacketHandler.SynchronizeRevivers.Add.class, SynchronizeReviversS2CPacket.Add.class, packetId++, Side.CLIENT);
|
||||||
|
INSTANCE.registerMessage(KnockdownsClientPacketHandler.SynchronizeRevivers.Remove.class, SynchronizeReviversS2CPacket.Remove.class, packetId++, Side.CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public static void sendToServer(IMessage message) {
|
||||||
|
INSTANCE.sendToServer(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendToAll(IMessage message) {
|
||||||
|
INSTANCE.sendToAll(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendToDimension(IMessage message, MessageContext context) {
|
||||||
|
INSTANCE.sendToDimension(message, context.getServerHandler().player.dimension);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendToTrackingAndSelf(IMessage message, EntityPlayerMP player) {
|
||||||
|
sendToPlayer(message, player);
|
||||||
|
sendToTracking(message, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendToMultiple(IMessage message, List<EntityPlayer> players, EntityPlayerMP player) {
|
||||||
|
sendToPlayer(message, player);
|
||||||
|
for (EntityPlayer listed : players) {
|
||||||
|
sendToPlayer(message, (EntityPlayerMP) listed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendToTracking(IMessage message, Entity entity) {
|
||||||
|
INSTANCE.sendToAllTracking(message, entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendToPlayer(IMessage message, EntityPlayerMP player) {
|
||||||
|
INSTANCE.sendTo(message, player);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.network;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
|
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||||
|
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
|
||||||
|
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
|
||||||
|
import ru.octol1ttle.knockdowns.common.ReviverTracker;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.c2s.CancelReviveC2SPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.c2s.PlayerCalloutC2SPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.s2c.PlayerCalloutS2CPacket;
|
||||||
|
import ru.octol1ttle.knockdowns.common.network.packets.s2c.SynchronizeReviversS2CPacket;
|
||||||
|
|
||||||
|
public class KnockdownsServerPacketHandler {
|
||||||
|
public static class Callout implements IMessageHandler<PlayerCalloutC2SPacket, IMessage> {
|
||||||
|
@Override
|
||||||
|
public IMessage onMessage(PlayerCalloutC2SPacket message, MessageContext ctx) {
|
||||||
|
KnockdownsNetwork.sendToDimension(
|
||||||
|
new PlayerCalloutS2CPacket(
|
||||||
|
ctx.getServerHandler().player.getEntityId(),
|
||||||
|
ctx.getServerHandler().player.getPositionEyes(1).add(0, 1, 0),
|
||||||
|
message.type
|
||||||
|
),
|
||||||
|
ctx
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CancelRevive implements IMessageHandler<CancelReviveC2SPacket, IMessage> {
|
||||||
|
@Override
|
||||||
|
public IMessage onMessage(CancelReviveC2SPacket message, MessageContext ctx) {
|
||||||
|
EntityPlayerMP player = ctx.getServerHandler().player;
|
||||||
|
for (Map.Entry<EntityPlayer, List<EntityPlayer>> revivers : ReviverTracker.getAllRevivers()) {
|
||||||
|
if (revivers.getValue().contains(player)) {
|
||||||
|
revivers.getValue().remove(player);
|
||||||
|
KnockdownsNetwork.sendToMultiple(
|
||||||
|
new SynchronizeReviversS2CPacket.Remove(revivers.getKey().getEntityId(), player.getEntityId()),
|
||||||
|
revivers.getValue(),
|
||||||
|
(EntityPlayerMP) revivers.getKey()
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.network.packets.c2s;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||||
|
|
||||||
|
public class CancelReviveC2SPacket implements IMessage {
|
||||||
|
public CancelReviveC2SPacket() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toBytes(ByteBuf buf) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromBytes(ByteBuf buf) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.network.packets.c2s;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||||
|
import ru.octol1ttle.knockdowns.common.communication.CalloutType;
|
||||||
|
|
||||||
|
public class PlayerCalloutC2SPacket implements IMessage {
|
||||||
|
public PlayerCalloutC2SPacket() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public CalloutType type;
|
||||||
|
public PlayerCalloutC2SPacket(CalloutType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toBytes(ByteBuf buf) {
|
||||||
|
buf.writeByte(this.type.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromBytes(ByteBuf buf) {
|
||||||
|
this.type = CalloutType.byId(buf.readByte());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.network.packets.s2c;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||||
|
import ru.octol1ttle.knockdowns.common.communication.CalloutType;
|
||||||
|
|
||||||
|
public class PlayerCalloutS2CPacket implements IMessage {
|
||||||
|
public PlayerCalloutS2CPacket() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int playerId;
|
||||||
|
public Vec3d position;
|
||||||
|
public CalloutType type;
|
||||||
|
|
||||||
|
public PlayerCalloutS2CPacket(int playerId, Vec3d position, CalloutType type) {
|
||||||
|
this.playerId = playerId;
|
||||||
|
this.position = position;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toBytes(ByteBuf buf) {
|
||||||
|
buf.writeInt(this.playerId);
|
||||||
|
buf.writeDouble(this.position.x);
|
||||||
|
buf.writeDouble(this.position.y);
|
||||||
|
buf.writeDouble(this.position.z);
|
||||||
|
buf.writeByte(this.type.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromBytes(ByteBuf buf) {
|
||||||
|
this.playerId = buf.readInt();
|
||||||
|
this.position = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
|
||||||
|
this.type = CalloutType.byId(buf.readByte());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.network.packets.s2c;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||||
|
|
||||||
|
public class PlayerKnockedDownS2CPacket implements IMessage {
|
||||||
|
public PlayerKnockedDownS2CPacket() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int playerId;
|
||||||
|
public int dimensionId;
|
||||||
|
public Vec3d position;
|
||||||
|
|
||||||
|
public PlayerKnockedDownS2CPacket(int playerId, int dimensionId, Vec3d position) {
|
||||||
|
this.playerId = playerId;
|
||||||
|
this.dimensionId = dimensionId;
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toBytes(ByteBuf buf) {
|
||||||
|
buf.writeInt(this.playerId);
|
||||||
|
buf.writeInt(this.dimensionId);
|
||||||
|
buf.writeDouble(this.position.x);
|
||||||
|
buf.writeDouble(this.position.y);
|
||||||
|
buf.writeDouble(this.position.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromBytes(ByteBuf buf) {
|
||||||
|
this.playerId = buf.readInt();
|
||||||
|
this.dimensionId = buf.readInt();
|
||||||
|
this.position = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.network.packets.s2c;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||||
|
|
||||||
|
public class SynchronizePlayerDataS2CPacket {
|
||||||
|
public static class KnockedDown implements IMessage {
|
||||||
|
public KnockedDown() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int playerId;
|
||||||
|
public boolean knockedDown;
|
||||||
|
|
||||||
|
public KnockedDown(int playerId, boolean knockedDown) {
|
||||||
|
this.playerId = playerId;
|
||||||
|
this.knockedDown = knockedDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toBytes(ByteBuf buf) {
|
||||||
|
buf.writeInt(this.playerId);
|
||||||
|
buf.writeBoolean(this.knockedDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromBytes(ByteBuf buf) {
|
||||||
|
this.playerId = buf.readInt();
|
||||||
|
this.knockedDown = buf.readBoolean();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ReviveTimeLeft implements IMessage {
|
||||||
|
public ReviveTimeLeft() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int playerId;
|
||||||
|
public int reviveTimeLeft;
|
||||||
|
|
||||||
|
public ReviveTimeLeft(int playerId, int reviveTimeLeft) {
|
||||||
|
this.playerId = playerId;
|
||||||
|
this.reviveTimeLeft = reviveTimeLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toBytes(ByteBuf buf) {
|
||||||
|
buf.writeInt(this.playerId);
|
||||||
|
buf.writeInt(this.reviveTimeLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromBytes(ByteBuf buf) {
|
||||||
|
this.playerId = buf.readInt();
|
||||||
|
this.reviveTimeLeft = buf.readInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Full implements IMessage {
|
||||||
|
public Full() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int playerId;
|
||||||
|
public boolean knockedDown;
|
||||||
|
public int reviveTimeLeft;
|
||||||
|
|
||||||
|
public Full(int playerId, boolean knockedDown, int reviveTimeLeft) {
|
||||||
|
this.playerId = playerId;
|
||||||
|
this.knockedDown = knockedDown;
|
||||||
|
this.reviveTimeLeft = reviveTimeLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toBytes(ByteBuf buf) {
|
||||||
|
buf.writeInt(this.playerId);
|
||||||
|
buf.writeBoolean(this.knockedDown);
|
||||||
|
buf.writeInt(this.reviveTimeLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromBytes(ByteBuf buf) {
|
||||||
|
this.playerId = buf.readInt();
|
||||||
|
this.knockedDown = buf.readBoolean();
|
||||||
|
this.reviveTimeLeft = buf.readInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.network.packets.s2c;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||||
|
|
||||||
|
public class SynchronizeReviversS2CPacket {
|
||||||
|
public static class Add implements IMessage {
|
||||||
|
public Add() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int knockedId;
|
||||||
|
public int reviverId;
|
||||||
|
|
||||||
|
public Add(int knockedId, int reviverId) {
|
||||||
|
this.knockedId = knockedId;
|
||||||
|
this.reviverId = reviverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toBytes(ByteBuf buf) {
|
||||||
|
buf.writeInt(this.knockedId);
|
||||||
|
buf.writeInt(this.reviverId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromBytes(ByteBuf buf) {
|
||||||
|
this.knockedId = buf.readInt();
|
||||||
|
this.reviverId = buf.readInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Remove implements IMessage {
|
||||||
|
public Remove() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int knockedId;
|
||||||
|
public int reviverId;
|
||||||
|
|
||||||
|
public Remove(int knockedId, int reviverId) {
|
||||||
|
this.knockedId = knockedId;
|
||||||
|
this.reviverId = reviverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toBytes(ByteBuf buf) {
|
||||||
|
buf.writeInt(this.knockedId);
|
||||||
|
buf.writeInt(this.reviverId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromBytes(ByteBuf buf) {
|
||||||
|
this.knockedId = buf.readInt();
|
||||||
|
this.reviverId = buf.readInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package ru.octol1ttle.knockdowns.common.registry;
|
||||||
|
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.util.SoundEvent;
|
||||||
|
import ru.octol1ttle.knockdowns.Tags;
|
||||||
|
|
||||||
|
public class KnockdownsSoundEvents {
|
||||||
|
public static final SoundEvent CALLOUT;
|
||||||
|
public static final SoundEvent KNOCKED_DOWN;
|
||||||
|
static {
|
||||||
|
ResourceLocation callout = new ResourceLocation(Tags.MOD_ID, "callout");
|
||||||
|
CALLOUT = new SoundEvent(callout).setRegistryName(callout);
|
||||||
|
|
||||||
|
ResourceLocation knockedDown = new ResourceLocation(Tags.MOD_ID, "knocked_down");
|
||||||
|
KNOCKED_DOWN = new SoundEvent(knockedDown).setRegistryName(knockedDown);
|
||||||
|
}
|
||||||
|
}
|
64
src/main/resources/assets/knockdowns/lang/ru_ru.lang
Normal file
64
src/main/resources/assets/knockdowns/lang/ru_ru.lang
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
knockdowns.key.category=Knockdowns
|
||||||
|
knockdowns.key.callout.danger="Опасность!"
|
||||||
|
knockdowns.key.callout.booyah="Йо-хо!"
|
||||||
|
knockdowns.key.callout.this_way_help="Сюда!" ("SOS!" когда тяжело ранен)
|
||||||
|
knockdowns.key.callout.ouch="Непруха!"
|
||||||
|
|
||||||
|
knockdowns.callout.danger=Опасность!
|
||||||
|
knockdowns.callout.booyah=Йо-хо!
|
||||||
|
knockdowns.callout.this_way=Сюда!
|
||||||
|
knockdowns.callout.ouch=Непруха!
|
||||||
|
knockdowns.callout.help=SOS!
|
||||||
|
|
||||||
|
knockdowns.subtitles.callout=Игрок зовёт союзников
|
||||||
|
knockdowns.subtitles.knocked_down=Игрок тяжело ранен
|
||||||
|
|
||||||
|
knockdown.attack.anvil=%1$s тяжело ранен упавшей наковальней
|
||||||
|
knockdown.attack.arrow=%1$s тяжело ранен стрелой %2$s
|
||||||
|
knockdown.attack.arrow.item=%1$s тяжело ранен стрелой %2$s с помощью %3$s
|
||||||
|
knockdown.attack.cactus=%1$s исколот до тяжелого ранения
|
||||||
|
knockdown.attack.cactus.player=%1$s тяжело ранен кактусом, спасаясь от %2$s
|
||||||
|
knockdown.attack.cramming=%1$s расплющен до тяжелого ранения
|
||||||
|
knockdown.attack.dragonBreath=%1$s тяжело ранен в драконьем дыхании
|
||||||
|
knockdown.attack.drown=%1$s тяжело ранен от нехватки воздуха
|
||||||
|
knockdown.attack.drown.player=%1$s тяжело ранен от нехватки воздуха, спасаясь от %2$s
|
||||||
|
knockdown.attack.explosion=%1$s тяжело ранен взрывом
|
||||||
|
knockdown.attack.explosion.player=%1$s был тяжело ранен взрывом %2$s
|
||||||
|
knockdown.attack.fall=%1$s разбился до тяжелого ранения
|
||||||
|
knockdown.attack.fallingBlock=%1$s тяжело ранен упавшим блоком
|
||||||
|
knockdown.attack.fireball=%1$s тяжело ранен файерболом %2$s
|
||||||
|
knockdown.attack.fireball.item=%1$s тяжело ранен файерболом %2$s с помощью %3$s
|
||||||
|
knockdown.attack.fireworks=%1$s с треском тяжело ранен
|
||||||
|
knockdown.attack.flyIntoWall=%1$s преобразовал кинетическую энергию в тяжелое ранение
|
||||||
|
knockdown.attack.generic=%1$s тяжело ранен
|
||||||
|
knockdown.attack.hotFloor=%1$s тяжело ранен, обнаружив под ногами лаву
|
||||||
|
knockdown.attack.hotFloor.player=%1$s зашёл в опасную зону тяжелого ранения из-за %2$s
|
||||||
|
knockdown.attack.inFire=%1$s сгорел до тяжелого ранения
|
||||||
|
knockdown.attack.inFire.player=%1$s тяжело ранен в огне, борясь с %2$s
|
||||||
|
knockdown.attack.inWall=%1$s погребён до тяжелого ранения
|
||||||
|
knockdown.attack.indirectMagic=%1$s был тяжело ранен %2$s с помощью магии
|
||||||
|
knockdown.attack.indirectMagic.item=%1$s был тяжело ранен %2$s с помощью %3$s
|
||||||
|
knockdown.attack.lava=%1$s решил получить тяжелое ранение в лаве
|
||||||
|
knockdown.attack.lava.player=%1$s получил тяжелое ранение от лавы, убегая от %2$s
|
||||||
|
knockdown.attack.lightningBolt=%1$s был тяжело ранен поражением молнией
|
||||||
|
knockdown.attack.magic=%1$s был тяжело ранен магией
|
||||||
|
knockdown.attack.mob=%1$s был тяжело ранен %2$s
|
||||||
|
knockdown.attack.onFire=%1$s сгорел до тяжелого ранения
|
||||||
|
knockdown.attack.onFire.player=%1$s был сожжён до тяжелого ранения, пока боролся с %2$s
|
||||||
|
knockdown.attack.outOfWorld=%1$s тяжело ранен отсутствием земли под собой
|
||||||
|
knockdown.attack.player=%1$s был тяжело ранен %2$s
|
||||||
|
knockdown.attack.player.item=%1$s был тяжело ранен %2$s с помощью %3$s
|
||||||
|
knockdown.attack.starve=%1$s тяжело ранен от голода
|
||||||
|
knockdown.attack.thorns=%1$s был тяжело ранен, пытаясь навредить %2$s
|
||||||
|
knockdown.attack.thrown=%1$s был избит до тяжелого ранения %2$s
|
||||||
|
knockdown.attack.thrown.item=%1$s был избит до тяжелого ранения %2$s с помощью %3$s
|
||||||
|
knockdown.attack.wither=%1$s тяжело ранен иссушением
|
||||||
|
knockdown.fell.accident.generic=%1$s разбился до тяжелого ранения
|
||||||
|
knockdown.fell.accident.ladder=%1$s свалился с лестницы и был тяжело ранен
|
||||||
|
knockdown.fell.accident.vines=%1$s сорвался с лианы и был тяжело ранен
|
||||||
|
knockdown.fell.accident.water=%1$s выпал из воды и был тяжело ранен
|
||||||
|
knockdown.fell.assist=%1$s свалился и был тяжело ранен благодаря %2$s
|
||||||
|
knockdown.fell.assist.item=%1$s был обречён на тяжелое ранение %2$s с помощью %3$s
|
||||||
|
knockdown.fell.finish=%1$s упал с высоты и был тяжело ранен %2$s
|
||||||
|
knockdown.fell.finish.item=%1$s упал с высоты и был тяжело ранен %2$s с помощью %3$s
|
||||||
|
knockdown.fell.killer=%1$s был обречён на тяжелое ранение
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"package": "",
|
"package": "ru.octol1ttle.knockdowns.common.mixins",
|
||||||
"required": true,
|
"required": true,
|
||||||
"refmap": "${mixin_refmap}",
|
"refmap": "${mixin_refmap}",
|
||||||
"target": "@env(DEFAULT)",
|
"target": "@env(DEFAULT)",
|
||||||
"minVersion": "0.8.5",
|
"minVersion": "0.8.5",
|
||||||
"compatibilityLevel": "JAVA_8",
|
"compatibilityLevel": "JAVA_8",
|
||||||
"mixins": [],
|
"mixins": [ "EntityLivingBaseMixin", "EntityPlayerMixin" ],
|
||||||
"server": [],
|
"server": [],
|
||||||
"client": []
|
"client": []
|
||||||
}
|
}
|
Loading…
Reference in a new issue