Skocz do zawartości

NPC - Jak napisać po mojemu.


KodziaK
 Udostępnij

Taka ankieta na dobry początek.  

5 użytkowników zagłosowało

  1. 1. Czy post wam się przydał?



Rekomendowane odpowiedzi

Witam jest to mój spóźniony wpis ale dodam tutaj tyle ile sam wiem i będę go edytował informacjami których się dowiem. Za wszystkie błędy przepraszam jak zna się lepiej proszę niech się wypowie nie znam się na tych npc dobrze a są dosyć ciekawe :)

 

Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!

 

Zacznijmy więc. Najpierw tworzymy nową klasę "Reflections".

Będzie to proste api do edycji class NMS.

Kod:

Spoiler
    public void setValue(Object obj,String name,Object value){
            try{
            Field field = obj.getClass().getDeclaredField(name);
            field.setAccessible(true);
            field.set(obj, value);
            }catch(Exception e){}
    }
   
    public Object getValue(Object obj,String name){
            try{
            Field field = obj.getClass().getDeclaredField(name);
            field.setAccessible(true);
            return field.get(obj);
            }catch(Exception e){}
            return null;
    }
   
    public void sendPacket(Packet<?> packet,Player player){
            ((CraftPlayer)player).getHandle().playerConnection.sendPacket(packet);
    }
   
    public void sendPacket(Packet<?> packet){
            for(Player player : Bukkit.getOnlinePlayers()){
                    sendPacket(packet,player);
            }
    }

 

 

Teraz tworzymy naszą główną klasę "NPC" musi ona używać "extends Reflections".

Na początek tworzymy wartości/zmienne dla naszego NPC.

Dla mnie to będą: owner, entityID, location, gameProfile oraz sneak

 

Tworzymy je w następujący sposób:

	OfflinePlayer owner;
	int entityID;
	Location location;
	GameProfile gameProfile;
	boolean sneak;

 

Dobrze by je było gdzieś przechować użyjemy do tego HashMapy:

		public static Map<OfflinePlayer, Integer> npcs = new HashMap<>();

 

Mamy podstawy teraz dodajmy funkcje klasy:

		public NPC(String name, OfflinePlayer p,Location loc, boolean crouch){
			entityID = (int)Math.ceil(Math.random() * 1000) + 2000;
			owner = p;
			gameProfile = new GameProfile(p.getUniqueId(), name);
			location = loc;
			sneak = crouch;
		}

 

Okej mamy to. Teraz zajmiemy  się samym tworzeniem NPC.

Tworzymy nową metodę będzie to u mnie "spawn".

I tworzymy pakiet którym będzie nasz NPC.

	public void spawn(){
  
		PacketPlayOutNamedEntitySpawn packet = new PacketPlayOutNamedEntitySpawn(); 
	
	}

 

Teraz ustawmy dane o naszym NPC które otrzyma serwer.

	public void spawn(){
  
	PacketPlayOutNamedEntitySpawn packet = new PacketPlayOutNamedEntitySpawn(); 
	
			setValue(packet, "a", entityID);
			setValue(packet, "b", gameProfile.getId());
			setValue(packet, "c", (int)MathHelper.floor(location.getX() * 32.0D));
			setValue(packet, "d", (int)MathHelper.floor(location.getY() * 32.0D));
			setValue(packet, "e", (int)MathHelper.floor(location.getZ() * 32.0D));
			setValue(packet, "f", (byte) ((int) (0.0F))); //Tutaj ustawiamy rotacje głowy (lewo, prawo)
			setValue(packet, "g", (byte) ((int) (65.0F))); //Tutaj ustawiamy rotacje głowy (góra, dół)
			setValue(packet, "h", 0);
		}

 

Ale to nie wszystko jeszcze musimy dodać DataWatcher. (Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!)

