Thread: Simple NPC spawn config editor

Results 1 to 2 of 2
  1. #1 Simple NPC spawn config editor 
    ya


    Join Date
    Jul 2014
    Posts
    507
    Thanks given
    135
    Thanks received
    131
    Rep Power
    836
    Title, made this yday/today, GUI is made using JavaFX, and is integrated with the client
    Allows u to add new NPCS, and then save it, aswell as remove NPCS (using right click "Remove Npc" on the npc [That option only appears if you have the tool open]
    Saves to JSON(easily modifiable if you use a different format to store ur npc spawns)
    dis code is for ruse, but very ez to adapt to ur base.




    Add/Save NPC button, writes the data to server, which will be saved to the JSON file(the npc is also of course being added to the world)




    Code:

    Client side

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.Menu?>
    <?import javafx.scene.control.MenuBar?>
    <?import javafx.scene.control.MenuItem?>
    <?import javafx.scene.control.TextField?>
    <?import javafx.scene.layout.AnchorPane?>
    
    <AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="488.0" prefWidth="724.0" style="-fx-background-color: #505050;" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.arlania.fxscenes.NpcConfigSceneController">
       <children>
          <Button fx:id="saveButton" layoutX="295.0" layoutY="424.0" mnemonicParsing="false" text="Add/Save NPC" />
          <TextField fx:id="npcIdField" layoutX="268.0" layoutY="35.0" promptText="NPC ID" />
          <TextField fx:id="directionField" layoutX="268.0" layoutY="82.0" promptText="Face / Direction" />
          <TextField layoutX="268.0" layoutY="133.0" promptText="X Position" fx:id="xPositionField" />
          <TextField fx:id="yPositionField" layoutX="268.0" layoutY="185.0" promptText="Y Position" />
          <TextField fx:id="zPositionField" layoutX="268.0" layoutY="232.0" promptText="Z Position(height)" />
          <TextField fx:id="coordinateField" layoutX="268.0" layoutY="276.0" promptText="Coordinate (True/False)" />
          <TextField fx:id="radiusField" layoutX="268.0" layoutY="320.0" promptText="Radius" />
          <Button fx:id="setCurrentPositionButton" layoutX="288.0" layoutY="368.0" mnemonicParsing="false" text="Set Current Position" />
          <MenuBar layoutX="432.0" layoutY="82.0">
            <menus>
              <Menu mnemonicParsing="false" text="Select">
                <items>
                  <MenuItem fx:id="northMenu" mnemonicParsing="false" text="North" />
                      <MenuItem fx:id="northEastMenu" mnemonicParsing="false" text="North East" />
                      <MenuItem fx:id="northWestMenu" mnemonicParsing="false" text="North West" />
                      <MenuItem fx:id="southMenu" mnemonicParsing="false" text="South" />
                      <MenuItem fx:id="southEastMenu" mnemonicParsing="false" text="South East" />
                      <MenuItem fx:id="southWestMenu" mnemonicParsing="false" text="South West" />
                      <MenuItem fx:id="eastMenu" mnemonicParsing="false" text="East" />
                      <MenuItem fx:id="westMenu" mnemonicParsing="false" text="West" />
                </items>
              </Menu>
            </menus>
          </MenuBar>
       </children>
    </AnchorPane>
    Code:
    package com.arlania;
    
    import java.io.IOException;
    import java.net.URL;
    
    import javafx.application.Application;
    import javafx.application.Platform;
    import javafx.event.EventHandler;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    import javafx.stage.WindowEvent;
    
    public class NpcConfigApplication extends Application{
    
    	@Override
    	public void start(Stage stage) throws Exception {
    		
    			String resourcePath = "fxscenes/NpcConfigScene.fxml";
    			URL location = getClass().getResource(resourcePath);
    			FXMLLoader loader = new FXMLLoader(location);
    			try {
    				stage.setTitle("Simple npc spawn config editor");
    				stage.setScene(new Scene(loader.load()));
    				stage.show();
    				stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
    				    @Override
    				    public void handle(WindowEvent t) {
    				    	System.out.println("Exiting cuz i like k");
    				        Platform.exit();
    				        Client.instance.npcEditing = false;
    				        Client.instance.sendNpcConfigPacket(1, 1, 1, 1, 5, false, 1);
    				       // System.exit(0); - Cant do that because, its integrated with the client, which will also exit the client.
    				    }
    				});
    				
    				
    				
    				
    			} catch (IOException e) {
    				e.printStackTrace();
    				Platform.exit();
    			}
    	
    	}
    
    }
    EDIT: use stage.hide() / stage.show() instead
    Code:
    package com.arlania.fxscenes;
    
    import java.net.URL;
    import java.util.ResourceBundle;
    
    import com.arlania.Client;
    
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Button;
    import javafx.scene.control.MenuItem;
    import javafx.scene.control.TextField;
    
    public class NpcConfigSceneController implements Initializable {
    
    	@FXML
    	private Button saveButton, setCurrentPositionButton;
    
    	@FXML
    	private TextField npcIdField, directionField, xPositionField, yPositionField, zPositionField, coordinateField,
    			radiusField;
    
    	private final Client instance = Client.instance;
    
    	@FXML
    	private MenuItem northMenu, northEastMenu, northWestMenu, southMenu, southEastMenu, southWestMenu, eastMenu,
    			westMenu;
    
    	private int direction = 0;
    
    	@Override
    	public void initialize(URL location, ResourceBundle resources) {
    		
    		instance.npcEditing = true;
    		
    		handleMenus();
    		
    		instance.sendNpcConfigPacket(1, 1, 1, 1, 1, true, 1);
    		
    		setCurrentPositionButton.setOnMouseClicked(x -> {
    			final int xPos = Client.getBaseX() + (Client.myPlayer.x - 6 >> 7);
    			final int yPos = Client.getBaseY() + (Client.myPlayer.y - 6 >> 7);
    			final int height = instance.plane;
    			xPositionField.setText(String.valueOf(xPos));
    			yPositionField.setText(String.valueOf(yPos));
    			zPositionField.setText(String.valueOf(height));
    		});
    
    		saveButton.setOnMouseClicked(x -> {
    			final int npcId = Integer.parseInt(npcIdField.getText());
    			final int xPos = Integer.parseInt(xPositionField.getText());
    			final int yPos = Integer.parseInt(yPositionField.getText());
    			final int zPos = Integer.parseInt(zPositionField.getText());
    			final boolean coordinate = Boolean.parseBoolean(coordinateField.getText());
    			final int radius = Integer.parseInt(radiusField.getText());
    			instance.sendNpcConfigPacket(npcId, direction, xPos, yPos, zPos, coordinate, radius);
    		});
    
    	}
    
    	private void handleMenus() { // ULTIMATE SHIT CODE, but cba
    
    		northMenu.setOnAction(x -> {
    			directionField.setText("NORTH");
    			direction = 1;
    		});
    		northEastMenu.setOnAction(x -> {
    			directionField.setText("NORTH_EAST");
    			direction = 2;
    		});
    		northWestMenu.setOnAction(x -> {
    			directionField.setText("NORTH_WEST");
    			direction = 0;
    		});
    		southMenu.setOnAction(x -> {
    			directionField.setText("SOUTH");
    			direction = 6;
    		});
    		southEastMenu.setOnAction(x -> {
    			directionField.setText("SOUTH_EAST");
    			direction = 7;
    		});
    		southWestMenu.setOnAction(x -> {
    			directionField.setText("SOUTH_WEST");
    			direction = 5;
    		});
    		eastMenu.setOnAction(x -> {
    			directionField.setText("EAST");
    			direction = 4;
    		});
    		westMenu.setOnAction(x -> {
    			directionField.setText("WEST");
    			direction = 3;
    		});
    
    	}
    
    }
    Client.java

    Code:
    public boolean npcEditing = false;
    	
    	public void sendNpcConfigPacket(int npcId, int direction, int xPos, int yPos, int zPos, boolean coordinate, int radius) {
    		
    		stream.createFrame(203);
    		
    		stream.writeWord(npcId);
    		stream.writeByte(direction);
    		stream.writeWord(xPos);
    		stream.writeWord(yPos);
    		stream.writeByte(zPos);
    		stream.writeByte(coordinate ? 1 : 0);
    		stream.writeByte(radius);
    		
    	}
    method where ur npc menus r built
    Code:
    if (l == 2) {
    							if(npcEditing) {
    								System.out.println("DRAWING THIS");
    								menuActionName[menuActionRow] = "Remove NPC" + " @[email protected]" + s;
    							}
    							menuActionID[menuActionRow] = 225;
    						}
    Server side

    NPC.java

    Code:
    private static final Gson builder = new GsonBuilder().setPrettyPrinting().create();
    	private static final Path FILE_PATH = Paths.get("./data/def/json/world_npcs.json");
    	private static ArrayList<SaveNpcData> data = null;
    
    	public static void loadNpcData() {
    		try {
    			SaveNpcData[] spawnData = builder.fromJson(new FileReader(FILE_PATH.toFile()), SaveNpcData[].class);
    			data = new ArrayList<>(Arrays.asList(spawnData));
    
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    
    	public static void writeNpcData(int npcId, Direction direction, Position position, Coordinator coordinator,
    			boolean add) {
    		try {
    			if (add) {
    				data.add(new SaveNpcData(npcId, direction, position, coordinator));
    			} else {
    				data.remove(new SaveNpcData(npcId, direction, position, coordinator));
    			}
    			String output = builder.toJson(data);
    			Files.write(FILE_PATH, output.getBytes());
    			NPC npc = new NPC(npcId, position);
    			if (add) {
    				World.register(npc);
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    then call the load method @ startup

    NpcConfigActionPacketListener (10/10 class naming)

    Code:
    package com.arlania.net.packet;
    
    import com.arlania.model.Direction;
    import com.arlania.model.Position;
    import com.arlania.net.packet.impl.NPCOptionPacketListener;
    import com.arlania.world.entity.impl.npc.NPC;
    import com.arlania.world.entity.impl.player.Player;
    import com.arlania.world.entity.impl.npc.NPCMovementCoordinator.Coordinator;
    
    public class NpcConfigActionPacketListener implements PacketListener {
    
    	@Override
    	public void handleMessage(Player player, Packet packet) {
    		
    		
    		int npcId = packet.readShort();
    		int dir = packet.readByte();
    		int xPos = packet.readShort();
    		int yPos = packet.readShort();
    		int zPos = packet.readByte();
    		boolean coordinate = packet.readByte() == 1 ? true : false;
    		int radius = packet.readByte();
    		
    		if(zPos == 5) { // kinda a cheaphax.
    			NPCOptionPacketListener.npcConfigEditing = false;
    			return;
    		}
    		
    		if(npcId == 1) {
    			NPCOptionPacketListener.npcConfigEditing = true;
    			return;
    		}
    		Direction direction = Direction.numberToDirection(dir);
    		Position position = new Position(xPos, yPos, zPos);
    		Coordinator cn = new Coordinator(coordinate, radius);
    		NPC.writeNpcData(npcId, direction, position, cn, true);
    	}
    
    }
    also add this
    Code:
     public static boolean npcConfigEditing = false;
    NpcOptionPacketListener, 2nd option

    Code:
    if(npcConfigEditing) {
    			NPC.writeNpcData(npcId, npc.getDirection(), npc.getDefaultPosition(), npc.getMovementCoordinator().getCoordinator(), false);
    			System.out.println("Added npc: " + npc.hashCode());
    			World.deregister(npc);
    			player.getMovementQueue().reset();
    			return;
    		}
    [/CODE]

    then add this class

    Code:
    package com.arlania;
    
    import com.arlania.model.Direction;
    import com.arlania.model.Position;
    import com.arlania.world.entity.impl.npc.NPCMovementCoordinator.Coordinator;
    import com.google.gson.annotations.SerializedName;
    
    public class SaveNpcData{
    	
    	@SerializedName("npc-id")
    	private int npcId;
    	private Direction face;
    	private Position position;
    	@SerializedName("walking-policy")
    	private Coordinator coordinator;
    	
    	
    	
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + npcId;
    		result = prime * result + ((position == null) ? 0 : position.hashCode());
    		return result;
    	}
    
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		SaveNpcData other = (SaveNpcData) obj;
    		if (npcId != other.npcId)
    			return false;
    		if (position == null) {
    			if (other.position != null)
    				return false;
    		} else if (!position.equals(other.position))
    			return false;
    		return true;
    	}
    
    	public SaveNpcData(int npcId, Direction direction, Position position, Coordinator coordinator) {
    		this.npcId = npcId;
    		this.face = direction;
    		this.position = position;
    		this.coordinator = coordinator;
    	}
    }
    Code:
    public static Direction numberToDirection(int number) {
    		
    		for(Direction dir : Direction.values()) { // this is not the fastest way but doesn't matter for an enum with like 8 values
    				
    			if(dir.intValue == number) {
    				System.out.println("Dir is: " + dir.toString());
    				return dir;
    			}
    			
    				
    			}
    		return Direction.NORTH; // default
    		
    			
    		}

    to Open the editor just call this
    Code:
     new Thread(() -> {
    				Application.launch(NpcConfigApplication.class);
    			}).start();

    -For mods, move this to "Snippets" if this isnt the correct section for it.
    Last edited by Suic; 08-01-2019 at 10:10 PM.
    Reply With Quote  
     

  2. #2  
    ya


    Join Date
    Jul 2014
    Posts
    507
    Thanks given
    135
    Thanks received
    131
    Rep Power
    836
    Updated the css


    Create a new CSS file (modena_dark.css) name doesn't actually matter but yeh
    paste this in [Only registered and activated users can see links. ] (css file from [Only registered and activated users can see links. ])
    in NpcConfigApplication Delete the new Scene bit and replace with
    Code:
    Scene scene = new Scene(loader.load());
    				scene.getStylesheets().add("modena_dark.css");
    also updated fxml file: [Only registered and activated users can see links. ]
    Reply With Quote  
     


Thread Information
Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)


User Tag List

Similar Threads

  1. Mostly complete #317 NPC spawn config
    By 2004Project in forum Buying
    Replies: 0
    Last Post: 07-07-2015, 09:13 PM
  2. 667/704 Npc Spawn/Shop editor?
    By titanpure7 in forum Help
    Replies: 6
    Last Post: 06-22-2012, 08:25 AM
  3. 317 NPC spawn config. Rep++
    By FuzzyNuts in forum Requests
    Replies: 0
    Last Post: 11-24-2011, 01:08 AM
  4. [Work in progress] Spawn/Config Editor
    By Nikki in forum Show-off
    Replies: 19
    Last Post: 04-21-2011, 04:51 PM
  5. Replies: 2
    Last Post: 04-20-2011, 05:48 PM
Posting Permissions
  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •