PrivateFields.java
3.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
* This file is part of LiteLoader.
* Copyright (C) 2012-16 Adam Mummery-Smith
* All Rights Reserved.
*/
package com.mumfrey.liteloader.util;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import com.mumfrey.liteloader.core.runtime.Obf;
/**
* Wrapper for obf/mcp reflection-accessed private fields, mainly added to
* centralise the locations I have to update the obfuscated field names.
*
* @author Adam Mummery-Smith
*
* @param <P> Parent class type, the type of the class that owns the field
* @param <T> Field type, the type of the field value
*/
public class PrivateFields<P, T>
{
/**
* Class to which this field belongs
*/
public final Class<P> parentClass;
/**
* Name used to access the field, determined at init
*/
private final String fieldName;
private boolean errorReported = false;
/**
* Creates a new private field entry
*
* @param obf
*/
protected PrivateFields(Class<P> owner, Obf obf)
{
this.parentClass = owner;
this.fieldName = ObfuscationUtilities.getObfuscatedFieldName(obf);
}
/**
* Get the current value of this field on the instance class supplied
*
* @param instance Class to get the value of
* @return field value or null if errors occur
*/
@SuppressWarnings("unchecked")
public T get(P instance)
{
try
{
Field field = this.parentClass.getDeclaredField(this.fieldName);
field.setAccessible(true);
return (T)field.get(instance);
}
catch (Exception ex)
{
if (!this.errorReported)
{
this.errorReported = true;
ex.printStackTrace();
}
return null;
}
}
/**
* Set the value of this field on the instance class supplied
*
* @param instance Object to set the value of the field on
* @param value value to set
* @return value
*/
public T set(P instance, T value)
{
try
{
Field field = this.parentClass.getDeclaredField(this.fieldName);
field.setAccessible(true);
field.set(instance, value);
}
catch (Exception ex)
{
if (!this.errorReported)
{
this.errorReported = true;
ex.printStackTrace();
}
}
return value;
}
/**
* Set the value of this FINAL field on the instance class supplied
*
* @param instance Object to set the value of the field on
* @param value value to set
* @return value
*/
public T setFinal(P instance, T value)
{
try
{
Field modifiers = Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);
Field field = this.parentClass.getDeclaredField(this.fieldName);
modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.setAccessible(true);
field.set(instance, value);
}
catch (Exception ex)
{
if (!this.errorReported)
{
this.errorReported = true;
ex.printStackTrace();
}
}
return value;
}
}