Nie jestem pewien w 100% co oznaczają zaimplementowane już DataWatchery ja tutaj dodałem swój (0x20)

		public void spawn(){
			PacketPlayOutNamedEntitySpawn packet = new PacketPlayOutNamedEntitySpawn();
			 
			setValue(packet, "a", entityID);
			setValue(packet, "b", gameProfile.getId());
			setValue(packet, "c", (int)MathHelper.floor(location.getX() * 32.0D));
			setValue(packet, "d", (int)MathHelper.floor(location.getY() * 32.0D));
			setValue(packet, "e", (int)MathHelper.floor(location.getZ() * 32.0D));
			setValue(packet, "f", (byte) ((int) (0.0F)));
			setValue(packet, "g", (byte) ((int) (65.0F)));
			setValue(packet, "h", 0);
			DataWatcher w = new DataWatcher(null);
			w.a(6,(float)20);
			if(sneak) {
				w.a(0,(byte)0x02);
			}
			w.a(10,(byte)127);
			setValue(packet, "i", w);
		}

 

Okej mamy to teraz zajmiemy się już samym pojawieniem gracza!

Tworzymy nową metodę ja nazwę ją "addToTablist".

Odpowiadać to będzie za pojawienie gracza. (musi być nie wiem jak go pojawić bez dodania to tablisty)

