Jump to content

Recommended Posts

Posted

Well... playerUUID.dat is literally buffered NBT tag. Format is very similar to .zip (that's not relevant, just saying that it's similar).

Anyway, dig into vanilla data loader class (i would start from EntityPlayer) and use it's methods to read NBTTag from .dat, then simply get tag you want and edit it.

 

Useful:

- Tags can be printed using Syso.

- Editing it can be done probably anywhere in code (command?)

- Note that you shouldn't edit .dat that is used by player (bam, corrupted or desynchro).

1.7.10 is no longer supported by forge, you are on your own.

Posted

I just changed my my system to something like this:

 

 

Player

package com.blackgecko.moro.mod.playerdata;

import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraftforge.common.IExtendedEntityProperties;

public class MoroPlayer implements IExtendedEntityProperties {
/*
 * Here I create a constant EXT_PROP_NAME for this class of properties. You
 * need a unique name for every instance of IExtendedEntityProperties you
 * make, and doing it at the top of each class as a constant makes it very
 * easy to organize and avoid typos. It's easiest to keep the same constant
 * name in every class, as it will be distinguished by the class name:
 * ExtendedPlayer.EXT_PROP_NAME vs. ExtendedEntity.EXT_PROP_NAME
 * 
 * Note that a single entity can have multiple extended properties, so each
 * property should have a unique name. Try to come up with something more
 * unique than the tutorial example.
 */
public final static String EXT_PROP_NAME = "MoroPlayer";

// I always include the entity to which the properties belong for easy
// access
// It's final because we won't be changing which player it is
private final EntityPlayer player;

// Declare other variables you want to add here

// We're adding mana to the player, so we'll need current and max mana
private int remainingTime;


int timeDay=5;

private boolean hasTimeLimit;
/*
 * The default constructor takes no arguments, but I put in the Entity so I
 * can initialize the above variable 'player'
 * 
 * Also, it's best to initialize any other variables you may have added,
 * just like in any constructor.
 */
public MoroPlayer(EntityPlayer player) {
	this.player = player;
	// Start with max mana. Every player starts with the same amount.
	this.remainingTime= 20*60+timeDay;
	this.hasTimeLimit=true;
}

/**
 * Used to register these extended properties for the player during
 * EntityConstructing event This method is for convenience only; it will
 * make your code look nicer
 */
public static final void register(EntityPlayer player) {
	player.registerExtendedProperties(MoroPlayer.EXT_PROP_NAME,new MoroPlayer(player));
}

/**
 * Returns ExtendedPlayer properties for player This method is for
 * convenience only; it will make your code look nicer
 */
public static final MoroPlayer get(EntityPlayer player) {
	return (MoroPlayer) player.getExtendedProperties(EXT_PROP_NAME);
}

// Save any custom data that needs saving here
@Override
public void saveNBTData(NBTTagCompound compound) {
	// We need to create a new tag compound that will save everything for
	// our Extended Properties
	NBTTagCompound properties = new NBTTagCompound();

	// We only have 2 variables currently; save them both to the new tag
	properties.setInteger("remainingTime", this.remainingTime);
	properties.setBoolean("hasTimeLimit", this.hasTimeLimit);

	/*
	 * Now add our custom tag to the player's tag with a unique name (our
	 * property's name). This will allow you to save multiple types of
	 * properties and distinguish between them. If you only have one type,
	 * it isn't as important, but it will still avoid conflicts between your
	 * tag names and vanilla tag names. For instance, if you add some
	 * "Items" tag, that will conflict with vanilla. Not good. So just use a
	 * unique tag name.
	 */
	compound.setTag(EXT_PROP_NAME, properties);
}

// Load whatever data you saved
@Override
public void loadNBTData(NBTTagCompound compound) {
	// Here we fetch the unique tag compound we set for this class of
	// Extended Properties
	NBTTagCompound properties = (NBTTagCompound) compound.getTag(EXT_PROP_NAME);
	// Get our data from the custom tag compound

	this.hasTimeLimit = properties.getBoolean("hasTimeLimit");
	this.remainingTime = properties.getInteger("remainingTime");


}

/*
 * I personally have yet to find a use for this method. If you know of any,
 * please let me know and I'll add it in!
 */
@Override
public void init(Entity entity, World world) {
}

/*
 * That's it for the IExtendedEntityProperties methods, but we need to add a
 * few of our own in order to interact with our new variables. For now,
 * let's make one method to consume mana and one to replenish it.
 */

public void switchTimeLimit(boolean b){
	this.hasTimeLimit=b;
}
public boolean getTimeLimit(){
	return this.hasTimeLimit;
}

public void setTime(int time){
	this.remainingTime=time;
}
public void addTime(int time){
	this.remainingTime+=time;
}
public int getTime(){
	return this.remainingTime;
}

}

and Event:


@SubscribeEvent
public void onEntityConstructing(EntityConstructing event)
{
/*
Be sure to check if the entity being constructed is the correct type for the extended properties you're about to add! The null check may not be necessary - I only use it to make sure properties are only registered once per entity
*/
if (event.entity instanceof EntityPlayer && MoroPlayer.get((EntityPlayer) event.entity) == null)
	MoroPlayer.register((EntityPlayer) event.entity);
	// That will call the constructor as well as cause the init() method
	// to be called automatically

// If you didn't make the two convenient methods from earlier, your code would be
// much uglier:
if (event.entity instanceof EntityPlayer && event.entity.getExtendedProperties(MoroPlayer.EXT_PROP_NAME) == null)
event.entity.registerExtendedProperties(MoroPlayer.EXT_PROP_NAME, new MoroPlayer((EntityPlayer) event.entity));
}

 

 

 

Same question, how do i access this data if the player is offline?

