- Версия(и) Minecraft
- 1.12.2
Писал был мод, который выводит убийства что-то типа в стиле кс, но так как он уже не нужен, то выкладываю, может кому будет интересен или полезен код/принцип.
Выводит на экран в стиле "Убийца-Оружие(которым убили)-Жертва", если килов несколько подряд, то стакает один под другим, вплоть до указаного кол-ва. Через некоторое время пропадает.
Совместим с сервером.
Результат работы:
Пока пришла в голову только такая идея, как реализовать. Возможно, есть что лучше. Тут все довольно простенько и лениво)
Выводит на экран в стиле "Убийца-Оружие(которым убили)-Жертва", если килов несколько подряд, то стакает один под другим, вплоть до указаного кол-ва. Через некоторое время пропадает.
Совместим с сервером.
Результат работы:
Тесты
Java:
package com.thunder.pvpinfomod;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.GlStateManager.DestFactor;
import net.minecraft.client.renderer.GlStateManager.SourceFactor;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.living.LivingDeathEvent;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent.Phase;
import net.minecraftforge.fml.common.gameevent.TickEvent.PlayerTickEvent;
import net.minecraftforge.fml.common.network.ByteBufUtils;
import net.minecraftforge.fml.common.network.NetworkRegistry;
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.common.network.simpleimpl.SimpleNetworkWrapper;
import net.minecraftforge.fml.relauncher.Side;
import static java.lang.System.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.logging.log4j.core.appender.db.jpa.converter.StackTraceElementAttributeConverter;
import org.lwjgl.opengl.GL11;
import org.w3c.dom.css.Counter;
import com.thunder.pvpinfomod.PVPInfo.PVPInfoOverlay.PvPContainer;
import io.netty.buffer.ByteBuf;
@Mod(modid = PVPInfo.MOD_ID, name = PVPInfo.MOD_NAME, version = PVPInfo.VERSION)
public class PVPInfo {
public static final String MOD_NAME = "PvP Info Mod";
public static final String MOD_ID = "pvpinfomod";
public static final String VERSION = "1.0.0";
@Mod.Instance(PVPInfo.MOD_ID)
public static PVPInfo INSTANCE;
@EventHandler
public void preInit(FMLPreInitializationEvent event) {
PVPNetwork.init();
}
@EventHandler
public void init(FMLInitializationEvent event) {
MinecraftForge.EVENT_BUS.register(this);
if(FMLCommonHandler.instance().getEffectiveSide().isClient())
MinecraftForge.EVENT_BUS.register(new PVPInfoOverlay());
}
public static class PVPNetwork {
public static SimpleNetworkWrapper network;
public static void init() {
network = NetworkRegistry.INSTANCE.newSimpleChannel(PVPInfo.MOD_ID);
network.registerMessage(PvPPacket.Handler.class, PvPPacket.class, 0, Side.CLIENT);
}
}
//client
public static class PvPPacket implements IMessage {
public NBTTagCompound nbtTag;
public ItemStack stack;
public PvPPacket() {}
public PvPPacket(NBTTagCompound nbtTag, ItemStack stack) {
this.nbtTag = nbtTag;
this.stack = stack;
}
@Override
public void fromBytes(ByteBuf buf) {
nbtTag = ByteBufUtils.readTag(buf);
stack = ByteBufUtils.readItemStack(buf);
}
@Override
public void toBytes(ByteBuf buf) {
ByteBufUtils.writeTag(buf, nbtTag);
ByteBufUtils.writeItemStack(buf, stack);
}
public static class Handler implements IMessageHandler<PvPPacket, IMessage> {
@Override
public IMessage onMessage(PvPPacket message, MessageContext ctx) {
EntityPlayerSP player = Minecraft.getMinecraft().player;
if(player!= null){
NBTTagCompound tagCompound = message.nbtTag;
ItemStack weapon = message.stack;
PVPInfoOverlay.tasks.add(0, new PvPContainer(tagCompound.getString("killer"), tagCompound.getString("victim"), weapon));
PVPInfoOverlay.canShow = true;
PVPInfoOverlay.ticker = 0;
}
return null;
}
}
}
//server
@SubscribeEvent
public void onDeath(LivingDeathEvent event){
EntityLivingBase victim = event.getEntityLiving();
DamageSource killer = event.getSource();
if(victim != null && victim instanceof EntityPlayer && killer.getTrueSource() instanceof EntityPlayer){
EntityPlayer vPlayer = (EntityPlayer)victim;
EntityPlayer kPlayer = (EntityPlayer)killer.getTrueSource();
ItemStack weapon = kPlayer.getHeldItem(kPlayer.getActiveHand());
PVPNetwork.network.sendToAll(new PvPPacket(createPvPInfo(kPlayer.getDisplayNameString(), vPlayer.getDisplayNameString()),
weapon.isEmpty() ? new ItemStack(Items.WOODEN_SWORD) : weapon));
}
}
//client
public static class PVPInfoOverlay extends Gui {
public static final int TASK_SIZE = 4;
public static final int X_OFFSET = 4;
public static final int Y_OFFSET = 10;
public static ArrayList<PvPContainer> tasks = new ArrayList<PVPInfoOverlay.PvPContainer>(TASK_SIZE);
public static Minecraft mc = Minecraft.getMinecraft();
public static final double SCALE = 0.5d;
public static int ticker;
public static boolean canShow;
public static final int TIME_TO_SHOW = 400;
@SubscribeEvent
public void renderOverlay(RenderGameOverlayEvent event) {
if (event.isCancelable() || event.getType() != RenderGameOverlayEvent.ElementType.EXPERIENCE)
return;
int start_x = 5;
int start_y = 5;
if(tasks.size() > TASK_SIZE) {
tasks.remove(TASK_SIZE);
tasks.trimToSize();
}
if(canShow){
if(ticker < TIME_TO_SHOW){
for(PvPContainer task : tasks){
if(task != null){
String killer = task.killer;
String victim = task.victim;
int sWidth = (int)((mc.fontRenderer.getStringWidth(killer) + X_OFFSET) * SCALE);
int gWidth = sWidth + 10 + (int)((mc.fontRenderer.getStringWidth(victim) + X_OFFSET * 2) * SCALE);
GlStateManager.pushMatrix();
GlStateManager.scale(SCALE, SCALE, SCALE);
//draw font
drawRect((int)((start_x - 2) / SCALE), (int)((start_y - 2) / SCALE), (int)(gWidth / SCALE) + X_OFFSET, (int)(start_y / SCALE) + Y_OFFSET + 2, Integer.MIN_VALUE);
//draw text and icon
mc.fontRenderer.drawString(killer, (int)(start_x / SCALE), (int)(start_y / SCALE), 0xd80f0f);
renderStack(task.weapon, (int)((start_x + sWidth) / SCALE), (int)(start_y / SCALE) - 4);
mc.fontRenderer.drawString(victim, (int)((start_x + sWidth + 6 + X_OFFSET) / SCALE), (int)(start_y / SCALE), 0x27c615);
GlStateManager.popMatrix();
start_y += Y_OFFSET;
}
}
}else{
ticker = 0;
canShow = false;
tasks.clear();
}
}
}
@SubscribeEvent
public void onTick(PlayerTickEvent event){
if(event.phase == Phase.END){
PVPInfoOverlay.ticker++;
if(PVPInfoOverlay.ticker > PVPInfoOverlay.TIME_TO_SHOW) PVPInfoOverlay.ticker = 0;
}
}
public void renderStack(ItemStack stack, int x, int y){
RenderHelper.enableGUIStandardItemLighting();
mc.getRenderItem().renderItemAndEffectIntoGUI(stack, x, y);
RenderHelper.disableStandardItemLighting();
}
public static class PvPContainer {
public String killer;
public String victim;
public ItemStack weapon;
public PvPContainer(String killer, String victim, ItemStack weapon){
this.killer = killer;
this.victim = victim;
this.weapon = weapon;
}
}
}
public static NBTTagCompound createPvPInfo(String killer, String victim){
NBTTagCompound pTag = new NBTTagCompound();
pTag.setString("killer", killer);
pTag.setString("victim", victim);
return pTag;
}
}
Пока пришла в голову только такая идея, как реализовать. Возможно, есть что лучше. Тут все довольно простенько и лениво)