Tutaj nie będę szczegółowo omawiać kod:

		public void addToTablist(){
			PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo();
			PacketPlayOutPlayerInfo.PlayerInfoData data = packet.new PlayerInfoData(gameProfile, 1, EnumGamemode.NOT_SET, CraftChatMessage.fromString(gameProfile.getName())[0]);
			@SuppressWarnings("unchecked")
			List<PacketPlayOutPlayerInfo.PlayerInfoData> players = (List<PacketPlayOutPlayerInfo.PlayerInfoData>) getValue(packet, "b");
			players.add(data);
			setValue(packet, "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER);
			setValue(packet, "b", players);
			sendPacket(packet);
		}

 

Tutaj usunięcie z tablisty.

		public void rmvFromTablist(){
			PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo();
			PacketPlayOutPlayerInfo.PlayerInfoData data = packet.new PlayerInfoData(gameProfile, 1, EnumGamemode.NOT_SET, CraftChatMessage.fromString(gameProfile.getName())[0]);
			@SuppressWarnings("unchecked")
			List<PacketPlayOutPlayerInfo.PlayerInfoData> players = (List<PacketPlayOutPlayerInfo.PlayerInfoData>) getValue(packet, "b");
			players.add(data);
			setValue(packet, "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER);
			setValue(packet, "b", players);
		  
			sendPacket(packet);
		}

 

A finalny kod wygląda tak:

Spoiler
package pl.gmail.k0dx.core.objects;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.craftbukkit.v1_8_R3.util.CraftChatMessage;

import com.mojang.authlib.GameProfile;

import net.minecraft.server.v1_8_R3.DataWatcher;
import net.minecraft.server.v1_8_R3.MathHelper;
import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy;
import net.minecraft.server.v1_8_R3.PacketPlayOutNamedEntitySpawn;
import net.minecraft.server.v1_8_R3.PacketPlayOutPlayerInfo;
import net.minecraft.server.v1_8_R3.WorldSettings.EnumGamemode;
import pl.gmail.k0dx.core.utils.Reflections;

public class NPC extends Reflections {

		public static Map<OfflinePlayer, Integer> npcs = new HashMap<>();
		
		OfflinePlayer owner;
		int entityID;
		Location location;
		GameProfile gameProfile;
		boolean sneak;
	  
	  
		public NPC(String name, OfflinePlayer p,Location loc, boolean crouch){
			entityID = (int)Math.ceil(Math.random() * 1000) + 2000;
			owner = p;
			gameProfile = new GameProfile(p.getUniqueId(), name);
			location = loc;
			sneak = crouch;
		}
	  
		
		public void spawn(){
			PacketPlayOutNamedEntitySpawn packet = new PacketPlayOutNamedEntitySpawn();
			 
			setValue(packet, "a", entityID);
			setValue(packet, "b", gameProfile.getId());
			setValue(packet, "c", (int)MathHelper.floor(location.getX() * 32.0D));
			setValue(packet, "d", (int)MathHelper.floor(location.getY() * 32.0D));
			setValue(packet, "e", (int)MathHelper.floor(location.getZ() * 32.0D));
			setValue(packet, "f", (byte) ((int) (0.0F)));
			setValue(packet, "g", (byte) ((int) (65.0F)));
			setValue(packet, "h", 0);
			DataWatcher w = new DataWatcher(null);
			w.a(6,(float)20);
			if(sneak) {
				w.a(0,(byte)0x02);
			}
			w.a(10,(byte)127);
			setValue(packet, "i", w);
			addToTablist();
			rmvFromTablist();
			sendPacket(packet);
			npcs.put(owner, entityID);
		}
	  
		public void destroy(){
			PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(new int[] {npcs.get(owner)});
			rmvFromTablist();
			sendPacket(packet);
		}
	  
		public void addToTablist(){
			PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo();
			PacketPlayOutPlayerInfo.PlayerInfoData data = packet.new PlayerInfoData(gameProfile, 1, EnumGamemode.NOT_SET, CraftChatMessage.fromString(gameProfile.getName())[0]);
			@SuppressWarnings("unchecked")
			List<PacketPlayOutPlayerInfo.PlayerInfoData> players = (List<PacketPlayOutPlayerInfo.PlayerInfoData>) getValue(packet, "b");
			players.add(data);
			setValue(packet, "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER);
			setValue(packet, "b", players);
			sendPacket(packet);
		}
	  
		public void rmvFromTablist(){
			PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo();
			PacketPlayOutPlayerInfo.PlayerInfoData data = packet.new PlayerInfoData(gameProfile, 1, EnumGamemode.NOT_SET, CraftChatMessage.fromString(gameProfile.getName())[0]);
			@SuppressWarnings("unchecked")
			List<PacketPlayOutPlayerInfo.PlayerInfoData> players = (List<PacketPlayOutPlayerInfo.PlayerInfoData>) getValue(packet, "b");
			players.add(data);
			setValue(packet, "a", PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER);
			setValue(packet, "b", players);
		  
			sendPacket(packet);
		} 
		public void setCrouch(boolean crouch) { // to można usunąć nie wymagane
			this.sneak = crouch; // to można usunąć nie wymagane
		} // to można usunąć nie wymagane
		
		public boolean getCrouch() { // to można usunąć nie wymagane
			return sneak; // to można usunąć nie wymagane
		} // to można usunąć nie wymagane
}

 

 

Dziękuje za przeczytanie! Tak wiem spóźniony i pewnie źle napisany kod ale nie jestem najlepszy a może komuś się przydać! <3 Jak opracuje zwiększenie długości nicku do 48 znaków dam znać!

 

Pisane przez KodziaK

Odnośnik do komentarza
Udostępnij na innych stronach

@keebe To nie miał być poradnik tylko post na blogu powiadziałem o głównej formie a reszta jest błacha. Z resztą sam wszystkiego nie rozumiem robiłem to z niemieckiego tutoriala z którego też uczyłem się tylko z kodu.

I chciałem tylko pokazać że to jest możliwe i jak to wykonać moim sposobem powiedziałem o stworzeniu NPC i zmienieniu jego danych nie powiedziałem nic na temat jego powiadania i znikania...

Odnośnik do komentarza
Udostępnij na innych stronach

Dnia 19.11.2017 o 14:13, McKoxu napisał:

Czekaj, chodzi tu o npc. takie jak np. w pluginie citizens ?

chodzi mu o tworzenie np. steava

Na początek tworzymy wartości/zmienne dla naszego NPC.

Dla mnie to będą: owner, entityID, location, gameProfile oraz sneak

 

Tworzymy je w następujący sposób:

	OfflinePlayer owner;
	int entityID;
	Location location;
	GameProfile gameProfile;
	boolean sneak;

lepiej jest nadac modyfikator dostepu tym 'zmiennym'

 

i nic nie opisales, co robi kod tylko po prostu go wkeiles, i w sumie kod nie twoj, nie napisales ze mozna tez zrobic aby ten 'npc' chodzil itd., wiec troche slabo

Odnośnik do komentarza
Udostępnij na innych stronach

  • Ixidi zablokował(a) ten temat
Nieaktywny
Ten temat został zamknięty. Brak możliwości dodania odpowiedzi.
 Udostępnij

  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...