Here could be your advertisement!

Posted

I just found this piece of code:

 

	SaveHandlerMP saveHandler = (SaveHandlerMP)DimensionManager.getWorld(0).getSaveHandler();
	NBTTagCompound playerNbt = saveHandler.getPlayerData(playerName);
	InventoryPlayer inventory = new InventoryPlayer(null);
	inventory.readFromNBT(playerNbt.getTagList("Inventory"));
	inventory.armorInventory = armor;
	inventory.mainInventory = contents;
	playerNbt.setTag("Inventory", inventory.writeToNBT(new NBTTagList()));
	try {
		File playersDirectory = new File(saveHandler.getSaveDirectory(), "players");

		File temp = new File(playersDirectory, username + ".dat.tmp");
		File playerFile = new File(playersDirectory, username + ".dat");
		CompressedStreamTools.writeCompressed(playerNbt, new FileOutputStream(temp));

		if (playerFile.exists()) {
			playerFile.delete();
		}
		temp.renameTo(playerFile);
	} catch (Exception e) {
		logger.warning("Data failed to save for " + username);
	}

The main problem is that .getPlayerDatadoesn't Exist on MP and for all alternatives i have to use EntityPlayer.(kinda hard without a player)

 

Any ideas on how to get this working?

 

EDIT: Oh, can someone tell me how to get the save folder on mp?

I want to try to get this line working without a saveHandler...

playersDirectory = new File(saveHandler.getSaveDirectory(), "players");

 

WorldDirectory....

Here could be your advertisement!

Posted

This is manually:

 

 

public class OfflineNBT {

public void writeToNBT(String playerName, NBTBase tag, String TagName){


	SaveHandlerMP saveHandler = (SaveHandlerMP)DimensionManager.getWorld(0).getSaveHandler();
	NBTTagCompound playerNbt = readFromNBT(playerName);
	if(playerNbt!=null){
		playerNbt.setTag(TagName, tag);

		try {
			File playersDirectory = new File(saveHandler.getWorldDirectory(), "players");

			File temp = new File(playersDirectory, playerName + ".dat.tmp");
			File playerFile = new File(playersDirectory, playerName + ".dat");
			CompressedStreamTools.writeCompressed(playerNbt, new FileOutputStream(temp));

			if (playerFile.exists()) {
				playerFile.delete();
			}
			temp.renameTo(playerFile);
		} catch (Exception e) {

		}
	}
}

public NBTTagCompound readFromNBT(String playerName){


	SaveHandlerMP saveHandler = (SaveHandlerMP)DimensionManager.getWorld(0).getSaveHandler();

	NBTTagCompound playerNbt;

	try {
		File playersDirectory = new File(saveHandler.getWorldDirectory(), "players");

		File playerFile = new File(playersDirectory, playerName + ".dat");
		return CompressedStreamTools.read(playerFile);

	} catch (Exception e) {

	}

	System.out.println("RETURNED NULL");
	return null;
}

}

 

 

Here could be your advertisement!

Posted

No, that is not manulally.

 

File temp = new File(playersDirectory, playerName + ".dat.tmp");

 

You can't use playerName, you don't HAVE a playerName: they're offline.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

Why not? player Name is just a string? And the player file shouldn't be deleted if the player disconnects...

EDIT: Apparently everything is not in a player folder but in a playerdata folder and uuids are used instead of names.

 

So how can i convert a a player name to an uuid?

 

EDIT2: Tried to use the uuid in my command instead. Still returns null.

Any ideas why?

 

 

 

public static NBTTagCompound readFromNBT(String playerName){


	SaveHandler saveHandler = (SaveHandler)MinecraftServer.getServer().worldServers[0].getSaveHandler();


	NBTTagCompound playerNbt;

	try {
		File playersDirectory = new File(saveHandler.getWorldDirectory(), "playerdata");

		File playerFile = new File(playersDirectory, playerName + ".dat");
		playerNbt = CompressedStreamTools.read(playerFile);
		if(playerNbt==null){
			System.out.println("playernbt is null");
		}

		return playerNbt;

	} catch (Exception e) {

	}

	System.out.println("RETURNED NULL");
	return null;
}

 

 

Here could be your advertisement!

Posted

Why not? player Name is just a string? And the player file shouldn't be deleted if the player disconnects...

EDIT: Apparently everything is not in a player folder but in a playerdata folder and uuids are used instead of names.

 

So how can i convert a a player name to an uuid?

 

Ta da!  That's why you have to read every file in the directory manually.  You won't be able to convert a playerName string into that player's UUID without the EntityPlayer object (99% sure).

 

And even if you could, where would you be pulling that name from anyway?

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

I don't want to force my users to enter the players uuid.

(As already said, i need it to edit offline users nbt for a chat command)

So does this mean that i have to loop through all players until i find one with the right name?

(Btw, where exactly is the playername stored?)

 

And i tested it by using the uuid as a string and it still returned null.

Here could be your advertisement!

Posted

Ok, maybe its faster if i store all my information in a json file instead of using ExtendedEntityProperties or nbt data.

I believe i heared a while ago that there are some built in features for this. Can someone send me a link for this?

Here could be your advertisement!

Posted

I don't want to force my users to enter the players uuid.

 

What on earth are you doing? o..O

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

well, s**t

Thats going to be funny! Yeahhhh...(not)

 

I want to limit the time every player can spend on the server a day. Now i am adding a command to extend the time that a player has left even if he is not online.

(And i also have to reset the time for every player at midnight...)

Do you have a better idea to do this?

 

 

EDIT2:

 

 

Ok, found a solution.

I save my data in an extra file when my players are offline and sync it with their data when they join.

Here could be your advertisement!

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.