camera update

This commit is contained in:
gnembon committed 2019-12-22 02:26:40 -04:00
1 parent 1dc2308d2e
commit 62529a352c
5 files changed
+311 -119

No files matched your search

@@ -106,7 +106,6 @@ import java.util.function.BiFunction;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static carpet.script.value.NBTSerializableValue.nameFromRegistryId;
import static java.lang.Math.abs;
import static java.lang.Math.max;
import static java.lang.Math.min;
@@ -2865,6 +2864,7 @@ public class CarpetExpression
CarpetContext cc = (CarpetContext)c;
BlockState targetBlock = null;
BlockValue.VectorLocator pointLocator;
boolean interactable = true;
String name;
try
{
@@ -2872,8 +2872,14 @@ public class CarpetExpression
name = nameValue instanceof NullValue ? "" : nameValue.getString();
pointLocator = BlockValue.locateVec(cc, lv, 1, true);
if (lv.size()>pointLocator.offset)
targetBlock = BlockValue.fromParams(cc, lv, pointLocator.offset, true).block.getBlockState();
{
BlockValue.LocatorResult blockLocator = BlockValue.fromParams(cc, lv, pointLocator.offset, true, true);
if (blockLocator.block != null) targetBlock = blockLocator.block.getBlockState();
if (lv.size() > blockLocator.offset)
{
interactable = lv.get(blockLocator.offset).evalValue(c, Context.BOOLEAN).getBoolean();
}
}
}
catch (IndexOutOfBoundsException e)
{
@@ -2901,6 +2907,7 @@ public class CarpetExpression
armorstand.setNoGravity(true);
armorstand.setInvisible(true);
armorstand.setInvulnerable(true);
armorstand.getDataTracker().set(ArmorStandEntity.ARMOR_STAND_FLAGS, (byte)(interactable?8 : 16|8));
cc.s.getWorld().spawnEntity(armorstand);
EntityValue result = new EntityValue(armorstand);
return (_c, _t) -> result;
@@ -3023,7 +3030,7 @@ public class CarpetExpression
this.expr.addLazyFunction("current_dimension", 0, (c, t, lv) -> {
ServerCommandSource s = ((CarpetContext)c).s;
Value retval = new StringValue(nameFromRegistryId(Registry.DIMENSION.getId(s.getWorld().dimension.getType())));
Value retval = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.DIMENSION.getId(s.getWorld().dimension.getType())));
return (cc, tt) -> retval;
});
+9 -7
View File
@@ -1198,16 +1198,14 @@ public class Expression implements Cloneable
{
Value v1 = lv1.evalValue(c, Context.BOOLEAN);
if (!v1.getBoolean()) return (cc, tt) -> v1;
Value v2 = lv2.evalValue(c, Context.BOOLEAN);
return v2.getBoolean() ? ((cc, tt) -> v2) : LazyValue.FALSE;
return lv2;
});
addLazyBinaryOperator("||", precedence.get("or||"), false, (c, t, lv1, lv2) ->
{
Value v1 = lv1.evalValue(c, Context.BOOLEAN);
if (v1.getBoolean()) return (cc, tt) -> v1;
Value v2 = lv2.evalValue(c, Context.BOOLEAN);
return v2.getBoolean() ? ((cc, tt) -> v2) : LazyValue.FALSE;
return lv2;
});
addBinaryOperator("~", precedence.get("attribute~:"), true, Value::in);
@@ -1928,7 +1926,7 @@ public class Expression implements Cloneable
LazyValue expr = lv.get(1);
//scoping
LazyValue _val = c.getVariable("_");
LazyValue _iter = c.getVariable("_i");
LazyValue _ite = c.getVariable("_i");
int successCount = 0;
for (int i=0; iterator.hasNext(); i++)
{
@@ -1959,7 +1957,7 @@ public class Expression implements Cloneable
//revering scope
((AbstractListValue) rval).fatality();
c.setVariable("_", _val);
c.setVariable("_i", _iter);
c.setVariable("_i", _ite);
long promiseWontChange = successCount;
return (cc, tt) -> new NumericValue(promiseWontChange);
});
@@ -1988,15 +1986,18 @@ public class Expression implements Cloneable
//scoping
LazyValue _val = c.getVariable("_");
LazyValue _acc = c.getVariable("_a");
LazyValue _ite = c.getVariable("_i");
while (iterator.hasNext())
for (int i=0; iterator.hasNext(); i++)
{
Value next = iterator.next();
String var = next.boundVariable;
next.bindTo("_");
Value promiseWontChangeYou = acc;
int seriously = i;
c.setVariable("_a", (cc, tt) -> promiseWontChangeYou.bindTo("_a"));
c.setVariable("_", (cc, tt) -> next);
c.setVariable("_i", (cc, tt) -> new NumericValue(seriously).bindTo("_i"));
try
{
acc = expr.evalValue(c, t);
@@ -2016,6 +2017,7 @@ public class Expression implements Cloneable
((AbstractListValue) rval).fatality();
c.setVariable("_a", _acc);
c.setVariable("_", _val);
c.setVariable("_i", _ite);
Value hopeItsEnoughPromise = acc;
return (cc, tt) -> hopeItsEnoughPromise;
@@ -130,15 +130,24 @@ public class BlockValue extends Value
public static LocatorResult fromParams(CarpetContext c, List<LazyValue> params, int offset)
{
return fromParams(c, params,offset, false);
return fromParams(c, params,offset, false, false);
}
public static LocatorResult fromParams(CarpetContext c, List<LazyValue> params, int offset, boolean acceptString)
{
return fromParams(c, params,offset, acceptString, false);
}
public static LocatorResult fromParams(CarpetContext c, List<LazyValue> params, int offset, boolean acceptString, boolean optional)
{
try
{
Value v1 = params.get(0 + offset).evalValue(c);
//add conditional from string name
if (optional && v1 instanceof NullValue)
{
return new LocatorResult(null, 1+offset);
}
if (acceptString && v1 instanceof StringValue)
{
return new LocatorResult(fromString(v1.getString()), 1+offset);
@@ -772,6 +772,39 @@ public class EntityValue extends Value
else
e.noClip = v.getBoolean();
});
put("effect", (e, v) ->
{
if (!(e instanceof LivingEntity)) return;
LivingEntity le = (LivingEntity)e;
if (v == null)
le.clearPotionEffects();
else if (v instanceof ListValue)
{
List<Value> lv = ((ListValue) v).getItems();
if (lv.size() >= 2 && lv.size() <= 5)
{
String effectName = lv.get(0).getString();
if (effectName.startsWith("minecraft:"))
effectName = "minecraft:"+effectName;
StatusEffect effect = Registry.STATUS_EFFECT.get(new Identifier(effectName));
if (effect == null)
throw new InternalExpressionException("Wrong effect name: "+effectName);
int duration = (int)NumericValue.asNumber(lv.get(1)).getLong();
int amplifier = 0;
if (lv.size() > 2)
amplifier = (int)NumericValue.asNumber(lv.get(2)).getLong();
boolean showParticles = true;
if (lv.size() > 3)
showParticles = lv.get(3).getBoolean();
boolean showIcon = true;
if (lv.size() > 4)
showIcon = lv.get(4).getBoolean();
le.addPotionEffect(new StatusEffectInstance(effect, duration, amplifier, showParticles, showIcon));
return;
}
}
throw new InternalExpressionException("'effect' needs either no arguments (clear) or effect name, duration, and optional amplifier, show particles and show icon");
});
// gamemode
// spectate
+248 -107
View File
@@ -35,31 +35,66 @@ __command() ->
''
);
// camera position for the player sticks out of their eyes
__camera_position(player) -> (player~'location' + l(0, player~'eye_height',0,0,0));
__update() ->
(
undef('global_path_precalculated');
global_needs_updating = true;
);
start() ->
(
p = player();
global_points = l(l(p ~ 'location', 0,'sharp'));
undef('global_path_precalculated');
str('Started path at %.1f %.1f %.1f', p~'x', p~'y', p~'z')
global_points = l(l(__camera_position(p), 0,'sharp'));
__update();
show();
str('Started path at %.1f %.1f %.1f', p~'x', p~'y', p~'z');
);
add(delay) ->
(
p = player();
mode = 'sharp';
mode = 'smooth';
//mode is currently unused, run_path does always sharp, gauss interpolator is always smooth
// but this option could be used could be used at some point by more robust interpolators
__add_path_segment(p ~ 'location', delay, mode);
str('Added point %d: %.1f %.1f %.1f', length(global_points), p~'x', p~'y', p~'z')
__add_path_segment(__camera_position(p), round(60*delay), mode);
__print_path_size();
);
prepend(delay) ->
(
p = player();
mode = 'smooth';
__prepend_path_segment(__camera_position(p), round(60*delay), mode);
__print_path_size();
);
__add_path_segment(vector, duration, mode) ->
(
undef('global_path_precalculated');
if ( (l('sharp','smooth') ~ mode) == null, exit('use smooth or sharp point'));
if(!global_points, exit('Cannot add point to path that didn\'t started yet!'));
l(v, end_time, m) = global_points:(-1);
vector:(-2) = __adjusted_rot(v:(-2) , vector:(-2) );
global_points += l(vector, end_time+duration, mode)
global_points += l(vector, end_time+duration, mode);
__update();
);
__prepend_path_segment(vector, duration, mode) ->
(
if ( (l('sharp','smooth') ~ mode) == null, exit('use smooth or sharp point'));
if(!global_points, exit('Cannot add point to path that didn\'t started yet!'));
l(v, start_time, m) = global_points:(-1);
vector:(-2) = __adjusted_rot(v:(-2), vector:(-2));
new_points = l(l(vector, 0, mode));
for (global_points,
_:1 += duration;
new_points += _;
);
global_points = new_points;
__update();
);
// adjusts current rotation so we don\'t spin around like crazy
__adjusted_rot(previous_rot, current_rot) ->
(
@@ -71,79 +106,80 @@ __adjusted_rot(previous_rot, current_rot) ->
__print_path_size() ->
(
__assert_valid_for_motion();
print("Path length: %d points, 0.2f secs at 60fps", length(global_points), global_points:(-1):1/60);
if (!__assert_valid_for_motion(),
print(str('%d points, %.1f secs', length(global_points), global_points:(-1):1/60));
);
'';
);
repeat(times, last_section_duration) ->
(
__assert_valid_for_motion();
undef('global_path_precalculated');
if (err = __assert_valid_for_motion(), exit(err));
positions = map(global_points, _:0);
modes = map(global_points, _:(-1));
durations = map(global_points, global_points:(_i+1):1 - _:1 );
durations:(-1) = last_section_duration;
durations:(-1) = round(60*last_section_duration);
loop(times,
loop( length(positions),
__add_path_segment(positions:_, durations:_, modes:_)
)
);
__update();
__print_path_size();
'';
);
speed(percentage) ->
stretch(percentage) ->
(
__assert_valid_for_motion();
if (err = __assert_valid_for_motion(), exit(err));
undef('global_path_precalculated');
if (percentage < 25 || percentage > 400,
exit('path speed can only be speed, or slowed down 4 times. Recall command for larger changes')
exit('path speed can only be speed, or slowed down 4 times. Re-call command for larger changes')
);
ratio = percentage/100;
previous_path_length = global_points:(-1):1;
for(global_points, _:1 = _:1*ratio );
undef('global_path_precalculated');
str('path %s from %d to %d ticks (%.2f seconds with 60fps)',
__update();
str('path %s from %.2f to %.2f seconds',
if(ratio<1,'shortened','extended'),
previous_path_length,
global_points:(-1):1,
previous_path_length/60,
global_points:(-1):1/60
)
);
select_interpolation(method) ->
(
undef('global_path_precalculated');
__prepare_path_if_needed() -> __prepare_path_if_needed_generic();
// each supported method needs to specify its __find_position_for_point to trace the path
// accepting segment number, and position in the segment
// or optionally __prepare_path_if_needed, if path is inefficient to compute point by point
if (
method == 'linear',
(
__find_position_for_point(s, p) -> __find_position_for_linear(s, p)
),
global_interpolator = if (
method == 'linear', '__interpolator_linear',
method == 'cr', '__interpolator_cr',
method == 'gauss', _(s, p) -> __interpolator_gauss(s, p, 0),
method ~ '^gauss_',
(
type = method - 'gauss_';
global_interpol_option = if(type=='auto',0,number(type));
__find_position_for_point(s, p) -> __find_position_for_gauss(s, p)
variance = number(type);
_(s, p, outer(variance)) -> __interpolator_gauss(s, p, variance);
),
exit('Choose one of the following methods: linear, gauss:auto, gauss:<deviation>')
exit('Choose one of the following methods: linear, gauss, gauss_<deviation>, cr')
);
__update();
'Ok'
);
select_interpolation('gauss_auto');
select_interpolation('cr');
__assert_valid_for_motion() ->
(
if(!global_points, exit('Path not defined yet'));
if(length(global_points)<2, exit('Path not complete - add more points'));
if(!global_points, return('Path not defined yet'));
if(length(global_points)<2, return('Path not complete - add more points'));
null
);
__get_path_at(segment, start, index) ->
(
v = global_path_precalculated:(start+index);
if(v == null,
v = __find_position_for_point(segment, index);
v = call(global_interpolator, segment, index);
global_path_precalculated:(start+index) = v
);
v
@@ -153,16 +189,11 @@ __invalidate_points_cache() -> global_path_precalculated = map(range(global_poin
global_showing_path = false;
global_playing_path = false;
stop() ->
hide() ->
(
if (!global_playing_path && !global_showing_path, return('You can only stop playing or showing the path'));
if (global_showing_path,
global_showing_path = false;
print('stopped showing path');
);
if (global_playing_path,
global_playing_path = false;
print('stopped playing path');
print('Stopped showing path');
);
''
);
@@ -170,84 +201,87 @@ stop() ->
clear() ->
(
global_points = l();
undef('global_path_precalculated');
__update();
);
global_needs_updating = false;
global_selected_point = null;
global_markers = null;
__distsq(vec1, vec2) -> reduce(vec1 - vec2, _a + _*_, 0);
__closest_point_to_center(center, points) ->
(
dd = __distsq(points:0, center);
for(points,
d = __distsq(_, center);
if( d<dd,
dd=d;
index = _i
);
);
index;
);
select() ->
(
if (!global_points, return());
if (!global_showing_path, return());
p = player();
selected_point = __closest_point_to_center(
p~'pos'+l(0,p~'eye_height',0),
map(global_points, slice(_:0, 0, 3))
);
global_selected_point = if (global_selected_point == selected_point, null, selected_point);
global_needs_updating = true;
// no need to _update since path is still valid
);
__on_player_attacks_entity(p, e) ->
(
if (e~'type' == 'armor_stand' && query(e, 'has_tag', '__scarpet_marker_camera') && global_markers,
for (global_markers,
if(_==e,
global_selected_point = if (global_selected_point == _i, null, _i);
global_needs_updating = true;
return();
)
);
);
);
global_show_thread = null;
show() ->
(
p = player();
__assert_valid_for_motion();
__print_path_size();
if (global_showing_path, return ());
global_showing_path = true;
global_needs_updating= false;
def __create_markers()->
__create_markers() ->
(
map(global_points,
m = create_marker(null, _:0, 'observer');
if (global_selected_point && _i == global_selected_point,
modify(m,'effect','glowing',72000);
map(global_points || l(),
is_selected = global_selected_point != null && _i == global_selected_point;
caption = if (_i == 0, 'start', str('%.1fs', global_points:_i:1/60); );
if (is_selected && _i > 0,
caption += str(' (%.1f current segment)', (global_points:_i:1 - global_points:(_i-1):1)/60);
);
m = create_marker(caption, _:0, 'observer');
if (is_selected,
modify(m,'effect','glowing',72000, 0, false, false);
);
m
);
);
task( _(outer(p)) -> (
markers = __create_markers();
loop(7200,
if(!global_showing_path, break());
if (global_needs_updating,
global_needs_updating = false;
for(markers, modify(_,'remove');
markers = __create_markers();
);
_show_path_tick('dust 0.9 0.1 0.1 1', 100);
sleep(100);
);
for(markers, modify(_,'remove');
print('Done!');
));
'';
);
play(fps) ->
__show_path_tick() ->
(
p = player();
__assert_valid_for_motion();
if (__assert_valid_for_motion(), return());
__prepare_path_if_needed();
global_playing_path = true;
task( _(outer(fps), outer(p)) -> (
sleep(1000);
mspt = 1000 / fps;
start_time = time();
point = 0;
loop( length(global_points)-1, segment = _;
if (p~'sneaking', global_playing_path = false);
if (!global_playing_path, break());
start = global_points:segment:1;
end = global_points:(segment+1):1;
loop(end-start,
v = __get_path_at(segment, start, _);
modify(p, 'location', v);
point += 1;
end_time = time();
took = end_time - start_time;
if (took < mspt, sleep(mspt-took));
start_time = time()
)
);
sleep(1000);
print('Done!');
));
'';
);
_show_path_tick(particle_type, total) ->
(
__assert_valid_for_motion();
__prepare_path_if_needed();
loop(total,
loop(100,
segment = floor(rand(length(global_points)-1));
particle_type = if ((segment+1) == global_selected_point, 'dust 0.1 0.9 0.1 1','dust 0.6 0.6 0.6 1');
start = global_points:segment:1;
end = global_points:(segment+1):1;
index = floor(rand(end-start));
@@ -256,11 +290,109 @@ _show_path_tick(particle_type, total) ->
);
null
);
task( _(outer(p)) -> (
global_markers = __create_markers();
loop(7200,
if(!global_showing_path, break());
if (global_needs_updating,
global_needs_updating = false;
for(global_markers, modify(_,'remove'));
global_markers = __create_markers();
);
__show_path_tick();
sleep(100);
);
for(global_markers, modify(_,'remove'));
global_markers = null;
global_showing_path = false;
));
'';
);
move() ->
(
if (global_selected_point == null, return());
if (!global_showing_path, return());
global_points:global_selected_point:0 = __camera_position(player());
__update();
);
duration(amount) ->
(
if (!global_selected_point, return()); // skip nulls, and 0 (first one)
if (!global_showing_path, return());
duration = number(amount);
new_ticks = round(duration * 60);
if (new_ticks < 10, return());
previous_ticks = global_points:global_selected_point:1-global_points:(global_selected_point-1):1;
delta = new_ticks - previous_ticks;
// adjust duration of all points after that.
for (range(global_selected_point, length(global_points)),
global_points:_:1 += delta;
);
__update();
);
delete_point() ->
(
if (global_selected_point == null, return()); // skip nulls, and 0 (first one)
if (!global_showing_path, return());
if (length(global_points) < 2, clear(); return());
if (global_selected_point == 0, global_points:1:1 = 0);
global_points = filter(global_points, _i != global_selected_point);
__update();
);
trim_path() ->
(
if (global_selected_point == null, return()); // skip nulls, and 0 (first one)
if (!global_showing_path, return());
global_points = slice(global_points, 0, global_selected_point);
__update();
);
play() ->
(
p = player();
if (err = __assert_valid_for_motion(), exit(err));
__prepare_path_if_needed();
task( _(outer(fps), outer(p)) -> (
sleep(1000);
global_playing_path = true;
mspt = 1000 / 60;
start_time = time();
point = 0;
player_offset = l(0,p~'eye_height',0,0,0);
try (
loop( length(global_points)-1, segment = _;
start = global_points:segment:1;
end = global_points:(segment+1):1;
loop(end-start,
if (p~'sneaking', global_playing_path = false);
if (!global_playing_path, throw());
v = __get_path_at(segment, start, _)-player_offset;
modify(p, 'location', v);
point += 1;
end_time = time();
took = end_time - start_time;
if (took < mspt, sleep(mspt-took));
start_time = time()
)
);
);
sleep(1000);
global_playing_path = false;
print('Done!');
));
'';
);
__prepare_path_if_needed_generic() ->
(
if(!global_path_precalculated, __invalidate_points_cache())
);
__find_position_for_linear(segment, point) ->
__interpolator_linear(segment, point) ->
(
l(va, start, mode_a) = global_points:segment;
l(vb, end, mode_b) = global_points:(segment+1);
@@ -271,16 +403,14 @@ __find_position_for_linear(segment, point) ->
//(1/sqrt(2*pi*d*d))*euler^(-((x-miu)^2)/(2*d*d))
// but we will be normalizing anyways, so who cares
__norm_prob(x, miu, d) -> euler^(-((x-miu)^2)/(2*d*d));
__find_position_for_gauss(from_index, point) ->
__interpolator_gauss(from_index, point, deviation) ->
(
dev = global_interpol_option;
components = l();
path_point = global_points:from_index:1;
try(
for(range(from_index+1, length(global_points)),
l(v,ptime,mode) = global_points:_;
dev = if (global_interpol_option > 0, global_interpol_option,
dev = if (deviation > 0, deviation,
devs = l();
if (_+1 < length(global_points), devs += global_points:(_+1):1-ptime);
if (_-1 >= 0, devs += ptime-global_points:(_-1):1);
@@ -295,7 +425,7 @@ __find_position_for_gauss(from_index, point) ->
try(
for(range(from_index, -1, -1),
l(v,ptime,mode) = global_points:_;
dev = if (global_interpol_option > 0, global_interpol_option,
dev = if (deviation > 0, deviation,
devs = l();
if (_+1 < length(global_points), devs += global_points:(_+1):1-ptime);
if (_-1 >= 0, devs += ptime-global_points:(_-1):1);
@@ -309,4 +439,15 @@ __find_position_for_gauss(from_index, point) ->
);
total = rtotal+ltotal;
reduce(components, _a+_:0*(_:1/total), l(0,0,0,0,0))
)
);
__interpolator_cr(from_index, point) ->
(
total = global_points:(from_index+1):1 - global_points:from_index:1;
p__1 = global_points:(if(from_index == 0, 0, from_index-1)):0;
p_0 = global_points:from_index:0;
p_1 = global_points:(from_index+1):0;
p_2 = global_points:(if(from_index == (length(global_points)-2), -1, from_index+2)):0;
r = point/total; // ratio within segment
(r*((2-r)*r-1) * p__1 + (r*r*(3*r-5)+2) * p_0 + r*((4 - 3*r)*r + 1) * p_1 + (r-1)*r*r * p_2) / 2
);